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