Test AA changes. try: -b do -p linux64 -u all[linux64-qr] -t none
Test AA changes. try: -b do -p linux64 -u all[linux64-qr] -t none
--- a/gfx/webrender/res/cs_clip_border.glsl
+++ b/gfx/webrender/res/cs_clip_border.glsl
@@ -150,29 +150,28 @@ void main(void) {
float d0 = distance_to_line(vPoint_Tangent0.xy,
vPoint_Tangent0.zw,
clip_relative_pos);
float d1 = distance_to_line(vPoint_Tangent1.xy,
vPoint_Tangent1.zw,
clip_relative_pos);
// Get AA widths based on zoom / scale etc.
- vec2 fw = fwidth(local_pos);
- float afwidth = length(fw);
+ float aa_range = compute_aa_range(local_pos);
// SDF subtract edges for dash clip
float dash_distance = max(d0, -d1);
// Get distance from dot.
float dot_distance = distance(clip_relative_pos, vDotParams.xy) - vDotParams.z;
// Select between dot/dash clip based on mode.
float d = mix(dash_distance, dot_distance, vAlphaMask.x);
- // Apply AA over half a device pixel for the clip.
- d = 1.0 - smoothstep(0.0, 0.5 * afwidth, d);
+ // Apply AA.
+ d = distance_aa(aa_range, d);
// Completely mask out clip if zero'ing out the rect.
d = d * vAlphaMask.y;
oFragColor = vec4(d, 0.0, 0.0, 1.0);
}
#endif
--- a/gfx/webrender/res/cs_clip_rectangle.glsl
+++ b/gfx/webrender/res/cs_clip_rectangle.glsl
@@ -96,61 +96,58 @@ void main(void) {
clip.bottom_left.outer_inner_radius.xy);
}
#endif
#ifdef WR_FRAGMENT_SHADER
float clip_against_ellipse_if_needed(vec2 pos,
float current_distance,
vec4 ellipse_center_radius,
- vec2 sign_modifier,
- float afwidth) {
+ vec2 sign_modifier) {
float ellipse_distance = distance_to_ellipse(pos - ellipse_center_radius.xy,
ellipse_center_radius.zw);
-
return mix(current_distance,
- ellipse_distance + afwidth,
+ ellipse_distance,
all(lessThan(sign_modifier * pos, sign_modifier * ellipse_center_radius.xy)));
}
float rounded_rect(vec2 pos) {
- float current_distance = 0.0;
-
- // Apply AA
- float afwidth = 0.5 * length(fwidth(pos));
+ // Start with a negative value (means "inside") for all fragments that are not
+ // in a corner. If the fragment is in a corner, one of the clip_against_ellipse_if_needed
+ // calls below will update it.
+ float current_distance = -1.0;
// Clip against each ellipse.
current_distance = clip_against_ellipse_if_needed(pos,
current_distance,
vClipCenter_Radius_TL,
- vec2(1.0),
- afwidth);
+ vec2(1.0));
current_distance = clip_against_ellipse_if_needed(pos,
current_distance,
vClipCenter_Radius_TR,
- vec2(-1.0, 1.0),
- afwidth);
+ vec2(-1.0, 1.0));
current_distance = clip_against_ellipse_if_needed(pos,
current_distance,
vClipCenter_Radius_BR,
- vec2(-1.0),
- afwidth);
+ vec2(-1.0));
current_distance = clip_against_ellipse_if_needed(pos,
current_distance,
vClipCenter_Radius_BL,
- vec2(1.0, -1.0),
- afwidth);
+ vec2(1.0, -1.0));
- return smoothstep(0.0, afwidth, 1.0 - current_distance);
+ // Apply AA
+ // See comment in ps_border_corner about the choice of constants.
+ float aa_range = compute_aa_range(pos);
+
+ return distance_aa(aa_range, current_distance);
}
-
void main(void) {
float alpha = 1.f;
vec2 local_pos = init_transform_fs(vPos, alpha);
float clip_alpha = rounded_rect(local_pos);
float combined_alpha = min(alpha, clip_alpha);
--- a/gfx/webrender/res/prim_shared.glsl
+++ b/gfx/webrender/res/prim_shared.glsl
@@ -714,34 +714,60 @@ void write_clip(vec2 global_pos, ClipAre
vec2 uv = global_pos + area.task_bounds.xy - area.screen_origin_target_index.xy;
vClipMaskUvBounds = area.task_bounds / texture_size.xyxy;
vClipMaskUv = vec3(uv / texture_size, area.screen_origin_target_index.z);
}
#endif //WR_VERTEX_SHADER
#ifdef WR_FRAGMENT_SHADER
+/// Find the appropriate half range to apply the AA smoothstep over.
+/// This range represents a coefficient to go from one CSS pixel to half a device pixel.
+float compute_aa_range(vec2 position) {
+ // We use 0.4 instead of 0.5 here to compensate for the fact that length(fw) is equal
+ // to sqrt(2) times the device pixel ratio in the typical case.
+ // This coefficient is chosen to ensure that a sample that any sample 0.5 pixels
+ // or more inside of the shape has no anti-aliasing applied to it (since pixels are
+ // sampled at their center, such a pixel (axis aligned) is fully inside the border),
+ // so that antialiased curves properly connect with non-antialiased vertical or horizontal
+ // lines.
+ //
+ // Using larger aa steps is quite common when rendering shapes with distance fields.
+ // It gives a smoother (although blurrier look) by extending the range that is smoothed
+ // to produce the anti aliasing. In our case, however, extending the range inside of
+ // the shape causes noticeable artifacts at the junction between an antialiased corner
+ // and a straight edge.
+ return 0.35355 * length(fwidth(position));
+}
+
+/// Return the blending coefficient to for distance antialiasing.
+///
+/// 0.0 means inside the shape, 1.0 means outside.
+float distance_aa(float aa_range, float signed_distance) {
+ return 1.0 - smoothstep(-aa_range, aa_range, signed_distance);
+}
+
#ifdef WR_FEATURE_TRANSFORM
float signed_distance_rect(vec2 pos, vec2 p0, vec2 p1) {
vec2 d = max(p0 - pos, pos - p1);
return length(max(vec2(0.0), d)) + min(0.0, max(d.x, d.y));
}
vec2 init_transform_fs(vec3 local_pos, out float fragment_alpha) {
fragment_alpha = 1.0;
vec2 pos = local_pos.xy / local_pos.z;
// Now get the actual signed distance.
float d = signed_distance_rect(pos, vLocalBounds.xy, vLocalBounds.zw);
// Find the appropriate distance to apply the AA smoothstep over.
- float afwidth = 0.5 * length(fwidth(pos.xy));
+ float aa_range = compute_aa_range(pos.xy);
// Only apply AA to fragments outside the signed distance field.
- fragment_alpha = 1.0 - smoothstep(0.0, afwidth, d);
+ fragment_alpha = distance_aa(aa_range, d);
return pos;
}
#endif //WR_FEATURE_TRANSFORM
float do_clip() {
// anything outside of the mask is considered transparent
bvec4 inside = lessThanEqual(
--- a/gfx/webrender/res/ps_border_corner.glsl
+++ b/gfx/webrender/res/ps_border_corner.glsl
@@ -319,21 +319,17 @@ void main(void) {
alpha = 0.0;
vec2 local_pos = init_transform_fs(vLocalPos, alpha);
#else
vec2 local_pos = vLocalPos;
#endif
alpha = min(alpha, do_clip());
- // Find the appropriate distance to apply the AA smoothstep over.
- // Using 0.7 instead of 0.5 for the step compensates for the fact that smoothstep
- // is smooth at its endpoints and has a steeper maximum slope than a linear ramp.
- vec2 fw = fwidth(local_pos);
- float aa_step = 0.7 * length(fw);
+ float aa_range = compute_aa_range(local_pos);
float distance_for_color;
float color_mix_factor;
// Only apply the clip AA if inside the clip region. This is
// necessary for correctness when the border width is greater
// than the border radius.
if (all(lessThan(local_pos * vClipSign, vClipCenter * vClipSign))) {
@@ -344,39 +340,36 @@ void main(void) {
// error of half a pixel towards the exterior of the curve (See issue #1750).
// This error is corrected by offsetting the distance by half a device pixel.
// This not entirely correct: it leaves an error that varries between
// 0 and (sqrt(2) - 1)/2 = 0.2 pixels but it is hardly noticeable and is better
// than the constant sqrt(2)/2 px error without the correction.
// To correct this exactly we would need to offset p by half a pixel in the
// direction of the center of the ellipse (a different offset for each corner).
- // A half device pixel in css pixels (using the average of width and height in case
- // there is any kind of transform applied).
- float half_px = 0.25 * (fw.x + fw.y);
// Get signed distance from the inner/outer clips.
- float d0 = distance_to_ellipse(p, vRadii0.xy) + half_px;
- float d1 = distance_to_ellipse(p, vRadii0.zw) + half_px;
- float d2 = distance_to_ellipse(p, vRadii1.xy) + half_px;
- float d3 = distance_to_ellipse(p, vRadii1.zw) + half_px;
+ float d0 = distance_to_ellipse(p, vRadii0.xy);
+ float d1 = distance_to_ellipse(p, vRadii0.zw);
+ float d2 = distance_to_ellipse(p, vRadii1.xy);
+ float d3 = distance_to_ellipse(p, vRadii1.zw);
// SDF subtract main radii
- float d_main = max(d0, aa_step - d1);
+ float d_main = max(d0, -d1);
// SDF subtract inner radii (double style borders)
- float d_inner = max(d2 - aa_step, -d3);
+ float d_inner = max(d2, -d3);
// Select how to combine the SDF based on border style.
float d = mix(max(d_main, -d_inner), d_main, vSDFSelect);
// Only apply AA to fragments outside the signed distance field.
- alpha = min(alpha, 1.0 - smoothstep(0.0, aa_step, d));
+ alpha = min(alpha, distance_aa(aa_range, d));
// Get the groove/ridge mix factor.
- color_mix_factor = smoothstep(-aa_step, aa_step, -d2);
+ color_mix_factor = distance_aa(aa_range, d2);
} else {
// Handle the case where the fragment is outside the clip
// region in a corner. This occurs when border width is
// greater than border radius.
// Get linear distances along horizontal and vertical edges.
vec2 d0 = vClipSign.xx * (local_pos.xx - vEdgeDistance.xz);
vec2 d1 = vClipSign.yy * (local_pos.yy - vEdgeDistance.yw);
@@ -398,14 +391,14 @@ void main(void) {
// Mix inner/outer color.
vec4 color0 = mix(vColor00, vColor01, color_mix_factor);
vec4 color1 = mix(vColor10, vColor11, color_mix_factor);
// Select color based on side of line. Get distance from the
// reference line, and then apply AA along the edge.
float ld = distance_to_line(vColorEdgeLine.xy, vColorEdgeLine.zw, local_pos);
- float m = smoothstep(-aa_step, aa_step, ld);
+ float m = distance_aa(aa_range, -ld);
vec4 color = mix(color0, color1, m);
oFragColor = color * vec4(1.0, 1.0, 1.0, alpha);
}
#endif
--- a/gfx/webrender/res/ps_border_edge.glsl
+++ b/gfx/webrender/res/ps_border_edge.glsl
@@ -248,18 +248,17 @@ void main(void) {
vec2 local_pos = init_transform_fs(vLocalPos, alpha);
#else
vec2 local_pos = vLocalPos;
#endif
alpha = min(alpha, do_clip());
// Find the appropriate distance to apply the step over.
- vec2 fw = fwidth(local_pos);
- float afwidth = length(fw);
+ float aa_range = compute_aa_range(local_pos);
// Applies the math necessary to draw a style: double
// border. In the case of a solid border, the vertex
// shader sets interpolator values that make this have
// no effect.
// Select the x/y coord, depending on which axis this edge is.
vec2 pos = mix(local_pos.xy, local_pos.yx, vAxisSelect);
@@ -286,18 +285,16 @@ void main(void) {
float x = mod(pos.y - vClipParams.x, vClipParams.y);
// Calculate dash alpha (on/off) based on dash length
float dash_alpha = step(x, vClipParams.z);
// Get the dot alpha
vec2 dot_relative_pos = vec2(x, pos.x) - vClipParams.zw;
float dot_distance = length(dot_relative_pos) - vClipParams.z;
- float dot_alpha = 1.0 - smoothstep(-0.5 * afwidth,
- 0.5 * afwidth,
- dot_distance);
+ float dot_alpha = distance_aa(aa_range, dot_distance);
// Select between dot/dash alpha based on clip mode.
alpha = min(alpha, mix(dash_alpha, dot_alpha, vClipSelect));
oFragColor = color * vec4(1.0, 1.0, 1.0, alpha);
}
#endif
new file mode 100644
--- /dev/null
+++ b/gfx/webrender/res/ps_hardware_composite.fs.glsl
@@ -0,0 +1,8 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+void main(void) {
+ vec2 uv = clamp(vUv.xy, vUvBounds.xy, vUvBounds.zw);
+ oFragColor = texture(sCacheRGBA8, vec3(uv, vUv.z));
+}
--- a/gfx/webrender/res/ps_hardware_composite.glsl
+++ b/gfx/webrender/res/ps_hardware_composite.glsl
@@ -1,39 +1,8 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include shared,prim_shared
varying vec3 vUv;
flat varying vec4 vUvBounds;
-
-#ifdef WR_VERTEX_SHADER
-void main(void) {
- CompositeInstance ci = fetch_composite_instance();
- AlphaBatchTask dest_task = fetch_alpha_batch_task(ci.render_task_index);
- AlphaBatchTask src_task = fetch_alpha_batch_task(ci.src_task_index);
-
- vec2 dest_origin = dest_task.render_target_origin -
- dest_task.screen_space_origin +
- vec2(ci.user_data0, ci.user_data1);
-
- vec2 local_pos = mix(dest_origin,
- dest_origin + src_task.size,
- aPosition.xy);
-
- vec2 texture_size = vec2(textureSize(sCacheRGBA8, 0));
- vec2 st0 = src_task.render_target_origin;
- vec2 st1 = src_task.render_target_origin + src_task.size;
- vUv = vec3(mix(st0, st1, aPosition.xy) / texture_size, src_task.render_target_layer_index);
- vUvBounds = vec4(st0 + 0.5, st1 - 0.5) / texture_size.xyxy;
-
- gl_Position = uTransform * vec4(local_pos, ci.z, 1.0);
-}
-#endif
-
-#ifdef WR_FRAGMENT_SHADER
-void main(void) {
- vec2 uv = clamp(vUv.xy, vUvBounds.xy, vUvBounds.zw);
- oFragColor = texture(sCacheRGBA8, vec3(uv, vUv.z));
-}
-#endif
new file mode 100644
--- /dev/null
+++ b/gfx/webrender/res/ps_hardware_composite.vs.glsl
@@ -0,0 +1,25 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+void main(void) {
+ CompositeInstance ci = fetch_composite_instance();
+ AlphaBatchTask dest_task = fetch_alpha_batch_task(ci.render_task_index);
+ AlphaBatchTask src_task = fetch_alpha_batch_task(ci.src_task_index);
+
+ vec2 dest_origin = dest_task.render_target_origin -
+ dest_task.screen_space_origin +
+ vec2(ci.user_data0, ci.user_data1);
+
+ vec2 local_pos = mix(dest_origin,
+ dest_origin + src_task.size,
+ aPosition.xy);
+
+ vec2 texture_size = vec2(textureSize(sCacheRGBA8, 0));
+ vec2 st0 = src_task.render_target_origin;
+ vec2 st1 = src_task.render_target_origin + src_task.size;
+ vUv = vec3(mix(st0, st1, aPosition.xy) / texture_size, src_task.render_target_layer_index);
+ vUvBounds = vec4(st0 + 0.5, st1 - 0.5) / texture_size.xyxy;
+
+ gl_Position = uTransform * vec4(local_pos, ci.z, 1.0);
+}
--- a/gfx/webrender/res/ps_line.glsl
+++ b/gfx/webrender/res/ps_line.glsl
@@ -185,18 +185,17 @@ void main(void) {
#else
vec2 local_pos = vLocalPos;
#endif
alpha = min(alpha, do_clip());
#endif
// Find the appropriate distance to apply the step over.
- vec2 fw = fwidth(local_pos);
- float afwidth = length(fw);
+ float aa_range = compute_aa_range(local_pos);
// Select the x/y coord, depending on which axis this edge is.
vec2 pos = mix(local_pos.xy, local_pos.yx, vAxisSelect);
switch (vStyle) {
case LINE_STYLE_SOLID: {
break;
}
@@ -210,19 +209,17 @@ void main(void) {
}
case LINE_STYLE_DOTTED: {
// Get the main-axis position relative to closest dot or dash.
float x = mod(pos.x - vLocalOrigin.x, vParams.x);
// Get the dot alpha
vec2 dot_relative_pos = vec2(x, pos.y) - vParams.yz;
float dot_distance = length(dot_relative_pos) - vParams.y;
- alpha = min(alpha, 1.0 - smoothstep(-0.5 * afwidth,
- 0.5 * afwidth,
- dot_distance));
+ alpha = min(alpha, distance_aa(aa_range, dot_distance));
break;
}
case LINE_STYLE_WAVY: {
vec2 normalized_local_pos = pos - vLocalOrigin.xy;
float y0 = vParams.y;
float dy = vParams.z;
float dx = vParams.w;
@@ -246,18 +243,16 @@ void main(void) {
vec2 b2_1 = vec2(4.0 * dx, y0);
float d2 = approx_distance(normalized_local_pos, b0_1, b1_1, b2_1);
// SDF union - this is needed to avoid artifacts where the
// bezier curves join.
float d = min(d1, d2);
// Apply AA based on the thickness of the wave.
- alpha = 1.0 - smoothstep(vParams.x - 0.5 * afwidth,
- vParams.x + 0.5 * afwidth,
- d);
+ alpha = distance_aa(aa_range, d - vParams.x);
break;
}
}
oFragColor = vColor * vec4(1.0, 1.0, 1.0, alpha);
}
#endif