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