Merge branch 'mesa_7_5_branch' into mesa_7_6_branch
[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_memory.h"
40 #include "tgsi/tgsi_parse.h"
41
42 #include "cso_cache/cso_context.h"
43 #include "cso_cache/cso_cache.h"
44 #include "cso_cache/cso_hash.h"
45
46 struct cso_context {
47 struct pipe_context *pipe;
48 struct cso_cache *cache;
49
50 struct {
51 void *samplers[PIPE_MAX_SAMPLERS];
52 unsigned nr_samplers;
53 } hw;
54
55 void *samplers[PIPE_MAX_SAMPLERS];
56 unsigned nr_samplers;
57
58 unsigned nr_samplers_saved;
59 void *samplers_saved[PIPE_MAX_SAMPLERS];
60
61 struct pipe_texture *textures[PIPE_MAX_SAMPLERS];
62 uint nr_textures;
63
64 uint nr_textures_saved;
65 struct pipe_texture *textures_saved[PIPE_MAX_SAMPLERS];
66
67 /** Current and saved state.
68 * The saved state is used as a 1-deep stack.
69 */
70 void *blend, *blend_saved;
71 void *depth_stencil, *depth_stencil_saved;
72 void *rasterizer, *rasterizer_saved;
73 void *fragment_shader, *fragment_shader_saved;
74 void *vertex_shader, *vertex_shader_saved;
75
76 struct pipe_framebuffer_state fb, fb_saved;
77 struct pipe_viewport_state vp, vp_saved;
78 struct pipe_blend_color blend_color;
79 };
80
81
82 static void
83 free_framebuffer_state(struct pipe_framebuffer_state *fb);
84
85
86 static boolean delete_blend_state(struct cso_context *ctx, void *state)
87 {
88 struct cso_blend *cso = (struct cso_blend *)state;
89
90 if (ctx->blend == cso->data)
91 return FALSE;
92
93 if (cso->delete_state)
94 cso->delete_state(cso->context, cso->data);
95 FREE(state);
96 return TRUE;
97 }
98
99 static boolean delete_depth_stencil_state(struct cso_context *ctx, void *state)
100 {
101 struct cso_depth_stencil_alpha *cso = (struct cso_depth_stencil_alpha *)state;
102
103 if (ctx->depth_stencil == cso->data)
104 return FALSE;
105
106 if (cso->delete_state)
107 cso->delete_state(cso->context, cso->data);
108 FREE(state);
109
110 return TRUE;
111 }
112
113 static boolean delete_sampler_state(struct cso_context *ctx, void *state)
114 {
115 struct cso_sampler *cso = (struct cso_sampler *)state;
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_rasterizer_state(struct cso_context *ctx, void *state)
123 {
124 struct cso_rasterizer *cso = (struct cso_rasterizer *)state;
125
126 if (ctx->rasterizer == cso->data)
127 return FALSE;
128 if (cso->delete_state)
129 cso->delete_state(cso->context, cso->data);
130 FREE(state);
131 return TRUE;
132 }
133
134 static boolean delete_fs_state(struct cso_context *ctx, void *state)
135 {
136 struct cso_fragment_shader *cso = (struct cso_fragment_shader *)state;
137 if (ctx->fragment_shader == cso->data)
138 return FALSE;
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_vs_state(struct cso_context *ctx, void *state)
146 {
147 struct cso_vertex_shader *cso = (struct cso_vertex_shader *)state;
148 if (ctx->vertex_shader == cso->data)
149 return TRUE;
150 if (cso->delete_state)
151 cso->delete_state(cso->context, cso->data);
152 FREE(state);
153 return FALSE;
154 }
155
156
157 static INLINE boolean delete_cso(struct cso_context *ctx,
158 void *state, enum cso_cache_type type)
159 {
160 switch (type) {
161 case CSO_BLEND:
162 return delete_blend_state(ctx, state);
163 break;
164 case CSO_SAMPLER:
165 return delete_sampler_state(ctx, state);
166 break;
167 case CSO_DEPTH_STENCIL_ALPHA:
168 return delete_depth_stencil_state(ctx, state);
169 break;
170 case CSO_RASTERIZER:
171 return delete_rasterizer_state(ctx, state);
172 break;
173 case CSO_FRAGMENT_SHADER:
174 return delete_fs_state(ctx, state);
175 break;
176 case CSO_VERTEX_SHADER:
177 return delete_vs_state(ctx, state);
178 break;
179 default:
180 assert(0);
181 FREE(state);
182 }
183 return FALSE;
184 }
185
186 static INLINE void sanitize_hash(struct cso_hash *hash, enum cso_cache_type type,
187 int max_size, void *user_data)
188 {
189 struct cso_context *ctx = (struct cso_context *)user_data;
190 /* if we're approach the maximum size, remove fourth of the entries
191 * otherwise every subsequent call will go through the same */
192 int hash_size = cso_hash_size(hash);
193 int max_entries = (max_size > hash_size) ? max_size : hash_size;
194 int to_remove = (max_size < max_entries) * max_entries/4;
195 struct cso_hash_iter iter = cso_hash_first_node(hash);
196 if (hash_size > max_size)
197 to_remove += hash_size - max_size;
198 while (to_remove) {
199 /*remove elements until we're good */
200 /*fixme: currently we pick the nodes to remove at random*/
201 void *cso = cso_hash_iter_data(iter);
202 if (delete_cso(ctx, cso, type)) {
203 iter = cso_hash_erase(hash, iter);
204 --to_remove;
205 } else
206 iter = cso_hash_iter_next(iter);
207 }
208 }
209
210
211 struct cso_context *cso_create_context( struct pipe_context *pipe )
212 {
213 struct cso_context *ctx = CALLOC_STRUCT(cso_context);
214 if (ctx == NULL)
215 goto out;
216
217 ctx->cache = cso_cache_create();
218 if (ctx->cache == NULL)
219 goto out;
220 cso_cache_set_sanitize_callback(ctx->cache,
221 sanitize_hash,
222 ctx);
223
224 ctx->pipe = pipe;
225
226 /* Enable for testing: */
227 if (0) cso_set_maximum_cache_size( ctx->cache, 4 );
228
229 return ctx;
230
231 out:
232 cso_destroy_context( ctx );
233 return NULL;
234 }
235
236
237 /**
238 * Prior to context destruction, this function unbinds all state objects.
239 */
240 void cso_release_all( struct cso_context *ctx )
241 {
242 unsigned i;
243
244 if (ctx->pipe) {
245 ctx->pipe->bind_blend_state( ctx->pipe, NULL );
246 ctx->pipe->bind_rasterizer_state( ctx->pipe, NULL );
247 ctx->pipe->bind_sampler_states( ctx->pipe, 0, NULL );
248 ctx->pipe->bind_depth_stencil_alpha_state( ctx->pipe, NULL );
249 ctx->pipe->bind_fs_state( ctx->pipe, NULL );
250 ctx->pipe->bind_vs_state( ctx->pipe, NULL );
251 }
252
253 for (i = 0; i < PIPE_MAX_SAMPLERS; i++) {
254 pipe_texture_reference(&ctx->textures[i], NULL);
255 pipe_texture_reference(&ctx->textures_saved[i], NULL);
256 }
257
258 free_framebuffer_state(&ctx->fb);
259 free_framebuffer_state(&ctx->fb_saved);
260
261 if (ctx->cache) {
262 cso_cache_delete( ctx->cache );
263 ctx->cache = NULL;
264 }
265 }
266
267
268 void cso_destroy_context( struct cso_context *ctx )
269 {
270 if (ctx) {
271 //cso_release_all( ctx );
272 FREE( ctx );
273 }
274 }
275
276
277 /* Those function will either find the state of the given template
278 * in the cache or they will create a new state from the given
279 * template, insert it in the cache and return it.
280 */
281
282 /*
283 * If the driver returns 0 from the create method then they will assign
284 * the data member of the cso to be the template itself.
285 */
286
287 enum pipe_error cso_set_blend(struct cso_context *ctx,
288 const struct pipe_blend_state *templ)
289 {
290 unsigned hash_key = cso_construct_key((void*)templ, sizeof(struct pipe_blend_state));
291 struct cso_hash_iter iter = cso_find_state_template(ctx->cache,
292 hash_key, CSO_BLEND,
293 (void*)templ);
294 void *handle;
295
296 if (cso_hash_iter_is_null(iter)) {
297 struct cso_blend *cso = MALLOC(sizeof(struct cso_blend));
298 if (!cso)
299 return PIPE_ERROR_OUT_OF_MEMORY;
300
301 memcpy(&cso->state, templ, sizeof(*templ));
302 cso->data = ctx->pipe->create_blend_state(ctx->pipe, &cso->state);
303 cso->delete_state = (cso_state_callback)ctx->pipe->delete_blend_state;
304 cso->context = ctx->pipe;
305
306 iter = cso_insert_state(ctx->cache, hash_key, CSO_BLEND, cso);
307 if (cso_hash_iter_is_null(iter)) {
308 FREE(cso);
309 return PIPE_ERROR_OUT_OF_MEMORY;
310 }
311
312 handle = cso->data;
313 }
314 else {
315 handle = ((struct cso_blend *)cso_hash_iter_data(iter))->data;
316 }
317
318 if (ctx->blend != handle) {
319 ctx->blend = handle;
320 ctx->pipe->bind_blend_state(ctx->pipe, handle);
321 }
322 return PIPE_OK;
323 }
324
325 void cso_save_blend(struct cso_context *ctx)
326 {
327 assert(!ctx->blend_saved);
328 ctx->blend_saved = ctx->blend;
329 }
330
331 void cso_restore_blend(struct cso_context *ctx)
332 {
333 if (ctx->blend != ctx->blend_saved) {
334 ctx->blend = ctx->blend_saved;
335 ctx->pipe->bind_blend_state(ctx->pipe, ctx->blend_saved);
336 }
337 ctx->blend_saved = NULL;
338 }
339
340
341
342 enum pipe_error cso_single_sampler(struct cso_context *ctx,
343 unsigned idx,
344 const struct pipe_sampler_state *templ)
345 {
346 void *handle = NULL;
347
348 if (templ != NULL) {
349 unsigned hash_key = cso_construct_key((void*)templ, sizeof(struct pipe_sampler_state));
350 struct cso_hash_iter iter = cso_find_state_template(ctx->cache,
351 hash_key, CSO_SAMPLER,
352 (void*)templ);
353
354 if (cso_hash_iter_is_null(iter)) {
355 struct cso_sampler *cso = MALLOC(sizeof(struct cso_sampler));
356 if (!cso)
357 return PIPE_ERROR_OUT_OF_MEMORY;
358
359 memcpy(&cso->state, templ, sizeof(*templ));
360 cso->data = ctx->pipe->create_sampler_state(ctx->pipe, &cso->state);
361 cso->delete_state = (cso_state_callback)ctx->pipe->delete_sampler_state;
362 cso->context = ctx->pipe;
363
364 iter = cso_insert_state(ctx->cache, hash_key, CSO_SAMPLER, cso);
365 if (cso_hash_iter_is_null(iter)) {
366 FREE(cso);
367 return PIPE_ERROR_OUT_OF_MEMORY;
368 }
369
370 handle = cso->data;
371 }
372 else {
373 handle = ((struct cso_sampler *)cso_hash_iter_data(iter))->data;
374 }
375 }
376
377 ctx->samplers[idx] = handle;
378 return PIPE_OK;
379 }
380
381 void cso_single_sampler_done( struct cso_context *ctx )
382 {
383 unsigned i;
384
385 /* find highest non-null sampler */
386 for (i = PIPE_MAX_SAMPLERS; i > 0; i--) {
387 if (ctx->samplers[i - 1] != NULL)
388 break;
389 }
390
391 ctx->nr_samplers = i;
392
393 if (ctx->hw.nr_samplers != ctx->nr_samplers ||
394 memcmp(ctx->hw.samplers,
395 ctx->samplers,
396 ctx->nr_samplers * sizeof(void *)) != 0)
397 {
398 memcpy(ctx->hw.samplers, ctx->samplers, ctx->nr_samplers * sizeof(void *));
399 ctx->hw.nr_samplers = ctx->nr_samplers;
400
401 ctx->pipe->bind_sampler_states(ctx->pipe, ctx->nr_samplers, ctx->samplers);
402 }
403 }
404
405 /*
406 * If the function encouters any errors it will return the
407 * last one. Done to always try to set as many samplers
408 * as possible.
409 */
410 enum pipe_error cso_set_samplers( struct cso_context *ctx,
411 unsigned nr,
412 const struct pipe_sampler_state **templates )
413 {
414 unsigned i;
415 enum pipe_error temp, error = PIPE_OK;
416
417 /* TODO: fastpath
418 */
419
420 for (i = 0; i < nr; i++) {
421 temp = cso_single_sampler( ctx, i, templates[i] );
422 if (temp != PIPE_OK)
423 error = temp;
424 }
425
426 for ( ; i < ctx->nr_samplers; i++) {
427 temp = cso_single_sampler( ctx, i, NULL );
428 if (temp != PIPE_OK)
429 error = temp;
430 }
431
432 cso_single_sampler_done( ctx );
433
434 return error;
435 }
436
437 void cso_save_samplers(struct cso_context *ctx)
438 {
439 ctx->nr_samplers_saved = ctx->nr_samplers;
440 memcpy(ctx->samplers_saved, ctx->samplers, sizeof(ctx->samplers));
441 }
442
443 void cso_restore_samplers(struct cso_context *ctx)
444 {
445 ctx->nr_samplers = ctx->nr_samplers_saved;
446 memcpy(ctx->samplers, ctx->samplers_saved, sizeof(ctx->samplers));
447 cso_single_sampler_done( ctx );
448 }
449
450
451 enum pipe_error cso_set_sampler_textures( struct cso_context *ctx,
452 uint count,
453 struct pipe_texture **textures )
454 {
455 uint i;
456
457 ctx->nr_textures = count;
458
459 for (i = 0; i < count; i++)
460 pipe_texture_reference(&ctx->textures[i], textures[i]);
461 for ( ; i < PIPE_MAX_SAMPLERS; i++)
462 pipe_texture_reference(&ctx->textures[i], NULL);
463
464 ctx->pipe->set_sampler_textures(ctx->pipe, count, textures);
465
466 return PIPE_OK;
467 }
468
469 void cso_save_sampler_textures( struct cso_context *ctx )
470 {
471 uint i;
472
473 ctx->nr_textures_saved = ctx->nr_textures;
474 for (i = 0; i < ctx->nr_textures; i++) {
475 assert(!ctx->textures_saved[i]);
476 pipe_texture_reference(&ctx->textures_saved[i], ctx->textures[i]);
477 }
478 }
479
480 void cso_restore_sampler_textures( struct cso_context *ctx )
481 {
482 uint i;
483
484 ctx->nr_textures = ctx->nr_textures_saved;
485
486 for (i = 0; i < ctx->nr_textures; i++) {
487 pipe_texture_reference(&ctx->textures[i], NULL);
488 ctx->textures[i] = ctx->textures_saved[i];
489 ctx->textures_saved[i] = NULL;
490 }
491 for ( ; i < PIPE_MAX_SAMPLERS; i++)
492 pipe_texture_reference(&ctx->textures[i], NULL);
493
494 ctx->pipe->set_sampler_textures(ctx->pipe, ctx->nr_textures, ctx->textures);
495
496 ctx->nr_textures_saved = 0;
497 }
498
499
500
501 enum pipe_error cso_set_depth_stencil_alpha(struct cso_context *ctx,
502 const struct pipe_depth_stencil_alpha_state *templ)
503 {
504 unsigned hash_key = cso_construct_key((void*)templ,
505 sizeof(struct pipe_depth_stencil_alpha_state));
506 struct cso_hash_iter iter = cso_find_state_template(ctx->cache,
507 hash_key,
508 CSO_DEPTH_STENCIL_ALPHA,
509 (void*)templ);
510 void *handle;
511
512 if (cso_hash_iter_is_null(iter)) {
513 struct cso_depth_stencil_alpha *cso = MALLOC(sizeof(struct cso_depth_stencil_alpha));
514 if (!cso)
515 return PIPE_ERROR_OUT_OF_MEMORY;
516
517 memcpy(&cso->state, templ, sizeof(*templ));
518 cso->data = ctx->pipe->create_depth_stencil_alpha_state(ctx->pipe, &cso->state);
519 cso->delete_state = (cso_state_callback)ctx->pipe->delete_depth_stencil_alpha_state;
520 cso->context = ctx->pipe;
521
522 iter = cso_insert_state(ctx->cache, hash_key, CSO_DEPTH_STENCIL_ALPHA, cso);
523 if (cso_hash_iter_is_null(iter)) {
524 FREE(cso);
525 return PIPE_ERROR_OUT_OF_MEMORY;
526 }
527
528 handle = cso->data;
529 }
530 else {
531 handle = ((struct cso_depth_stencil_alpha *)cso_hash_iter_data(iter))->data;
532 }
533
534 if (ctx->depth_stencil != handle) {
535 ctx->depth_stencil = handle;
536 ctx->pipe->bind_depth_stencil_alpha_state(ctx->pipe, handle);
537 }
538 return PIPE_OK;
539 }
540
541 void cso_save_depth_stencil_alpha(struct cso_context *ctx)
542 {
543 assert(!ctx->depth_stencil_saved);
544 ctx->depth_stencil_saved = ctx->depth_stencil;
545 }
546
547 void cso_restore_depth_stencil_alpha(struct cso_context *ctx)
548 {
549 if (ctx->depth_stencil != ctx->depth_stencil_saved) {
550 ctx->depth_stencil = ctx->depth_stencil_saved;
551 ctx->pipe->bind_depth_stencil_alpha_state(ctx->pipe, ctx->depth_stencil_saved);
552 }
553 ctx->depth_stencil_saved = NULL;
554 }
555
556
557
558 enum pipe_error cso_set_rasterizer(struct cso_context *ctx,
559 const struct pipe_rasterizer_state *templ)
560 {
561 unsigned hash_key = cso_construct_key((void*)templ,
562 sizeof(struct pipe_rasterizer_state));
563 struct cso_hash_iter iter = cso_find_state_template(ctx->cache,
564 hash_key, CSO_RASTERIZER,
565 (void*)templ);
566 void *handle = NULL;
567
568 if (cso_hash_iter_is_null(iter)) {
569 struct cso_rasterizer *cso = MALLOC(sizeof(struct cso_rasterizer));
570 if (!cso)
571 return PIPE_ERROR_OUT_OF_MEMORY;
572
573 memcpy(&cso->state, templ, sizeof(*templ));
574 cso->data = ctx->pipe->create_rasterizer_state(ctx->pipe, &cso->state);
575 cso->delete_state = (cso_state_callback)ctx->pipe->delete_rasterizer_state;
576 cso->context = ctx->pipe;
577
578 iter = cso_insert_state(ctx->cache, hash_key, CSO_RASTERIZER, cso);
579 if (cso_hash_iter_is_null(iter)) {
580 FREE(cso);
581 return PIPE_ERROR_OUT_OF_MEMORY;
582 }
583
584 handle = cso->data;
585 }
586 else {
587 handle = ((struct cso_rasterizer *)cso_hash_iter_data(iter))->data;
588 }
589
590 if (ctx->rasterizer != handle) {
591 ctx->rasterizer = handle;
592 ctx->pipe->bind_rasterizer_state(ctx->pipe, handle);
593 }
594 return PIPE_OK;
595 }
596
597 void cso_save_rasterizer(struct cso_context *ctx)
598 {
599 assert(!ctx->rasterizer_saved);
600 ctx->rasterizer_saved = ctx->rasterizer;
601 }
602
603 void cso_restore_rasterizer(struct cso_context *ctx)
604 {
605 if (ctx->rasterizer != ctx->rasterizer_saved) {
606 ctx->rasterizer = ctx->rasterizer_saved;
607 ctx->pipe->bind_rasterizer_state(ctx->pipe, ctx->rasterizer_saved);
608 }
609 ctx->rasterizer_saved = NULL;
610 }
611
612
613
614 enum pipe_error cso_set_fragment_shader_handle(struct cso_context *ctx,
615 void *handle )
616 {
617 if (ctx->fragment_shader != handle) {
618 ctx->fragment_shader = handle;
619 ctx->pipe->bind_fs_state(ctx->pipe, handle);
620 }
621 return PIPE_OK;
622 }
623
624 void cso_delete_fragment_shader(struct cso_context *ctx, void *handle )
625 {
626 if (handle == ctx->fragment_shader) {
627 /* unbind before deleting */
628 ctx->pipe->bind_fs_state(ctx->pipe, NULL);
629 ctx->fragment_shader = NULL;
630 }
631 ctx->pipe->delete_fs_state(ctx->pipe, handle);
632 }
633
634 /* Not really working:
635 */
636 #if 0
637 enum pipe_error cso_set_fragment_shader(struct cso_context *ctx,
638 const struct pipe_shader_state *templ)
639 {
640 const struct tgsi_token *tokens = templ->tokens;
641 unsigned num_tokens = tgsi_num_tokens(tokens);
642 size_t tokens_size = num_tokens*sizeof(struct tgsi_token);
643 unsigned hash_key = cso_construct_key((void*)tokens, tokens_size);
644 struct cso_hash_iter iter = cso_find_state_template(ctx->cache,
645 hash_key,
646 CSO_FRAGMENT_SHADER,
647 (void*)tokens);
648 void *handle = NULL;
649
650 if (cso_hash_iter_is_null(iter)) {
651 struct cso_fragment_shader *cso = MALLOC(sizeof(struct cso_fragment_shader) + tokens_size);
652 struct tgsi_token *cso_tokens = (struct tgsi_token *)((char *)cso + sizeof(*cso));
653
654 if (!cso)
655 return PIPE_ERROR_OUT_OF_MEMORY;
656
657 memcpy(cso_tokens, tokens, tokens_size);
658 cso->state.tokens = cso_tokens;
659 cso->data = ctx->pipe->create_fs_state(ctx->pipe, &cso->state);
660 cso->delete_state = (cso_state_callback)ctx->pipe->delete_fs_state;
661 cso->context = ctx->pipe;
662
663 iter = cso_insert_state(ctx->cache, hash_key, CSO_FRAGMENT_SHADER, cso);
664 if (cso_hash_iter_is_null(iter)) {
665 FREE(cso);
666 return PIPE_ERROR_OUT_OF_MEMORY;
667 }
668
669 handle = cso->data;
670 }
671 else {
672 handle = ((struct cso_fragment_shader *)cso_hash_iter_data(iter))->data;
673 }
674
675 return cso_set_fragment_shader_handle( ctx, handle );
676 }
677 #endif
678
679 void cso_save_fragment_shader(struct cso_context *ctx)
680 {
681 assert(!ctx->fragment_shader_saved);
682 ctx->fragment_shader_saved = ctx->fragment_shader;
683 }
684
685 void cso_restore_fragment_shader(struct cso_context *ctx)
686 {
687 if (ctx->fragment_shader_saved != ctx->fragment_shader) {
688 ctx->pipe->bind_fs_state(ctx->pipe, ctx->fragment_shader_saved);
689 ctx->fragment_shader = ctx->fragment_shader_saved;
690 }
691 ctx->fragment_shader_saved = NULL;
692 }
693
694
695 enum pipe_error cso_set_vertex_shader_handle(struct cso_context *ctx,
696 void *handle )
697 {
698 if (ctx->vertex_shader != handle) {
699 ctx->vertex_shader = handle;
700 ctx->pipe->bind_vs_state(ctx->pipe, handle);
701 }
702 return PIPE_OK;
703 }
704
705 void cso_delete_vertex_shader(struct cso_context *ctx, void *handle )
706 {
707 if (handle == ctx->vertex_shader) {
708 /* unbind before deleting */
709 ctx->pipe->bind_vs_state(ctx->pipe, NULL);
710 ctx->vertex_shader = NULL;
711 }
712 ctx->pipe->delete_vs_state(ctx->pipe, handle);
713 }
714
715
716 /* Not really working:
717 */
718 #if 0
719 enum pipe_error cso_set_vertex_shader(struct cso_context *ctx,
720 const struct pipe_shader_state *templ)
721 {
722 unsigned hash_key = cso_construct_key((void*)templ,
723 sizeof(struct pipe_shader_state));
724 struct cso_hash_iter iter = cso_find_state_template(ctx->cache,
725 hash_key, CSO_VERTEX_SHADER,
726 (void*)templ);
727 void *handle = NULL;
728
729 if (cso_hash_iter_is_null(iter)) {
730 struct cso_vertex_shader *cso = MALLOC(sizeof(struct cso_vertex_shader));
731
732 if (!cso)
733 return PIPE_ERROR_OUT_OF_MEMORY;
734
735 memcpy(cso->state, templ, sizeof(*templ));
736 cso->data = ctx->pipe->create_vs_state(ctx->pipe, &cso->state);
737 cso->delete_state = (cso_state_callback)ctx->pipe->delete_vs_state;
738 cso->context = ctx->pipe;
739
740 iter = cso_insert_state(ctx->cache, hash_key, CSO_VERTEX_SHADER, cso);
741 if (cso_hash_iter_is_null(iter)) {
742 FREE(cso);
743 return PIPE_ERROR_OUT_OF_MEMORY;
744 }
745
746 handle = cso->data;
747 }
748 else {
749 handle = ((struct cso_vertex_shader *)cso_hash_iter_data(iter))->data;
750 }
751
752 return cso_set_vertex_shader_handle( ctx, handle );
753 }
754 #endif
755
756
757
758 void cso_save_vertex_shader(struct cso_context *ctx)
759 {
760 assert(!ctx->vertex_shader_saved);
761 ctx->vertex_shader_saved = ctx->vertex_shader;
762 }
763
764 void cso_restore_vertex_shader(struct cso_context *ctx)
765 {
766 if (ctx->vertex_shader_saved != ctx->vertex_shader) {
767 ctx->pipe->bind_vs_state(ctx->pipe, ctx->vertex_shader_saved);
768 ctx->vertex_shader = ctx->vertex_shader_saved;
769 }
770 ctx->vertex_shader_saved = NULL;
771 }
772
773
774 /**
775 * Copy framebuffer state from src to dst with refcounting of surfaces.
776 */
777 static void
778 copy_framebuffer_state(struct pipe_framebuffer_state *dst,
779 const struct pipe_framebuffer_state *src)
780 {
781 uint i;
782
783 dst->width = src->width;
784 dst->height = src->height;
785 dst->nr_cbufs = src->nr_cbufs;
786 for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) {
787 pipe_surface_reference(&dst->cbufs[i], src->cbufs[i]);
788 }
789 pipe_surface_reference(&dst->zsbuf, src->zsbuf);
790 }
791
792
793 static void
794 free_framebuffer_state(struct pipe_framebuffer_state *fb)
795 {
796 uint i;
797
798 for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) {
799 pipe_surface_reference(&fb->cbufs[i], NULL);
800 }
801 pipe_surface_reference(&fb->zsbuf, NULL);
802 }
803
804
805 enum pipe_error cso_set_framebuffer(struct cso_context *ctx,
806 const struct pipe_framebuffer_state *fb)
807 {
808 if (memcmp(&ctx->fb, fb, sizeof(*fb)) != 0) {
809 copy_framebuffer_state(&ctx->fb, fb);
810 ctx->pipe->set_framebuffer_state(ctx->pipe, fb);
811 }
812 return PIPE_OK;
813 }
814
815 void cso_save_framebuffer(struct cso_context *ctx)
816 {
817 copy_framebuffer_state(&ctx->fb_saved, &ctx->fb);
818 }
819
820 void cso_restore_framebuffer(struct cso_context *ctx)
821 {
822 if (memcmp(&ctx->fb, &ctx->fb_saved, sizeof(ctx->fb))) {
823 copy_framebuffer_state(&ctx->fb, &ctx->fb_saved);
824 ctx->pipe->set_framebuffer_state(ctx->pipe, &ctx->fb);
825 free_framebuffer_state(&ctx->fb_saved);
826 }
827 }
828
829
830 enum pipe_error cso_set_viewport(struct cso_context *ctx,
831 const struct pipe_viewport_state *vp)
832 {
833 if (memcmp(&ctx->vp, vp, sizeof(*vp))) {
834 ctx->vp = *vp;
835 ctx->pipe->set_viewport_state(ctx->pipe, vp);
836 }
837 return PIPE_OK;
838 }
839
840 void cso_save_viewport(struct cso_context *ctx)
841 {
842 ctx->vp_saved = ctx->vp;
843 }
844
845
846 void cso_restore_viewport(struct cso_context *ctx)
847 {
848 if (memcmp(&ctx->vp, &ctx->vp_saved, sizeof(ctx->vp))) {
849 ctx->vp = ctx->vp_saved;
850 ctx->pipe->set_viewport_state(ctx->pipe, &ctx->vp);
851 }
852 }
853
854
855
856
857 enum pipe_error cso_set_blend_color(struct cso_context *ctx,
858 const struct pipe_blend_color *bc)
859 {
860 if (memcmp(&ctx->blend_color, bc, sizeof(ctx->blend_color))) {
861 ctx->blend_color = *bc;
862 ctx->pipe->set_blend_color(ctx->pipe, bc);
863 }
864 return PIPE_OK;
865 }