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