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