[gtk+/wip/baedert/gl: 15/37] gl renderer: Save clip in every node



commit 55f75b34afc6763dded9f710b58496c86ebe412b
Author: Timm Bäder <mail baedert org>
Date:   Thu Nov 16 21:04:18 2017 +0100

    gl renderer: Save clip in every node

 gsk/gskglrenderer.c                        |  174 ++++++++++++++++------------
 gsk/meson.build                            |    1 +
 gsk/resources/glsl/gl3_common.fs.glsl      |   85 +++++++++++++-
 gsk/resources/glsl/gl3_common.vs.glsl      |    1 +
 gsk/resources/glsl/linear_gradient.fs.glsl |    8 +-
 gsk/resources/glsl/rounded_clip.fs.glsl    |   91 ---------------
 6 files changed, 189 insertions(+), 171 deletions(-)
---
diff --git a/gsk/gskglrenderer.c b/gsk/gskglrenderer.c
index b42c690..9634459 100644
--- a/gsk/gskglrenderer.c
+++ b/gsk/gskglrenderer.c
@@ -57,6 +57,10 @@ typedef struct {
   int blendMode_location;
   int viewport_location;
   int projection_location;
+  int modelview_location;
+  int clip_location;
+  int clip_corner_widths_location;
+  int clip_corner_heights_location;
 
   /* Shader-specific locations */
   union {
@@ -94,7 +98,6 @@ enum {
   MODE_TEXTURE,
   MODE_COLOR_MATRIX,
   MODE_LINEAR_GRADIENT,
-  MODE_ROUNDED_CLIP,
   N_MODES
 };
 
@@ -108,6 +111,10 @@ typedef struct {
 
   graphene_matrix_t mvp;
   graphene_matrix_t projection;
+  graphene_matrix_t modelview;
+
+  /* (Rounded) Clip */
+  GskRoundedRect rounded_clip;
 
   float opacity;
   float z;
@@ -127,11 +134,6 @@ typedef struct {
       graphene_point_t start_point;
       graphene_point_t end_point;
     } linear_gradient_data;
-    struct {
-      graphene_rect_t clip_bounds;
-      float corner_widths[4];
-      float corner_heights[4];
-    } rounded_clip_data;
   };
 
   const char *name;
@@ -165,6 +167,10 @@ enum {
   BLEND_MODE,
   VIEWPORT,
   PROJECTION,
+  MODELVIEW,
+  CLIP,
+  CLIP_CORNER_WIDTHS,
+  CLIP_CORNER_HEIGHTS,
   N_UNIFORMS
 };
 
@@ -216,7 +222,7 @@ struct _GskGLRenderer
   Program color_program;
   Program color_matrix_program;
   Program linear_gradient_program;
-  Program rounded_clip_program;
+  Program clip_program;
 
   GArray *render_items;
 
@@ -314,6 +320,14 @@ init_common_locations (GskGLRenderer    *self,
                                                                      self->uniforms[VIEWPORT]);
   prog->projection_location = gsk_shader_builder_get_uniform_location (builder, prog->id,
                                                                        self->uniforms[PROJECTION]);
+  prog->modelview_location = gsk_shader_builder_get_uniform_location (builder, prog->id,
+                                                                      self->uniforms[MODELVIEW]);
+  prog->clip_location = gsk_shader_builder_get_uniform_location (builder, prog->id,
+                                                                 self->uniforms[CLIP]);
+  prog->clip_corner_widths_location = gsk_shader_builder_get_uniform_location (builder, prog->id,
+                                                                               
self->uniforms[CLIP_CORNER_WIDTHS]);
+  prog->clip_corner_heights_location = gsk_shader_builder_get_uniform_location (builder, prog->id,
+                                                                               
self->uniforms[CLIP_CORNER_HEIGHTS]);
 
   prog->position_location =
     gsk_shader_builder_get_attribute_location (builder, prog->id, self->attributes[POSITION]);
@@ -340,6 +354,10 @@ gsk_gl_renderer_create_programs (GskGLRenderer  *self,
   self->uniforms[BLEND_MODE] = gsk_shader_builder_add_uniform (builder, "uBlendMode");
   self->uniforms[VIEWPORT] = gsk_shader_builder_add_uniform (builder, "uViewport");
   self->uniforms[PROJECTION] = gsk_shader_builder_add_uniform (builder, "uProjection");
+  self->uniforms[MODELVIEW] = gsk_shader_builder_add_uniform (builder, "uModelview");
+  self->uniforms[CLIP] = gsk_shader_builder_add_uniform (builder, "uClip");
+  self->uniforms[CLIP_CORNER_WIDTHS] = gsk_shader_builder_add_uniform (builder, "uClipCornerWidths");
+  self->uniforms[CLIP_CORNER_HEIGHTS] = gsk_shader_builder_add_uniform (builder, "uClipCornerHeights");
 
   self->attributes[POSITION] = gsk_shader_builder_add_attribute (builder, "aPosition");
   self->attributes[UV] = gsk_shader_builder_add_attribute (builder, "aUv");
@@ -428,7 +446,7 @@ gsk_gl_renderer_create_programs (GskGLRenderer  *self,
   INIT_PROGRAM_UNIFORM_LOCATION (color_matrix_program, color_offset_location, "uColorOffset");
 
   self->linear_gradient_program.id = gsk_shader_builder_create_program (builder,
-                                                                        "linear_gradient.vs.glsl",
+                                                                        "blit.vs.glsl",
                                                                         "linear_gradient.fs.glsl",
                                                                         &shader_error);
   if (shader_error != NULL)
@@ -445,22 +463,6 @@ gsk_gl_renderer_create_programs (GskGLRenderer  *self,
   INIT_PROGRAM_UNIFORM_LOCATION (linear_gradient_program, start_point_location, "uStartPoint");
   INIT_PROGRAM_UNIFORM_LOCATION (linear_gradient_program, end_point_location, "uEndPoint");
 
-  self->rounded_clip_program.id = gsk_shader_builder_create_program (builder,
-                                                                     "blit.vs.glsl",
-                                                                     "rounded_clip.fs.glsl",
-                                                                     &shader_error);
-  if (shader_error != NULL)
-    {
-      g_propagate_prefixed_error (error,
-                                  shader_error,
-                                  "Unable to create 'rounded_clip' program: ");
-      goto out;
-    }
-  init_common_locations (self, builder, &self->rounded_clip_program);
-  INIT_PROGRAM_UNIFORM_LOCATION (rounded_clip_program, clip_bounds_location, "uClipBounds");
-  INIT_PROGRAM_UNIFORM_LOCATION (rounded_clip_program, corner_widths_location, "uCornerWidths");
-  INIT_PROGRAM_UNIFORM_LOCATION (rounded_clip_program, corner_heights_location, "uCornerHeights");
-
   res = TRUE;
 
 out:
@@ -718,21 +720,6 @@ render_item (GskGLRenderer    *self,
         }
       break;
 
-      case MODE_ROUNDED_CLIP:
-        {
-          g_assert (item->program == &self->rounded_clip_program);
-          glUniform1i (item->program->source_location, 0);
-          gsk_gl_driver_bind_source_texture (self->gl_driver, item->render_target);
-          glUniform4f (item->program->clip_bounds_location,
-                       item->rounded_clip_data.clip_bounds.origin.x,
-                       item->rounded_clip_data.clip_bounds.origin.y,
-                       item->rounded_clip_data.clip_bounds.size.width,
-                       item->rounded_clip_data.clip_bounds.size.height);
-          glUniform4fv (item->program->corner_widths_location, 1, item->rounded_clip_data.corner_widths);
-          glUniform4fv (item->program->corner_heights_location, 1, item->rounded_clip_data.corner_heights);
-        }
-      break;
-
       default:
         g_assert_not_reached ();
     }
@@ -740,12 +727,30 @@ render_item (GskGLRenderer    *self,
   /* Common uniforms */
   graphene_matrix_to_float (&item->mvp, mat);
   glUniformMatrix4fv (item->program->mvp_location, 1, GL_FALSE, mat);
+
   graphene_matrix_to_float (&item->projection, mat);
-  glUniformMatrix4fv (item->program->projection_location, 1, GL_FALSE, mat);
+  glUniformMatrix4fv (item->program->projection_location, 1, GL_TRUE, mat);
+
+  graphene_matrix_to_float (&item->modelview, mat);
+  glUniformMatrix4fv (item->program->modelview_location, 1, GL_TRUE, mat);
   glUniform1f (item->program->alpha_location, item->opacity);
   glUniform4f (item->program->viewport_location,
                self->viewport.origin.x, self->viewport.origin.y,
                self->viewport.size.width, self->viewport.size.height);
+  glUniform4f (item->program->clip_location,
+               item->rounded_clip.bounds.origin.x, item->rounded_clip.bounds.origin.y,
+               item->rounded_clip.bounds.size.width, item->rounded_clip.bounds.size.height);
+
+  glUniform4f (item->program->clip_corner_widths_location,
+               MAX (item->rounded_clip.corner[0].width, 1),
+               MAX (item->rounded_clip.corner[1].width, 1),
+               MAX (item->rounded_clip.corner[2].width, 1),
+               MAX (item->rounded_clip.corner[3].width, 1));
+  glUniform4f (item->program->clip_corner_heights_location,
+               MAX (item->rounded_clip.corner[0].height, 1),
+               MAX (item->rounded_clip.corner[1].height, 1),
+               MAX (item->rounded_clip.corner[2].height, 1),
+               MAX (item->rounded_clip.corner[3].height, 1));
 
   gsk_gl_driver_bind_vao (self->gl_driver, item->vao_id);
   glDrawArrays (GL_TRIANGLES, 0, N_VERTICES);
@@ -836,7 +841,8 @@ gsk_gl_renderer_add_render_item (GskGLRenderer           *self,
                                  const graphene_matrix_t *modelview,
                                  GArray                  *render_items,
                                  GskRenderNode           *node,
-                                 int                      render_target)
+                                 int                      render_target,
+                                 const GskRoundedRect    *parent_clip)
 {
   RenderItem item;
 
@@ -848,7 +854,8 @@ gsk_gl_renderer_add_render_item (GskGLRenderer           *self,
       for (i = 0, p = gsk_container_node_get_n_children (node); i < p; i++)
         {
           GskRenderNode *child = gsk_container_node_get_child (node, i);
-          gsk_gl_renderer_add_render_item (self, projection, modelview, render_items, child, render_target);
+          gsk_gl_renderer_add_render_item (self, projection, modelview, render_items,
+                                           child, render_target, parent_clip);
         }
       return;
     }
@@ -857,7 +864,6 @@ gsk_gl_renderer_add_render_item (GskGLRenderer           *self,
 
   item.name = node->name != NULL ? node->name : "unnamed";
 
-  /*g_message ("%s: %s", __FUNCTION__, item.name);*/
 
   item.size.width = node->bounds.size.width;
   item.size.height = node->bounds.size.height;
@@ -867,8 +873,6 @@ gsk_gl_renderer_add_render_item (GskGLRenderer           *self,
   item.min.x = node->bounds.origin.x;
   item.min.y = node->bounds.origin.y;
 
-  /*g_message ("%s: %f, %f", item.name, item.min.x, item.min.y);*/
-
   item.max.x = item.min.x + node->bounds.size.width;
   item.max.y = item.min.y + node->bounds.size.height;
 
@@ -878,6 +882,8 @@ gsk_gl_renderer_add_render_item (GskGLRenderer           *self,
 
   item.opacity = 1.0;
   item.projection = *projection;
+  item.modelview = *modelview;
+  item.rounded_clip = *parent_clip;
 
   item.blend_mode = GSK_BLEND_MODE_DEFAULT;
 
@@ -902,7 +908,7 @@ gsk_gl_renderer_add_render_item (GskGLRenderer           *self,
             graphene_matrix_init_identity (&identity);
             init_framebuffer_for_node (self, &item, node, projection, &p);
             gsk_gl_renderer_add_render_item (self, &p, &identity, item.children, child,
-                                             item.render_target);
+                                             item.render_target, parent_clip);
           }
         else
           {
@@ -925,39 +931,49 @@ gsk_gl_renderer_add_render_item (GskGLRenderer           *self,
     case GSK_CLIP_NODE:
       {
         GskRenderNode *child = gsk_clip_node_get_child (node);
-        graphene_matrix_t p;
-        graphene_matrix_t identity;
+        graphene_rect_t transformed_clip;
+        graphene_rect_t intersection;
+        GskRoundedRect child_clip;
 
-        graphene_matrix_init_identity (&identity);
-        init_framebuffer_for_node (self, &item, node, projection, &p);
-        gsk_gl_renderer_add_render_item (self, &p, &identity, item.children, child,
-                                         item.render_target);
-        item.mode = MODE_BLIT;
+        transformed_clip = *gsk_clip_node_peek_clip (node);
+        graphene_matrix_transform_bounds (modelview, &transformed_clip, &transformed_clip);
+
+        /* Since we do the intersection here, we also need to transform by the modelview matrix.
+         * We can't do it in the shader. Same with rounded clips */
+        graphene_rect_intersection (&transformed_clip,
+                                    &parent_clip->bounds,
+                                    &intersection);
+
+        gsk_rounded_rect_init_from_rect (&child_clip, &intersection, 0.0f);
+
+        gsk_gl_renderer_add_render_item (self, projection, modelview, render_items, child,
+                                         render_target, &child_clip);
       }
-      break;
+      return;
 
     case GSK_ROUNDED_CLIP_NODE:
       {
         GskRenderNode *child = gsk_rounded_clip_node_get_child (node);
-        const GskRoundedRect *clip = gsk_rounded_clip_node_peek_clip (node);
-        graphene_matrix_t p;
-        graphene_matrix_t identity;
-        int i;
-
-        graphene_matrix_init_identity (&identity);
-        init_framebuffer_for_node (self, &item, node, projection, &p);
-        gsk_gl_renderer_add_render_item (self, &p, &identity, item.children, child,
-                                         item.render_target);
-        item.mode = MODE_ROUNDED_CLIP;
-        item.program = &self->rounded_clip_program;
-        item.rounded_clip_data.clip_bounds = clip->bounds;
-        for (i = 0; i < 4; i ++)
-          {
-            item.rounded_clip_data.corner_widths[i]  = MAX (clip->corner[i].width,  1);
-            item.rounded_clip_data.corner_heights[i] = MAX (clip->corner[i].height, 1);
-          }
+        const GskRoundedRect *rounded_clip = gsk_rounded_clip_node_peek_clip (node);
+        graphene_rect_t transformed_clip;
+        graphene_rect_t intersection;
+        GskRoundedRect child_clip;
+
+        transformed_clip = rounded_clip->bounds;
+        graphene_matrix_transform_bounds (modelview, &transformed_clip, &transformed_clip);
+
+        graphene_rect_intersection (&transformed_clip, &parent_clip->bounds,
+                                    &intersection);
+        gsk_rounded_rect_init (&child_clip, &intersection,
+                               &rounded_clip->corner[0],
+                               &rounded_clip->corner[1],
+                               &rounded_clip->corner[2],
+                               &rounded_clip->corner[3]);
+
+        gsk_gl_renderer_add_render_item (self, projection, modelview, render_items, child,
+                                         render_target, &child_clip);
       }
-      break;
+      return;
 
     case GSK_COLOR_MATRIX_NODE:
       {
@@ -972,7 +988,7 @@ gsk_gl_renderer_add_render_item (GskGLRenderer           *self,
             graphene_matrix_init_identity (&identity);
             init_framebuffer_for_node (self, &item, node, projection, &p);
             gsk_gl_renderer_add_render_item (self, &p, &identity, item.children, child,
-                                             item.render_target);
+                                             item.render_target, parent_clip);
           }
         else
           {
@@ -1075,10 +1091,12 @@ gsk_gl_renderer_add_render_item (GskGLRenderer           *self,
         graphene_matrix_init_from_matrix (&transform, gsk_transform_node_peek_transform (node));
         graphene_matrix_multiply (&transform, modelview, &transformed_mv);
         gsk_gl_renderer_add_render_item (self,
-                                         projection, &transformed_mv,
+                                         projection,
+                                         &transformed_mv,
                                          render_items,
                                          gsk_transform_node_get_child (node),
-                                         render_target);
+                                         render_target,
+                                         parent_clip);
       }
       return;
 
@@ -1188,12 +1206,16 @@ gsk_gl_renderer_validate_tree (GskGLRenderer           *self,
                                const graphene_matrix_t *projection)
 {
   graphene_matrix_t modelview;
+  GskRoundedRect viewport_clip;
+
   graphene_matrix_init_scale (&modelview, self->scale_factor, self->scale_factor, 1.0f);
 
   gdk_gl_context_make_current (self->gl_context);
 
+  gsk_rounded_rect_init_from_rect (&viewport_clip, &self->viewport, 0.0f);
+
   gsk_gl_renderer_add_render_item (self, projection, &modelview, self->render_items, root,
-                                   self->texture_id);
+                                   self->texture_id, &viewport_clip);
 }
 
 static void
diff --git a/gsk/meson.build b/gsk/meson.build
index 389ef38..cd1e955 100644
--- a/gsk/meson.build
+++ b/gsk/meson.build
@@ -10,6 +10,7 @@ gsk_private_source_shaders = [
   'resources/glsl/linear_gradient.fs.glsl',
   'resources/glsl/linear_gradient.vs.glsl',
   'resources/glsl/rounded_clip.fs.glsl',
+  'resources/glsl/clip.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 f1c9bdf..ad465bc 100644
--- a/gsk/resources/glsl/gl3_common.fs.glsl
+++ b/gsk/resources/glsl/gl3_common.fs.glsl
@@ -4,18 +4,101 @@ uniform sampler2D uSource;
 uniform sampler2D uMask;
 uniform mat4 uMVP;
 uniform mat4 uProjection = mat4(1.0);
+uniform mat4 uModelview = mat4(1.0);
 uniform float uAlpha = 1.0;
 uniform int uBlendMode;
 uniform vec4 uViewport;
 
+// In GtkSnapshot coordinates
+uniform vec4 uClip;
+uniform vec4 uClipCornerWidths  = vec4(1, 1, 1, 1);
+uniform vec4 uClipCornerHeights = vec4(1, 1, 1, 1);
+
 in vec2 vUv;
 
 out vec4 outputColor;
 
+
+struct RoundedRect
+{
+  vec4 bounds;
+  vec4 corner_widths;
+  vec4 corner_heights;
+};
+
+float
+ellipsis_dist (vec2 p, vec2 radius)
+{
+  vec2 p0 = p / radius;
+  vec2 p1 = 2.0 * p0 / radius;
+
+  return (dot(p0, p0) - 1.0) / length (p1);
+}
+
+float
+ellipsis_coverage (vec2 point, vec2 center, vec2 radius)
+{
+  float d = ellipsis_dist (point - center, radius);
+  return clamp (0.5 - d, 0.0, 1.0);
+}
+
+float
+rounded_rect_coverage (RoundedRect r, vec2 p)
+{
+  if (p.x < r.bounds.x || p.y < r.bounds.y ||
+      p.x >= r.bounds.z || p.y >= r.bounds.w)
+    return 0.0;
+
+  vec2 rad_tl = vec2(r.corner_widths.x, r.corner_heights.x);
+  vec2 rad_tr = vec2(r.corner_widths.y, r.corner_heights.y);
+  vec2 rad_br = vec2(r.corner_widths.z, r.corner_heights.z);
+  vec2 rad_bl = vec2(r.corner_widths.w, r.corner_heights.w);
+
+  vec2 ref_tl = r.bounds.xy + vec2( r.corner_widths.x,  r.corner_heights.x);
+  vec2 ref_tr = r.bounds.zy + vec2(-r.corner_widths.y,  r.corner_heights.y);
+  vec2 ref_br = r.bounds.zw + vec2(-r.corner_widths.z, -r.corner_heights.z);
+  vec2 ref_bl = r.bounds.xw + vec2( r.corner_widths.w, -r.corner_heights.w);
+
+  float d_tl = ellipsis_coverage(p, ref_tl, rad_tl);
+  float d_tr = ellipsis_coverage(p, ref_tr, rad_tr);
+  float d_br = ellipsis_coverage(p, ref_br, rad_br);
+  float d_bl = ellipsis_coverage(p, ref_bl, rad_bl);
+
+  vec4 corner_coverages = 1.0 - vec4(d_tl, d_tr, d_br, d_bl);
+
+  bvec4 is_out = bvec4(p.x < ref_tl.x && p.y < ref_tl.y,
+                       p.x > ref_tr.x && p.y < ref_tr.y,
+                       p.x > ref_br.x && p.y > ref_br.y,
+                       p.x < ref_bl.x && p.y > ref_bl.y);
+
+  return 1.0 - dot(vec4(is_out), corner_coverages);
+}
+
+RoundedRect
+rounded_rect_shrink (RoundedRect r, vec4 amount)
+{
+  vec4 new_bounds = r.bounds + vec4(1.0,1.0,-1.0,-1.0) * amount.wxyz;
+  vec4 new_widths = max (r.corner_widths - amount.wyyw, 0.0);
+  vec4 new_heights = max (r.corner_heights - amount.xxzz, 0.0);
+
+  return RoundedRect (new_bounds, new_widths, new_heights);
+}
+
 vec4 Texture(sampler2D sampler, vec2 texCoords) {
   return texture(sampler, texCoords);
 }
 
 void setOutputColor(vec4 color) {
-  outputColor = color;
+  vec4 clipBounds = uClip;
+  vec4 f = gl_FragCoord;
+
+  f.x += uViewport.x;
+  f.y = (uViewport.y + uViewport.w) - f.y;
+
+  clipBounds.z = clipBounds.x + clipBounds.z;
+  clipBounds.w = clipBounds.y + clipBounds.w;
+
+  RoundedRect r = RoundedRect(clipBounds, uClipCornerWidths, uClipCornerHeights);
+
+  outputColor = color * rounded_rect_coverage(r, f.xy);
 }
diff --git a/gsk/resources/glsl/gl3_common.vs.glsl b/gsk/resources/glsl/gl3_common.vs.glsl
index f82f99c..9794cf0 100644
--- a/gsk/resources/glsl/gl3_common.vs.glsl
+++ b/gsk/resources/glsl/gl3_common.vs.glsl
@@ -1,5 +1,6 @@
 uniform mat4 uMVP;
 uniform mat4 uProjection;
+//uniform mat4 uModelview;
 
 in vec2 aPosition;
 in vec2 aUv;
diff --git a/gsk/resources/glsl/linear_gradient.fs.glsl b/gsk/resources/glsl/linear_gradient.fs.glsl
index cbbc71c..d107e8a 100644
--- a/gsk/resources/glsl/linear_gradient.fs.glsl
+++ b/gsk/resources/glsl/linear_gradient.fs.glsl
@@ -12,13 +12,15 @@ vec4 fragCoord() {
 }
 
 void main() {
-  float maxDist = length(uEndPoint - uStartPoint);
+  vec2 startPoint = (vec4(uStartPoint, 0, 1) * uModelview).xy;
+  vec2 endPoint   = (vec4(uEndPoint,   0, 1) * uModelview).xy;
+  float maxDist   = length(endPoint - startPoint);
 
   // Position relative to startPoint
-  vec2 pos = fragCoord().xy - uStartPoint;
+  vec2 pos = fragCoord().xy - startPoint;
 
   // Gradient direction
-  vec2 gradient = uEndPoint - uStartPoint;
+  vec2 gradient = endPoint - startPoint;
   float gradientLength = length(gradient);
 
   // Current pixel, projected onto the line between the start point and the end point
diff --git a/gsk/resources/glsl/rounded_clip.fs.glsl b/gsk/resources/glsl/rounded_clip.fs.glsl
index 5589c12..e69de29 100644
--- a/gsk/resources/glsl/rounded_clip.fs.glsl
+++ b/gsk/resources/glsl/rounded_clip.fs.glsl
@@ -1,91 +0,0 @@
-uniform vec4 uClipBounds;
-uniform vec4 uCornerWidths;
-uniform vec4 uCornerHeights;
-
-struct RoundedRect
-{
-  vec4 bounds;
-  vec4 corner_widths;
-  vec4 corner_heights;
-};
-
-float
-ellipsis_dist (vec2 p, vec2 radius)
-{
-  vec2 p0 = p / radius;
-  vec2 p1 = 2.0 * p0 / radius;
-
-  return (dot(p0, p0) - 1.0) / length (p1);
-}
-
-float
-ellipsis_coverage (vec2 point, vec2 center, vec2 radius)
-{
-  float d = ellipsis_dist (point - center, radius);
-  return clamp (0.5 - d, 0.0, 1.0);
-}
-
-float
-rounded_rect_coverage (RoundedRect r, vec2 p)
-{
-  if (p.x < r.bounds.x || p.y < r.bounds.y ||
-      p.x >= r.bounds.z || p.y >= r.bounds.w)
-    return 0.0;
-
-  vec2 rad_tl = vec2(r.corner_widths.x, r.corner_heights.x);
-  vec2 rad_tr = vec2(r.corner_widths.y, r.corner_heights.y);
-  vec2 rad_br = vec2(r.corner_widths.z, r.corner_heights.z);
-  vec2 rad_bl = vec2(r.corner_widths.w, r.corner_heights.w);
-
-  vec2 ref_tl = r.bounds.xy + vec2( r.corner_widths.x,  r.corner_heights.x);
-  vec2 ref_tr = r.bounds.zy + vec2(-r.corner_widths.y,  r.corner_heights.y);
-  vec2 ref_br = r.bounds.zw + vec2(-r.corner_widths.z, -r.corner_heights.z);
-  vec2 ref_bl = r.bounds.xw + vec2( r.corner_widths.w, -r.corner_heights.w);
-
-  float d_tl = ellipsis_coverage(p, ref_tl, rad_tl);
-  float d_tr = ellipsis_coverage(p, ref_tr, rad_tr);
-  float d_br = ellipsis_coverage(p, ref_br, rad_br);
-  float d_bl = ellipsis_coverage(p, ref_bl, rad_bl);
-
-  vec4 corner_coverages = 1.0 - vec4(d_tl, d_tr, d_br, d_bl);
-
-  bvec4 is_out = bvec4(p.x < ref_tl.x && p.y < ref_tl.y,
-                       p.x > ref_tr.x && p.y < ref_tr.y,
-                       p.x > ref_br.x && p.y > ref_br.y,
-                       p.x < ref_bl.x && p.y > ref_bl.y);
-
-  return 1.0 - dot(vec4(is_out), corner_coverages);
-}
-
-RoundedRect
-rounded_rect_shrink (RoundedRect r, vec4 amount)
-{
-  vec4 new_bounds = r.bounds + vec4(1.0,1.0,-1.0,-1.0) * amount.wxyz;
-  vec4 new_widths = max (r.corner_widths - amount.wyyw, 0.0);
-  vec4 new_heights = max (r.corner_heights - amount.xxzz, 0.0);
-
-  return RoundedRect (new_bounds, new_widths, new_heights);
-}
-
-vec4 fragCoord() {
-  vec4 f = gl_FragCoord;
-  f.x += uViewport.x;
-  f.y = (uViewport.y + uViewport.w) - f.y;
-  return f;
-}
-
-vec4 clip(vec4 color) {
-  vec4 bounds = uClipBounds;
-  bounds.z = bounds.x + bounds.z;
-  bounds.w = bounds.y + bounds.w;
-
-  RoundedRect r = RoundedRect(bounds, uCornerWidths, uCornerHeights);
-
-  return color * rounded_rect_coverage(r, fragCoord().xy);
-}
-
-void main() {
-  vec4 diffuse = Texture(uSource, vUv);
-
-  setOutputColor(clip(diffuse) * uAlpha);
-}


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