st/mesa: implement EXT_transform_feedback and ARB_transform_feedback2
[mesa.git] / src / gallium / auxiliary / cso_cache / cso_context.c
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 */
55 struct 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
77 struct 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
120 static 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
133 static 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
147 static 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
156 static 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
168 static 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
179 static 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
190 static 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
205 static 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
237 static 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
262 struct 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
293 out:
294 cso_destroy_context( ctx );
295 return NULL;
296 }
297
298
299 /**
300 * Prior to context destruction, this function unbinds all state objects.
301 */
302 void 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 */
363 void 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
381 enum 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
423 void cso_save_blend(struct cso_context *ctx)
424 {
425 assert(!ctx->blend_saved);
426 ctx->blend_saved = ctx->blend;
427 }
428
429 void 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
440 enum 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
480 void 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
486 void 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
497 enum 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
536 void cso_save_rasterizer(struct cso_context *ctx)
537 {
538 assert(!ctx->rasterizer_saved);
539 ctx->rasterizer_saved = ctx->rasterizer;
540 }
541
542 void 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
553 enum 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
563 void 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
576 enum 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
619 void 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
625 void 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
635 enum 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
645 void 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
659 enum 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
699 void 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
705 void 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
715 enum 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
725 void cso_save_framebuffer(struct cso_context *ctx)
726 {
727 util_copy_framebuffer_state(&ctx->fb_saved, &ctx->fb);
728 }
729
730 void 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
740 enum 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
750 void cso_save_viewport(struct cso_context *ctx)
751 {
752 ctx->vp_saved = ctx->vp;
753 }
754
755
756 void 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
765 enum 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
775 enum 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
785 enum 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
795 void cso_save_stencil_ref(struct cso_context *ctx)
796 {
797 ctx->stencil_ref_saved = ctx->stencil_ref;
798 }
799
800
801 void 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
809 enum 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
821 void 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
831 void 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
841 void 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
856 static INLINE void
857 clip_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
867 static INLINE int
868 clip_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
883 void
884 cso_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
893 void
894 cso_save_clip(struct cso_context *ctx)
895 {
896 clip_state_cpy(&ctx->clip_saved, &ctx->clip);
897 }
898
899 void
900 cso_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
908 enum 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
956 void cso_save_vertex_elements(struct cso_context *ctx)
957 {
958 assert(!ctx->velements_saved);
959 ctx->velements_saved = ctx->velements;
960 }
961
962 void 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
973 void 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
986 void 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
994 void 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
1007 static enum pipe_error
1008 single_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
1051 enum pipe_error
1052 cso_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
1059 enum pipe_error
1060 cso_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
1069 static void
1070 single_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
1109 void
1110 cso_single_sampler_done( struct cso_context *ctx )
1111 {
1112 single_sampler_done(ctx, &ctx->fragment_samplers);
1113 }
1114
1115 void
1116 cso_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 */
1127 static enum pipe_error
1128 set_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
1156 enum pipe_error
1157 cso_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
1164 enum pipe_error
1165 cso_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
1174 static void
1175 save_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
1181 void
1182 cso_save_samplers(struct cso_context *ctx)
1183 {
1184 save_samplers(ctx, &ctx->fragment_samplers);
1185 }
1186
1187 void
1188 cso_save_vertex_samplers(struct cso_context *ctx)
1189 {
1190 save_samplers(ctx, &ctx->vertex_samplers);
1191 }
1192
1193
1194
1195 static void
1196 restore_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
1203 void
1204 cso_restore_samplers(struct cso_context *ctx)
1205 {
1206 restore_samplers(ctx, &ctx->fragment_samplers);
1207 }
1208
1209 void
1210 cso_restore_vertex_samplers(struct cso_context *ctx)
1211 {
1212 restore_samplers(ctx, &ctx->vertex_samplers);
1213 }
1214
1215
1216
1217 static void
1218 set_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
1243 void
1244 cso_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
1253 void
1254 cso_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
1265 static void
1266 save_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
1279 void
1280 cso_save_fragment_sampler_views(struct cso_context *ctx)
1281 {
1282 save_sampler_views(ctx, &ctx->fragment_samplers);
1283 }
1284
1285 void
1286 cso_save_vertex_sampler_views(struct cso_context *ctx)
1287 {
1288 save_sampler_views(ctx, &ctx->vertex_samplers);
1289 }
1290
1291
1292 static void
1293 restore_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
1318 void
1319 cso_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
1325 void
1326 cso_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
1333 void
1334 cso_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
1366 void
1367 cso_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
1383 void
1384 cso_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 }