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



commit d252d5bb24afec1f5c2ceb78e6d560079a452efd
Author: Neil Roberts <neil linux intel com>
Date:   Fri Oct 28 15:01:09 2011 +0100

    Stash

 cogl/cogl-context.c                |    7 ++++-
 cogl/cogl-pipeline-progend-glsl.c  |   56 +++++++++++++++++++++++++++++++++++-
 cogl/cogl-pipeline-state-private.h |    4 ++
 cogl/cogl-pipeline-state.c         |   17 ++++++++---
 cogl/cogl-pipeline-state.h         |    5 +++
 cogl/cogl-pipeline.c               |   31 +++++++++++---------
 6 files changed, 99 insertions(+), 21 deletions(-)
---
diff --git a/cogl/cogl-context.c b/cogl/cogl-context.c
index 1a8f907..386d6bf 100644
--- a/cogl/cogl-context.c
+++ b/cogl/cogl-context.c
@@ -204,7 +204,12 @@ cogl_context_new (CoglDisplay *display,
       g_assert_not_reached ();
     }
 
-  context->uniform_names = NULL;
+  /* 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);
 
   /* Initialise the driver specific state */
   _cogl_init_feature_overrides (context);
diff --git a/cogl/cogl-pipeline-progend-glsl.c b/cogl/cogl-pipeline-progend-glsl.c
index 15273f9..46fdd41 100644
--- a/cogl/cogl-pipeline-progend-glsl.c
+++ b/cogl/cogl-pipeline-progend-glsl.c
@@ -139,6 +139,17 @@ typedef struct
    * so know if we need to update all of the uniforms */
   CoglPipeline *last_used_for_pipeline;
 
+  /* TRUE if any of the uniforms on this pipeline have been modified
+     since it was last flushed. If so then we'll flush all of the
+     uniforms that this pipeline overrides (but not necessarily those
+     that the parent overrides if we've already flushed them) */
+  gboolean uniforms_changed;
+
+  /* Array of GL uniform locations indexed by Cogl's uniform
+     location. We are careful only to allocated this array if a custom
+     uniform is actually set */
+  GArray *uniform_locations;
+
   UnitState *unit_state;
 } CoglPipelineProgramState;
 
@@ -308,6 +319,8 @@ program_state_new (int n_layers)
   program_state->program = 0;
   program_state->n_tex_coord_attribs = 0;
   program_state->unit_state = g_new (UnitState, n_layers);
+  program_state->uniforms_changed = TRUE;
+  program_state->uniform_locations = NULL;
 #ifdef HAVE_COGL_GLES2
   program_state->tex_coord_attribute_locations = NULL;
   program_state->flushed_modelview_stack = NULL;
@@ -348,6 +361,9 @@ destroy_program_state (void *user_data,
 
       g_free (program_state->unit_state);
 
+      if (program_state->uniform_locations)
+        g_array_free (program_state->uniform_locations, TRUE);
+
       g_slice_free (CoglPipelineProgramState, program_state);
     }
 }
@@ -539,6 +555,34 @@ update_builtin_uniforms (CoglPipeline *pipeline,
 #endif /* HAVE_COGL_GLES2 */
 
 static void
+_cogl_pipeline_progend_glsl_flush_uniforms (CoglPipeline *pipeline,
+                                            CoglPipelineProgramState *
+                                                                  program_state,
+                                            GLuint gl_program,
+                                            gboolean program_changed)
+{
+  CoglPipeline *flushed_ancestor;
+
+  /* Try to find a common ancestor for the values that were already
+     flushed on the pipeline that this program state was last used for
+     so we can avoid flushing those */
+
+  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 */
+      if (program_state->uniform_locations)
+        g_array_set_size (program_state->uniform_locations, 0);
+    }
+  else
+    {
+      flushed_ancestor = program_state->last_used_for_pipeline;
+    }
+}
+
+static void
 _cogl_pipeline_progend_glsl_end (CoglPipeline *pipeline,
                                  unsigned long pipelines_difference,
                                  int n_tex_coord_attribs)
@@ -745,6 +789,11 @@ _cogl_pipeline_progend_glsl_end (CoglPipeline *pipeline,
     }
 #endif
 
