diff options
| author | Zack Rusin <zack@tungstengraphics.com> | 2007-09-14 04:08:58 -0400 | 
|---|---|---|
| committer | Zack Rusin <zack@tungstengraphics.com> | 2007-09-18 06:31:22 -0400 | 
| commit | 9780327c5d95586a88fce94d7b47342355ead118 (patch) | |
| tree | 9007ea135504d8fd90b49a391a43fa579b9374b5 /src/mesa | |
| parent | ffacb1c12a77d71613e8171e31ffc348959881e4 (diff) | |
First stab at immutable state objects (create/bind/delete)
We want our state objects to be immutable, handled via the
create/bind/delete calls instead of struct propagation.
Only implementing the blend state to see how it would look like
and work.
Diffstat (limited to 'src/mesa')
23 files changed, 382 insertions, 59 deletions
| diff --git a/src/mesa/cso_cache/cso_cache.c b/src/mesa/cso_cache/cso_cache.c new file mode 100644 index 0000000000..bb853308be --- /dev/null +++ b/src/mesa/cso_cache/cso_cache.c @@ -0,0 +1,176 @@ +/************************************************************************** + * + * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +/* Authors:  Zack Rusin <zack@tungstengraphics.com> + */ + +#include "cso_cache.h" + +#if 1 +static unsigned hash_key( const void *key, unsigned key_size ) +{ +   unsigned *ikey = (unsigned *)key; +   unsigned hash = 0, i; + +   assert(key_size % 4 == 0); + +   /* I'm sure this can be improved on: +    */ +   for (i = 0; i < key_size/4; i++) +      hash ^= ikey[i]; + +   return hash; +} +#else +static unsigned hash_key(const unsigned char *p, int n) +{ +   unsigned h = 0; +   unsigned g; + +   while (n--) { +      h = (h << 4) + *p++; +      if ((g = (h & 0xf0000000)) != 0) +         h ^= g >> 23; +      h &= ~g; +   } +   return h; +} +#endif + +unsigned cso_construct_key(void *item, int item_size) +{ +   return hash_key((const unsigned char*)(item), item_size); +} + +struct cso_cache_item * +cso_insert_state(struct cso_cache *sc, +                 unsigned hash_key, +                 void *state, int state_size) +{ +   struct cso_cache_item *found_state = +      _mesa_HashLookup(sc->hash, hash_key); +   struct cso_cache_item *item = +      malloc(sizeof(struct cso_cache_item)); +   _mesa_printf("inserting state ========= key = %d\n", hash_key); +   item->key        = hash_key; +   item->state_size = state_size; +   item->state      = state; +   item->next       = 0; + +   if (found_state) { +      while (found_state->next) +         found_state = found_state->next; +      found_state->next = item; +   } else +      _mesa_HashInsert(sc->hash, hash_key, item); +   return item; +} + +struct cso_cache_item * +cso_find_state(struct cso_cache *sc, +               unsigned hash_key, +               void *state, int state_size) +{ +   struct cso_cache_item *found_state = +      _mesa_HashLookup(sc->hash, hash_key); + +   while (found_state && +          (found_state->state_size != state_size || +           memcmp(found_state->state, state, state_size))) { +      found_state = found_state->next; +   } + +   _mesa_printf("finding state  ========== %d (%p)\n", hash_key, found_state); +   return found_state; +} + +struct cso_cache_item * +cso_remove_state(struct cso_cache *sc, +                 unsigned hash_key, +                 void *state, int state_size) +{ +   struct cso_cache_item *found_state = +      _mesa_HashLookup(sc->hash, hash_key); +   struct cso_cache_item *prev = 0; + +   while (found_state && +          (found_state->state_size != state_size || +           memcmp(found_state->state, state, state_size))) { +      prev = found_state; +      found_state = found_state->next; +   } +   if (found_state) { +      if (prev) +         prev->next = found_state->next; +      else { +         if (found_state->next) +            _mesa_HashInsert(sc->hash, hash_key, found_state->next); +         else +            _mesa_HashRemove(sc->hash, hash_key); +      } +   } +   return found_state; +} + +struct cso_cache *cso_cache_create(void) +{ +   struct cso_cache *sc = malloc(sizeof(struct cso_cache)); + +   sc->hash = _mesa_NewHashTable(); + +   return sc; +} + +void cso_cache_destroy(struct cso_cache *sc) +{ +   assert(sc); +   assert(sc->hash); +   _mesa_DeleteHashTable(sc->hash); +   free(sc); +} + +/* This function will either find the state of the given template + * in the cache or it will create a new state state from the given + * template, will insert it in the cache and return it. + */ +struct pipe_blend_state * cso_cached_blend_state( +   struct st_context *st, +   const struct pipe_blend_state *blend) +{ +   unsigned hash_key = cso_construct_key((void*)blend, sizeof(struct pipe_blend_state)); +   struct cso_cache_item *cache_item = cso_find_state(st->cache, +                                                      hash_key, +                                                      (void*)blend, +                                                      sizeof(struct pipe_blend_state)); +   if (!cache_item) { +      const struct pipe_blend_state *created_state = st->pipe->create_blend_state( +         st->pipe, blend); +      cache_item = cso_insert_state(st->cache, hash_key, +                                    (void*)created_state, sizeof(struct pipe_blend_state)); +   } +   return (struct pipe_blend_state*)cache_item->state; +} diff --git a/src/mesa/cso_cache/cso_cache.h b/src/mesa/cso_cache/cso_cache.h new file mode 100644 index 0000000000..ca0a2d576a --- /dev/null +++ b/src/mesa/cso_cache/cso_cache.h @@ -0,0 +1,75 @@ +/************************************************************************** + * + * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + + /* +  * Authors: +  *   Zack Rusin <zack@tungstengraphics.com> +  */ + +#ifndef CSO_CACHE_H +#define CSO_CACHE_H + +#include "state_tracker/st_context.h" +#include "pipe/p_context.h" +#include "pipe/p_state.h" + + +#include "main/hash.h" + +struct cso_cache_item { +   unsigned key; + +   unsigned    state_size; +   const void *state; + +   struct cso_cache_item *next; +}; + +struct cso_cache { +   struct _mesa_HashTable *hash; +}; + +void cso_cache_destroy(struct cso_cache *sc); +struct cso_cache *cso_cache_create(void); + +unsigned cso_construct_key(void *item, int item_size); + +struct cso_cache_item *cso_insert_state(struct cso_cache *sc, +                                                   unsigned hash_key, +                                                   void *state, int state_size); +struct cso_cache_item *cso_find_state(struct cso_cache *sc, +                                                 unsigned hash_key, +                                                 void *state, int state_size); +struct cso_cache_item *cso_remove_state(struct cso_cache *sc, +                                                   unsigned hash_key, +                                                   void *state, int state_size); + +struct pipe_blend_state *cso_cached_blend_state( +    struct st_context *pipe, +    const struct pipe_blend_state *state); + +#endif diff --git a/src/mesa/pipe/failover/fo_context.h b/src/mesa/pipe/failover/fo_context.h index 5666d4e830..b065aa832a 100644 --- a/src/mesa/pipe/failover/fo_context.h +++ b/src/mesa/pipe/failover/fo_context.h @@ -67,8 +67,9 @@ struct failover_context {     /* The most recent drawing state as set by the driver:      */ +   const struct pipe_blend_state *blend; +     struct pipe_alpha_test_state alpha_test; -   struct pipe_blend_state blend;     struct pipe_blend_color blend_color;     struct pipe_clear_color_state clear_color;     struct pipe_clip_state clip; diff --git a/src/mesa/pipe/failover/fo_state.c b/src/mesa/pipe/failover/fo_state.c index 097acf7d57..2357d7ef5c 100644 --- a/src/mesa/pipe/failover/fo_state.c +++ b/src/mesa/pipe/failover/fo_state.c @@ -58,14 +58,14 @@ failover_set_alpha_test_state(struct pipe_context *pipe,  static void  -failover_set_blend_state( struct pipe_context *pipe, +failover_bind_blend_state( struct pipe_context *pipe,  			  const struct pipe_blend_state *blend )  {     struct failover_context *failover = failover_context(pipe); -   failover->blend = *blend; +   failover->blend = blend;     failover->dirty |= FO_NEW_BLEND; -   failover->hw->set_blend_state( failover->hw, blend ); +   failover->hw->bind_blend_state( failover->hw, blend );  } @@ -266,9 +266,10 @@ failover_set_vertex_element(struct pipe_context *pipe,  void  failover_init_state_functions( struct failover_context *failover )  { +   failover->pipe.bind_blend_state = failover_bind_blend_state; +     failover->pipe.set_alpha_test_state = failover_set_alpha_test_state;     failover->pipe.set_blend_color = failover_set_blend_color; -   failover->pipe.set_blend_state = failover_set_blend_state;     failover->pipe.set_clip_state = failover_set_clip_state;     failover->pipe.set_clear_color_state = failover_set_clear_color_state;     failover->pipe.set_depth_state = failover_set_depth_test_state; diff --git a/src/mesa/pipe/failover/fo_state_emit.c b/src/mesa/pipe/failover/fo_state_emit.c index 52fcf5dbc9..77413d100b 100644 --- a/src/mesa/pipe/failover/fo_state_emit.c +++ b/src/mesa/pipe/failover/fo_state_emit.c @@ -59,7 +59,7 @@ failover_state_emit( struct failover_context *failover )        failover->sw->set_alpha_test_state( failover->sw, &failover->alpha_test );     if (failover->dirty & FO_NEW_BLEND) -      failover->sw->set_blend_state( failover->sw, &failover->blend ); +      failover->sw->bind_blend_state( failover->sw, failover->blend );     if (failover->dirty & FO_NEW_BLEND_COLOR)        failover->sw->set_blend_color( failover->sw, &failover->blend_color ); diff --git a/src/mesa/pipe/i915simple/i915_context.h b/src/mesa/pipe/i915simple/i915_context.h index c30c79d83c..215c5294fa 100644 --- a/src/mesa/pipe/i915simple/i915_context.h +++ b/src/mesa/pipe/i915simple/i915_context.h @@ -123,8 +123,9 @@ struct i915_context     /* The most recent drawing state as set by the driver:      */ +   const struct pipe_blend_state *blend; +     struct pipe_alpha_test_state alpha_test; -   struct pipe_blend_state blend;     struct pipe_blend_color blend_color;     struct pipe_clear_color_state clear_color;     struct pipe_clip_state clip; diff --git a/src/mesa/pipe/i915simple/i915_state.c b/src/mesa/pipe/i915simple/i915_state.c index f5ea721cc8..478988fd4a 100644 --- a/src/mesa/pipe/i915simple/i915_state.c +++ b/src/mesa/pipe/i915simple/i915_state.c @@ -37,17 +37,37 @@  /* None of this state is actually used for anything yet.   */ -static void i915_set_blend_state( struct pipe_context *pipe, + +static const struct pipe_blend_state * +i915_create_blend_state(struct pipe_context *pipe, +                        const struct pipe_blend_state *blend) +{ +   /*struct i915_context *i915 = i915_context(pipe);*/ + +   struct pipe_blend_state *new_blend = malloc(sizeof(struct pipe_blend_state)); +   memcpy(new_blend, blend, sizeof(struct pipe_blend_state)); + +   return new_blend; +} + +static void i915_bind_blend_state( struct pipe_context *pipe,  			     const struct pipe_blend_state *blend )  {     struct i915_context *i915 = i915_context(pipe); -   i915->blend = *blend; +   i915->blend = blend;     i915->dirty |= I915_NEW_BLEND;  } +static void i915_delete_blend_state( struct pipe_context *pipe, +			     const struct pipe_blend_state *blend ) +{ +   /*struct i915_context *i915 = i915_context(pipe);*/ +   free(blend); +} +  static void i915_set_blend_color( struct pipe_context *pipe,  			     const struct pipe_blend_color *blend_color )  { @@ -289,9 +309,12 @@ static void i915_set_vertex_element( struct pipe_context *pipe,  void  i915_init_state_functions( struct i915_context *i915 )  { +   i915->pipe.create_blend_state = i915_create_blend_state; +   i915->pipe.bind_blend_state = i915_bind_blend_state; +   i915->pipe.delete_blend_state = i915_delete_blend_state; +     i915->pipe.set_alpha_test_state = i915_set_alpha_test_state;     i915->pipe.set_blend_color = i915_set_blend_color; -   i915->pipe.set_blend_state = i915_set_blend_state;     i915->pipe.set_clip_state = i915_set_clip_state;     i915->pipe.set_clear_color_state = i915_set_clear_color_state;     i915->pipe.set_constant_buffer = i915_set_constant_buffer; diff --git a/src/mesa/pipe/i915simple/i915_state_dynamic.c b/src/mesa/pipe/i915simple/i915_state_dynamic.c index e648357754..49a30fac11 100644 --- a/src/mesa/pipe/i915simple/i915_state_dynamic.c +++ b/src/mesa/pipe/i915simple/i915_state_dynamic.c @@ -82,7 +82,7 @@ static void upload_MODES4( struct i915_context *i915 )     {        modes4 |= (_3DSTATE_MODES_4_CMD |  		 ENABLE_LOGIC_OP_FUNC | -		 LOGIC_OP_FUNC(i915_translate_logic_op(i915->blend.logicop_func))); +		 LOGIC_OP_FUNC(i915_translate_logic_op(i915->blend->logicop_func)));     }     /* Always, so that we know when state is in-active:  @@ -204,13 +204,13 @@ static void upload_IAB( struct i915_context *i915 )     unsigned iab = 0;     { -      unsigned eqRGB  = i915->blend.rgb_func; -      unsigned srcRGB = i915->blend.rgb_src_factor; -      unsigned dstRGB = i915->blend.rgb_dst_factor; +      unsigned eqRGB  = i915->blend->rgb_func; +      unsigned srcRGB = i915->blend->rgb_src_factor; +      unsigned dstRGB = i915->blend->rgb_dst_factor; -      unsigned eqA    = i915->blend.alpha_func; -      unsigned srcA   = i915->blend.alpha_src_factor; -      unsigned dstA   = i915->blend.alpha_dst_factor; +      unsigned eqA    = i915->blend->alpha_func; +      unsigned srcA   = i915->blend->alpha_src_factor; +      unsigned dstA   = i915->blend->alpha_dst_factor;        /* Special handling for MIN/MAX filter modes handled at         * state_tracker level. diff --git a/src/mesa/pipe/i915simple/i915_state_immediate.c b/src/mesa/pipe/i915simple/i915_state_immediate.c index 38a24733e1..aaca534f5a 100644 --- a/src/mesa/pipe/i915simple/i915_state_immediate.c +++ b/src/mesa/pipe/i915simple/i915_state_immediate.c @@ -145,22 +145,22 @@ static void upload_S5( struct i915_context *i915 )     }     /* I915_NEW_BLEND */ -   if (i915->blend.logicop_enable)  +   if (i915->blend->logicop_enable)         LIS5 |= S5_LOGICOP_ENABLE; -   if (i915->blend.dither)  +   if (i915->blend->dither)         LIS5 |= S5_COLOR_DITHER_ENABLE; -   if ((i915->blend.colormask & PIPE_MASK_R) == 0) +   if ((i915->blend->colormask & PIPE_MASK_R) == 0)        LIS5 |= S5_WRITEDISABLE_RED; -   if ((i915->blend.colormask & PIPE_MASK_G) == 0) +   if ((i915->blend->colormask & PIPE_MASK_G) == 0)        LIS5 |= S5_WRITEDISABLE_GREEN; -   if ((i915->blend.colormask & PIPE_MASK_B) == 0) +   if ((i915->blend->colormask & PIPE_MASK_B) == 0)        LIS5 |= S5_WRITEDISABLE_BLUE; -   if ((i915->blend.colormask & PIPE_MASK_A) == 0) +   if ((i915->blend->colormask & PIPE_MASK_A) == 0)        LIS5 |= S5_WRITEDISABLE_ALPHA; @@ -205,11 +205,11 @@ static void upload_S6( struct i915_context *i915 )     /* I915_NEW_BLEND      */ -   if (i915->blend.blend_enable) +   if (i915->blend->blend_enable)     { -      unsigned funcRGB = i915->blend.rgb_func; -      unsigned srcRGB = i915->blend.rgb_src_factor; -      unsigned dstRGB = i915->blend.rgb_dst_factor; +      unsigned funcRGB = i915->blend->rgb_func; +      unsigned srcRGB = i915->blend->rgb_src_factor; +      unsigned dstRGB = i915->blend->rgb_dst_factor;        LIS6 |= (S6_CBUF_BLEND_ENABLE |  	       SRC_BLND_FACT(i915_translate_blend_factor(srcRGB)) | diff --git a/src/mesa/pipe/p_context.h b/src/mesa/pipe/p_context.h index ec5555c38e..b9af69fc05 100644 --- a/src/mesa/pipe/p_context.h +++ b/src/mesa/pipe/p_context.h @@ -31,7 +31,7 @@  #include "p_state.h"  #include "p_compiler.h" - +struct pipe_state_cache;  /**   * Software pipeline rendering context.  Basically a collection of   * state setting functions, plus VBO drawing entrypoint. @@ -85,12 +85,16 @@ struct pipe_context {     /*      * State functions      */ +   const struct pipe_blend_state * (*create_blend_state)(struct pipe_context *, +                                                         const struct pipe_blend_state *); +   void (*bind_blend_state)(struct pipe_context *, +                            const struct pipe_blend_state *); +   void (*delete_blend_state)(struct pipe_context *, +                              const struct pipe_blend_state *); +     void (*set_alpha_test_state)( struct pipe_context *,                                   const struct pipe_alpha_test_state * ); -   void (*set_blend_state)( struct pipe_context *, -                            const struct pipe_blend_state * ); -     void (*set_blend_color)( struct pipe_context *,                              const struct pipe_blend_color * ); diff --git a/src/mesa/pipe/softpipe/sp_context.c b/src/mesa/pipe/softpipe/sp_context.c index 92357808e2..b9c7013e9e 100644 --- a/src/mesa/pipe/softpipe/sp_context.c +++ b/src/mesa/pipe/softpipe/sp_context.c @@ -250,9 +250,12 @@ struct pipe_context *softpipe_create( struct pipe_winsys *pipe_winsys,     softpipe->pipe.max_texture_size = softpipe_max_texture_size;     /* state setters */ +   softpipe->pipe.create_blend_state = softpipe_create_blend_state; +   softpipe->pipe.bind_blend_state = softpipe_bind_blend_state; +   softpipe->pipe.delete_blend_state = softpipe_delete_blend_state; +     softpipe->pipe.set_alpha_test_state = softpipe_set_alpha_test_state;     softpipe->pipe.set_blend_color = softpipe_set_blend_color; -   softpipe->pipe.set_blend_state = softpipe_set_blend_state;     softpipe->pipe.set_clip_state = softpipe_set_clip_state;     softpipe->pipe.set_clear_color_state = softpipe_set_clear_color_state;     softpipe->pipe.set_constant_buffer = softpipe_set_constant_buffer; diff --git a/src/mesa/pipe/softpipe/sp_context.h b/src/mesa/pipe/softpipe/sp_context.h index 13d1143c89..7fecf2974a 100644 --- a/src/mesa/pipe/softpipe/sp_context.h +++ b/src/mesa/pipe/softpipe/sp_context.h @@ -71,8 +71,9 @@ struct softpipe_context {     /* The most recent drawing state as set by the driver:      */ +   const struct pipe_blend_state *blend; +     struct pipe_alpha_test_state alpha_test; -   struct pipe_blend_state blend;     struct pipe_blend_color blend_color;     struct pipe_clear_color_state clear_color;     struct pipe_clip_state clip; diff --git a/src/mesa/pipe/softpipe/sp_quad.c b/src/mesa/pipe/softpipe/sp_quad.c index 0f0736479f..2fcbea1f22 100644 --- a/src/mesa/pipe/softpipe/sp_quad.c +++ b/src/mesa/pipe/softpipe/sp_quad.c @@ -11,12 +11,12 @@ sp_build_quad_pipeline(struct softpipe_context *sp)     sp->quad.first = sp->quad.output; -   if (sp->blend.colormask != 0xf) { +   if (sp->blend->colormask != 0xf) {        sp->quad.colormask->next = sp->quad.first;        sp->quad.first = sp->quad.colormask;     } -   if (sp->blend.blend_enable) { +   if (sp->blend->blend_enable) {        sp->quad.blend->next = sp->quad.first;        sp->quad.first = sp->quad.blend;     } diff --git a/src/mesa/pipe/softpipe/sp_quad_blend.c b/src/mesa/pipe/softpipe/sp_quad_blend.c index e5335f3b19..6c7135e53c 100755 --- a/src/mesa/pipe/softpipe/sp_quad_blend.c +++ b/src/mesa/pipe/softpipe/sp_quad_blend.c @@ -111,7 +111,7 @@ blend_quad(struct quad_stage *qs, struct quad_header *quad)     /*      * Compute src/first term RGB      */ -   switch (softpipe->blend.rgb_src_factor) { +   switch (softpipe->blend->rgb_src_factor) {     case PIPE_BLENDFACTOR_ONE:        VEC4_COPY(source[0], quad->outputs.color[0]); /* R */        VEC4_COPY(source[1], quad->outputs.color[1]); /* G */ @@ -253,7 +253,7 @@ blend_quad(struct quad_stage *qs, struct quad_header *quad)     /*      * Compute src/first term A      */ -   switch (softpipe->blend.alpha_src_factor) { +   switch (softpipe->blend->alpha_src_factor) {     case PIPE_BLENDFACTOR_ONE:        VEC4_COPY(source[3], quad->outputs.color[3]); /* A */        break; @@ -275,7 +275,7 @@ blend_quad(struct quad_stage *qs, struct quad_header *quad)     /*      * Compute dest/second term RGB      */ -   switch (softpipe->blend.rgb_dst_factor) { +   switch (softpipe->blend->rgb_dst_factor) {     case PIPE_BLENDFACTOR_ONE:        /* dest = dest * 1   NO-OP, leave dest as-is */        break; @@ -301,7 +301,7 @@ blend_quad(struct quad_stage *qs, struct quad_header *quad)     /*      * Compute dest/second term A      */ -   switch (softpipe->blend.alpha_dst_factor) { +   switch (softpipe->blend->alpha_dst_factor) {     case PIPE_BLENDFACTOR_ONE:        /* dest = dest * 1   NO-OP, leave dest as-is */        break; @@ -323,7 +323,7 @@ blend_quad(struct quad_stage *qs, struct quad_header *quad)     /*      * Combine RGB terms      */ -   switch (softpipe->blend.rgb_func) { +   switch (softpipe->blend->rgb_func) {     case PIPE_BLEND_ADD:        VEC4_ADD(quad->outputs.color[0], source[0], dest[0]); /* R */        VEC4_ADD(quad->outputs.color[1], source[1], dest[1]); /* G */ @@ -356,7 +356,7 @@ blend_quad(struct quad_stage *qs, struct quad_header *quad)     /*      * Combine A terms      */ -   switch (softpipe->blend.alpha_func) { +   switch (softpipe->blend->alpha_func) {     case PIPE_BLEND_ADD:        VEC4_ADD(quad->outputs.color[3], source[3], dest[3]); /* A */        break; diff --git a/src/mesa/pipe/softpipe/sp_quad_colormask.c b/src/mesa/pipe/softpipe/sp_quad_colormask.c index 7bb65bf8c8..c3e110532a 100644 --- a/src/mesa/pipe/softpipe/sp_quad_colormask.c +++ b/src/mesa/pipe/softpipe/sp_quad_colormask.c @@ -49,19 +49,19 @@ colormask_quad(struct quad_stage *qs, struct quad_header *quad)     sps->read_quad_f_swz(sps, quad->x0, quad->y0, dest);     /* R */ -   if (!(softpipe->blend.colormask & PIPE_MASK_R)) +   if (!(softpipe->blend->colormask & PIPE_MASK_R))         COPY_4V(quad->outputs.color[0], dest[0]);     /* G */ -   if (!(softpipe->blend.colormask & PIPE_MASK_G)) +   if (!(softpipe->blend->colormask & PIPE_MASK_G))         COPY_4V(quad->outputs.color[1], dest[1]);     /* B */ -   if (!(softpipe->blend.colormask & PIPE_MASK_B)) +   if (!(softpipe->blend->colormask & PIPE_MASK_B))         COPY_4V(quad->outputs.color[2], dest[2]);     /* A */ -   if (!(softpipe->blend.colormask & PIPE_MASK_A)) +   if (!(softpipe->blend->colormask & PIPE_MASK_A))         COPY_4V(quad->outputs.color[3], dest[3]);     /* pass quad to next stage */ diff --git a/src/mesa/pipe/softpipe/sp_state.h b/src/mesa/pipe/softpipe/sp_state.h index f40ebe3e2b..e2b1a2a164 100644 --- a/src/mesa/pipe/softpipe/sp_state.h +++ b/src/mesa/pipe/softpipe/sp_state.h @@ -33,6 +33,13 @@  #include "pipe/p_state.h" +const struct pipe_blend_state * +softpipe_create_blend_state(struct pipe_context *, +                            const struct pipe_blend_state *); +void softpipe_bind_blend_state(struct pipe_context *, +                               const struct pipe_blend_state *); +void softpipe_delete_blend_state(struct pipe_context *, +                                 const struct pipe_blend_state *);  void softpipe_set_framebuffer_state( struct pipe_context *,  			     const struct pipe_framebuffer_state * ); @@ -40,9 +47,6 @@ void softpipe_set_framebuffer_state( struct pipe_context *,  void softpipe_set_alpha_test_state( struct pipe_context *,                                      const struct pipe_alpha_test_state * ); -void softpipe_set_blend_state( struct pipe_context *, -                               const struct pipe_blend_state * ); -  void softpipe_set_blend_color( struct pipe_context *pipe,                                 const struct pipe_blend_color *blend_color ); diff --git a/src/mesa/pipe/softpipe/sp_state_blend.c b/src/mesa/pipe/softpipe/sp_state_blend.c index b2e85d86cc..57f2df7923 100644 --- a/src/mesa/pipe/softpipe/sp_state_blend.c +++ b/src/mesa/pipe/softpipe/sp_state_blend.c @@ -30,17 +30,32 @@  #include "sp_context.h"  #include "sp_state.h" +const struct pipe_blend_state * +softpipe_create_blend_state(struct pipe_context *pipe, +                            const struct pipe_blend_state *blend) +{ +   struct pipe_blend_state *new_blend = malloc(sizeof(struct pipe_blend_state)); +   memcpy(new_blend, blend, sizeof(struct pipe_blend_state)); + +   return new_blend; +} -void softpipe_set_blend_state( struct pipe_context *pipe, +void softpipe_bind_blend_state( struct pipe_context *pipe,  			     const struct pipe_blend_state *blend )  {     struct softpipe_context *softpipe = softpipe_context(pipe); -   softpipe->blend = *blend; +   softpipe->blend = blend;     softpipe->dirty |= SP_NEW_BLEND;  } +void softpipe_delete_blend_state(struct pipe_context *pipe, +                                 const struct pipe_blend_state *blend ) +{ +   free(blend); +} +  void softpipe_set_blend_color( struct pipe_context *pipe,  			     const struct pipe_blend_color *blend_color ) diff --git a/src/mesa/sources b/src/mesa/sources index ec561294c5..e57942d664 100644 --- a/src/mesa/sources +++ b/src/mesa/sources @@ -186,6 +186,9 @@ TGSIDECO_SOURCES = \  TGSIMESA_SOURCES = \  	pipe/tgsi/mesa/mesa_to_tgsi.c +STATECACHE_SOURCES = \ +	cso_cache/cso_cache.c +  STATETRACKER_SOURCES = \  	state_tracker/st_atom.c \  	state_tracker/st_atom_alphatest.c \ @@ -373,6 +376,7 @@ SOLO_SOURCES = \  	$(TGSIEXEC_SOURCES)	\  	$(TGSIDECO_SOURCES)	\  	$(TGSIMESA_SOURCES)	\ +	$(STATECACHE_SOURCES)   \  	$(STATETRACKER_SOURCES)	\  	$(TNL_SOURCES)		\  	$(SHADER_SOURCES)	\ diff --git a/src/mesa/state_tracker/st_atom_blend.c b/src/mesa/state_tracker/st_atom_blend.c index afd21a6141..d007d50ad3 100644 --- a/src/mesa/state_tracker/st_atom_blend.c +++ b/src/mesa/state_tracker/st_atom_blend.c @@ -36,6 +36,7 @@  #include "st_atom.h"  #include "pipe/p_context.h"  #include "pipe/p_defines.h" +#include "cso_cache/cso_cache.h"  /** @@ -209,10 +210,14 @@ update_blend( struct st_context *st )     if (st->ctx->Color.DitherFlag)        blend.dither = 1; -   if (memcmp(&blend, &st->state.blend, sizeof(blend)) != 0) { +   struct pipe_blend_state *real_blend = +      cso_cached_blend_state(st, &blend); + +   if (st->state.blend != real_blend) {        /* state has changed */ -      st->state.blend = blend;  /* struct copy */ -      st->pipe->set_blend_state(st->pipe, &blend); /* set new state */ +      st->state.blend = real_blend; +      /* bind new state */ +      st->pipe->bind_blend_state(st->pipe, real_blend);     }     if (memcmp(st->ctx->Color.BlendColor, &st->state.blend_color, 4 * sizeof(GLfloat)) != 0) { diff --git a/src/mesa/state_tracker/st_cb_clear.c b/src/mesa/state_tracker/st_cb_clear.c index fa222df2a4..dc8a84af08 100644 --- a/src/mesa/state_tracker/st_cb_clear.c +++ b/src/mesa/state_tracker/st_cb_clear.c @@ -49,6 +49,8 @@  #include "pipe/tgsi/mesa/mesa_to_tgsi.h" +#include "cso_cache/cso_cache.h" +  #include "vf/vf.h" @@ -295,7 +297,8 @@ clear_with_quad(GLcontext *ctx,           if (st->ctx->Color.DitherFlag)              blend.dither = 1;        } -      pipe->set_blend_state(pipe, &blend); +      const struct pipe_blend_state *state = cso_cached_blend_state(st, &blend); +      pipe->bind_blend_state(pipe, state);     }     /* depth state: always pass */ @@ -390,7 +393,7 @@ clear_with_quad(GLcontext *ctx,     /* Restore pipe state */     pipe->set_alpha_test_state(pipe, &st->state.alpha_test); -   pipe->set_blend_state(pipe, &st->state.blend); +   pipe->bind_blend_state(pipe, st->state.blend);     pipe->set_depth_state(pipe, &st->state.depth);     pipe->set_fs_state(pipe, &st->state.fs);     pipe->set_vs_state(pipe, &st->state.vs); diff --git a/src/mesa/state_tracker/st_cb_drawpixels.c b/src/mesa/state_tracker/st_cb_drawpixels.c index e2280cdafa..c2d231cdb5 100644 --- a/src/mesa/state_tracker/st_cb_drawpixels.c +++ b/src/mesa/state_tracker/st_cb_drawpixels.c @@ -474,8 +474,8 @@ static GLboolean  any_fragment_ops(const struct st_context *st)  {     if (st->state.alpha_test.enabled || -       st->state.blend.blend_enable || -       st->state.blend.logicop_enable || +       st->state.blend->blend_enable || +       st->state.blend->logicop_enable ||         st->state.depth.enabled)        /* XXX more checks */        return GL_TRUE; diff --git a/src/mesa/state_tracker/st_context.c b/src/mesa/state_tracker/st_context.c index 6ab643f1fe..26815d5cd4 100644 --- a/src/mesa/state_tracker/st_context.c +++ b/src/mesa/state_tracker/st_context.c @@ -45,6 +45,7 @@  #include "st_program.h"  #include "pipe/p_context.h"  #include "pipe/draw/draw_context.h" +#include "cso_cache/cso_cache.h"  void st_invalidate_state(GLcontext * ctx, GLuint new_state) @@ -71,6 +72,8 @@ struct st_context *st_create_context( GLcontext *ctx,     st->dirty.mesa = ~0;     st->dirty.st = ~0; +   st->cache = cso_cache_create(); +     st_init_atoms( st );     st_init_draw( st ); @@ -112,6 +115,7 @@ void st_destroy_context( struct st_context *st )     /*st_destroy_cb_teximage( st );*/     st_destroy_cb_texture( st );  #endif +   cso_cache_destroy( st->cache );     st->pipe->destroy( st->pipe );     FREE( st ); diff --git a/src/mesa/state_tracker/st_context.h b/src/mesa/state_tracker/st_context.h index 56cae7d973..bd2efdb960 100644 --- a/src/mesa/state_tracker/st_context.h +++ b/src/mesa/state_tracker/st_context.h @@ -39,7 +39,7 @@ struct st_texture_image;  struct st_fragment_program;  struct draw_context;  struct draw_stage; - +struct cso_cache;  #define ST_NEW_MESA                    0x1 /* Mesa state has changed */  #define ST_NEW_FRAGMENT_PROGRAM        0x2 @@ -74,8 +74,9 @@ struct st_context      * though, we just shove random objects across the interface.        */     struct { +      const struct pipe_blend_state  *blend; +        struct pipe_alpha_test_state  alpha_test; -      struct pipe_blend_state  blend;        struct pipe_blend_color  blend_color;        struct pipe_clear_color_state clear_color;        struct pipe_clip_state clip; @@ -122,6 +123,8 @@ struct st_context     struct st_fragment_program *fp;     struct pipe_buffer_handle *default_attrib_buffer; + +   struct cso_cache *cache;  }; | 
