[gtk/ngl-less-shaders] ngl: Special-case css backgrounds




commit 19dfc8106b972239030d33985fdb05d5b380be66
Author: Matthias Clasen <mclasen redhat com>
Date:   Sat Mar 13 23:30:18 2021 -0500

    ngl: Special-case css backgrounds
    
    Recognize a common pattern: A rounded clip with
    a color node, followed by a border node, with the
    same outline. This is what CSS backgrounds frequently
    produce, and we can render it more efficiently with
    a combined shader.

 gsk/meson.build                    |  1 +
 gsk/ngl/gsknglcommandqueue.c       |  6 ++++
 gsk/ngl/gskngldriver.c             |  2 ++
 gsk/ngl/gsknglprograms.defs        | 23 ++++++++------
 gsk/ngl/gsknglrenderjob.c          | 64 ++++++++++++++++++++++++++++++++++++++
 gsk/ngl/gskngltypesprivate.h       |  1 +
 gsk/ngl/resources/preamble.vs.glsl |  2 ++
 7 files changed, 90 insertions(+), 9 deletions(-)
---
diff --git a/gsk/meson.build b/gsk/meson.build
index 8f9a6281c0..8e2b0f1782 100644
--- a/gsk/meson.build
+++ b/gsk/meson.build
@@ -40,6 +40,7 @@ gsk_private_ngl_shaders = [
   'ngl/resources/blend.glsl',
   'ngl/resources/repeat.glsl',
   'ngl/resources/custom.glsl',
+  'ngl/resources/filled_border.glsl',
 ]
 
 gsk_public_sources = files([
diff --git a/gsk/ngl/gsknglcommandqueue.c b/gsk/ngl/gsknglcommandqueue.c
index aff201cb4a..bebd315823 100644
--- a/gsk/ngl/gsknglcommandqueue.c
+++ b/gsk/ngl/gsknglcommandqueue.c
@@ -1010,6 +1010,12 @@ gsk_ngl_command_queue_execute (GskNglCommandQueue   *self,
                          sizeof (GskNglDrawVertex),
                          (void *) G_STRUCT_OFFSET (GskNglDrawVertex, color));
 
+  /* 3 = color2 location */
+  glEnableVertexAttribArray (3);
+  glVertexAttribPointer (3, 4, GL_FLOAT, GL_FALSE,
+                         sizeof (GskNglDrawVertex),
+                         (void *) G_STRUCT_OFFSET (GskNglDrawVertex, color2));
+
   /* Setup initial scissor clip */
   if (scissor != NULL)
     {
diff --git a/gsk/ngl/gskngldriver.c b/gsk/ngl/gskngldriver.c
index 3d910e5d51..93763dbb12 100644
--- a/gsk/ngl/gskngldriver.c
+++ b/gsk/ngl/gskngldriver.c
@@ -348,6 +348,7 @@ gsk_ngl_driver_load_programs (GskNglDriver  *self,
   gsk_ngl_compiler_bind_attribute (compiler, "aPosition", 0);
   gsk_ngl_compiler_bind_attribute (compiler, "aUv", 1);
   gsk_ngl_compiler_bind_attribute (compiler, "aColor", 2);
+  gsk_ngl_compiler_bind_attribute (compiler, "aColor2", 3);
 
   /* Use XMacros to register all of our programs and their uniforms */
 #define GSK_NGL_NO_UNIFORMS
@@ -1046,6 +1047,7 @@ gsk_ngl_driver_lookup_shader (GskNglDriver  *self,
       gsk_ngl_compiler_bind_attribute (compiler, "aPosition", 0);
       gsk_ngl_compiler_bind_attribute (compiler, "aUv", 1);
       gsk_ngl_compiler_bind_attribute (compiler, "aColor", 2);
+      gsk_ngl_compiler_bind_attribute (compiler, "aColor2", 3);
 
       if ((program = gsk_ngl_compiler_compile (compiler, NULL, "", error)))
         {
diff --git a/gsk/ngl/gsknglprograms.defs b/gsk/ngl/gsknglprograms.defs
index e20cca2fa9..f4f4a0dfe5 100644
--- a/gsk/ngl/gsknglprograms.defs
+++ b/gsk/ngl/gsknglprograms.defs
@@ -15,8 +15,8 @@ GSK_NGL_DEFINE_PROGRAM (blur,
 
 GSK_NGL_DEFINE_PROGRAM (border,
                         "/org/gtk/libgsk/ngl/border.glsl",
-                        GSK_NGL_ADD_UNIFORM (2, BORDER_WIDTHS, u_widths)
-                        GSK_NGL_ADD_UNIFORM (3, BORDER_OUTLINE_RECT, u_outline_rect))
+                        GSK_NGL_ADD_UNIFORM (1, BORDER_WIDTHS, u_widths)
+                        GSK_NGL_ADD_UNIFORM (2, BORDER_OUTLINE_RECT, u_outline_rect))
 
 GSK_NGL_DEFINE_PROGRAM (color,
                         "/org/gtk/libgsk/ngl/color.glsl",
@@ -42,11 +42,16 @@ GSK_NGL_DEFINE_PROGRAM (cross_fade,
                         GSK_NGL_ADD_UNIFORM (1, CROSS_FADE_PROGRESS, u_progress)
                         GSK_NGL_ADD_UNIFORM (2, CROSS_FADE_SOURCE2, u_source2))
 
+GSK_NGL_DEFINE_PROGRAM (filled_border,
+                        "/org/gtk/libgsk/ngl/filled_border.glsl",
+                        GSK_NGL_ADD_UNIFORM (1, FILLED_BORDER_WIDTHS, u_widths)
+                        GSK_NGL_ADD_UNIFORM (2, FILLED_BORDER_OUTLINE_RECT, u_outline_rect))
+
 GSK_NGL_DEFINE_PROGRAM (inset_shadow,
                         "/org/gtk/libgsk/ngl/inset_shadow.glsl",
-                        GSK_NGL_ADD_UNIFORM (2, INSET_SHADOW_SPREAD, u_spread)
-                        GSK_NGL_ADD_UNIFORM (3, INSET_SHADOW_OFFSET, u_offset)
-                        GSK_NGL_ADD_UNIFORM (4, INSET_SHADOW_OUTLINE_RECT, u_outline_rect))
+                        GSK_NGL_ADD_UNIFORM (1, INSET_SHADOW_SPREAD, u_spread)
+                        GSK_NGL_ADD_UNIFORM (2, INSET_SHADOW_OFFSET, u_offset)
+                        GSK_NGL_ADD_UNIFORM (3, INSET_SHADOW_OUTLINE_RECT, u_outline_rect))
 
 GSK_NGL_DEFINE_PROGRAM (linear_gradient,
                         "/org/gtk/libgsk/ngl/linear_gradient.glsl",
@@ -57,7 +62,7 @@ GSK_NGL_DEFINE_PROGRAM (linear_gradient,
 
 GSK_NGL_DEFINE_PROGRAM (outset_shadow,
                         "/org/gtk/libgsk/ngl/outset_shadow.glsl",
-                        GSK_NGL_ADD_UNIFORM (2, OUTSET_SHADOW_OUTLINE_RECT, u_outline_rect))
+                        GSK_NGL_ADD_UNIFORM (1, OUTSET_SHADOW_OUTLINE_RECT, u_outline_rect))
 
 GSK_NGL_DEFINE_PROGRAM (radial_gradient,
                         "/org/gtk/libgsk/ngl/radial_gradient.glsl",
@@ -74,6 +79,6 @@ GSK_NGL_DEFINE_PROGRAM (repeat,
 
 GSK_NGL_DEFINE_PROGRAM (unblurred_outset_shadow,
                         "/org/gtk/libgsk/ngl/unblurred_outset_shadow.glsl",
-                        GSK_NGL_ADD_UNIFORM (2, UNBLURRED_OUTSET_SHADOW_SPREAD, u_spread)
-                        GSK_NGL_ADD_UNIFORM (3, UNBLURRED_OUTSET_SHADOW_OFFSET, u_offset)
-                        GSK_NGL_ADD_UNIFORM (4, UNBLURRED_OUTSET_SHADOW_OUTLINE_RECT, u_outline_rect))
+                        GSK_NGL_ADD_UNIFORM (1, UNBLURRED_OUTSET_SHADOW_SPREAD, u_spread)
+                        GSK_NGL_ADD_UNIFORM (2, UNBLURRED_OUTSET_SHADOW_OFFSET, u_offset)
+                        GSK_NGL_ADD_UNIFORM (3, UNBLURRED_OUTSET_SHADOW_OUTLINE_RECT, u_outline_rect))
diff --git a/gsk/ngl/gsknglrenderjob.c b/gsk/ngl/gsknglrenderjob.c
index 1a5a98faab..967e91c0ba 100644
--- a/gsk/ngl/gsknglrenderjob.c
+++ b/gsk/ngl/gsknglrenderjob.c
@@ -1794,6 +1794,50 @@ gsk_ngl_render_job_visit_border_node (GskNglRenderJob     *job,
   gsk_ngl_render_job_end_draw (job);
 }
 
+static void
+gsk_ngl_render_job_visit_css_background (GskNglRenderJob     *job,
+                                         const GskRenderNode *node,
+                                         const GskRenderNode *node2)
+{
+  const GskRenderNode *child = gsk_rounded_clip_node_get_child (node);
+  const GdkRGBA *c2 = gsk_color_node_get_color (child);
+  const GdkRGBA *c = gsk_border_node_get_colors (node2);
+  const GskRoundedRect *rounded_outline = gsk_border_node_get_outline (node2);
+  const float *widths = gsk_border_node_get_widths (node2);
+  float min_x = job->offset_x + node2->bounds.origin.x;
+  float min_y = job->offset_y + node2->bounds.origin.y;
+  float max_x = min_x + node2->bounds.size.width;
+  float max_y = min_y + node2->bounds.size.height;
+  GskRoundedRect outline;
+  GskNglDrawVertex *vertices;
+
+  if (node_is_invisible (node2))
+    return;
+
+  gsk_ngl_render_job_transform_rounded_rect (job, rounded_outline, &outline);
+
+  gsk_ngl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, filled_border));
+
+  gsk_ngl_program_set_uniform4fv (job->current_program,
+                                  UNIFORM_FILLED_BORDER_WIDTHS, 0,
+                                  1,
+                                  widths);
+  gsk_ngl_program_set_uniform_rounded_rect (job->current_program,
+                                            UNIFORM_FILLED_BORDER_OUTLINE_RECT, 0,
+                                            &outline);
+
+  vertices = gsk_ngl_command_queue_add_vertices (job->command_queue);
+
+  vertices[0] = (GskNglDrawVertex) { { min_x, min_y }, { 0, 0 }, { c[0].red, c[0].green, c[0].blue, 
c[0].alpha }, { c2->red, c2->green, c2->blue, c2->alpha } };
+  vertices[1] = (GskNglDrawVertex) { { min_x, max_y }, { 0, 0 }, { c[0].red, c[0].green, c[0].blue, 
c[0].alpha }, { c2->red, c2->green, c2->blue, c2->alpha } };
+  vertices[2] = (GskNglDrawVertex) { { max_x, min_y }, { 0, 0 }, { c[0].red, c[0].green, c[0].blue, 
c[0].alpha }, { c2->red, c2->green, c2->blue, c2->alpha } };
+  vertices[3] = (GskNglDrawVertex) { { max_x, max_y }, { 0, 0 }, { c[0].red, c[0].green, c[0].blue, 
c[0].alpha }, { c2->red, c2->green, c2->blue, c2->alpha } };
+  vertices[4] = (GskNglDrawVertex) { { min_x, max_y }, { 0, 0 }, { c[0].red, c[0].green, c[0].blue, 
c[0].alpha }, { c2->red, c2->green, c2->blue, c2->alpha } };
+  vertices[5] = (GskNglDrawVertex) { { max_x, min_y }, { 0, 0 }, { c[0].red, c[0].green, c[0].blue, 
c[0].alpha }, { c2->red, c2->green, c2->blue, c2->alpha } };
+
+  gsk_ngl_render_job_end_draw (job);
+}
+
 /* Returns TRUE if applying @transform to @bounds
  * yields an axis-aligned rectangle
  */
@@ -3337,6 +3381,26 @@ gsk_ngl_render_job_visit_node (GskNglRenderJob     *job,
         for (guint i = 0; i < n_children; i++)
           {
             const GskRenderNode *child = gsk_container_node_get_child (node, i);
+#if 1
+            if (job->current_clip->is_fully_contained &&
+                gsk_render_node_get_node_type (child) == GSK_ROUNDED_CLIP_NODE &&
+                i + 1 < n_children)
+              {
+                const GskRenderNode *child2 = gsk_rounded_clip_node_get_child (child);
+                const GskRenderNode *child3 = gsk_container_node_get_child (node, i + 1);
+                if (gsk_render_node_get_node_type (child2) == GSK_COLOR_NODE &&
+                    gsk_render_node_get_node_type (child3) == GSK_BORDER_NODE &&
+                    gsk_border_node_get_uniform_color (child3) &&
+                    gsk_rounded_rect_equal (gsk_rounded_clip_node_get_clip (child),
+                                            gsk_border_node_get_outline (child3)))
+                  {
+                    gsk_ngl_render_job_visit_css_background (job, child, child3);
+                    i++; /* skip the border node */
+                    continue;
+                  }
+              }
+#endif
+
             gsk_ngl_render_job_visit_node (job, child);
           }
       }
diff --git a/gsk/ngl/gskngltypesprivate.h b/gsk/ngl/gskngltypesprivate.h
index dc76fb41f4..a65130c19f 100644
--- a/gsk/ngl/gskngltypesprivate.h
+++ b/gsk/ngl/gskngltypesprivate.h
@@ -56,6 +56,7 @@ struct _GskNglDrawVertex
   float position[2];
   float uv[2];
   float color[4];
+  float color2[4];
 };
 
 G_END_DECLS
diff --git a/gsk/ngl/resources/preamble.vs.glsl b/gsk/ngl/resources/preamble.vs.glsl
index a549ff6ded..758bca89d2 100644
--- a/gsk/ngl/resources/preamble.vs.glsl
+++ b/gsk/ngl/resources/preamble.vs.glsl
@@ -6,11 +6,13 @@ uniform float u_alpha;
 attribute vec2 aPosition;
 attribute vec2 aUv;
 attribute vec4 aColor;
+attribute vec4 aColor2;
 _OUT_ vec2 vUv;
 #else
 _IN_ vec2 aPosition;
 _IN_ vec2 aUv;
 _IN_ vec4 aColor;
+_IN_ vec4 aColor2;
 _OUT_ vec2 vUv;
 #endif
 


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