[gtk+] gl renderer: Render unblurred outset shadows differently



commit 4946810960f2cca865961ecb87d87c7584be3ccf
Author: Timm Bäder <mail baedert org>
Date:   Mon Jan 15 10:55:40 2018 +0100

    gl renderer: Render unblurred outset shadows differently
    
    We don't need to draw anything to a texure for those.

 gsk/gl/gskglrenderer.c                             |   84 ++++++++++++++++---
 gsk/gl/gskglrenderopsprivate.h                     |   24 +++++-
 gsk/meson.build                                    |    1 +
 gsk/resources/glsl/unblurred_outset_shadow.fs.glsl |   25 ++++++
 4 files changed, 117 insertions(+), 17 deletions(-)
---
diff --git a/gsk/gl/gskglrenderer.c b/gsk/gl/gskglrenderer.c
index 11c088d..7dfa012 100644
--- a/gsk/gl/gskglrenderer.c
+++ b/gsk/gl/gskglrenderer.c
@@ -209,6 +209,7 @@ struct _GskGLRenderer
       Program blur_program;
       Program inset_shadow_program;
       Program outset_shadow_program;
+      Program unblurred_outset_shadow_program;
       Program shadow_program;
       Program border_program;
       Program cross_fade_program;
@@ -861,6 +862,36 @@ render_inset_shadow_node (GskGLRenderer       *self,
 }
 
 static inline void
+render_unblurred_outset_shadow_node (GskGLRenderer       *self,
+                                     GskRenderNode       *node,
+                                     RenderOpBuilder     *builder,
+                                     const GskQuadVertex *vertex_data)
+{
+  const float spread = gsk_outset_shadow_node_get_spread (node);
+  GskRoundedRect r = *gsk_outset_shadow_node_peek_outline (node);
+  RenderOp op;
+
+  op.op = OP_CHANGE_UNBLURRED_OUTSET_SHADOW;
+  rgba_to_float (gsk_outset_shadow_node_peek_color (node), op.unblurred_outset_shadow.color);
+
+  gsk_rounded_rect_shrink (&r, -spread, -spread, -spread, -spread);
+
+  rounded_rect_to_floats (self, builder,
+                          &r,
+                          op.unblurred_outset_shadow.outline,
+                          op.unblurred_outset_shadow.corner_widths,
+                          op.unblurred_outset_shadow.corner_heights);
+
+  op.unblurred_outset_shadow.spread = gsk_outset_shadow_node_get_spread (node) * self->scale_factor;
+  op.unblurred_outset_shadow.offset[0] = gsk_outset_shadow_node_get_dx (node) * self->scale_factor;
+  op.unblurred_outset_shadow.offset[1] = -gsk_outset_shadow_node_get_dy (node) * self->scale_factor;
+
+  ops_set_program (builder, &self->unblurred_outset_shadow_program);
+  ops_add (builder, &op);
+  ops_draw (builder, vertex_data);
+}
+
+static inline void
 render_outset_shadow_node (GskGLRenderer       *self,
                            GskRenderNode       *node,
                            RenderOpBuilder     *builder)
