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



commit 683cebe22e66e7f5a7eb82b5688f4c2fb2a22c2f
Author: Neil Roberts <neil linux intel com>
Date:   Tue Nov 1 11:49:56 2011 +0000

    Stash

 cogl/cogl-bitmask.c               |   11 ++
 cogl/cogl-bitmask.h               |   14 ++-
 cogl/cogl-context-private.h       |    3 +-
 cogl/cogl-context.c               |   11 +--
 cogl/cogl-pipeline-private.h      |    7 --
 cogl/cogl-pipeline-progend-glsl.c |  187 ++++++++++++++++++++++++++++++++-----
 cogl/cogl-pipeline-state.c        |   15 +--
 cogl/cogl-pipeline.c              |   21 ++--
 8 files changed, 205 insertions(+), 64 deletions(-)
---
diff --git a/cogl/cogl-bitmask.c b/cogl/cogl-bitmask.c
index abac435..90f3436 100644
--- a/cogl/cogl-bitmask.c
+++ b/cogl/cogl-bitmask.c
@@ -273,3 +273,14 @@ _cogl_bitmask_is_empty_array (const CoglBitmask *bitmask)
 
   return TRUE;
 }
+
+void
+_cogl_bitmask_set_flags_array (const CoglBitmask *bitmask,
+                               unsigned long *flags)
+{
+  const GArray *array = (const GArray *) *bitmask;
+  int i;
+
+  for (i = 0; i < array->len; i++)
+    flags[i] |= g_array_index (array, unsigned long, i);
+}
diff --git a/cogl/cogl-bitmask.h b/cogl/cogl-bitmask.h
index a1710af..e44f2a2 100644
--- a/cogl/cogl-bitmask.h
+++ b/cogl/cogl-bitmask.h
@@ -104,6 +104,10 @@ _cogl_bitmask_clear_all_in_array (CoglBitmask *bitmask);
 gboolean
 _cogl_bitmask_is_empty_array (const CoglBitmask *bitmask);
 
+void
+_cogl_bitmask_set_flags_array (const CoglBitmask *bitmask,
+                               unsigned long *flags);
+
 /*
  * cogl_bitmask_set_bits:
  * @dst: The bitmask to modify
@@ -254,22 +258,20 @@ _cogl_bitmask_is_empty (const CoglBitmask *bitmask)
 /*
  * _cogl_bitmask_set_flags:
  * @bitmask: A pointer to a bitmask
- * @flags: An array of unsigned ints
+ * @flags: An array of flags
  *
- * This or's the bits from @bitmask into the flags array (see
+ * Bitwise or's the bits from @bitmask into the flags array (see
  * cogl-flags) pointed to by @flags.
  */
-#if 0
 static inline void
 _cogl_bitmask_set_flags (const CoglBitmask *bitmask,
-                         unsigned int *flags)
+                         unsigned long *flags)
 {
   if (_cogl_bitmask_has_array (bitmask))
     return _cogl_bitmask_set_flags_array (bitmask, flags);
   else
-    flags[0] |= _cogl_bitmask
+    flags[0] |= _cogl_bitmask_to_bits (bitmask);
 }
-#endif
 
 G_END_DECLS
 
diff --git a/cogl/cogl-context-private.h b/cogl/cogl-context-private.h
index 97f8757..8125e7b 100644
--- a/cogl/cogl-context-private.h
+++ b/cogl/cogl-context-private.h
@@ -263,7 +263,8 @@ struct _CoglContext
      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;
+  GSList *uniform_names;
+  int n_uniform_names;
 
   /* This defines a list of function pointers that Cogl uses from
      either GL or GLES. All functions are accessed indirectly through
diff --git a/cogl/cogl-context.c b/cogl/cogl-context.c
index 9058625..a972ee2 100644
--- a/cogl/cogl-context.c
+++ b/cogl/cogl-context.c
@@ -221,12 +221,8 @@ cogl_context_new (CoglDisplay *display,
       g_assert_not_reached ();
     }
 
-  /* We don't need a destructor for the uniform name string because
-     it is contained within the allocation of the struct */
-  context->uniform_names = g_hash_table_new_full (g_str_hash,
-                                                  g_str_equal,
-                                                  NULL,
-                                                  g_free);
+  context->uniform_names = NULL;
+  context->n_uniform_names = 0;
 
   /* Initialise the driver specific state */
   _cogl_init_feature_overrides (context);
@@ -493,7 +489,8 @@ _cogl_context_free (CoglContext *context)
 
   cogl_pipeline_cache_free (context->pipeline_cache);
 
