[gtk] snapshot: Add gtk_snapshot_from_parent



commit cf1526cca62a956d1605fa6cdcc241e59c039600
Author: Timm Bäder <tbaeder redhat com>
Date:   Wed Jan 16 08:30:42 2019 +0100

    snapshot: Add gtk_snapshot_from_parent
    
    Most of the time, the GtkSnapshot objects we create while snapshotting
    widgets don't end up containing all that many nodes or states in their
    respective node or state stack. This undermines the amortized allocation
    behavior of the G(Ptr)Array we use for the stacks. So instead, use the
    (until now unused) parent_snapshot GtkSnapshot* passed to
    gtk_widget_create_render_node and reuse its node and state stack.
    
    We do not avoid allocating a new GtkSnapshot object, but we do avoid
    allocating a ton of G(Ptr)Array objects and we also avoid realloc'ing
    their storage.

 gtk/gtksnapshot.c        | 36 ++++++++++++++++++++++++++++++------
 gtk/gtksnapshotprivate.h |  4 ++++
 gtk/gtkwidget.c          |  2 +-
 3 files changed, 35 insertions(+), 7 deletions(-)
---
diff --git a/gtk/gtksnapshot.c b/gtk/gtksnapshot.c
index 3bc18cd4e8..7eb12dd33e 100644
--- a/gtk/gtksnapshot.c
+++ b/gtk/gtksnapshot.c
@@ -162,6 +162,7 @@ gtk_snapshot_new (void)
 
   snapshot = g_object_new (GTK_TYPE_SNAPSHOT, NULL);
 
+  snapshot->from_parent = FALSE;
   snapshot->state_stack = g_array_new (FALSE, TRUE, sizeof (GtkSnapshotState));
   g_array_set_clear_func (snapshot->state_stack, (GDestroyNotify)gtk_snapshot_state_clear);
   snapshot->nodes = g_ptr_array_new_with_free_func ((GDestroyNotify)gsk_render_node_unref);
@@ -173,6 +174,24 @@ gtk_snapshot_new (void)
   return snapshot;
 }
 
+/* Private. Does the same as _new but does not allocate a NEW
+ * state/node stack. */
+GtkSnapshot *
+gtk_snapshot_new_with_parent (GtkSnapshot *parent_snapshot)
+{
+  GtkSnapshot *snapshot = g_object_new (GTK_TYPE_SNAPSHOT, NULL);
+
+  snapshot->state_stack = parent_snapshot->state_stack;
+  snapshot->nodes = parent_snapshot->nodes;
+  snapshot->from_parent = TRUE;
+
+  gtk_snapshot_push_state (snapshot,
+                           0, 0,
+                           gtk_snapshot_collect_default);
+
+  return snapshot;
+}
+
 /**
  * gtk_snapshot_free_to_node: (skip)
  * @snapshot: (transfer full): a #GtkSnapshot
@@ -904,7 +923,8 @@ gtk_snapshot_pop_internal (GtkSnapshot *snapshot)
   guint state_index;
   GskRenderNode *node;
 
-  if (snapshot->state_stack->len == 0)
+  if (snapshot->state_stack->len == 0 &&
+      !snapshot->from_parent)
     {
       g_warning ("Too many gtk_snapshot_pop() calls.");
       return NULL;
@@ -950,17 +970,21 @@ gtk_snapshot_to_node (GtkSnapshot *snapshot)
   GskRenderNode *result;
 
   /* We should have exactly our initial state */
-  if (snapshot->state_stack->len > 1)
+  if (snapshot->state_stack->len > 1 &&
+      !snapshot->from_parent)
     {
       g_warning ("Too many gtk_snapshot_push() calls. %u states remaining.", snapshot->state_stack->len);
     }
-  
+
   result = gtk_snapshot_pop_internal (snapshot);
 
-  g_array_free (snapshot->state_stack, TRUE);
-  snapshot->state_stack = NULL;
+  if (!snapshot->from_parent)
+    {
+      g_array_free (snapshot->state_stack, TRUE);
+      g_ptr_array_free (snapshot->nodes, TRUE);
+    }
 
-  g_ptr_array_free (snapshot->nodes, TRUE);
+  snapshot->state_stack = NULL;
   snapshot->nodes = NULL;
 
   return result;
diff --git a/gtk/gtksnapshotprivate.h b/gtk/gtksnapshotprivate.h
index b54fb4b702..5e554ca85e 100644
--- a/gtk/gtksnapshotprivate.h
+++ b/gtk/gtksnapshotprivate.h
@@ -90,6 +90,8 @@ struct _GdkSnapshot {
 
   GArray                *state_stack;
   GPtrArray             *nodes;
+
+  guint from_parent : 1;
 };
 
 struct _GtkSnapshotClass {
@@ -99,6 +101,8 @@ struct _GtkSnapshotClass {
 void                    gtk_snapshot_append_node_internal       (GtkSnapshot            *snapshot,
                                                                  GskRenderNode          *node);
 
+GtkSnapshot *           gtk_snapshot_new_with_parent            (GtkSnapshot            *parent_snapshot);
+
 G_END_DECLS
 
 #endif /* __GTK_SNAPSHOT_PRIVATE_H__ */
diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c
index 4fadd96534..7e03bfc987 100644
--- a/gtk/gtkwidget.c
+++ b/gtk/gtkwidget.c
@@ -12961,7 +12961,7 @@ gtk_widget_create_render_node (GtkWidget   *widget,
   if (opacity <= 0.0)
     return NULL;
 
-  snapshot = gtk_snapshot_new ();
+  snapshot = gtk_snapshot_new_with_parent (parent_snapshot);
 
   _gtk_widget_get_allocation (widget, &allocation);
   gtk_snapshot_push_debug (snapshot,


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]