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