From e6ac05b15b73626928afd44bafd662500664f405 Mon Sep 17 00:00:00 2001 From: Dzmitry Malyshau Date: Wed, 3 Jan 2018 16:37:25 -0500 Subject: [PATCH 1/5] Fixed edge mask decoding in the shader --- webrender/res/brush.glsl | 4 ++-- webrender/src/border.rs | 22 +++++++++++----------- webrender/src/prim_store.rs | 4 +++- 3 files changed, 16 insertions(+), 14 deletions(-) diff --git a/webrender/res/brush.glsl b/webrender/res/brush.glsl index ac1d57d077..ad833d3ee0 100644 --- a/webrender/res/brush.glsl +++ b/webrender/res/brush.glsl @@ -78,7 +78,6 @@ void main(void) { vec4[2] segment_data = fetch_from_resource_cache_2(segment_address); RectWithSize local_segment_rect = RectWithSize(segment_data[0].xy, segment_data[0].zw); - vec4 edge_aa_segment_mask = vec4((int(segment_data[1].x) & ivec4(1,2,4,8)) != ivec4(0)); vec2 device_pos, local_pos; @@ -121,11 +120,12 @@ void main(void) { vLocalBounds = vec4(vec2(-1000000.0), vec2(1000000.0)); #endif } else { + bvec4 edge_mask = notEqual(int(segment_data[1].x) & ivec4(1, 2, 4, 8), ivec4(0)); vi = write_transform_vertex( local_segment_rect, brush_prim.local_rect, brush_prim.local_clip_rect, - edge_aa_segment_mask, + mix(vec4(0.0), vec4(1.0), edge_mask), float(brush.z), scroll_node, pic_task diff --git a/webrender/src/border.rs b/webrender/src/border.rs index b9e17506ae..9c4b1b1688 100644 --- a/webrender/src/border.rs +++ b/webrender/src/border.rs @@ -433,20 +433,20 @@ impl FrameBuilder { ); let p3 = info.rect.bottom_right(); - let segment = |x0, y0, x1, y1, mask| BrushSegment::new( + let segment = |x0, y0, x1, y1| BrushSegment::new( LayerPoint::new(x0, y0), LayerSize::new(x1-x0, y1-y0), false, - mask + EdgeAaSegmentMask::all() // Note: this doesn't seem right, needs revision ); // Add a solid rectangle for each visible edge/corner combination. if top_edge == BorderEdgeKind::Solid { let descriptor = BrushSegmentDescriptor { segments: vec![ - segment(p0.x, p0.y, p1.x, p1.y, EdgeAaSegmentMask::TOP | EdgeAaSegmentMask::LEFT), - segment(p2.x, p0.y, p3.x, p1.y, EdgeAaSegmentMask::TOP | EdgeAaSegmentMask::RIGHT), - segment(p1.x, p0.y, p2.x, p1.y, EdgeAaSegmentMask::TOP), + segment(p0.x, p0.y, p1.x, p1.y), + segment(p2.x, p0.y, p3.x, p1.y), + segment(p1.x, p0.y, p2.x, p1.y), ], clip_mask_kind: BrushClipMaskKind::Unknown, }; @@ -462,7 +462,7 @@ impl FrameBuilder { if left_edge == BorderEdgeKind::Solid { let descriptor = BrushSegmentDescriptor { segments: vec![ - segment(p0.x, p1.y, p1.x, p2.y, EdgeAaSegmentMask::LEFT), + segment(p0.x, p1.y, p1.x, p2.y), ], clip_mask_kind: BrushClipMaskKind::Unknown, }; @@ -478,7 +478,7 @@ impl FrameBuilder { if right_edge == BorderEdgeKind::Solid { let descriptor = BrushSegmentDescriptor { segments: vec![ - segment(p2.x, p1.y, p3.x, p2.y, EdgeAaSegmentMask::RIGHT), + segment(p2.x, p1.y, p3.x, p2.y), ], clip_mask_kind: BrushClipMaskKind::Unknown, }; @@ -494,9 +494,9 @@ impl FrameBuilder { if bottom_edge == BorderEdgeKind::Solid { let descriptor = BrushSegmentDescriptor { segments: vec![ - segment(p1.x, p2.y, p2.x, p3.y, EdgeAaSegmentMask::BOTTOM), - segment(p2.x, p2.y, p3.x, p3.y, EdgeAaSegmentMask::BOTTOM | EdgeAaSegmentMask::RIGHT), - segment(p0.x, p2.y, p1.x, p3.y, EdgeAaSegmentMask::BOTTOM | EdgeAaSegmentMask::LEFT), + segment(p1.x, p2.y, p2.x, p3.y), + segment(p2.x, p2.y, p3.x, p3.y), + segment(p0.x, p2.y, p1.x, p3.y), ], clip_mask_kind: BrushClipMaskKind::Unknown, }; @@ -934,4 +934,4 @@ impl ImageBorderSegment { tile_spacing, } } -} \ No newline at end of file +} diff --git a/webrender/src/prim_store.rs b/webrender/src/prim_store.rs index 2d33c56bdc..c13c31e305 100644 --- a/webrender/src/prim_store.rs +++ b/webrender/src/prim_store.rs @@ -293,6 +293,7 @@ impl BrushPrimitive { } fn write_gpu_blocks(&self, request: &mut GpuDataRequest) { + // has to match VECS_PER_SPECIFIC_BRUSH match self.kind { BrushKind::Solid { color } => { request.push(color.premultiplied()); @@ -1241,6 +1242,7 @@ impl PrimitiveStore { // Mark this GPU resource as required for this frame. if let Some(mut request) = gpu_cache.request(&mut metadata.gpu_location) { + // has to match VECS_PER_BRUSH_PRIM request.push(metadata.local_rect); request.push(metadata.local_clip_rect); @@ -1299,10 +1301,10 @@ impl PrimitiveStore { PrimitiveKind::Brush => { let brush = &self.cpu_brushes[metadata.cpu_prim_index.0]; brush.write_gpu_blocks(&mut request); - match brush.segment_desc { Some(ref segment_desc) => { for segment in &segment_desc.segments { + // has to match VECS_PER_SEGMENT request.push(segment.local_rect); request.push([ segment.edge_flags.bits() as f32, From 29cacae5bd80486590000bfe222ef080615a14cf Mon Sep 17 00:00:00 2001 From: Dzmitry Malyshau Date: Fri, 5 Jan 2018 00:07:24 -0500 Subject: [PATCH 2/5] Rotated clip large ref test --- wrench/reftests/transforms/reftest.list | 1 + .../reftests/transforms/rotated-clip-large.png | Bin 0 -> 9461 bytes .../transforms/rotated-clip-large.yaml | 17 +++++++++++++++++ 3 files changed, 18 insertions(+) create mode 100644 wrench/reftests/transforms/rotated-clip-large.png create mode 100644 wrench/reftests/transforms/rotated-clip-large.yaml diff --git a/wrench/reftests/transforms/reftest.list b/wrench/reftests/transforms/reftest.list index f580bc0155..9a6942c38d 100644 --- a/wrench/reftests/transforms/reftest.list +++ b/wrench/reftests/transforms/reftest.list @@ -1,5 +1,6 @@ == local-clip.yaml local-clip.png == rotated-clip.yaml rotated-clip.png +== rotated-clip-large.yaml rotated-clip-large.png == image-rotated-clip.yaml image-rotated-clip.png # Something leaks the state: the test passes if only run `reftest reftests/transform` # but fails when all the tests are run diff --git a/wrench/reftests/transforms/rotated-clip-large.png b/wrench/reftests/transforms/rotated-clip-large.png new file mode 100644 index 0000000000000000000000000000000000000000..5f9a252f14db90bd6080cfcdc139425eb3b4b88d GIT binary patch literal 9461 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 literal 0 HcmV?d00001 diff --git a/wrench/reftests/transforms/rotated-clip-large.yaml b/wrench/reftests/transforms/rotated-clip-large.yaml new file mode 100644 index 0000000000..18aa7e3dd4 --- /dev/null +++ b/wrench/reftests/transforms/rotated-clip-large.yaml @@ -0,0 +1,17 @@ +--- +root: + items: + - + bounds: 100 100 300 300 + items: + - type: clip + bounds: [20, 20, 200, 200] + complex: + - rect: [20, 20, 200, 200] + radius: 32 + items: + - type: rect + bounds: 20 20 200 200 + color: blue + type: stacking-context + transform: rotate(33) From 8804cab68354572d7711cf2c48999c158d358287 Mon Sep 17 00:00:00 2001 From: Dzmitry Malyshau Date: Fri, 5 Jan 2018 10:02:01 -0500 Subject: [PATCH 3/5] Masked edge AA extrusion --- webrender/res/prim_shared.glsl | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/webrender/res/prim_shared.glsl b/webrender/res/prim_shared.glsl index 7753298899..858931d5ba 100644 --- a/webrender/res/prim_shared.glsl +++ b/webrender/res/prim_shared.glsl @@ -630,9 +630,10 @@ VertexInfo write_transform_vertex(RectWithSize local_segment_rect, // However, it's fast and simple. If / when we ever run into issues, we // can do some math on the projection matrix to work out a variable // amount to extrude. + // Note: only those sides are extruded that have AA applied. float extrude_distance = 2.0; - local_segment_rect.p0 -= vec2(extrude_distance); - local_segment_rect.size += vec2(2.0 * extrude_distance); + local_segment_rect.p0 -= extrude_distance * clip_edge_mask.xy; + local_segment_rect.size += extrude_distance * (clip_edge_mask.xy + clip_edge_mask.zw); // Select the corner of the local rect that we are processing. vec2 local_pos = local_segment_rect.p0 + local_segment_rect.size * aPosition.xy; From 897c87271a73db580df8cc7f06efc16d902fbee6 Mon Sep 17 00:00:00 2001 From: Dzmitry Malyshau Date: Fri, 5 Jan 2018 11:33:37 -0500 Subject: [PATCH 4/5] Dynamic extrusion factor --- webrender/res/prim_shared.glsl | 72 ++++++++++++++++++++++++++++------ webrender/src/prim_store.rs | 4 +- 2 files changed, 62 insertions(+), 14 deletions(-) diff --git a/webrender/res/prim_shared.glsl b/webrender/res/prim_shared.glsl index 858931d5ba..25531288ac 100644 --- a/webrender/res/prim_shared.glsl +++ b/webrender/res/prim_shared.glsl @@ -16,6 +16,11 @@ #define SUBPX_DIR_HORIZONTAL 1 #define SUBPX_DIR_VERTICAL 2 +// Fixed value for the edge extrusion for AA, +// specified in pixels. If not defined, the extrusion +// is computed automatically. +//#define FIXED_EDGE_EXTRUSION (2.0) + uniform sampler2DArray sCacheA8; uniform sampler2DArray sCacheRGBA8; @@ -145,6 +150,9 @@ vec4 fetch_from_resource_cache_1(int address) { struct ClipScrollNode { mat4 transform; +#ifndef FIXED_EDGE_EXTRUSION + mat4 inverse_transform; +#endif bool is_axis_aligned; }; @@ -162,6 +170,9 @@ ClipScrollNode fetch_clip_scroll_node(int index) { node.transform[1] = TEXEL_FETCH(sClipScrollNodes, uv0, 0, ivec2(1, 0)); node.transform[2] = TEXEL_FETCH(sClipScrollNodes, uv0, 0, ivec2(2, 0)); node.transform[3] = TEXEL_FETCH(sClipScrollNodes, uv0, 0, ivec2(3, 0)); +#ifndef FIXED_EDGE_EXTRUSION + node.inverse_transform = inverse(node.transform); +#endif vec4 misc = TEXEL_FETCH(sClipScrollNodes, uv0, 0, ivec2(4, 0)); node.is_axis_aligned = misc.x == 0.0; @@ -514,11 +525,28 @@ vec4 get_node_pos(vec2 pos, ClipScrollNode node) { vec3 a = ah.xyz / ah.w; // get the normal to the scroll node plane +#ifdef FIXED_EDGE_EXTRUSION mat4 inv_transform = inverse(node.transform); +#else + mat4 inv_transform = node.inverse_transform; +#endif vec3 n = transpose(mat3(inv_transform)) * vec3(0.0, 0.0, 1.0); return untransform(pos, n, a, inv_transform); } +#ifndef FIXED_EDGE_EXTRUSION +// Given a local CSS space position, and an expected offset of its transformed result, +// produce a new local space CSS position in homogeneous coordinates. +vec4 retransform(vec2 pos, vec2 transformed_offset, ClipScrollNode node) { + vec4 ah = node.transform * vec4(0.0, 0.0, 0.0, 1.0); + vec3 a = ah.xyz / ah.w; + vec3 n = transpose(mat3(node.inverse_transform)) * vec3(0.0, 0.0, 1.0); + + vec4 pt = node.transform * vec4(pos, 0.0, 1.0); + return untransform(pt.xy/pt.w + transformed_offset, n, a, node.inverse_transform); +} +#endif //ifndef FIXED_EDGE_EXTRUSION + // Compute a snapping offset in world space (adjusted to pixel ratio), // given local position on the scroll_node and a snap rectangle. vec2 compute_snap_offset(vec2 local_pos, @@ -622,21 +650,41 @@ VertexInfo write_transform_vertex(RectWithSize local_segment_rect, prim_rect.p0 = clamp(prim_rect.p0, clip_rect.p0, clip_rect.p1); prim_rect.p1 = clamp(prim_rect.p1, clip_rect.p0, clip_rect.p1); - // As this is a transform shader, extrude by 2 (local space) pixels - // in each direction. This gives enough space around the edge to + // Note: only those sides are extruded that have AA applied. + vec4 extrude_edge_mask = clip_edge_mask * vec4(-1.0, -1.0, 1.0, 1.0); + vec2 local_pos; + +#ifdef FIXED_EDGE_EXTRUSION + // Extrude the edges by a given value (in local space) in each direction. + // Hopefully, this gives enough space around the edge to // apply distance anti-aliasing. Technically, it: // (a) slightly over-estimates the number of required pixels in the simple case. // (b) might not provide enough edge in edge case perspective projections. - // However, it's fast and simple. If / when we ever run into issues, we - // can do some math on the projection matrix to work out a variable - // amount to extrude. - // Note: only those sides are extruded that have AA applied. - float extrude_distance = 2.0; - local_segment_rect.p0 -= extrude_distance * clip_edge_mask.xy; - local_segment_rect.size += extrude_distance * (clip_edge_mask.xy + clip_edge_mask.zw); + // (c) simple and fast // Select the corner of the local rect that we are processing. - vec2 local_pos = local_segment_rect.p0 + local_segment_rect.size * aPosition.xy; + local_pos = local_segment_rect.p0 + aPosition.xy * local_segment_rect.size + + FIXED_EDGE_EXTRUSION * mix(extrude_edge_mask.xy, extrude_edge_mask.zw, aPosition.xy); +#else + // Dynamic extrusion distance computation based on the inverse transform. + { + extrude_edge_mask *= 0.5; // half a pixel offset. TODO: divide by `uDevicePixelRatio`? + vec4 rect = vec4(local_segment_rect.p0, local_segment_rect.p0 + local_segment_rect.size); + + vec4 p00 = retransform(rect.xy, extrude_edge_mask.xy, scroll_node); + vec4 p10 = retransform(rect.zy, extrude_edge_mask.zy, scroll_node); + vec4 p11 = retransform(rect.zw, extrude_edge_mask.zw, scroll_node); + vec4 p01 = retransform(rect.xw, extrude_edge_mask.xw, scroll_node); + + vec4 diag0 = vec4(p00.xy, p11.xy) / vec4(p00.ww, p11.ww); + vec4 diag1 = vec4(p10.xy, p01.xy) / vec4(p10.ww, p01.ww); + // This should work for affine transformations. + local_pos = mix( + mix(diag0.xy, diag1.xw, aPosition.xy), + mix(diag1.zy, diag0.zw, aPosition.xy), + aPosition.yx); + } +#endif // Transform the current vertex to the world cpace. vec4 world_pos = scroll_node.transform * vec4(local_pos, 0.0, 1.0); @@ -669,7 +717,7 @@ VertexInfo write_transform_vertex_primitive(Primitive prim) { prim.local_rect, prim.local_rect, prim.local_clip_rect, - vec4(0.0), + vec4(1.0), prim.z, prim.scroll_node, prim.task @@ -718,7 +766,7 @@ TextRun fetch_text_run(int address) { struct Image { vec4 stretch_size_and_tile_spacing; // Size of the actual image and amount of space between // tiled instances of this image. - vec4 sub_rect; // If negative, ignored. + vec4 sub_rect; // If negative, ignored. }; Image fetch_image(int address) { diff --git a/webrender/src/prim_store.rs b/webrender/src/prim_store.rs index c13c31e305..59b02a0dac 100644 --- a/webrender/src/prim_store.rs +++ b/webrender/src/prim_store.rs @@ -1292,7 +1292,7 @@ impl PrimitiveStore { // GPU blocks... request.push(metadata.local_rect); request.push([ - EdgeAaSegmentMask::empty().bits() as f32, + EdgeAaSegmentMask::all().bits() as f32, 0.0, 0.0, 0.0 @@ -1317,7 +1317,7 @@ impl PrimitiveStore { None => { request.push(metadata.local_rect); request.push([ - EdgeAaSegmentMask::empty().bits() as f32, + EdgeAaSegmentMask::all().bits() as f32, 0.0, 0.0, 0.0 From eff5ad1862d5b33002da14ae3851669922ebeca0 Mon Sep 17 00:00:00 2001 From: Dzmitry Malyshau Date: Fri, 5 Jan 2018 16:52:40 -0500 Subject: [PATCH 5/5] New rotated AA reftest --- wrench/reftests/aa/reftest.list | 1 + wrench/reftests/aa/rotate-y.png | Bin 0 -> 29991 bytes wrench/reftests/aa/rotate-y.yaml | 47 +++++++++++++++++++++++++++++++ 3 files changed, 48 insertions(+) create mode 100644 wrench/reftests/aa/rotate-y.png create mode 100644 wrench/reftests/aa/rotate-y.yaml diff --git a/wrench/reftests/aa/reftest.list b/wrench/reftests/aa/reftest.list index ec09c585ab..55953d46d2 100644 --- a/wrench/reftests/aa/reftest.list +++ b/wrench/reftests/aa/reftest.list @@ -1 +1,2 @@ == rounded-rects.yaml rounded-rects-ref.png +== rotate-y.yaml rotate-y.png diff --git a/wrench/reftests/aa/rotate-y.png b/wrench/reftests/aa/rotate-y.png new file mode 100644 index 0000000000000000000000000000000000000000..b2324b8c299802fafa3d16c00c1b20c345ccbe43 GIT binary patch literal 29991 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 literal 0 HcmV?d00001 diff --git a/wrench/reftests/aa/rotate-y.yaml b/wrench/reftests/aa/rotate-y.yaml new file mode 100644 index 0000000000..841d49f9de --- /dev/null +++ b/wrench/reftests/aa/rotate-y.yaml @@ -0,0 +1,47 @@ +--- +root: + items: + - + type: "stacking-context" + items: + - + type: "stacking-context" + transform: rotate-z(1) rotate-y(0) translate(20, 20, 0) + items: + - + bounds: [0, 0, 200, 200] + image: checkerboard(2, 16, 12) + stretch-size: 200 200 + - + type: "stacking-context" + transform: rotate-z(1) rotate-y(22) translate(240,20,0) + items: + - + bounds: [0, 0, 200, 200] + image: checkerboard(2, 16, 12) + stretch-size: 200 200 + - + type: "stacking-context" + transform: rotate-z(1) rotate-y(44) translate(-240,240,0) + items: + - + bounds: [0, 0, 200, 200] + image: checkerboard(2, 16, 12) + stretch-size: 200 200 + - + type: "stacking-context" + transform: rotate-z(1) rotate-y(66) translate(-320,240,0) + items: + - + bounds: [0, 0, 200, 200] + image: checkerboard(2, 16, 12) + stretch-size: 200 200 + + - + type: "stacking-context" + transform: rotate-z(1) rotate-y(88) translate(-480,240,0) + items: + - + bounds: [0, 0, 200, 200] + image: checkerboard(2, 16, 12) + stretch-size: 200 200