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



commit c77e69c8652b7e19630d3317892a704855f6f188
Author: Neil Roberts <neil linux intel com>
Date:   Mon Oct 31 14:22:18 2011 +0000

    Stash

 cogl/cogl-bitmask.h               |   20 +++++++++
 cogl/cogl-pipeline-private.h      |    3 +
 cogl/cogl-pipeline-progend-glsl.c |   82 ++++++++++++++++++++++++++++++++++--
 cogl/cogl-pipeline.c              |    3 +
 4 files changed, 103 insertions(+), 5 deletions(-)
---
diff --git a/cogl/cogl-bitmask.h b/cogl/cogl-bitmask.h
index e94f367..a1710af 100644
--- a/cogl/cogl-bitmask.h
+++ b/cogl/cogl-bitmask.h
@@ -251,6 +251,26 @@ _cogl_bitmask_is_empty (const CoglBitmask *bitmask)
     return *bitmask == _cogl_bitmask_from_bits (0);
 }
 
+/*
+ * _cogl_bitmask_set_flags:
+ * @bitmask: A pointer to a bitmask
+ * @flags: An array of unsigned ints
+ *
+ * This 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)
+{
+  if (_cogl_bitmask_has_array (bitmask))
+    return _cogl_bitmask_set_flags_array (bitmask, flags);
+  else
+    flags[0] |= _cogl_bitmask
+}
+#endif
+
 G_END_DECLS
 
 #endif /* __COGL_BITMASK_H */
diff --git a/cogl/cogl-pipeline-private.h b/cogl/cogl-pipeline-private.h
index eaf807f..c9e91bc 100644
--- a/cogl/cogl-pipeline-private.h
+++ b/cogl/cogl-pipeline-private.h
@@ -375,6 +375,9 @@ struct _CoglPipelineUniformOverride
 typedef struct
 {
   CoglBitmask override_mask;
+  /* Uniforms that have been modified since this pipeline was last
+     flushed */
+  CoglBitmask changed_mask;
   CoglPipelineUniformOverrideList override_list;
 } CoglPipelineUniformsState;
 
diff --git a/cogl/cogl-pipeline-progend-glsl.c b/cogl/cogl-pipeline-progend-glsl.c
index 6d94a14..9cda3c7 100644
--- a/cogl/cogl-pipeline-progend-glsl.c
+++ b/cogl/cogl-pipeline-progend-glsl.c
@@ -555,6 +555,27 @@ update_builtin_uniforms (CoglPipeline *pipeline,
 
 #endif /* HAVE_COGL_GLES2 */
 
+static GSList *
+get_ancestors (CoglPipeline *pipeline)
+{
+  GSList *ancestors = NULL;
+
+  while (pipeline)
+    ancestors = g_slist_prepend (ancestors, pipeline);
+
+  return ancestors;
+}
+
+typedef struct
+{
+  CoglProgramState *program_state;
+  CoglPipeline *flushed_ancestor;
+  unsigned int *force_flush_uniforms;
+  unsigned int *flushed_uniforms;
+  const CoglPipelineUniformsState *uniforms_state;
+  int uniforms_count;
+} FlushUniformsClosure;
+
 static void
 _cogl_pipeline_progend_glsl_flush_uniforms (CoglPipeline *pipeline,
                                             CoglPipelineProgramState *
@@ -562,7 +583,24 @@ _cogl_pipeline_progend_glsl_flush_uniforms (CoglPipeline *pipeline,
                                             GLuint gl_program,
                                             gboolean program_changed)
 {
-  CoglPipeline *flushed_ancestor;
+  FlushUniformsClosure data;
+  int uniforms_count;
+
+  _cogl_bitmask_init (&data.force_flush_uniforms);
+
+  if (pipeline->differences & COGL_PIPELINE_STATE_UNIFORMS)
+    data.uniforms_state = &pipeline->big_state->data.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);
+  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);
 
   /* Try to find a common ancestor for the values that were already
      flushed on the pipeline that this program state was last used for
@@ -571,16 +609,50 @@ _cogl_pipeline_progend_glsl_flush_uniforms (CoglPipeline *pipeline,
   if (program_changed)
     {
       /* The program has changed so we have no common ancestor and we
-         need to flush everything */
-      flushed_ancestor = NULL;
-      /* All of the uniform locations are invalid */
+         need to flush everything. All of the uniform locations are
+         invalid */
       if (program_state->uniform_locations)
         g_array_set_size (program_state->uniform_locations, 0);
     }
   else
     {
-      flushed_ancestor = program_state->last_used_for_pipeline;
+      GSList *flushed_ancestors =
+        get_ancestors (program_state->last_used_for_pipeline);
+      GSList *new_ancestors =
+        get_ancestors (pipeline);
+      GSList *a, *b;
+
+      for (a = flushed_ancestors, b = new_ancestors;
+           a && b && a->data == b->data;
+           a = a->next, b = b->next)
+        data.flushed_ancestor = a->data;
+
+      g_slist_free (flushed_ancestors);
+      g_slist_free (new_ancestors);
+
+      /* 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);
+
+      /* 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);
+          a = a->next;
+        }
     }
+
+  if (data.uniforms_state)
+    _cogl_bitmask_clear (&data.uniforms_state->changed_mask);
+
+  _cogl_bitmask_destroy (&data.force_flush_uniforms);
 }
 
 static void
diff --git a/cogl/cogl-pipeline.c b/cogl/cogl-pipeline.c
index 5575f2b..ba79aad 100644
--- a/cogl/cogl-pipeline.c
+++ b/cogl/cogl-pipeline.c
@@ -223,6 +223,7 @@ _cogl_pipeline_init_default_pipeline (void)
   cull_face_state->front_winding = COGL_WINDING_COUNTER_CLOCKWISE;
 
   _cogl_bitmask_init (&uniforms_state->override_mask);
+  _cogl_bitmask_init (&uniforms_state->changed_mask);
   COGL_SLIST_INIT (&uniforms_state->override_list);
 
   ctx->default_pipeline = _cogl_pipeline_object_new (pipeline);
@@ -478,6 +479,7 @@ _cogl_pipeline_free (CoglPipeline *pipeline)
         }
 
       _cogl_bitmask_destroy (&uniforms_state->override_mask);
+      _cogl_bitmask_destroy (&uniforms_state->changed_mask);
     }
 
   if (pipeline->differences & COGL_PIPELINE_STATE_NEEDS_BIG_STATE)
@@ -1038,6 +1040,7 @@ _cogl_pipeline_init_multi_property_sparse_state (CoglPipeline *pipeline,
         CoglPipelineUniformsState *uniforms_state =
           &pipeline->big_state->uniforms_state;
         _cogl_bitmask_init (&uniforms_state->override_mask);
+        _cogl_bitmask_init (&uniforms_state->changed_mask);
         COGL_SLIST_INIT (&uniforms_state->override_list);
       }
     }



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