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