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