mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-11-08 17:50:10 +00:00
gsk: Turn GskRenderNode into a pure GTypeInstance
Using GObject as the base type for a transient tree may prove to be too intensive, especially when creating a lot of node instances. Since we don't need properties or signals, and we don't need complex destruction semantics, we can use GTypeInstance directly as the base type for GskRenderNode.
This commit is contained in:
parent
b997f4c575
commit
b8a92dfa0e
@ -80,7 +80,6 @@ enum {
|
||||
PROP_USE_ALPHA,
|
||||
PROP_SCALE_FACTOR,
|
||||
PROP_WINDOW,
|
||||
PROP_ROOT_NODE,
|
||||
PROP_DISPLAY,
|
||||
PROP_DRAWING_CONTEXT,
|
||||
|
||||
@ -228,10 +227,6 @@ gsk_renderer_get_property (GObject *gobject,
|
||||
g_value_set_object (value, priv->window);
|
||||
break;
|
||||
|
||||
case PROP_ROOT_NODE:
|
||||
g_value_set_object (value, priv->root_node);
|
||||
break;
|
||||
|
||||
case PROP_DRAWING_CONTEXT:
|
||||
g_value_set_object (value, priv->drawing_context);
|
||||
break;
|
||||
@ -401,21 +396,6 @@ gsk_renderer_class_init (GskRendererClass *klass)
|
||||
G_PARAM_STATIC_STRINGS |
|
||||
G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
/**
|
||||
* GskRenderer:root-node:
|
||||
*
|
||||
* The root #GskRenderNode of the scene to be rendered.
|
||||
*
|
||||
* Since: 3.22
|
||||
*/
|
||||
gsk_renderer_properties[PROP_ROOT_NODE] =
|
||||
g_param_spec_object ("root-node",
|
||||
"Root Node",
|
||||
"The root render node to render",
|
||||
GSK_TYPE_RENDER_NODE,
|
||||
G_PARAM_READABLE |
|
||||
G_PARAM_STATIC_STRINGS);
|
||||
|
||||
/**
|
||||
* GskRenderer:display:
|
||||
*
|
||||
@ -930,16 +910,17 @@ gsk_renderer_render (GskRenderer *renderer,
|
||||
g_return_if_fail (priv->is_realized);
|
||||
g_return_if_fail (GSK_IS_RENDER_NODE (root));
|
||||
g_return_if_fail (GDK_IS_DRAWING_CONTEXT (context));
|
||||
g_return_if_fail (priv->drawing_context == NULL);
|
||||
g_return_if_fail (priv->root_node == NULL);
|
||||
|
||||
g_set_object (&priv->root_node, root);
|
||||
g_set_object (&priv->drawing_context, context);
|
||||
|
||||
gsk_render_node_make_immutable (root);
|
||||
priv->drawing_context = g_object_ref (context);
|
||||
priv->root_node = gsk_render_node_ref (root);
|
||||
gsk_render_node_make_immutable (priv->root_node);
|
||||
|
||||
GSK_RENDERER_GET_CLASS (renderer)->render (renderer, root, context);
|
||||
|
||||
g_clear_object (&priv->root_node);
|
||||
g_clear_object (&priv->drawing_context);
|
||||
g_clear_pointer (&priv->root_node, gsk_render_node_unref);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -33,32 +33,122 @@
|
||||
|
||||
#include <graphene-gobject.h>
|
||||
|
||||
G_DEFINE_TYPE (GskRenderNode, gsk_render_node, G_TYPE_OBJECT)
|
||||
#include <gobject/gvaluecollector.h>
|
||||
|
||||
static void
|
||||
gsk_render_node_dispose (GObject *gobject)
|
||||
value_render_node_init (GValue *value)
|
||||
{
|
||||
value->data[0].v_pointer = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
value_render_node_free (GValue *value)
|
||||
{
|
||||
if (value->data[0].v_pointer != NULL)
|
||||
gsk_render_node_unref (value->data[0].v_pointer);
|
||||
}
|
||||
|
||||
static void
|
||||
value_render_node_copy (const GValue *src,
|
||||
GValue *dst)
|
||||
{
|
||||
if (src->data[0].v_pointer != NULL)
|
||||
dst->data[0].v_pointer = gsk_render_node_ref (src->data[0].v_pointer);
|
||||
else
|
||||
dst->data[0].v_pointer = NULL;
|
||||
}
|
||||
|
||||
static gpointer
|
||||
value_render_node_peek_pointer (const GValue *value)
|
||||
{
|
||||
return value->data[0].v_pointer;
|
||||
}
|
||||
|
||||
static gchar *
|
||||
value_render_node_collect_value (GValue *value,
|
||||
guint n_collect_values,
|
||||
GTypeCValue *collect_values,
|
||||
guint collect_flags)
|
||||
{
|
||||
GskRenderNode *node;
|
||||
|
||||
node = collect_values[0].v_pointer;
|
||||
|
||||
if (node == NULL)
|
||||
{
|
||||
value->data[0].v_pointer = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (node->parent_instance.g_class == NULL)
|
||||
return g_strconcat ("invalid unclassed GskRenderNode pointer for "
|
||||
"value type '",
|
||||
G_VALUE_TYPE_NAME (value),
|
||||
"'",
|
||||
NULL);
|
||||
|
||||
value->data[0].v_pointer = gsk_render_node_ref (node);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static gchar *
|
||||
value_render_node_lcopy_value (const GValue *value,
|
||||
guint n_collect_values,
|
||||
GTypeCValue *collect_values,
|
||||
guint collect_flags)
|
||||
{
|
||||
GskRenderNode **node_p = collect_values[0].v_pointer;
|
||||
|
||||
if (node_p == NULL)
|
||||
return g_strconcat ("value location for '",
|
||||
G_VALUE_TYPE_NAME (value),
|
||||
"' passed as NULL",
|
||||
NULL);
|
||||
|
||||
if (value->data[0].v_pointer == NULL)
|
||||
*node_p = NULL;
|
||||
else if (collect_flags & G_VALUE_NOCOPY_CONTENTS)
|
||||
*node_p = value->data[0].v_pointer;
|
||||
else
|
||||
*node_p = gsk_render_node_ref (value->data[0].v_pointer);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_render_node_finalize (GskRenderNode *self)
|
||||
{
|
||||
GskRenderNode *self = GSK_RENDER_NODE (gobject);
|
||||
GskRenderNodeIter iter;
|
||||
|
||||
gsk_render_node_iter_init (&iter, self);
|
||||
while (gsk_render_node_iter_next (&iter, NULL))
|
||||
gsk_render_node_iter_remove (&iter);
|
||||
|
||||
G_OBJECT_CLASS (gsk_render_node_parent_class)->dispose (gobject);
|
||||
g_type_free_instance ((GTypeInstance *) self);
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_render_node_class_base_init (GskRenderNodeClass *klass)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_render_node_class_base_finalize (GskRenderNodeClass *klass)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_render_node_class_init (GskRenderNodeClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
gobject_class->dispose = gsk_render_node_dispose;
|
||||
klass->finalize = gsk_render_node_finalize;
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_render_node_init (GskRenderNode *self)
|
||||
{
|
||||
self->ref_count = 1;
|
||||
|
||||
graphene_rect_init_from_rect (&self->bounds, graphene_rect_zero ());
|
||||
|
||||
graphene_matrix_init_identity (&self->transform);
|
||||
@ -69,6 +159,54 @@ gsk_render_node_init (GskRenderNode *self)
|
||||
self->is_mutable = TRUE;
|
||||
}
|
||||
|
||||
GType
|
||||
gsk_render_node_get_type (void)
|
||||
{
|
||||
static volatile gsize gsk_render_node_type__volatile;
|
||||
|
||||
if (g_once_init_enter (&gsk_render_node_type__volatile))
|
||||
{
|
||||
static const GTypeFundamentalInfo finfo = {
|
||||
(G_TYPE_FLAG_CLASSED |
|
||||
G_TYPE_FLAG_INSTANTIATABLE |
|
||||
G_TYPE_FLAG_DERIVABLE |
|
||||
G_TYPE_FLAG_DEEP_DERIVABLE),
|
||||
};
|
||||
static const GTypeValueTable render_node_value_table = {
|
||||
value_render_node_init,
|
||||
value_render_node_free,
|
||||
value_render_node_copy,
|
||||
value_render_node_peek_pointer,
|
||||
"p", value_render_node_collect_value,
|
||||
"p", value_render_node_lcopy_value,
|
||||
};
|
||||
const GTypeInfo render_node_info = {
|
||||
sizeof (GskRenderNodeClass),
|
||||
|
||||
(GBaseInitFunc) gsk_render_node_class_base_init,
|
||||
(GBaseFinalizeFunc) gsk_render_node_class_base_finalize,
|
||||
(GClassInitFunc) gsk_render_node_class_init,
|
||||
(GClassFinalizeFunc) NULL,
|
||||
NULL,
|
||||
|
||||
sizeof (GskRenderNode), 16,
|
||||
(GInstanceInitFunc) gsk_render_node_init,
|
||||
|
||||
&render_node_value_table,
|
||||
};
|
||||
GType gsk_render_node_type =
|
||||
g_type_register_fundamental (g_type_fundamental_next (),
|
||||
g_intern_static_string ("GskRenderNode"),
|
||||
&render_node_info,
|
||||
&finfo,
|
||||
0);
|
||||
|
||||
g_once_init_leave (&gsk_render_node_type__volatile, gsk_render_node_type);
|
||||
}
|
||||
|
||||
return gsk_render_node_type__volatile;
|
||||
}
|
||||
|
||||
/**
|
||||
* gsk_render_node_new:
|
||||
*
|
||||
@ -81,7 +219,47 @@ gsk_render_node_init (GskRenderNode *self)
|
||||
GskRenderNode *
|
||||
gsk_render_node_new (void)
|
||||
{
|
||||
return g_object_new (GSK_TYPE_RENDER_NODE, NULL);
|
||||
return (GskRenderNode *) g_type_create_instance (GSK_TYPE_RENDER_NODE);
|
||||
}
|
||||
|
||||
/**
|
||||
* gsk_render_node_ref:
|
||||
* @node: a #GskRenderNode
|
||||
*
|
||||
* Acquires a reference on the given #GskRenderNode.
|
||||
*
|
||||
* Returns: (transfer none): the #GskRenderNode with an additional reference
|
||||
*
|
||||
* Since: 3.22
|
||||
*/
|
||||
GskRenderNode *
|
||||
gsk_render_node_ref (GskRenderNode *node)
|
||||
{
|
||||
g_return_val_if_fail (GSK_IS_RENDER_NODE (node), NULL);
|
||||
|
||||
g_atomic_int_inc (&node->ref_count);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
/**
|
||||
* gsk_render_node_unref:
|
||||
* @node: a #GskRenderNode
|
||||
*
|
||||
* Releases a reference on the given #GskRenderNode.
|
||||
*
|
||||
* If the reference was the last, the resources associated to the @node are
|
||||
* freed.
|
||||
*
|
||||
* Since: 3.22
|
||||
*/
|
||||
void
|
||||
gsk_render_node_unref (GskRenderNode *node)
|
||||
{
|
||||
g_return_if_fail (GSK_IS_RENDER_NODE (node));
|
||||
|
||||
if (g_atomic_int_dec_and_test (&node->ref_count))
|
||||
GSK_RENDER_NODE_GET_CLASS (node)->finalize (node);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -206,7 +384,7 @@ gsk_render_node_insert_child_internal (GskRenderNode *node,
|
||||
|
||||
insert_func (node, child, insert_func_data);
|
||||
|
||||
g_object_ref (child);
|
||||
gsk_render_node_ref (child);
|
||||
|
||||
child->parent = node;
|
||||
child->age = 0;
|
||||
@ -606,7 +784,7 @@ gsk_render_node_remove_child (GskRenderNode *node,
|
||||
if (node->last_child == child)
|
||||
node->last_child = prev_sibling;
|
||||
|
||||
g_object_unref (child);
|
||||
gsk_render_node_unref (child);
|
||||
|
||||
return node;
|
||||
}
|
||||
@ -1098,3 +1276,69 @@ gsk_render_node_make_immutable (GskRenderNode *node)
|
||||
while (gsk_render_node_iter_next (&iter, &child))
|
||||
gsk_render_node_make_immutable (child);
|
||||
}
|
||||
|
||||
void
|
||||
gsk_value_set_render_node (GValue *value,
|
||||
GskRenderNode *node)
|
||||
{
|
||||
GskRenderNode *old_node;
|
||||
|
||||
g_return_if_fail (GSK_VALUE_HOLDS_RENDER_NODE (value));
|
||||
|
||||
old_node = value->data[0].v_pointer;
|
||||
|
||||
if (node != NULL)
|
||||
{
|
||||
g_return_if_fail (GSK_IS_RENDER_NODE (node));
|
||||
|
||||
value->data[0].v_pointer = gsk_render_node_ref (node);
|
||||
}
|
||||
else
|
||||
value->data[0].v_pointer = NULL;
|
||||
|
||||
if (old_node != NULL)
|
||||
gsk_render_node_unref (old_node);
|
||||
}
|
||||
|
||||
void
|
||||
gsk_value_take_render_node (GValue *value,
|
||||
GskRenderNode *node)
|
||||
{
|
||||
GskRenderNode *old_node;
|
||||
|
||||
g_return_if_fail (GSK_VALUE_HOLDS_RENDER_NODE (value));
|
||||
|
||||
old_node = value->data[0].v_pointer;
|
||||
|
||||
if (node != NULL)
|
||||
{
|
||||
g_return_if_fail (GSK_IS_RENDER_NODE (node));
|
||||
|
||||
/* take over ownership */
|
||||
value->data[0].v_pointer = node;
|
||||
}
|
||||
else
|
||||
value->data[0].v_pointer = NULL;
|
||||
|
||||
if (old_node != NULL)
|
||||
gsk_render_node_unref (old_node);
|
||||
}
|
||||
|
||||
GskRenderNode *
|
||||
gsk_value_get_render_node (const GValue *value)
|
||||
{
|
||||
g_return_val_if_fail (GSK_VALUE_HOLDS_RENDER_NODE (value), NULL);
|
||||
|
||||
return value->data[0].v_pointer;
|
||||
}
|
||||
|
||||
GskRenderNode *
|
||||
gsk_value_dup_render_node (const GValue *value)
|
||||
{
|
||||
g_return_val_if_fail (GSK_VALUE_HOLDS_RENDER_NODE (value), NULL);
|
||||
|
||||
if (value->data[0].v_pointer != NULL)
|
||||
return gsk_render_node_ref (value->data[0].v_pointer);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
@ -40,6 +40,10 @@ GType gsk_render_node_get_type (void) G_GNUC_CONST;
|
||||
|
||||
GDK_AVAILABLE_IN_3_22
|
||||
GskRenderNode * gsk_render_node_new (void);
|
||||
GDK_AVAILABLE_IN_3_22
|
||||
GskRenderNode * gsk_render_node_ref (GskRenderNode *node);
|
||||
GDK_AVAILABLE_IN_3_22
|
||||
void gsk_render_node_unref (GskRenderNode *node);
|
||||
|
||||
GDK_AVAILABLE_IN_3_22
|
||||
GskRenderNode * gsk_render_node_get_parent (GskRenderNode *node);
|
||||
@ -115,6 +119,19 @@ GDK_AVAILABLE_IN_3_22
|
||||
void gsk_render_node_set_name (GskRenderNode *node,
|
||||
const char *name);
|
||||
|
||||
#define GSK_VALUE_HOLDS_RENDER_NODE(value) (G_VALUE_HOLDS (value, GSK_TYPE_RENDER_NODE))
|
||||
|
||||
GDK_AVAILABLE_IN_3_22
|
||||
void gsk_value_set_render_node (GValue *value,
|
||||
GskRenderNode *node);
|
||||
GDK_AVAILABLE_IN_3_22
|
||||
void gsk_value_take_render_node (GValue *value,
|
||||
GskRenderNode *node);
|
||||
GDK_AVAILABLE_IN_3_22
|
||||
GskRenderNode * gsk_value_get_render_node (const GValue *value);
|
||||
GDK_AVAILABLE_IN_3_22
|
||||
GskRenderNode * gsk_value_dup_render_node (const GValue *value);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GSK_RENDER_NODE_H__ */
|
||||
|
@ -12,7 +12,9 @@ G_BEGIN_DECLS
|
||||
|
||||
struct _GskRenderNode
|
||||
{
|
||||
GObject parent_instance;
|
||||
GTypeInstance parent_instance;
|
||||
|
||||
volatile int ref_count;
|
||||
|
||||
/* The graph */
|
||||
GskRenderNode *parent;
|
||||
@ -58,7 +60,9 @@ struct _GskRenderNode
|
||||
|
||||
struct _GskRenderNodeClass
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
GTypeClass parent_class;
|
||||
|
||||
void (* finalize) (GskRenderNode *node);
|
||||
};
|
||||
|
||||
void gsk_render_node_make_immutable (GskRenderNode *node);
|
||||
|
Loading…
Reference in New Issue
Block a user