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