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