[cogl/wip/neil/pipeline-uniforms: 8/9] Stash



commit f58a2961f5d75cbbdd59789009c29396bc0523d1
Author: Neil Roberts <neil linux intel com>
Date:   Thu Oct 27 16:56:11 2011 +0100

    Stash

 cogl/cogl-pipeline-state-private.h |    4 +
 cogl/cogl-pipeline-state.c         |  248 +++++++++++++++++++++++++++---------
 cogl/cogl-pipeline.c               |    5 +-
 cogl/cogl-pipeline.h               |   27 ++++
 4 files changed, 221 insertions(+), 63 deletions(-)
---
diff --git a/cogl/cogl-pipeline-state-private.h b/cogl/cogl-pipeline-state-private.h
index dd00f00..8b8fe3f 100644
--- a/cogl/cogl-pipeline-state-private.h
+++ b/cogl/cogl-pipeline-state-private.h
@@ -87,6 +87,10 @@ gboolean
 _cogl_pipeline_cull_face_state_equal (CoglPipeline *authority0,
                                       CoglPipeline *authority1);
 
+gboolean
+_cogl_pipeline_uniforms_state_equal (CoglPipeline *authority0,
+                                     CoglPipeline *authority1);
+
 void
 _cogl_pipeline_hash_color_state (CoglPipeline *authority,
                                  CoglPipelineHashState *state);
diff --git a/cogl/cogl-pipeline-state.c b/cogl/cogl-pipeline-state.c
index 5270756..7709335 100644
--- a/cogl/cogl-pipeline-state.c
+++ b/cogl/cogl-pipeline-state.c
@@ -238,6 +238,94 @@ _cogl_pipeline_user_shader_equal (CoglPipeline *authority0,
           authority1->big_state->user_program);
 }
 
+typedef struct
+{
+  const CoglBoxedValue **values;
+  const CoglPipelineUniformOverride *override_values;
+} GetUniformsClosure;
+
+static gboolean
+get_uniforms_cb (int uniform_num, void *user_data)
+{
+  GetUniformsClosure *data = user_data;
+
+  if (data->values[uniform_num] == NULL)
+    data->values[uniform_num] = &data->override_values->value;
+
+  data->override_values = COGL_SLIST_NEXT (data->override_values, list_node);
+
+  return TRUE;
+}
+
+static void
+_cogl_pipeline_get_all_uniform_values (CoglPipeline *pipeline,
+                                       const CoglBoxedValue **values)
+{
+  GetUniformsClosure data;
+
+  _COGL_GET_CONTEXT (ctx, NO_RETVAL);
+
+  memset (values, 0,
+          sizeof (const CoglBoxedValue *) *
+          g_hash_table_size (ctx->uniform_names));
+
+  data.values = values;
+
+  do
+    {
+      const CoglPipelineUniformsState *uniforms_state =
+        &pipeline->big_state->uniforms_state;
+
+      data.override_values = COGL_SLIST_FIRST (&uniforms_state->override_list);
+
+      if ((pipeline->differences & COGL_PIPELINE_STATE_UNIFORMS))
+        _cogl_bitmask_foreach (&uniforms_state->override_mask,
+                               get_uniforms_cb,
+                               &data);
+
+      pipeline = _cogl_pipeline_get_parent (pipeline);
+    }
+  while (pipeline);
+}
+
+gboolean
+_cogl_pipeline_uniforms_state_equal (CoglPipeline *authority0,
+                                     CoglPipeline *authority1)
+{
+  const CoglBoxedValue **values0, **values1;
+  int n_uniform_names;
+  int i;
+
+  _COGL_GET_CONTEXT (ctx, FALSE);
+
+  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);
+
+  _cogl_pipeline_get_all_uniform_values (authority0, values0);
+  _cogl_pipeline_get_all_uniform_values (authority1, values1);
+
+  for (i = 0; i < n_uniform_names; i++)
+    {
+      const CoglBoxedValue *value0 = values0[i];
+      const CoglBoxedValue *value1 = values1[i];
+
+      if (value0 == NULL || value0->type == COGL_BOXED_NONE)
+        {
+          if (value1 != NULL && value1->type != COGL_BOXED_NONE)
+            return FALSE;
+        }
+      else if (!_cogl_boxed_value_equal (value0, value1))
+        return FALSE;
+    }
+
+  return TRUE;
+}
+
 void
 cogl_pipeline_get_color (CoglPipeline *pipeline,
                          CoglColor    *color)
@@ -1262,6 +1350,106 @@ cogl_pipeline_set_point_size (CoglPipeline *pipeline,
                                    _cogl_pipeline_point_size_equal);
 }
 
