[cogl/wip/neil/pipeline-uniforms: 11/17] Stash



commit 5ce0d50154d76bf0b35618521d5db28887a8e577
Author: Neil Roberts <neil linux intel com>
Date:   Wed Oct 26 18:55:15 2011 +0100

    Stash

 cogl/cogl-context-private.h  |    7 +++++
 cogl/cogl-context.c          |    4 +++
 cogl/cogl-pipeline-private.h |   42 +++++++++++++++++++++++++++-
 cogl/cogl-pipeline-state.c   |   60 +++++++++++++++++++++++++++++++++++++++++
 cogl/cogl-pipeline.c         |   61 ++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 172 insertions(+), 2 deletions(-)
---
diff --git a/cogl/cogl-context-private.h b/cogl/cogl-context-private.h
index df0aa4a..97f8757 100644
--- a/cogl/cogl-context-private.h
+++ b/cogl/cogl-context-private.h
@@ -258,6 +258,13 @@ struct _CoglContext
     [COGL_FLAGS_N_LONGS_FOR_SIZE (COGL_WINSYS_FEATURE_N_FEATURES)];
   void *winsys;
 
+  /* List of names of uniforms. These are used like quarks to give a
+     unique number to each uniform name except that we ensure that
+     they increase sequentially so that we can use the id as an index
+     into a bitfield representing the uniforms that a pipeline
+     overrides from its parent */
+  GHashTable *uniform_names;
+
   /* This defines a list of function pointers that Cogl uses from
      either GL or GLES. All functions are accessed indirectly through
      these pointers rather than linking to them directly */
diff --git a/cogl/cogl-context.c b/cogl/cogl-context.c
index bd3eca4..6f64cc6 100644
--- a/cogl/cogl-context.c
+++ b/cogl/cogl-context.c
@@ -221,6 +221,8 @@ cogl_context_new (CoglDisplay *display,
       g_assert_not_reached ();
     }
 
+  context->uniform_names = NULL;
+
   /* Initialise the driver specific state */
   _cogl_init_feature_overrides (context);
 
@@ -486,6 +488,8 @@ _cogl_context_free (CoglContext *context)
 
   cogl_pipeline_cache_free (context->pipeline_cache);
 
+  g_hash_table_destroy (context->uniform_names);
+
   g_byte_array_free (context->buffer_map_fallback_array, TRUE);
 
   cogl_object_unref (context->display);
diff --git a/cogl/cogl-pipeline-private.h b/cogl/cogl-pipeline-private.h
index d6c0dcc..eaf807f 100644
--- a/cogl/cogl-pipeline-private.h
+++ b/cogl/cogl-pipeline-private.h
@@ -167,6 +167,7 @@ typedef enum
   COGL_PIPELINE_STATE_POINT_SIZE_INDEX,
   COGL_PIPELINE_STATE_LOGIC_OPS_INDEX,
   COGL_PIPELINE_STATE_CULL_FACE_INDEX,
+  COGL_PIPELINE_STATE_UNIFORMS_INDEX,
 
   /* non-sparse */
   COGL_PIPELINE_STATE_REAL_BLEND_ENABLE_INDEX,
@@ -214,6 +215,8 @@ typedef enum _CoglPipelineState
     1L<<COGL_PIPELINE_STATE_LOGIC_OPS_INDEX,
   COGL_PIPELINE_STATE_CULL_FACE =
     1L<<COGL_PIPELINE_STATE_CULL_FACE_INDEX,
+  COGL_PIPELINE_STATE_UNIFORMS =
+    1L<<COGL_PIPELINE_STATE_UNIFORMS_INDEX,
 
   COGL_PIPELINE_STATE_REAL_BLEND_ENABLE =
     1L<<COGL_PIPELINE_STATE_REAL_BLEND_ENABLE_INDEX,
@@ -249,7 +252,8 @@ typedef enum _CoglPipelineState
    COGL_PIPELINE_STATE_FOG | \
    COGL_PIPELINE_STATE_POINT_SIZE | \
    COGL_PIPELINE_STATE_LOGIC_OPS | \
