[mutter] background-content: Shrink and optimize the rounded-clip shader



commit 9e6a3f537bfbaa7e3dcada5728513cf9b993b55a
Author: Daniel van Vugt <daniel van vugt canonical com>
Date:   Mon May 10 17:18:55 2021 +0800

    background-content: Shrink and optimize the rounded-clip shader
    
    The main benefit being it now fits within the hardware limits for the
    i915 Mesa driver, and runs on the GPU instead of software fallback.
    
    Fixes: https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/4251,
           https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/4425
    
    Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1860>

 src/compositor/meta-background-content.c | 129 +++++++++----------------------
 1 file changed, 38 insertions(+), 91 deletions(-)
---
diff --git a/src/compositor/meta-background-content.c b/src/compositor/meta-background-content.c
index 86f7777528..eeae41c62b 100644
--- a/src/compositor/meta-background-content.c
+++ b/src/compositor/meta-background-content.c
@@ -135,77 +135,50 @@ typedef enum
 "cogl_color_out.rgb = cogl_color_out.rgb * pixel_brightness;\n"                \
 "cogl_color_out.rgb += (rand(position) - 0.5) / 255.0;\n"                      \
 
-/* The ellipsis_dist(), ellipsis_coverage() and rounded_rect_coverage() are
- * copied from GSK, see gsk_ellipsis_dist(), gsk_ellipsis_coverage(), and
- * gsk_rounded_rect_coverage() here:
- * https://gitlab.gnome.org/GNOME/gtk/-/blob/4.3.1/gsk/gl/resources/preamble.fs.glsl
- */
 #define ROUNDED_CLIP_FRAGMENT_SHADER_DECLARATIONS                            \
-"uniform vec4 bounds;           // x, y: top left; w, v: bottom right     \n"\
-"uniform vec4 corner_centers_1; // x, y: top left; w, v: top right        \n"\
-"uniform vec4 corner_centers_2; // x, y: bottom right; w, v: bottom left  \n"\
+"uniform vec4 bounds;           // x, y: top left; z, w: bottom right     \n"\
+"uniform float clip_radius;                                               \n"\
 "uniform vec2 pixel_step;                                                 \n"\
 "                                                                         \n"\
 "float                                                                    \n"\
-"ellipsis_dist (vec2 p, vec2 radius)                                      \n"\
+"rounded_rect_coverage (vec2 p)                                           \n"\
 "{                                                                        \n"\
-"  if (radius == vec2(0, 0))                                              \n"\
-"    return 0.0;                                                          \n"\
+"  float center_left  = bounds.x + clip_radius;                           \n"\
+"  float center_right = bounds.z - clip_radius;                           \n"\
+"  float center_x;                                                        \n"\
 "                                                                         \n"\
-"  vec2 p0 = p / radius;                                                  \n"\
-"  vec2 p1 = (2.0 * p0) / radius;                                         \n"\
+"  if (p.x < center_left)                                                 \n"\
+"    center_x = center_left;                                              \n"\
+"  else if (p.x > center_right)                                           \n"\
+"    center_x = center_right;                                             \n"\
+"  else                                                                   \n"\
+"    return 1.0; // The vast majority of pixels exit early here           \n"\
 "                                                                         \n"\
-"  return (dot(p0, p0) - 1.0) / length (p1);                              \n"\
-"}                                                                        \n"\
+"  float center_top    = bounds.y + clip_radius;                          \n"\
+"  float center_bottom = bounds.w - clip_radius;                          \n"\
+"  float center_y;                                                        \n"\
 "                                                                         \n"\
-"float                                                                    \n"\
-"ellipsis_coverage (vec2 point, vec2 center, vec2 radius)                 \n"\
-"{                                                                        \n"\
-"  float d = ellipsis_dist ((point - center), radius);                    \n"\
-"  return clamp (0.5 - d, 0.0, 1.0);                                      \n"\
-"}                                                                        \n"\
-"                                                                         \n"\
-"float                                                                    \n"\
-"rounded_rect_coverage (vec4 bounds,                                      \n"\
-"                       vec4 corner_centers_1,                            \n"\
-"                       vec4 corner_centers_2,                            \n"\
-"                       vec2 p)                                           \n"\
-"{                                                                        \n"\
-"  if (p.x < bounds.x || p.y < bounds.y ||                                \n"\
-"      p.x >= bounds.z || p.y >= bounds.w)                                \n"\
-"    return 0.0;                                                          \n"\
-"                                                                         \n"\
-"  vec2 ref_tl = corner_centers_1.xy;                                     \n"\
-"  vec2 ref_tr = corner_centers_1.zw;                                     \n"\
-"  vec2 ref_br = corner_centers_2.xy;                                     \n"\
-"  vec2 ref_bl = corner_centers_2.zw;                                     \n"\
-"                                                                         \n"\
-"  if (p.x >= ref_tl.x && p.x >= ref_bl.x &&                              \n"\
-"      p.x <= ref_tr.x && p.x <= ref_br.x)                                \n"\
+"  if (p.y < center_top)                                                  \n"\
+"    center_y = center_top;                                               \n"\
+"  else if (p.y > center_bottom)                                          \n"\
+"    center_y = center_bottom;                                            \n"\
+"  else                                                                   \n"\
 "    return 1.0;                                                          \n"\
 "                                                                         \n"\
