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