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