summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Clasen <mclasen@redhat.com>2021-04-09 15:36:21 +0000
committerMatthias Clasen <mclasen@redhat.com>2021-04-09 15:36:21 +0000
commit715449695c4db95e435fbfc7a2f8ce75692bc995 (patch)
tree9d9a8dc039aa472aca55b2b7f8950dec271cfe11
parentd15b0afca996532130c1602a7d02659731c329df (diff)
parentbfe4aea981b225ad5e4f4daf5902b6a4e30e90fc (diff)
downloadgtk+-715449695c4db95e435fbfc7a2f8ce75692bc995.tar.gz
Merge branch 'ngl-coloring-underlines' into 'master'
Optimize underlines in text See merge request GNOME/gtk!3414
-rw-r--r--demos/gtk-demo/iconscroll.c15
-rw-r--r--gsk/ngl/gsknglcommandqueue.c7
-rw-r--r--gsk/ngl/gsknglcommandqueueprivate.h1
-rw-r--r--gsk/ngl/gsknglrenderjob.c44
-rw-r--r--gsk/ngl/gskngltexturelibrary.c48
5 files changed, 106 insertions, 9 deletions
diff --git a/demos/gtk-demo/iconscroll.c b/demos/gtk-demo/iconscroll.c
index 2eb9aa6e92..8212818516 100644
--- a/demos/gtk-demo/iconscroll.c
+++ b/demos/gtk-demo/iconscroll.c
@@ -116,20 +116,25 @@ populate_emoji_text (void)
GtkWidget *textview;
GtkTextBuffer *buffer;
GString *s;
+ GtkTextIter iter;
- s = g_string_sized_new (1000 * 30 * 4);
+ s = g_string_sized_new (500 * 30 * 4);
- for (int i = 0; i < 1000; i++)
+ for (int i = 0; i < 500; i++)
{
if (i % 2)
- g_string_append (s, "x");
+ g_string_append (s, "<span underline=\"single\" underline_color=\"red\">x</span>");
for (int j = 0; j < 30; j++)
- g_string_append (s, "💓x");
+ {
+ g_string_append (s, "💓");
+ g_string_append (s, "<span underline=\"single\" underline_color=\"red\">x</span>");
+ }
g_string_append (s, "\n");
}
buffer = gtk_text_buffer_new (NULL);
- gtk_text_buffer_set_text (buffer, s->str, s->len);
+ gtk_text_buffer_get_start_iter (buffer, &iter);
+ gtk_text_buffer_insert_markup (buffer, &iter, s->str, s->len);
g_string_free (s, TRUE);
diff --git a/gsk/ngl/gsknglcommandqueue.c b/gsk/ngl/gsknglcommandqueue.c
index bdfef2f35c..ca84d04774 100644
--- a/gsk/ngl/gsknglcommandqueue.c
+++ b/gsk/ngl/gsknglcommandqueue.c
@@ -169,7 +169,7 @@ gsk_ngl_command_queue_print_batch (GskNglCommandQueue *self,
for (guint i = 0; i < batch->draw.bind_count; i++)
{
const GskNglCommandBind *bind = &self->batch_binds.items[batch->draw.bind_offset + i];
- g_print (" Bind[%d]: %u\n", bind->texture, bind->id);
+ g_printerr (" Bind[%d]: %u\n", bind->texture, bind->id);
}
for (guint i = 0; i < batch->draw.uniform_count; i++)
@@ -951,6 +951,7 @@ gsk_ngl_command_queue_execute (GskNglCommandQueue *self,
guint n_binds = 0;
guint n_fbos = 0;
guint n_uniforms = 0;
+ guint n_programs = 0;
guint vao_id;
guint vbo_id;
int textures[4];
@@ -1062,6 +1063,8 @@ gsk_ngl_command_queue_execute (GskNglCommandQueue *self,
{
program = batch->any.program;
glUseProgram (program);
+
+ n_programs++;
}
if (apply_framebuffer (&framebuffer, batch->draw.framebuffer))
@@ -1144,6 +1147,7 @@ gsk_ngl_command_queue_execute (GskNglCommandQueue *self,
gdk_profiler_set_int_counter (self->metrics.n_binds, n_binds);
gdk_profiler_set_int_counter (self->metrics.n_uniforms, n_uniforms);
gdk_profiler_set_int_counter (self->metrics.n_fbos, n_fbos);
+ gdk_profiler_set_int_counter (self->metrics.n_programs, n_programs);
gdk_profiler_set_int_counter (self->metrics.n_uploads, self->n_uploads);
gdk_profiler_set_int_counter (self->metrics.queue_depth, self->batches.len);
@@ -1415,6 +1419,7 @@ gsk_ngl_command_queue_set_profiler (GskNglCommandQueue *self,
self->metrics.n_fbos = gdk_profiler_define_int_counter ("fbos", "Number of framebuffers attached");
self->metrics.n_uniforms = gdk_profiler_define_int_counter ("uniforms", "Number of uniforms changed");
self->metrics.n_uploads = gdk_profiler_define_int_counter ("uploads", "Number of texture uploads");
+ self->metrics.n_programs = gdk_profiler_define_int_counter ("programs", "Number of program changes");
self->metrics.queue_depth = gdk_profiler_define_int_counter ("gl-queue-depth", "Depth of GL command batches");
}
#endif
diff --git a/gsk/ngl/gsknglcommandqueueprivate.h b/gsk/ngl/gsknglcommandqueueprivate.h
index bcd7c8312d..a05095dbf0 100644
--- a/gsk/ngl/gsknglcommandqueueprivate.h
+++ b/gsk/ngl/gsknglcommandqueueprivate.h
@@ -250,6 +250,7 @@ struct _GskNglCommandQueue
guint n_fbos;
guint n_uniforms;
guint n_uploads;
+ guint n_programs;
guint queue_depth;
} metrics;
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
diff --git a/gsk/ngl/gskngltexturelibrary.c b/gsk/ngl/gskngltexturelibrary.c
index 85449b3fa2..2de6e492c5 100644
--- a/gsk/ngl/gskngltexturelibrary.c
+++ b/gsk/ngl/gskngltexturelibrary.c
@@ -20,6 +20,7 @@
#include "config.h"
+#include <gdk/gdkglcontextprivate.h>
#include <gsk/gskdebugprivate.h>
#include "gsknglcommandqueueprivate.h"
@@ -240,6 +241,51 @@ gsk_ngl_texture_atlas_pack (GskNglTextureAtlas *self,
}
static void
+gsk_ngl_texture_atlas_initialize (GskNglDriver *driver,
+ GskNglTextureAtlas *atlas)
+{
+ /* Insert a single pixel at 0,0 for use in coloring */
+
+ gboolean packed;
+ int x, y;
+ guint gl_format;
+ guint gl_type;
+ guint8 pixel_data[4 * 3 * 3];
+
+ gdk_gl_context_push_debug_group_printf (gdk_gl_context_get_current (),
+ "Initializing Atlas");
+
+ packed = gsk_ngl_texture_atlas_pack (atlas, 3, 3, &x, &y);
+ g_assert (packed);
+ g_assert (x == 0 && y == 0);
+
+ memset (pixel_data, 255, sizeof pixel_data);
+
+ if (gdk_gl_context_get_use_es (gdk_gl_context_get_current ()))
+ {
+ gl_format = GL_RGBA;
+ gl_type = GL_UNSIGNED_BYTE;
+ }
+ else
+ {
+ gl_format = GL_BGRA;
+ gl_type = GL_UNSIGNED_INT_8_8_8_8_REV;
+ }
+
+ glBindTexture (GL_TEXTURE_2D, atlas->texture_id);
+
+ glTexSubImage2D (GL_TEXTURE_2D, 0,
+ 0, 0,
+ 3, 3,
+ gl_format, gl_type,
+ pixel_data);
+
+ gdk_gl_context_pop_debug_group (gdk_gl_context_get_current ());
+
+ driver->command_queue->n_uploads++;
+}
+
+static void
gsk_ngl_texture_atlases_pack (GskNglDriver *driver,
int width,
int height,
@@ -265,6 +311,8 @@ gsk_ngl_texture_atlases_pack (GskNglDriver *driver,
/* No atlas has enough space, so create a new one... */
atlas = gsk_ngl_driver_create_atlas (driver);
+ gsk_ngl_texture_atlas_initialize (driver, atlas);
+
/* Pack it onto that one, which surely has enough space... */
if (!gsk_ngl_texture_atlas_pack (atlas, width, height, &x, &y))
g_assert_not_reached ();