Bug 1431582 - WR support non-locally-rasterized split planes r=gw

Now that we no longer guarantee that a picture with perspective transform is rasterized in local space, we need to ensure that the shaders don't apply perspective correction to the texture coordinates twice.
For that to be the case, we pass an extra flag to the plane splitting shader, and un-do the perspective correction if it's not enabled.

Differential Revision: https://phabricator.services.mozilla.com/D17854

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Dzmitry Malyshau 2019-01-29 15:31:09 +00:00
Родитель 83b0934186
Коммит a68eff5db8
5 изменённых файлов: 50 добавлений и 24 удалений

Просмотреть файл

@ -6,8 +6,11 @@
#include shared,prim_shared,brush
varying vec3 vUv;
// Interpolated UV coordinates to sample.
varying vec2 vUv;
// X = layer index to sample, Y = flag to allow perspective interpolation of UV.
flat varying vec2 vLayerAndPerspective;
flat varying float vAmount;
flat varying int vOp;
flat varying mat3 vColorMat;
@ -39,8 +42,10 @@ void brush_vs(
vec2 y = mix(extra_data.st_bl, extra_data.st_br, f.x);
f = mix(x, y, f.y);
vec2 uv = mix(uv0, uv1, f);
vUv = vec3(uv / texture_size, res.layer);
float perspective_interpolate = (brush_flags & BRUSH_FLAG_PERSPECTIVE_INTERPOLATION) != 0 ? 1.0 : 0.0;
vUv = uv / texture_size * mix(vi.world_pos.w, 1.0, perspective_interpolate);
vLayerAndPerspective = vec2(res.layer, perspective_interpolate);
vUvClipBounds = vec4(uv0, uv1) / texture_size.xyxy;
float lumR = 0.2126;
@ -146,7 +151,8 @@ vec3 LinearToSrgb(vec3 color) {
}
Fragment brush_fs() {
vec4 Cs = texture(sColor0, vUv);
float perspective_divisor = mix(gl_FragCoord.w, 1.0, vLayerAndPerspective.y);
vec4 Cs = texture(sColor0, vec3(vUv * perspective_divisor, vLayerAndPerspective.x));
// Un-premultiply the input.
float alpha = Cs.a;

Просмотреть файл

@ -10,8 +10,10 @@
varying vec2 vLocalPos;
#endif
// Interpolated uv coordinates in xy, and layer in z.
varying vec3 vUv;
// Interpolated UV coordinates to sample.
varying vec2 vUv;
// X = layer index to sample, Y = flag to allow perspective interpolation of UV.
flat varying vec2 vLayerAndPerspective;
// Normalized bounds of the source image in the texture.
flat varying vec4 vUvBounds;
// Normalized bounds of the source image in the texture, adjusted to avoid
@ -97,7 +99,8 @@ void brush_vs(
}
}
vUv.z = res.layer;
float perspective_interpolate = (brush_flags & BRUSH_FLAG_PERSPECTIVE_INTERPOLATION) != 0 ? 1.0 : 0.0;
vLayerAndPerspective = vec2(res.layer, perspective_interpolate);
// Handle case where the UV coords are inverted (e.g. from an
// external image).
@ -141,9 +144,12 @@ void brush_vs(
// Offset and scale vUv here to avoid doing it in the fragment shader.
vec2 repeat = local_rect.size / stretch_size;
vUv.xy = mix(uv0, uv1, f) - min_uv;
vUv.xy /= texture_size;
vUv.xy *= repeat.xy;
vUv = mix(uv0, uv1, f) - min_uv;
vUv /= texture_size;
vUv *= repeat.xy;
if (perspective_interpolate == 0.0) {
vUv *= vi.world_pos.w;
}
#ifdef WR_FEATURE_TEXTURE_RECT
vUvBounds = vec4(0.0, 0.0, vec2(textureSize(sColor0)));
@ -201,12 +207,13 @@ void brush_vs(
Fragment brush_fs() {
vec2 uv_size = vUvBounds.zw - vUvBounds.xy;
float perspective_divisor = mix(gl_FragCoord.w, 1.0, vLayerAndPerspective.y);
#ifdef WR_FEATURE_ALPHA_PASS
// This prevents the uv on the top and left parts of the primitive that was inflated
// for anti-aliasing purposes from going beyound the range covered by the regular
// (non-inflated) primitive.
vec2 local_uv = max(vUv.xy, vec2(0.0));
vec2 local_uv = max(vUv * perspective_divisor, vec2(0.0));
// Handle horizontal and vertical repetitions.
vec2 repeated_uv = mod(local_uv, uv_size) + vUvBounds.xy;
@ -222,13 +229,13 @@ Fragment brush_fs() {
}
#else
// Handle horizontal and vertical repetitions.
vec2 repeated_uv = mod(vUv.xy, uv_size) + vUvBounds.xy;
vec2 repeated_uv = mod(vUv * perspective_divisor, uv_size) + vUvBounds.xy;
#endif
// Clamp the uvs to avoid sampling artifacts.
vec2 uv = clamp(repeated_uv, vUvSampleBounds.xy, vUvSampleBounds.zw);
vec4 texel = TEX_SAMPLE(sColor0, vec3(uv, vUv.z));
vec4 texel = TEX_SAMPLE(sColor0, vec3(uv, vLayerAndPerspective.x));
Fragment frag;

Просмотреть файл

@ -4,7 +4,10 @@
#include shared,prim_shared
varying vec3 vUv;
// interpolated UV coordinates to sample.
varying vec2 vUv;
// X = layer index to sample, Y = flag to allow perspective interpolation of UV.
flat varying vec2 vLayerAndPerspective;
flat varying vec4 vUvSampleBounds;
#ifdef WR_VERTEX_SHADER
@ -103,15 +106,18 @@ void main(void) {
f.y, f.x
);
vec2 uv = mix(uv0, uv1, f);
float perspective_interpolate = float(ph.user_data.y);
vUv = vec3(uv / texture_size, res.layer);
vUv = uv / texture_size * mix(gl_Position.w, 1.0, perspective_interpolate);
vLayerAndPerspective = vec2(res.layer, perspective_interpolate);
}
#endif
#ifdef WR_FRAGMENT_SHADER
void main(void) {
float alpha = do_clip();
vec2 uv = clamp(vUv.xy, vUvSampleBounds.xy, vUvSampleBounds.zw);
oFragColor = alpha * textureLod(sPrevPassColor, vec3(uv, vUv.z), 0.0);
float perspective_divisor = mix(gl_FragCoord.w, 1.0, vLayerAndPerspective.y);
vec2 uv = clamp(vUv * perspective_divisor, vUvSampleBounds.xy, vUvSampleBounds.zw);
oFragColor = alpha * textureLod(sPrevPassColor, vec3(uv, vLayerAndPerspective.x), 0.0);
}
#endif

Просмотреть файл

@ -597,6 +597,8 @@ impl AlphaBatchBuilder {
#[cfg(debug_assertions)] //TODO: why is this needed?
debug_assert_eq!(prim_instance.prepared_frame_id, render_tasks.frame_id());
let is_chased = prim_instance.is_chased();
let transform_id = transforms
.get_id(
prim_instance.spatial_node_index,
@ -627,6 +629,12 @@ impl AlphaBatchBuilder {
prim_common_data.prim_size,
);
if is_chased {
println!("\tbatch {:?} with clip {:?} and bound {:?}",
prim_rect, clip_task_address, bounding_rect);
}
match prim_instance.kind {
PrimitiveInstanceKind::Clear { data_handle } => {
let prim_data = &ctx.data_stores.prim[data_handle];
@ -972,7 +980,7 @@ impl AlphaBatchBuilder {
let prim_instance = &picture.prim_list.prim_instances[child.anchor];
let prim_info = &ctx.scratch.prim_info[prim_instance.visibility_info.0 as usize];
let pic_index = match prim_instance.kind {
let child_pic_index = match prim_instance.kind {
PrimitiveInstanceKind::Picture { pic_index, .. } => pic_index,
PrimitiveInstanceKind::LineDecoration { .. } |
PrimitiveInstanceKind::TextRun { .. } |
@ -987,7 +995,7 @@ impl AlphaBatchBuilder {
unreachable!();
}
};
let pic = &ctx.prim_store.pictures[pic_index.0];
let pic = &ctx.prim_store.pictures[child_pic_index.0];
// Get clip task, if set, for the picture primitive.
@ -1007,13 +1015,12 @@ impl AlphaBatchBuilder {
transform_id: child.transform_id,
};
let surface_index = pic
let raster_config = pic
.raster_config
.as_ref()
.expect("BUG: 3d primitive was not assigned a surface")
.surface_index;
.expect("BUG: 3d primitive was not assigned a surface");
let (uv_rect_address, _) = ctx
.surfaces[surface_index.0]
.surfaces[raster_config.surface_index.0]
.surface
.as_ref()
.expect("BUG: no surface")
@ -1025,7 +1032,7 @@ impl AlphaBatchBuilder {
let prim_header_index = prim_headers.push(&prim_header, z_id, [
uv_rect_address.as_int(),
0,
if raster_config.establishes_raster_root { 1 } else { 0 },
0,
]);

Просмотреть файл

@ -16,4 +16,4 @@ platform(linux,mac) fuzzy(1,20) == same-plane.yaml same-plane.png
#== cross.yaml cross-ref.yaml
== mixed-order.yaml mixed-order-ref.yaml
fuzzy(1,40000) == filter.yaml filter-ref.yaml
#fuzzy(1,10000) == gradient.yaml gradient-ref.yaml
fuzzy(1,10000) == gradient.yaml gradient-ref.yaml