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