cso: add context cleanup code from st/mesa
[mesa.git] / src / gallium / auxiliary / cso_cache / cso_context.c
1 /**************************************************************************
2 *
3 * Copyright 2007 VMware, Inc.
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 VMWARE 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 <zackr@vmware.com>
35 * @author Keith Whitwell <keithw@vmware.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_SHADER_SAMPLER_VIEWS];
71 unsigned nr_views;
72
73 struct pipe_sampler_view *views_saved[PIPE_MAX_SHADER_SAMPLER_VIEWS];
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_tessellation;
86 boolean has_streamout;
87
88 struct sampler_info samplers[PIPE_SHADER_TYPES];
89
90 struct pipe_vertex_buffer aux_vertex_buffer_current;
91 struct pipe_vertex_buffer aux_vertex_buffer_saved;
92 unsigned aux_vertex_buffer_index;
93
94 struct pipe_constant_buffer aux_constbuf_current[PIPE_SHADER_TYPES];
95 struct pipe_constant_buffer aux_constbuf_saved[PIPE_SHADER_TYPES];
96
97 unsigned nr_so_targets;
98 struct pipe_stream_output_target *so_targets[PIPE_MAX_SO_BUFFERS];
99
100 unsigned nr_so_targets_saved;
101 struct pipe_stream_output_target *so_targets_saved[PIPE_MAX_SO_BUFFERS];
102
103 /** Current and saved state.
104 * The saved state is used as a 1-deep stack.
105 */
106 void *blend, *blend_saved;
107 void *depth_stencil, *depth_stencil_saved;
108 void *rasterizer, *rasterizer_saved;
109 void *fragment_shader, *fragment_shader_saved;
110 void *vertex_shader, *vertex_shader_saved;
111 void *geometry_shader, *geometry_shader_saved;
112 void *tessctrl_shader, *tessctrl_shader_saved;
113 void *tesseval_shader, *tesseval_shader_saved;
114 void *velements, *velements_saved;
115 struct pipe_query *render_condition, *render_condition_saved;
116 uint render_condition_mode, render_condition_mode_saved;
117 boolean render_condition_cond, render_condition_cond_saved;
118
119 struct pipe_clip_state clip;
120 struct pipe_clip_state clip_saved;
121
122 struct pipe_framebuffer_state fb, fb_saved;
123 struct pipe_viewport_state vp, vp_saved;
124 struct pipe_blend_color blend_color;
125 unsigned sample_mask, sample_mask_saved;
126 unsigned min_samples, min_samples_saved;
127 struct pipe_stencil_ref stencil_ref, stencil_ref_saved;
128 };
129
130
131 static boolean delete_blend_state(struct cso_context *ctx, void *state)
132 {
133 struct cso_blend *cso = (struct cso_blend *)state;
134
135 if (ctx->blend == cso->data)
136 return FALSE;
137
138 if (cso->delete_state)
139 cso->delete_state(cso->context, cso->data);
140 FREE(state);
141 return TRUE;
142 }
143
144 static boolean delete_depth_stencil_state(struct cso_context *ctx, void *state)
145 {
146 struct cso_depth_stencil_alpha *cso =
147 (struct cso_depth_stencil_alpha *)state;
148
149 if (ctx->depth_stencil == cso->data)
150 return FALSE;
151
152 if (cso->delete_state)
153 cso->delete_state(cso->context, cso->data);
154 FREE(state);
155
156 return TRUE;
157 }
158
159 static boolean delete_sampler_state(struct cso_context *ctx, void *state)
160 {
161 struct cso_sampler *cso = (struct cso_sampler *)state;
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_rasterizer_state(struct cso_context *ctx, void *state)
169 {
170 struct cso_rasterizer *cso = (struct cso_rasterizer *)state;
171
172 if (ctx->rasterizer == cso->data)
173 return FALSE;
174 if (cso->delete_state)
175 cso->delete_state(cso->context, cso->data);
176 FREE(state);
177 return TRUE;
178 }
179
180 static boolean delete_vertex_elements(struct cso_context *ctx,
181 void *state)
182 {
183 struct cso_velements *cso = (struct cso_velements *)state;
184
185 if (ctx->velements == cso->data)
186 return FALSE;
187
188 if (cso->delete_state)
189 cso->delete_state(cso->context, cso->data);
190 FREE(state);
191 return TRUE;
192 }
193
194
195 static INLINE boolean delete_cso(struct cso_context *ctx,
196 void *state, enum cso_cache_type type)
197 {
198 switch (type) {
199 case CSO_BLEND:
200 return delete_blend_state(ctx, state);
201 case CSO_SAMPLER:
202 return delete_sampler_state(ctx, state);
203 case CSO_DEPTH_STENCIL_ALPHA:
204 return delete_depth_stencil_state(ctx, state);
205 case CSO_RASTERIZER:
206 return delete_rasterizer_state(ctx, state);
207 case CSO_VELEMENTS:
208 return delete_vertex_elements(ctx, state);
209 default:
210 assert(0);
211 FREE(state);
212 }
213 return FALSE;
214 }
215
216 static INLINE void
217 sanitize_hash(struct cso_hash *hash, enum cso_cache_type type,
218 int max_size, void *user_data)
219 {
220 struct cso_context *ctx = (struct cso_context *)user_data;
221 /* if we're approach the maximum size, remove fourth of the entries
222 * otherwise every subsequent call will go through the same */
223 int hash_size = cso_hash_size(hash);
224 int max_entries = (max_size > hash_size) ? max_size : hash_size;
225 int to_remove = (max_size < max_entries) * max_entries/4;
226 struct cso_hash_iter iter = cso_hash_first_node(hash);
227 if (hash_size > max_size)
228 to_remove += hash_size - max_size;
229 while (to_remove) {
230 /*remove elements until we're good */
231 /*fixme: currently we pick the nodes to remove at random*/
232 void *cso = cso_hash_iter_data(iter);
233 if (delete_cso(ctx, cso, type)) {
234 iter = cso_hash_erase(hash, iter);
235 --to_remove;
236 } else
237 iter = cso_hash_iter_next(iter);
238 }
239 }
240
241 static void cso_init_vbuf(struct cso_context *cso)
242 {
243 struct u_vbuf_caps caps;
244
245 /* Install u_vbuf if there is anything unsupported. */
246 if (u_vbuf_get_caps(cso->pipe->screen, &caps)) {
247 cso->vbuf = u_vbuf_create(cso->pipe, &caps,
248 cso->aux_vertex_buffer_index);
249 }
250 }
251
252 struct cso_context *cso_create_context( struct pipe_context *pipe )
253 {
254 struct cso_context *ctx = CALLOC_STRUCT(cso_context);
255 if (ctx == NULL)
256 goto out;
257
258 ctx->cache = cso_cache_create();
259 if (ctx->cache == NULL)
260 goto out;
261 cso_cache_set_sanitize_callback(ctx->cache,
262 sanitize_hash,
263 ctx);
264
265 ctx->pipe = pipe;
266 ctx->sample_mask = ~0;
267
268 ctx->aux_vertex_buffer_index = 0; /* 0 for now */
269
270 cso_init_vbuf(ctx);
271
272 /* Enable for testing: */
273 if (0) cso_set_maximum_cache_size( ctx->cache, 4 );
274
275 if (pipe->screen->get_shader_param(pipe->screen, PIPE_SHADER_GEOMETRY,
276 PIPE_SHADER_CAP_MAX_INSTRUCTIONS) > 0) {
277 ctx->has_geometry_shader = TRUE;
278 }
279 if (pipe->screen->get_shader_param(pipe->screen, PIPE_SHADER_TESS_CTRL,
280 PIPE_SHADER_CAP_MAX_INSTRUCTIONS) > 0) {
281 ctx->has_tessellation = TRUE;
282 }
283 if (pipe->screen->get_param(pipe->screen,
284 PIPE_CAP_MAX_STREAM_OUTPUT_BUFFERS) != 0) {
285 ctx->has_streamout = TRUE;
286 }
287
288 return ctx;
289
290 out:
291 cso_destroy_context( ctx );
292 return NULL;
293 }
294
295 /**
296 * Free the CSO context.
297 */
298 void cso_destroy_context( struct cso_context *ctx )
299 {
300 unsigned i, shader;
301
302 if (ctx->pipe) {
303 ctx->pipe->set_index_buffer(ctx->pipe, NULL);
304
305 ctx->pipe->bind_blend_state( ctx->pipe, NULL );
306 ctx->pipe->bind_rasterizer_state( ctx->pipe, NULL );
307
308 {
309 static struct pipe_sampler_view *views[PIPE_MAX_SHADER_SAMPLER_VIEWS] = { NULL };
310 static void *zeros[PIPE_MAX_SAMPLERS] = { NULL };
311 struct pipe_screen *scr = ctx->pipe->screen;
312 unsigned sh;
313 for (sh = 0; sh < PIPE_SHADER_TYPES; sh++) {
314 int maxsam = scr->get_shader_param(scr, sh,
315 PIPE_SHADER_CAP_MAX_TEXTURE_SAMPLERS);
316 int maxview = scr->get_shader_param(scr, sh,
317 PIPE_SHADER_CAP_MAX_SAMPLER_VIEWS);
318 assert(maxsam <= PIPE_MAX_SAMPLERS);
319 assert(maxview <= PIPE_MAX_SHADER_SAMPLER_VIEWS);
320 if (maxsam > 0) {
321 ctx->pipe->bind_sampler_states(ctx->pipe, sh, 0, maxsam, zeros);
322 }
323 if (maxview > 0) {
324 ctx->pipe->set_sampler_views(ctx->pipe, sh, 0, maxview, views);
325 }
326 }
327 }
328
329 ctx->pipe->bind_depth_stencil_alpha_state( ctx->pipe, NULL );
330 ctx->pipe->bind_fs_state( ctx->pipe, NULL );
331 ctx->pipe->set_constant_buffer(ctx->pipe, PIPE_SHADER_FRAGMENT, 0, NULL);
332 ctx->pipe->bind_vs_state( ctx->pipe, NULL );
333 ctx->pipe->set_constant_buffer(ctx->pipe, PIPE_SHADER_VERTEX, 0, NULL);
334 if (ctx->has_geometry_shader) {
335 ctx->pipe->bind_gs_state(ctx->pipe, NULL);
336 ctx->pipe->set_constant_buffer(ctx->pipe, PIPE_SHADER_GEOMETRY, 0, NULL);
337 }
338 if (ctx->has_tessellation) {
339 ctx->pipe->bind_tcs_state(ctx->pipe, NULL);
340 ctx->pipe->set_constant_buffer(ctx->pipe, PIPE_SHADER_TESS_CTRL, 0, NULL);
341 ctx->pipe->bind_tes_state(ctx->pipe, NULL);
342 ctx->pipe->set_constant_buffer(ctx->pipe, PIPE_SHADER_TESS_EVAL, 0, NULL);
343 }
344 ctx->pipe->bind_vertex_elements_state( ctx->pipe, NULL );
345
346 if (ctx->has_streamout)
347 ctx->pipe->set_stream_output_targets(ctx->pipe, 0, NULL, NULL);
348 }
349
350 /* free sampler views for each shader stage */
351 for (shader = 0; shader < Elements(ctx->samplers); shader++) {
352 struct sampler_info *info = &ctx->samplers[shader];
353 for (i = 0; i < PIPE_MAX_SHADER_SAMPLER_VIEWS; i++) {
354 pipe_sampler_view_reference(&info->views[i], NULL);
355 pipe_sampler_view_reference(&info->views_saved[i], NULL);
356 }
357 }
358
359 util_unreference_framebuffer_state(&ctx->fb);
360 util_unreference_framebuffer_state(&ctx->fb_saved);
361
362 pipe_resource_reference(&ctx->aux_vertex_buffer_current.buffer, NULL);
363 pipe_resource_reference(&ctx->aux_vertex_buffer_saved.buffer, NULL);
364
365 for (i = 0; i < PIPE_SHADER_TYPES; i++) {
366 pipe_resource_reference(&ctx->aux_constbuf_current[i].buffer, NULL);
367 pipe_resource_reference(&ctx->aux_constbuf_saved[i].buffer, NULL);
368 }
369
370 for (i = 0; i < PIPE_MAX_SO_BUFFERS; i++) {
371 pipe_so_target_reference(&ctx->so_targets[i], NULL);
372 pipe_so_target_reference(&ctx->so_targets_saved[i], NULL);
373 }
374
375 if (ctx->cache) {
376 cso_cache_delete( ctx->cache );
377 ctx->cache = NULL;
378 }
379
380 if (ctx->vbuf)
381 u_vbuf_destroy(ctx->vbuf);
382 FREE( ctx );
383 }
384
385
386 /* Those function will either find the state of the given template
387 * in the cache or they will create a new state from the given
388 * template, insert it in the cache and return it.
389 */
390
391 /*
392 * If the driver returns 0 from the create method then they will assign
393 * the data member of the cso to be the template itself.
394 */
395
396 enum pipe_error cso_set_blend(struct cso_context *ctx,
397 const struct pipe_blend_state *templ)
398 {
399 unsigned key_size, hash_key;
400 struct cso_hash_iter iter;
401 void *handle;
402
403 key_size = templ->independent_blend_enable ?
404 sizeof(struct pipe_blend_state) :
405 (char *)&(templ->rt[1]) - (char *)templ;
406 hash_key = cso_construct_key((void*)templ, key_size);
407 iter = cso_find_state_template(ctx->cache, hash_key, CSO_BLEND,
408 (void*)templ, key_size);
409
410 if (cso_hash_iter_is_null(iter)) {
411 struct cso_blend *cso = MALLOC(sizeof(struct cso_blend));
412 if (!cso)
413 return PIPE_ERROR_OUT_OF_MEMORY;
414
415 memset(&cso->state, 0, sizeof cso->state);
416 memcpy(&cso->state, templ, key_size);
417 cso->data = ctx->pipe->create_blend_state(ctx->pipe, &cso->state);
418 cso->delete_state = (cso_state_callback)ctx->pipe->delete_blend_state;
419 cso->context = ctx->pipe;
420
421 iter = cso_insert_state(ctx->cache, hash_key, CSO_BLEND, cso);
422 if (cso_hash_iter_is_null(iter)) {
423 FREE(cso);
424 return PIPE_ERROR_OUT_OF_MEMORY;
425 }
426
427 handle = cso->data;
428 }
429 else {
430 handle = ((struct cso_blend *)cso_hash_iter_data(iter))->data;
431 }
432
433 if (ctx->blend != handle) {
434 ctx->blend = handle;
435 ctx->pipe->bind_blend_state(ctx->pipe, handle);
436 }
437 return PIPE_OK;
438 }
439
440 void cso_save_blend(struct cso_context *ctx)
441 {
442 assert(!ctx->blend_saved);
443 ctx->blend_saved = ctx->blend;
444 }
445
446 void cso_restore_blend(struct cso_context *ctx)
447 {
448 if (ctx->blend != ctx->blend_saved) {
449 ctx->blend = ctx->blend_saved;
450 ctx->pipe->bind_blend_state(ctx->pipe, ctx->blend_saved);
451 }
452 ctx->blend_saved = NULL;
453 }
454
455
456
457 enum pipe_error
458 cso_set_depth_stencil_alpha(struct cso_context *ctx,
459 const struct pipe_depth_stencil_alpha_state *templ)
460 {
461 unsigned key_size = sizeof(struct pipe_depth_stencil_alpha_state);
462 unsigned hash_key = cso_construct_key((void*)templ, key_size);
463 struct cso_hash_iter iter = cso_find_state_template(ctx->cache,
464 hash_key,
465 CSO_DEPTH_STENCIL_ALPHA,
466 (void*)templ, key_size);
467 void *handle;
468
469 if (cso_hash_iter_is_null(iter)) {
470 struct cso_depth_stencil_alpha *cso =
471 MALLOC(sizeof(struct cso_depth_stencil_alpha));
472 if (!cso)
473 return PIPE_ERROR_OUT_OF_MEMORY;
474
475 memcpy(&cso->state, templ, sizeof(*templ));
476 cso->data = ctx->pipe->create_depth_stencil_alpha_state(ctx->pipe,
477 &cso->state);
478 cso->delete_state =
479 (cso_state_callback)ctx->pipe->delete_depth_stencil_alpha_state;
480 cso->context = ctx->pipe;
481
482 iter = cso_insert_state(ctx->cache, hash_key,
483 CSO_DEPTH_STENCIL_ALPHA, cso);
484 if (cso_hash_iter_is_null(iter)) {
485 FREE(cso);
486 return PIPE_ERROR_OUT_OF_MEMORY;
487 }
488
489 handle = cso->data;
490 }
491 else {
492 handle = ((struct cso_depth_stencil_alpha *)
493 cso_hash_iter_data(iter))->data;
494 }
495
496 if (ctx->depth_stencil != handle) {
497 ctx->depth_stencil = handle;
498 ctx->pipe->bind_depth_stencil_alpha_state(ctx->pipe, handle);
499 }
500 return PIPE_OK;
501 }
502
503 void cso_save_depth_stencil_alpha(struct cso_context *ctx)
504 {
505 assert(!ctx->depth_stencil_saved);
506 ctx->depth_stencil_saved = ctx->depth_stencil;
507 }
508
509 void cso_restore_depth_stencil_alpha(struct cso_context *ctx)
510 {
511 if (ctx->depth_stencil != ctx->depth_stencil_saved) {
512 ctx->depth_stencil = ctx->depth_stencil_saved;
513 ctx->pipe->bind_depth_stencil_alpha_state(ctx->pipe,
514 ctx->depth_stencil_saved);
515 }
516 ctx->depth_stencil_saved = NULL;
517 }
518
519
520
521 enum pipe_error cso_set_rasterizer(struct cso_context *ctx,
522 const struct pipe_rasterizer_state *templ)
523 {
524 unsigned key_size = sizeof(struct pipe_rasterizer_state);
525 unsigned hash_key = cso_construct_key((void*)templ, key_size);
526 struct cso_hash_iter iter = cso_find_state_template(ctx->cache,
527 hash_key,
528 CSO_RASTERIZER,
529 (void*)templ, key_size);
530 void *handle = NULL;
531
532 if (cso_hash_iter_is_null(iter)) {
533 struct cso_rasterizer *cso = MALLOC(sizeof(struct cso_rasterizer));
534 if (!cso)
535 return PIPE_ERROR_OUT_OF_MEMORY;
536
537 memcpy(&cso->state, templ, sizeof(*templ));
538 cso->data = ctx->pipe->create_rasterizer_state(ctx->pipe, &cso->state);
539 cso->delete_state =
540 (cso_state_callback)ctx->pipe->delete_rasterizer_state;
541 cso->context = ctx->pipe;
542
543 iter = cso_insert_state(ctx->cache, hash_key, CSO_RASTERIZER, cso);
544 if (cso_hash_iter_is_null(iter)) {
545 FREE(cso);
546 return PIPE_ERROR_OUT_OF_MEMORY;
547 }
548
549 handle = cso->data;
550 }
551 else {
552 handle = ((struct cso_rasterizer *)cso_hash_iter_data(iter))->data;
553 }
554
555 if (ctx->rasterizer != handle) {
556 ctx->rasterizer = handle;
557 ctx->pipe->bind_rasterizer_state(ctx->pipe, handle);
558 }
559 return PIPE_OK;
560 }
561
562 void cso_save_rasterizer(struct cso_context *ctx)
563 {
564 assert(!ctx->rasterizer_saved);
565 ctx->rasterizer_saved = ctx->rasterizer;
566 }
567
568 void cso_restore_rasterizer(struct cso_context *ctx)
569 {
570 if (ctx->rasterizer != ctx->rasterizer_saved) {
571 ctx->rasterizer = ctx->rasterizer_saved;
572 ctx->pipe->bind_rasterizer_state(ctx->pipe, ctx->rasterizer_saved);
573 }
574 ctx->rasterizer_saved = NULL;
575 }
576
577
578 void cso_set_fragment_shader_handle(struct cso_context *ctx, void *handle )
579 {
580 if (ctx->fragment_shader != handle) {
581 ctx->fragment_shader = handle;
582 ctx->pipe->bind_fs_state(ctx->pipe, handle);
583 }
584 }
585
586 void cso_delete_fragment_shader(struct cso_context *ctx, void *handle )
587 {
588 if (handle == ctx->fragment_shader) {
589 /* unbind before deleting */
590 ctx->pipe->bind_fs_state(ctx->pipe, NULL);
591 ctx->fragment_shader = NULL;
592 }
593 ctx->pipe->delete_fs_state(ctx->pipe, handle);
594 }
595
596 void cso_save_fragment_shader(struct cso_context *ctx)
597 {
598 assert(!ctx->fragment_shader_saved);
599 ctx->fragment_shader_saved = ctx->fragment_shader;
600 }
601
602 void cso_restore_fragment_shader(struct cso_context *ctx)
603 {
604 if (ctx->fragment_shader_saved != ctx->fragment_shader) {
605 ctx->pipe->bind_fs_state(ctx->pipe, ctx->fragment_shader_saved);
606 ctx->fragment_shader = ctx->fragment_shader_saved;
607 }
608 ctx->fragment_shader_saved = NULL;
609 }
610
611
612 void cso_set_vertex_shader_handle(struct cso_context *ctx, void *handle)
613 {
614 if (ctx->vertex_shader != handle) {
615 ctx->vertex_shader = handle;
616 ctx->pipe->bind_vs_state(ctx->pipe, handle);
617 }
618 }
619
620 void cso_delete_vertex_shader(struct cso_context *ctx, void *handle )
621 {
622 if (handle == ctx->vertex_shader) {
623 /* unbind before deleting */
624 ctx->pipe->bind_vs_state(ctx->pipe, NULL);
625 ctx->vertex_shader = NULL;
626 }
627 ctx->pipe->delete_vs_state(ctx->pipe, handle);
628 }
629
630 void cso_save_vertex_shader(struct cso_context *ctx)
631 {
632 assert(!ctx->vertex_shader_saved);
633 ctx->vertex_shader_saved = ctx->vertex_shader;
634 }
635
636 void cso_restore_vertex_shader(struct cso_context *ctx)
637 {
638 if (ctx->vertex_shader_saved != ctx->vertex_shader) {
639 ctx->pipe->bind_vs_state(ctx->pipe, ctx->vertex_shader_saved);
640 ctx->vertex_shader = ctx->vertex_shader_saved;
641 }
642 ctx->vertex_shader_saved = NULL;
643 }
644
645
646 void cso_set_framebuffer(struct cso_context *ctx,
647 const struct pipe_framebuffer_state *fb)
648 {
649 if (memcmp(&ctx->fb, fb, sizeof(*fb)) != 0) {
650 util_copy_framebuffer_state(&ctx->fb, fb);
651 ctx->pipe->set_framebuffer_state(ctx->pipe, fb);
652 }
653 }
654
655 void cso_save_framebuffer(struct cso_context *ctx)
656 {
657 util_copy_framebuffer_state(&ctx->fb_saved, &ctx->fb);
658 }
659
660 void cso_restore_framebuffer(struct cso_context *ctx)
661 {
662 if (memcmp(&ctx->fb, &ctx->fb_saved, sizeof(ctx->fb))) {
663 util_copy_framebuffer_state(&ctx->fb, &ctx->fb_saved);
664 ctx->pipe->set_framebuffer_state(ctx->pipe, &ctx->fb);
665 util_unreference_framebuffer_state(&ctx->fb_saved);
666 }
667 }
668
669
670 void cso_set_viewport(struct cso_context *ctx,
671 const struct pipe_viewport_state *vp)
672 {
673 if (memcmp(&ctx->vp, vp, sizeof(*vp))) {
674 ctx->vp = *vp;
675 ctx->pipe->set_viewport_states(ctx->pipe, 0, 1, vp);
676 }
677 }
678
679 void cso_save_viewport(struct cso_context *ctx)
680 {
681 ctx->vp_saved = ctx->vp;
682 }
683
684
685 void cso_restore_viewport(struct cso_context *ctx)
686 {
687 if (memcmp(&ctx->vp, &ctx->vp_saved, sizeof(ctx->vp))) {
688 ctx->vp = ctx->vp_saved;
689 ctx->pipe->set_viewport_states(ctx->pipe, 0, 1, &ctx->vp);
690 }
691 }
692
693
694 void cso_set_blend_color(struct cso_context *ctx,
695 const struct pipe_blend_color *bc)
696 {
697 if (memcmp(&ctx->blend_color, bc, sizeof(ctx->blend_color))) {
698 ctx->blend_color = *bc;
699 ctx->pipe->set_blend_color(ctx->pipe, bc);
700 }
701 }
702
703 void cso_set_sample_mask(struct cso_context *ctx, unsigned sample_mask)
704 {
705 if (ctx->sample_mask != sample_mask) {
706 ctx->sample_mask = sample_mask;
707 ctx->pipe->set_sample_mask(ctx->pipe, sample_mask);
708 }
709 }
710
711 void cso_save_sample_mask(struct cso_context *ctx)
712 {
713 ctx->sample_mask_saved = ctx->sample_mask;
714 }
715
716 void cso_restore_sample_mask(struct cso_context *ctx)
717 {
718 cso_set_sample_mask(ctx, ctx->sample_mask_saved);
719 }
720
721 void cso_set_min_samples(struct cso_context *ctx, unsigned min_samples)
722 {
723 if (ctx->min_samples != min_samples && ctx->pipe->set_min_samples) {
724 ctx->min_samples = min_samples;
725 ctx->pipe->set_min_samples(ctx->pipe, min_samples);
726 }
727 }
728
729 void cso_save_min_samples(struct cso_context *ctx)
730 {
731 ctx->min_samples_saved = ctx->min_samples;
732 }
733
734 void cso_restore_min_samples(struct cso_context *ctx)
735 {
736 cso_set_min_samples(ctx, ctx->min_samples_saved);
737 }
738
739 void cso_set_stencil_ref(struct cso_context *ctx,
740 const struct pipe_stencil_ref *sr)
741 {
742 if (memcmp(&ctx->stencil_ref, sr, sizeof(ctx->stencil_ref))) {
743 ctx->stencil_ref = *sr;
744 ctx->pipe->set_stencil_ref(ctx->pipe, sr);
745 }
746 }
747
748 void cso_save_stencil_ref(struct cso_context *ctx)
749 {
750 ctx->stencil_ref_saved = ctx->stencil_ref;
751 }
752
753
754 void cso_restore_stencil_ref(struct cso_context *ctx)
755 {
756 if (memcmp(&ctx->stencil_ref, &ctx->stencil_ref_saved,
757 sizeof(ctx->stencil_ref))) {
758 ctx->stencil_ref = ctx->stencil_ref_saved;
759 ctx->pipe->set_stencil_ref(ctx->pipe, &ctx->stencil_ref);
760 }
761 }
762
763 void cso_set_render_condition(struct cso_context *ctx,
764 struct pipe_query *query,
765 boolean condition, uint mode)
766 {
767 struct pipe_context *pipe = ctx->pipe;
768
769 if (ctx->render_condition != query ||
770 ctx->render_condition_mode != mode ||
771 ctx->render_condition_cond != condition) {
772 pipe->render_condition(pipe, query, condition, mode);
773 ctx->render_condition = query;
774 ctx->render_condition_cond = condition;
775 ctx->render_condition_mode = mode;
776 }
777 }
778
779 void cso_save_render_condition(struct cso_context *ctx)
780 {
781 ctx->render_condition_saved = ctx->render_condition;
782 ctx->render_condition_cond_saved = ctx->render_condition_cond;
783 ctx->render_condition_mode_saved = ctx->render_condition_mode;
784 }
785
786 void cso_restore_render_condition(struct cso_context *ctx)
787 {
788 cso_set_render_condition(ctx, ctx->render_condition_saved,
789 ctx->render_condition_cond_saved,
790 ctx->render_condition_mode_saved);
791 }
792
793 void cso_set_geometry_shader_handle(struct cso_context *ctx, void *handle)
794 {
795 assert(ctx->has_geometry_shader || !handle);
796
797 if (ctx->has_geometry_shader && ctx->geometry_shader != handle) {
798 ctx->geometry_shader = handle;
799 ctx->pipe->bind_gs_state(ctx->pipe, handle);
800 }
801 }
802
803 void cso_delete_geometry_shader(struct cso_context *ctx, void *handle)
804 {
805 if (handle == ctx->geometry_shader) {
806 /* unbind before deleting */
807 ctx->pipe->bind_gs_state(ctx->pipe, NULL);
808 ctx->geometry_shader = NULL;
809 }
810 ctx->pipe->delete_gs_state(ctx->pipe, handle);
811 }
812
813 void cso_save_geometry_shader(struct cso_context *ctx)
814 {
815 if (!ctx->has_geometry_shader) {
816 return;
817 }
818
819 assert(!ctx->geometry_shader_saved);
820 ctx->geometry_shader_saved = ctx->geometry_shader;
821 }
822
823 void cso_restore_geometry_shader(struct cso_context *ctx)
824 {
825 if (!ctx->has_geometry_shader) {
826 return;
827 }
828
829 if (ctx->geometry_shader_saved != ctx->geometry_shader) {
830 ctx->pipe->bind_gs_state(ctx->pipe, ctx->geometry_shader_saved);
831 ctx->geometry_shader = ctx->geometry_shader_saved;
832 }
833 ctx->geometry_shader_saved = NULL;
834 }
835
836 void cso_set_tessctrl_shader_handle(struct cso_context *ctx, void *handle)
837 {
838 assert(ctx->has_tessellation || !handle);
839
840 if (ctx->has_tessellation && ctx->tessctrl_shader != handle) {
841 ctx->tessctrl_shader = handle;
842 ctx->pipe->bind_tcs_state(ctx->pipe, handle);
843 }
844 }
845
846 void cso_delete_tessctrl_shader(struct cso_context *ctx, void *handle)
847 {
848 if (handle == ctx->tessctrl_shader) {
849 /* unbind before deleting */
850 ctx->pipe->bind_tcs_state(ctx->pipe, NULL);
851 ctx->tessctrl_shader = NULL;
852 }
853 ctx->pipe->delete_tcs_state(ctx->pipe, handle);
854 }
855
856 void cso_save_tessctrl_shader(struct cso_context *ctx)
857 {
858 if (!ctx->has_tessellation) {
859 return;
860 }
861
862 assert(!ctx->tessctrl_shader_saved);
863 ctx->tessctrl_shader_saved = ctx->tessctrl_shader;
864 }
865
866 void cso_restore_tessctrl_shader(struct cso_context *ctx)
867 {
868 if (!ctx->has_tessellation) {
869 return;
870 }
871
872 if (ctx->tessctrl_shader_saved != ctx->tessctrl_shader) {
873 ctx->pipe->bind_tcs_state(ctx->pipe, ctx->tessctrl_shader_saved);
874 ctx->tessctrl_shader = ctx->tessctrl_shader_saved;
875 }
876 ctx->tessctrl_shader_saved = NULL;
877 }
878
879 void cso_set_tesseval_shader_handle(struct cso_context *ctx, void *handle)
880 {
881 assert(ctx->has_tessellation || !handle);
882
883 if (ctx->has_tessellation && ctx->tesseval_shader != handle) {
884 ctx->tesseval_shader = handle;
885 ctx->pipe->bind_tes_state(ctx->pipe, handle);
886 }
887 }
888
889 void cso_delete_tesseval_shader(struct cso_context *ctx, void *handle)
890 {
891 if (handle == ctx->tesseval_shader) {
892 /* unbind before deleting */
893 ctx->pipe->bind_tes_state(ctx->pipe, NULL);
894 ctx->tesseval_shader = NULL;
895 }
896 ctx->pipe->delete_tes_state(ctx->pipe, handle);
897 }
898
899 void cso_save_tesseval_shader(struct cso_context *ctx)
900 {
901 if (!ctx->has_tessellation) {
902 return;
903 }
904
905 assert(!ctx->tesseval_shader_saved);
906 ctx->tesseval_shader_saved = ctx->tesseval_shader;
907 }
908
909 void cso_restore_tesseval_shader(struct cso_context *ctx)
910 {
911 if (!ctx->has_tessellation) {
912 return;
913 }
914
915 if (ctx->tesseval_shader_saved != ctx->tesseval_shader) {
916 ctx->pipe->bind_tes_state(ctx->pipe, ctx->tesseval_shader_saved);
917 ctx->tesseval_shader = ctx->tesseval_shader_saved;
918 }
919 ctx->tesseval_shader_saved = NULL;
920 }
921
922 /* clip state */
923
924 static INLINE void
925 clip_state_cpy(struct pipe_clip_state *dst,
926 const struct pipe_clip_state *src)
927 {
928 memcpy(dst->ucp, src->ucp, sizeof(dst->ucp));
929 }
930
931 static INLINE int
932 clip_state_cmp(const struct pipe_clip_state *a,
933 const struct pipe_clip_state *b)
934 {
935 return memcmp(a->ucp, b->ucp, sizeof(a->ucp));
936 }
937
938 void
939 cso_set_clip(struct cso_context *ctx,
940 const struct pipe_clip_state *clip)
941 {
942 if (clip_state_cmp(&ctx->clip, clip)) {
943 clip_state_cpy(&ctx->clip, clip);
944 ctx->pipe->set_clip_state(ctx->pipe, clip);
945 }
946 }
947
948 void
949 cso_save_clip(struct cso_context *ctx)
950 {
951 clip_state_cpy(&ctx->clip_saved, &ctx->clip);
952 }
953
954 void
955 cso_restore_clip(struct cso_context *ctx)
956 {
957 if (clip_state_cmp(&ctx->clip, &ctx->clip_saved)) {
958 clip_state_cpy(&ctx->clip, &ctx->clip_saved);
959 ctx->pipe->set_clip_state(ctx->pipe, &ctx->clip_saved);
960 }
961 }
962
963 enum pipe_error
964 cso_set_vertex_elements(struct cso_context *ctx,
965 unsigned count,
966 const struct pipe_vertex_element *states)
967 {
968 struct u_vbuf *vbuf = ctx->vbuf;
969 unsigned key_size, hash_key;
970 struct cso_hash_iter iter;
971 void *handle;
972 struct cso_velems_state velems_state;
973
974 if (vbuf) {
975 u_vbuf_set_vertex_elements(vbuf, count, states);
976 return PIPE_OK;
977 }
978
979 /* Need to include the count into the stored state data too.
980 * Otherwise first few count pipe_vertex_elements could be identical
981 * even if count is different, and there's no guarantee the hash would
982 * be different in that case neither.
983 */
984 key_size = sizeof(struct pipe_vertex_element) * count + sizeof(unsigned);
985 velems_state.count = count;
986 memcpy(velems_state.velems, states,
987 sizeof(struct pipe_vertex_element) * count);
988 hash_key = cso_construct_key((void*)&velems_state, key_size);
989 iter = cso_find_state_template(ctx->cache, hash_key, CSO_VELEMENTS,
990 (void*)&velems_state, key_size);
991
992 if (cso_hash_iter_is_null(iter)) {
993 struct cso_velements *cso = MALLOC(sizeof(struct cso_velements));
994 if (!cso)
995 return PIPE_ERROR_OUT_OF_MEMORY;
996
997 memcpy(&cso->state, &velems_state, key_size);
998 cso->data = ctx->pipe->create_vertex_elements_state(ctx->pipe, count,
999 &cso->state.velems[0]);
1000 cso->delete_state =
1001 (cso_state_callback) ctx->pipe->delete_vertex_elements_state;
1002 cso->context = ctx->pipe;
1003
1004 iter = cso_insert_state(ctx->cache, hash_key, CSO_VELEMENTS, cso);
1005 if (cso_hash_iter_is_null(iter)) {
1006 FREE(cso);
1007 return PIPE_ERROR_OUT_OF_MEMORY;
1008 }
1009
1010 handle = cso->data;
1011 }
1012 else {
1013 handle = ((struct cso_velements *)cso_hash_iter_data(iter))->data;
1014 }
1015
1016 if (ctx->velements != handle) {
1017 ctx->velements = handle;
1018 ctx->pipe->bind_vertex_elements_state(ctx->pipe, handle);
1019 }
1020 return PIPE_OK;
1021 }
1022
1023 void cso_save_vertex_elements(struct cso_context *ctx)
1024 {
1025 struct u_vbuf *vbuf = ctx->vbuf;
1026
1027 if (vbuf) {
1028 u_vbuf_save_vertex_elements(vbuf);
1029 return;
1030 }
1031
1032 assert(!ctx->velements_saved);
1033 ctx->velements_saved = ctx->velements;
1034 }
1035
1036 void cso_restore_vertex_elements(struct cso_context *ctx)
1037 {
1038 struct u_vbuf *vbuf = ctx->vbuf;
1039
1040 if (vbuf) {
1041 u_vbuf_restore_vertex_elements(vbuf);
1042 return;
1043 }
1044
1045 if (ctx->velements != ctx->velements_saved) {
1046 ctx->velements = ctx->velements_saved;
1047 ctx->pipe->bind_vertex_elements_state(ctx->pipe, ctx->velements_saved);
1048 }
1049 ctx->velements_saved = NULL;
1050 }
1051
1052 /* vertex buffers */
1053
1054 void cso_set_vertex_buffers(struct cso_context *ctx,
1055 unsigned start_slot, unsigned count,
1056 const struct pipe_vertex_buffer *buffers)
1057 {
1058 struct u_vbuf *vbuf = ctx->vbuf;
1059
1060 if (vbuf) {
1061 u_vbuf_set_vertex_buffers(vbuf, start_slot, count, buffers);
1062 return;
1063 }
1064
1065 /* Save what's in the auxiliary slot, so that we can save and restore it
1066 * for meta ops. */
1067 if (start_slot <= ctx->aux_vertex_buffer_index &&
1068 start_slot+count > ctx->aux_vertex_buffer_index) {
1069 if (buffers) {
1070 const struct pipe_vertex_buffer *vb =
1071 buffers + (ctx->aux_vertex_buffer_index - start_slot);
1072
1073 pipe_resource_reference(&ctx->aux_vertex_buffer_current.buffer,
1074 vb->buffer);
1075 memcpy(&ctx->aux_vertex_buffer_current, vb,
1076 sizeof(struct pipe_vertex_buffer));
1077 }
1078 else {
1079 pipe_resource_reference(&ctx->aux_vertex_buffer_current.buffer,
1080 NULL);
1081 ctx->aux_vertex_buffer_current.user_buffer = NULL;
1082 }
1083 }
1084
1085 ctx->pipe->set_vertex_buffers(ctx->pipe, start_slot, count, buffers);
1086 }
1087
1088 void cso_save_aux_vertex_buffer_slot(struct cso_context *ctx)
1089 {
1090 struct u_vbuf *vbuf = ctx->vbuf;
1091
1092 if (vbuf) {
1093 u_vbuf_save_aux_vertex_buffer_slot(vbuf);
1094 return;
1095 }
1096
1097 pipe_resource_reference(&ctx->aux_vertex_buffer_saved.buffer,
1098 ctx->aux_vertex_buffer_current.buffer);
1099 memcpy(&ctx->aux_vertex_buffer_saved, &ctx->aux_vertex_buffer_current,
1100 sizeof(struct pipe_vertex_buffer));
1101 }
1102
1103 void cso_restore_aux_vertex_buffer_slot(struct cso_context *ctx)
1104 {
1105 struct u_vbuf *vbuf = ctx->vbuf;
1106
1107 if (vbuf) {
1108 u_vbuf_restore_aux_vertex_buffer_slot(vbuf);
1109 return;
1110 }
1111
1112 cso_set_vertex_buffers(ctx, ctx->aux_vertex_buffer_index, 1,
1113 &ctx->aux_vertex_buffer_saved);
1114 pipe_resource_reference(&ctx->aux_vertex_buffer_saved.buffer, NULL);
1115 }
1116
1117 unsigned cso_get_aux_vertex_buffer_slot(struct cso_context *ctx)
1118 {
1119 return ctx->aux_vertex_buffer_index;
1120 }
1121
1122
1123 /**************** fragment/vertex sampler view state *************************/
1124
1125 static enum pipe_error
1126 single_sampler(struct cso_context *ctx,
1127 struct sampler_info *info,
1128 unsigned idx,
1129 const struct pipe_sampler_state *templ)
1130 {
1131 void *handle = NULL;
1132
1133 if (templ != NULL) {
1134 unsigned key_size = sizeof(struct pipe_sampler_state);
1135 unsigned hash_key = cso_construct_key((void*)templ, key_size);
1136 struct cso_hash_iter iter =
1137 cso_find_state_template(ctx->cache,
1138 hash_key, CSO_SAMPLER,
1139 (void *) templ, key_size);
1140
1141 if (cso_hash_iter_is_null(iter)) {
1142 struct cso_sampler *cso = MALLOC(sizeof(struct cso_sampler));
1143 if (!cso)
1144 return PIPE_ERROR_OUT_OF_MEMORY;
1145
1146 memcpy(&cso->state, templ, sizeof(*templ));
1147 cso->data = ctx->pipe->create_sampler_state(ctx->pipe, &cso->state);
1148 cso->delete_state =
1149 (cso_state_callback) ctx->pipe->delete_sampler_state;
1150 cso->context = ctx->pipe;
1151
1152 iter = cso_insert_state(ctx->cache, hash_key, CSO_SAMPLER, cso);
1153 if (cso_hash_iter_is_null(iter)) {
1154 FREE(cso);
1155 return PIPE_ERROR_OUT_OF_MEMORY;
1156 }
1157
1158 handle = cso->data;
1159 }
1160 else {
1161 handle = ((struct cso_sampler *)cso_hash_iter_data(iter))->data;
1162 }
1163 }
1164
1165 info->samplers[idx] = handle;
1166
1167 return PIPE_OK;
1168 }
1169
1170 enum pipe_error
1171 cso_single_sampler(struct cso_context *ctx,
1172 unsigned shader_stage,
1173 unsigned idx,
1174 const struct pipe_sampler_state *templ)
1175 {
1176 return single_sampler(ctx, &ctx->samplers[shader_stage], idx, templ);
1177 }
1178
1179
1180
1181 static void
1182 single_sampler_done(struct cso_context *ctx, unsigned shader_stage)
1183 {
1184 struct sampler_info *info = &ctx->samplers[shader_stage];
1185 unsigned i;
1186
1187 /* find highest non-null sampler */
1188 for (i = PIPE_MAX_SAMPLERS; i > 0; i--) {
1189 if (info->samplers[i - 1] != NULL)
1190 break;
1191 }
1192
1193 info->nr_samplers = i;
1194
1195 if (info->hw.nr_samplers != info->nr_samplers ||
1196 memcmp(info->hw.samplers,
1197 info->samplers,
1198 info->nr_samplers * sizeof(void *)) != 0)
1199 {
1200 memcpy(info->hw.samplers,
1201 info->samplers,
1202 info->nr_samplers * sizeof(void *));
1203
1204 /* set remaining slots/pointers to null */
1205 for (i = info->nr_samplers; i < info->hw.nr_samplers; i++)
1206 info->samplers[i] = NULL;
1207
1208 ctx->pipe->bind_sampler_states(ctx->pipe, shader_stage, 0,
1209 MAX2(info->nr_samplers,
1210 info->hw.nr_samplers),
1211 info->samplers);
1212
1213 info->hw.nr_samplers = info->nr_samplers;
1214 }
1215 }
1216
1217 void
1218 cso_single_sampler_done(struct cso_context *ctx, unsigned shader_stage)
1219 {
1220 single_sampler_done(ctx, shader_stage);
1221 }
1222
1223
1224 /*
1225 * If the function encouters any errors it will return the
1226 * last one. Done to always try to set as many samplers
1227 * as possible.
1228 */
1229 enum pipe_error
1230 cso_set_samplers(struct cso_context *ctx,
1231 unsigned shader_stage,
1232 unsigned nr,
1233 const struct pipe_sampler_state **templates)
1234 {
1235 struct sampler_info *info = &ctx->samplers[shader_stage];
1236 unsigned i;
1237 enum pipe_error temp, error = PIPE_OK;
1238
1239 /* TODO: fastpath
1240 */
1241
1242 for (i = 0; i < nr; i++) {
1243 temp = single_sampler(ctx, info, i, templates[i]);
1244 if (temp != PIPE_OK)
1245 error = temp;
1246 }
1247
1248 for ( ; i < info->nr_samplers; i++) {
1249 temp = single_sampler(ctx, info, i, NULL);
1250 if (temp != PIPE_OK)
1251 error = temp;
1252 }
1253
1254 single_sampler_done(ctx, shader_stage);
1255
1256 return error;
1257 }
1258
1259 void
1260 cso_save_samplers(struct cso_context *ctx, unsigned shader_stage)
1261 {
1262 struct sampler_info *info = &ctx->samplers[shader_stage];
1263 info->nr_samplers_saved = info->nr_samplers;
1264 memcpy(info->samplers_saved, info->samplers, sizeof(info->samplers));
1265 }
1266
1267
1268 void
1269 cso_restore_samplers(struct cso_context *ctx, unsigned shader_stage)
1270 {
1271 struct sampler_info *info = &ctx->samplers[shader_stage];
1272 info->nr_samplers = info->nr_samplers_saved;
1273 memcpy(info->samplers, info->samplers_saved, sizeof(info->samplers));
1274 single_sampler_done(ctx, shader_stage);
1275 }
1276
1277
1278 void
1279 cso_set_sampler_views(struct cso_context *ctx,
1280 unsigned shader_stage,
1281 unsigned count,
1282 struct pipe_sampler_view **views)
1283 {
1284 struct sampler_info *info = &ctx->samplers[shader_stage];
1285 unsigned i;
1286 boolean any_change = FALSE;
1287
1288 /* reference new views */
1289 for (i = 0; i < count; i++) {
1290 any_change |= info->views[i] != views[i];
1291 pipe_sampler_view_reference(&info->views[i], views[i]);
1292 }
1293 /* unref extra old views, if any */
1294 for (; i < info->nr_views; i++) {
1295 any_change |= info->views[i] != NULL;
1296 pipe_sampler_view_reference(&info->views[i], NULL);
1297 }
1298
1299 /* bind the new sampler views */
1300 if (any_change) {
1301 ctx->pipe->set_sampler_views(ctx->pipe, shader_stage, 0,
1302 MAX2(info->nr_views, count),
1303 info->views);
1304 }
1305
1306 info->nr_views = count;
1307 }
1308
1309
1310 void
1311 cso_save_sampler_views(struct cso_context *ctx, unsigned shader_stage)
1312 {
1313 struct sampler_info *info = &ctx->samplers[shader_stage];
1314 unsigned i;
1315
1316 info->nr_views_saved = info->nr_views;
1317
1318 for (i = 0; i < info->nr_views; i++) {
1319 assert(!info->views_saved[i]);
1320 pipe_sampler_view_reference(&info->views_saved[i], info->views[i]);
1321 }
1322 }
1323
1324
1325 void
1326 cso_restore_sampler_views(struct cso_context *ctx, unsigned shader_stage)
1327 {
1328 struct sampler_info *info = &ctx->samplers[shader_stage];
1329 unsigned i, nr_saved = info->nr_views_saved;
1330 unsigned num;
1331
1332 for (i = 0; i < nr_saved; i++) {
1333 pipe_sampler_view_reference(&info->views[i], NULL);
1334 /* move the reference from one pointer to another */
1335 info->views[i] = info->views_saved[i];
1336 info->views_saved[i] = NULL;
1337 }
1338 for (; i < info->nr_views; i++) {
1339 pipe_sampler_view_reference(&info->views[i], NULL);
1340 }
1341
1342 num = MAX2(info->nr_views, nr_saved);
1343
1344 /* bind the old/saved sampler views */
1345 ctx->pipe->set_sampler_views(ctx->pipe, shader_stage, 0, num, info->views);
1346
1347 info->nr_views = nr_saved;
1348 info->nr_views_saved = 0;
1349 }
1350
1351
1352 void
1353 cso_set_stream_outputs(struct cso_context *ctx,
1354 unsigned num_targets,
1355 struct pipe_stream_output_target **targets,
1356 const unsigned *offsets)
1357 {
1358 struct pipe_context *pipe = ctx->pipe;
1359 uint i;
1360
1361 if (!ctx->has_streamout) {
1362 assert(num_targets == 0);
1363 return;
1364 }
1365
1366 if (ctx->nr_so_targets == 0 && num_targets == 0) {
1367 /* Nothing to do. */
1368 return;
1369 }
1370
1371 /* reference new targets */
1372 for (i = 0; i < num_targets; i++) {
1373 pipe_so_target_reference(&ctx->so_targets[i], targets[i]);
1374 }
1375 /* unref extra old targets, if any */
1376 for (; i < ctx->nr_so_targets; i++) {
1377 pipe_so_target_reference(&ctx->so_targets[i], NULL);
1378 }
1379
1380 pipe->set_stream_output_targets(pipe, num_targets, targets,
1381 offsets);
1382 ctx->nr_so_targets = num_targets;
1383 }
1384
1385 void
1386 cso_save_stream_outputs(struct cso_context *ctx)
1387 {
1388 uint i;
1389
1390 if (!ctx->has_streamout) {
1391 return;
1392 }
1393
1394 ctx->nr_so_targets_saved = ctx->nr_so_targets;
1395
1396 for (i = 0; i < ctx->nr_so_targets; i++) {
1397 assert(!ctx->so_targets_saved[i]);
1398 pipe_so_target_reference(&ctx->so_targets_saved[i], ctx->so_targets[i]);
1399 }
1400 }
1401
1402 void
1403 cso_restore_stream_outputs(struct cso_context *ctx)
1404 {
1405 struct pipe_context *pipe = ctx->pipe;
1406 uint i;
1407 unsigned offset[PIPE_MAX_SO_BUFFERS];
1408
1409 if (!ctx->has_streamout) {
1410 return;
1411 }
1412
1413 if (ctx->nr_so_targets == 0 && ctx->nr_so_targets_saved == 0) {
1414 /* Nothing to do. */
1415 return;
1416 }
1417
1418 assert(ctx->nr_so_targets_saved <= PIPE_MAX_SO_BUFFERS);
1419 for (i = 0; i < ctx->nr_so_targets_saved; i++) {
1420 pipe_so_target_reference(&ctx->so_targets[i], NULL);
1421 /* move the reference from one pointer to another */
1422 ctx->so_targets[i] = ctx->so_targets_saved[i];
1423 ctx->so_targets_saved[i] = NULL;
1424 /* -1 means append */
1425 offset[i] = (unsigned)-1;
1426 }
1427 for (; i < ctx->nr_so_targets; i++) {
1428 pipe_so_target_reference(&ctx->so_targets[i], NULL);
1429 }
1430
1431 pipe->set_stream_output_targets(pipe, ctx->nr_so_targets_saved,
1432 ctx->so_targets, offset);
1433
1434 ctx->nr_so_targets = ctx->nr_so_targets_saved;
1435 ctx->nr_so_targets_saved = 0;
1436 }
1437
1438 /* constant buffers */
1439
1440 void
1441 cso_set_constant_buffer(struct cso_context *cso, unsigned shader_stage,
1442 unsigned index, struct pipe_constant_buffer *cb)
1443 {
1444 struct pipe_context *pipe = cso->pipe;
1445
1446 pipe->set_constant_buffer(pipe, shader_stage, index, cb);
1447
1448 if (index == 0) {
1449 util_copy_constant_buffer(&cso->aux_constbuf_current[shader_stage], cb);
1450 }
1451 }
1452
1453 void
1454 cso_set_constant_buffer_resource(struct cso_context *cso,
1455 unsigned shader_stage,
1456 unsigned index,
1457 struct pipe_resource *buffer)
1458 {
1459 if (buffer) {
1460 struct pipe_constant_buffer cb;
1461 cb.buffer = buffer;
1462 cb.buffer_offset = 0;
1463 cb.buffer_size = buffer->width0;
1464 cb.user_buffer = NULL;
1465 cso_set_constant_buffer(cso, shader_stage, index, &cb);
1466 } else {
1467 cso_set_constant_buffer(cso, shader_stage, index, NULL);
1468 }
1469 }
1470
1471 void
1472 cso_save_constant_buffer_slot0(struct cso_context *cso,
1473 unsigned shader_stage)
1474 {
1475 util_copy_constant_buffer(&cso->aux_constbuf_saved[shader_stage],
1476 &cso->aux_constbuf_current[shader_stage]);
1477 }
1478
1479 void
1480 cso_restore_constant_buffer_slot0(struct cso_context *cso,
1481 unsigned shader_stage)
1482 {
1483 cso_set_constant_buffer(cso, shader_stage, 0,
1484 &cso->aux_constbuf_saved[shader_stage]);
1485 pipe_resource_reference(&cso->aux_constbuf_saved[shader_stage].buffer,
1486 NULL);
1487 }
1488
1489 /* drawing */
1490
1491 void
1492 cso_set_index_buffer(struct cso_context *cso,
1493 const struct pipe_index_buffer *ib)
1494 {
1495 struct u_vbuf *vbuf = cso->vbuf;
1496
1497 if (vbuf) {
1498 u_vbuf_set_index_buffer(vbuf, ib);
1499 } else {
1500 struct pipe_context *pipe = cso->pipe;
1501 pipe->set_index_buffer(pipe, ib);
1502 }
1503 }
1504
1505 void
1506 cso_draw_vbo(struct cso_context *cso,
1507 const struct pipe_draw_info *info)
1508 {
1509 struct u_vbuf *vbuf = cso->vbuf;
1510
1511 if (vbuf) {
1512 u_vbuf_draw_vbo(vbuf, info);
1513 } else {
1514 struct pipe_context *pipe = cso->pipe;
1515 pipe->draw_vbo(pipe, info);
1516 }
1517 }
1518
1519 void
1520 cso_draw_arrays(struct cso_context *cso, uint mode, uint start, uint count)
1521 {
1522 struct pipe_draw_info info;
1523
1524 util_draw_init_info(&info);
1525
1526 info.mode = mode;
1527 info.start = start;
1528 info.count = count;
1529 info.min_index = start;
1530 info.max_index = start + count - 1;
1531
1532 cso_draw_vbo(cso, &info);
1533 }
1534
1535 void
1536 cso_draw_arrays_instanced(struct cso_context *cso, uint mode,
1537 uint start, uint count,
1538 uint start_instance, uint instance_count)
1539 {
1540 struct pipe_draw_info info;
1541
1542 util_draw_init_info(&info);
1543
1544 info.mode = mode;
1545 info.start = start;
1546 info.count = count;
1547 info.min_index = start;
1548 info.max_index = start + count - 1;
1549 info.start_instance = start_instance;
1550 info.instance_count = instance_count;
1551
1552 cso_draw_vbo(cso, &info);
1553 }