[gtk+] gsk: Turn GskRenderNode into a pure GTypeInstance
- From: Emmanuele Bassi <ebassi src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+] gsk: Turn GskRenderNode into a pure GTypeInstance
- Date: Tue, 18 Oct 2016 10:52:40 +0000 (UTC)
commit b8a92dfa0eddca1283b08b17359bf628f25211dc
Author: Emmanuele Bassi <ebassi gnome org>
Date: Wed Jun 29 19:05:33 2016 +0100
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.
gsk/gskrenderer.c | 31 +----
gsk/gskrendernode.c | 264 ++++++++++++++++++++++++++++++++++++++++++--
gsk/gskrendernode.h | 17 +++
gsk/gskrendernodeprivate.h | 8 +-
4 files changed, 283 insertions(+), 37 deletions(-)
---
diff --git a/gsk/gskrenderer.c b/gsk/gskrenderer.c
index 72717bb..bcccb38 100644
--- a/gsk/gskrenderer.c
+++ b/gsk/gskrenderer.c
@@ -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;
@@ -402,21 +397,6 @@ gsk_renderer_class_init (GskRendererClass *klass)
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:
*
* The #GdkDisplay used by the #GskRenderer.
@@ -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);
}
/**
diff --git a/gsk/gskrendernode.c b/gsk/gskrendernode.c
index 95feb24..4618c5a 100644
--- a/gsk/gskrendernode.c
+++ b/gsk/gskrendernode.c
@@ -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_init (GskRenderNodeClass *klass)
+gsk_render_node_class_base_init (GskRenderNodeClass *klass)
+{
+}
+
+static void
+gsk_render_node_class_base_finalize (GskRenderNodeClass *klass)
{
- GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+}
- gobject_class->dispose = gsk_render_node_dispose;
+static void
+gsk_render_node_class_init (GskRenderNodeClass *klass)
+{
+ 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;
+}
diff --git a/gsk/gskrendernode.h b/gsk/gskrendernode.h
index 18e56f7..d8b57e2 100644
--- a/gsk/gskrendernode.h
+++ b/gsk/gskrendernode.h
@@ -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__ */
diff --git a/gsk/gskrendernodeprivate.h b/gsk/gskrendernodeprivate.h
index 9e9188f..16b7cf9 100644
--- a/gsk/gskrendernodeprivate.h
+++ b/gsk/gskrendernodeprivate.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);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]