[gtk+: 43/97] gl renderer: Implement unblurred inset shadows



commit 388157b99502c8b723d3d83a1800db4ef623d0ae
Author: Timm Bäder <mail baedert org>
Date:   Thu Nov 30 16:48:03 2017 +0100

    gl renderer: Implement unblurred inset shadows

 gsk/gl/gskglrenderer.c                  |   88 ++++++++++++++++++++++++++++++-
 gsk/gl/gskglrenderopsprivate.h          |   24 +++++++-
 gsk/meson.build                         |    1 +
 gsk/resources/glsl/gl3_common.fs.glsl   |    1 +
 gsk/resources/glsl/inset_shadow.fs.glsl |   28 ++++++++++
 5 files changed, 138 insertions(+), 4 deletions(-)
---
diff --git a/gsk/gl/gskglrenderer.c b/gsk/gl/gskglrenderer.c
index b8883d9..4a2211e 100644
--- a/gsk/gl/gskglrenderer.c
+++ b/gsk/gl/gskglrenderer.c
@@ -74,6 +74,36 @@ font_has_color_glyphs (const PangoFont *font)
   return has_color;
 }
 
+static inline void
+rounded_rect_to_floats (const GskRoundedRect *rect,
+                        float                *outline,
+                        float                *corner_widths,
+                        float                *corner_heights)
+{
+  int i;
+
+  outline[0] = rect->bounds.origin.x;
+  outline[1] = rect->bounds.origin.y;
+  outline[2] = rect->bounds.size.width;
+  outline[3] = rect->bounds.size.height;
+
+  for (i = 0; i < 4; i ++)
+    {
+      corner_widths[i] = MAX (rect->corner[i].width, 1);
+      corner_heights[i] = MAX (rect->corner[i].height, 1);
+    }
+}
+
+static inline void
+rgba_to_float (const GdkRGBA *c,
+               float         *f)
+{
+  f[0] = c->red;
+  f[1] = c->green;
+  f[2] = c->blue;
+  f[3] = c->alpha;
+}
+
 static void gsk_gl_renderer_setup_render_mode (GskGLRenderer   *self);
 static void add_offscreen_ops                 (GskGLRenderer   *self,
                                                RenderOpBuilder *builder,
@@ -131,6 +161,7 @@ struct _GskGLRenderer
       Program color_matrix_program;
       Program linear_gradient_program;
       Program blur_program;
+      Program inset_shadow_program;
     };
   };
 
@@ -388,6 +419,25 @@ gsk_gl_renderer_create_programs (GskGLRenderer  *self,
   INIT_PROGRAM_UNIFORM_LOCATION (blur_program, blur_radius_location, "uBlurRadius");
   INIT_PROGRAM_UNIFORM_LOCATION (blur_program, blur_size_location, "uSize");
 
+  self->inset_shadow_program.id = gsk_shader_builder_create_program (builder,
+                                                                     "blit.vs.glsl", "inset_shadow.fs.glsl",
+                                                                     &shader_error);
+  if (shader_error != NULL)
+    {
+      g_propagate_prefixed_error (error,
+                                  shader_error,
+                                  "Unable to create 'inset shadow' program: ");
+      goto out;
+    }
+  self->blur_program.index = 7;
+  self->blur_program.name = "inset shadow";
+  init_common_locations (self, builder, &self->inset_shadow_program);
+  INIT_PROGRAM_UNIFORM_LOCATION (inset_shadow_program, inset_shadow_color_location, "uColor");
+  INIT_PROGRAM_UNIFORM_LOCATION (inset_shadow_program, inset_shadow_spread_location, "uSpread");
+  INIT_PROGRAM_UNIFORM_LOCATION (inset_shadow_program, inset_shadow_outline_location, "uOutline");
+  INIT_PROGRAM_UNIFORM_LOCATION (inset_shadow_program, inset_shadow_outline_corner_widths_location, 
"uOutlineCornerWidths");
+  INIT_PROGRAM_UNIFORM_LOCATION (inset_shadow_program, inset_shadow_outline_corner_heights_location, 
"uOutlineCornerHeights");
+
   res = TRUE;
 
 out:
@@ -1005,9 +1055,35 @@ gsk_gl_renderer_add_render_ops (GskGLRenderer   *self,
       }
     break;
 
+    case GSK_INSET_SHADOW_NODE:
+      {
+        RenderOp op;
+
+        /* TODO: Implement blurred inset shadows as well */
+        if (gsk_inset_shadow_node_get_blur_radius (node) > 0)
+          goto do_default;
+
+        op.op = OP_CHANGE_INSET_SHADOW;
+        rgba_to_float (gsk_inset_shadow_node_peek_color (node), op.inset_shadow.color);
+        rounded_rect_to_floats (gsk_inset_shadow_node_peek_outline (node),
+                                op.inset_shadow.outline,
+                                op.inset_shadow.corner_widths,
+                                op.inset_shadow.corner_heights);
+        op.inset_shadow.radius = gsk_inset_shadow_node_get_blur_radius (node);
+        op.inset_shadow.spread = gsk_inset_shadow_node_get_spread (node);
+        op.inset_shadow.d[0] = gsk_inset_shadow_node_get_dx (node);
+        op.inset_shadow.d[1] = -gsk_inset_shadow_node_get_dy (node);
+
+        ops_set_program (builder, &self->inset_shadow_program);
+        ops_add (builder, &op);
+        ops_draw (builder, vertex_data);
+      }
+    break;
+
+do_default:
+
     case GSK_REPEATING_LINEAR_GRADIENT_NODE:
     case GSK_BORDER_NODE:
-    case GSK_INSET_SHADOW_NODE:
     case GSK_OUTSET_SHADOW_NODE:
     case GSK_SHADOW_NODE:
     case GSK_CROSS_FADE_NODE:
@@ -1305,6 +1381,16 @@ gsk_gl_renderer_render_ops (GskGLRenderer *self,
           glUniform2f (program->blur_size_location, op->blur.size.width, op->blur.size.height);
           break;
 
+       case OP_CHANGE_INSET_SHADOW:
+          g_assert (program == &self->inset_shadow_program);
+          glUniform4fv (program->inset_shadow_color_location, 1, op->inset_shadow.color);
+          glUniform2fv (program->inset_shadow_d_location, 1, op->inset_shadow.d);
+          glUniform1f (program->inset_shadow_spread_location, op->inset_shadow.spread);
+          glUniform4fv (program->inset_shadow_outline_location, 1, op->inset_shadow.outline);
+          glUniform4fv (program->inset_shadow_outline_corner_widths_location, 1, 
op->inset_shadow.corner_widths);
+          glUniform4fv (program->inset_shadow_outline_corner_heights_location, 1, 
op->inset_shadow.corner_heights);
+          break;
+
         case OP_DRAW:
           OP_PRINT (" -> draw %ld, size %ld and program %s\n",
                     op->draw.vao_offset, op->draw.vao_size, program->name);
diff --git a/gsk/gl/gskglrenderopsprivate.h b/gsk/gl/gskglrenderopsprivate.h
index f324c83..beec752 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 7
+#define GL_N_PROGRAMS 8
 
 enum {
   OP_NONE,
@@ -27,8 +27,9 @@ enum {
   OP_CHANGE_LINEAR_GRADIENT =  11,
   OP_CHANGE_COLOR_MATRIX    =  12,
   OP_CHANGE_BLUR            =  13,
-  OP_CLEAR                  =  14,
-  OP_DRAW                   =  15,
+  OP_CHANGE_INSET_SHADOW    =  14,
+  OP_CLEAR                  =  15,
+  OP_DRAW                   =  16,
 };
 
 typedef struct
@@ -76,6 +77,14 @@ typedef struct
       int blur_radius_location;
       int blur_size_location;
     };
+    struct {
+      int inset_shadow_color_location;
+      int inset_shadow_spread_location;
+      int inset_shadow_d_location;
+      int inset_shadow_outline_location;
+      int inset_shadow_outline_corner_widths_location;
+      int inset_shadow_outline_corner_heights_location;
+    };
   };
 } Program;
 
