[cogl/wip/example-crate: 14/20] pipeline: don't prune user pipelines



commit 9670cf8567a87fb03ce859285605c266e0e1f7be
Author: Robert Bragg <robert linux intel com>
Date:   Mon Jun 27 13:07:53 2011 +0100

    pipeline: don't prune user pipelines
    
    We encourage developers to create template pipelines that we can
    associated re-usable state such as shaders with, but our logic for
    pruning redundant ancestry was actually pruning those templates!
    
    We now keep track of which pipelines are created for internal purposes
    (e.g. copy-on-write pipelines created when modifying an immutable
    pipeline referenced in the journal) and we only ever prune those. We no
    longer prune user created pipelines.
    
    We are careful to consider that pipelines that are initially created
    explicitly by the user, might eventually become internal only. This
    is true if the ref_count of a pipeline is equal to the number of
    children it has, since we know the application no longer owns a
    reference to the pipeline. In this situation we will allow pruning.
    
    NB: The main reason we need to do pruning is to consider cases where
    the user toggles back and fourth between the same states and we need to
    avoid creating an endlessly growing chain

 cogl/cogl-pipeline-private.h |   10 +++++++++
 cogl/cogl-pipeline.c         |   43 +++++++++++++++++++++++++++++++++++++----
 2 files changed, 48 insertions(+), 5 deletions(-)
---
diff --git a/cogl/cogl-pipeline-private.h b/cogl/cogl-pipeline-private.h
index c7aa323..fd08a4f 100644
--- a/cogl/cogl-pipeline-private.h
+++ b/cogl/cogl-pipeline-private.h
@@ -711,6 +711,16 @@ struct _CoglPipeline
    */
   unsigned int          fragend_priv_set_mask:COGL_PIPELINE_N_FRAGENDS;
 
+  /* If this pipeline was explicitly constructed/copied by the user
+   * then we'll avoid touching it during ancestor pruning. This way
+   * we'll only prune internal copy-on-write pipelines.
+   *
+   * NB: We used to do more agressive pruning, but it would negate the
+   * effort of users to create template pipelines that could be used
+   * to share state, including shaders, because those template
+   * materials would often be shadowed and then pruned. */
+  unsigned int          is_user_pipeline:1;
+
   /* Weak pipelines don't count as dependants on their parents which
    * means that the parent pipeline can be modified without
    * considering how the modifications may affect the weak pipeline.
diff --git a/cogl/cogl-pipeline.c b/cogl/cogl-pipeline.c
index 45fc077..6e89c92 100644
--- a/cogl/cogl-pipeline.c
+++ b/cogl/cogl-pipeline.c
@@ -245,6 +245,9 @@ _cogl_pipeline_init_default_pipeline (void)
   _cogl_pipeline_node_init (COGL_PIPELINE_NODE (pipeline));
 
   pipeline->is_weak = FALSE;
+  /* We say the default pipeline is a user pipeline to stop it
+   * very being pruned. */
+  pipeline->is_user_pipeline = TRUE;
   pipeline->journal_ref_count = 0;
   pipeline->fragend = COGL_PIPELINE_FRAGEND_UNDEFINED;
   pipeline->vertend = COGL_PIPELINE_VERTEND_UNDEFINED;
@@ -439,6 +442,8 @@ _cogl_pipeline_copy (CoglPipeline *src, gboolean is_weak)
 
   pipeline->is_weak = is_weak;
 
+  pipeline->is_user_pipeline = FALSE;
+
   pipeline->journal_ref_count = 0;
 
   pipeline->differences = 0;
@@ -482,7 +487,9 @@ _cogl_pipeline_copy (CoglPipeline *src, gboolean is_weak)
 CoglPipeline *
 cogl_pipeline_copy (CoglPipeline *src)
 {
-  return _cogl_pipeline_copy (src, FALSE);
+  CoglPipeline *copy = _cogl_pipeline_copy (src, FALSE);
+  copy->is_user_pipeline = TRUE;
+  return copy;
 }
 
 CoglPipeline *
@@ -495,6 +502,7 @@ _cogl_pipeline_weak_copy (CoglPipeline *pipeline,
 
   copy = _cogl_pipeline_copy (pipeline, TRUE);
   copy_pipeline = COGL_PIPELINE (copy);
+  copy_pipeline->is_user_pipeline = TRUE;
   copy_pipeline->destroy_callback = callback;
   copy_pipeline->destroy_data = user_data;
 
@@ -510,6 +518,7 @@ cogl_pipeline_new (void)
 
   new = cogl_pipeline_copy (ctx->default_pipeline);
   _cogl_pipeline_set_static_breadcrumb (new, "new");
+  new->is_user_pipeline = TRUE;
   return new;
 }
 
@@ -3852,10 +3861,34 @@ _cogl_pipeline_get_colorubv (CoglPipeline *pipeline,
   _cogl_color_get_rgba_4ubv (&authority->color, color);
 }
 
+static gboolean
+_cogl_pipeline_can_prune_ancestor (CoglPipeline *pipeline,
+                                   CoglPipeline *ancestor)
+{
+  /* If a pipeline is only referenced by its dependant children, then
+   * we no longer care that the pipeline was originally created by the
+   * user and consider it a candidate for pruning. */
+  if (ancestor->is_user_pipeline &&
+      (COGL_OBJECT (ancestor)->ref_count ==
+       g_list_length (COGL_PIPELINE_NODE (pipeline)->children)))
+    ancestor->is_user_pipeline = FALSE;
+
+  /* XXX: is it even worth having this special consideration, are we
+   * ever going to  */
+
+  if (!ancestor->is_user_pipeline &&
+      _cogl_pipeline_get_parent (ancestor) &&
+      (ancestor->differences | pipeline->differences) ==
+      pipeline->differences)
+    return TRUE;
+  else
+    return FALSE;
+}
+
 static void
 _cogl_pipeline_prune_redundant_ancestry (CoglPipeline *pipeline)
 {
-  CoglPipeline *new_parent = _cogl_pipeline_get_parent (pipeline);
+  CoglPipeline *new_parent;
 
   /* Before considering pruning redundant ancestry we check if this
    * pipeline is an authority for layer state and if so only consider
@@ -3878,11 +3911,11 @@ _cogl_pipeline_prune_redundant_ancestry (CoglPipeline *pipeline)
         return;
     }
 
+  new_parent = _cogl_pipeline_get_parent (pipeline);
+
   /* walk up past ancestors that are now redundant and potentially
    * reparent the pipeline. */
-  while (_cogl_pipeline_get_parent (new_parent) &&
-         (new_parent->differences | pipeline->differences) ==
-          pipeline->differences)
+  while (_cogl_pipeline_can_prune_ancestor (pipeline, new_parent))
     new_parent = _cogl_pipeline_get_parent (new_parent);
 
   if (new_parent != _cogl_pipeline_get_parent (pipeline))



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