gallium: always save and restore vertex buffers using cso_cache
[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 uint nr_vertex_buffers;
85 struct pipe_vertex_buffer vertex_buffers[PIPE_MAX_ATTRIBS];
86
87 uint nr_vertex_buffers_saved;
88 struct pipe_vertex_buffer vertex_buffers_saved[PIPE_MAX_ATTRIBS];
89
90 /** Current and saved state.
91 * The saved state is used as a 1-deep stack.
92 */
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;
99
100 struct pipe_clip_state clip;
101 struct pipe_clip_state clip_saved;
102
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;
108 };
109
110
111 static boolean delete_blend_state(struct cso_context *ctx, void *state)
112 {
113 struct cso_blend *cso = (struct cso_blend *)state;
114
115 if (ctx->blend == cso->data)
116 return FALSE;
117
118 if (cso->delete_state)
119 cso->delete_state(cso->context, cso->data);
120 FREE(state);
121 return TRUE;
122 }
123
124 static boolean delete_depth_stencil_state(struct cso_context *ctx, void *state)
125 {
126 struct cso_depth_stencil_alpha *cso = (struct cso_depth_stencil_alpha *)state;
127
128 if (ctx->depth_stencil == cso->data)
129 return FALSE;
130
131 if (cso->delete_state)
132 cso->delete_state(cso->context, cso->data);
133 FREE(state);
134
135 return TRUE;
136 }
137
138 static boolean delete_sampler_state(struct cso_context *ctx, void *state)
139 {
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;
145 }
146
147 static boolean delete_rasterizer_state(struct cso_context *ctx, void *state)
148 {
149 struct cso_rasterizer *cso = (struct cso_rasterizer *)state;
150
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;
157 }
158
159 static boolean delete_fs_state(struct cso_context *ctx, void *state)
160 {
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;
168 }
169
170 static boolean delete_vs_state(struct cso_context *ctx, void *state)
171 {
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;
179 }
180
181 static boolean delete_vertex_elements(struct cso_context *ctx,
182 void *state)
183 {
184 struct cso_velements *cso = (struct cso_velements *)state;
185
186 if (ctx->velements == cso->data)
187 return FALSE;
188
189 if (cso->delete_state)
190 cso->delete_state(cso->context, cso->data);
191 FREE(state);
192 return TRUE;
193 }
194
195
196 static INLINE boolean delete_cso(struct cso_context *ctx,
197 void *state, enum cso_cache_type type)
198 {
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);
224 }
225 return FALSE;
226 }
227
228 static INLINE void sanitize_hash(struct cso_hash *hash, enum cso_cache_type type,
229 int max_size, void *user_data)
230 {
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);
249 }
250 }
251
252
253 struct cso_context *cso_create_context( struct pipe_context *pipe )
254 {
255 struct cso_context *ctx = CALLOC_STRUCT(cso_context);
256 if (ctx == NULL)
257 goto out;
258
259 assert(PIPE_MAX_SAMPLERS == PIPE_MAX_VERTEX_SAMPLERS);
260
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);
267
268 ctx->pipe = pipe;
269
270 /* Enable for testing: */
271 if (0) cso_set_maximum_cache_size( ctx->cache, 4 );
272
273 return ctx;
274
275 out:
276 cso_destroy_context( ctx );
277 return NULL;
278 }
279
280
281 /**
282 * Prior to context destruction, this function unbinds all state objects.
283 */
284 void cso_release_all( struct cso_context *ctx )
285 {
286 unsigned i;
287 struct sampler_info *info;
288
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);
302 }
303
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);
309 }
310
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);
316 }
317
318 util_unreference_framebuffer_state(&ctx->fb);
319 util_unreference_framebuffer_state(&ctx->fb_saved);
320
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);
327
328 if (ctx->cache) {
329 cso_cache_delete( ctx->cache );
330 ctx->cache = NULL;
331 }
332 }
333
334
335 /**
336 * Free the CSO context. NOTE: the state tracker should have previously called
337 * cso_release_all().
338 */
339 void cso_destroy_context( struct cso_context *ctx )
340 {
341 if (ctx) {
342 FREE( ctx );
343 }
344 }
345
346
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.
350 */
351
352 /*
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.
355 */
356
357 enum pipe_error cso_set_blend(struct cso_context *ctx,
358 const struct pipe_blend_state *templ)
359 {
360 unsigned key_size, hash_key;
361 struct cso_hash_iter iter;
362 void *handle;
363
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);
368
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;
373
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;
379
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;
384 }
385
386 handle = cso->data;
387 }
388 else {
389 handle = ((struct cso_blend *)cso_hash_iter_data(iter))->data;
390 }
391
392 if (ctx->blend != handle) {
393 ctx->blend = handle;
394 ctx->pipe->bind_blend_state(ctx->pipe, handle);
395 }
396 return PIPE_OK;
397 }
398
399 void cso_save_blend(struct cso_context *ctx)
400 {
401 assert(!ctx->blend_saved);
402 ctx->blend_saved = ctx->blend;
403 }
404
405 void cso_restore_blend(struct cso_context *ctx)
406 {
407 if (ctx->blend != ctx->blend_saved) {
408 ctx->blend = ctx->blend_saved;
409 ctx->pipe->bind_blend_state(ctx->pipe, ctx->blend_saved);
410 }
411 ctx->blend_saved = NULL;
412 }
413
414
415
416 enum pipe_error cso_set_depth_stencil_alpha(struct cso_context *ctx,
417 const struct pipe_depth_stencil_alpha_state *templ)
418 {
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;
426
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;
431
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;
436
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;
441 }
442
443 handle = cso->data;
444 }
445 else {
446 handle = ((struct cso_depth_stencil_alpha *)cso_hash_iter_data(iter))->data;
447 }
448
449 if (ctx->depth_stencil != handle) {
450 ctx->depth_stencil = handle;
451 ctx->pipe->bind_depth_stencil_alpha_state(ctx->pipe, handle);
452 }
453 return PIPE_OK;
454 }
455
456 void cso_save_depth_stencil_alpha(struct cso_context *ctx)
457 {
458 assert(!ctx->depth_stencil_saved);
459 ctx->depth_stencil_saved = ctx->depth_stencil;
460 }
461
462 void cso_restore_depth_stencil_alpha(struct cso_context *ctx)
463 {
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);
467 }
468 ctx->depth_stencil_saved = NULL;
469 }
470
471
472
473 enum pipe_error cso_set_rasterizer(struct cso_context *ctx,
474 const struct pipe_rasterizer_state *templ)
475 {
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;
482
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;
487
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;
492
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;
497 }
498
499 handle = cso->data;
500 }
501 else {
502 handle = ((struct cso_rasterizer *)cso_hash_iter_data(iter))->data;
503 }
504
505 if (ctx->rasterizer != handle) {
506 ctx->rasterizer = handle;
507 ctx->pipe->bind_rasterizer_state(ctx->pipe, handle);
508 }
509 return PIPE_OK;
510 }
511
512 void cso_save_rasterizer(struct cso_context *ctx)
513 {
514 assert(!ctx->rasterizer_saved);
515 ctx->rasterizer_saved = ctx->rasterizer;
516 }
517
518 void cso_restore_rasterizer(struct cso_context *ctx)
519 {
520 if (ctx->rasterizer != ctx->rasterizer_saved) {
521 ctx->rasterizer = ctx->rasterizer_saved;
522 ctx->pipe->bind_rasterizer_state(ctx->pipe, ctx->rasterizer_saved);
523 }
524 ctx->rasterizer_saved = NULL;
525 }
526
527
528
529 enum pipe_error cso_set_fragment_shader_handle(struct cso_context *ctx,
530 void *handle )
531 {
532 if (ctx->fragment_shader != handle) {
533 ctx->fragment_shader = handle;
534 ctx->pipe->bind_fs_state(ctx->pipe, handle);
535 }
536 return PIPE_OK;
537 }
538
539 void cso_delete_fragment_shader(struct cso_context *ctx, void *handle )
540 {
541 if (handle == ctx->fragment_shader) {
542 /* unbind before deleting */
543 ctx->pipe->bind_fs_state(ctx->pipe, NULL);
544 ctx->fragment_shader = NULL;
545 }
546 ctx->pipe->delete_fs_state(ctx->pipe, handle);
547 }
548
549 /* Not really working:
550 */
551 #if 0
552 enum pipe_error cso_set_fragment_shader(struct cso_context *ctx,
553 const struct pipe_shader_state *templ)
554 {
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;
565
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));
569
570 if (!cso)
571 return PIPE_ERROR_OUT_OF_MEMORY;
572
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;
578
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;
583 }
584
585 handle = cso->data;
586 }
587 else {
588 handle = ((struct cso_fragment_shader *)cso_hash_iter_data(iter))->data;
589 }
590
591 return cso_set_fragment_shader_handle( ctx, handle );
592 }
593 #endif
594
595 void cso_save_fragment_shader(struct cso_context *ctx)
596 {
597 assert(!ctx->fragment_shader_saved);
598 ctx->fragment_shader_saved = ctx->fragment_shader;
599 }
600
601 void cso_restore_fragment_shader(struct cso_context *ctx)
602 {
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;
606 }
607 ctx->fragment_shader_saved = NULL;
608 }
609
610
611 enum pipe_error cso_set_vertex_shader_handle(struct cso_context *ctx,
612 void *handle )
613 {
614 if (ctx->vertex_shader != handle) {
615 ctx->vertex_shader = handle;
616 ctx->pipe->bind_vs_state(ctx->pipe, handle);
617 }
618 return PIPE_OK;
619 }
620
621 void cso_delete_vertex_shader(struct cso_context *ctx, void *handle )
622 {
623 if (handle == ctx->vertex_shader) {
624 /* unbind before deleting */
625 ctx->pipe->bind_vs_state(ctx->pipe, NULL);
626 ctx->vertex_shader = NULL;
627 }
628 ctx->pipe->delete_vs_state(ctx->pipe, handle);
629 }
630
631
632 /* Not really working:
633 */
634 #if 0
635 enum pipe_error cso_set_vertex_shader(struct cso_context *ctx,
636 const struct pipe_shader_state *templ)
637 {
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;
645
646 if (cso_hash_iter_is_null(iter)) {
647 struct cso_vertex_shader *cso = MALLOC(sizeof(struct cso_vertex_shader));
648
649 if (!cso)
650 return PIPE_ERROR_OUT_OF_MEMORY;
651
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;
656
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;
661 }
662
663 handle = cso->data;
664 }
665 else {
666 handle = ((struct cso_vertex_shader *)cso_hash_iter_data(iter))->data;
667 }
668
669 return cso_set_vertex_shader_handle( ctx, handle );
670 }
671 #endif
672
673
674
675 void cso_save_vertex_shader(struct cso_context *ctx)
676 {
677 assert(!ctx->vertex_shader_saved);
678 ctx->vertex_shader_saved = ctx->vertex_shader;
679 }
680
681 void cso_restore_vertex_shader(struct cso_context *ctx)
682 {
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;
686 }
687 ctx->vertex_shader_saved = NULL;
688 }
689
690
691 enum pipe_error cso_set_framebuffer(struct cso_context *ctx,
692 const struct pipe_framebuffer_state *fb)
693 {
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);
697 }
698 return PIPE_OK;
699 }
700
701 void cso_save_framebuffer(struct cso_context *ctx)
702 {
703 util_copy_framebuffer_state(&ctx->fb_saved, &ctx->fb);
704 }
705
706 void cso_restore_framebuffer(struct cso_context *ctx)
707 {
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);
712 }
713 }
714
715
716 enum pipe_error cso_set_viewport(struct cso_context *ctx,
717 const struct pipe_viewport_state *vp)
718 {
719 if (memcmp(&ctx->vp, vp, sizeof(*vp))) {
720 ctx->vp = *vp;
721 ctx->pipe->set_viewport_state(ctx->pipe, vp);
722 }
723 return PIPE_OK;
724 }
725
726 void cso_save_viewport(struct cso_context *ctx)
727 {
728 ctx->vp_saved = ctx->vp;
729 }
730
731
732 void cso_restore_viewport(struct cso_context *ctx)
733 {
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);
737 }
738 }
739
740
741 enum pipe_error cso_set_blend_color(struct cso_context *ctx,
742 const struct pipe_blend_color *bc)
743 {
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);
747 }
748 return PIPE_OK;
749 }
750
751 enum pipe_error cso_set_sample_mask(struct cso_context *ctx,
752 unsigned sample_mask)
753 {
754 if (ctx->sample_mask != sample_mask) {
755 ctx->sample_mask = sample_mask;
756 ctx->pipe->set_sample_mask(ctx->pipe, sample_mask);
757 }
758 return PIPE_OK;
759 }
760
761 enum pipe_error cso_set_stencil_ref(struct cso_context *ctx,
762 const struct pipe_stencil_ref *sr)
763 {
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);
767 }
768 return PIPE_OK;
769 }
770
771 void cso_save_stencil_ref(struct cso_context *ctx)
772 {
773 ctx->stencil_ref_saved = ctx->stencil_ref;
774 }
775
776
777 void cso_restore_stencil_ref(struct cso_context *ctx)
778 {
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);
782 }
783 }
784
785 enum pipe_error cso_set_geometry_shader_handle(struct cso_context *ctx,
786 void *handle)
787 {
788 if (ctx->geometry_shader != handle) {
789 ctx->geometry_shader = handle;
790 ctx->pipe->bind_gs_state(ctx->pipe, handle);
791 }
792 return PIPE_OK;
793 }
794
795 void cso_delete_geometry_shader(struct cso_context *ctx, void *handle)
796 {
797 if (handle == ctx->geometry_shader) {
798 /* unbind before deleting */
799 ctx->pipe->bind_gs_state(ctx->pipe, NULL);
800 ctx->geometry_shader = NULL;
801 }
802 ctx->pipe->delete_gs_state(ctx->pipe, handle);
803 }
804
805 void cso_save_geometry_shader(struct cso_context *ctx)
806 {
807 assert(!ctx->geometry_shader_saved);
808 ctx->geometry_shader_saved = ctx->geometry_shader;
809 }
810
811 void cso_restore_geometry_shader(struct cso_context *ctx)
812 {
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;
816 }
817 ctx->geometry_shader_saved = NULL;
818 }
819
820 /* clip state */
821
822 static INLINE void
823 clip_state_cpy(struct pipe_clip_state *dst,
824 const struct pipe_clip_state *src)
825 {
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]));
830 }
831 }
832
833 static INLINE int
834 clip_state_cmp(const struct pipe_clip_state *a,
835 const struct pipe_clip_state *b)
836 {
837 if (a->depth_clamp != b->depth_clamp) {
838 return 1;
839 }
840 if (a->nr != b->nr) {
841 return 1;
842 }
843 if (a->nr) {
844 return memcmp(a->ucp, b->ucp, a->nr * sizeof(a->ucp[0]));
845 }
846 return 0;
847 }
848
849 void
850 cso_set_clip(struct cso_context *ctx,
851 const struct pipe_clip_state *clip)
852 {
853 if (clip_state_cmp(&ctx->clip, clip)) {
854 clip_state_cpy(&ctx->clip, clip);
855 ctx->pipe->set_clip_state(ctx->pipe, clip);
856 }
857 }
858
859 void
860 cso_save_clip(struct cso_context *ctx)
861 {
862 clip_state_cpy(&ctx->clip_saved, &ctx->clip);
863 }
864
865 void
866 cso_restore_clip(struct cso_context *ctx)
867 {
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);
871 }
872 }
873
874 enum pipe_error cso_set_vertex_elements(struct cso_context *ctx,
875 unsigned count,
876 const struct pipe_vertex_element *states)
877 {
878 unsigned key_size, hash_key;
879 struct cso_hash_iter iter;
880 void *handle;
881 struct cso_velems_state velems_state;
882
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);
892
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;
897
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;
902
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;
907 }
908
909 handle = cso->data;
910 }
911 else {
912 handle = ((struct cso_velements *)cso_hash_iter_data(iter))->data;
913 }
914
915 if (ctx->velements != handle) {
916 ctx->velements = handle;
917 ctx->pipe->bind_vertex_elements_state(ctx->pipe, handle);
918 }
919 return PIPE_OK;
920 }
921
922 void cso_save_vertex_elements(struct cso_context *ctx)
923 {
924 assert(!ctx->velements_saved);
925 ctx->velements_saved = ctx->velements;
926 }
927
928 void cso_restore_vertex_elements(struct cso_context *ctx)
929 {
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);
933 }
934 ctx->velements_saved = NULL;
935 }
936
937 /* vertex buffers */
938
939 void cso_set_vertex_buffers(struct cso_context *ctx,
940 unsigned count,
941 const struct pipe_vertex_buffer *buffers)
942 {
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);
949 }
950 }
951
952 void cso_save_vertex_buffers(struct cso_context *ctx)
953 {
954 util_copy_vertex_buffers(ctx->vertex_buffers_saved,
955 &ctx->nr_vertex_buffers_saved,
956 ctx->vertex_buffers,
957 ctx->nr_vertex_buffers);
958 }
959
960 void cso_restore_vertex_buffers(struct cso_context *ctx)
961 {
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);
968 }
969
970
971 /**************** fragment/vertex sampler view state *************************/
972
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)
978 {
979 void *handle = NULL;
980
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);
988
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;
993
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;
998
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;
1003 }
1004
1005 handle = cso->data;
1006 }
1007 else {
1008 handle = ((struct cso_sampler *)cso_hash_iter_data(iter))->data;
1009 }
1010 }
1011
1012 info->samplers[idx] = handle;
1013
1014 return PIPE_OK;
1015 }
1016
1017 enum pipe_error
1018 cso_single_sampler(struct cso_context *ctx,
1019 unsigned idx,
1020 const struct pipe_sampler_state *templ)
1021 {
1022 return single_sampler(ctx, &ctx->fragment_samplers, idx, templ);
1023 }
1024
1025 enum pipe_error
1026 cso_single_vertex_sampler(struct cso_context *ctx,
1027 unsigned idx,
1028 const struct pipe_sampler_state *templ)
1029 {
1030 return single_sampler(ctx, &ctx->vertex_samplers, idx, templ);
1031 }
1032
1033
1034
1035 static void
1036 single_sampler_done(struct cso_context *ctx,
1037 struct sampler_info *info)
1038 {
1039 unsigned i;
1040
1041 /* find highest non-null sampler */
1042 for (i = PIPE_MAX_SAMPLERS; i > 0; i--) {
1043 if (info->samplers[i - 1] != NULL)
1044 break;
1045 }
1046
1047 info->nr_samplers = i;
1048
1049 if (info->hw.nr_samplers != info->nr_samplers ||
1050 memcmp(info->hw.samplers,
1051 info->samplers,
1052 info->nr_samplers * sizeof(void *)) != 0)
1053 {
1054 memcpy(info->hw.samplers,
1055 info->samplers,
1056 info->nr_samplers * sizeof(void *));
1057 info->hw.nr_samplers = info->nr_samplers;
1058
1059 if (info == &ctx->fragment_samplers) {
1060 ctx->pipe->bind_fragment_sampler_states(ctx->pipe,
1061 info->nr_samplers,
1062 info->samplers);
1063 }
1064 else if (info == &ctx->vertex_samplers) {
1065 ctx->pipe->bind_vertex_sampler_states(ctx->pipe,
1066 info->nr_samplers,
1067 info->samplers);
1068 }
1069 else {
1070 assert(0);
1071 }
1072 }
1073 }
1074
1075 void
1076 cso_single_sampler_done( struct cso_context *ctx )
1077 {
1078 single_sampler_done(ctx, &ctx->fragment_samplers);
1079 }
1080
1081 void
1082 cso_single_vertex_sampler_done(struct cso_context *ctx)
1083 {
1084 single_sampler_done(ctx, &ctx->vertex_samplers);
1085 }
1086
1087
1088 /*
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.
1092 */
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)
1098 {
1099 unsigned i;
1100 enum pipe_error temp, error = PIPE_OK;
1101
1102 /* TODO: fastpath
1103 */
1104
1105 for (i = 0; i < nr; i++) {
1106 temp = single_sampler(ctx, info, i, templates[i]);
1107 if (temp != PIPE_OK)
1108 error = temp;
1109 }
1110
1111 for ( ; i < info->nr_samplers; i++) {
1112 temp = single_sampler(ctx, info, i, NULL);
1113 if (temp != PIPE_OK)
1114 error = temp;
1115 }
1116
1117 single_sampler_done(ctx, info);
1118
1119 return error;
1120 }
1121
1122 enum pipe_error
1123 cso_set_samplers(struct cso_context *ctx,
1124 unsigned nr,
1125 const struct pipe_sampler_state **templates)
1126 {
1127 return set_samplers(ctx, &ctx->fragment_samplers, nr, templates);
1128 }
1129
1130 enum pipe_error
1131 cso_set_vertex_samplers(struct cso_context *ctx,
1132 unsigned nr,
1133 const struct pipe_sampler_state **templates)
1134 {
1135 return set_samplers(ctx, &ctx->vertex_samplers, nr, templates);
1136 }
1137
1138
1139
1140 static void
1141 save_samplers(struct cso_context *ctx, struct sampler_info *info)
1142 {
1143 info->nr_samplers_saved = info->nr_samplers;
1144 memcpy(info->samplers_saved, info->samplers, sizeof(info->samplers));
1145 }
1146
1147 void
1148 cso_save_samplers(struct cso_context *ctx)
1149 {
1150 save_samplers(ctx, &ctx->fragment_samplers);
1151 }
1152
1153 void
1154 cso_save_vertex_samplers(struct cso_context *ctx)
1155 {
1156 save_samplers(ctx, &ctx->vertex_samplers);
1157 }
1158
1159
1160
1161 static void
1162 restore_samplers(struct cso_context *ctx, struct sampler_info *info)
1163 {
1164 info->nr_samplers = info->nr_samplers_saved;
1165 memcpy(info->samplers, info->samplers_saved, sizeof(info->samplers));
1166 single_sampler_done(ctx, info);
1167 }
1168
1169 void
1170 cso_restore_samplers(struct cso_context *ctx)
1171 {
1172 restore_samplers(ctx, &ctx->fragment_samplers);
1173 }
1174
1175 void
1176 cso_restore_vertex_samplers(struct cso_context *ctx)
1177 {
1178 restore_samplers(ctx, &ctx->vertex_samplers);
1179 }
1180
1181
1182
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)
1191 {
1192 uint i;
1193
1194 /* reference new views */
1195 for (i = 0; i < count; i++) {
1196 pipe_sampler_view_reference(&info->views[i], views[i]);
1197 }
1198 /* unref extra old views, if any */
1199 for (; i < info->nr_views; i++) {
1200 pipe_sampler_view_reference(&info->views[i], NULL);
1201 }
1202
1203 info->nr_views = count;
1204
1205 /* bind the new sampler views */
1206 set_views(ctx->pipe, count, info->views);
1207 }
1208
1209 void
1210 cso_set_fragment_sampler_views(struct cso_context *ctx,
1211 uint count,
1212 struct pipe_sampler_view **views)
1213 {
1214 set_sampler_views(ctx, &ctx->fragment_samplers,
1215 ctx->pipe->set_fragment_sampler_views,
1216 count, views);
1217 }
1218
1219 void
1220 cso_set_vertex_sampler_views(struct cso_context *ctx,
1221 uint count,
1222 struct pipe_sampler_view **views)
1223 {
1224 set_sampler_views(ctx, &ctx->vertex_samplers,
1225 ctx->pipe->set_vertex_sampler_views,
1226 count, views);
1227 }
1228
1229
1230
1231 static void
1232 save_sampler_views(struct cso_context *ctx,
1233 struct sampler_info *info)
1234 {
1235 uint i;
1236
1237 info->nr_views_saved = info->nr_views;
1238
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]);
1242 }
1243 }
1244
1245 void
1246 cso_save_fragment_sampler_views(struct cso_context *ctx)
1247 {
1248 save_sampler_views(ctx, &ctx->fragment_samplers);
1249 }
1250
1251 void
1252 cso_save_vertex_sampler_views(struct cso_context *ctx)
1253 {
1254 save_sampler_views(ctx, &ctx->vertex_samplers);
1255 }
1256
1257
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 **))
1264 {
1265 uint i;
1266
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);
1270 }
1271 for (; i < info->nr_views; i++) {
1272 pipe_sampler_view_reference(&info->views[i], NULL);
1273 }
1274
1275 /* bind the old/saved sampler views */
1276 set_views(ctx->pipe, info->nr_views_saved, info->views);
1277
1278 info->nr_views = info->nr_views_saved;
1279 info->nr_views_saved = 0;
1280 }
1281
1282 void
1283 cso_restore_fragment_sampler_views(struct cso_context *ctx)
1284 {
1285 restore_sampler_views(ctx, &ctx->fragment_samplers,
1286 ctx->pipe->set_fragment_sampler_views);
1287 }
1288
1289 void
1290 cso_restore_vertex_sampler_views(struct cso_context *ctx)
1291 {
1292 restore_sampler_views(ctx, &ctx->vertex_samplers,
1293 ctx->pipe->set_vertex_sampler_views);
1294 }