-   COGL_PIPELINE_STATE_CULL_FACE)
+   COGL_PIPELINE_STATE_CULL_FACE | \
+   COGL_PIPELINE_STATE_UNIFORMS)
 
 #define COGL_PIPELINE_STATE_MULTI_PROPERTY \
   (COGL_PIPELINE_STATE_LAYERS | \
@@ -258,7 +262,8 @@ typedef enum _CoglPipelineState
    COGL_PIPELINE_STATE_DEPTH | \
    COGL_PIPELINE_STATE_FOG | \
    COGL_PIPELINE_STATE_LOGIC_OPS | \
-   COGL_PIPELINE_STATE_CULL_FACE)
+   COGL_PIPELINE_STATE_CULL_FACE | \
+   COGL_PIPELINE_STATE_UNIFORMS)
 
 #define COGL_PIPELINE_STATE_AFFECTS_VERTEX_CODEGEN \
   (COGL_PIPELINE_STATE_LAYERS | \
@@ -348,6 +353,31 @@ typedef struct
   CoglWinding front_winding;
 } CoglPipelineCullFaceState;
 
+typedef struct _CoglPipelineUniformOverride CoglPipelineUniformOverride;
+
+COGL_SLIST_HEAD (CoglPipelineUniformOverrideList,
+                 CoglPipelineUniformOverride);
+
+struct _CoglPipelineUniformOverride
+{
+  COGL_SLIST_ENTRY (CoglPipelineUniformOverride) list_node;
+
+  /* We don't need to store the location of the uniform here because
+     it is implicit from the order in the list */
+
+  /* One of these overrides can effectively remove a uniform by
+     setting the boxed value type to none. In that case no attempt
+     will be made to upload the value */
+
+  CoglBoxedValue value;
+};
+
+typedef struct
+{
+  CoglBitmask override_mask;
+  CoglPipelineUniformOverrideList override_list;
+} CoglPipelineUniformsState;
+
 typedef struct
 {
   CoglPipelineLightingState lighting_state;
@@ -359,6 +389,7 @@ typedef struct
   float point_size;
   CoglPipelineLogicOpsState logic_ops_state;
   CoglPipelineCullFaceState cull_face_state;
+  CoglPipelineUniformsState uniforms_state;
 } CoglPipelineBigState;
 
 typedef enum
@@ -380,6 +411,13 @@ typedef struct _CoglPipelineHashState
   unsigned int hash;
 } CoglPipelineHashState;
 
