material: use common node type for materials and layers

Since 365605cf42, materials and layers are represented in a tree
structure that allows traversing up through parents and iterating down
through children.  This re-works the related typedefs and reparenting
code so that they can be shared.
This commit is contained in:
Robert Bragg 2010-07-08 11:49:31 +01:00
parent 2d20589d8e
commit ea708094c5
3 changed files with 326 additions and 287 deletions

View File

@ -172,9 +172,12 @@ find_arbfp_authority (CoglMaterial *material)
/* Find the next ancestor after that, that also modifies state /* Find the next ancestor after that, that also modifies state
* affecting arbfp codegen... */ * affecting arbfp codegen... */
if (authority0->parent) if (_cogl_material_get_parent (authority0))
authority1 = _cogl_material_get_authority (authority0->parent, {
COGL_MATERIAL_STATE_LAYERS); authority1 =
_cogl_material_get_authority (_cogl_material_get_parent (authority0),
COGL_MATERIAL_STATE_LAYERS);
}
else else
return authority0; return authority0;
@ -210,12 +213,13 @@ find_arbfp_authority (CoglMaterial *material)
/* Find the next ancestor after that, that also modifies state /* Find the next ancestor after that, that also modifies state
* affecting arbfp codegen... */ * affecting arbfp codegen... */
if (!authority1->parent) if (!_cogl_material_get_parent (authority1))
break; break;
authority0 = authority1; authority0 = authority1;
authority1 = _cogl_material_get_authority (authority1->parent, authority1 =
COGL_MATERIAL_STATE_LAYERS); _cogl_material_get_authority (_cogl_material_get_parent (authority1),
COGL_MATERIAL_STATE_LAYERS);
if (authority1 == authority0) if (authority1 == authority0)
break; break;
} }
@ -967,9 +971,10 @@ _cogl_material_backend_arbfp_material_pre_change_notify (
} }
static gboolean static gboolean
invalidate_arbfp_authority_cache_cb (CoglMaterial *material, invalidate_arbfp_authority_cache_cb (CoglMaterialNode *node,
void *user_data) void *user_data)
{ {
CoglMaterial *material = COGL_MATERIAL (node);
invalidate_arbfp_authority_cache (material); invalidate_arbfp_authority_cache (material);
return TRUE; return TRUE;
} }
@ -982,9 +987,9 @@ _cogl_material_backend_arbfp_material_set_parent_notify (
* any of its descendants will now be invalid. */ * any of its descendants will now be invalid. */
invalidate_arbfp_authority_cache (material); invalidate_arbfp_authority_cache (material);
_cogl_material_foreach_child (material, _cogl_material_node_foreach_child (COGL_MATERIAL_NODE (material),
invalidate_arbfp_authority_cache_cb, invalidate_arbfp_authority_cache_cb,
NULL); NULL);
} }
static void static void

View File

