[cogl] pipeline: Reset last_used_for_pipeline when the pipeline is destroyed



commit 49e733fcdcb12978ae165c6352e2c0acb6bc6757
Author: Neil Roberts <neil linux intel com>
Date:   Sun Oct 23 20:22:23 2011 +0100

    pipeline: Reset last_used_for_pipeline when the pipeline is destroyed
    
    Both the GLSL and the ARBfp pipeline backends were using a variable
    called last_used_for_pipeline to keep track of the last pipeline that
    the shader or program state was used for. If this address is the same
    as last time when the pipeline state is flushed then Cogl will only
    flush the uniforms that have been modified, otherwise it will flush
    all of them. The problem with this is that there was nothing to keep
    that address alive so it could be destroyed and reused for a different
    pipeline by the time the shader state is reused. This is quite likely
    to happen in an application using legacy state because in that case
    the shader state will always be used with a one-shot pipeline that
    will likely be recycled in the next frame.
    
    There is already a destroy callback to unref the shader state when the
    pipeline is destroyed so this patch just makes that callback also
    clear the last_used_for_pipeline pointer if it matches the pipeline
    being destroyed.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=662542
    
    Reviewed-by: Robert Bragg <robert linux intel com>

 cogl/cogl-pipeline-fragend-arbfp.c |   18 +++++++++++++-----
 cogl/cogl-pipeline-progend-glsl.c  |   18 +++++++++++++-----
 2 files changed, 26 insertions(+), 10 deletions(-)
---
diff --git a/cogl/cogl-pipeline-fragend-arbfp.c b/cogl/cogl-pipeline-fragend-arbfp.c
index 2270767..42d18fe 100644
--- a/cogl/cogl-pipeline-fragend-arbfp.c
+++ b/cogl/cogl-pipeline-fragend-arbfp.c
@@ -109,12 +109,20 @@ get_shader_state (CoglPipeline *pipeline)
 }
 
 static void
-destroy_shader_state (void *user_data)
+destroy_shader_state (void *user_data,
+                      void *instance)
 {
   CoglPipelineShaderState *shader_state = user_data;
 
   _COGL_GET_CONTEXT (ctx, NO_RETVAL);
 
+  /* If the shader state was last used for this pipeline then clear it
+     so that if same address gets used again for a new pipeline then
+     we won't think it's the same pipeline and avoid updating the
+     constants */
+  if (shader_state->last_used_for_pipeline == instance)
+    shader_state->last_used_for_pipeline = NULL;
+
   if (--shader_state->ref_count == 0)
     {
       if (shader_state->gl_program)
@@ -132,10 +140,10 @@ destroy_shader_state (void *user_data)
 static void
 set_shader_state (CoglPipeline *pipeline, CoglPipelineShaderState *shader_state)
 {
-  cogl_object_set_user_data (COGL_OBJECT (pipeline),
-                             &shader_state_key,
-                             shader_state,
-                             destroy_shader_state);
+  _cogl_object_set_user_data (COGL_OBJECT (pipeline),
+                              &shader_state_key,
+                              shader_state,
+                              destroy_shader_state);
 }
 
 static void
diff --git a/cogl/cogl-pipeline-progend-glsl.c b/cogl/cogl-pipeline-progend-glsl.c
index 10d9266..15273f9 100644
--- a/cogl/cogl-pipeline-progend-glsl.c
+++ b/cogl/cogl-pipeline-progend-glsl.c
@@ -319,12 +319,20 @@ program_state_new (int n_layers)
 }
 
 static void
-destroy_program_state (void *user_data)
+destroy_program_state (void *user_data,
+                       void *instance)
 {
   CoglPipelineProgramState *program_state = user_data;
 
   _COGL_GET_CONTEXT (ctx, NO_RETVAL);
 
+  /* If the program state was last used for this pipeline then clear
+     it so that if same address gets used again for a new pipeline
+     then we won't think it's the same pipeline and avoid updating the
+     uniforms */
+  if (program_state->last_used_for_pipeline == instance)
+    program_state->last_used_for_pipeline = NULL;
+
   if (--program_state->ref_count == 0)
     {
 #ifdef HAVE_COGL_GLES2
@@ -348,10 +356,10 @@ static void
 set_program_state (CoglPipeline *pipeline,
                   CoglPipelineProgramState *program_state)
 {
-  cogl_object_set_user_data (COGL_OBJECT (pipeline),
-                             &program_state_key,
-                             program_state,
-                             destroy_program_state);
+  _cogl_object_set_user_data (COGL_OBJECT (pipeline),
+                              &program_state_key,
+                              program_state,
+                              destroy_program_state);
 }
 
 static void



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