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