@ -227,6 +227,48 @@ typedef struct
} CoglMaterialLayerBigState; } CoglMaterialLayerBigState;
/* Materials and layers represent their state in a tree structure where
* some of the state relating to a given material or layer may actually
* be owned by one if is ancestors in the tree. We have a common data
* type to track the tree heirachy so we can share code... */
typedef struct _CoglMaterialNode CoglMaterialNode;
struct _CoglMaterialNode
{
/* the parent in terms of class hierarchy, so anything inheriting
* from CoglMaterialNode also inherits from CoglObject. */
CoglObject _parent;
/* The parent material/layer */
CoglMaterialNode *parent;
/* As an optimization for creating leaf node materials/layers (the
* most common) we don't require any list node allocations to link
* to a single descendant. */
CoglMaterialNode *first_child;
/* Determines if node->first_child and node->children are
* initialized pointers. */
gboolean has_children;
/* Materials and layers are sparse structures defined as a diff
* against their parent and may have multiple children which depend
* on them to define the values of properties which they don't
* change. */
GList *children;
};
#define COGL_MATERIAL_NODE(X) ((CoglMaterialNode *)(X))
typedef void (*CoglMaterialNodeUnparentVFunc) (CoglMaterialNode *node);
typedef gboolean (*CoglMaterialNodeChildCallback) (CoglMaterialNode *child,
void *user_data);
void
_cogl_material_node_foreach_child (CoglMaterialNode *node,
CoglMaterialNodeChildCallback callback,
void *user_data);
struct _CoglMaterialLayer struct _CoglMaterialLayer
{ {
/* XXX: Please think twice about adding members that *have* be /* XXX: Please think twice about adding members that *have* be
@ -243,8 +285,11 @@ struct _CoglMaterialLayer
* layers or if instead it can go under ->big_state. * layers or if instead it can go under ->big_state.
*/ */
/* the parent in terms of class hierarchy */ /* Layers represent their state in a tree structure where some of
CoglObject _parent; * the state relating to a given material or layer may actually be
* owned by one if is ancestors in the tree. We have a common data
* type to track the tree heirachy so we can share code... */
CoglMaterialNode _parent;
/* Some layers have a material owner, which is to say that the layer /* Some layers have a material owner, which is to say that the layer
* is referenced in that materials->layer_differences list. A layer * is referenced in that materials->layer_differences list. A layer
@ -252,21 +297,6 @@ struct _CoglMaterialLayer
* other layers that keeps track of some shared state. */ * other layers that keeps track of some shared state. */
CoglMaterial *owner; CoglMaterial *owner;
/* Layers are sparse structures defined as a diff against
* their parent... */
CoglMaterialLayer *parent;
/* As an optimization for creating leaf node layers (the most
* common) we don't require any list node allocations to link
* to a single descendant. */
CoglMaterialLayer *first_child;
/* Layers are sparse structures defined as a diff against
* their parent and may have multiple children which depend
* on them to define the values of properties which they don't
* change. */
GList *children;
/* The lowest index is blended first then others on top */ /* The lowest index is blended first then others on top */
int index; int index;
@ -316,10 +346,6 @@ struct _CoglMaterialLayer
/* bitfields */ /* bitfields */
/* Determines if layer->first_child and layer->children are
* initialized pointers. */
unsigned int has_children:1;
/* Determines if layer->big_state is valid */ /* Determines if layer->big_state is valid */
unsigned int has_big_state:1; unsigned int has_big_state:1;
@ -481,33 +507,17 @@ struct _CoglMaterial
* materials or if instead it can go under ->big_state. * materials or if instead it can go under ->big_state.
*/ */
/* the parent in terms of class hierarchy */ /* Layers represent their state in a tree structure where some of
CoglObject _parent; * the state relating to a given material or layer may actually be
* owned by one if is ancestors in the tree. We have a common data
* type to track the tree heirachy so we can share code... */
CoglMaterialNode _parent;
/* We need to track if a material is referenced in the journal /* We need to track if a material is referenced in the journal
* because we can't allow modification to these materials without * because we can't allow modification to these materials without
* flushing the journal first */ * flushing the journal first */
unsigned long journal_ref_count; unsigned long journal_ref_count;
/* Materials are sparse structures defined as a diff against
* their parent. */
CoglMaterial *parent;
/* As an optimization for creating leaf node materials (the most
* common) we don't require any list node allocations to link
* to a single descendant.
*
* Only valid if ->has_children bitfield is set */
CoglMaterial *first_child;
/* Materials are sparse structures defined as a diff against
* their parent and may have multiple children which depend
* on them to define the values of properties which they don't
* change.
*
* Only valid if ->has_children bitfield is set */
GList *children;
/* A mask of which sparse state groups are different in this /* A mask of which sparse state groups are different in this
* material in comparison to its parent. */ * material in comparison to its parent. */
unsigned long differences; unsigned long differences;
@ -598,10 +608,6 @@ struct _CoglMaterial
* blending, this holds our final decision */ * blending, this holds our final decision */
unsigned int real_blend_enable:1; unsigned int real_blend_enable:1;
/* Determines if material->first_child and material->children are
* initialized pointers. */
unsigned int has_children:1;
unsigned int layers_cache_dirty:1; unsigned int layers_cache_dirty:1;
unsigned int deprecated_get_layers_list_dirty:1; unsigned int deprecated_get_layers_list_dirty:1;
@ -786,6 +792,9 @@ unsigned int
_cogl_get_n_args_for_combine_func (GLint func); _cogl_get_n_args_for_combine_func (GLint func);
CoglMaterial *
_cogl_material_get_parent (CoglMaterial *material);
void void
_cogl_material_get_colorubv (CoglMaterial *material, _cogl_material_get_colorubv (CoglMaterial *material,
guint8 *color); guint8 *color);
@ -850,14 +859,6 @@ CoglMaterial *
_cogl_material_get_authority (CoglMaterial *material, _cogl_material_get_authority (CoglMaterial *material,
unsigned long difference); unsigned long difference);
typedef gboolean (*CoglMaterialChildCallback) (CoglMaterial *child,
void *user_data);
void
_cogl_material_foreach_child (CoglMaterial *material,
CoglMaterialChildCallback callback,
void *user_data);
unsigned long unsigned long
_cogl_material_layer_compare_differences (CoglMaterialLayer *layer0, _cogl_material_layer_compare_differences (CoglMaterialLayer *layer0,
CoglMaterialLayer *layer1); CoglMaterialLayer *layer1);

View File

@ -97,6 +97,7 @@ static void _cogl_material_add_layer_difference (CoglMaterial *material,
gboolean inc_n_layers); gboolean inc_n_layers);
static void handle_automatic_blend_enable (CoglMaterial *material, static void handle_automatic_blend_enable (CoglMaterial *material,
CoglMaterialState changes); CoglMaterialState changes);
static void recursively_free_layer_caches (CoglMaterial *material);
static const CoglMaterialBackend *backends[COGL_MATERIAL_N_BACKENDS]; static const CoglMaterialBackend *backends[COGL_MATERIAL_N_BACKENDS];
@ -294,6 +295,78 @@ _cogl_material_error_quark (void)
return g_quark_from_static_string ("cogl-material-error-quark"); return g_quark_from_static_string ("cogl-material-error-quark");
} }
static void
_cogl_material_node_init (CoglMaterialNode *node)
{
node->parent = NULL;
node->has_children = FALSE;
}
static void
_cogl_material_node_set_parent_real (CoglMaterialNode *node,
CoglMaterialNode *parent,
CoglMaterialNodeUnparentVFunc unparent)
{
/* NB: the old parent may indirectly be keeping the new parent alive so we
* have to ref the new parent before unrefing the old */
cogl_object_ref (parent);
if (node->parent)
unparent (node);
if (G_UNLIKELY (parent->has_children))
parent->children = g_list_prepend (parent->children, node);
else
{
parent->has_children = TRUE;
parent->first_child = node;
parent->children = NULL;
}
node->parent = parent;
}
static void
_cogl_material_node_unparent_real (CoglMaterialNode *node)
{
CoglMaterialNode *parent = node->parent;
if (parent == NULL)
return;
g_return_if_fail (parent->has_children);
if (parent->first_child == node)
{
if (parent->children)
{
parent->first_child = parent->children->data;
parent->children =
g_list_delete_link (parent->children, parent->children);
}
else
parent->has_children = FALSE;
}
else
parent->children = g_list_remove (parent->children, node);
cogl_object_unref (parent);
node->parent = NULL;
}
void
_cogl_material_node_foreach_child (CoglMaterialNode *node,
CoglMaterialNodeChildCallback callback,
void *user_data)
{
if (node->has_children)
{
callback (node->first_child, user_data);
g_list_foreach (node->children, (GFunc)callback, user_data);
}
}
/* /*
* This initializes the first material owned by the Cogl context. All * This initializes the first material owned by the Cogl context. All
* subsequently instantiated materials created via the cogl_material_new() * subsequently instantiated materials created via the cogl_material_new()
@ -325,9 +398,10 @@ _cogl_material_init_default_material (void)
backends[COGL_MATERIAL_BACKEND_FIXED] = &_cogl_material_fixed_backend; backends[COGL_MATERIAL_BACKEND_FIXED] = &_cogl_material_fixed_backend;
#endif #endif
_cogl_material_node_init (COGL_MATERIAL_NODE (material));
material->is_weak = FALSE; material->is_weak = FALSE;
material->journal_ref_count = 0; material->journal_ref_count = 0;
material->parent = NULL;
material->backend = COGL_MATERIAL_BACKEND_UNDEFINED; material->backend = COGL_MATERIAL_BACKEND_UNDEFINED;
material->differences = COGL_MATERIAL_STATE_ALL_SPARSE; material->differences = COGL_MATERIAL_STATE_ALL_SPARSE;
@ -400,32 +474,18 @@ _cogl_material_init_default_material (void)
} }
static void static void
_cogl_material_unparent (CoglMaterial *material) _cogl_material_unparent (CoglMaterialNode *material)
{ {
CoglMaterial *parent = material->parent; /* Chain up */
_cogl_material_node_unparent_real (material);
}
if (parent == NULL) static gboolean
return; recursively_free_layer_caches_cb (CoglMaterialNode *node,
void *user_data)
g_return_if_fail (parent->has_children); {
recursively_free_layer_caches (COGL_MATERIAL (node));
if (parent->first_child == material) return TRUE;
{
if (parent->children)
{
parent->first_child = parent->children->data;
parent->children =
g_list_delete_link (parent->children, parent->children);
}
else
parent->has_children = FALSE;
}
else
parent->children = g_list_remove (parent->children, material);
cogl_object_unref (parent);
material->parent = NULL;
} }
/* This recursively frees the layers_cache of a material and all of /* This recursively frees the layers_cache of a material and all of
@ -437,8 +497,6 @@ _cogl_material_unparent (CoglMaterial *material)
static void static void
recursively_free_layer_caches (CoglMaterial *material) recursively_free_layer_caches (CoglMaterial *material)
{ {
GList *l;
/* Note: we maintain the invariable that if a material already has a /* Note: we maintain the invariable that if a material already has a
* dirty layers_cache then so do all of its descendants. */ * dirty layers_cache then so do all of its descendants. */
if (material->layers_cache_dirty) if (material->layers_cache_dirty)
@ -449,33 +507,18 @@ recursively_free_layer_caches (CoglMaterial *material)
material->layers_cache); material->layers_cache);
material->layers_cache_dirty = TRUE; material->layers_cache_dirty = TRUE;
if (material->has_children) _cogl_material_node_foreach_child (COGL_MATERIAL_NODE (material),
{ recursively_free_layer_caches_cb,
recursively_free_layer_caches (material->first_child); NULL);
for (l = material->children; l; l = l->next)
recursively_free_layer_caches (l->data);
}
} }
static void static void
_cogl_material_set_parent (CoglMaterial *material, CoglMaterial *parent) _cogl_material_set_parent (CoglMaterial *material, CoglMaterial *parent)
{ {
cogl_object_ref (parent); /* Chain up */
_cogl_material_node_set_parent_real (COGL_MATERIAL_NODE (material),
if (material->parent) COGL_MATERIAL_NODE (parent),
_cogl_material_unparent (material); _cogl_material_unparent);
material->parent = parent;
if (G_UNLIKELY (parent->has_children))
parent->children = g_list_prepend (parent->children, material);
else
{
parent->has_children = TRUE;
parent->first_child = material;
parent->children = NULL;
}
material->parent = parent;
/* Since we just changed the ancestry of the material its cache of /* Since we just changed the ancestry of the material its cache of
* layers could now be invalid so free it... */ * layers could now be invalid so free it... */
@ -483,7 +526,7 @@ _cogl_material_set_parent (CoglMaterial *material, CoglMaterial *parent)
recursively_free_layer_caches (material); recursively_free_layer_caches (material);
/* If the fragment processing backend is also caching state along /* If the fragment processing backend is also caching state along
* with the material that depends on the materials ancestry then it * with the material that depends on the material's ancestry then it
* may be notified here... * may be notified here...
*/ */
if (material->backend != COGL_MATERIAL_BACKEND_UNDEFINED && if (material->backend != COGL_MATERIAL_BACKEND_UNDEFINED &&
@ -498,16 +541,12 @@ cogl_material_copy (CoglMaterial *src)
{ {
CoglMaterial *material = g_slice_new (CoglMaterial); CoglMaterial *material = g_slice_new (CoglMaterial);
material->_parent = src->_parent; _cogl_material_node_init (COGL_MATERIAL_NODE (material));
material->is_weak = FALSE; material->is_weak = FALSE;
material->journal_ref_count = 0; material->journal_ref_count = 0;
material->parent = NULL;
material->has_children = FALSE;
material->differences = 0; material->differences = 0;
material->has_big_state = FALSE; material->has_big_state = FALSE;
@ -582,7 +621,7 @@ _cogl_material_free (CoglMaterial *material)
{ {
_cogl_material_backend_free_priv (material); _cogl_material_backend_free_priv (material);
_cogl_material_unparent (material); _cogl_material_unparent (COGL_MATERIAL_NODE (material));
if (material->differences & COGL_MATERIAL_STATE_USER_SHADER && if (material->differences & COGL_MATERIAL_STATE_USER_SHADER &&
material->big_state->user_program) material->big_state->user_program)
@ -609,23 +648,40 @@ _cogl_material_get_real_blend_enabled (CoglMaterial *material)
return material->real_blend_enable; return material->real_blend_enable;
} }
inline CoglMaterial *
_cogl_material_get_parent (CoglMaterial *material)
{
CoglMaterialNode *parent_node = COGL_MATERIAL_NODE (material)->parent;
return COGL_MATERIAL (parent_node);
}
CoglMaterial * CoglMaterial *
_cogl_material_get_authority (CoglMaterial *material, _cogl_material_get_authority (CoglMaterial *material,
unsigned long difference) unsigned long difference)
{ {
CoglMaterial *authority = material; CoglMaterial *authority = material;
while (!(authority->differences & difference)) while (!(authority->differences & difference))
authority = authority->parent; authority = _cogl_material_get_parent (authority);
return authority; return authority;
} }
/* XXX: Think twice before making this non static since it is used
* heavily and we expect the compiler to inline it...
*/
static CoglMaterialLayer *
_cogl_material_layer_get_parent (CoglMaterialLayer *layer)
{
CoglMaterialNode *parent_node = COGL_MATERIAL_NODE (layer)->parent;
return COGL_MATERIAL_LAYER (parent_node);
}
CoglMaterialLayer * CoglMaterialLayer *
_cogl_material_layer_get_authority (CoglMaterialLayer *layer, _cogl_material_layer_get_authority (CoglMaterialLayer *layer,
unsigned long difference) unsigned long difference)
{ {
CoglMaterialLayer *authority = layer; CoglMaterialLayer *authority = layer;
while (!(authority->differences & difference)) while (!(authority->differences & difference))
authority = authority->parent; authority = _cogl_material_layer_get_parent (authority);
return authority; return authority;
} }
@ -689,7 +745,9 @@ _cogl_material_update_layers_cache (CoglMaterial *material)
*/ */
layers_found = 0; layers_found = 0;
for (current = material; current->parent; current = current->parent) for (current = material;
_cogl_material_get_parent (current);
current = _cogl_material_get_parent (current))
{ {
GList *l; GList *l;
@ -1058,21 +1116,10 @@ _cogl_material_initialize_state (CoglMaterial *dest,
} }
} }
void
_cogl_material_foreach_child (CoglMaterial *material,
CoglMaterialChildCallback callback,
void *user_data)
{
if (material->has_children)
{
callback (material->first_child, user_data);
g_list_foreach (material->children, (GFunc)callback, user_data);
}
}
static gboolean static gboolean
check_if_strong_cb (CoglMaterial *material, void *user_data) check_if_strong_cb (CoglMaterialNode *node, void *user_data)
{ {
CoglMaterial *material = COGL_MATERIAL (node);
gboolean *has_strong_child = user_data; gboolean *has_strong_child = user_data;
if (!material->is_weak) if (!material->is_weak)
@ -1087,16 +1134,17 @@ static gboolean
has_strong_children (CoglMaterial *material) has_strong_children (CoglMaterial *material)
{ {
gboolean has_strong_child = FALSE; gboolean has_strong_child = FALSE;
_cogl_material_foreach_child (material, _cogl_material_node_foreach_child (COGL_MATERIAL_NODE (material),
check_if_strong_cb, check_if_strong_cb,
&has_strong_child); &has_strong_child);
return has_strong_child; return has_strong_child;
} }
static gboolean static gboolean
reparent_strong_children_cb (CoglMaterial *material, reparent_strong_children_cb (CoglMaterialNode *node,
void *user_data) void *user_data)
{ {
CoglMaterial *material = COGL_MATERIAL (node);
CoglMaterial *parent = user_data; CoglMaterial *parent = user_data;
if (material->is_weak) if (material->is_weak)
@ -1175,6 +1223,7 @@ _cogl_material_pre_change_notify (CoglMaterial *material,
if (has_strong_children (material)) if (has_strong_children (material))
{ {
CoglMaterial *new_authority; CoglMaterial *new_authority;
COGL_STATIC_COUNTER (material_copy_on_write_counter, COGL_STATIC_COUNTER (material_copy_on_write_counter,
"material copy on write counter", "material copy on write counter",
"Increments each time a material " "Increments each time a material "
@ -1183,7 +1232,8 @@ _cogl_material_pre_change_notify (CoglMaterial *material,
COGL_COUNTER_INC (_cogl_uprof_context, material_copy_on_write_counter); COGL_COUNTER_INC (_cogl_uprof_context, material_copy_on_write_counter);
new_authority = cogl_material_copy (material->parent); new_authority =
cogl_material_copy (_cogl_material_get_parent (material));
_cogl_material_set_static_breadcrumb (new_authority, _cogl_material_set_static_breadcrumb (new_authority,
"pre_change_notify:copy-on-write"); "pre_change_notify:copy-on-write");
@ -1204,12 +1254,9 @@ _cogl_material_pre_change_notify (CoglMaterial *material,
/* Reparent the strong children of material to be children of /* Reparent the strong children of material to be children of
* new_authority instead... */ * new_authority instead... */
new_authority->has_children = FALSE; _cogl_material_node_foreach_child (COGL_MATERIAL_NODE (material),
new_authority->first_child = NULL; reparent_strong_children_cb,
new_authority->children = NULL; new_authority);
_cogl_material_foreach_child (material,
reparent_strong_children_cb,
new_authority);
/* The children will keep the new authority alive so drop the /* The children will keep the new authority alive so drop the
* reference we got when copying... */ * reference we got when copying... */
@ -1311,7 +1358,8 @@ static void
_cogl_material_try_reverting_layers_authority (CoglMaterial *authority, _cogl_material_try_reverting_layers_authority (CoglMaterial *authority,
CoglMaterial *old_authority) CoglMaterial *old_authority)
{ {
if (authority->layer_differences == NULL && authority->parent) if (authority->layer_differences == NULL &&
_cogl_material_get_parent (authority))
{ {
/* If the previous _STATE_LAYERS authority has the same /* If the previous _STATE_LAYERS authority has the same
* ->n_layers then we can revert to that being the authority * ->n_layers then we can revert to that being the authority
@ -1319,7 +1367,7 @@ _cogl_material_try_reverting_layers_authority (CoglMaterial *authority,
if (!old_authority) if (!old_authority)
{ {
old_authority = old_authority =
_cogl_material_get_authority (authority->parent, _cogl_material_get_authority (_cogl_material_get_parent (authority),
COGL_MATERIAL_STATE_LAYERS); COGL_MATERIAL_STATE_LAYERS);
} }
@ -1466,21 +1514,6 @@ _cogl_get_n_args_for_combine_func (GLint func)
return 0; return 0;
} }
typedef gboolean (*CoglMaterialLayerChildCallback) (CoglMaterialLayer *child,
void *user_data);
void
_cogl_material_layer_foreach_child (CoglMaterialLayer *layer,
CoglMaterialLayerChildCallback callback,
void *user_data)
{
if (layer->has_children)
{
callback (layer->first_child, user_data);
g_list_foreach (layer->children, (GFunc)callback, user_data);
}
}
static void static void
_cogl_material_layer_initialize_state (CoglMaterialLayer *dest, _cogl_material_layer_initialize_state (CoglMaterialLayer *dest,
CoglMaterialLayer *src, CoglMaterialLayer *src,
@ -1579,7 +1612,8 @@ _cogl_material_layer_pre_change_notify (CoglMaterial *required_owner,
/* Identify the case where the layer is new with no owner or /* Identify the case where the layer is new with no owner or
* dependants and so we don't need to do anything. */ * dependants and so we don't need to do anything. */
if (layer->has_children == FALSE && layer->owner == NULL) if (COGL_MATERIAL_NODE (layer)->has_children == FALSE &&
layer->owner == NULL)
goto init_layer_state; goto init_layer_state;
/* We only allow a NULL required_owner for new layers */ /* We only allow a NULL required_owner for new layers */
@ -1588,7 +1622,8 @@ _cogl_material_layer_pre_change_notify (CoglMaterial *required_owner,
/* Unlike materials; layers are simply considered immutable once /* Unlike materials; layers are simply considered immutable once
* they have dependants - either children or another material owner. * they have dependants - either children or another material owner.
*/ */
if (layer->has_children || layer->owner != required_owner) if (COGL_MATERIAL_NODE (layer)->has_children ||
layer->owner != required_owner)
{ {
CoglMaterialLayer *new = _cogl_material_layer_copy (layer); CoglMaterialLayer *new = _cogl_material_layer_copy (layer);
_cogl_material_add_layer_difference (required_owner, new, FALSE); _cogl_material_add_layer_difference (required_owner, new, FALSE);
@ -1629,30 +1664,39 @@ init_layer_state:
return layer; return layer;
} }
static void
_cogl_material_layer_unparent (CoglMaterialNode *layer)
{
/* Chain up */
_cogl_material_node_unparent_real (layer);
}
static void
_cogl_material_layer_set_parent (CoglMaterialLayer *layer,
CoglMaterialLayer *parent)
{
/* Chain up */
_cogl_material_node_set_parent_real (COGL_MATERIAL_NODE (layer),
COGL_MATERIAL_NODE (parent),
_cogl_material_layer_unparent);
}
/* XXX: This is duplicated logic; the same as for /* XXX: This is duplicated logic; the same as for
* _cogl_material_prune_redundant_ancestry it would be nice to find a * _cogl_material_prune_redundant_ancestry it would be nice to find a
* way to consolidate these functions! */ * way to consolidate these functions! */
static void static void
_cogl_material_layer_prune_redundant_ancestry (CoglMaterialLayer *layer) _cogl_material_layer_prune_redundant_ancestry (CoglMaterialLayer *layer)
{ {
CoglMaterialLayer *new_parent = layer->parent; CoglMaterialLayer *new_parent = _cogl_material_layer_get_parent (layer);
/* walk up past ancestors that are now redundant and potentially /* walk up past ancestors that are now redundant and potentially
* reparent the layer. */ * reparent the layer. */
while (new_parent->parent && while (_cogl_material_layer_get_parent (new_parent) &&
(new_parent->differences | layer->differences) == (new_parent->differences | layer->differences) ==
layer->differences) layer->differences)
new_parent = new_parent->parent; new_parent = _cogl_material_layer_get_parent (new_parent);
if (new_parent != layer->parent) _cogl_material_layer_set_parent (layer, new_parent);
{
CoglMaterialLayer *old_parent = layer->parent;
layer->parent = cogl_object_ref (new_parent);
/* Note: the old parent may indirectly be keeping
the new parent alive so we have to ref the new
parent before unrefing the old */
cogl_object_unref (old_parent);
}
} }
/* /*
@ -1691,10 +1735,13 @@ _cogl_material_set_layer_unit (CoglMaterial *required_owner,
/* If the layer we found is currently the authority on the state /* If the layer we found is currently the authority on the state
* we are changing see if we can revert to one of our ancestors * we are changing see if we can revert to one of our ancestors
* being the authority. */ * being the authority. */
if (layer == authority && authority->parent != NULL) if (layer == authority &&
_cogl_material_layer_get_parent (authority) != NULL)
{ {
CoglMaterialLayer *parent =
_cogl_material_layer_get_parent (authority);
CoglMaterialLayer *old_authority = CoglMaterialLayer *old_authority =
_cogl_material_layer_get_authority (authority->parent, change); _cogl_material_layer_get_authority (parent, change);
if (old_authority->unit_index == unit_index) if (old_authority->unit_index == unit_index)
{ {
@ -1909,7 +1956,7 @@ _cogl_material_prune_empty_layer_difference (CoglMaterial *layers_authority,
/* Find the GList link that references the empty layer */ /* Find the GList link that references the empty layer */
GList *link = g_list_find (layers_authority->layer_differences, layer); GList *link = g_list_find (layers_authority->layer_differences, layer);
/* No material directly owns the root node layer so this is safe... */ /* No material directly owns the root node layer so this is safe... */
CoglMaterialLayer *layer_parent = layer->parent; CoglMaterialLayer *layer_parent = _cogl_material_layer_get_parent (layer);
CoglMaterialLayerInfo layer_info; CoglMaterialLayerInfo layer_info;
CoglMaterial *old_layers_authority; CoglMaterial *old_layers_authority;
@ -1922,7 +1969,7 @@ _cogl_material_prune_empty_layer_difference (CoglMaterial *layers_authority,
if (layer_parent->index == layer->index && layer_parent->owner == NULL) if (layer_parent->index == layer->index && layer_parent->owner == NULL)
{ {
cogl_object_ref (layer_parent); cogl_object_ref (layer_parent);
link->data = layer->parent; link->data = _cogl_material_layer_get_parent (layer);
cogl_object_unref (layer); cogl_object_unref (layer);
recursively_free_layer_caches (layers_authority); recursively_free_layer_caches (layers_authority);
return; return;
@ -1951,10 +1998,12 @@ _cogl_material_prune_empty_layer_difference (CoglMaterial *layers_authority,
* list of layers with indices > layer_index... */ * list of layers with indices > layer_index... */
layer_info.ignore_shift_layers_if_found = TRUE; layer_info.ignore_shift_layers_if_found = TRUE;
/* We know the default/root material isn't a LAYERS authority so /* We know the default/root material isn't a LAYERS authority so it's
* it's safe to dereference layers_authority->parent. */ * safe to use the result of _cogl_material_get_parent (layers_authority)
* without checking it.
*/
old_layers_authority = old_layers_authority =
_cogl_material_get_authority (layers_authority->parent, _cogl_material_get_authority (_cogl_material_get_parent (layers_authority),
COGL_MATERIAL_STATE_LAYERS); COGL_MATERIAL_STATE_LAYERS);
_cogl_material_get_layer_info (old_layers_authority, &layer_info); _cogl_material_get_layer_info (old_layers_authority, &layer_info);
@ -1964,9 +2013,10 @@ _cogl_material_prune_empty_layer_difference (CoglMaterial *layers_authority,
if (!layer_info.layer) if (!layer_info.layer)
return; return;
/* If the layer that would become the authority for layer->index /* If the layer that would become the authority for layer->index is
* is layer->parent then we can simply remove the layer difference. */ * _cogl_material_layer_get_parent (layer) then we can simply remove the
if (layer_info.layer == layer->parent) * layer difference. */
if (layer_info.layer == _cogl_material_layer_get_parent (layer))
{ {
_cogl_material_remove_layer_difference (layers_authority, layer, FALSE); _cogl_material_remove_layer_difference (layers_authority, layer, FALSE);
_cogl_material_try_reverting_layers_authority (layers_authority, _cogl_material_try_reverting_layers_authority (layers_authority,
@ -2014,10 +2064,13 @@ _cogl_material_set_layer_texture (CoglMaterial *material,
/* If the original layer we found is currently the authority on /* If the original layer we found is currently the authority on
* the state we are changing see if we can revert to one of our * the state we are changing see if we can revert to one of our
* ancestors being the authority. */ * ancestors being the authority. */
if (layer == authority && authority->parent != NULL) if (layer == authority &&
_cogl_material_layer_get_parent (authority) != NULL)
{ {
CoglMaterialLayer *parent =
_cogl_material_layer_get_parent (authority);
CoglMaterialLayer *old_authority = CoglMaterialLayer *old_authority =
_cogl_material_layer_get_authority (authority->parent, change); _cogl_material_layer_get_authority (parent, change);
if (old_authority->texture_overridden == overriden && if (old_authority->texture_overridden == overriden &&
old_authority->texture == texture && old_authority->texture == texture &&
@ -2183,10 +2236,13 @@ _cogl_material_set_layer_wrap_modes (CoglMaterial *material,
/* If the original layer we found is currently the authority on /* If the original layer we found is currently the authority on
* the state we are changing see if we can revert to one of our * the state we are changing see if we can revert to one of our
* ancestors being the authority. */ * ancestors being the authority. */
if (layer == authority && authority->parent != NULL) if (layer == authority &&
_cogl_material_layer_get_parent (authority) != NULL)
{ {
CoglMaterialLayer *parent =
_cogl_material_layer_get_parent (authority);
CoglMaterialLayer *old_authority = CoglMaterialLayer *old_authority =
_cogl_material_layer_get_authority (authority->parent, change); _cogl_material_layer_get_authority (parent, change);
if (old_authority->wrap_mode_s == wrap_mode_s && if (old_authority->wrap_mode_s == wrap_mode_s &&
old_authority->wrap_mode_t == wrap_mode_t && old_authority->wrap_mode_t == wrap_mode_t &&
@ -2534,10 +2590,13 @@ cogl_material_set_layer_point_sprite_coords_enabled (CoglMaterial *material,
/* If the original layer we found is currently the authority on /* If the original layer we found is currently the authority on
* the state we are changing see if we can revert to one of our * the state we are changing see if we can revert to one of our
* ancestors being the authority. */ * ancestors being the authority. */
if (layer == authority && authority->parent != NULL) if (layer == authority &&
_cogl_material_layer_get_parent (authority) != NULL)
{ {
CoglMaterialLayer *parent =
_cogl_material_layer_get_parent (authority);
CoglMaterialLayer *old_authority = CoglMaterialLayer *old_authority =
_cogl_material_layer_get_authority (authority->parent, change); _cogl_material_layer_get_authority (parent, change);
if (old_authority->big_state->point_sprite_coords == enable) if (old_authority->big_state->point_sprite_coords == enable)
{ {
@ -2787,9 +2846,9 @@ _cogl_material_layer_compare_differences (CoglMaterialLayer *layer0,
g_array_set_size (ctx->material0_nodes, 0); g_array_set_size (ctx->material0_nodes, 0);
g_array_set_size (ctx->material1_nodes, 0); g_array_set_size (ctx->material1_nodes, 0);
for (node0 = layer0; node0; node0 = node0->parent) for (node0 = layer0; node0; node0 = _cogl_material_layer_get_parent (node0))
g_array_append_vals (ctx->material0_nodes, &node0, 1); g_array_append_vals (ctx->material0_nodes, &node0, 1);
for (node1 = layer1; node1; node1 = node1->parent) for (node1 = layer1; node1; node1 = _cogl_material_layer_get_parent (node1))
g_array_append_vals (ctx->material1_nodes, &node1, 1); g_array_append_vals (ctx->material1_nodes, &node1, 1);
len0 = ctx->material0_nodes->len; len0 = ctx->material0_nodes->len;
@ -2807,7 +2866,7 @@ _cogl_material_layer_compare_differences (CoglMaterialLayer *layer0,
CoglMaterialLayer *, len1_index--); CoglMaterialLayer *, len1_index--);
if (node0 != node1) if (node0 != node1)
{ {
common_ancestor = node0->parent; common_ancestor = _cogl_material_layer_get_parent (node0);
break; break;
} }
} }
@ -3185,9 +3244,9 @@ _cogl_material_compare_differences (CoglMaterial *material0,
g_array_set_size (ctx->material0_nodes, 0); g_array_set_size (ctx->material0_nodes, 0);
g_array_set_size (ctx->material1_nodes, 0); g_array_set_size (ctx->material1_nodes, 0);
for (node0 = material0; node0; node0 = node0->parent) for (node0 = material0; node0; node0 = _cogl_material_get_parent (node0))
g_array_append_vals (ctx->material0_nodes, &node0, 1); g_array_append_vals (ctx->material0_nodes, &node0, 1);
for (node1 = material1; node1; node1 = node1->parent) for (node1 = material1; node1; node1 = _cogl_material_get_parent (node1))
g_array_append_vals (ctx->material1_nodes, &node1, 1); g_array_append_vals (ctx->material1_nodes, &node1, 1);
len0 = ctx->material0_nodes->len; len0 = ctx->material0_nodes->len;
@ -3205,7 +3264,7 @@ _cogl_material_compare_differences (CoglMaterial *material0,
CoglMaterial *, len1_index--); CoglMaterial *, len1_index--);
if (node0 != node1) if (node0 != node1)
{ {
common_ancestor = node0->parent; common_ancestor = _cogl_material_get_parent (node0);
break; break;
} }
} }
@ -3396,24 +3455,16 @@ _cogl_material_get_colorubv (CoglMaterial *material,
static void static void
_cogl_material_prune_redundant_ancestry (CoglMaterial *material) _cogl_material_prune_redundant_ancestry (CoglMaterial *material)
{ {
CoglMaterial *new_parent = material->parent; CoglMaterial *new_parent = _cogl_material_get_parent (material);
/* walk up past ancestors that are now redundant and potentially /* walk up past ancestors that are now redundant and potentially
* reparent the material. */ * reparent the material. */
while (new_parent->parent && while (_cogl_material_get_parent (new_parent) &&
(new_parent->differences | material->differences) == (new_parent->differences | material->differences) ==
material->differences) material->differences)
new_parent = new_parent->parent; new_parent = _cogl_material_get_parent (new_parent);
if (new_parent != material->parent) _cogl_material_set_parent (material, new_parent);
{
CoglMaterial *old_parent = material->parent;
material->parent = cogl_object_ref (new_parent);
/* Note: the old parent may indirectly be keeping
the new parent alive so we have to ref the new
parent before unrefing the old */
cogl_object_unref (old_parent);
}
} }
static void static void
@ -3424,10 +3475,12 @@ _cogl_material_update_authority (CoglMaterial *material,
{ {
/* If we are the current authority see if we can revert to one of /* If we are the current authority see if we can revert to one of
* our ancestors being the authority */ * our ancestors being the authority */
if (material == authority && authority->parent != NULL) if (material == authority &&
_cogl_material_get_parent (authority) != NULL)
{ {
CoglMaterial *parent = _cogl_material_get_parent (authority);
CoglMaterial *old_authority = CoglMaterial *old_authority =
_cogl_material_get_authority (authority->parent, state); _cogl_material_get_authority (parent, state);
if (comparitor (authority, old_authority)) if (comparitor (authority, old_authority))
material->differences &= ~state; material->differences &= ~state;
@ -3659,12 +3712,12 @@ void
cogl_material_get_specular (CoglMaterial *material, cogl_material_get_specular (CoglMaterial *material,
CoglColor *specular) CoglColor *specular)
{ {
CoglMaterial *authority = material; CoglMaterial *authority;
g_return_if_fail (cogl_is_material (material)); g_return_if_fail (cogl_is_material (material));
while (!(authority->differences & COGL_MATERIAL_STATE_LIGHTING)) authority =
authority = authority->parent; _cogl_material_get_authority (material, COGL_MATERIAL_STATE_LIGHTING);
cogl_color_init_from_4fv (specular, cogl_color_init_from_4fv (specular,
authority->big_state->lighting_state.specular); authority->big_state->lighting_state.specular);
@ -4001,10 +4054,12 @@ cogl_material_set_blend (CoglMaterial *material,
/* If we are the current authority see if we can revert to one of our /* If we are the current authority see if we can revert to one of our
* ancestors being the authority */ * ancestors being the authority */
if (material == authority && authority->parent != NULL) if (material == authority &&
_cogl_material_get_parent (authority) != NULL)
{ {
CoglMaterial *parent = _cogl_material_get_parent (authority);
CoglMaterial *old_authority = CoglMaterial *old_authority =
_cogl_material_get_authority (authority->parent, state); _cogl_material_get_authority (parent, state);
if (_cogl_material_blend_state_equal (authority, old_authority)) if (_cogl_material_blend_state_equal (authority, old_authority))
material->differences &= ~state; material->differences &= ~state;
@ -4091,10 +4146,12 @@ _cogl_material_set_user_program (CoglMaterial *material,
/* If we are the current authority see if we can revert to one of our /* If we are the current authority see if we can revert to one of our
* ancestors being the authority */ * ancestors being the authority */
if (material == authority && authority->parent != NULL) if (material == authority &&
_cogl_material_get_parent (authority) != NULL)
{ {
CoglMaterial *parent = _cogl_material_get_parent (authority);
CoglMaterial *old_authority = CoglMaterial *old_authority =
_cogl_material_get_authority (authority->parent, state); _cogl_material_get_authority (parent, state);
if (old_authority->big_state->user_program == program) if (old_authority->big_state->user_program == program)
material->differences &= ~state; material->differences &= ~state;
@ -4354,22 +4411,9 @@ _cogl_material_layer_copy (CoglMaterialLayer *src)
CoglMaterialLayer *layer = g_slice_new (CoglMaterialLayer); CoglMaterialLayer *layer = g_slice_new (CoglMaterialLayer);
int i; int i;
cogl_object_ref (src); _cogl_material_node_init (COGL_MATERIAL_NODE (layer));
layer->_parent = src->_parent;
layer->owner = NULL; layer->owner = NULL;
layer->parent = src;
if (src->has_children)
src->children = g_list_prepend (src->children, layer);
else
{
src->has_children = TRUE;
src->first_child = layer;
src->children = NULL;
}
layer->has_children = FALSE;
layer->index = src->index; layer->index = src->index;
layer->differences = 0; layer->differences = 0;
layer->has_big_state = FALSE; layer->has_big_state = FALSE;
@ -4377,42 +4421,17 @@ _cogl_material_layer_copy (CoglMaterialLayer *src)
for (i = 0; i < COGL_MATERIAL_N_BACKENDS; i++) for (i = 0; i < COGL_MATERIAL_N_BACKENDS; i++)
layer->backend_priv[i] = NULL; layer->backend_priv[i] = NULL;
_cogl_material_layer_set_parent (layer, src);
return _cogl_material_layer_object_new (layer); return _cogl_material_layer_object_new (layer);
} }
static void
_cogl_material_layer_unparent (CoglMaterialLayer *layer)
{
CoglMaterialLayer *parent = layer->parent;
if (parent == NULL)
return;
g_return_if_fail (parent->has_children);
if (parent->first_child == layer)
{
if (parent->children)
{
parent->first_child = parent->children->data;
parent->children =
g_list_delete_link (parent->children, parent->children);
}
else
parent->has_children = FALSE;
}
else
parent->children = g_list_remove (parent->children, layer);
cogl_object_unref (parent);
}
static void static void
_cogl_material_layer_free (CoglMaterialLayer *layer) _cogl_material_layer_free (CoglMaterialLayer *layer)
{ {
int i; int i;
_cogl_material_layer_unparent (layer); _cogl_material_layer_unparent (COGL_MATERIAL_NODE (layer));
/* NB: layers may be used by multiple materials which may be using /* NB: layers may be used by multiple materials which may be using
* different backends, therefore we determine which backends to * different backends, therefore we determine which backends to
@ -4472,7 +4491,8 @@ _cogl_material_init_default_layers (void)
_COGL_GET_CONTEXT (ctx, NO_RETVAL); _COGL_GET_CONTEXT (ctx, NO_RETVAL);
layer->has_children = FALSE; _cogl_material_node_init (COGL_MATERIAL_NODE (layer));
layer->index = 0; layer->index = 0;
for (i = 0; i < COGL_MATERIAL_N_BACKENDS; i++) for (i = 0; i < COGL_MATERIAL_N_BACKENDS; i++)
@ -4705,10 +4725,12 @@ cogl_material_set_layer_combine (CoglMaterial *material,
/* If the original layer we found is currently the authority on /* If the original layer we found is currently the authority on
* the state we are changing see if we can revert to one of our * the state we are changing see if we can revert to one of our
* ancestors being the authority. */ * ancestors being the authority. */
if (layer == authority && authority->parent != NULL) if (layer == authority &&
_cogl_material_layer_get_parent (authority) != NULL)
{ {
CoglMaterialLayer *parent = _cogl_material_layer_get_parent (authority);
CoglMaterialLayer *old_authority = CoglMaterialLayer *old_authority =
_cogl_material_layer_get_authority (authority->parent, state); _cogl_material_layer_get_authority (parent, state);
if (_cogl_material_layer_combine_state_equal (authority, if (_cogl_material_layer_combine_state_equal (authority,
old_authority)) old_authority))
@ -4775,10 +4797,13 @@ cogl_material_set_layer_combine_constant (CoglMaterial *material,
/* If the original layer we found is currently the authority on /* If the original layer we found is currently the authority on
* the state we are changing see if we can revert to one of our * the state we are changing see if we can revert to one of our
* ancestors being the authority. */ * ancestors being the authority. */
if (layer == authority && authority->parent != NULL) if (layer == authority &&
_cogl_material_layer_get_parent (authority) != NULL)
{ {
CoglMaterialLayer *parent =
_cogl_material_layer_get_parent (authority);
CoglMaterialLayer *old_authority = CoglMaterialLayer *old_authority =
_cogl_material_layer_get_authority (authority->parent, state); _cogl_material_layer_get_authority (parent, state);
CoglMaterialLayerBigState *old_big_state = old_authority->big_state; CoglMaterialLayerBigState *old_big_state = old_authority->big_state;
if (memcmp (old_big_state->texture_combine_constant, if (memcmp (old_big_state->texture_combine_constant,
@ -4854,10 +4879,13 @@ cogl_material_set_layer_matrix (CoglMaterial *material,
/* If the original layer we found is currently the authority on /* If the original layer we found is currently the authority on
* the state we are changing see if we can revert to one of our * the state we are changing see if we can revert to one of our
* ancestors being the authority. */ * ancestors being the authority. */
if (layer == authority && authority->parent != NULL) if (layer == authority &&
_cogl_material_layer_get_parent (authority) != NULL)
{ {
CoglMaterialLayer *parent =
_cogl_material_layer_get_parent (authority);
CoglMaterialLayer *old_authority = CoglMaterialLayer *old_authority =
_cogl_material_layer_get_authority (authority->parent, state); _cogl_material_layer_get_authority (parent, state);
if (cogl_matrix_equal (matrix, &old_authority->big_state->matrix)) if (cogl_matrix_equal (matrix, &old_authority->big_state->matrix))
{ {
@ -5017,7 +5045,7 @@ _cogl_material_layer_has_user_matrix (CoglMaterialLayer *layer)
COGL_MATERIAL_LAYER_STATE_USER_MATRIX); COGL_MATERIAL_LAYER_STATE_USER_MATRIX);
/* If the authority is the default material then no, otherwise yes */ /* If the authority is the default material then no, otherwise yes */
return authority->parent ? TRUE : FALSE; return _cogl_material_layer_get_parent (authority) ? TRUE : FALSE;
} }
static void static void
@ -5094,7 +5122,7 @@ cogl_material_set_layer_filters (CoglMaterial *material,
CoglMaterialFilter min_filter, CoglMaterialFilter min_filter,
CoglMaterialFilter mag_filter) CoglMaterialFilter mag_filter)
{ {
CoglMaterialLayerState change = COGL_MATERIAL_LAYER_STATE_FILTERS; CoglMaterialLayerState state = COGL_MATERIAL_LAYER_STATE_FILTERS;
CoglMaterialLayer *layer; CoglMaterialLayer *layer;
CoglMaterialLayer *authority; CoglMaterialLayer *authority;
CoglMaterialLayer *new; CoglMaterialLayer *new;
@ -5111,13 +5139,13 @@ cogl_material_set_layer_filters (CoglMaterial *material,
/* Now find the ancestor of the layer that is the authority for the /* Now find the ancestor of the layer that is the authority for the
* state we want to change */ * state we want to change */
authority = _cogl_material_layer_get_authority (layer, change); authority = _cogl_material_layer_get_authority (layer, state);
if (authority->min_filter == min_filter && if (authority->min_filter == min_filter &&
authority->mag_filter == mag_filter) authority->mag_filter == mag_filter)
return; return;
new = _cogl_material_layer_pre_change_notify (material, layer, change); new = _cogl_material_layer_pre_change_notify (material, layer, state);
if (new != layer) if (new != layer)
layer = new; layer = new;
else else
@ -5125,15 +5153,18 @@ cogl_material_set_layer_filters (CoglMaterial *material,
/* If the original layer we found is currently the authority on /* If the original layer we found is currently the authority on
* the state we are changing see if we can revert to one of our * the state we are changing see if we can revert to one of our
* ancestors being the authority. */ * ancestors being the authority. */
if (layer == authority && authority->parent != NULL) if (layer == authority &&
_cogl_material_layer_get_parent (authority) != NULL)
{ {
CoglMaterialLayer *parent =
_cogl_material_layer_get_parent (authority);
CoglMaterialLayer *old_authority = CoglMaterialLayer *old_authority =
_cogl_material_layer_get_authority (authority->parent, change); _cogl_material_layer_get_authority (parent, state);
if (old_authority->min_filter == min_filter && if (old_authority->min_filter == min_filter &&
old_authority->mag_filter == mag_filter) old_authority->mag_filter == mag_filter)
{ {
layer->differences &= ~change; layer->differences &= ~state;
g_assert (layer->owner == material); g_assert (layer->owner == material);
if (layer->differences == 0) if (layer->differences == 0)
@ -5153,7 +5184,7 @@ cogl_material_set_layer_filters (CoglMaterial *material,
* ourselves if that's true... */ * ourselves if that's true... */
if (layer != authority) if (layer != authority)
{ {
layer->differences |= change; layer->differences |= state;
_cogl_material_layer_prune_redundant_ancestry (layer); _cogl_material_layer_prune_redundant_ancestry (layer);
} }
} }
@ -6235,8 +6266,9 @@ typedef struct
} PrintDebugState; } PrintDebugState;
static gboolean static gboolean
dump_layer_cb (CoglMaterialLayer *layer, void *user_data) dump_layer_cb (CoglMaterialNode *node, void *user_data)
{ {
CoglMaterialLayer *layer = COGL_MATERIAL_LAYER (node);
PrintDebugState *state = user_data; PrintDebugState *state = user_data;
int layer_id = *state->node_id_ptr; int layer_id = *state->node_id_ptr;
PrintDebugState state_out; PrintDebugState state_out;
@ -6291,9 +6323,9 @@ dump_layer_cb (CoglMaterialLayer *layer, void *user_data)
state_out.graph = state->graph; state_out.graph = state->graph;
state_out.indent = state->indent + 2; state_out.indent = state->indent + 2;
_cogl_material_layer_foreach_child (layer, _cogl_material_node_foreach_child (COGL_MATERIAL_NODE (layer),
dump_layer_cb, dump_layer_cb,
&state_out); &state_out);
return TRUE; return TRUE;
} }
@ -6320,8 +6352,9 @@ dump_layer_ref_cb (CoglMaterialLayer *layer, void *data)
} }
static gboolean static gboolean
dump_material_cb (CoglMaterial *material, void *user_data) dump_material_cb (CoglMaterialNode *node, void *user_data)
{ {
CoglMaterial *material = COGL_MATERIAL (node);
PrintDebugState *state = user_data; PrintDebugState *state = user_data;
int material_id = *state->node_id_ptr; int material_id = *state->node_id_ptr;
PrintDebugState state_out; PrintDebugState state_out;
@ -6417,9 +6450,9 @@ dump_material_cb (CoglMaterial *material, void *user_data)
state_out.graph = state->graph; state_out.graph = state->graph;
state_out.indent = state->indent + 2; state_out.indent = state->indent + 2;
_cogl_material_foreach_child (material, _cogl_material_node_foreach_child (COGL_MATERIAL_NODE (material),
dump_material_cb, dump_material_cb,
&state_out); &state_out);
return TRUE; return TRUE;
} }