зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
5c43b240ea
Коммит
1df57d7ca5
|
@ -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,9 @@ vec3 LinearToSrgb(vec3 color) {
|
|||
}
|
||||
|
||||
Fragment brush_fs() {
|
||||
vec4 Cs = texture(sColor0, vUv);
|
||||
float perspective_divisor = mix(gl_FragCoord.w, 1.0, vLayerAndPerspective.y);
|
||||
vec2 uv = vUv * perspective_divisor;
|
||||
vec4 Cs = texture(sColor0, vec3(uv, vLayerAndPerspective.x));
|
||||
|
||||
// Un-premultiply the input.
|
||||
float alpha = Cs.a;
|
||||
|
@ -179,7 +186,7 @@ Fragment brush_fs() {
|
|||
|
||||
// Fail-safe to ensure that we don't sample outside the rendered
|
||||
// portion of a blend source.
|
||||
alpha *= point_inside_rect(vUv.xy, vUvClipBounds.xy, vUvClipBounds.zw);
|
||||
alpha *= point_inside_rect(uv, vUvClipBounds.xy, vUvClipBounds.zw);
|
||||
|
||||
// Pre-multiply the alpha into the output value.
|
||||
return Fragment(alpha * vec4(color, 1.0));
|
||||
|
|
|
@ -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,
|
||||
]);
|
||||
|
||||
|
@ -1058,6 +1065,14 @@ impl AlphaBatchBuilder {
|
|||
|
||||
match picture.raster_config {
|
||||
Some(ref raster_config) => {
|
||||
// If the child picture was rendered in local space, we can safely
|
||||
// interpolate the UV coordinates with perspective correction.
|
||||
let brush_flags = if raster_config.establishes_raster_root {
|
||||
BrushFlags::PERSPECTIVE_INTERPOLATION
|
||||
} else {
|
||||
BrushFlags::empty()
|
||||
};
|
||||
|
||||
match raster_config.composite_mode {
|
||||
PictureCompositeMode::TileCache { .. } => {
|
||||
// Construct a local clip rect that ensures we only draw pixels where
|
||||
|
@ -1119,7 +1134,7 @@ impl AlphaBatchBuilder {
|
|||
clip_task_address,
|
||||
segment_index: INVALID_SEGMENT_INDEX,
|
||||
edge_flags: EdgeAaSegmentMask::empty(),
|
||||
brush_flags: BrushFlags::empty(),
|
||||
brush_flags,
|
||||
user_data: uv_rect_address,
|
||||
};
|
||||
|
||||
|
@ -1223,7 +1238,7 @@ impl AlphaBatchBuilder {
|
|||
prim_header_index,
|
||||
segment_index: INVALID_SEGMENT_INDEX,
|
||||
edge_flags: EdgeAaSegmentMask::empty(),
|
||||
brush_flags: BrushFlags::empty(),
|
||||
brush_flags,
|
||||
clip_task_address,
|
||||
user_data: uv_rect_address.as_int(),
|
||||
};
|
||||
|
@ -1303,7 +1318,7 @@ impl AlphaBatchBuilder {
|
|||
clip_task_address,
|
||||
segment_index: INVALID_SEGMENT_INDEX,
|
||||
edge_flags: EdgeAaSegmentMask::empty(),
|
||||
brush_flags: BrushFlags::empty(),
|
||||
brush_flags,
|
||||
user_data: shadow_uv_rect_address,
|
||||
};
|
||||
|
||||
|
@ -1312,7 +1327,7 @@ impl AlphaBatchBuilder {
|
|||
clip_task_address,
|
||||
segment_index: INVALID_SEGMENT_INDEX,
|
||||
edge_flags: EdgeAaSegmentMask::empty(),
|
||||
brush_flags: BrushFlags::empty(),
|
||||
brush_flags,
|
||||
user_data: content_uv_rect_address,
|
||||
};
|
||||
|
||||
|
@ -1397,7 +1412,7 @@ impl AlphaBatchBuilder {
|
|||
clip_task_address,
|
||||
segment_index: INVALID_SEGMENT_INDEX,
|
||||
edge_flags: EdgeAaSegmentMask::empty(),
|
||||
brush_flags: BrushFlags::empty(),
|
||||
brush_flags,
|
||||
user_data: 0,
|
||||
};
|
||||
|
||||
|
@ -1442,7 +1457,7 @@ impl AlphaBatchBuilder {
|
|||
clip_task_address,
|
||||
segment_index: INVALID_SEGMENT_INDEX,
|
||||
edge_flags: EdgeAaSegmentMask::empty(),
|
||||
brush_flags: BrushFlags::empty(),
|
||||
brush_flags,
|
||||
user_data: 0,
|
||||
};
|
||||
|
||||
|
@ -1482,7 +1497,7 @@ impl AlphaBatchBuilder {
|
|||
clip_task_address,
|
||||
segment_index: INVALID_SEGMENT_INDEX,
|
||||
edge_flags: EdgeAaSegmentMask::empty(),
|
||||
brush_flags: BrushFlags::empty(),
|
||||
brush_flags,
|
||||
user_data: uv_rect_address,
|
||||
};
|
||||
|
||||
|
|
|
@ -2442,7 +2442,7 @@ impl PicturePrimitive {
|
|||
|
||||
self.raster_config = Some(RasterConfig {
|
||||
composite_mode,
|
||||
establishes_raster_root: surface_spatial_node_index == surface.raster_spatial_node_index,
|
||||
establishes_raster_root: surface.raster_spatial_node_index != parent_raster_spatial_node_index,
|
||||
surface_index: state.push_surface(surface),
|
||||
});
|
||||
}
|
||||
|
|
|
@ -3169,7 +3169,7 @@ impl PrimitiveInstance {
|
|||
segment.has_mask,
|
||||
segment.edge_flags,
|
||||
[0.0; 4],
|
||||
BrushFlags::empty(),
|
||||
BrushFlags::PERSPECTIVE_INTERPOLATION,
|
||||
),
|
||||
);
|
||||
});
|
||||
|
|
|
@ -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
|
||||
|
|
Загрузка…
Ссылка в новой задаче