Bug 1539846. Ensure building rect changes cause invalidations. r=mstange
authorJeff Muizelaar <jmuizelaar@mozilla.com>
Fri, 03 May 2019 20:46:07 +0000
changeset 531459 5a6f2d97508e58da24d3ea26e82373d621849863
parent 531458 ca2f86087d3f9f09c185b2bf209261e892be27d6
child 531460 81d3a25685dcde796218147075147e44177615a5
push id11265
push userffxbld-merge
push dateMon, 13 May 2019 10:53:39 +0000
treeherdermozilla-beta@77e0fe8dbdd3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmstange
bugs1539846
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 1539846. Ensure building rect changes cause invalidations. r=mstange Typically this would be handled by the visible region of the layer changing. However, since we build the container layer for the filter item directly the visible region doesn't get set or checked. As a shortcut to using more of FLB we just ensure the building rect hasn't changed. The situations under which this bugs shows up are somewhat rare: - The filtered item needs to be in transform so that it's bounds are not changed by scrolling. - The filtered item needs to contain items that change their drawing depending on the building rect. In this case an image with downscale on decode. - The filter needs to be unsupported by WebRender. Differential Revision: https://phabricator.services.mozilla.com/D29879
gfx/layers/wr/WebRenderCommandBuilder.cpp
gfx/layers/wr/WebRenderUserData.h
layout/reftests/invalidation/jetstream-scroll-ref.html
layout/reftests/invalidation/jetstream-scroll.html
layout/reftests/invalidation/reftest.list
--- a/gfx/layers/wr/WebRenderCommandBuilder.cpp
+++ b/gfx/layers/wr/WebRenderCommandBuilder.cpp
@@ -2232,16 +2232,23 @@ WebRenderCommandBuilder::GenerateFallbac
           recorder, dummyDt, dtSize.ToUnknownSize());
       if (!fallbackData->mBasicLayerManager) {
         fallbackData->mBasicLayerManager =
             new BasicLayerManager(BasicLayerManager::BLM_INACTIVE);
       }
       bool isInvalidated = PaintItemByDrawTarget(
           aItem, dt, offset, aDisplayListBuilder,
           fallbackData->mBasicLayerManager, scale, highlight);
+      if (!isInvalidated) {
+        if (!aItem->GetBuildingRect().IsEqualInterior(fallbackData->mBuildingRect)) {
+          // The building rect has changed but we didn't see any invalidations.
+          // We should still consider this an invalidation.
+          isInvalidated = true;
+        }
+      }
       recorder->FlushItem(IntRect({0, 0}, dtSize.ToUnknownSize()));
       TakeExternalSurfaces(
           recorder, fallbackData->mExternalSurfaces,
           mManager->GetRenderRootStateManager(aBuilder.GetRenderRoot()),
           aResources);
       recorder->Finish();
 
       if (!validFonts) {
@@ -2323,16 +2330,17 @@ WebRenderCommandBuilder::GenerateFallbac
     }
 
     fallbackData->mScale = scale;
     fallbackData->SetInvalid(false);
   }
 
   // Update current bounds to fallback data
   fallbackData->mBounds = paintBounds;
