b46e66869d8bfd5b2e2af8d0f4b8bf7cd144e573
[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 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 */
364 void 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
382 enum 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
424 void cso_save_blend(struct cso_context *ctx)
425 {
426 assert(!ctx->blend_saved);
427 ctx->blend_saved = ctx->blend;
428 }
429
430 void 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
441 enum 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
481 void 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
487 void 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
498 enum 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
537 void cso_save_rasterizer(struct cso_context *ctx)
538 {
539 assert(!ctx->rasterizer_saved);
540 ctx->rasterizer_saved = ctx->rasterizer;
541 }
542
543 void 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
554 enum 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
564 void 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
577 enum 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
620 void 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
626 void 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
636 enum 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
646 void 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
660 enum 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
700 void 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
706 void 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
716 enum 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
726 void cso_save_framebuffer(struct cso_context *ctx)
727 {
728 util_copy_framebuffer_state(&ctx->fb_saved, &ctx->fb);
729 }
730
731 void 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
741 enum 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
751 void cso_save_viewport(struct cso_context *ctx)
752 {
753 ctx->vp_saved = ctx->vp;
754 }
755
756
757 void 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
766 enum 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
776 enum 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
786 enum 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
796 void cso_save_stencil_ref(struct cso_context *ctx)
797 {
798 ctx->stencil_ref_saved = ctx->stencil_ref;
799 }
800
801
802 void 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
810 enum 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
822 void 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
832 void 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
842 void 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
857 static INLINE void
858 clip_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
868 static INLINE int
869 clip_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
884 void
885 cso_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
894 void
895 cso_save_clip(struct cso_context *ctx)
896 {
897 clip_state_cpy(&ctx->clip_saved, &ctx->clip);
898 }
899
900 void
901 cso_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
909 enum 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
957 void cso_save_vertex_elements(struct cso_context *ctx)
958 {
959 assert(!ctx->velements_saved);
960 ctx->velements_saved = ctx->velements;
961 }
962
963 void 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
974 void 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
987 void 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
995 void 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
1008 static enum pipe_error
1009 single_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
1052 enum pipe_error
1053 cso_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
1060 enum pipe_error
1061 cso_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
1070 static void
1071 single_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
1110 void
1111 cso_single_sampler_done( struct cso_context *ctx )
1112 {
1113 single_sampler_done(ctx, &ctx->fragment_samplers);
1114 }
1115
1116 void
1117 cso_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 */
1128 static enum pipe_error
1129 set_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
1157 enum pipe_error
1158 cso_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
1165 enum pipe_error
1166 cso_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
1175 static void
1176 save_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
1182 void
1183 cso_save_samplers(struct cso_context *ctx)
1184 {
1185 save_samplers(ctx, &ctx->fragment_samplers);
1186 }
1187
1188 void
1189 cso_save_vertex_samplers(struct cso_context *ctx)
1190 {
1191 save_samplers(ctx, &ctx->vertex_samplers);
1192 }
1193
1194
1195
1196 static void
1197 restore_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
1204 void
1205 cso_restore_samplers(struct cso_context *ctx)
1206 {
1207 restore_samplers(ctx, &ctx->fragment_samplers);
1208 }
1209
1210 void
1211 cso_restore_vertex_samplers(struct cso_context *ctx)
1212 {
1213 restore_samplers(ctx, &ctx->vertex_samplers);
1214 }
1215
1216
1217
1218 static void
1219 set_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
1244 void
1245 cso_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
1254 void
1255 cso_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
1266 static void
1267 save_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
1280 void
1281 cso_save_fragment_sampler_views(struct cso_context *ctx)
1282 {
1283 save_sampler_views(ctx, &ctx->fragment_samplers);
1284 }
1285
1286 void
1287 cso_save_vertex_sampler_views(struct cso_context *ctx)
1288 {
1289 save_sampler_views(ctx, &ctx->vertex_samplers);
1290 }
1291
1292
1293 static void
1294 restore_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
1319 void
1320 cso_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
1326 void
1327 cso_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
1334 void
1335 cso_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
1367 void
1368 cso_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
1384 void
1385 cso_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 }