1 /**************************************************************************
2  *
3  * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
4  * All Rights Reserved.
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the
8  * "Software"), to deal in the Software without restriction, including
9  * without limitation the rights to use, copy, modify, merge, publish,
10  * distribute, sub license, and/or sell copies of the Software, and to
11  * permit persons to whom the Software is furnished to do so, subject to
12  * the following conditions:
13  *
14  * The above copyright notice and this permission notice (including the
15  * next paragraph) shall be included in all copies or substantial portions
16  * of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25  *
26  **************************************************************************/
27 
28  /**
29   * @file
30   *
31   * Wrap the cso cache & hash mechanisms in a simplified
32   * pipe-driver-specific interface.
33   *
34   * @author Zack Rusin <zack@tungstengraphics.com>
35   * @author Keith Whitwell <keith@tungstengraphics.com>
36   */
37 
38 #include "pipe/p_state.h"
39 #include "util/u_draw.h"
40 #include "util/u_framebuffer.h"
41 #include "util/u_inlines.h"
42 #include "util/u_math.h"
43 #include "util/u_memory.h"
44 #include "util/u_vbuf.h"
45 #include "tgsi/tgsi_parse.h"
46 
47 #include "cso_cache/cso_context.h"
48 #include "cso_cache/cso_cache.h"
49 #include "cso_cache/cso_hash.h"
50 #include "cso_context.h"
51 
52 
53 /**
54  * Info related to samplers and sampler views.
55  * We have one of these for fragment samplers and another for vertex samplers.
56  */
57 struct sampler_info
58 {
59    struct {
60       void *samplers[PIPE_MAX_SAMPLERS];
61       unsigned nr_samplers;
62    } hw;
63 
64    void *samplers[PIPE_MAX_SAMPLERS];
65    unsigned nr_samplers;
66 
67    void *samplers_saved[PIPE_MAX_SAMPLERS];
68    unsigned nr_samplers_saved;
69 
70    struct pipe_sampler_view *views[PIPE_MAX_SAMPLERS];
71    unsigned nr_views;
72 
73    struct pipe_sampler_view *views_saved[PIPE_MAX_SAMPLERS];
74    unsigned nr_views_saved;
75 };
76 
77 
78 
79 struct cso_context {
80    struct pipe_context *pipe;
81    struct cso_cache *cache;
82    struct u_vbuf *vbuf;
83 
84    boolean has_geometry_shader;
85    boolean has_streamout;
86 
87    struct sampler_info samplers[PIPE_SHADER_TYPES];
88 
89    uint nr_vertex_buffers;
90    struct pipe_vertex_buffer vertex_buffers[PIPE_MAX_ATTRIBS];
91 
92    uint nr_vertex_buffers_saved;
93    struct pipe_vertex_buffer vertex_buffers_saved[PIPE_MAX_ATTRIBS];
94 
95    unsigned nr_so_targets;
96    struct pipe_stream_output_target *so_targets[PIPE_MAX_SO_BUFFERS];
97 
98    unsigned nr_so_targets_saved;
99    struct pipe_stream_output_target *so_targets_saved[PIPE_MAX_SO_BUFFERS];
100 
101    /** Current and saved state.
102     * The saved state is used as a 1-deep stack.
103     */
104    void *blend, *blend_saved;
105    void *depth_stencil, *depth_stencil_saved;
106    void *rasterizer, *rasterizer_saved;
107    void *fragment_shader, *fragment_shader_saved;
108    void *vertex_shader, *vertex_shader_saved;
109    void *geometry_shader, *geometry_shader_saved;
110    void *velements, *velements_saved;
111 
112    struct pipe_clip_state clip;
113    struct pipe_clip_state clip_saved;
114 
115    struct pipe_framebuffer_state fb, fb_saved;
116    struct pipe_viewport_state vp, vp_saved;
117    struct pipe_blend_color blend_color;
118    unsigned sample_mask, sample_mask_saved;
119    struct pipe_stencil_ref stencil_ref, stencil_ref_saved;
120 };
121 
122 
delete_blend_state(struct cso_context * ctx,void * state)123 static boolean delete_blend_state(struct cso_context *ctx, void *state)
124 {
125    struct cso_blend *cso = (struct cso_blend *)state;
126 
127    if (ctx->blend == cso->data)
128       return FALSE;
129 
130    if (cso->delete_state)
131       cso->delete_state(cso->context, cso->data);
132    FREE(state);
133    return TRUE;
134 }
135 
delete_depth_stencil_state(struct cso_context * ctx,void * state)136 static boolean delete_depth_stencil_state(struct cso_context *ctx, void *state)
137 {
138    struct cso_depth_stencil_alpha *cso =
139       (struct cso_depth_stencil_alpha *)state;
140 
141    if (ctx->depth_stencil == cso->data)
142       return FALSE;
143 
144    if (cso->delete_state)
145       cso->delete_state(cso->context, cso->data);
146    FREE(state);
147 
148    return TRUE;
149 }
150 
delete_sampler_state(struct cso_context * ctx,void * state)151 static boolean delete_sampler_state(struct cso_context *ctx, void *state)
152 {
153    struct cso_sampler *cso = (struct cso_sampler *)state;
154    if (cso->delete_state)
155       cso->delete_state(cso->context, cso->data);
156    FREE(state);
157    return TRUE;
158 }
159 
delete_rasterizer_state(struct cso_context * ctx,void * state)160 static boolean delete_rasterizer_state(struct cso_context *ctx, void *state)
161 {
162    struct cso_rasterizer *cso = (struct cso_rasterizer *)state;
163 
164    if (ctx->rasterizer == cso->data)
165       return FALSE;
166    if (cso->delete_state)
167       cso->delete_state(cso->context, cso->data);
168    FREE(state);
169    return TRUE;
170 }
171 
delete_vertex_elements(struct cso_context * ctx,void * state)172 static boolean delete_vertex_elements(struct cso_context *ctx,
173                                       void *state)
174 {
175    struct cso_velements *cso = (struct cso_velements *)state;
176 
177    if (ctx->velements == cso->data)
178       return FALSE;
179 
180    if (cso->delete_state)
181       cso->delete_state(cso->context, cso->data);
182    FREE(state);
183    return TRUE;
184 }
185 
186 
delete_cso(struct cso_context * ctx,void * state,enum cso_cache_type type)187 static INLINE boolean delete_cso(struct cso_context *ctx,
188                                  void *state, enum cso_cache_type type)
189 {
190    switch (type) {
191    case CSO_BLEND:
192       return delete_blend_state(ctx, state);
193    case CSO_SAMPLER:
194       return delete_sampler_state(ctx, state);
195    case CSO_DEPTH_STENCIL_ALPHA:
196       return delete_depth_stencil_state(ctx, state);
197    case CSO_RASTERIZER:
198       return delete_rasterizer_state(ctx, state);
199    case CSO_VELEMENTS:
200       return delete_vertex_elements(ctx, state);
201    default:
202       assert(0);
203       FREE(state);
204    }
205    return FALSE;
206 }
207 
208 static INLINE void
sanitize_hash(struct cso_hash * hash,enum cso_cache_type type,int max_size,void * user_data)209 sanitize_hash(struct cso_hash *hash, enum cso_cache_type type,
210               int max_size, void *user_data)
211 {
212    struct cso_context *ctx = (struct cso_context *)user_data;
213    /* if we're approach the maximum size, remove fourth of the entries
214     * otherwise every subsequent call will go through the same */
215    int hash_size = cso_hash_size(hash);
216    int max_entries = (max_size > hash_size) ? max_size : hash_size;
217    int to_remove =  (max_size < max_entries) * max_entries/4;
218    struct cso_hash_iter iter = cso_hash_first_node(hash);
219    if (hash_size > max_size)
220       to_remove += hash_size - max_size;
221    while (to_remove) {
222       /*remove elements until we're good */
223       /*fixme: currently we pick the nodes to remove at random*/
224       void *cso = cso_hash_iter_data(iter);
225       if (delete_cso(ctx, cso, type)) {
226          iter = cso_hash_erase(hash, iter);
227          --to_remove;
228       } else
229          iter = cso_hash_iter_next(iter);
230    }
231 }
232 
cso_init_vbuf(struct cso_context * cso)233 static void cso_init_vbuf(struct cso_context *cso)
234 {
235    struct u_vbuf_caps caps;
236 
237    u_vbuf_get_caps(cso->pipe->screen, &caps);
238 
239    /* Install u_vbuf if there is anything unsupported. */
240    if (!caps.buffer_offset_unaligned ||
241        !caps.buffer_stride_unaligned ||
242        !caps.velem_src_offset_unaligned ||
243        !caps.format_fixed32 ||
244        !caps.format_float16 ||
245        !caps.format_float64 ||
246        !caps.format_norm32 ||
247        !caps.format_scaled32 ||
248        !caps.user_vertex_buffers) {
249       cso->vbuf = u_vbuf_create(cso->pipe, &caps);
250    }
251 }
252 
cso_create_context(struct pipe_context * pipe)253 struct cso_context *cso_create_context( struct pipe_context *pipe )
254 {
255    struct cso_context *ctx = CALLOC_STRUCT(cso_context);
256    if (ctx == NULL)
257       goto out;
258 
259    ctx->cache = cso_cache_create();
260    if (ctx->cache == NULL)
261       goto out;
262    cso_cache_set_sanitize_callback(ctx->cache,
263                                    sanitize_hash,
264                                    ctx);
265 
266    ctx->pipe = pipe;
267    ctx->sample_mask_saved = ~0;
268 
269    cso_init_vbuf(ctx);
270 
271    /* Enable for testing: */
272    if (0) cso_set_maximum_cache_size( ctx->cache, 4 );
273 
274    if (pipe->screen->get_shader_param(pipe->screen, PIPE_SHADER_GEOMETRY,
275                                 PIPE_SHADER_CAP_MAX_INSTRUCTIONS) > 0) {
276       ctx->has_geometry_shader = TRUE;
277    }
278    if (pipe->screen->get_param(pipe->screen,
279                                PIPE_CAP_MAX_STREAM_OUTPUT_BUFFERS) != 0) {
280       ctx->has_streamout = TRUE;
281    }
282 
283    return ctx;
284 
285 out:
286    cso_destroy_context( ctx );
287    return NULL;
288 }
289 
290 /**
291  * Prior to context destruction, this function unbinds all state objects.
292  */
cso_release_all(struct cso_context * ctx)293 void cso_release_all( struct cso_context *ctx )
294 {
295    unsigned i, shader;
296 
297    if (ctx->pipe) {
298       ctx->pipe->bind_blend_state( ctx->pipe, NULL );
299       ctx->pipe->bind_rasterizer_state( ctx->pipe, NULL );
300       ctx->pipe->bind_fragment_sampler_states( ctx->pipe, 0, NULL );
301       if (ctx->pipe->bind_vertex_sampler_states)
302          ctx->pipe->bind_vertex_sampler_states(ctx->pipe, 0, NULL);
303       ctx->pipe->bind_depth_stencil_alpha_state( ctx->pipe, NULL );
304       ctx->pipe->bind_fs_state( ctx->pipe, NULL );
305       ctx->pipe->bind_vs_state( ctx->pipe, NULL );
306       ctx->pipe->bind_vertex_elements_state( ctx->pipe, NULL );
307       ctx->pipe->set_fragment_sampler_views(ctx->pipe, 0, NULL);
308       if (ctx->pipe->set_vertex_sampler_views)
309          ctx->pipe->set_vertex_sampler_views(ctx->pipe, 0, NULL);
310       if (ctx->pipe->set_stream_output_targets)
311          ctx->pipe->set_stream_output_targets(ctx->pipe, 0, NULL, 0);
312    }
313 
314    /* free fragment samplers, views */
315    for (shader = 0; shader < Elements(ctx->samplers); shader++) {
316       struct sampler_info *info = &ctx->samplers[shader];
317       for (i = 0; i < PIPE_MAX_SAMPLERS; i++) {
318          pipe_sampler_view_reference(&info->views[i], NULL);
319          pipe_sampler_view_reference(&info->views_saved[i], NULL);
320       }
321    }
322 
323    util_unreference_framebuffer_state(&ctx->fb);
324    util_unreference_framebuffer_state(&ctx->fb_saved);
325 
326    util_copy_vertex_buffers(ctx->vertex_buffers,
327                             &ctx->nr_vertex_buffers,
328                             NULL, 0);
329    util_copy_vertex_buffers(ctx->vertex_buffers_saved,
330                             &ctx->nr_vertex_buffers_saved,
331                             NULL, 0);
332 
333    for (i = 0; i < PIPE_MAX_SO_BUFFERS; i++) {
334       pipe_so_target_reference(&ctx->so_targets[i], NULL);
335       pipe_so_target_reference(&ctx->so_targets_saved[i], NULL);
336    }
337 
338    if (ctx->cache) {
339       cso_cache_delete( ctx->cache );
340       ctx->cache = NULL;
341    }
342 }
343 
344 
345 /**
346  * Free the CSO context.  NOTE: the state tracker should have previously called
347  * cso_release_all().
348  */
cso_destroy_context(struct cso_context * ctx)349 void cso_destroy_context( struct cso_context *ctx )
350 {
351    if (ctx) {
352       if (ctx->vbuf)
353          u_vbuf_destroy(ctx->vbuf);
354       FREE( ctx );
355    }
356 }
357 
358 
359 /* Those function will either find the state of the given template
360  * in the cache or they will create a new state from the given
361  * template, insert it in the cache and return it.
362  */
363 
364 /*
365  * If the driver returns 0 from the create method then they will assign
366  * the data member of the cso to be the template itself.
367  */
368 
cso_set_blend(struct cso_context * ctx,const struct pipe_blend_state * templ)369 enum pipe_error cso_set_blend(struct cso_context *ctx,
370                               const struct pipe_blend_state *templ)
371 {
372    unsigned key_size, hash_key;
373    struct cso_hash_iter iter;
374    void *handle;
375 
376    key_size = templ->independent_blend_enable ?
377       sizeof(struct pipe_blend_state) :
378       (char *)&(templ->rt[1]) - (char *)templ;
379    hash_key = cso_construct_key((void*)templ, key_size);
380    iter = cso_find_state_template(ctx->cache, hash_key, CSO_BLEND,
381                                   (void*)templ, key_size);
382 
383    if (cso_hash_iter_is_null(iter)) {
384       struct cso_blend *cso = MALLOC(sizeof(struct cso_blend));
385       if (!cso)
386          return PIPE_ERROR_OUT_OF_MEMORY;
387 
388       memset(&cso->state, 0, sizeof cso->state);
389       memcpy(&cso->state, templ, key_size);
390       cso->data = ctx->pipe->create_blend_state(ctx->pipe, &cso->state);
391       cso->delete_state = (cso_state_callback)ctx->pipe->delete_blend_state;
392       cso->context = ctx->pipe;
393 
394       iter = cso_insert_state(ctx->cache, hash_key, CSO_BLEND, cso);
395       if (cso_hash_iter_is_null(iter)) {
396          FREE(cso);
397          return PIPE_ERROR_OUT_OF_MEMORY;
398       }
399 
400       handle = cso->data;
401    }
402    else {
403       handle = ((struct cso_blend *)cso_hash_iter_data(iter))->data;
404    }
405 
406    if (ctx->blend != handle) {
407       ctx->blend = handle;
408       ctx->pipe->bind_blend_state(ctx->pipe, handle);
409    }
410    return PIPE_OK;
411 }
412 
cso_save_blend(struct cso_context * ctx)413 void cso_save_blend(struct cso_context *ctx)
414 {
415    assert(!ctx->blend_saved);
416    ctx->blend_saved = ctx->blend;
417 }
418 
cso_restore_blend(struct cso_context * ctx)419 void cso_restore_blend(struct cso_context *ctx)
420 {
421    if (ctx->blend != ctx->blend_saved) {
422       ctx->blend = ctx->blend_saved;
423       ctx->pipe->bind_blend_state(ctx->pipe, ctx->blend_saved);
424    }
425    ctx->blend_saved = NULL;
426 }
427 
428 
429 
430 enum pipe_error
cso_set_depth_stencil_alpha(struct cso_context * ctx,const struct pipe_depth_stencil_alpha_state * templ)431 cso_set_depth_stencil_alpha(struct cso_context *ctx,
432                             const struct pipe_depth_stencil_alpha_state *templ)
433 {
434    unsigned key_size = sizeof(struct pipe_depth_stencil_alpha_state);
435    unsigned hash_key = cso_construct_key((void*)templ, key_size);
436    struct cso_hash_iter iter = cso_find_state_template(ctx->cache,
437                                                        hash_key,
438                                                        CSO_DEPTH_STENCIL_ALPHA,
439                                                        (void*)templ, key_size);
440    void *handle;
441 
442    if (cso_hash_iter_is_null(iter)) {
443       struct cso_depth_stencil_alpha *cso =
444          MALLOC(sizeof(struct cso_depth_stencil_alpha));
445       if (!cso)
446          return PIPE_ERROR_OUT_OF_MEMORY;
447 
448       memcpy(&cso->state, templ, sizeof(*templ));
449       cso->data = ctx->pipe->create_depth_stencil_alpha_state(ctx->pipe,
450                                                               &cso->state);
451       cso->delete_state =
452          (cso_state_callback)ctx->pipe->delete_depth_stencil_alpha_state;
453       cso->context = ctx->pipe;
454 
455       iter = cso_insert_state(ctx->cache, hash_key,
456                               CSO_DEPTH_STENCIL_ALPHA, cso);
457       if (cso_hash_iter_is_null(iter)) {
458          FREE(cso);
459          return PIPE_ERROR_OUT_OF_MEMORY;
460       }
461 
462       handle = cso->data;
463    }
464    else {
465       handle = ((struct cso_depth_stencil_alpha *)
466                 cso_hash_iter_data(iter))->data;
467    }
468 
469    if (ctx->depth_stencil != handle) {
470       ctx->depth_stencil = handle;
471       ctx->pipe->bind_depth_stencil_alpha_state(ctx->pipe, handle);
472    }
473    return PIPE_OK;
474 }
475 
cso_save_depth_stencil_alpha(struct cso_context * ctx)476 void cso_save_depth_stencil_alpha(struct cso_context *ctx)
477 {
478    assert(!ctx->depth_stencil_saved);
479    ctx->depth_stencil_saved = ctx->depth_stencil;
480 }
481 
cso_restore_depth_stencil_alpha(struct cso_context * ctx)482 void cso_restore_depth_stencil_alpha(struct cso_context *ctx)
483 {
484    if (ctx->depth_stencil != ctx->depth_stencil_saved) {
485       ctx->depth_stencil = ctx->depth_stencil_saved;
486       ctx->pipe->bind_depth_stencil_alpha_state(ctx->pipe,
487                                                 ctx->depth_stencil_saved);
488    }
489    ctx->depth_stencil_saved = NULL;
490 }
491 
492 
493 
cso_set_rasterizer(struct cso_context * ctx,const struct pipe_rasterizer_state * templ)494 enum pipe_error cso_set_rasterizer(struct cso_context *ctx,
495                                    const struct pipe_rasterizer_state *templ)
496 {
497    unsigned key_size = sizeof(struct pipe_rasterizer_state);
498    unsigned hash_key = cso_construct_key((void*)templ, key_size);
499    struct cso_hash_iter iter = cso_find_state_template(ctx->cache,
500                                                        hash_key,
501                                                        CSO_RASTERIZER,
502                                                        (void*)templ, key_size);
503    void *handle = NULL;
504 
505    if (cso_hash_iter_is_null(iter)) {
506       struct cso_rasterizer *cso = MALLOC(sizeof(struct cso_rasterizer));
507       if (!cso)
508          return PIPE_ERROR_OUT_OF_MEMORY;
509 
510       memcpy(&cso->state, templ, sizeof(*templ));
511       cso->data = ctx->pipe->create_rasterizer_state(ctx->pipe, &cso->state);
512       cso->delete_state =
513          (cso_state_callback)ctx->pipe->delete_rasterizer_state;
514       cso->context = ctx->pipe;
515 
516       iter = cso_insert_state(ctx->cache, hash_key, CSO_RASTERIZER, cso);
517       if (cso_hash_iter_is_null(iter)) {
518          FREE(cso);
519          return PIPE_ERROR_OUT_OF_MEMORY;
520       }
521 
522       handle = cso->data;
523    }
524    else {
525       handle = ((struct cso_rasterizer *)cso_hash_iter_data(iter))->data;
526    }
527 
528    if (ctx->rasterizer != handle) {
529       ctx->rasterizer = handle;
530       ctx->pipe->bind_rasterizer_state(ctx->pipe, handle);
531    }
532    return PIPE_OK;
533 }
534 
cso_save_rasterizer(struct cso_context * ctx)535 void cso_save_rasterizer(struct cso_context *ctx)
536 {
537    assert(!ctx->rasterizer_saved);
538    ctx->rasterizer_saved = ctx->rasterizer;
539 }
540 
cso_restore_rasterizer(struct cso_context * ctx)541 void cso_restore_rasterizer(struct cso_context *ctx)
542 {
543    if (ctx->rasterizer != ctx->rasterizer_saved) {
544       ctx->rasterizer = ctx->rasterizer_saved;
545       ctx->pipe->bind_rasterizer_state(ctx->pipe, ctx->rasterizer_saved);
546    }
547    ctx->rasterizer_saved = NULL;
548 }
549 
550 
551 
cso_set_fragment_shader_handle(struct cso_context * ctx,void * handle)552 enum pipe_error cso_set_fragment_shader_handle(struct cso_context *ctx,
553                                                void *handle )
554 {
555    if (ctx->fragment_shader != handle) {
556       ctx->fragment_shader = handle;
557       ctx->pipe->bind_fs_state(ctx->pipe, handle);
558    }
559    return PIPE_OK;
560 }
561 
cso_delete_fragment_shader(struct cso_context * ctx,void * handle)562 void cso_delete_fragment_shader(struct cso_context *ctx, void *handle )
563 {
564    if (handle == ctx->fragment_shader) {
565       /* unbind before deleting */
566       ctx->pipe->bind_fs_state(ctx->pipe, NULL);
567       ctx->fragment_shader = NULL;
568    }
569    ctx->pipe->delete_fs_state(ctx->pipe, handle);
570 }
571 
cso_save_fragment_shader(struct cso_context * ctx)572 void cso_save_fragment_shader(struct cso_context *ctx)
573 {
574    assert(!ctx->fragment_shader_saved);
575    ctx->fragment_shader_saved = ctx->fragment_shader;
576 }
577 
cso_restore_fragment_shader(struct cso_context * ctx)578 void cso_restore_fragment_shader(struct cso_context *ctx)
579 {
580    if (ctx->fragment_shader_saved != ctx->fragment_shader) {
581       ctx->pipe->bind_fs_state(ctx->pipe, ctx->fragment_shader_saved);
582       ctx->fragment_shader = ctx->fragment_shader_saved;
583    }
584    ctx->fragment_shader_saved = NULL;
585 }
586 
587 
cso_set_vertex_shader_handle(struct cso_context * ctx,void * handle)588 enum pipe_error cso_set_vertex_shader_handle(struct cso_context *ctx,
589                                              void *handle )
590 {
591    if (ctx->vertex_shader != handle) {
592       ctx->vertex_shader = handle;
593       ctx->pipe->bind_vs_state(ctx->pipe, handle);
594    }
595    return PIPE_OK;
596 }
597 
cso_delete_vertex_shader(struct cso_context * ctx,void * handle)598 void cso_delete_vertex_shader(struct cso_context *ctx, void *handle )
599 {
600    if (handle == ctx->vertex_shader) {
601       /* unbind before deleting */
602       ctx->pipe->bind_vs_state(ctx->pipe, NULL);
603       ctx->vertex_shader = NULL;
604    }
605    ctx->pipe->delete_vs_state(ctx->pipe, handle);
606 }
607 
cso_save_vertex_shader(struct cso_context * ctx)608 void cso_save_vertex_shader(struct cso_context *ctx)
609 {
610    assert(!ctx->vertex_shader_saved);
611    ctx->vertex_shader_saved = ctx->vertex_shader;
612 }
613 
cso_restore_vertex_shader(struct cso_context * ctx)614 void cso_restore_vertex_shader(struct cso_context *ctx)
615 {
616    if (ctx->vertex_shader_saved != ctx->vertex_shader) {
617       ctx->pipe->bind_vs_state(ctx->pipe, ctx->vertex_shader_saved);
618       ctx->vertex_shader = ctx->vertex_shader_saved;
619    }
620    ctx->vertex_shader_saved = NULL;
621 }
622 
623 
cso_set_framebuffer(struct cso_context * ctx,const struct pipe_framebuffer_state * fb)624 enum pipe_error cso_set_framebuffer(struct cso_context *ctx,
625                                     const struct pipe_framebuffer_state *fb)
626 {
627    if (memcmp(&ctx->fb, fb, sizeof(*fb)) != 0) {
628       util_copy_framebuffer_state(&ctx->fb, fb);
629       ctx->pipe->set_framebuffer_state(ctx->pipe, fb);
630    }
631    return PIPE_OK;
632 }
633 
cso_save_framebuffer(struct cso_context * ctx)634 void cso_save_framebuffer(struct cso_context *ctx)
635 {
636    util_copy_framebuffer_state(&ctx->fb_saved, &ctx->fb);
637 }
638 
cso_restore_framebuffer(struct cso_context * ctx)639 void cso_restore_framebuffer(struct cso_context *ctx)
640 {
641    if (memcmp(&ctx->fb, &ctx->fb_saved, sizeof(ctx->fb))) {
642       util_copy_framebuffer_state(&ctx->fb, &ctx->fb_saved);
643       ctx->pipe->set_framebuffer_state(ctx->pipe, &ctx->fb);
644       util_unreference_framebuffer_state(&ctx->fb_saved);
645    }
646 }
647 
648 
cso_set_viewport(struct cso_context * ctx,const struct pipe_viewport_state * vp)649 enum pipe_error cso_set_viewport(struct cso_context *ctx,
650                                  const struct pipe_viewport_state *vp)
651 {
652    if (memcmp(&ctx->vp, vp, sizeof(*vp))) {
653       ctx->vp = *vp;
654       ctx->pipe->set_viewport_state(ctx->pipe, vp);
655    }
656    return PIPE_OK;
657 }
658 
cso_save_viewport(struct cso_context * ctx)659 void cso_save_viewport(struct cso_context *ctx)
660 {
661    ctx->vp_saved = ctx->vp;
662 }
663 
664 
cso_restore_viewport(struct cso_context * ctx)665 void cso_restore_viewport(struct cso_context *ctx)
666 {
667    if (memcmp(&ctx->vp, &ctx->vp_saved, sizeof(ctx->vp))) {
668       ctx->vp = ctx->vp_saved;
669       ctx->pipe->set_viewport_state(ctx->pipe, &ctx->vp);
670    }
671 }
672 
673 
cso_set_blend_color(struct cso_context * ctx,const struct pipe_blend_color * bc)674 enum pipe_error cso_set_blend_color(struct cso_context *ctx,
675                                     const struct pipe_blend_color *bc)
676 {
677    if (memcmp(&ctx->blend_color, bc, sizeof(ctx->blend_color))) {
678       ctx->blend_color = *bc;
679       ctx->pipe->set_blend_color(ctx->pipe, bc);
680    }
681    return PIPE_OK;
682 }
683 
cso_set_sample_mask(struct cso_context * ctx,unsigned sample_mask)684 enum pipe_error cso_set_sample_mask(struct cso_context *ctx,
685                                     unsigned sample_mask)
686 {
687    if (ctx->sample_mask != sample_mask) {
688       ctx->sample_mask = sample_mask;
689       ctx->pipe->set_sample_mask(ctx->pipe, sample_mask);
690    }
691    return PIPE_OK;
692 }
693 
cso_save_sample_mask(struct cso_context * ctx)694 void cso_save_sample_mask(struct cso_context *ctx)
695 {
696    ctx->sample_mask_saved = ctx->sample_mask;
697 }
698 
cso_restore_sample_mask(struct cso_context * ctx)699 void cso_restore_sample_mask(struct cso_context *ctx)
700 {
701    cso_set_sample_mask(ctx, ctx->sample_mask_saved);
702 }
703 
cso_set_stencil_ref(struct cso_context * ctx,const struct pipe_stencil_ref * sr)704 enum pipe_error cso_set_stencil_ref(struct cso_context *ctx,
705                                     const struct pipe_stencil_ref *sr)
706 {
707    if (memcmp(&ctx->stencil_ref, sr, sizeof(ctx->stencil_ref))) {
708       ctx->stencil_ref = *sr;
709       ctx->pipe->set_stencil_ref(ctx->pipe, sr);
710    }
711    return PIPE_OK;
712 }
713 
cso_save_stencil_ref(struct cso_context * ctx)714 void cso_save_stencil_ref(struct cso_context *ctx)
715 {
716    ctx->stencil_ref_saved = ctx->stencil_ref;
717 }
718 
719 
cso_restore_stencil_ref(struct cso_context * ctx)720 void cso_restore_stencil_ref(struct cso_context *ctx)
721 {
722    if (memcmp(&ctx->stencil_ref, &ctx->stencil_ref_saved,
723               sizeof(ctx->stencil_ref))) {
724       ctx->stencil_ref = ctx->stencil_ref_saved;
725       ctx->pipe->set_stencil_ref(ctx->pipe, &ctx->stencil_ref);
726    }
727 }
728 
cso_set_geometry_shader_handle(struct cso_context * ctx,void * handle)729 enum pipe_error cso_set_geometry_shader_handle(struct cso_context *ctx,
730                                                void *handle)
731 {
732    assert(ctx->has_geometry_shader || !handle);
733 
734    if (ctx->has_geometry_shader && ctx->geometry_shader != handle) {
735       ctx->geometry_shader = handle;
736       ctx->pipe->bind_gs_state(ctx->pipe, handle);
737    }
738    return PIPE_OK;
739 }
740 
cso_delete_geometry_shader(struct cso_context * ctx,void * handle)741 void cso_delete_geometry_shader(struct cso_context *ctx, void *handle)
742 {
743     if (handle == ctx->geometry_shader) {
744       /* unbind before deleting */
745       ctx->pipe->bind_gs_state(ctx->pipe, NULL);
746       ctx->geometry_shader = NULL;
747    }
748    ctx->pipe->delete_gs_state(ctx->pipe, handle);
749 }
750 
cso_save_geometry_shader(struct cso_context * ctx)751 void cso_save_geometry_shader(struct cso_context *ctx)
752 {
753    if (!ctx->has_geometry_shader) {
754       return;
755    }
756 
757    assert(!ctx->geometry_shader_saved);
758    ctx->geometry_shader_saved = ctx->geometry_shader;
759 }
760 
cso_restore_geometry_shader(struct cso_context * ctx)761 void cso_restore_geometry_shader(struct cso_context *ctx)
762 {
763    if (!ctx->has_geometry_shader) {
764       return;
765    }
766 
767    if (ctx->geometry_shader_saved != ctx->geometry_shader) {
768       ctx->pipe->bind_gs_state(ctx->pipe, ctx->geometry_shader_saved);
769       ctx->geometry_shader = ctx->geometry_shader_saved;
770    }
771    ctx->geometry_shader_saved = NULL;
772 }
773 
774 /* clip state */
775 
776 static INLINE void
clip_state_cpy(struct pipe_clip_state * dst,const struct pipe_clip_state * src)777 clip_state_cpy(struct pipe_clip_state *dst,
778                const struct pipe_clip_state *src)
779 {
780    memcpy(dst->ucp, src->ucp, sizeof(dst->ucp));
781 }
782 
783 static INLINE int
clip_state_cmp(const struct pipe_clip_state * a,const struct pipe_clip_state * b)784 clip_state_cmp(const struct pipe_clip_state *a,
785                const struct pipe_clip_state *b)
786 {
787    return memcmp(a->ucp, b->ucp, sizeof(a->ucp));
788 }
789 
790 void
cso_set_clip(struct cso_context * ctx,const struct pipe_clip_state * clip)791 cso_set_clip(struct cso_context *ctx,
792              const struct pipe_clip_state *clip)
793 {
794    if (clip_state_cmp(&ctx->clip, clip)) {
795       clip_state_cpy(&ctx->clip, clip);
796       ctx->pipe->set_clip_state(ctx->pipe, clip);
797    }
798 }
799 
800 void
cso_save_clip(struct cso_context * ctx)801 cso_save_clip(struct cso_context *ctx)
802 {
803    clip_state_cpy(&ctx->clip_saved, &ctx->clip);
804 }
805 
806 void
cso_restore_clip(struct cso_context * ctx)807 cso_restore_clip(struct cso_context *ctx)
808 {
809    if (clip_state_cmp(&ctx->clip, &ctx->clip_saved)) {
810       clip_state_cpy(&ctx->clip, &ctx->clip_saved);
811       ctx->pipe->set_clip_state(ctx->pipe, &ctx->clip_saved);
812    }
813 }
814 
815 enum pipe_error
cso_set_vertex_elements(struct cso_context * ctx,unsigned count,const struct pipe_vertex_element * states)816 cso_set_vertex_elements(struct cso_context *ctx,
817                         unsigned count,
818                         const struct pipe_vertex_element *states)
819 {
820    struct u_vbuf *vbuf = ctx->vbuf;
821    unsigned key_size, hash_key;
822    struct cso_hash_iter iter;
823    void *handle;
824    struct cso_velems_state velems_state;
825 
826    if (vbuf) {
827       u_vbuf_set_vertex_elements(vbuf, count, states);
828       return PIPE_OK;
829    }
830 
831    /* Need to include the count into the stored state data too.
832     * Otherwise first few count pipe_vertex_elements could be identical
833     * even if count is different, and there's no guarantee the hash would
834     * be different in that case neither.
835     */
836    key_size = sizeof(struct pipe_vertex_element) * count + sizeof(unsigned);
837    velems_state.count = count;
838    memcpy(velems_state.velems, states,
839           sizeof(struct pipe_vertex_element) * count);
840    hash_key = cso_construct_key((void*)&velems_state, key_size);
841    iter = cso_find_state_template(ctx->cache, hash_key, CSO_VELEMENTS,
842                                   (void*)&velems_state, key_size);
843 
844    if (cso_hash_iter_is_null(iter)) {
845       struct cso_velements *cso = MALLOC(sizeof(struct cso_velements));
846       if (!cso)
847          return PIPE_ERROR_OUT_OF_MEMORY;
848 
849       memcpy(&cso->state, &velems_state, key_size);
850       cso->data = ctx->pipe->create_vertex_elements_state(ctx->pipe, count,
851                                                       &cso->state.velems[0]);
852       cso->delete_state =
853          (cso_state_callback) ctx->pipe->delete_vertex_elements_state;
854       cso->context = ctx->pipe;
855 
856       iter = cso_insert_state(ctx->cache, hash_key, CSO_VELEMENTS, cso);
857       if (cso_hash_iter_is_null(iter)) {
858          FREE(cso);
859          return PIPE_ERROR_OUT_OF_MEMORY;
860       }
861 
862       handle = cso->data;
863    }
864    else {
865       handle = ((struct cso_velements *)cso_hash_iter_data(iter))->data;
866    }
867 
868    if (ctx->velements != handle) {
869       ctx->velements = handle;
870       ctx->pipe->bind_vertex_elements_state(ctx->pipe, handle);
871    }
872    return PIPE_OK;
873 }
874 
cso_save_vertex_elements(struct cso_context * ctx)875 void cso_save_vertex_elements(struct cso_context *ctx)
876 {
877    struct u_vbuf *vbuf = ctx->vbuf;
878 
879    if (vbuf) {
880       u_vbuf_save_vertex_elements(vbuf);
881       return;
882    }
883 
884    assert(!ctx->velements_saved);
885    ctx->velements_saved = ctx->velements;
886 }
887 
cso_restore_vertex_elements(struct cso_context * ctx)888 void cso_restore_vertex_elements(struct cso_context *ctx)
889 {
890    struct u_vbuf *vbuf = ctx->vbuf;
891 
892    if (vbuf) {
893       u_vbuf_restore_vertex_elements(vbuf);
894       return;
895    }
896 
897    if (ctx->velements != ctx->velements_saved) {
898       ctx->velements = ctx->velements_saved;
899       ctx->pipe->bind_vertex_elements_state(ctx->pipe, ctx->velements_saved);
900    }
901    ctx->velements_saved = NULL;
902 }
903 
904 /* vertex buffers */
905 
cso_set_vertex_buffers(struct cso_context * ctx,unsigned count,const struct pipe_vertex_buffer * buffers)906 void cso_set_vertex_buffers(struct cso_context *ctx,
907                             unsigned count,
908                             const struct pipe_vertex_buffer *buffers)
909 {
910    struct u_vbuf *vbuf = ctx->vbuf;
911 
912    if (vbuf) {
913       u_vbuf_set_vertex_buffers(vbuf, count, buffers);
914       return;
915    }
916 
917    if (count != ctx->nr_vertex_buffers ||
918        memcmp(buffers, ctx->vertex_buffers,
919               sizeof(struct pipe_vertex_buffer) * count) != 0) {
920       util_copy_vertex_buffers(ctx->vertex_buffers, &ctx->nr_vertex_buffers,
921                                buffers, count);
922       ctx->pipe->set_vertex_buffers(ctx->pipe, count, buffers);
923    }
924 }
925 
cso_save_vertex_buffers(struct cso_context * ctx)926 void cso_save_vertex_buffers(struct cso_context *ctx)
927 {
928    struct u_vbuf *vbuf = ctx->vbuf;
929 
930    if (vbuf) {
931       u_vbuf_save_vertex_buffers(vbuf);
932       return;
933    }
934 
935    util_copy_vertex_buffers(ctx->vertex_buffers_saved,
936                             &ctx->nr_vertex_buffers_saved,
937                             ctx->vertex_buffers,
938                             ctx->nr_vertex_buffers);
939 }
940 
cso_restore_vertex_buffers(struct cso_context * ctx)941 void cso_restore_vertex_buffers(struct cso_context *ctx)
942 {
943    unsigned i;
944    struct u_vbuf *vbuf = ctx->vbuf;
945 
946    if (vbuf) {
947       u_vbuf_restore_vertex_buffers(vbuf);
948       return;
949    }
950 
951    util_copy_vertex_buffers(ctx->vertex_buffers,
952                             &ctx->nr_vertex_buffers,
953                             ctx->vertex_buffers_saved,
954                             ctx->nr_vertex_buffers_saved);
955 
956    for (i = 0; i < ctx->nr_vertex_buffers_saved; i++) {
957       pipe_resource_reference(&ctx->vertex_buffers_saved[i].buffer, NULL);
958    }
959    ctx->nr_vertex_buffers_saved = 0;
960 
961    ctx->pipe->set_vertex_buffers(ctx->pipe, ctx->nr_vertex_buffers,
962                                  ctx->vertex_buffers);
963 }
964 
965 
966 /**************** fragment/vertex sampler view state *************************/
967 
968 static enum pipe_error
single_sampler(struct cso_context * ctx,struct sampler_info * info,unsigned idx,const struct pipe_sampler_state * templ)969 single_sampler(struct cso_context *ctx,
970                struct sampler_info *info,
971                unsigned idx,
972                const struct pipe_sampler_state *templ)
973 {
974    void *handle = NULL;
975 
976    if (templ != NULL) {
977       unsigned key_size = sizeof(struct pipe_sampler_state);
978       unsigned hash_key = cso_construct_key((void*)templ, key_size);
979       struct cso_hash_iter iter =
980          cso_find_state_template(ctx->cache,
981                                  hash_key, CSO_SAMPLER,
982                                  (void *) templ, key_size);
983 
984       if (cso_hash_iter_is_null(iter)) {
985          struct cso_sampler *cso = MALLOC(sizeof(struct cso_sampler));
986          if (!cso)
987             return PIPE_ERROR_OUT_OF_MEMORY;
988 
989          memcpy(&cso->state, templ, sizeof(*templ));
990          cso->data = ctx->pipe->create_sampler_state(ctx->pipe, &cso->state);
991          cso->delete_state =
992             (cso_state_callback) ctx->pipe->delete_sampler_state;
993          cso->context = ctx->pipe;
994 
995          iter = cso_insert_state(ctx->cache, hash_key, CSO_SAMPLER, cso);
996          if (cso_hash_iter_is_null(iter)) {
997             FREE(cso);
998             return PIPE_ERROR_OUT_OF_MEMORY;
999          }
1000 
1001          handle = cso->data;
1002       }
1003       else {
1004          handle = ((struct cso_sampler *)cso_hash_iter_data(iter))->data;
1005       }
1006    }
1007 
1008    info->samplers[idx] = handle;
1009 
1010    return PIPE_OK;
1011 }
1012 
1013 enum pipe_error
cso_single_sampler(struct cso_context * ctx,unsigned shader_stage,unsigned idx,const struct pipe_sampler_state * templ)1014 cso_single_sampler(struct cso_context *ctx,
1015                    unsigned shader_stage,
1016                    unsigned idx,
1017                    const struct pipe_sampler_state *templ)
1018 {
1019    return single_sampler(ctx, &ctx->samplers[shader_stage], idx, templ);
1020 }
1021 
1022 
1023 
1024 static void
single_sampler_done(struct cso_context * ctx,unsigned shader_stage)1025 single_sampler_done(struct cso_context *ctx, unsigned shader_stage)
1026 {
1027    struct sampler_info *info = &ctx->samplers[shader_stage];
1028    unsigned i;
1029 
1030    /* find highest non-null sampler */
1031    for (i = PIPE_MAX_SAMPLERS; i > 0; i--) {
1032       if (info->samplers[i - 1] != NULL)
1033          break;
1034    }
1035 
1036    info->nr_samplers = i;
1037 
1038    if (info->hw.nr_samplers != info->nr_samplers ||
1039        memcmp(info->hw.samplers,
1040               info->samplers,
1041               info->nr_samplers * sizeof(void *)) != 0)
1042    {
1043       memcpy(info->hw.samplers,
1044              info->samplers,
1045              info->nr_samplers * sizeof(void *));
1046       info->hw.nr_samplers = info->nr_samplers;
1047 
1048       switch (shader_stage) {
1049       case PIPE_SHADER_FRAGMENT:
1050          ctx->pipe->bind_fragment_sampler_states(ctx->pipe,
1051                                                  info->nr_samplers,
1052                                                  info->samplers);
1053          break;
1054       case PIPE_SHADER_VERTEX:
1055          ctx->pipe->bind_vertex_sampler_states(ctx->pipe,
1056                                                info->nr_samplers,
1057                                                info->samplers);
1058          break;
1059       case PIPE_SHADER_GEOMETRY:
1060          ctx->pipe->bind_geometry_sampler_states(ctx->pipe,
1061                                                info->nr_samplers,
1062                                                info->samplers);
1063          break;
1064       default:
1065          assert(!"bad shader type in single_sampler_done()");
1066       }
1067    }
1068 }
1069 
1070 void
cso_single_sampler_done(struct cso_context * ctx,unsigned shader_stage)1071 cso_single_sampler_done(struct cso_context *ctx, unsigned shader_stage)
1072 {
1073    single_sampler_done(ctx, shader_stage);
1074 }
1075 
1076 
1077 /*
1078  * If the function encouters any errors it will return the
1079  * last one. Done to always try to set as many samplers
1080  * as possible.
1081  */
1082 enum pipe_error
cso_set_samplers(struct cso_context * ctx,unsigned shader_stage,unsigned nr,const struct pipe_sampler_state ** templates)1083 cso_set_samplers(struct cso_context *ctx,
1084                  unsigned shader_stage,
1085                  unsigned nr,
1086                  const struct pipe_sampler_state **templates)
1087 {
1088    struct sampler_info *info = &ctx->samplers[shader_stage];
1089    unsigned i;
1090    enum pipe_error temp, error = PIPE_OK;
1091 
1092    /* TODO: fastpath
1093     */
1094 
1095    for (i = 0; i < nr; i++) {
1096       temp = single_sampler(ctx, info, i, templates[i]);
1097       if (temp != PIPE_OK)
1098          error = temp;
1099    }
1100 
1101    for ( ; i < info->nr_samplers; i++) {
1102       temp = single_sampler(ctx, info, i, NULL);
1103       if (temp != PIPE_OK)
1104          error = temp;
1105    }
1106 
1107    single_sampler_done(ctx, shader_stage);
1108 
1109    return error;
1110 }
1111 
1112 void
cso_save_samplers(struct cso_context * ctx,unsigned shader_stage)1113 cso_save_samplers(struct cso_context *ctx, unsigned shader_stage)
1114 {
1115    struct sampler_info *info = &ctx->samplers[shader_stage];
1116    info->nr_samplers_saved = info->nr_samplers;
1117    memcpy(info->samplers_saved, info->samplers, sizeof(info->samplers));
1118 }
1119 
1120 
1121 void
cso_restore_samplers(struct cso_context * ctx,unsigned shader_stage)1122 cso_restore_samplers(struct cso_context *ctx, unsigned shader_stage)
1123 {
1124    struct sampler_info *info = &ctx->samplers[shader_stage];
1125    info->nr_samplers = info->nr_samplers_saved;
1126    memcpy(info->samplers, info->samplers_saved, sizeof(info->samplers));
1127    single_sampler_done(ctx, shader_stage);
1128 }
1129 
1130 
1131 void
cso_set_sampler_views(struct cso_context * ctx,unsigned shader_stage,unsigned count,struct pipe_sampler_view ** views)1132 cso_set_sampler_views(struct cso_context *ctx,
1133                       unsigned shader_stage,
1134                       unsigned count,
1135                       struct pipe_sampler_view **views)
1136 {
1137    struct sampler_info *info = &ctx->samplers[shader_stage];
1138    unsigned i;
1139 
1140    /* reference new views */
1141    for (i = 0; i < count; i++) {
1142       pipe_sampler_view_reference(&info->views[i], views[i]);
1143    }
1144    /* unref extra old views, if any */
1145    for (; i < info->nr_views; i++) {
1146       pipe_sampler_view_reference(&info->views[i], NULL);
1147    }
1148 
1149    info->nr_views = count;
1150 
1151    /* bind the new sampler views */
1152    switch (shader_stage) {
1153    case PIPE_SHADER_FRAGMENT:
1154       ctx->pipe->set_fragment_sampler_views(ctx->pipe, count, info->views);
1155       break;
1156    case PIPE_SHADER_VERTEX:
1157       ctx->pipe->set_vertex_sampler_views(ctx->pipe, count, info->views);
1158       break;
1159    case PIPE_SHADER_GEOMETRY:
1160       ctx->pipe->set_geometry_sampler_views(ctx->pipe, count, info->views);
1161       break;
1162    default:
1163       assert(!"bad shader type in cso_set_sampler_views()");
1164    }
1165 }
1166 
1167 
1168 void
cso_save_sampler_views(struct cso_context * ctx,unsigned shader_stage)1169 cso_save_sampler_views(struct cso_context *ctx, unsigned shader_stage)
1170 {
1171    struct sampler_info *info = &ctx->samplers[shader_stage];
1172    unsigned i;
1173 
1174    info->nr_views_saved = info->nr_views;
1175 
1176    for (i = 0; i < info->nr_views; i++) {
1177       assert(!info->views_saved[i]);
1178       pipe_sampler_view_reference(&info->views_saved[i], info->views[i]);
1179    }
1180 }
1181 
1182 
1183 void
cso_restore_sampler_views(struct cso_context * ctx,unsigned shader_stage)1184 cso_restore_sampler_views(struct cso_context *ctx, unsigned shader_stage)
1185 {
1186    struct sampler_info *info = &ctx->samplers[shader_stage];
1187    unsigned i, nr_saved = info->nr_views_saved;
1188 
1189    for (i = 0; i < nr_saved; i++) {
1190       pipe_sampler_view_reference(&info->views[i], NULL);
1191       /* move the reference from one pointer to another */
1192       info->views[i] = info->views_saved[i];
1193       info->views_saved[i] = NULL;
1194    }
1195    for (; i < info->nr_views; i++) {
1196       pipe_sampler_view_reference(&info->views[i], NULL);
1197    }
1198 
1199    /* bind the old/saved sampler views */
1200    switch (shader_stage) {
1201    case PIPE_SHADER_FRAGMENT:
1202       ctx->pipe->set_fragment_sampler_views(ctx->pipe, nr_saved, info->views);
1203       break;
1204    case PIPE_SHADER_VERTEX:
1205       ctx->pipe->set_vertex_sampler_views(ctx->pipe, nr_saved, info->views);
1206       break;
1207    case PIPE_SHADER_GEOMETRY:
1208       ctx->pipe->set_geometry_sampler_views(ctx->pipe, nr_saved, info->views);
1209       break;
1210    default:
1211       assert(!"bad shader type in cso_restore_sampler_views()");
1212    }
1213 
1214    info->nr_views = nr_saved;
1215    info->nr_views_saved = 0;
1216 }
1217 
1218 
1219 void
cso_set_stream_outputs(struct cso_context * ctx,unsigned num_targets,struct pipe_stream_output_target ** targets,unsigned append_bitmask)1220 cso_set_stream_outputs(struct cso_context *ctx,
1221                        unsigned num_targets,
1222                        struct pipe_stream_output_target **targets,
1223                        unsigned append_bitmask)
1224 {
1225    struct pipe_context *pipe = ctx->pipe;
1226    uint i;
1227 
1228    if (!ctx->has_streamout) {
1229       assert(num_targets == 0);
1230       return;
1231    }
1232 
1233    if (ctx->nr_so_targets == 0 && num_targets == 0) {
1234       /* Nothing to do. */
1235       return;
1236    }
1237 
1238    /* reference new targets */
1239    for (i = 0; i < num_targets; i++) {
1240       pipe_so_target_reference(&ctx->so_targets[i], targets[i]);
1241    }
1242    /* unref extra old targets, if any */
1243    for (; i < ctx->nr_so_targets; i++) {
1244       pipe_so_target_reference(&ctx->so_targets[i], NULL);
1245    }
1246 
1247    pipe->set_stream_output_targets(pipe, num_targets, targets,
1248                                    append_bitmask);
1249    ctx->nr_so_targets = num_targets;
1250 }
1251 
1252 void
cso_save_stream_outputs(struct cso_context * ctx)1253 cso_save_stream_outputs(struct cso_context *ctx)
1254 {
1255    uint i;
1256 
1257    if (!ctx->has_streamout) {
1258       return;
1259    }
1260 
1261    ctx->nr_so_targets_saved = ctx->nr_so_targets;
1262 
1263    for (i = 0; i < ctx->nr_so_targets; i++) {
1264       assert(!ctx->so_targets_saved[i]);
1265       pipe_so_target_reference(&ctx->so_targets_saved[i], ctx->so_targets[i]);
1266    }
1267 }
1268 
1269 void
cso_restore_stream_outputs(struct cso_context * ctx)1270 cso_restore_stream_outputs(struct cso_context *ctx)
1271 {
1272    struct pipe_context *pipe = ctx->pipe;
1273    uint i;
1274 
1275    if (!ctx->has_streamout) {
1276       return;
1277    }
1278 
1279    if (ctx->nr_so_targets == 0 && ctx->nr_so_targets_saved == 0) {
1280       /* Nothing to do. */
1281       return;
1282    }
1283 
1284    for (i = 0; i < ctx->nr_so_targets_saved; i++) {
1285       pipe_so_target_reference(&ctx->so_targets[i], NULL);
1286       /* move the reference from one pointer to another */
1287       ctx->so_targets[i] = ctx->so_targets_saved[i];
1288       ctx->so_targets_saved[i] = NULL;
1289    }
1290    for (; i < ctx->nr_so_targets; i++) {
1291       pipe_so_target_reference(&ctx->so_targets[i], NULL);
1292    }
1293 
1294    /* ~0 means append */
1295    pipe->set_stream_output_targets(pipe, ctx->nr_so_targets_saved,
1296                                    ctx->so_targets, ~0);
1297 
1298    ctx->nr_so_targets = ctx->nr_so_targets_saved;
1299    ctx->nr_so_targets_saved = 0;
1300 }
1301 
1302 /* drawing */
1303 
1304 void
cso_set_index_buffer(struct cso_context * cso,const struct pipe_index_buffer * ib)1305 cso_set_index_buffer(struct cso_context *cso,
1306                      const struct pipe_index_buffer *ib)
1307 {
1308    struct u_vbuf *vbuf = cso->vbuf;
1309 
1310    if (vbuf) {
1311       u_vbuf_set_index_buffer(vbuf, ib);
1312    } else {
1313       struct pipe_context *pipe = cso->pipe;
1314       pipe->set_index_buffer(pipe, ib);
1315    }
1316 }
1317 
1318 void
cso_draw_vbo(struct cso_context * cso,const struct pipe_draw_info * info)1319 cso_draw_vbo(struct cso_context *cso,
1320              const struct pipe_draw_info *info)
1321 {
1322    struct u_vbuf *vbuf = cso->vbuf;
1323 
1324    if (vbuf) {
1325       u_vbuf_draw_vbo(vbuf, info);
1326    } else {
1327       struct pipe_context *pipe = cso->pipe;
1328       pipe->draw_vbo(pipe, info);
1329    }
1330 }
1331 
1332 void
cso_draw_arrays(struct cso_context * cso,uint mode,uint start,uint count)1333 cso_draw_arrays(struct cso_context *cso, uint mode, uint start, uint count)
1334 {
1335    struct pipe_draw_info info;
1336 
1337    util_draw_init_info(&info);
1338 
1339    info.mode = mode;
1340    info.start = start;
1341    info.count = count;
1342    info.min_index = start;
1343    info.max_index = start + count - 1;
1344 
1345    cso_draw_vbo(cso, &info);
1346 }
1347