@@ -953,19 +984,12 @@ render_outset_shadow_node (GskGLRenderer       *self,
   gsk_rounded_rect_init_from_rect (&blit_clip,
                                    &GRAPHENE_RECT_INIT (0, 0, texture_width, texture_height), 0.0f);
 
-  if (blur_radius > 0)
-    {
-      ops_set_program (builder, &self->blur_program);
-      op.op = OP_CHANGE_BLUR;
-      op.blur.size.width = texture_width;
-      op.blur.size.height = texture_height;
-      op.blur.radius = blur_radius;
-      ops_add (builder, &op);
-    }
-  else
-    {
-      ops_set_program (builder, &self->blit_program);
-    }
+  ops_set_program (builder, &self->blur_program);
+  op.op = OP_CHANGE_BLUR;
+  op.blur.size.width = texture_width;
+  op.blur.size.height = texture_height;
+  op.blur.radius = blur_radius;
+  ops_add (builder, &op);
 
   ops_set_clip (builder, &blit_clip);
   ops_set_texture (builder, texture_id);
@@ -1536,6 +1560,22 @@ apply_inset_shadow_op (const Program  *program,
   glUniform4fv (program->inset_shadow.corner_widths_location, 1, op->inset_shadow.corner_widths);
   glUniform4fv (program->inset_shadow.corner_heights_location, 1, op->inset_shadow.corner_heights);
 }
+
+static inline void
+apply_unblurred_outset_shadow_op (const Program  *program,
+                                  const RenderOp *op)
+{
+  OP_PRINT (" -> unblurred outset shadow");
+  glUniform4fv (program->unblurred_outset_shadow.color_location, 1, op->unblurred_outset_shadow.color);
+  glUniform2fv (program->unblurred_outset_shadow.offset_location, 1, op->unblurred_outset_shadow.offset);
+  glUniform1f (program->unblurred_outset_shadow.spread_location, op->unblurred_outset_shadow.spread);
+  glUniform4fv (program->unblurred_outset_shadow.outline_location, 1, op->unblurred_outset_shadow.outline);
+  glUniform4fv (program->unblurred_outset_shadow.corner_widths_location, 1,
+                op->unblurred_outset_shadow.corner_widths);
+  glUniform4fv (program->unblurred_outset_shadow.corner_heights_location, 1,
+                op->unblurred_outset_shadow.corner_heights);
+}
+
 static inline void
 apply_outset_shadow_op (const Program  *program,
                         const RenderOp *op)
@@ -1684,6 +1724,7 @@ gsk_gl_renderer_create_programs (GskGLRenderer  *self,
     { "blur",            "blit.vs.glsl",  "blur.fs.glsl" },
     { "inset shadow",    "blit.vs.glsl",  "inset_shadow.fs.glsl" },
     { "outset shadow",   "blit.vs.glsl",  "outset_shadow.fs.glsl" },
+    { "unblurred outset shadow",   "blit.vs.glsl",  "unblurred_outset_shadow.fs.glsl" },
     { "shadow",          "blit.vs.glsl",  "shadow.fs.glsl" },
     { "border",          "blit.vs.glsl",  "border.fs.glsl" },
     { "cross fade",      "blit.vs.glsl",  "cross_fade.fs.glsl" },
@@ -1795,6 +1836,14 @@ gsk_gl_renderer_create_programs (GskGLRenderer  *self,
   INIT_PROGRAM_UNIFORM_LOCATION (outset_shadow, corner_widths);
   INIT_PROGRAM_UNIFORM_LOCATION (outset_shadow, corner_heights);
 
+  /* unblurred outset shadow */
+  INIT_PROGRAM_UNIFORM_LOCATION (unblurred_outset_shadow, color);
+  INIT_PROGRAM_UNIFORM_LOCATION (unblurred_outset_shadow, spread);
+  INIT_PROGRAM_UNIFORM_LOCATION (unblurred_outset_shadow, offset);
+  INIT_PROGRAM_UNIFORM_LOCATION (unblurred_outset_shadow, outline);
+  INIT_PROGRAM_UNIFORM_LOCATION (unblurred_outset_shadow, corner_widths);
+  INIT_PROGRAM_UNIFORM_LOCATION (unblurred_outset_shadow, corner_heights);
+
   /* shadow */
   INIT_PROGRAM_UNIFORM_LOCATION (shadow, color);
 
@@ -2109,7 +2158,10 @@ gsk_gl_renderer_add_render_ops (GskGLRenderer   *self,
     break;
 
     case GSK_OUTSET_SHADOW_NODE:
-      render_outset_shadow_node (self, node, builder);
+      if (gsk_outset_shadow_node_get_blur_radius (node) > 0)
+        render_outset_shadow_node (self, node, builder);
+      else
+        render_unblurred_outset_shadow_node (self, node, builder, vertex_data);
     break;
 
     case GSK_SHADOW_NODE:
@@ -2346,6 +2398,10 @@ gsk_gl_renderer_render_ops (GskGLRenderer *self,
           apply_border_op (program, op);
           break;
 
+        case OP_CHANGE_UNBLURRED_OUTSET_SHADOW:
+          apply_unblurred_outset_shadow_op (program, op);
+          break;
+
         case OP_DRAW:
           OP_PRINT (" -> draw %ld, size %ld and program %d\n",
                     op->draw.vao_offset, op->draw.vao_size, program->index);
diff --git a/gsk/gl/gskglrenderopsprivate.h b/gsk/gl/gskglrenderopsprivate.h
index aaff53c..b700b75 100644
--- a/gsk/gl/gskglrenderopsprivate.h
+++ b/gsk/gl/gskglrenderopsprivate.h
@@ -10,7 +10,7 @@
 #include "gskglrendererprivate.h"
 
 #define GL_N_VERTICES 6
-#define GL_N_PROGRAMS 12
+#define GL_N_PROGRAMS 13
 
 enum {
   OP_NONE,
@@ -32,8 +32,9 @@ enum {
   OP_CHANGE_BORDER          =  16,
   OP_CHANGE_BORDER_COLOR    =  17,
   OP_CHANGE_CROSS_FADE      =  18,
-  OP_CLEAR                  =  19,
-  OP_DRAW                   =  20,
+  OP_CHANGE_UNBLURRED_OUTSET_SHADOW = 19,
+  OP_CLEAR                  =  20,
+  OP_DRAW                   =  21,
 };
 
 typedef struct
@@ -95,6 +96,14 @@ typedef struct
       int corner_heights_location;
     } outset_shadow;
     struct {
+      int outline_location;
+      int corner_widths_location;
+      int corner_heights_location;
+      int color_location;
+      int spread_location;
+      int offset_location;
+    } unblurred_outset_shadow;
+    struct {
       int color_location;
       int widths_location;
     } border;
@@ -160,6 +169,15 @@ typedef struct
       float color[4];
     } outset_shadow;
     struct {
+      float outline[4];
+      float corner_widths[4];
+      float corner_heights[4];
+      float radius;
+      float spread;
+      float offset[2];
+      float color[4];
+    } unblurred_outset_shadow;
+    struct {
       float color[4];
     } shadow;
     struct {
diff --git a/gsk/meson.build b/gsk/meson.build
index b852237..d6e1342 100644
--- a/gsk/meson.build
+++ b/gsk/meson.build
@@ -10,6 +10,7 @@ gsk_private_gl_shaders = [
   'resources/glsl/blur.fs.glsl',
   'resources/glsl/inset_shadow.fs.glsl',
   'resources/glsl/outset_shadow.fs.glsl',
+  'resources/glsl/unblurred_outset_shadow.fs.glsl',
   'resources/glsl/shadow.fs.glsl',
   'resources/glsl/border.fs.glsl',
   'resources/glsl/cross_fade.fs.glsl',
diff --git a/gsk/resources/glsl/unblurred_outset_shadow.fs.glsl 
b/gsk/resources/glsl/unblurred_outset_shadow.fs.glsl
new file mode 100644
index 0000000..1ae48ec
--- /dev/null
+++ b/gsk/resources/glsl/unblurred_outset_shadow.fs.glsl
@@ -0,0 +1,25 @@
+uniform float u_spread;
+uniform vec4 u_color;
+uniform vec2 u_offset;
+uniform vec4 u_outline;
+uniform vec4 u_corner_widths;
+uniform vec4 u_corner_heights;
+
+
+void main() {
+  vec4 f = gl_FragCoord;
+
+  f.x += u_viewport.x;
+  f.y = (u_viewport.y + u_viewport.w) - f.y;
+
+  RoundedRect outline = RoundedRect(vec4(u_outline.xy, u_outline.xy + u_outline.zw),
+                                    u_corner_widths, u_corner_heights);
+  RoundedRect inside = rounded_rect_shrink(outline, vec4(u_spread));
+
+  vec2 offset = vec2(u_offset.x, - u_offset.y);
+  vec4 color = vec4(u_color.rgb * u_color.a, u_color.a);
+  color = color * clamp (rounded_rect_coverage (outline, f.xy - offset) -
+                         rounded_rect_coverage (inside, f.xy),
+                         0.0, 1.0);
+  setOutputColor(color * u_alpha);
+}


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