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