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