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