summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Clasen <mclasen@redhat.com>2021-04-08 23:11:06 -0400
committerMatthias Clasen <mclasen@redhat.com>2021-04-08 23:37:51 -0400
commit0caa28c1dee734fc42411f61d96171d2621b9062 (patch)
tree42fc9b2cef34cbc3739070375608eb7fa1965299
parentd8ba4b4114b523ca86676692731b5f9247b8596f (diff)
downloadgtk+-0caa28c1dee734fc42411f61d96171d2621b9062.tar.gz
ngl: Optimize underlines in text
Opportunistically use the coloring program for drawing underlines instead of the color program. This avoids program changes in the middle of text. For the Emoji text scrolling benchmark, this reduces the program changes per frame from > 1000 to around 100.
-rw-r--r--gsk/ngl/gsknglrenderjob.c44
1 files changed, 41 insertions, 3 deletions
diff --git a/gsk/ngl/gsknglrenderjob.c b/gsk/ngl/gsknglrenderjob.c
index b1bda44790..69c92ac80f 100644
--- a/gsk/ngl/gsknglrenderjob.c
+++ b/gsk/ngl/gsknglrenderjob.c
@@ -1360,16 +1360,54 @@ blur_node (GskNglRenderJob *job,
*max_y = job->offset_y + node->bounds.origin.y + node->bounds.size.height + half_blur_extra;
}
+#define ATLAS_SIZE 512
+
static inline void
gsk_ngl_render_job_visit_color_node (GskNglRenderJob *job,
const GskRenderNode *node)
{
guint16 color[4];
+ GskNglProgram *program;
+ GskNglCommandBatch *batch;
rgba_to_half (gsk_color_node_get_color (node), color);
- gsk_ngl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, color));
- gsk_ngl_render_job_draw_rect_with_color (job, &node->bounds, color);
- gsk_ngl_render_job_end_draw (job);
+
+ /* Avoid switching away from the coloring program for
+ * rendering a solid color.
+ */
+ program = CHOOSE_PROGRAM (job, coloring);
+ batch = gsk_ngl_command_queue_get_batch (job->command_queue);
+
+ if (batch->any.kind == GSK_NGL_COMMAND_KIND_DRAW &&
+ batch->any.program == program->id)
+ {
+ GskNglRenderOffscreen offscreen = {0};
+
+ gsk_ngl_render_job_begin_draw (job, program);
+
+ /* The top left few pixels in our atlases are always
+ * solid white, so we can use it here, without
+ * having to choose any particular atlas texture.
+ */
+ offscreen.was_offscreen = FALSE;
+ offscreen.area.x = 1.f / ATLAS_SIZE;
+ offscreen.area.y = 1.f / ATLAS_SIZE;
+ offscreen.area.x2 = 2.f / ATLAS_SIZE;
+ offscreen.area.y2 = 2.f / ATLAS_SIZE;
+
+ gsk_ngl_render_job_draw_offscreen_with_color (job,
+ &node->bounds,
+ &offscreen,
+ color);
+
+ gsk_ngl_render_job_end_draw (job);
+ }
+ else
+ {
+ gsk_ngl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, color));
+ gsk_ngl_render_job_draw_rect_with_color (job, &node->bounds, color);
+ gsk_ngl_render_job_end_draw (job);
+ }
}
static inline void