cogl-pipeline: Fix reference counting on promoting weak parents

When a copy is made of a weak pipeline it tries to promote the weak
parent by taking a reference on that weak pipeline's parent. However
promote_weak_ancestors was instead always taking a reference on the
first parent, regardless of whether it was weak. The corresponding
revert_weak_ancestors function which is supposed to undo the effect of
promote_weak_ancestors only unref'd the parent if was weak. This meant
that any non-weak pipeline copy would end up leaking a reference on
its parent.

This patch changes both functions to have a similar loop. It loops
through all of the parents of the pipeline until it finds one that is
not weak and refs or unrefs the *parent* of that pipeline instead of
the pipeline itself.

Signed-off-by: Robert Bragg <robert@linux.intel.com>
This commit is contained in:
Neil Roberts 2011-07-06 12:28:07 +01:00
parent 2f0a20cdb5
commit 17a558a386

View File

@ -375,37 +375,40 @@ _cogl_pipeline_promote_weak_ancestors (CoglPipeline *strong)
g_return_if_fail (!strong->is_weak); g_return_if_fail (!strong->is_weak);
for (n = COGL_PIPELINE_NODE (strong)->parent; n; n = n->parent) /* If the parent of strong is weak, then we want to promote it by
{ taking a reference on strong's grandparent. We don't need to take
CoglPipeline *pipeline = COGL_PIPELINE (n); a reference on strong's direct parent */
cogl_object_ref (pipeline); if (COGL_PIPELINE_NODE (strong)->parent == NULL)
if (!pipeline->is_weak)
return; return;
}
for (n = COGL_PIPELINE_NODE (strong)->parent;
/* We can assume that all weak pipelines have a parent */
COGL_PIPELINE (n)->is_weak;
n = n->parent)
/* 'n' is weak so we take a reference on its parent */
cogl_object_ref (n->parent);
} }
static void static void
_cogl_pipeline_revert_weak_ancestors (CoglPipeline *strong) _cogl_pipeline_revert_weak_ancestors (CoglPipeline *strong)
{ {
CoglPipeline *parent = _cogl_pipeline_get_parent (strong);
CoglPipelineNode *n; CoglPipelineNode *n;
g_return_if_fail (!strong->is_weak); g_return_if_fail (!strong->is_weak);
if (!parent || !parent->is_weak) /* This reverts the effect of calling
_cogl_pipeline_promote_weak_ancestors */
if (COGL_PIPELINE_NODE (strong)->parent == NULL)
return; return;
for (n = COGL_PIPELINE_NODE (strong)->parent; n; n = n->parent) for (n = COGL_PIPELINE_NODE (strong)->parent;
{ /* We can assume that all weak pipelines have a parent */
CoglPipeline *pipeline = COGL_PIPELINE (n); COGL_PIPELINE (n)->is_weak;
n = n->parent)
cogl_object_unref (pipeline); /* 'n' is weak so we unref its parent */
cogl_object_unref (n->parent);
if (!pipeline->is_weak)
return;
}
} }
/* XXX: Always have an eye out for opportunities to lower the cost of /* XXX: Always have an eye out for opportunities to lower the cost of