@@ -113,6 +122,15 @@ typedef struct
       float radius;
       graphene_size_t size;
     } blur;
+    struct {
+      float outline[4];
+      float corner_widths[4];
+      float corner_heights[4];
+      float radius;
+      float spread;
+      float d[2];
+      float color[4];
+    } inset_shadow;
   };
 } RenderOp;
 
diff --git a/gsk/meson.build b/gsk/meson.build
index 548c193..01bbd32 100644
--- a/gsk/meson.build
+++ b/gsk/meson.build
@@ -9,6 +9,7 @@ gsk_private_source_shaders = [
   'resources/glsl/linear_gradient.fs.glsl',
   'resources/glsl/blur.vs.glsl',
   'resources/glsl/blur.fs.glsl',
+  'resources/glsl/inset_shadow.fs.glsl',
   'resources/glsl/es2_common.fs.glsl',
   'resources/glsl/es2_common.vs.glsl',
   'resources/glsl/gl3_common.fs.glsl',
diff --git a/gsk/resources/glsl/gl3_common.fs.glsl b/gsk/resources/glsl/gl3_common.fs.glsl
index 4e516d2..3eb4c7b 100644
--- a/gsk/resources/glsl/gl3_common.fs.glsl
+++ b/gsk/resources/glsl/gl3_common.fs.glsl
@@ -100,4 +100,5 @@ void setOutputColor(vec4 color) {
   RoundedRect r = RoundedRect(clipBounds, uClipCornerWidths, uClipCornerHeights);
 
   outputColor = color * rounded_rect_coverage(r, f.xy);
+  /*outputColor = color;*/
 }
diff --git a/gsk/resources/glsl/inset_shadow.fs.glsl b/gsk/resources/glsl/inset_shadow.fs.glsl
new file mode 100644
index 0000000..6cb4368
--- /dev/null
+++ b/gsk/resources/glsl/inset_shadow.fs.glsl
@@ -0,0 +1,28 @@
+uniform float uSpread;
+uniform float uBlurRadius;
+uniform vec4 uColor;
+uniform vec2 uD;
+uniform vec4 uOutline;
+uniform vec4 uOutlineCornerWidths;
+uniform vec4 uOutlineCornerHeights;
+
+
+void main() {
+  vec4 f = gl_FragCoord;
+
+  f.x += uViewport.x;
+  f.y = (uViewport.y + uViewport.w) - f.y;
+
+  RoundedRect outline = RoundedRect(vec4(uOutline.xy, uOutline.xy + uOutline.zw),
+                                    uOutlineCornerWidths, uOutlineCornerHeights);
+  RoundedRect inside = rounded_rect_shrink(outline, vec4(uSpread));
+
+  vec4 color = vec4(uColor.rgb * uColor.a, uColor.a);
+  color = color * clamp (rounded_rect_coverage (outline, f.xy) -
+                         rounded_rect_coverage (inside, f.xy - uD),
+                         0.0, 1.0);
+  setOutputColor(color);
+
+  /*setOutputColor(vec4(1, 0, 0, 1) * rounded_rect_coverage (outline, f.xy));*/
+  /*setOutputColor(vec4(0, 0, 1, 1) * rounded_rect_coverage (inside, f.xy));*/
+}


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