[gtk+/wip/alexl/optimize-snapshot: 5/7] GtkSnapshot: Reuse snapshot state objects



commit 6341fab985864cfa337c55cb35e06a7b13119838
Author: Alexander Larsson <alexl redhat com>
Date:   Wed Jan 11 11:41:46 2017 +0100

    GtkSnapshot: Reuse snapshot state objects
    
    Rather than allocate new ones all the time we reuse the previous ones.
    We just clear them and save them in the parent for later reuse.

 gtk/gtksnapshot.c        |   40 +++++++++++++++++++++++++++++-----------
 gtk/gtksnapshotprivate.h |    1 +
 2 files changed, 30 insertions(+), 11 deletions(-)
---
diff --git a/gtk/gtksnapshot.c b/gtk/gtksnapshot.c
index e170058..72f1b15 100644
--- a/gtk/gtksnapshot.c
+++ b/gtk/gtksnapshot.c
@@ -84,11 +84,18 @@ gtk_snapshot_state_new (GtkSnapshotState       *parent,
 {
   GtkSnapshotState *state;
 
-  state = g_slice_new0 (GtkSnapshotState);
-
-  state->nodes = g_ptr_array_new_with_free_func ((GDestroyNotify) gsk_render_node_unref);
+  if (parent != NULL && parent->cached_state != NULL)
+    {
+      state = parent->cached_state;
+      parent->cached_state = NULL;
+    }
+  else
+    {
+      state = g_slice_new0 (GtkSnapshotState);
+      state->nodes = g_ptr_array_new_with_free_func ((GDestroyNotify) gsk_render_node_unref);
+      state->parent = parent;
+    }
 
-  state->parent = parent;
   state->name = name;
   if (clip)
     state->clip_region = cairo_region_reference (clip);
@@ -100,15 +107,20 @@ gtk_snapshot_state_new (GtkSnapshotState       *parent,
 }
 
 static void
+gtk_snapshot_state_clear (GtkSnapshotState *state)
+{
+  g_ptr_array_set_size (state->nodes, 0);
+  g_clear_pointer (&state->clip_region, cairo_region_destroy);
+  g_clear_pointer (&state->name, g_free);
+}
+
+static void
 gtk_snapshot_state_free (GtkSnapshotState *state)
 {
+  if (state->cached_state)
+    gtk_snapshot_state_free (state->cached_state);
+  gtk_snapshot_state_clear (state);
   g_ptr_array_unref (state->nodes);
-
-  if (state->clip_region)
-    cairo_region_destroy (state->clip_region);
-
-  g_free (state->name);
-
   g_slice_free (GtkSnapshotState, state);
 }
 
@@ -697,7 +709,13 @@ gtk_snapshot_pop (GtkSnapshot *snapshot)
                               state->nodes->len,
                               state->name);
 
-  gtk_snapshot_state_free (state);
+  if (snapshot->state == NULL)
+    gtk_snapshot_state_free (state);
+  else
+    {
+      gtk_snapshot_state_clear (state);
+      snapshot->state->cached_state = state;
+    }
 
   return node;
 }
diff --git a/gtk/gtksnapshotprivate.h b/gtk/gtksnapshotprivate.h
index 3141558..2384a8b 100644
--- a/gtk/gtksnapshotprivate.h
+++ b/gtk/gtksnapshotprivate.h
@@ -31,6 +31,7 @@ typedef GskRenderNode * (* GtkSnapshotCollectFunc) (GtkSnapshotState *state,
 
 struct _GtkSnapshotState {
   GtkSnapshotState      *parent;
+  GtkSnapshotState      *cached_state; /* A cleared state object we can (re)use */
 
   char                  *name;
   GPtrArray             *nodes;


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