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