-"  if (p.y >= ref_tl.y && p.y >= ref_tr.y &&                              \n"\
-"      p.y <= ref_bl.y && p.y <= ref_br.y)                                \n"\
-"    return 1.0;                                                          \n"\
-"                                                                         \n"\
-"  vec2 rad_tl = corner_centers_1.xy - bounds.xy;                         \n"\
-"  vec2 rad_tr = corner_centers_1.zw - bounds.zy;                         \n"\
-"  vec2 rad_br = corner_centers_2.xy - bounds.zw;                         \n"\
-"  vec2 rad_bl = corner_centers_2.zw - bounds.xw;                         \n"\
-"                                                                         \n"\
-"  float d_tl = ellipsis_coverage(p, ref_tl, rad_tl);                     \n"\
-"  float d_tr = ellipsis_coverage(p, ref_tr, rad_tr);                     \n"\
-"  float d_br = ellipsis_coverage(p, ref_br, rad_br);                     \n"\
-"  float d_bl = ellipsis_coverage(p, ref_bl, rad_bl);                     \n"\
+"  vec2 delta = p - vec2 (center_x, center_y);                            \n"\
+"  float dist_squared = dot (delta, delta);                               \n"\
 "                                                                         \n"\
-"  vec4 corner_coverages = 1.0 - vec4(d_tl, d_tr, d_br, d_bl);            \n"\
+"  // Fully outside the circle                                            \n"\
+"  if (dist_squared >= (clip_radius * clip_radius))                       \n"\
+"    return 0.0;                                                          \n"\
 "                                                                         \n"\
-"  bvec4 is_out = bvec4(p.x < ref_tl.x && p.y < ref_tl.y,                 \n"\
-"                       p.x > ref_tr.x && p.y < ref_tr.y,                 \n"\
-"                       p.x > ref_br.x && p.y > ref_br.y,                 \n"\
-"                       p.x < ref_bl.x && p.y > ref_bl.y);                \n"\
+"  // Fully inside the circle                                             \n"\
+"  float inner_radius = clip_radius - 1.0;                                \n"\
+"  if (dist_squared <= (inner_radius * inner_radius))                     \n"\
+"    return 1.0;                                                          \n"\
 "                                                                         \n"\
-"  return 1.0 - dot(vec4(is_out), corner_coverages);                      \n"\
+"  // Only pixels on the edge of the curve need expensive antialiasing    \n"\
+"  return clip_radius - sqrt (dist_squared);                              \n"\
 "}                                                                        \n"
 
 #define ROUNDED_CLIP_FRAGMENT_SHADER_CODE                                    \
@@ -213,10 +186,7 @@ typedef enum
 "                                                                         \n"\
 "texture_coord = cogl_tex_coord0_in.xy / pixel_step;                      \n"\
 "                                                                         \n"\
-"cogl_color_out *= rounded_rect_coverage (bounds,                         \n"\
-"                                         corner_centers_1,               \n"\
-"                                         corner_centers_2,               \n"\
-"                                         texture_coord);                 \n"
+"cogl_color_out *= rounded_rect_coverage (texture_coord);                 \n"
 
 typedef struct _MetaBackgroundLayer MetaBackgroundLayer;
 
@@ -540,45 +510,22 @@ setup_pipeline (MetaBackgroundContent *self,
         bounds_y2,
       };
 
-      float corner_centers_1[] = {
-        bounds_x1 + clip_radius,
-        bounds_y1 + clip_radius,
-        bounds_x2 - clip_radius,
-        bounds_y1 + clip_radius,
-      };
-
-      float corner_centers_2[] = {
-        bounds_x2 - clip_radius,
-        bounds_y2 - clip_radius,
-        bounds_x1 + clip_radius,
-        bounds_y2 - clip_radius,
-      };
-
       int bounds_uniform_location;
-      int corner_centers_1_uniform_location;
-      int corner_centers_2_uniform_location;
+      int clip_radius_uniform_location;
 
       bounds_uniform_location =
         cogl_pipeline_get_uniform_location (self->pipeline, "bounds");
-      corner_centers_1_uniform_location =
-        cogl_pipeline_get_uniform_location (self->pipeline, "corner_centers_1");
-      corner_centers_2_uniform_location =
-        cogl_pipeline_get_uniform_location (self->pipeline, "corner_centers_2");
+      clip_radius_uniform_location =
+        cogl_pipeline_get_uniform_location (self->pipeline, "clip_radius");
 
       cogl_pipeline_set_uniform_float (self->pipeline,
                                        bounds_uniform_location,
                                        4, 1,
                                        bounds);
 
-      cogl_pipeline_set_uniform_float (self->pipeline,
-                                       corner_centers_1_uniform_location,
-                                       4, 1,
-                                       corner_centers_1);
-
-      cogl_pipeline_set_uniform_float (self->pipeline,
-                                       corner_centers_2_uniform_location,
-                                       4, 1,
-                                       corner_centers_2);
+      cogl_pipeline_set_uniform_1f (self->pipeline,
+                                    clip_radius_uniform_location,
+                                    clip_radius);
 
       self->changed &= ~CHANGED_ROUNDED_CLIP_PARAMETERS;
     }


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