Bug 1414033 - Recursively invalidate any cached ContainerLayer surfaces for new attached Layers, since they might have been moved and we don't track invalid areas within them. r=mstange
authorMatt Woodrow <mwoodrow@mozilla.com>
Thu, 02 May 2019 21:00:30 +0000
changeset 472360 2de2d4ea2587f0592518c94e771a89d418dc2d86
parent 472359 83e1c60d2283bb0141b0d26412db6b0b6b36b48c
child 472361 569aec33bccb48a4c91ec0fdbf1109430b6b113e
push id35954
push userrgurzau@mozilla.com
push dateFri, 03 May 2019 04:14:31 +0000
treeherdermozilla-central@d7b02bc7cf44 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmstange
bugs1414033
milestone68.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1414033 - Recursively invalidate any cached ContainerLayer surfaces for new attached Layers, since they might have been moved and we don't track invalid areas within them. r=mstange Differential Revision: https://phabricator.services.mozilla.com/D29452
gfx/layers/LayerTreeInvalidation.cpp
layout/reftests/layers/opacity-keep-intermediate-surface-too-long-ref.html
layout/reftests/layers/opacity-keep-intermediate-surface-too-long.html
layout/reftests/layers/reftest.list
--- a/gfx/layers/LayerTreeInvalidation.cpp
+++ b/gfx/layers/LayerTreeInvalidation.cpp
@@ -135,16 +135,28 @@ static void NotifySubdocumentInvalidatio
         if (container) {
           nsIntRegion region =
               container->GetLocalVisibleRegion().ToUnknownRegion();
           aCallback(container, &region);
         }
       });
 }
 
+static void SetChildrenChangedRecursive(Layer* aLayer) {
+  ForEachNode<ForwardIterator>(
+      aLayer,
+      [](Layer* layer) {
+        ContainerLayer* container = layer->AsContainerLayer();
+        if (container) {
+          container->SetChildrenChanged(true);
+          container->SetInvalidCompositeRect(nullptr);
+        }
+      });
+}
+
 struct LayerPropertiesBase : public LayerProperties {
   explicit LayerPropertiesBase(Layer* aLayer)
       : mLayer(aLayer),
         mMaskLayer(nullptr),
         mVisibleRegion(mLayer->GetLocalVisibleRegion().ToUnknownRegion()),
         mPostXScale(aLayer->GetPostXScale()),
         mPostYScale(aLayer->GetPostYScale()),
         mOpacity(aLayer->GetLocalOpacity()),
@@ -442,20 +454,24 @@ struct ContainerLayerProperties : public
             // We've already seen this child in mChildren (which means it must
             // have been reordered) and invalidated its old area. We need to
             // invalidate its new area too:
             invalidateChildsCurrentArea = true;
           }
         } else {
           // |child| is new
           invalidateChildsCurrentArea = true;
+          SetChildrenChangedRecursive(child);
         }
       } else {
         // |child| is new, or was reordered to a higher index
         invalidateChildsCurrentArea = true;
+        if (!oldIndexMap.Contains(child)) {
+          SetChildrenChangedRecursive(child);
+        }
       }
       if (invalidateChildsCurrentArea) {
         LTI_DUMP(child->GetLocalVisibleRegion().ToUnknownRegion(),
                  "invalidateChildsCurrentArea");
         AddTransformedRegion(result,
                              child->GetLocalVisibleRegion().ToUnknownRegion(),
                              GetTransformForInvalidation(child));
         if (aCallback) {
new file mode 100644
--- /dev/null
+++ b/layout/reftests/layers/opacity-keep-intermediate-surface-too-long-ref.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<html lang="en"><head>
+<meta http-equiv="content-type" content="text/html; charset=UTF-8"><meta charset="utf-8">
+<title>Clicking the canvas should turn it green (and shift it slighly)</title>
+
+<style>
+
+canvas {
+  border: 10px solid black;
+}
+
+.opacity {
+  opacity: 0.8;
+}
+
+</style>
+
+</head><body><div style="transform: translateX(1px)">
+  <div class="wrapper" style="transform: translateX(1px);">
+    <div class="opacity">
+      <div class="border">
+        <canvas id="canvas" width="200" height="200"></canvas>
+      </div>
+    </div>
+  </div>
+</div>
+
+<script>
+
+var canvas = document.getElementById('canvas');
+canvas.width = 200;
+canvas.height = 200;
+var ctx = canvas.getContext('2d');
+ctx.fillStyle = 'lime';
+ctx.fillRect(0, 0, 200, 200);
+</script>
+</body></html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/layers/opacity-keep-intermediate-surface-too-long.html
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<html lang="en" class="reftest-wait"><head>
+<meta http-equiv="content-type" content="text/html; charset=UTF-8"><meta charset="utf-8">
+<title>Clicking the canvas should turn it green (and shift it slighly)</title>
+
+<style>
+
+canvas {
+  border: 10px solid black;
+}
+
+.opacity {
+  opacity: 0.8;
+}
+
+</style>
+
+</head><body><div style="transform: translateX(1px)"><!-- create reference frame -->
+  <div class="wrapper"><!-- this starts out without a transform but later gets transformed -->
+    <div class="opacity"><!-- this creates a ContainerLayer with an intermediate surface for group opacity -->
+      <div class="border"><!-- this adds another visual element into the group opacity -->
+        <canvas id="canvas" width="200" height="200"></canvas><!-- this causes all ancestor effects to become active ContainerLayers -->
+      </div>
+    </div>
+  </div>
+</div>
+
+<script>
+
+var canvas = document.getElementById('canvas');
+var wrapper = document.querySelector('.wrapper');
+canvas.width = 200;
+canvas.height = 200;
+var ctx = canvas.getContext('2d');
+ctx.fillStyle = 'red';
+ctx.fillRect(0, 0, 200, 200);
+
+function doTest() {
+  ctx.fillStyle = 'lime';
+  ctx.fillRect(0, 0, 200, 200);
+  wrapper.style.transform = 'translateX(1px)';
+  document.documentElement.removeAttribute("class");
+}
+document.addEventListener("MozReftestInvalidate", doTest);
+
+</script>
+</body></html>
--- a/layout/reftests/layers/reftest.list
+++ b/layout/reftests/layers/reftest.list
@@ -35,8 +35,10 @@ skip-if(!asyncPan) == fixed-pos-scrolled
 #   Direct2D 1.1 works (as a proxy for Windows 7 SP1 + Platform Update or higher), OR
 #   The GPU process has been forced on.
 # If these conditions are met, but the GPU process is not on, these tests will turn on
 # and compare false.
 skip-if(!browserIsRemote||!d2d||gpuProcess) == data:text/plain,FAIL about:blank
 skip-if(!gpuProcessForceEnabled||gpuProcess) == data:text/plain,FAIL about:blank
 
 fuzzy-if(webrender,0-1,0-8033) == opacity-background-1.html opacity-background-1-ref.html
+
+== opacity-keep-intermediate-surface-too-long.html opacity-keep-intermediate-surface-too-long-ref.html