-  g_hash_table_destroy (context->uniform_names);
+  g_slist_foreach (context->uniform_names, (GFunc) g_free, NULL);
+  g_slist_free (context->uniform_names);
 
   g_byte_array_free (context->buffer_map_fallback_array, TRUE);
 
diff --git a/cogl/cogl-pipeline-private.h b/cogl/cogl-pipeline-private.h
index c9e91bc..4f28840 100644
--- a/cogl/cogl-pipeline-private.h
+++ b/cogl/cogl-pipeline-private.h
@@ -414,13 +414,6 @@ 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-progend-glsl.c b/cogl/cogl-pipeline-progend-glsl.c
index 9cda3c7..4ec6f37 100644
--- a/cogl/cogl-pipeline-progend-glsl.c
+++ b/cogl/cogl-pipeline-progend-glsl.c
@@ -29,6 +29,8 @@
 #include "config.h"
 #endif
 
+#include <string.h>
+
 #include "cogl-util.h"
 #include "cogl-context-private.h"
 #include "cogl-pipeline-private.h"
@@ -165,6 +167,7 @@ get_program_state (CoglPipeline *pipeline)
 #ifdef HAVE_COGL_GLES2
 
 #define ATTRIBUTE_LOCATION_UNKNOWN -2
+#define UNIFORM_LOCATION_UNKNOWN -2
 
 /* Under GLES2 the vertex attribute API needs to query the attribute
    numbers because it can't used the fixed function API to set the
@@ -566,16 +569,127 @@ get_ancestors (CoglPipeline *pipeline)
   return ancestors;
 }
 
+static void
+flush_uniform_boxed_value (CoglContext *ctx,
+                           GLint uniform_location,
+                           const CoglBoxedValue *value)
+{
+  switch (value->type)
+    {
+    case COGL_BOXED_FLOAT:
+      {
+        const float *array;
+
+        if (value->count > 1)
+          array = value->v.float_array;
+        else
+          array = value->v.float_value;
+
+        switch (value->size)
+          {
+          case 1:
+            ctx->glUniform1fv (uniform_location,
+                               value->count,
+                               array);
+            break;
+
+          case 2:
+            ctx->glUniform2fv (uniform_location,
+                               value->count,
+                               array);
+            break;
+
+          case 3:
+            ctx->glUniform3fv (uniform_location,
+                               value->count,
+                               array);
+            break;
+
+          case 4:
+            ctx->glUniform4fv (uniform_location,
+                               value->count,
+                               array);
+            break;
+          }
+
+        break;
+
+        /* FIXME: add more types... */
+      }
+    }
+}
+
 typedef struct
 {
-  CoglProgramState *program_state;
+  CoglPipelineProgramState *program_state;
   CoglPipeline *flushed_ancestor;
-  unsigned int *force_flush_uniforms;
-  unsigned int *flushed_uniforms;
-  const CoglPipelineUniformsState *uniforms_state;
-  int uniforms_count;
+  unsigned long *force_flush_uniforms;
+  unsigned long *flushed_uniforms;
+  CoglPipelineUniformsState *uniforms_state;
+  gboolean found_ancestor;
+  CoglContext *ctx;
+  CoglPipelineUniformOverride *override;
 } FlushUniformsClosure;
 
