gl renderer: Fix clipped borders
authorTimm Bäder <mail@baedert.org>
Thu, 15 Mar 2018 16:27:19 +0000 (17:27 +0100)
committerTimm Bäder <mail@baedert.org>
Thu, 15 Mar 2018 17:11:57 +0000 (18:11 +0100)
Stop abusing the clip rect for borders.

gsk/gl/gskglrenderer.c
gsk/gl/gskglrenderops.c
gsk/gl/gskglrenderopsprivate.h
gsk/resources/glsl/border.fs.glsl

index 7afc34879c8a38e6d81a63505d0ce73064390b21..b82c2e53c3a1d6cd0527ddc143abc3f9d91a1992 100644 (file)
@@ -242,28 +242,6 @@ struct _GskGLRendererClass
 
 G_DEFINE_TYPE (GskGLRenderer, gsk_gl_renderer, GSK_TYPE_RENDERER)
 
-static inline void
-rounded_rect_intersect (GskGLRenderer        *self,
-                        RenderOpBuilder      *builder,
-                        const GskRoundedRect *rect,
-                        GskRoundedRect       *dest)
-{
-  graphene_rect_t transformed_rect;
-  graphene_rect_t intersection;
-  int i;
-
-  graphene_matrix_transform_bounds (&builder->current_modelview, &rect->bounds, &transformed_rect);
-  graphene_rect_intersection (&transformed_rect, &builder->current_clip.bounds,
-                              &intersection);
-
-  dest->bounds = intersection;
-  for (i = 0; i < 4; i ++)
-    {
-      dest->corner[i].width = rect->corner[i].width * self->scale_factor;
-      dest->corner[i].height = rect->corner[i].height * self->scale_factor;
-    }
-}
-
 static inline void
 rounded_rect_to_floats (GskGLRenderer        *self,
                         RenderOpBuilder      *builder,
@@ -429,10 +407,9 @@ render_border_node (GskGLRenderer   *self,
   const GdkRGBA *colors = gsk_border_node_peek_colors (node);
   const GskRoundedRect *rounded_outline = gsk_border_node_peek_outline (node);
   const float *og_widths = gsk_border_node_peek_widths (node);
+  GskRoundedRect outline;
   float widths[4];
-  const gboolean needs_clip = TRUE;/*!gsk_rounded_rect_is_rectilinear (rounded_outline);*/
   int i;
-  GskRoundedRect prev_clip;
   struct {
     float w;
     float h;
@@ -490,22 +467,6 @@ render_border_node (GskGLRenderer   *self,
   for (i = 0; i < 4; i ++)
     widths[i] *= self->scale_factor;
 
-  if (needs_clip)
-    {
-      GskRoundedRect child_clip;
-
-      ops_set_program (builder, &self->border_program);
-
-      rounded_rect_intersect (self, builder, rounded_outline, &child_clip);
-      prev_clip = ops_set_clip (builder, &child_clip);
-
-      ops_set_border (builder, widths);
-    }
-  else
-    {
-      ops_set_program (builder, &self->color_program);
-    }
-
   {
     const GskQuadVertex side_data[4][6] = {
       /* Top */
@@ -555,6 +516,19 @@ render_border_node (GskGLRenderer   *self,
     /* We sort them by color */
     sort_border_sides (colors, indices);
 
+    /* Prepare outline */
+    outline = *rounded_outline;
+    graphene_matrix_transform_bounds (&builder->current_modelview,
+                                      &outline.bounds, &outline.bounds);
+    for (i = 0; i < 4; i ++)
+      {
+        outline.corner[i].width *= self->scale_factor;
+        outline.corner[i].height *= self->scale_factor;
+      }
+
+    ops_set_program (builder, &self->border_program);
+    ops_set_border (builder, widths, &outline);
+
     for (i = 0; i < 4; i ++)
       {
         if (widths[indices[i]] > 0)
@@ -564,9 +538,6 @@ render_border_node (GskGLRenderer   *self,
           }
       }
   }
-
-  if (needs_clip)
-    ops_set_clip (builder, &prev_clip);
 }
 
 static inline void
@@ -1696,9 +1667,29 @@ static inline void
 apply_border_op (const Program  *program,
                  const RenderOp *op)
 {
+  const GskRoundedRect *o = &op->border.outline;
+  float outline[4];
+  float widths[4];
+  float heights[4];
+  int i;
   OP_PRINT (" -> Border (%f, %f, %f, %f)",
             op->border.widths[0], op->border.widths[1], op->border.widths[2], op->border.widths[3]);
+
+  outline[0] = o->bounds.origin.x;
+  outline[1] = o->bounds.origin.y;
+  outline[2] = o->bounds.size.width;
+  outline[3] = o->bounds.size.height;
+
+  for (i = 0; i < 4; i ++)
+    {
+      widths[i] = o->corner[i].width;
+      heights[i] = o->corner[i].height;
+    }
+
   glUniform4fv (program->border.widths_location, 1, op->border.widths);
+  glUniform4fv (program->border.outline_location, 1, outline);
+  glUniform4fv (program->border.corner_widths_location, 1, widths);
+  glUniform4fv (program->border.corner_heights_location, 1, heights);
 }
 
 static inline void
@@ -1889,6 +1880,9 @@ gsk_gl_renderer_create_programs (GskGLRenderer  *self,
   /* border */
   INIT_PROGRAM_UNIFORM_LOCATION (border, color);
   INIT_PROGRAM_UNIFORM_LOCATION (border, widths);
+  INIT_PROGRAM_UNIFORM_LOCATION (border, outline);
+  INIT_PROGRAM_UNIFORM_LOCATION (border, corner_widths);
+  INIT_PROGRAM_UNIFORM_LOCATION (border, corner_heights);
 
   /* cross fade */
   INIT_PROGRAM_UNIFORM_LOCATION (cross_fade, progress);
index 0520ff769b753fea411093cb530021657e11a48d..b36c06d8d0cd229ebec3894257d8102acb2e406f 100644 (file)
@@ -309,13 +309,18 @@ ops_set_color_matrix (RenderOpBuilder         *builder,
 }
 
 void
-ops_set_border (RenderOpBuilder *builder,
-                const float     *widths)
+ops_set_border (RenderOpBuilder      *builder,
+                const float          *widths,
+                const GskRoundedRect *outline)
 {
   RenderOp op;
 
+  /* TODO: Assert that current_program == border program? */
+
   if (memcmp (&builder->program_state[builder->current_program->index].border.widths,
-              widths, sizeof (float) * 4) == 0)
+              widths, sizeof (float) * 4) == 0 &&
+      memcmp (&builder->program_state[builder->current_program->index].border.outline,
+              outline, sizeof (GskRoundedRect)) == 0)
     return;
 
   memcpy (&builder->program_state[builder->current_program->index].border.widths,
@@ -326,6 +331,7 @@ ops_set_border (RenderOpBuilder *builder,
   op.border.widths[1] = widths[1];
   op.border.widths[2] = widths[2];
   op.border.widths[3] = widths[3];
+  op.border.outline = *outline;
   g_array_append_val (builder->render_ops, op);
 }
 
index b700b75f948739788478fe5675f2aaa0765c889f..7d6fe8a82177ffa7c399f8fe004e7fc6bbb1a1dd 100644 (file)
@@ -106,6 +106,9 @@ typedef struct
     struct {
       int color_location;
       int widths_location;
+      int outline_location;
+      int corner_widths_location;
+      int corner_heights_location;
     } border;
     struct {
       int source2_location;
@@ -183,6 +186,7 @@ typedef struct
     struct {
       float widths[4];
       float color[4];
+      GskRoundedRect outline;
     } border;
     struct {
       float progress;
@@ -211,6 +215,7 @@ typedef struct
       struct {
         float widths[4];
         float color[4];
+        GskRoundedRect outline;
       } border;
     };
   } program_state[GL_N_PROGRAMS];
@@ -265,7 +270,8 @@ void              ops_set_color_matrix   (RenderOpBuilder         *builder,
                                           const graphene_vec4_t   *offset);
 
 void              ops_set_border         (RenderOpBuilder         *builder,
-                                          const float             *widths);
+                                          const float             *widths,
+                                          const GskRoundedRect    *outline);
 
 void              ops_set_border_color   (RenderOpBuilder         *builder,
                                           const GdkRGBA           *color);
index 59b1b816e5150d3a81cba8664255fd0c1663d837..970c5739eac1886940fd6a180f9e33e764a263b2 100644 (file)
@@ -1,20 +1,21 @@
-uniform vec4 u_color;// = vec4(1, 0, 1, 1);
+uniform vec4 u_color;
 uniform vec4 u_widths;
 
-// For border we abuse, ehm, re-use, the global clip
-// as rounded rect and shrink it by u_widths
+uniform vec4 u_outline;
+uniform vec4 u_corner_widths;
+uniform vec4 u_corner_heights;
+
 void main() {
-  vec4 bounds = u_clip;
-  vec4 f = gl_FragCoord;
+  vec4 bounds = u_outline;
 
+  bounds.z = bounds.x + bounds.z;
+  bounds.w = bounds.y + bounds.w;
 
+  vec4 f = gl_FragCoord;
   f.x += u_viewport.x;
   f.y = (u_viewport.y + u_viewport.w) - f.y;
 
-  bounds.z = bounds.x + bounds.z;
-  bounds.w = bounds.y + bounds.w;
-
-  RoundedRect routside = RoundedRect (bounds, u_clip_corner_widths, u_clip_corner_heights);
+  RoundedRect routside = RoundedRect (bounds, u_corner_widths, u_corner_heights);
   RoundedRect rinside = rounded_rect_shrink (routside, u_widths);
 
   float alpha = clamp (rounded_rect_coverage (routside, f.xy) -