+  fallbackData->mBuildingRect = aItem->GetBuildingRect();
 
   MOZ_ASSERT(fallbackData->GetImageKey());
 
   return fallbackData.forget();
 }
 
 class WebRenderMaskData : public WebRenderUserData {
  public:
--- a/gfx/layers/wr/WebRenderUserData.h
+++ b/gfx/layers/wr/WebRenderUserData.h
@@ -198,16 +198,17 @@ class WebRenderFallbackData : public Web
   /// Create a WebRenderImageData to manage the image we are about to render
   /// into.
   WebRenderImageData* PaintIntoImage();
 
   std::vector<RefPtr<gfx::SourceSurface>> mExternalSurfaces;
   RefPtr<BasicLayerManager> mBasicLayerManager;
   nsAutoPtr<nsDisplayItemGeometry> mGeometry;
   nsRect mBounds;
+  nsRect mBuildingRect;
   gfx::Size mScale;
 
  protected:
   void ClearImageKey();
 
   std::vector<RefPtr<gfx::ScaledFont>> mFonts;
   Maybe<wr::BlobImageKey> mBlobKey;
   // When rendering into a blob image, mImageData is null. It is non-null only
new file mode 100644
--- /dev/null
+++ b/layout/reftests/invalidation/jetstream-scroll-ref.html
@@ -0,0 +1,70 @@
+<!DOCTYPE html>
+<html class="reftest-wait" reftest-async-scroll><head>
+<meta http-equiv="content-type" content="text/html; charset=UTF-8"><meta charset="utf-8">
+<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=yes, viewport-fit=cover">
+<style>
+    figure {
+        position: relative;
+        width: 100vw;
+        left: 50%;
+        transform: translate(-50%);
+    }
+
+    figure img {
+        filter: url(#invertLightness)
+    }
+
+    main { scrollbar-width: none; width: 400px; height: 500px; overflow: auto; border: 1px solid black; }
+</style>
+
+</head>
+
+<body>
+
+    <svg xmlns="http://www.w3.org/2000/svg"> <style>svg{display:block;width:0;height:0}</style>
+        <filter id="invertLightness" x="0" y="0" style="color-interpolation-filters:sRGB">
+            <feColorMatrix type="matrix" in="SourceGraphic" result="red" values="1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 1">
+            </feColorMatrix>
+            <feColorMatrix type="matrix" in="SourceGraphic" result="green" values="0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 1">
+            </feColorMatrix>
+            <feColorMatrix type="matrix" in="SourceGraphic" result="blue" values="0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 1">
+            </feColorMatrix>
+            <feBlend in="red" in2="green" mode="lighten" result="maxyellow"></feBlend>
+            <feBlend in="maxyellow" in2="blue" mode="lighten" result="max"></feBlend>
+            <feBlend in="red" in2="green" mode="darken" result="minyellow"></feBlend>
+            <feBlend in="minyellow" in2="blue" mode="darken" result="min"></feBlend>
+            <feComponentTransfer result="adjustment" in="min">
+                <feFuncR type="linear" intercept="1" slope="-1"></feFuncR>
+                <feFuncG type="linear" intercept="1" slope="-1"></feFuncG>
+                <feFuncB type="linear" intercept="1" slope="-1"></feFuncB>
+            </feComponentTransfer>
+            <feComposite operator="arithmetic" in="SourceGraphic" in2="adjustment" k1="0" k2="1" k3="1" k4="-1" result="channelAdjustment"></feComposite>
+            <feComposite operator="arithmetic" in="channelAdjustment" in2="max" k1="0" k2="1" k3="-1" k4="1" result="finalColors">
+            </feComposite>
+            <feComposite operator="in" in="finalColors" in2="SourceAlpha"></feComposite>
+        </filter>
+    </svg>
+    <main id="content"
+          reftest-displayport-x="0"
+          reftest-displayport-y="0"
+          reftest-displayport-w="400"
+          reftest-displayport-h="500">
+    <div>
+      <article>
+        <div>
+          <div style="height: 1000px"></div>
+          <figure>
+            <img id=telement src="data:image/webp;base64,UklGRugAAABXRUJQVlA4TNsAAAAvOEuOAQfQxhK3sf8BBW3bMOUPvzuO6H+G//znP//5z3/+85///Oc///nPf/7zn//85z//+c9//vOf//znP//5z3/+85///Oc///nPf/7zn//85z//+c9//vOf//znP//5z3/+85///Oc///nPf/7zn//85z//+c9//vOf//znP//5z3/+85///Oc///nPf/7zn//85z//+c9//vOf//znP//5z3/+85///Oc///nPf/7zn//85z//+c9//vOf//znP//5z3/+85///Oc///nPf/7zn//85z//qwEA" alt="JetStream 2 Scores. Bigger is Better.">
+          </figure>
+        </div>
+      </article>
+    </div>
+    </main>
+</body>
+<script>
+
+    document.getElementById("content").scrollTop = 1100;
+    document.documentElement.removeAttribute("class");
+</script>
+
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/invalidation/jetstream-scroll.html
@@ -0,0 +1,73 @@
+<!DOCTYPE html>
+<html class="reftest-wait" reftest-async-scroll><head>
+<meta http-equiv="content-type" content="text/html; charset=UTF-8"><meta charset="utf-8">
+<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=yes, viewport-fit=cover">
+<style>
+    figure {
+        position: relative;
+        width: 100vw;
+        left: 50%;
+        transform: translate(-50%);
+    }
+
+    figure img {
+        filter: url(#invertLightness)
+    }
+
+    main { scrollbar-width: none; width: 400px; height: 500px; overflow: auto; border: 1px solid black; }
+</style>
+
+</head>
+
+<body>
+
+    <svg xmlns="http://www.w3.org/2000/svg"> <style>svg{display:block;width:0;height:0}</style>
+        <filter id="invertLightness" x="0" y="0" style="color-interpolation-filters:sRGB">
+            <feColorMatrix type="matrix" in="SourceGraphic" result="red" values="1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 1">
+            </feColorMatrix>
+            <feColorMatrix type="matrix" in="SourceGraphic" result="green" values="0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 1">
+            </feColorMatrix>
+            <feColorMatrix type="matrix" in="SourceGraphic" result="blue" values="0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 1">
+            </feColorMatrix>
+            <feBlend in="red" in2="green" mode="lighten" result="maxyellow"></feBlend>
+            <feBlend in="maxyellow" in2="blue" mode="lighten" result="max"></feBlend>
+            <feBlend in="red" in2="green" mode="darken" result="minyellow"></feBlend>
+            <feBlend in="minyellow" in2="blue" mode="darken" result="min"></feBlend>
+            <feComponentTransfer result="adjustment" in="min">
+                <feFuncR type="linear" intercept="1" slope="-1"></feFuncR>
+                <feFuncG type="linear" intercept="1" slope="-1"></feFuncG>
+                <feFuncB type="linear" intercept="1" slope="-1"></feFuncB>
+            </feComponentTransfer>
+            <feComposite operator="arithmetic" in="SourceGraphic" in2="adjustment" k1="0" k2="1" k3="1" k4="-1" result="channelAdjustment"></feComposite>
+            <feComposite operator="arithmetic" in="channelAdjustment" in2="max" k1="0" k2="1" k3="-1" k4="1" result="finalColors">
+            </feComposite>
+            <feComposite operator="in" in="finalColors" in2="SourceAlpha"></feComposite>
+        </filter>
+    </svg>
+    <main id="content"
+          reftest-displayport-x="0"
+          reftest-displayport-y="0"
+          reftest-displayport-w="400"
+          reftest-displayport-h="500">
+    <div>
+      <article>
+        <div>
+          <div style="height: 1000px"></div>
+          <figure>
+            <img id=telement src="data:image/webp;base64,UklGRugAAABXRUJQVlA4TNsAAAAvOEuOAQfQxhK3sf8BBW3bMOUPvzuO6H+G//znP//5z3/+85///Oc///nPf/7zn//85z//+c9//vOf//znP//5z3/+85///Oc///nPf/7zn//85z//+c9//vOf//znP//5z3/+85///Oc///nPf/7zn//85z//+c9//vOf//znP//5z3/+85///Oc///nPf/7zn//85z//+c9//vOf//znP//5z3/+85///Oc///nPf/7zn//85z//+c9//vOf//znP//5z3/+85///Oc///nPf/7zn//85z//qwEA" alt="JetStream 2 Scores. Bigger is Better.">
+          </figure>
+        </div>
+      </article>
+    </div>
+    </main>
+</body>
+<script>
+
+  document.getElementById("content").scrollTop = 800;
+  document.addEventListener("MozReftestInvalidate", function() {
+    document.getElementById("content").scrollTop = 1100;
+    document.documentElement.removeAttribute("class");
+  });
+</script>
+
+</html>
--- a/layout/reftests/invalidation/reftest.list
+++ b/layout/reftests/invalidation/reftest.list
@@ -98,8 +98,9 @@ pref(layers.single-tile.enabled,false) !
 
 != fractional-transform-1.html about:blank
 skip-if(/^Windows\x20NT\x2010\.0/.test(http.oscpu)) != fractional-transform-2.html about:blank
 != fractional-transform-3.html about:blank
 
 == partially-scrolled-svg-group.html partially-scrolled-svg-group-ref.html
 
 == paintedlayer-recycling-8.html paintedlayer-recycling-8-ref.html
+pref(image.downscale-during-decode.enabled,true) == jetstream-scroll.html jetstream-scroll-ref.html