]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
patch 9.2.0856: GTK4: undercurl rendering is inefficient v9.2.0856
authorFoxe Chen <chen.foxe@gmail.com>
Sat, 25 Jul 2026 16:57:36 +0000 (16:57 +0000)
committerChristian Brabandt <cb@256bit.org>
Sat, 25 Jul 2026 16:57:36 +0000 (16:57 +0000)
Problem:  In the GTK4 GUI the undercurl is drawn by building a path
          across the whole width of each decorated row.  With many
          undercurls on screen this causes frame drops.
Solution: Render a single cycle of the undercurl and tile it across the
          row with a repeating node, so the Vulkan and OpenGL
          renderers can repeat directly (Foxe Chen).

closes: #20829

Signed-off-by: Foxe Chen <chen.foxe@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
src/gui_gtk4_da.c
src/version.c

index 739f2e0aed5ac459d962943c796687db31de8b02..7a082cedfc2eeb6a0481d5141dc79c03391bd0b7 100644 (file)
@@ -914,7 +914,12 @@ draw_row_ensure_decor(DrawRow *drow, int flags)
        int x_start = FILL_X(0);
        int x_end = FILL_X(drow->n_cells);
 
-       // GskPath was added in GSK 4.14, otherwise use cairo
+       // Instead of rendering the entire pattern, use a repeating node to
+       // render a single cycle of the undercurl, taking advantage of the GPU
+       // (if using opengl or vulkan renderer).
+       GskRenderNode *child = NULL;
+
+       // GskPath was added in GSK 4.14, otherwise use Cairo
 #if GTK_CHECK_VERSION(4, 14, 0)
        GskPathBuilder  *builder;
        GskPath         *path;
@@ -924,52 +929,52 @@ draw_row_ensure_decor(DrawRow *drow, int flags)
 
        builder = gsk_path_builder_new();
 
-       gsk_path_builder_move_to(builder,
-               x_start + 1,
-               y - 2 + 0.5);
+       // Start at X = -1 (val[7]) to ensure a fully formed stroke at X = 0
+       gsk_path_builder_move_to(builder, -1, y - val[7] + 0.5);
+       gsk_path_builder_line_to(builder, 0, y - val[0] + 0.5);
 
-       for (int i = x_start + 1; i < x_end; i++)
-       {
-           int offset = val[i % 8];
+       for (int i = 1; i < 8; i++)
+           gsk_path_builder_line_to(builder, i, y - val[i] + 0.5);
 
-           gsk_path_builder_line_to(builder,
-                   i, y - offset + 0.5);
-       }
+       // Extend to X = 9 (val[1]) to ensure a fully formed stroke at X = 8
+       gsk_path_builder_line_to(builder, 8, y - val[0] + 0.5);
+       gsk_path_builder_line_to(builder, 9, y - val[1] + 0.5);
 
        path = gsk_path_builder_free_to_path(builder);
-
        stroke = gsk_stroke_new(1.0);
 
-       gsk_path_get_stroke_bounds (path, stroke, &bounds);
+       gsk_path_get_stroke_bounds(path, stroke, &bounds);
        color_node = gsk_color_node_new(&white_rgba, &bounds);
+       child = gsk_stroke_node_new(color_node, path, stroke);
 
-       drow->underc_mask = gsk_stroke_node_new(color_node, path, stroke);
        gsk_stroke_free(stroke);
        gsk_path_unref(path);
        gsk_render_node_unref(color_node);
 #else
-       cairo_t         *cr;
-       GskRenderNode   *node;
+       cairo_t *cr;
 
-       node = gsk_cairo_node_new(
-               &GRAPHENE_RECT_INIT(x_start, y - 3, x_end - x_start, 5));
-       cr = gsk_cairo_node_get_draw_context(node);
+       child = gsk_cairo_node_new(&GRAPHENE_RECT_INIT(-2, y - 4, 12, 7));
+       cr = gsk_cairo_node_get_draw_context(child);
 
        cairo_set_line_width(cr, 1.0);
        cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 1.0);
 
-       cairo_move_to(cr, x_start + 1, y - 2 + 0.5);
+       cairo_move_to(cr, -1, y - val[7] + 0.5);
+       cairo_line_to(cr, 0, y - val[0] + 0.5);
 
-       for (int i = x_start + 1; i < x_end; ++i)
-       {
-           int offset = val[i % 8];
-           cairo_line_to(cr, i, y - offset + 0.5);
-       }
+       for (int i = 1; i < 8; ++i)
+           cairo_line_to(cr, i, y - val[i] + 0.5);
+
+       cairo_line_to(cr, 8, y - val[0] + 0.5);
+       cairo_line_to(cr, 9, y - val[1] + 0.5);
 
        cairo_stroke(cr);
        cairo_destroy(cr);
-       drow->underc_mask = node;
 #endif
+       drow->underc_mask = gsk_repeat_node_new(
+               &GRAPHENE_RECT_INIT(x_start, y - 3, x_end - x_start, 5),
+               child, &GRAPHENE_RECT_INIT(0.0f, y - 3, 8.0f, 5.0f));
+       gsk_render_node_unref(child);
     }
 }
 
index 7a37a44ea2faea8ddb94f3d39552838b5beb228d..b289c6800e798ce0960f25449516d6bcf336bd6a 100644 (file)
@@ -758,6 +758,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    856,
 /**/
     855,
 /**/