+static gboolean
+flush_uniform_cb (int uniform_num, void *user_data)
+{
+  FlushUniformsClosure *data = user_data;
+
+  if (!COGL_FLAGS_GET (data->flushed_uniforms, uniform_num) &&
+      (!data->found_ancestor ||
+       COGL_FLAGS_GET (data->force_flush_uniforms, uniform_num)))
+    {
+      GArray *uniform_locations;
+      GLint uniform_location;
+
+      if (data->program_state->uniform_locations == NULL)
+        data->program_state->uniform_locations =
+          g_array_new (FALSE, FALSE, sizeof (GLint));
+
+      uniform_locations = data->program_state->uniform_locations;
+
+      if (uniform_locations->len <= uniform_num)
+        {
+          unsigned int old_len = uniform_locations->len;
+
+          g_array_set_size (uniform_locations, uniform_num + 1);
+
+          while (old_len <= uniform_num)
+            {
+              g_array_index (uniform_locations, GLint, old_len) =
+                UNIFORM_LOCATION_UNKNOWN;
+              old_len++;
+            }
+        }
+
+      uniform_location = g_array_index (uniform_locations, GLint, uniform_num);
+
+      if (uniform_location == UNIFORM_LOCATION_UNKNOWN)
+        {
+          const char *uniform_name =
+            g_slist_nth (data->ctx->uniform_names, uniform_num)->data;
+
+          uniform_location =
+            data->ctx->glGetUniformLocation (data->program_state->program,
+                                             uniform_name);
+          g_array_index (uniform_locations, GLint, uniform_num) =
+            uniform_location;
+        }
+
+      if (uniform_location != -1)
+        flush_uniform_boxed_value (data->ctx,
+                                   uniform_location,
+                                   &data->override->value);
+
+      COGL_FLAGS_SET (data->flushed_uniforms, uniform_num, TRUE);
+    }
+
+  data->override = COGL_SLIST_NEXT (data->override, list_node);
+
+  return TRUE;
+}
+
 static void
 _cogl_pipeline_progend_glsl_flush_uniforms (CoglPipeline *pipeline,
                                             CoglPipelineProgramState *
@@ -584,23 +698,29 @@ _cogl_pipeline_progend_glsl_flush_uniforms (CoglPipeline *pipeline,
                                             gboolean program_changed)
 {
   FlushUniformsClosure data;
-  int uniforms_count;
+  int n_uniform_longs;
+
+  _COGL_GET_CONTEXT (ctx, NO_RETVAL);
 
   _cogl_bitmask_init (&data.force_flush_uniforms);
 
   if (pipeline->differences & COGL_PIPELINE_STATE_UNIFORMS)
-    data.uniforms_state = &pipeline->big_state->data.uniforms_state;
+    data.uniforms_state = &pipeline->big_state->uniforms_state;
   else
     data.uniforms_state = NULL;
 
   data.flushed_ancestor = NULL;
-  data.uniforms_count = g_hash_table_size (ctx->uniform_names);
-  data.force_flush_uniforms = g_newa (unsigned int, data.uniforms_count);
+  data.program_state = program_state;
+  data.ctx = ctx;
+
+  n_uniform_longs = COGL_FLAGS_N_LONGS_FOR_SIZE (ctx->n_uniform_names);
+
+  data.force_flush_uniforms = g_newa (unsigned long, n_uniform_longs);
   memset (data.force_flush_uniforms, 0,
-          sizeof (unsigned int) * data.uniforms_count);
-  data.flushed_uniforms = g_newa (unsigned int, data.uniforms_count);
-  memset (data.data.flushed_uniforms, 0,
-          sizeof (unsigned int) * data.uniforms_count);
+          n_uniform_longs * sizeof (unsigned long));
+  data.flushed_uniforms = g_newa (unsigned long, n_uniform_longs);
+  memset (data.flushed_uniforms, 0,
+          n_uniform_longs * sizeof (unsigned long));
 
   /* Try to find a common ancestor for the values that were already
      flushed on the pipeline that this program state was last used for
@@ -633,26 +753,49 @@ _cogl_pipeline_progend_glsl_flush_uniforms (CoglPipeline *pipeline,
       /* We need to be sure to flush any uniforms that have changed
          since the last flush */
       if (data.uniforms_state)
-        _cogl_bitmask_set_bits (&data.force_flush_uniforms,
-                                &data.uniforms_state->changed_mask);
+        _cogl_bitmask_set_flags (&data.uniforms_state->changed_mask,
+                                 data.force_flush_uniforms);
 
       /* We need to flush any uniforms that are children of the common
          ancestor up to the last used pipeline */
       while (a)
         {
           CoglPipeline *child_pipeline = a->data;
-          const CoglPipelineUniformsState *data.uniforms_state =
-            &child_pipeline->big_state->data.uniforms_state;
-          _cogl_bitmask_set_bits (&data.force_flush_uniforms,
-                                  &data.uniforms_state->override_mask);
+          if (pipeline->differences & COGL_PIPELINE_STATE_UNIFORMS)
+            {
+              const CoglPipelineUniformsState *uniforms_state =
+                &child_pipeline->big_state->uniforms_state;
+              _cogl_bitmask_set_flags (&uniforms_state->override_mask,
+                                       data.force_flush_uniforms);
+            }
           a = a->next;
         }
     }
 
-  if (data.uniforms_state)
-    _cogl_bitmask_clear (&data.uniforms_state->changed_mask);
+  data.found_ancestor = FALSE;
+
+  while (pipeline)
+    {
+      if (pipeline == data.flushed_ancestor)
+        data.found_ancestor = TRUE;
+
+      if (pipeline->differences & COGL_PIPELINE_STATE_UNIFORMS)
+        {
+          const CoglPipelineUniformsState *uniforms_state =
+            &pipeline->big_state->uniforms_state;
+
+          data.override = COGL_SLIST_FIRST (&uniforms_state->override_list);
+
+          _cogl_bitmask_foreach (&uniforms_state->override_mask,
+                                 flush_uniform_cb,
+                                 &data);
+        }
 
-  _cogl_bitmask_destroy (&data.force_flush_uniforms);
+      pipeline = _cogl_pipeline_get_parent (pipeline);
+    }
+
+  if (data.uniforms_state)
+    _cogl_bitmask_clear_all (&data.uniforms_state->changed_mask);
 }
 
 static void
