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