+typedef struct _CoglPipelineUniformName
+{
+  int index;
+  /* Overallocated to store the name in this struct */
+  char name[1];
+} CoglPipelineUniformName;
+
 /*
  * CoglPipelineDestroyCallback
  * @pipeline: The #CoglPipeline that has been destroyed
diff --git a/cogl/cogl-pipeline-state.c b/cogl/cogl-pipeline-state.c
index 78102d8..f91acfd 100644
--- a/cogl/cogl-pipeline-state.c
+++ b/cogl/cogl-pipeline-state.c
@@ -1455,3 +1455,63 @@ _cogl_pipeline_hash_cull_face_state (CoglPipeline *authority,
                                      cull_face_state,
                                      sizeof (CoglPipelineCullFaceState));
 }
+
+static void
+cogl_pipeline_set_uniform_x (CoglPipeline *pipeline,
+                             int location,
+                             int size,
+                             int count,
+                             CoglBoxedType type,
+                             gsize value_size,
+                             gconstpointer value,
+                             gboolean transpose)
+{
+  CoglPipelineUniformOverride *previous_override = NULL;
+  CoglPipelineUniformOverride *override = NULL;
+
+  _COGL_GET_CONTEXT (ctx, NO_RETVAL);
+
+  g_return_if_fail (cogl_is_pipeline (pipeline));
+  g_return_if_fail (location >= 0);
+  g_return_if_fail (location < g_hash_table_size (ctx->uniform_names));
+  g_return_if_fail (size >= 1 && size <= 4 && count >= 1);
+#if 0
+  if (uniform_no >= 0 && uniform_no < program->custom_uniforms->len &&
+      size >= 1 && size <= 4 && count >= 1)
+    {
+      CoglProgramUniform *uniform =
+        &g_array_index (program->custom_uniforms,
+                        CoglProgramUniform, uniform_no);
+
+      if (count == 1)
+        {
+          if (uniform->value.count > 1)
+            g_free (uniform->value.v.array);
+
+          memcpy (uniform->value.v.float_value, value, value_size);
+        }
+      else
+        {
+          if (uniform->value.count > 1)
+            {
+              if (uniform->value.count != count ||
+                  uniform->value.size != size ||
+                  uniform->value.type != type)
+                {
+                  g_free (uniform->value.v.array);
+                  uniform->value.v.array = g_malloc (count * value_size);
+                }
+            }
+          else
+            uniform->value.v.array = g_malloc (count * value_size);
+
+          memcpy (uniform->value.v.array, value, count * value_size);
+        }
+
+      uniform->value.type = type;
+      uniform->value.size = size;
+      uniform->value.count = count;
+      uniform->dirty = TRUE;
+    }
+#endif
+}
diff --git a/cogl/cogl-pipeline.c b/cogl/cogl-pipeline.c
index 60e96eb..1ba2cb0 100644
--- a/cogl/cogl-pipeline.c
+++ b/cogl/cogl-pipeline.c
@@ -458,6 +458,25 @@ _cogl_pipeline_free (CoglPipeline *pipeline)
       pipeline->big_state->user_program)
     cogl_handle_unref (pipeline->big_state->user_program);
 
+  if (pipeline->differences & COGL_PIPELINE_STATE_UNIFORMS)
+    {
+      CoglPipelineUniformsState *uniforms_state
+        = &pipeline->big_state->uniforms_state;
+      CoglPipelineUniformOverride *override, *tmp;
+
+      COGL_SLIST_FOREACH_SAFE (override,
+                               &uniforms_state->override_list,
+                               list_node,
+                               tmp)
+        {
+          if (override->value.count > 1)
+            g_free (override->value.v.array);
+          g_free (override);
+        }
+
+      _cogl_bitmask_destroy (&uniforms_state->override_mask);
+    }
+
   if (pipeline->differences & COGL_PIPELINE_STATE_NEEDS_BIG_STATE)
     g_slice_free (CoglPipelineBigState, pipeline->big_state);
 
@@ -2808,3 +2827,45 @@ _cogl_pipeline_get_state_for_fragment_codegen (CoglContext *context)
 
   return state;
 }
+
+int
+cogl_pipeline_get_uniform_location (CoglPipeline *pipeline,
+                                    const char *uniform_name)
+{
+  CoglPipelineUniformName *name_node;
+  int name_len;
+  int location = 0;
+
+  _COGL_GET_CONTEXT (ctx, -1);
+
+  /* This API is designed as if the uniform locations are specific to
+     a pipeline but they are actually unique across a whole
+     CoglContext. Potentially this could just be
+     cogl_context_get_uniform_location but it seems to make sense to
+     keep the API this way so that we can change the internals if need
+     be. */
+
+  /* Look for an existing uniform with this name */
+  if (ctx->uniform_names)
+    {
+      name_node = g_hash_table_lookup (ctx->uniform_names, uniform_name);
+      if (name_node)
+        return name_node->index;
+    }
+  else
+    /* We don't need a destructor for the uniform name string because
+       it is contained within the allocation of the struct */
+    ctx->uniform_names = g_hash_table_new_full (g_str_hash,
+                                                g_str_equal,
+                                                NULL,
+                                                g_free);
+
+  name_len = strlen (uniform_name);
+  name_node = g_malloc (sizeof (CoglPipelineUniformName) + name_len);
+  name_node->index = g_hash_table_size (ctx->uniform_names);
+  memcpy (name_node->name, uniform_name, name_len + 1);
+
+  g_hash_table_insert (ctx->uniform_names, name_node->name, name_node);
+
+  return location;
+}



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]