mirror of
https://github.com/brl/mutter.git
synced 2024-12-27 05:12:15 +00:00
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>
This commit is contained in:
parent
a8c18514a2
commit
9e6a3f537b
@ -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"\
|
||||
" vec2 delta = p - vec2 (center_x, center_y); \n"\
|
||||
" float dist_squared = dot (delta, delta); \n"\
|
||||
" \n"\
|
||||
" // Fully outside the circle \n"\
|
||||
" if (dist_squared >= (clip_radius * clip_radius)) \n"\
|
||||
" return 0.0; \n"\
|
||||
" \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"\
|
||||
" 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"\
|
||||
" \n"\
|
||||
" vec4 corner_coverages = 1.0 - vec4(d_tl, d_tr, d_br, d_bl); \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"\
|
||||
" \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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user