+typedef struct
+{
+  int location;
+  CoglPipelineUniformOverride *previous_override;
+  CoglPipelineUniformOverride *found_override;
+  CoglPipelineUniformOverride *it;
+} FindUniformOverrideClosure;
+
+static gboolean
+find_uniform_override_cb (int it_location,
+                          void *user_data)
+{
+  FindUniformOverrideClosure *data = user_data;
+
+  if (it_location < data->location)
+    {
+      data->previous_override = data->it;
+      data->it = COGL_SLIST_NEXT (data->it, list_node);
+
+      return TRUE;
+    }
+  else
+    {
+      if (it_location == data->location)
+        data->found_override = data->it;
+
+      return FALSE;
+    }
+}
+
+static CoglBoxedValue *
+_cogl_pipeline_override_uniform (CoglPipeline *pipeline,
+                                 int location)
+{
+  CoglPipelineState state = COGL_PIPELINE_STATE_POINT_SIZE;
+  CoglPipelineUniformsState *uniforms_state;
+  CoglPipeline *authority;
+  FindUniformOverrideClosure find_data;
+  CoglPipelineUniformOverride *override;
+
+  _COGL_GET_CONTEXT (ctx, NULL);
+
+  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);
+
+  authority = _cogl_pipeline_get_authority (pipeline, state);
+
+  /* - Flush journal primitives referencing the current state.
+   * - Make sure the pipeline has no dependants so it may be modified.
+   * - If the pipeline isn't currently an authority for the state being
+   *   changed, then initialize that state from the current authority.
+   */
+  _cogl_pipeline_pre_change_notify (pipeline, state, NULL, FALSE);
+
+  uniforms_state = &authority->big_state->uniforms_state;
+
+  find_data.previous_override = NULL;
+  find_data.found_override = NULL;
+  find_data.it = COGL_SLIST_FIRST (&uniforms_state->override_list);
+  find_data.location = location;
+
+  _cogl_bitmask_foreach (&uniforms_state->override_mask,
+                         find_uniform_override_cb,
+                         &find_data);
+
+  /* If this pipeline already has an override for this value then we
+     can just use it directly */
+  if (find_data.found_override)
+    return &find_data.found_override->value;
+
+  /* We need to add a new override */
+  override = g_slice_new (CoglPipelineUniformOverride);
+  _cogl_boxed_value_init (&override->value);
+
+  if (find_data.previous_override)
+    COGL_SLIST_INSERT_AFTER (find_data.previous_override, override, list_node);
+  else
+    COGL_SLIST_INSERT_HEAD (&uniforms_state->override_list,
+                            override,
+                            list_node);
+
+  _cogl_bitmask_set (&uniforms_state->override_mask, location, TRUE);
+
+  return &override->value;
+}
+
+void
+cogl_pipeline_set_uniform_1f (CoglPipeline *pipeline,
+                              int uniform_location,
+                              float value)
+{
+  CoglBoxedValue *boxed_value;
+
+  boxed_value = _cogl_pipeline_override_uniform (pipeline, uniform_location);
+
+  _cogl_boxed_value_set_1f (boxed_value, value);
+}
+
 void
 _cogl_pipeline_hash_color_state (CoglPipeline *authority,
                                  CoglPipelineHashState *state)
@@ -1455,63 +1643,3 @@ _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 9f755aa..eeb3858 100644
--- a/cogl/cogl-pipeline.c
+++ b/cogl/cogl-pipeline.c
@@ -469,9 +469,8 @@ _cogl_pipeline_free (CoglPipeline *pipeline)
                                list_node,
                                tmp)
         {
-          if (override->value.count > 1)
-            g_free (override->value.v.array);
-          g_free (override);
+          _cogl_boxed_value_destroy (&override->value);
+          g_slice_free (CoglPipelineUniformOverride, override);
         }
 
       _cogl_bitmask_destroy (&uniforms_state->override_mask);
diff --git a/cogl/cogl-pipeline.h b/cogl/cogl-pipeline.h
index d93c6f8..11b71a0 100644
--- a/cogl/cogl-pipeline.h
+++ b/cogl/cogl-pipeline.h
@@ -138,6 +138,33 @@ cogl_pipeline_foreach_layer (CoglPipeline *pipeline,
                              CoglPipelineLayerCallback callback,
                              void *user_data);
 
+#define cogl_pipeline_get_uniform_location \
+        cogl_pipeline_get_uniform_location_EXP
+/**
+ * cogl_pipeline_get_uniform_location:
+ * @pipeline: A #CoglPipeline object
+ * @uniform_name: The name of a uniform
+ *
+ * This is used to get an integer representing the uniform with the
+ * name @uniform_name. The integer can be passed to functions such as
+ * cogl_pipeline_set_uniform_1f() to set the value of a uniform.
+ *
+ * This function will always return a valid integer. Ie, unlike
+ * OpenGL, it does not return -1 if the uniform is not available in
+ * this pipeline so it can not be used to test whether uniforms are
+ * present. It is not necessary to set the program on the pipeline
+ * before calling this function.
+ *
+ * Return value: A integer representing the location of the given uniform.
+ *
+ * Since: 2.0
+ * Stability: Unstable
+ */
+int
+cogl_pipeline_get_uniform_location (CoglPipeline *pipeline,
+                                    const char *uniform_name);
+
+
 #endif /* COGL_ENABLE_EXPERIMENTAL_API */
 
 G_END_DECLS



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