diff --git a/cogl/cogl-pipeline-state.c b/cogl/cogl-pipeline-state.c
index e1c2a49..cb91335 100644
--- a/cogl/cogl-pipeline-state.c
+++ b/cogl/cogl-pipeline-state.c
@@ -266,8 +266,7 @@ _cogl_pipeline_get_all_uniform_values (CoglPipeline *pipeline,
   _COGL_GET_CONTEXT (ctx, NO_RETVAL);
 
   memset (values, 0,
-          sizeof (const CoglBoxedValue *) *
-          g_hash_table_size (ctx->uniform_names));
+          sizeof (const CoglBoxedValue *) * ctx->n_uniform_names);
 
   data.values = values;
 
@@ -293,7 +292,6 @@ _cogl_pipeline_uniforms_state_equal (CoglPipeline *authority0,
                                      CoglPipeline *authority1)
 {
   const CoglBoxedValue **values0, **values1;
-  int n_uniform_names;
   int i;
 
   _COGL_GET_CONTEXT (ctx, FALSE);
@@ -301,15 +299,13 @@ _cogl_pipeline_uniforms_state_equal (CoglPipeline *authority0,
   if (authority0 == authority1)
     return TRUE;
 
-  n_uniform_names = g_hash_table_size (ctx->uniform_names);
-
-  values0 = g_alloca (sizeof (const CoglBoxedValue *) * n_uniform_names);
-  values1 = g_alloca (sizeof (const CoglBoxedValue *) * n_uniform_names);
+  values0 = g_alloca (sizeof (const CoglBoxedValue *) * ctx->n_uniform_names);
+  values1 = g_alloca (sizeof (const CoglBoxedValue *) * ctx->n_uniform_names);
 
   _cogl_pipeline_get_all_uniform_values (authority0, values0);
   _cogl_pipeline_get_all_uniform_values (authority1, values1);
 
-  for (i = 0; i < n_uniform_names; i++)
+  for (i = 0; i < ctx->n_uniform_names; i++)
     {
       const CoglBoxedValue *value0 = values0[i];
       const CoglBoxedValue *value1 = values1[i];
@@ -1393,8 +1389,7 @@ _cogl_pipeline_override_uniform (CoglPipeline *pipeline,
 
   g_return_val_if_fail (cogl_is_pipeline (pipeline), NULL);
   g_return_val_if_fail (location >= 0, NULL);
-  g_return_val_if_fail (location < g_hash_table_size (ctx->uniform_names),
-                        NULL);
+  g_return_val_if_fail (location < ctx->n_uniform_names, NULL);
 
   /* - Flush journal primitives referencing the current state.
    * - Make sure the pipeline has no dependants so it may be modified.
diff --git a/cogl/cogl-pipeline.c b/cogl/cogl-pipeline.c
index ba79aad..3d2bf3e 100644
--- a/cogl/cogl-pipeline.c
+++ b/cogl/cogl-pipeline.c
@@ -2847,8 +2847,7 @@ int
 cogl_pipeline_get_uniform_location (CoglPipeline *pipeline,
                                     const char *uniform_name)
 {
-  CoglPipelineUniformName *name_node;
-  int name_len;
+  GSList *l;
   int location = 0;
 
   _COGL_GET_CONTEXT (ctx, -1);
@@ -2861,16 +2860,16 @@ cogl_pipeline_get_uniform_location (CoglPipeline *pipeline,
      be. */
 
   /* Look for an existing uniform with this name */
-  name_node = g_hash_table_lookup (ctx->uniform_names, uniform_name);
-  if (name_node)
-    return name_node->index;
+  for (l = ctx->uniform_names; l; l = l->next)
+    {
+      if (!strcmp (uniform_name, l->data))
+        return location;
 
-  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);
+      location++;
+    }
 
-  g_hash_table_insert (ctx->uniform_names, name_node->name, name_node);
+  ctx->uniform_names =
+    g_slist_append (ctx->uniform_names, g_strdup (uniform_name));
 
-  return location;
+  return ctx->n_uniform_names++;
 }



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