First stab at immutable state objects (create/bind/delete)
authorZack Rusin <zack@tungstengraphics.com>
Fri, 14 Sep 2007 08:08:58 +0000 (04:08 -0400)
committerZack Rusin <zack@tungstengraphics.com>
Tue, 18 Sep 2007 10:31:22 +0000 (06:31 -0400)
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.

23 files changed:
src/mesa/cso_cache/cso_cache.c [new file with mode: 0644]
src/mesa/cso_cache/cso_cache.h [new file with mode: 0644]
src/mesa/pipe/failover/fo_context.h
src/mesa/pipe/failover/fo_state.c
src/mesa/pipe/failover/fo_state_emit.c
src/mesa/pipe/i915simple/i915_context.h
src/mesa/pipe/i915simple/i915_state.c
src/mesa/pipe/i915simple/i915_state_dynamic.c
src/mesa/pipe/i915simple/i915_state_immediate.c
src/mesa/pipe/p_context.h
src/mesa/pipe/softpipe/sp_context.c
src/mesa/pipe/softpipe/sp_context.h
src/mesa/pipe/softpipe/sp_quad.c
src/mesa/pipe/softpipe/sp_quad_blend.c
src/mesa/pipe/softpipe/sp_quad_colormask.c
src/mesa/pipe/softpipe/sp_state.h
src/mesa/pipe/softpipe/sp_state_blend.c
src/mesa/sources
src/mesa/state_tracker/st_atom_blend.c
src/mesa/state_tracker/st_cb_clear.c
src/mesa/state_tracker/st_cb_drawpixels.c
src/mesa/state_tracker/st_context.c
src/mesa/state_tracker/st_context.h

diff --git a/src/mesa/cso_cache/cso_cache.c b/src/mesa/cso_cache/cso_cache.c
new file mode 100644 (file)
index 0000000..bb85330
--- /dev/null
@@ -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 (file)
index 0000000..ca0a2d5
--- /dev/null
@@ -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
index 5666d4e83065c4b0f95a4c389eb3fdc2cbf2d8f5..b065aa832a4bed8898483c34b50de1b6a37d7545 100644 (file)
@@ -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;
index 097acf7d5797f9e0806ec5026719a61eac674e16..2357d7ef5cef5241f70eb217f0fdea929fd18c07 100644 (file)
@@ -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;
index 52fcf5dbc95282edfbe08f871869fecccc233ed5..77413d100b3e06a38cbd67296ba05fba8662cc7e 100644 (file)
@@ -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 );
index c30c79d83c927139188142dd90c89857d931e40a..215c5294fa60cbfdc45eb690593e54311095fb3c 100644 (file)
@@ -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;
index f5ea721cc8e790d43a95c37678ba3a791a2e1c6b..478988fd4a958fcdf73192c67798e4c02e593d5d 100644 (file)
 
 /* 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;
index e648357754f5d78b2b9ab1b4695693ee8ed28936..49a30fac1158dedd0263c6d935dce5d6e4c76f9a 100644 (file)
@@ -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.
index 38a24733e12cccfa9a040f47d6be8acd3455ff6b..aaca534f5ad66d06e1f65456906cc3f991617861 100644 (file)
@@ -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)) |
index ec5555c38e9cdf490c9d1904eee5fe1e7f2bb15c..b9af69fc05072cbf02c4d2b16f2311a1c78d0ece 100644 (file)
@@ -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 * );
 
index 92357808e295f25e9c26e2a7e445e471d1f801da..b9c7013e9e1a193907e3d3c91781af462be7605b 100644 (file)
@@ -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;
index 13d1143c89031babc0401ecbaaad6efc12d03064..7fecf2974ac1cd8794f837dc026c0ca79350faed 100644 (file)
@@ -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;
index 0f0736479f2c8ecdc5b54f73f3d6aa4d01f5c09e..2fcbea1f22ef188120d2c42ce3af12596fd7dc60 100644 (file)
@@ -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;
    }
index e5335f3b19abd69106c251d4e5a6747811cae981..6c7135e53c550801fc379d03f3e19c14a7e2006c 100755 (executable)
@@ -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;
index 7bb65bf8c80fdafbd2f474ea36a63b3bb1b3a896..c3e110532a11b6617ee4407e21a020ecff4f06f6 100644 (file)
@@ -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 */
index f40ebe3e2b83a19bddeced7e362603e8a7947fb8..e2b1a2a16418c05c0c077a568f2a026c925fb50d 100644 (file)
 
 #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 );
 
index b2e85d86cc066dded8592d19fbffe34d94481c35..57f2df79238e8270aba952367653294eec47991b 100644 (file)
 #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 )
index ec561294c5a9ef3f1f284b26b1d434faf2696792..e57942d6641bbbaaab2acce7fff551ec0fd43462 100644 (file)
@@ -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)       \
index afd21a6141c76a980215a46f667094bf2bcb0a56..d007d50ad39a6995c3deab0309f65136f3118be8 100644 (file)
@@ -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) {
index fa222df2a48c367c0d55413a93c83924f9d87bd8..dc8a84af08f49518a1e81fc827b70cdc6788c62e 100644 (file)
@@ -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);
index e2280cdafa89be071485c37710b893415df15741..c2d231cdb5d2dbe2eec9933c5f02c5b85444f2e4 100644 (file)
@@ -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;
index 6ab643f1feff8340ab15defd7b1246b8edba9b12..26815d5cd42444164091c73bbaec7d462c02a1dd 100644 (file)
@@ -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 );
index 56cae7d9734ca45d2885f3b18af4d5563b32e977..bd2efdb960bf6b43f3bbb1dc962dbb10533625b1 100644 (file)
@@ -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;
 };