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