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