summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel van Vugt <daniel.van.vugt@canonical.com>2021-05-10 17:18:55 +0800
committerDaniel van Vugt <daniel.van.vugt@canonical.com>2021-07-26 16:17:46 +0800
commit9e6a3f537bfbaa7e3dcada5728513cf9b993b55a (patch)
tree3b8cccce4bc0b7f9ab22ddad9138cebdda40b0eb
parenta8c18514a2108af891fc5b81fa0adf4a5afc19f3 (diff)
downloadmutter-9e6a3f537bfbaa7e3dcada5728513cf9b993b55a.tar.gz
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>
-rw-r--r--src/compositor/meta-background-content.c129
1 files changed, 38 insertions, 91 deletions
diff --git a/src/compositor/meta-background-content.c b/src/compositor/meta-background-content.c
index 86f777752..eeae41c62 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;
}