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
authorMarkus Stange <mstange@themasta.com>
Mon, 04 Apr 2016 23:21:31 -0400
changeset 347734 4f1bcad3f4d6edb149785e1bbeb876ef74869bb0
parent 347733 ff6c2806545ebe2f2fa9ea9fd5b0d65cba478d59
child 347735 4f29fd865fad1a5316990b763d3a21b0ea1fee7a
push id14653
push userolivier@olivieryiptong.com
push dateTue, 05 Apr 2016 19:21:01 +0000
reviewersbotond
bugs1260335
milestone48.0a1
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
gfx/layers/composite/AsyncCompositionManager.cpp
layout/reftests/async-scrolling/perspective-scrolling-4-ref.html
layout/reftests/async-scrolling/perspective-scrolling-4.html
layout/reftests/async-scrolling/reftest.list
--- a/gfx/layers/composite/AsyncCompositionManager.cpp
+++ b/gfx/layers/composite/AsyncCompositionManager.cpp
@@ -820,16 +820,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.
@@ -973,18 +978,17 @@ AsyncCompositionManager::ApplyAsyncConte
     if (scrollMetadata.GetMaskLayerIndex()) {
       size_t maskLayerIndex = scrollMetadata.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,44 @@
+<!DOCTYPE html>
+<html lang="en">
+<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">
+  <div class="transformed"></div>
+  <div class="spacer"></div>
+</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,49 @@
+<!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>
+
+</div>
--- 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
 pref(apz.disable_for_scroll_linked_effects,true) skip-if(!asyncPan) == disable-apz-for-sle-pages.html disable-apz-for-sle-pages-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