mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-12-27 06:00:22 +00:00
ad65db901a
Our coverage computation only works for well-behaved rects and rounded rects. But our modelview transform might flip x or y around, causing things to fail. Add functions to normalize rects and rounded rects, and use it whenever we transform a rounded rect in GLSL.
167 lines
3.9 KiB
GLSL
167 lines
3.9 KiB
GLSL
uniform sampler2D u_source;
|
|
uniform mat4 u_projection;
|
|
uniform mat4 u_modelview;
|
|
uniform float u_alpha;
|
|
uniform vec4 u_viewport;
|
|
uniform vec4[3] u_clip_rect;
|
|
|
|
#if defined(GSK_LEGACY)
|
|
_OUT_ vec4 outputColor;
|
|
#elif !defined(GSK_GLES)
|
|
_OUT_ vec4 outputColor;
|
|
#endif
|
|
|
|
_IN_ vec2 vUv;
|
|
|
|
|
|
GskRoundedRect gsk_decode_rect(_GSK_ROUNDED_RECT_UNIFORM_ r)
|
|
{
|
|
GskRoundedRect rect;
|
|
#if defined(GSK_GLES) || defined(GSK_LEGACY)
|
|
rect = GskRoundedRect(r[0], r[1], r[2]);
|
|
#else
|
|
rect = r;
|
|
#endif
|
|
gsk_rounded_rect_normalize (rect);
|
|
|
|
return rect;
|
|
}
|
|
|
|
float
|
|
gsk_ellipsis_dist (vec2 p, vec2 radius)
|
|
{
|
|
if (radius == vec2(0, 0))
|
|
return 0.0;
|
|
|
|
vec2 p0 = p / radius;
|
|
vec2 p1 = 2.0 * p0 / radius;
|
|
|
|
return (dot(p0, p0) - 1.0) / length (p1);
|
|
}
|
|
|
|
float
|
|
gsk_ellipsis_coverage (vec2 point, vec2 center, vec2 radius)
|
|
{
|
|
float d = gsk_ellipsis_dist (point - center, radius);
|
|
return clamp (0.5 - d, 0.0, 1.0);
|
|
}
|
|
|
|
float
|
|
gsk_rounded_rect_coverage (GskRoundedRect 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 ref_tl = r.corner_points1.xy;
|
|
vec2 ref_tr = r.corner_points1.zw;
|
|
vec2 ref_br = r.corner_points2.xy;
|
|
vec2 ref_bl = r.corner_points2.zw;
|
|
|
|
if (p.x >= ref_tl.x && p.x >= ref_bl.x &&
|
|
p.x <= ref_tr.x && p.x <= ref_br.x)
|
|
return 1.0;
|
|
|
|
if (p.y >= ref_tl.y && p.y >= ref_tr.y &&
|
|
p.y <= ref_bl.y && p.y <= ref_br.y)
|
|
return 1.0;
|
|
|
|
vec2 rad_tl = r.corner_points1.xy - r.bounds.xy;
|
|
vec2 rad_tr = r.corner_points1.zw - r.bounds.zy;
|
|
vec2 rad_br = r.corner_points2.xy - r.bounds.zw;
|
|
vec2 rad_bl = r.corner_points2.zw - r.bounds.xw;
|
|
|
|
float d_tl = gsk_ellipsis_coverage(p, ref_tl, rad_tl);
|
|
float d_tr = gsk_ellipsis_coverage(p, ref_tr, rad_tr);
|
|
float d_br = gsk_ellipsis_coverage(p, ref_br, rad_br);
|
|
float d_bl = gsk_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);
|
|
}
|
|
|
|
float
|
|
gsk_rect_coverage (vec4 r, vec2 p)
|
|
{
|
|
if (p.x < r.x || p.y < r.y ||
|
|
p.x >= r.z || p.y >= r.w)
|
|
return 0.0;
|
|
|
|
return 1.0;
|
|
}
|
|
|
|
vec4 GskTexture(sampler2D sampler, vec2 texCoords) {
|
|
#if defined(GSK_GLES) || defined(GSK_LEGACY)
|
|
return texture2D(sampler, texCoords);
|
|
#else
|
|
return texture(sampler, texCoords);
|
|
#endif
|
|
}
|
|
|
|
#ifdef GSK_GL3
|
|
layout(origin_upper_left) in vec4 gl_FragCoord;
|
|
#endif
|
|
|
|
vec2 gsk_get_frag_coord() {
|
|
vec2 fc = gl_FragCoord.xy;
|
|
|
|
#ifdef GSK_GL3
|
|
fc += u_viewport.xy;
|
|
#else
|
|
fc.x += u_viewport.x;
|
|
fc.y = (u_viewport.y + u_viewport.w) - fc.y;
|
|
#endif
|
|
|
|
return fc;
|
|
}
|
|
|
|
void gskSetOutputColor(vec4 color) {
|
|
vec4 result;
|
|
|
|
#if defined(NO_CLIP)
|
|
result = color;
|
|
#elif defined(RECT_CLIP)
|
|
float coverage = gsk_rect_coverage(gsk_get_bounds(u_clip_rect),
|
|
gsk_get_frag_coord());
|
|
result = color * coverage;
|
|
#else
|
|
float coverage = gsk_rounded_rect_coverage(gsk_create_rect(u_clip_rect),
|
|
gsk_get_frag_coord());
|
|
result = color * coverage;
|
|
#endif
|
|
|
|
#if defined(GSK_GLES) || defined(GSK_LEGACY)
|
|
gl_FragColor = result;
|
|
#else
|
|
outputColor = result;
|
|
#endif
|
|
}
|
|
|
|
void gskSetScaledOutputColor(vec4 color, float alpha) {
|
|
vec4 result;
|
|
|
|
#if defined(NO_CLIP)
|
|
result = color * alpha;
|
|
#elif defined(RECT_CLIP)
|
|
float coverage = gsk_rect_coverage(gsk_get_bounds(u_clip_rect),
|
|
gsk_get_frag_coord());
|
|
result = color * (alpha * coverage);
|
|
#else
|
|
float coverage = gsk_rounded_rect_coverage(gsk_create_rect(u_clip_rect),
|
|
gsk_get_frag_coord());
|
|
result = color * (alpha * coverage);
|
|
#endif
|
|
|
|
#if defined(GSK_GLES) || defined(GSK_LEGACY)
|
|
gl_FragColor = result;
|
|
#else
|
|
outputColor = result;
|
|
#endif
|
|
}
|