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