+  _cogl_pipeline_progend_glsl_flush_uniforms (pipeline,
+                                              program_state,
+                                              gl_program,
+                                              program_changed);
+
   if (user_program)
     _cogl_program_flush_uniforms (user_program,
                                   gl_program,
@@ -764,7 +813,12 @@ _cogl_pipeline_progend_glsl_pre_change_notify (CoglPipeline *pipeline,
 
   if ((change & _cogl_pipeline_get_state_for_fragment_codegen (ctx)))
     dirty_program_state (pipeline);
-
+  else if ((change & COGL_PIPELINE_STATE_UNIFORMS))
+    {
+      CoglPipelineProgramState *program_state = get_program_state (pipeline);
+      if (program_state)
+        program_state->uniforms_changed = TRUE;
+    }
 #ifdef HAVE_COGL_GLES2
   else if (ctx->driver == COGL_DRIVER_GLES2)
     {
diff --git a/cogl/cogl-pipeline-state-private.h b/cogl/cogl-pipeline-state-private.h
index 8b8fe3f..dbc0bc6 100644
--- a/cogl/cogl-pipeline-state-private.h
+++ b/cogl/cogl-pipeline-state-private.h
@@ -143,4 +143,8 @@ void
 _cogl_pipeline_hash_cull_face_state (CoglPipeline *authority,
                                      CoglPipelineHashState *state);
 
+void
+_cogl_pipeline_hash_uniforms_state (CoglPipeline *authority,
+                                    CoglPipelineHashState *state);
+
 #endif /* __COGL_PIPELINE_STATE_PRIVATE_H */
diff --git a/cogl/cogl-pipeline-state.c b/cogl/cogl-pipeline-state.c
index 7709335..3b987c4 100644
--- a/cogl/cogl-pipeline-state.c
+++ b/cogl/cogl-pipeline-state.c
@@ -1384,9 +1384,8 @@ static CoglBoxedValue *
 _cogl_pipeline_override_uniform (CoglPipeline *pipeline,
                                  int location)
 {
-  CoglPipelineState state = COGL_PIPELINE_STATE_POINT_SIZE;
+  CoglPipelineState state = COGL_PIPELINE_STATE_UNIFORMS;
   CoglPipelineUniformsState *uniforms_state;
-  CoglPipeline *authority;
   FindUniformOverrideClosure find_data;
   CoglPipelineUniformOverride *override;
 
@@ -1397,8 +1396,6 @@ _cogl_pipeline_override_uniform (CoglPipeline *pipeline,
   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
@@ -1406,7 +1403,7 @@ _cogl_pipeline_override_uniform (CoglPipeline *pipeline,
    */
   _cogl_pipeline_pre_change_notify (pipeline, state, NULL, FALSE);
 
-  uniforms_state = &authority->big_state->uniforms_state;
+  uniforms_state = &pipeline->big_state->uniforms_state;
 
   find_data.previous_override = NULL;
   find_data.found_override = NULL;
@@ -1643,3 +1640,13 @@ _cogl_pipeline_hash_cull_face_state (CoglPipeline *authority,
                                      cull_face_state,
                                      sizeof (CoglPipelineCullFaceState));
 }
+
+void
+_cogl_pipeline_hash_uniforms_state (CoglPipeline *authority,
+                                    CoglPipelineHashState *state)
+{
+  /* This isn't used anywhere yet because the uniform state doesn't
+     affect program generation. It's quite a hassle to implement so
+     let's just leave it until something actually needs it */
+  g_warn_if_reached ();
+}
diff --git a/cogl/cogl-pipeline-state.h b/cogl/cogl-pipeline-state.h
index 7015b00..fa97863 100644
--- a/cogl/cogl-pipeline-state.h
+++ b/cogl/cogl-pipeline-state.h
@@ -686,6 +686,11 @@ void
 cogl_pipeline_get_depth_state (CoglPipeline *pipeline,
                                CoglDepthState *state_out);
 
+void
+cogl_pipeline_set_uniform_1f (CoglPipeline *pipeline,
+                              int uniform_location,
+                              float value);
+
 #endif /* COGL_ENABLE_EXPERIMENTAL_API */
 
 G_END_DECLS
diff --git a/cogl/cogl-pipeline.c b/cogl/cogl-pipeline.c
index eeb3858..2bcef9b 100644
--- a/cogl/cogl-pipeline.c
+++ b/cogl/cogl-pipeline.c
@@ -111,6 +111,7 @@ _cogl_pipeline_init_default_pipeline (void)
   CoglDepthState *depth_state = &big_state->depth_state;
   CoglPipelineLogicOpsState *logic_ops_state = &big_state->logic_ops_state;
   CoglPipelineCullFaceState *cull_face_state = &big_state->cull_face_state;
+  CoglPipelineUniformsState *uniforms_state = &big_state->uniforms_state;
 
   _COGL_GET_CONTEXT (ctx, NO_RETVAL);
 
@@ -221,6 +222,9 @@ _cogl_pipeline_init_default_pipeline (void)
   cull_face_state->mode = COGL_PIPELINE_CULL_FACE_MODE_NONE;
   cull_face_state->front_winding = COGL_WINDING_COUNTER_CLOCKWISE;
 
+  _cogl_bitmask_init (&uniforms_state->override_mask);
+  COGL_SLIST_INIT (&uniforms_state->override_list);
+
   ctx->default_pipeline = _cogl_pipeline_object_new (pipeline);
 }
 
@@ -1029,6 +1033,13 @@ _cogl_pipeline_init_multi_property_sparse_state (CoglPipeline *pipeline,
                 sizeof (CoglPipelineCullFaceState));
         break;
       }
+    case COGL_PIPELINE_STATE_UNIFORMS:
+      {
+        CoglPipelineUniformsState *uniforms_state =
+          &pipeline->big_state->uniforms_state;
+        _cogl_bitmask_init (&uniforms_state->override_mask);
+        COGL_SLIST_INIT (&uniforms_state->override_list);
+      }
     }
 }
 
@@ -2628,9 +2639,11 @@ _cogl_pipeline_init_state_hash_functions (void)
     _cogl_pipeline_hash_point_size_state;
   state_hash_functions[COGL_PIPELINE_STATE_LOGIC_OPS_INDEX] =
     _cogl_pipeline_hash_logic_ops_state;
+  state_hash_functions[COGL_PIPELINE_STATE_UNIFORMS_INDEX] =
+    _cogl_pipeline_hash_uniforms_state;
 
   /* So we get a big error if we forget to update this code! */
-  g_assert (COGL_PIPELINE_STATE_SPARSE_COUNT == 13);
+  g_assert (COGL_PIPELINE_STATE_SPARSE_COUNT == 14);
 }
 
 unsigned int
@@ -2845,19 +2858,9 @@ cogl_pipeline_get_uniform_location (CoglPipeline *pipeline,
      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_node = g_hash_table_lookup (ctx->uniform_names, uniform_name);
+  if (name_node)
+    return name_node->index;
 
   name_len = strlen (uniform_name);
   name_node = g_malloc (sizeof (CoglPipelineUniformName) + name_len);



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