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