[gtk+/wip/ebassi/gsk-renderer: 14/83] gsk: Turn GskRenderNode into a pure GTypeInstance



commit 0377e9c75a1ffad2cdb12c139f3c6abe1bff3e06
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]