cogl-pipeline: Use BSD lists for the list of pipeline children
Instead of having a separate GList for the children we can use the linked list code from FreeBSD and store the list node directly in the struct. That way we can avoid having a separate slice allocation for the list node. It also means that we effectively have a pointer to the list node given a pointer to the pipeline node. That means we can unparent a pipeline without having to walk the entire list of children. With this change there is no need to have the optimisation to fast track a pipeline that only has one child which simplifies the code somewhat. With this patch we are removing a pointer and a gboolean from the CoglPipeline struct and adding two pointers. On 32-bit architectures this should end up exactly the same size because a gboolean is the same size as a pointer. On 64-bit architectures I think it should end up 4 bytes smaller because it also ends up removing two cases where a pointer follows a gboolean which presumably would mean the compiler would have to insert 4 bytes of padding to keep the pointer aligned to 8 bytes. https://bugzilla.gnome.org/show_bug.cgi?id=652514
This commit is contained in:
parent
7b50c38cc8
commit
b9b41723c1
@ -34,6 +34,7 @@
|
|||||||
#include "cogl-matrix.h"
|
#include "cogl-matrix.h"
|
||||||
#include "cogl-object-private.h"
|
#include "cogl-object-private.h"
|
||||||
#include "cogl-profile.h"
|
#include "cogl-profile.h"
|
||||||
|
#include "cogl-queue.h"
|
||||||
|
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
|
|
||||||
@ -259,11 +260,14 @@ typedef struct
|
|||||||
|
|
||||||
} CoglPipelineLayerBigState;
|
} CoglPipelineLayerBigState;
|
||||||
|
|
||||||
|
typedef struct _CoglPipelineNode CoglPipelineNode;
|
||||||
|
|
||||||
|
COGL_LIST_HEAD (CoglPipelineNodeList, CoglPipelineNode);
|
||||||
|
|
||||||
/* Materials and layers represent their state in a tree structure where
|
/* Materials and layers represent their state in a tree structure where
|
||||||
* some of the state relating to a given pipeline or layer may actually
|
* some of the state relating to a given pipeline or layer may actually
|
||||||
* be owned by one if is ancestors in the tree. We have a common data
|
* 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... */
|
* type to track the tree heirachy so we can share code... */
|
||||||
typedef struct _CoglPipelineNode CoglPipelineNode;
|
|
||||||
struct _CoglPipelineNode
|
struct _CoglPipelineNode
|
||||||
{
|
{
|
||||||
/* the parent in terms of class hierarchy, so anything inheriting
|
/* the parent in terms of class hierarchy, so anything inheriting
|
||||||
@ -273,24 +277,15 @@ struct _CoglPipelineNode
|
|||||||
/* The parent pipeline/layer */
|
/* The parent pipeline/layer */
|
||||||
CoglPipelineNode *parent;
|
CoglPipelineNode *parent;
|
||||||
|
|
||||||
|
/* The list entry here contains pointers to the node's siblings */
|
||||||
|
COGL_LIST_ENTRY (CoglPipelineNode) list_node;
|
||||||
|
|
||||||
|
/* List of children */
|
||||||
|
CoglPipelineNodeList children;
|
||||||
|
|
||||||
/* TRUE if the node took a strong reference on its parent. Weak
|
/* TRUE if the node took a strong reference on its parent. Weak
|
||||||
* pipelines for instance don't take a reference on their parent. */
|
* pipelines for instance don't take a reference on their parent. */
|
||||||
gboolean has_parent_reference;
|
gboolean has_parent_reference;
|
||||||
|
|
||||||
/* As an optimization for creating leaf node pipelines/layers (the
|
|
||||||
* most common) we don't require any list node allocations to link
|
|
||||||
* to a single descendant. */
|
|
||||||
CoglPipelineNode *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_PIPELINE_NODE(X) ((CoglPipelineNode *)(X))
|
#define COGL_PIPELINE_NODE(X) ((CoglPipelineNode *)(X))
|
||||||
|
@ -108,7 +108,7 @@ static void
|
|||||||
_cogl_pipeline_node_init (CoglPipelineNode *node)
|
_cogl_pipeline_node_init (CoglPipelineNode *node)
|
||||||
{
|
{
|
||||||
node->parent = NULL;
|
node->parent = NULL;
|
||||||
node->has_children = FALSE;
|
COGL_LIST_INIT (&node->children);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -131,14 +131,7 @@ _cogl_pipeline_node_set_parent_real (CoglPipelineNode *node,
|
|||||||
if (node->parent)
|
if (node->parent)
|
||||||
unparent (node);
|
unparent (node);
|
||||||
|
|
||||||
if (G_UNLIKELY (parent->has_children))
|
COGL_LIST_INSERT_HEAD (&parent->children, node, list_node);
|
||||||
parent->children = g_list_prepend (parent->children, node);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
parent->has_children = TRUE;
|
|
||||||
parent->first_child = node;
|
|
||||||
parent->children = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
node->parent = parent;
|
node->parent = parent;
|
||||||
node->has_parent_reference = take_strong_reference;
|
node->has_parent_reference = take_strong_reference;
|
||||||
@ -159,21 +152,9 @@ _cogl_pipeline_node_unparent_real (CoglPipelineNode *node)
|
|||||||
if (parent == NULL)
|
if (parent == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
g_return_if_fail (parent->has_children);
|
g_return_if_fail (!COGL_LIST_EMPTY (&parent->children));
|
||||||
|
|
||||||
if (parent->first_child == node)
|
COGL_LIST_REMOVE (node, list_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);
|
|
||||||
|
|
||||||
if (node->has_parent_reference)
|
if (node->has_parent_reference)
|
||||||
cogl_object_unref (parent);
|
cogl_object_unref (parent);
|
||||||
@ -186,11 +167,10 @@ _cogl_pipeline_node_foreach_child (CoglPipelineNode *node,
|
|||||||
CoglPipelineNodeChildCallback callback,
|
CoglPipelineNodeChildCallback callback,
|
||||||
void *user_data)
|
void *user_data)
|
||||||
{
|
{
|
||||||
if (node->has_children)
|
CoglPipelineNode *child, *next;
|
||||||
{
|
|
||||||
callback (node->first_child, user_data);
|
COGL_LIST_FOREACH_SAFE (child, &node->children, list_node, next)
|
||||||
g_list_foreach (node->children, (GFunc)callback, user_data);
|
callback (child, user_data);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -555,7 +535,7 @@ _cogl_pipeline_free (CoglPipeline *pipeline)
|
|||||||
destroy_weak_children_cb,
|
destroy_weak_children_cb,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
g_assert (!COGL_PIPELINE_NODE (pipeline)->has_children);
|
g_assert (COGL_LIST_EMPTY (&COGL_PIPELINE_NODE (pipeline)->children));
|
||||||
|
|
||||||
_cogl_pipeline_fragend_free_priv (pipeline);
|
_cogl_pipeline_fragend_free_priv (pipeline);
|
||||||
|
|
||||||
@ -1334,7 +1314,7 @@ _cogl_pipeline_pre_change_notify (CoglPipeline *pipeline,
|
|||||||
/* If there are still children remaining though we'll need to
|
/* If there are still children remaining though we'll need to
|
||||||
* perform a copy-on-write and reparent the dependants as children
|
* perform a copy-on-write and reparent the dependants as children
|
||||||
* of the copy. */
|
* of the copy. */
|
||||||
if (COGL_PIPELINE_NODE (pipeline)->has_children)
|
if (!COGL_LIST_EMPTY (&COGL_PIPELINE_NODE (pipeline)->children))
|
||||||
{
|
{
|
||||||
CoglPipeline *new_authority;
|
CoglPipeline *new_authority;
|
||||||
|
|
||||||
@ -1764,7 +1744,7 @@ _cogl_pipeline_layer_pre_change_notify (CoglPipeline *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 (COGL_PIPELINE_NODE (layer)->has_children == FALSE &&
|
if (COGL_LIST_EMPTY (&COGL_PIPELINE_NODE (layer)->children) &&
|
||||||
layer->owner == NULL)
|
layer->owner == NULL)
|
||||||
goto init_layer_state;
|
goto init_layer_state;
|
||||||
|
|
||||||
@ -1786,7 +1766,7 @@ _cogl_pipeline_layer_pre_change_notify (CoglPipeline *required_owner,
|
|||||||
* they have dependants - either direct children, or another
|
* they have dependants - either direct children, or another
|
||||||
* pipeline as an owner.
|
* pipeline as an owner.
|
||||||
*/
|
*/
|
||||||
if (COGL_PIPELINE_NODE (layer)->has_children ||
|
if (!COGL_LIST_EMPTY (&COGL_PIPELINE_NODE (layer)->children) ||
|
||||||
layer->owner != required_owner)
|
layer->owner != required_owner)
|
||||||
{
|
{
|
||||||
CoglPipelineLayer *new = _cogl_pipeline_layer_copy (layer);
|
CoglPipelineLayer *new = _cogl_pipeline_layer_copy (layer);
|
||||||
|
Loading…
Reference in New Issue
Block a user