Bug 1260335 - On perspective ContainerLayers, the clip deferred from their child layer needs to be affected by the perspective layer's async transforms. r?botond
MozReview-Commit-ID: EEgsdFXGI1E
--- a/gfx/layers/composite/AsyncCompositionManager.cpp
+++ b/gfx/layers/composite/AsyncCompositionManager.cpp
@@ -819,16 +819,21 @@ AsyncCompositionManager::ApplyAsyncConte
// Each layer has multiple clips. Its local clip, which must move with async
// transforms, and its scrollframe clips, which are the clips between each
// scrollframe and its ancestor scrollframe. Scrollframe clips include the
// composition bounds and any other clips induced by layout.
//
// The final clip for the layer is the intersection of these clips.
Maybe<ParentLayerIntRect> asyncClip = aLayer->GetClipRect();
+ // If we are a perspective transform ContainerLayer, apply the clip deferred
+ // from our child (if there is any) before we iterate over our frame metrics,
+ // because this clip is subject to all async transforms of this layer.
+ asyncClip = IntersectMaybeRects(asyncClip, clipDeferredFromChildren);
+
// The transform of a mask layer is relative to the masked layer's parent
// layer. So whenever we apply an async transform to a layer, we need to
// apply that same transform to the layer's own mask layer.
// A layer can also have "ancestor" mask layers for any rounded clips from
// its ancestor scroll frames. A scroll frame mask layer only needs to be
// async transformed for async scrolls of this scroll frame's ancestor
// scroll frames, not for async scrolls of this scroll frame itself.
// In the loop below, we iterate over scroll frames from inside to outside.
@@ -970,18 +975,17 @@ AsyncCompositionManager::ApplyAsyncConte
if (metrics.GetMaskLayerIndex()) {
size_t maskLayerIndex = metrics.GetMaskLayerIndex().value();
Layer* ancestorMaskLayer = aLayer->GetAncestorMaskLayerAt(maskLayerIndex);
ancestorMaskLayers.AppendElement(ancestorMaskLayer);
}
}
if (hasAsyncTransform || clipDeferredFromChildren) {
- aLayer->AsLayerComposite()->SetShadowClipRect(
- IntersectMaybeRects(asyncClip, clipDeferredFromChildren));
+ aLayer->AsLayerComposite()->SetShadowClipRect(asyncClip);
}
if (hasAsyncTransform) {
// Apply the APZ transform on top of GetLocalTransform() here (rather than
// GetTransform()) in case the OMTA code in SampleAnimations already set a
// shadow transform; in that case we want to apply ours on top of that one
// rather than clobber it.
SetShadowTransform(aLayer,
new file mode 100644
--- /dev/null
+++ b/layout/reftests/async-scrolling/perspective-scrolling-4-ref.html
@@ -0,0 +1,53 @@
+<!DOCTYPE html>
+<html lang="en"
+ reftest-async-scroll
+ reftest-displayport-x="0" reftest-displayport-y="0"
+ reftest-displayport-w="800" reftest-displayport-h="1000"
+ reftest-async-scroll-x="0" reftest-async-scroll-y="0">
+<meta charset="utf-8">
+<title>Reference: Perspective scrolling with nested clips</title>
+
+<style>
+
+html {
+ padding: 50px 0 3000px;
+}
+
+body {
+ margin: 0;
+}
+
+.scrollbox {
+ width: 600px;
+ height: 500px;
+ perspective: 1px;
+ overflow: auto;
+}
+
+.transformed {
+ will-change: transform;
+ width: 200px;
+ height: 200px;
+ margin: 200px 100px;
+ border: 10px solid black;
+}
+
+.spacer {
+ height: 4000px;
+}
+
+</style>
+
+<div class="scrollbox"
+ reftest-displayport-x="0" reftest-displayport-y="0"
+ reftest-displayport-w="600" reftest-displayport-h="2000"
+ reftest-async-scroll-x="0" reftest-async-scroll-y="0">
+
+<div class="transformed"></div>
+<div class="spacer"></div>
+
+<script>
+
+document.scrollingElement.scrollTop = 250;
+
+</script>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/async-scrolling/perspective-scrolling-4.html
@@ -0,0 +1,52 @@
+<!DOCTYPE html>
+<html lang="en"
+ reftest-async-scroll
+ reftest-displayport-x="0" reftest-displayport-y="0"
+ reftest-displayport-w="800" reftest-displayport-h="1000"
+ reftest-async-scroll-x="0" reftest-async-scroll-y="250">
+<meta charset="utf-8">
+<title>Perspective scrolling with nested clips</title>
+
+<style>
+
+html {
+ padding: 50px 0 3000px;
+}
+
+body {
+ margin: 0;
+}
+
+.scrollbox {
+ width: 600px;
+ height: 500px;
+ perspective: 1px;
+ overflow: auto;
+}
+
+.transformed {
+ will-change: transform;
+ width: 200px;
+ height: 200px;
+ margin: 200px 100px;
+ border: 10px solid black;
+}
+
+.spacer {
+ height: 4000px;
+}
+
+</style>
+
+<div class="scrollbox"
+ reftest-displayport-x="0" reftest-displayport-y="0"
+ reftest-displayport-w="600" reftest-displayport-h="2000"
+ reftest-async-scroll-x="0" reftest-async-scroll-y="0">
+
+<div class="transformed"></div>
+<div class="spacer"></div>
+
+<script>
+// document.scrollingElement.scrollTop = 250;
+// document.querySelector(".scrollbox").scrollTop = 0;
+</script>
--- a/layout/reftests/async-scrolling/reftest.list
+++ b/layout/reftests/async-scrolling/reftest.list
@@ -34,16 +34,17 @@ skip-if(!asyncPan) == position-sticky-tr
skip-if(!asyncPan) == offscreen-prerendered-active-opacity.html offscreen-prerendered-active-opacity-ref.html
fuzzy-if(Android,6,4) skip-if(!asyncPan) == offscreen-clipped-blendmode-1.html offscreen-clipped-blendmode-ref.html
fuzzy-if(Android,6,4) skip-if(!asyncPan) == offscreen-clipped-blendmode-2.html offscreen-clipped-blendmode-ref.html
fuzzy-if(Android,6,4) skip == offscreen-clipped-blendmode-3.html offscreen-clipped-blendmode-ref.html # bug 1251588 - wrong AGR on mix-blend-mode item
fuzzy-if(Android,6,4) skip-if(!asyncPan) == offscreen-clipped-blendmode-4.html offscreen-clipped-blendmode-ref.html
fuzzy-if(Android,7,4) skip-if(!asyncPan) == perspective-scrolling-1.html perspective-scrolling-1-ref.html
fuzzy-if(Android,7,4) skip-if(!asyncPan) == perspective-scrolling-2.html perspective-scrolling-2-ref.html
fuzzy-if(Android,7,4) skip-if(!asyncPan) == perspective-scrolling-3.html perspective-scrolling-3-ref.html
+fuzzy-if(Android,7,4) skip-if(!asyncPan) == perspective-scrolling-4.html perspective-scrolling-4-ref.html
skip-if(!asyncPan) == background-blend-mode-1.html background-blend-mode-1-ref.html
# for the following tests, we want to disable the low-precision buffer
# as it will expand the displayport beyond what the test specifies in
# its reftest-displayport attributes, and interfere with where we expect
# checkerboarding to occur
default-preferences pref(layers.low-precision-buffer,false)
skip-if(!asyncPan) == checkerboard-1.html checkerboard-1-ref.html