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