[gtk/wip/chergert/cache-text-render-node] textview: cache paragraph render nodes



commit 3b959456ac5335639e9642571f59f17ec8ee97f7
Author: Christian Hergert <chergert redhat com>
Date:   Tue Oct 8 11:35:49 2019 -0700

    textview: cache paragraph render nodes
    
    We can avoid recreating a number of text nodes from render_para() on
    sub-sequent runs if we cache the rendernode instead of just the
    PangoLayout.
    
    When used with GtkSourceMap, this can yield a ~7 FPS improvement during
    smooth scrolling at the cost of some more memory.

 gtk/gtktextlayout.c           | 37 ++++++++++++++++++++++++++++++-------
 gtk/gtktextlayoutprivate.h    |  3 +++
 gtk/gtktextlinedisplaycache.c |  1 +
 3 files changed, 34 insertions(+), 7 deletions(-)
---
diff --git a/gtk/gtktextlayout.c b/gtk/gtktextlayout.c
index f51dd42fcb..d7c270a9dc 100644
--- a/gtk/gtktextlayout.c
+++ b/gtk/gtktextlayout.c
@@ -2643,6 +2643,7 @@ gtk_text_line_display_finalize (GtkTextLineDisplay *display)
 
   g_clear_object (&display->layout);
   g_clear_pointer (&display->cursors, g_array_unref);
+  g_clear_pointer (&display->node, gsk_render_node_unref);
 }
 
 GtkTextLineDisplay *
@@ -3862,7 +3863,6 @@ render_para (GskPangoRenderer   *crenderer,
   int screen_width;
   GdkRGBA *selection = NULL;
   gboolean first = TRUE;
-  graphene_point_t point = { 0, offset_y };
 
   g_return_if_fail (GTK_IS_TEXT_VIEW (crenderer->widget));
 
@@ -3880,8 +3880,12 @@ render_para (GskPangoRenderer   *crenderer,
       gtk_style_context_restore (context);
     }
 
-  gtk_snapshot_save (crenderer->snapshot);
-  gtk_snapshot_translate (crenderer->snapshot, &point);
+  if (offset_y)
+    {
+      gtk_snapshot_save (crenderer->snapshot);
+      gtk_snapshot_translate (crenderer->snapshot,
+                              &GRAPHENE_POINT_INIT (0, offset_y));
+    }
 
   do
     {
@@ -4054,7 +4058,8 @@ render_para (GskPangoRenderer   *crenderer,
     }
   while (pango_layout_iter_next_line (iter));
 
-  gtk_snapshot_restore (crenderer->snapshot);
+  if (offset_y)
+    gtk_snapshot_restore (crenderer->snapshot);
 
   gdk_rgba_free (selection);
   pango_layout_iter_free (iter);
@@ -4146,9 +4151,27 @@ gtk_text_layout_snapshot (GtkTextLayout      *layout,
                 }
             }
 
-          render_para (crenderer, offset_y, line_display,
-                       selection_start_index, selection_end_index,
-                       cursor_alpha);
+          if (line_display->node == NULL)
+            {
+              GtkSnapshot *sub = gtk_snapshot_new ();
+
+              crenderer->snapshot = sub;
+              render_para (crenderer, 0, line_display,
+                           selection_start_index, selection_end_index,
+                           cursor_alpha);
+              crenderer->snapshot = snapshot;
+
+              line_display->node = gtk_snapshot_free_to_node (sub);
+            }
+
+          if (line_display->node != NULL)
+            {
+              gtk_snapshot_save (crenderer->snapshot);
+              gtk_snapshot_translate (crenderer->snapshot,
+                                      &GRAPHENE_POINT_INIT (0, offset_y));
+              gtk_snapshot_append_node (crenderer->snapshot, line_display->node);
+              gtk_snapshot_restore (crenderer->snapshot);
+            }
 
           /* We paint the cursors last, because they overlap another chunk
            * and need to appear on top.
diff --git a/gtk/gtktextlayoutprivate.h b/gtk/gtktextlayoutprivate.h
index 99d4f812e8..f408d199de 100644
--- a/gtk/gtktextlayoutprivate.h
+++ b/gtk/gtktextlayoutprivate.h
@@ -216,6 +216,9 @@ struct _GtkTextAttrAppearance
 struct _GtkTextLineDisplay
 {
   PangoLayout *layout;
+
+  GskRenderNode *node;
+
   GArray *cursors;      /* indexes of cursors in the PangoLayout */
 
   /* GSequenceIter backpointer for use within cache */
diff --git a/gtk/gtktextlinedisplaycache.c b/gtk/gtktextlinedisplaycache.c
index 2fe174c0f6..c15d8907d6 100644
--- a/gtk/gtktextlinedisplaycache.c
+++ b/gtk/gtktextlinedisplaycache.c
@@ -234,6 +234,7 @@ gtk_text_line_display_cache_invalidate_display (GtkTextLineDisplayCache *cache,
   if (cursors_only)
     {
       g_clear_pointer (&display->cursors, g_array_unref);
+      g_clear_pointer (&display->node, gsk_render_node_unref);
       display->cursors_invalid = TRUE;
       display->has_block_cursor = FALSE;
     }


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