revert 213 commits (to 56092) from the last month. 10 still need work to resolve...
[AROS.git] / workbench / libs / mesa / src / gallium / auxiliary / cso_cache / cso_context.c
blobfdd40fca126f2a8a1a3af3df6f96a6da02878a55
1 /**************************************************************************
3 * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
4 * All Rights Reserved.
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:
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.
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.
26 **************************************************************************/
28 /**
29 * @file
31 * Wrap the cso cache & hash mechanisms in a simplified
32 * pipe-driver-specific interface.
34 * @author Zack Rusin <zack@tungstengraphics.com>
35 * @author Keith Whitwell <keith@tungstengraphics.com>
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"
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"
51 /**
52 * Info related to samplers and sampler views.
53 * We have one of these for fragment samplers and another for vertex samplers.
55 struct sampler_info
57 struct {
58 void *samplers[PIPE_MAX_SAMPLERS];
59 unsigned nr_samplers;
60 } hw;
62 void *samplers[PIPE_MAX_SAMPLERS];
63 unsigned nr_samplers;
65 void *samplers_saved[PIPE_MAX_SAMPLERS];
66 unsigned nr_samplers_saved;
68 struct pipe_sampler_view *views[PIPE_MAX_SAMPLERS];
69 unsigned nr_views;
71 struct pipe_sampler_view *views_saved[PIPE_MAX_SAMPLERS];
72 unsigned nr_views_saved;
77 struct cso_context {
78 struct pipe_context *pipe;
79 struct cso_cache *cache;
81 struct sampler_info fragment_samplers;
82 struct sampler_info vertex_samplers;
84 uint nr_vertex_buffers;
85 struct pipe_vertex_buffer vertex_buffers[PIPE_MAX_ATTRIBS];
87 uint nr_vertex_buffers_saved;
88 struct pipe_vertex_buffer vertex_buffers_saved[PIPE_MAX_ATTRIBS];
90 /** Current and saved state.
91 * The saved state is used as a 1-deep stack.
93 void *blend, *blend_saved;
94 void *depth_stencil, *depth_stencil_saved;
95 void *rasterizer, *rasterizer_saved;
96 void *fragment_shader, *fragment_shader_saved, *geometry_shader;
97 void *vertex_shader, *vertex_shader_saved, *geometry_shader_saved;
98 void *velements, *velements_saved;
100 struct pipe_clip_state clip;
101 struct pipe_clip_state clip_saved;
103 struct pipe_framebuffer_state fb, fb_saved;
104 struct pipe_viewport_state vp, vp_saved;
105 struct pipe_blend_color blend_color;
106 unsigned sample_mask;
107 struct pipe_stencil_ref stencil_ref, stencil_ref_saved;
111 static boolean delete_blend_state(struct cso_context *ctx, void *state)
113 struct cso_blend *cso = (struct cso_blend *)state;
115 if (ctx->blend == cso->data)
116 return FALSE;
118 if (cso->delete_state)
119 cso->delete_state(cso->context, cso->data);
120 FREE(state);
121 return TRUE;
124 static boolean delete_depth_stencil_state(struct cso_context *ctx, void *state)
126 struct cso_depth_stencil_alpha *cso = (struct cso_depth_stencil_alpha *)state;
128 if (ctx->depth_stencil == cso->data)
129 return FALSE;
131 if (cso->delete_state)
132 cso->delete_state(cso->context, cso->data);
133 FREE(state);
135 return TRUE;
138 static boolean delete_sampler_state(struct cso_context *ctx, void *state)
140 struct cso_sampler *cso = (struct cso_sampler *)state;
141 if (cso->delete_state)
142 cso->delete_state(cso->context, cso->data);
143 FREE(state);
144 return TRUE;
147 static boolean delete_rasterizer_state(struct cso_context *ctx, void *state)
149 struct cso_rasterizer *cso = (struct cso_rasterizer *)state;
151 if (ctx->rasterizer == cso->data)
152 return FALSE;
153 if (cso->delete_state)
154 cso->delete_state(cso->context, cso->data);
155 FREE(state);
156 return TRUE;
159 static boolean delete_fs_state(struct cso_context *ctx, void *state)
161 struct cso_fragment_shader *cso = (struct cso_fragment_shader *)state;
162 if (ctx->fragment_shader == cso->data)
163 return FALSE;
164 if (cso->delete_state)
165 cso->delete_state(cso->context, cso->data);
166 FREE(state);
167 return TRUE;
170 static boolean delete_vs_state(struct cso_context *ctx, void *state)
172 struct cso_vertex_shader *cso = (struct cso_vertex_shader *)state;
173 if (ctx->vertex_shader == cso->data)
174 return TRUE;
175 if (cso->delete_state)
176 cso->delete_state(cso->context, cso->data);
177 FREE(state);
178 return FALSE;
181 static boolean delete_vertex_elements(struct cso_context *ctx,
182 void *state)
184 struct cso_velements *cso = (struct cso_velements *)state;
186 if (ctx->velements == cso->data)
187 return FALSE;
189 if (cso->delete_state)
190 cso->delete_state(cso->context, cso->data);
191 FREE(state);
192 return TRUE;
196 static INLINE boolean delete_cso(struct cso_context *ctx,
197 void *state, enum cso_cache_type type)
199 switch (type) {
200 case CSO_BLEND:
201 return delete_blend_state(ctx, state);
202 break;
203 case CSO_SAMPLER:
204 return delete_sampler_state(ctx, state);
205 break;
206 case CSO_DEPTH_STENCIL_ALPHA:
207 return delete_depth_stencil_state(ctx, state);
208 break;
209 case CSO_RASTERIZER:
210 return delete_rasterizer_state(ctx, state);
211 break;
212 case CSO_FRAGMENT_SHADER:
213 return delete_fs_state(ctx, state);
214 break;
215 case CSO_VERTEX_SHADER:
216 return delete_vs_state(ctx, state);
217 break;
218 case CSO_VELEMENTS:
219 return delete_vertex_elements(ctx, state);
220 break;
221 default:
222 assert(0);
223 FREE(state);
225 return FALSE;
228 static INLINE void sanitize_hash(struct cso_hash *hash, enum cso_cache_type type,
229 int max_size, void *user_data)
231 struct cso_context *ctx = (struct cso_context *)user_data;
232 /* if we're approach the maximum size, remove fourth of the entries
233 * otherwise every subsequent call will go through the same */
234 int hash_size = cso_hash_size(hash);
235 int max_entries = (max_size > hash_size) ? max_size : hash_size;
236 int to_remove = (max_size < max_entries) * max_entries/4;
237 struct cso_hash_iter iter = cso_hash_first_node(hash);
238 if (hash_size > max_size)
239 to_remove += hash_size - max_size;
240 while (to_remove) {
241 /*remove elements until we're good */
242 /*fixme: currently we pick the nodes to remove at random*/
243 void *cso = cso_hash_iter_data(iter);
244 if (delete_cso(ctx, cso, type)) {
245 iter = cso_hash_erase(hash, iter);
246 --to_remove;
247 } else
248 iter = cso_hash_iter_next(iter);
253 struct cso_context *cso_create_context( struct pipe_context *pipe )
255 struct cso_context *ctx = CALLOC_STRUCT(cso_context);
256 if (ctx == NULL)
257 goto out;
259 assert(PIPE_MAX_SAMPLERS == PIPE_MAX_VERTEX_SAMPLERS);
261 ctx->cache = cso_cache_create();
262 if (ctx->cache == NULL)
263 goto out;
264 cso_cache_set_sanitize_callback(ctx->cache,
265 sanitize_hash,
266 ctx);
268 ctx->pipe = pipe;
270 /* Enable for testing: */
271 if (0) cso_set_maximum_cache_size( ctx->cache, 4 );
273 return ctx;
275 out:
276 cso_destroy_context( ctx );
277 return NULL;
282 * Prior to context destruction, this function unbinds all state objects.
284 void cso_release_all( struct cso_context *ctx )
286 unsigned i;
287 struct sampler_info *info;
289 if (ctx->pipe) {
290 ctx->pipe->bind_blend_state( ctx->pipe, NULL );
291 ctx->pipe->bind_rasterizer_state( ctx->pipe, NULL );
292 ctx->pipe->bind_fragment_sampler_states( ctx->pipe, 0, NULL );
293 if (ctx->pipe->bind_vertex_sampler_states)
294 ctx->pipe->bind_vertex_sampler_states(ctx->pipe, 0, NULL);
295 ctx->pipe->bind_depth_stencil_alpha_state( ctx->pipe, NULL );
296 ctx->pipe->bind_fs_state( ctx->pipe, NULL );
297 ctx->pipe->bind_vs_state( ctx->pipe, NULL );
298 ctx->pipe->bind_vertex_elements_state( ctx->pipe, NULL );
299 ctx->pipe->set_fragment_sampler_views(ctx->pipe, 0, NULL);
300 if (ctx->pipe->set_vertex_sampler_views)
301 ctx->pipe->set_vertex_sampler_views(ctx->pipe, 0, NULL);
304 /* free fragment samplers, views */
305 info = &ctx->fragment_samplers;
306 for (i = 0; i < PIPE_MAX_SAMPLERS; i++) {
307 pipe_sampler_view_reference(&info->views[i], NULL);
308 pipe_sampler_view_reference(&info->views_saved[i], NULL);
311 /* free vertex samplers, views */
312 info = &ctx->vertex_samplers;
313 for (i = 0; i < PIPE_MAX_SAMPLERS; i++) {
314 pipe_sampler_view_reference(&info->views[i], NULL);
315 pipe_sampler_view_reference(&info->views_saved[i], NULL);
318 util_unreference_framebuffer_state(&ctx->fb);
319 util_unreference_framebuffer_state(&ctx->fb_saved);
321 util_copy_vertex_buffers(ctx->vertex_buffers,
322 &ctx->nr_vertex_buffers,
323 NULL, 0);
324 util_copy_vertex_buffers(ctx->vertex_buffers_saved,
325 &ctx->nr_vertex_buffers_saved,
326 NULL, 0);
328 if (ctx->cache) {
329 cso_cache_delete( ctx->cache );
330 ctx->cache = NULL;
336 * Free the CSO context. NOTE: the state tracker should have previously called
337 * cso_release_all().
339 void cso_destroy_context( struct cso_context *ctx )
341 if (ctx) {
342 FREE( ctx );
347 /* Those function will either find the state of the given template
348 * in the cache or they will create a new state from the given
349 * template, insert it in the cache and return it.
353 * If the driver returns 0 from the create method then they will assign
354 * the data member of the cso to be the template itself.
357 enum pipe_error cso_set_blend(struct cso_context *ctx,
358 const struct pipe_blend_state *templ)
360 unsigned key_size, hash_key;
361 struct cso_hash_iter iter;
362 void *handle;
364 key_size = templ->independent_blend_enable ? sizeof(struct pipe_blend_state) :
365 (char *)&(templ->rt[1]) - (char *)templ;
366 hash_key = cso_construct_key((void*)templ, key_size);
367 iter = cso_find_state_template(ctx->cache, hash_key, CSO_BLEND, (void*)templ, key_size);
369 if (cso_hash_iter_is_null(iter)) {
370 struct cso_blend *cso = MALLOC(sizeof(struct cso_blend));
371 if (!cso)
372 return PIPE_ERROR_OUT_OF_MEMORY;
374 memset(&cso->state, 0, sizeof cso->state);
375 memcpy(&cso->state, templ, key_size);
376 cso->data = ctx->pipe->create_blend_state(ctx->pipe, &cso->state);
377 cso->delete_state = (cso_state_callback)ctx->pipe->delete_blend_state;
378 cso->context = ctx->pipe;
380 iter = cso_insert_state(ctx->cache, hash_key, CSO_BLEND, cso);
381 if (cso_hash_iter_is_null(iter)) {
382 FREE(cso);
383 return PIPE_ERROR_OUT_OF_MEMORY;
386 handle = cso->data;
388 else {
389 handle = ((struct cso_blend *)cso_hash_iter_data(iter))->data;
392 if (ctx->blend != handle) {
393 ctx->blend = handle;
394 ctx->pipe->bind_blend_state(ctx->pipe, handle);
396 return PIPE_OK;
399 void cso_save_blend(struct cso_context *ctx)
401 assert(!ctx->blend_saved);
402 ctx->blend_saved = ctx->blend;
405 void cso_restore_blend(struct cso_context *ctx)
407 if (ctx->blend != ctx->blend_saved) {
408 ctx->blend = ctx->blend_saved;
409 ctx->pipe->bind_blend_state(ctx->pipe, ctx->blend_saved);
411 ctx->blend_saved = NULL;
416 enum pipe_error cso_set_depth_stencil_alpha(struct cso_context *ctx,
417 const struct pipe_depth_stencil_alpha_state *templ)
419 unsigned key_size = sizeof(struct pipe_depth_stencil_alpha_state);
420 unsigned hash_key = cso_construct_key((void*)templ, key_size);
421 struct cso_hash_iter iter = cso_find_state_template(ctx->cache,
422 hash_key,
423 CSO_DEPTH_STENCIL_ALPHA,
424 (void*)templ, key_size);
425 void *handle;
427 if (cso_hash_iter_is_null(iter)) {
428 struct cso_depth_stencil_alpha *cso = MALLOC(sizeof(struct cso_depth_stencil_alpha));
429 if (!cso)
430 return PIPE_ERROR_OUT_OF_MEMORY;
432 memcpy(&cso->state, templ, sizeof(*templ));
433 cso->data = ctx->pipe->create_depth_stencil_alpha_state(ctx->pipe, &cso->state);
434 cso->delete_state = (cso_state_callback)ctx->pipe->delete_depth_stencil_alpha_state;
435 cso->context = ctx->pipe;
437 iter = cso_insert_state(ctx->cache, hash_key, CSO_DEPTH_STENCIL_ALPHA, cso);
438 if (cso_hash_iter_is_null(iter)) {
439 FREE(cso);
440 return PIPE_ERROR_OUT_OF_MEMORY;
443 handle = cso->data;
445 else {
446 handle = ((struct cso_depth_stencil_alpha *)cso_hash_iter_data(iter))->data;
449 if (ctx->depth_stencil != handle) {
450 ctx->depth_stencil = handle;
451 ctx->pipe->bind_depth_stencil_alpha_state(ctx->pipe, handle);
453 return PIPE_OK;
456 void cso_save_depth_stencil_alpha(struct cso_context *ctx)
458 assert(!ctx->depth_stencil_saved);
459 ctx->depth_stencil_saved = ctx->depth_stencil;
462 void cso_restore_depth_stencil_alpha(struct cso_context *ctx)
464 if (ctx->depth_stencil != ctx->depth_stencil_saved) {
465 ctx->depth_stencil = ctx->depth_stencil_saved;
466 ctx->pipe->bind_depth_stencil_alpha_state(ctx->pipe, ctx->depth_stencil_saved);
468 ctx->depth_stencil_saved = NULL;
473 enum pipe_error cso_set_rasterizer(struct cso_context *ctx,
474 const struct pipe_rasterizer_state *templ)
476 unsigned key_size = sizeof(struct pipe_rasterizer_state);
477 unsigned hash_key = cso_construct_key((void*)templ, key_size);
478 struct cso_hash_iter iter = cso_find_state_template(ctx->cache,
479 hash_key, CSO_RASTERIZER,
480 (void*)templ, key_size);
481 void *handle = NULL;
483 if (cso_hash_iter_is_null(iter)) {
484 struct cso_rasterizer *cso = MALLOC(sizeof(struct cso_rasterizer));
485 if (!cso)
486 return PIPE_ERROR_OUT_OF_MEMORY;
488 memcpy(&cso->state, templ, sizeof(*templ));
489 cso->data = ctx->pipe->create_rasterizer_state(ctx->pipe, &cso->state);
490 cso->delete_state = (cso_state_callback)ctx->pipe->delete_rasterizer_state;
491 cso->context = ctx->pipe;
493 iter = cso_insert_state(ctx->cache, hash_key, CSO_RASTERIZER, cso);
494 if (cso_hash_iter_is_null(iter)) {
495 FREE(cso);
496 return PIPE_ERROR_OUT_OF_MEMORY;
499 handle = cso->data;
501 else {
502 handle = ((struct cso_rasterizer *)cso_hash_iter_data(iter))->data;
505 if (ctx->rasterizer != handle) {
506 ctx->rasterizer = handle;
507 ctx->pipe->bind_rasterizer_state(ctx->pipe, handle);
509 return PIPE_OK;
512 void cso_save_rasterizer(struct cso_context *ctx)
514 assert(!ctx->rasterizer_saved);
515 ctx->rasterizer_saved = ctx->rasterizer;
518 void cso_restore_rasterizer(struct cso_context *ctx)
520 if (ctx->rasterizer != ctx->rasterizer_saved) {
521 ctx->rasterizer = ctx->rasterizer_saved;
522 ctx->pipe->bind_rasterizer_state(ctx->pipe, ctx->rasterizer_saved);
524 ctx->rasterizer_saved = NULL;
529 enum pipe_error cso_set_fragment_shader_handle(struct cso_context *ctx,
530 void *handle )
532 if (ctx->fragment_shader != handle) {
533 ctx->fragment_shader = handle;
534 ctx->pipe->bind_fs_state(ctx->pipe, handle);
536 return PIPE_OK;
539 void cso_delete_fragment_shader(struct cso_context *ctx, void *handle )
541 if (handle == ctx->fragment_shader) {
542 /* unbind before deleting */
543 ctx->pipe->bind_fs_state(ctx->pipe, NULL);
544 ctx->fragment_shader = NULL;
546 ctx->pipe->delete_fs_state(ctx->pipe, handle);
549 /* Not really working:
551 #if 0
552 enum pipe_error cso_set_fragment_shader(struct cso_context *ctx,
553 const struct pipe_shader_state *templ)
555 const struct tgsi_token *tokens = templ->tokens;
556 unsigned num_tokens = tgsi_num_tokens(tokens);
557 size_t tokens_size = num_tokens*sizeof(struct tgsi_token);
558 unsigned hash_key = cso_construct_key((void*)tokens, tokens_size);
559 struct cso_hash_iter iter = cso_find_state_template(ctx->cache,
560 hash_key,
561 CSO_FRAGMENT_SHADER,
562 (void*)tokens,
563 sizeof(*templ)); /* XXX correct? tokens_size? */
564 void *handle = NULL;
566 if (cso_hash_iter_is_null(iter)) {
567 struct cso_fragment_shader *cso = MALLOC(sizeof(struct cso_fragment_shader) + tokens_size);
568 struct tgsi_token *cso_tokens = (struct tgsi_token *)((char *)cso + sizeof(*cso));
570 if (!cso)
571 return PIPE_ERROR_OUT_OF_MEMORY;
573 memcpy(cso_tokens, tokens, tokens_size);
574 cso->state.tokens = cso_tokens;
575 cso->data = ctx->pipe->create_fs_state(ctx->pipe, &cso->state);
576 cso->delete_state = (cso_state_callback)ctx->pipe->delete_fs_state;
577 cso->context = ctx->pipe;
579 iter = cso_insert_state(ctx->cache, hash_key, CSO_FRAGMENT_SHADER, cso);
580 if (cso_hash_iter_is_null(iter)) {
581 FREE(cso);
582 return PIPE_ERROR_OUT_OF_MEMORY;
585 handle = cso->data;
587 else {
588 handle = ((struct cso_fragment_shader *)cso_hash_iter_data(iter))->data;
591 return cso_set_fragment_shader_handle( ctx, handle );
593 #endif
595 void cso_save_fragment_shader(struct cso_context *ctx)
597 assert(!ctx->fragment_shader_saved);
598 ctx->fragment_shader_saved = ctx->fragment_shader;
601 void cso_restore_fragment_shader(struct cso_context *ctx)
603 if (ctx->fragment_shader_saved != ctx->fragment_shader) {
604 ctx->pipe->bind_fs_state(ctx->pipe, ctx->fragment_shader_saved);
605 ctx->fragment_shader = ctx->fragment_shader_saved;
607 ctx->fragment_shader_saved = NULL;
611 enum pipe_error cso_set_vertex_shader_handle(struct cso_context *ctx,
612 void *handle )
614 if (ctx->vertex_shader != handle) {
615 ctx->vertex_shader = handle;
616 ctx->pipe->bind_vs_state(ctx->pipe, handle);
618 return PIPE_OK;
621 void cso_delete_vertex_shader(struct cso_context *ctx, void *handle )
623 if (handle == ctx->vertex_shader) {
624 /* unbind before deleting */
625 ctx->pipe->bind_vs_state(ctx->pipe, NULL);
626 ctx->vertex_shader = NULL;
628 ctx->pipe->delete_vs_state(ctx->pipe, handle);
632 /* Not really working:
634 #if 0
635 enum pipe_error cso_set_vertex_shader(struct cso_context *ctx,
636 const struct pipe_shader_state *templ)
638 unsigned hash_key = cso_construct_key((void*)templ,
639 sizeof(struct pipe_shader_state));
640 struct cso_hash_iter iter = cso_find_state_template(ctx->cache,
641 hash_key, CSO_VERTEX_SHADER,
642 (void*)templ,
643 sizeof(*templ));
644 void *handle = NULL;
646 if (cso_hash_iter_is_null(iter)) {
647 struct cso_vertex_shader *cso = MALLOC(sizeof(struct cso_vertex_shader));
649 if (!cso)
650 return PIPE_ERROR_OUT_OF_MEMORY;
652 memcpy(cso->state, templ, sizeof(*templ));
653 cso->data = ctx->pipe->create_vs_state(ctx->pipe, &cso->state);
654 cso->delete_state = (cso_state_callback)ctx->pipe->delete_vs_state;
655 cso->context = ctx->pipe;
657 iter = cso_insert_state(ctx->cache, hash_key, CSO_VERTEX_SHADER, cso);
658 if (cso_hash_iter_is_null(iter)) {
659 FREE(cso);
660 return PIPE_ERROR_OUT_OF_MEMORY;
663 handle = cso->data;
665 else {
666 handle = ((struct cso_vertex_shader *)cso_hash_iter_data(iter))->data;
669 return cso_set_vertex_shader_handle( ctx, handle );
671 #endif
675 void cso_save_vertex_shader(struct cso_context *ctx)
677 assert(!ctx->vertex_shader_saved);
678 ctx->vertex_shader_saved = ctx->vertex_shader;
681 void cso_restore_vertex_shader(struct cso_context *ctx)
683 if (ctx->vertex_shader_saved != ctx->vertex_shader) {
684 ctx->pipe->bind_vs_state(ctx->pipe, ctx->vertex_shader_saved);
685 ctx->vertex_shader = ctx->vertex_shader_saved;
687 ctx->vertex_shader_saved = NULL;
691 enum pipe_error cso_set_framebuffer(struct cso_context *ctx,
692 const struct pipe_framebuffer_state *fb)
694 if (memcmp(&ctx->fb, fb, sizeof(*fb)) != 0) {
695 util_copy_framebuffer_state(&ctx->fb, fb);
696 ctx->pipe->set_framebuffer_state(ctx->pipe, fb);
698 return PIPE_OK;
701 void cso_save_framebuffer(struct cso_context *ctx)
703 util_copy_framebuffer_state(&ctx->fb_saved, &ctx->fb);
706 void cso_restore_framebuffer(struct cso_context *ctx)
708 if (memcmp(&ctx->fb, &ctx->fb_saved, sizeof(ctx->fb))) {
709 util_copy_framebuffer_state(&ctx->fb, &ctx->fb_saved);
710 ctx->pipe->set_framebuffer_state(ctx->pipe, &ctx->fb);
711 util_unreference_framebuffer_state(&ctx->fb_saved);
716 enum pipe_error cso_set_viewport(struct cso_context *ctx,
717 const struct pipe_viewport_state *vp)
719 if (memcmp(&ctx->vp, vp, sizeof(*vp))) {
720 ctx->vp = *vp;
721 ctx->pipe->set_viewport_state(ctx->pipe, vp);
723 return PIPE_OK;
726 void cso_save_viewport(struct cso_context *ctx)
728 ctx->vp_saved = ctx->vp;
732 void cso_restore_viewport(struct cso_context *ctx)
734 if (memcmp(&ctx->vp, &ctx->vp_saved, sizeof(ctx->vp))) {
735 ctx->vp = ctx->vp_saved;
736 ctx->pipe->set_viewport_state(ctx->pipe, &ctx->vp);
741 enum pipe_error cso_set_blend_color(struct cso_context *ctx,
742 const struct pipe_blend_color *bc)
744 if (memcmp(&ctx->blend_color, bc, sizeof(ctx->blend_color))) {
745 ctx->blend_color = *bc;
746 ctx->pipe->set_blend_color(ctx->pipe, bc);
748 return PIPE_OK;
751 enum pipe_error cso_set_sample_mask(struct cso_context *ctx,
752 unsigned sample_mask)
754 if (ctx->sample_mask != sample_mask) {
755 ctx->sample_mask = sample_mask;
756 ctx->pipe->set_sample_mask(ctx->pipe, sample_mask);
758 return PIPE_OK;
761 enum pipe_error cso_set_stencil_ref(struct cso_context *ctx,
762 const struct pipe_stencil_ref *sr)
764 if (memcmp(&ctx->stencil_ref, sr, sizeof(ctx->stencil_ref))) {
765 ctx->stencil_ref = *sr;
766 ctx->pipe->set_stencil_ref(ctx->pipe, sr);
768 return PIPE_OK;
771 void cso_save_stencil_ref(struct cso_context *ctx)
773 ctx->stencil_ref_saved = ctx->stencil_ref;
777 void cso_restore_stencil_ref(struct cso_context *ctx)
779 if (memcmp(&ctx->stencil_ref, &ctx->stencil_ref_saved, sizeof(ctx->stencil_ref))) {
780 ctx->stencil_ref = ctx->stencil_ref_saved;
781 ctx->pipe->set_stencil_ref(ctx->pipe, &ctx->stencil_ref);
785 enum pipe_error cso_set_geometry_shader_handle(struct cso_context *ctx,
786 void *handle)
788 if (ctx->geometry_shader != handle) {
789 ctx->geometry_shader = handle;
790 ctx->pipe->bind_gs_state(ctx->pipe, handle);
792 return PIPE_OK;
795 void cso_delete_geometry_shader(struct cso_context *ctx, void *handle)
797 if (handle == ctx->geometry_shader) {
798 /* unbind before deleting */
799 ctx->pipe->bind_gs_state(ctx->pipe, NULL);
800 ctx->geometry_shader = NULL;
802 ctx->pipe->delete_gs_state(ctx->pipe, handle);
805 void cso_save_geometry_shader(struct cso_context *ctx)
807 assert(!ctx->geometry_shader_saved);
808 ctx->geometry_shader_saved = ctx->geometry_shader;
811 void cso_restore_geometry_shader(struct cso_context *ctx)
813 if (ctx->geometry_shader_saved != ctx->geometry_shader) {
814 ctx->pipe->bind_gs_state(ctx->pipe, ctx->geometry_shader_saved);
815 ctx->geometry_shader = ctx->geometry_shader_saved;
817 ctx->geometry_shader_saved = NULL;
820 /* clip state */
822 static INLINE void
823 clip_state_cpy(struct pipe_clip_state *dst,
824 const struct pipe_clip_state *src)
826 dst->depth_clamp = src->depth_clamp;
827 dst->nr = src->nr;
828 if (src->nr) {
829 memcpy(dst->ucp, src->ucp, src->nr * sizeof(src->ucp[0]));
833 static INLINE int
834 clip_state_cmp(const struct pipe_clip_state *a,
835 const struct pipe_clip_state *b)
837 if (a->depth_clamp != b->depth_clamp) {
838 return 1;
840 if (a->nr != b->nr) {
841 return 1;
843 if (a->nr) {
844 return memcmp(a->ucp, b->ucp, a->nr * sizeof(a->ucp[0]));
846 return 0;
849 void
850 cso_set_clip(struct cso_context *ctx,
851 const struct pipe_clip_state *clip)
853 if (clip_state_cmp(&ctx->clip, clip)) {
854 clip_state_cpy(&ctx->clip, clip);
855 ctx->pipe->set_clip_state(ctx->pipe, clip);
859 void
860 cso_save_clip(struct cso_context *ctx)
862 clip_state_cpy(&ctx->clip_saved, &ctx->clip);
865 void
866 cso_restore_clip(struct cso_context *ctx)
868 if (clip_state_cmp(&ctx->clip, &ctx->clip_saved)) {
869 clip_state_cpy(&ctx->clip, &ctx->clip_saved);
870 ctx->pipe->set_clip_state(ctx->pipe, &ctx->clip_saved);
874 enum pipe_error cso_set_vertex_elements(struct cso_context *ctx,
875 unsigned count,
876 const struct pipe_vertex_element *states)
878 unsigned key_size, hash_key;
879 struct cso_hash_iter iter;
880 void *handle;
881 struct cso_velems_state velems_state;
883 /* need to include the count into the stored state data too.
884 Otherwise first few count pipe_vertex_elements could be identical even if count
885 is different, and there's no guarantee the hash would be different in that
886 case neither */
887 key_size = sizeof(struct pipe_vertex_element) * count + sizeof(unsigned);
888 velems_state.count = count;
889 memcpy(velems_state.velems, states, sizeof(struct pipe_vertex_element) * count);
890 hash_key = cso_construct_key((void*)&velems_state, key_size);
891 iter = cso_find_state_template(ctx->cache, hash_key, CSO_VELEMENTS, (void*)&velems_state, key_size);
893 if (cso_hash_iter_is_null(iter)) {
894 struct cso_velements *cso = MALLOC(sizeof(struct cso_velements));
895 if (!cso)
896 return PIPE_ERROR_OUT_OF_MEMORY;
898 memcpy(&cso->state, &velems_state, key_size);
899 cso->data = ctx->pipe->create_vertex_elements_state(ctx->pipe, count, &cso->state.velems[0]);
900 cso->delete_state = (cso_state_callback)ctx->pipe->delete_vertex_elements_state;
901 cso->context = ctx->pipe;
903 iter = cso_insert_state(ctx->cache, hash_key, CSO_VELEMENTS, cso);
904 if (cso_hash_iter_is_null(iter)) {
905 FREE(cso);
906 return PIPE_ERROR_OUT_OF_MEMORY;
909 handle = cso->data;
911 else {
912 handle = ((struct cso_velements *)cso_hash_iter_data(iter))->data;
915 if (ctx->velements != handle) {
916 ctx->velements = handle;
917 ctx->pipe->bind_vertex_elements_state(ctx->pipe, handle);
919 return PIPE_OK;
922 void cso_save_vertex_elements(struct cso_context *ctx)
924 assert(!ctx->velements_saved);
925 ctx->velements_saved = ctx->velements;
928 void cso_restore_vertex_elements(struct cso_context *ctx)
930 if (ctx->velements != ctx->velements_saved) {
931 ctx->velements = ctx->velements_saved;
932 ctx->pipe->bind_vertex_elements_state(ctx->pipe, ctx->velements_saved);
934 ctx->velements_saved = NULL;
937 /* vertex buffers */
939 void cso_set_vertex_buffers(struct cso_context *ctx,
940 unsigned count,
941 const struct pipe_vertex_buffer *buffers)
943 if (count != ctx->nr_vertex_buffers ||
944 memcmp(buffers, ctx->vertex_buffers,
945 sizeof(struct pipe_vertex_buffer) * count) != 0) {
946 util_copy_vertex_buffers(ctx->vertex_buffers, &ctx->nr_vertex_buffers,
947 buffers, count);
948 ctx->pipe->set_vertex_buffers(ctx->pipe, count, buffers);
952 void cso_save_vertex_buffers(struct cso_context *ctx)
954 util_copy_vertex_buffers(ctx->vertex_buffers_saved,
955 &ctx->nr_vertex_buffers_saved,
956 ctx->vertex_buffers,
957 ctx->nr_vertex_buffers);
960 void cso_restore_vertex_buffers(struct cso_context *ctx)
962 util_copy_vertex_buffers(ctx->vertex_buffers,
963 &ctx->nr_vertex_buffers,
964 ctx->vertex_buffers_saved,
965 ctx->nr_vertex_buffers_saved);
966 ctx->pipe->set_vertex_buffers(ctx->pipe, ctx->nr_vertex_buffers,
967 ctx->vertex_buffers);
971 /**************** fragment/vertex sampler view state *************************/
973 static enum pipe_error
974 single_sampler(struct cso_context *ctx,
975 struct sampler_info *info,
976 unsigned idx,
977 const struct pipe_sampler_state *templ)
979 void *handle = NULL;
981 if (templ != NULL) {
982 unsigned key_size = sizeof(struct pipe_sampler_state);
983 unsigned hash_key = cso_construct_key((void*)templ, key_size);
984 struct cso_hash_iter iter =
985 cso_find_state_template(ctx->cache,
986 hash_key, CSO_SAMPLER,
987 (void *) templ, key_size);
989 if (cso_hash_iter_is_null(iter)) {
990 struct cso_sampler *cso = MALLOC(sizeof(struct cso_sampler));
991 if (!cso)
992 return PIPE_ERROR_OUT_OF_MEMORY;
994 memcpy(&cso->state, templ, sizeof(*templ));
995 cso->data = ctx->pipe->create_sampler_state(ctx->pipe, &cso->state);
996 cso->delete_state = (cso_state_callback)ctx->pipe->delete_sampler_state;
997 cso->context = ctx->pipe;
999 iter = cso_insert_state(ctx->cache, hash_key, CSO_SAMPLER, cso);
1000 if (cso_hash_iter_is_null(iter)) {
1001 FREE(cso);
1002 return PIPE_ERROR_OUT_OF_MEMORY;
1005 handle = cso->data;
1007 else {
1008 handle = ((struct cso_sampler *)cso_hash_iter_data(iter))->data;
1012 info->samplers[idx] = handle;
1014 return PIPE_OK;
1017 enum pipe_error
1018 cso_single_sampler(struct cso_context *ctx,
1019 unsigned idx,
1020 const struct pipe_sampler_state *templ)
1022 return single_sampler(ctx, &ctx->fragment_samplers, idx, templ);
1025 enum pipe_error
1026 cso_single_vertex_sampler(struct cso_context *ctx,
1027 unsigned idx,
1028 const struct pipe_sampler_state *templ)
1030 return single_sampler(ctx, &ctx->vertex_samplers, idx, templ);
1035 static void
1036 single_sampler_done(struct cso_context *ctx,
1037 struct sampler_info *info)
1039 unsigned i;
1041 /* find highest non-null sampler */
1042 for (i = PIPE_MAX_SAMPLERS; i > 0; i--) {
1043 if (info->samplers[i - 1] != NULL)
1044 break;
1047 info->nr_samplers = i;
1049 if (info->hw.nr_samplers != info->nr_samplers ||
1050 memcmp(info->hw.samplers,
1051 info->samplers,
1052 info->nr_samplers * sizeof(void *)) != 0)
1054 memcpy(info->hw.samplers,
1055 info->samplers,
1056 info->nr_samplers * sizeof(void *));
1057 info->hw.nr_samplers = info->nr_samplers;
1059 if (info == &ctx->fragment_samplers) {
1060 ctx->pipe->bind_fragment_sampler_states(ctx->pipe,
1061 info->nr_samplers,
1062 info->samplers);
1064 else if (info == &ctx->vertex_samplers) {
1065 ctx->pipe->bind_vertex_sampler_states(ctx->pipe,
1066 info->nr_samplers,
1067 info->samplers);
1069 else {
1070 assert(0);
1075 void
1076 cso_single_sampler_done( struct cso_context *ctx )
1078 single_sampler_done(ctx, &ctx->fragment_samplers);
1081 void
1082 cso_single_vertex_sampler_done(struct cso_context *ctx)
1084 single_sampler_done(ctx, &ctx->vertex_samplers);
1089 * If the function encouters any errors it will return the
1090 * last one. Done to always try to set as many samplers
1091 * as possible.
1093 static enum pipe_error
1094 set_samplers(struct cso_context *ctx,
1095 struct sampler_info *info,
1096 unsigned nr,
1097 const struct pipe_sampler_state **templates)
1099 unsigned i;
1100 enum pipe_error temp, error = PIPE_OK;
1102 /* TODO: fastpath
1105 for (i = 0; i < nr; i++) {
1106 temp = single_sampler(ctx, info, i, templates[i]);
1107 if (temp != PIPE_OK)
1108 error = temp;
1111 for ( ; i < info->nr_samplers; i++) {
1112 temp = single_sampler(ctx, info, i, NULL);
1113 if (temp != PIPE_OK)
1114 error = temp;
1117 single_sampler_done(ctx, info);
1119 return error;
1122 enum pipe_error
1123 cso_set_samplers(struct cso_context *ctx,
1124 unsigned nr,
1125 const struct pipe_sampler_state **templates)
1127 return set_samplers(ctx, &ctx->fragment_samplers, nr, templates);
1130 enum pipe_error
1131 cso_set_vertex_samplers(struct cso_context *ctx,
1132 unsigned nr,
1133 const struct pipe_sampler_state **templates)
1135 return set_samplers(ctx, &ctx->vertex_samplers, nr, templates);
1140 static void
1141 save_samplers(struct cso_context *ctx, struct sampler_info *info)
1143 info->nr_samplers_saved = info->nr_samplers;
1144 memcpy(info->samplers_saved, info->samplers, sizeof(info->samplers));
1147 void
1148 cso_save_samplers(struct cso_context *ctx)
1150 save_samplers(ctx, &ctx->fragment_samplers);
1153 void
1154 cso_save_vertex_samplers(struct cso_context *ctx)
1156 save_samplers(ctx, &ctx->vertex_samplers);
1161 static void
1162 restore_samplers(struct cso_context *ctx, struct sampler_info *info)
1164 info->nr_samplers = info->nr_samplers_saved;
1165 memcpy(info->samplers, info->samplers_saved, sizeof(info->samplers));
1166 single_sampler_done(ctx, info);
1169 void
1170 cso_restore_samplers(struct cso_context *ctx)
1172 restore_samplers(ctx, &ctx->fragment_samplers);
1175 void
1176 cso_restore_vertex_samplers(struct cso_context *ctx)
1178 restore_samplers(ctx, &ctx->vertex_samplers);
1183 static void
1184 set_sampler_views(struct cso_context *ctx,
1185 struct sampler_info *info,
1186 void (*set_views)(struct pipe_context *,
1187 unsigned num_views,
1188 struct pipe_sampler_view **),
1189 uint count,
1190 struct pipe_sampler_view **views)
1192 uint i;
1194 /* reference new views */
1195 for (i = 0; i < count; i++) {
1196 pipe_sampler_view_reference(&info->views[i], views[i]);
1198 /* unref extra old views, if any */
1199 for (; i < info->nr_views; i++) {
1200 pipe_sampler_view_reference(&info->views[i], NULL);
1203 info->nr_views = count;
1205 /* bind the new sampler views */
1206 set_views(ctx->pipe, count, info->views);
1209 void
1210 cso_set_fragment_sampler_views(struct cso_context *ctx,
1211 uint count,
1212 struct pipe_sampler_view **views)
1214 set_sampler_views(ctx, &ctx->fragment_samplers,
1215 ctx->pipe->set_fragment_sampler_views,
1216 count, views);
1219 void
1220 cso_set_vertex_sampler_views(struct cso_context *ctx,
1221 uint count,
1222 struct pipe_sampler_view **views)
1224 set_sampler_views(ctx, &ctx->vertex_samplers,
1225 ctx->pipe->set_vertex_sampler_views,
1226 count, views);
1231 static void
1232 save_sampler_views(struct cso_context *ctx,
1233 struct sampler_info *info)
1235 uint i;
1237 info->nr_views_saved = info->nr_views;
1239 for (i = 0; i < info->nr_views; i++) {
1240 assert(!info->views_saved[i]);
1241 pipe_sampler_view_reference(&info->views_saved[i], info->views[i]);
1245 void
1246 cso_save_fragment_sampler_views(struct cso_context *ctx)
1248 save_sampler_views(ctx, &ctx->fragment_samplers);
1251 void
1252 cso_save_vertex_sampler_views(struct cso_context *ctx)
1254 save_sampler_views(ctx, &ctx->vertex_samplers);
1258 static void
1259 restore_sampler_views(struct cso_context *ctx,
1260 struct sampler_info *info,
1261 void (*set_views)(struct pipe_context *,
1262 unsigned num_views,
1263 struct pipe_sampler_view **))
1265 uint i;
1267 for (i = 0; i < info->nr_views_saved; i++) {
1268 pipe_sampler_view_reference(&info->views[i], info->views_saved[i]);
1269 pipe_sampler_view_reference(&info->views_saved[i], NULL);
1271 for (; i < info->nr_views; i++) {
1272 pipe_sampler_view_reference(&info->views[i], NULL);
1275 /* bind the old/saved sampler views */
1276 set_views(ctx->pipe, info->nr_views_saved, info->views);
1278 info->nr_views = info->nr_views_saved;
1279 info->nr_views_saved = 0;
1282 void
1283 cso_restore_fragment_sampler_views(struct cso_context *ctx)
1285 restore_sampler_views(ctx, &ctx->fragment_samplers,
1286 ctx->pipe->set_fragment_sampler_views);
1289 void
1290 cso_restore_vertex_sampler_views(struct cso_context *ctx)
1292 restore_sampler_views(ctx, &ctx->vertex_samplers,
1293 ctx->pipe->set_vertex_sampler_views);