Bug 1582645. Only set mLastVisibleRect after we've sent it to WebRender. r=nical
authorJeff Muizelaar <jrmuizel@gmail.com>
Mon, 30 Sep 2019 17:48:34 +0000
changeset 495726 df723e7120dc878f3cec9cf8c6eda070ba16d115
parent 495725 7d38a5ce1de0f6b204f0e335d9a8d9ae2217c1e2
child 495727 42727308025767aa9f53eaf149b13b154f537bc8
push id114140
push userdvarga@mozilla.com
push dateWed, 02 Oct 2019 18:04:51 +0000
treeherdermozilla-inbound@32eb0ea893f3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnical
bugs1582645
milestone71.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 1582645. Only set mLastVisibleRect after we've sent it to WebRender. r=nical This avoids us setting when we don't send it. e.g. When it's empty. Differential Revision: https://phabricator.services.mozilla.com/D47028
gfx/layers/wr/WebRenderCommandBuilder.cpp
layout/svg/crashtests/invalidation-of-opacity-0.html
--- a/gfx/layers/wr/WebRenderCommandBuilder.cpp
+++ b/gfx/layers/wr/WebRenderCommandBuilder.cpp
@@ -290,18 +290,22 @@ struct DIGroup {
   //    We'll just need to be careful when iterating.
   //    The advantage of a Vec is that everything stays compact
   //    and we don't need to heap allocate the BlobItemData's
   nsTHashtable<nsPtrHashKey<BlobItemData>> mDisplayItems;
 
   IntRect mInvalidRect;
   nsRect mGroupBounds;
   LayerIntRect mVisibleRect;
+  // This is the last visible rect sent to WebRender. It's used
+  // to compute the invalid rect and ensure that we send
+  // the appropriate data to WebRender for merging.
   LayerIntRect mLastVisibleRect;
-  // this is the intersection of mVisibleRect and mLastVisibleRect
+
+  // This is the intersection of mVisibleRect and mLastVisibleRect
   // we ensure that mInvalidRect is contained in mPreservedRect
   IntRect mPreservedRect;
   int32_t mAppUnitsPerDevPixel;
   gfx::Size mScale;
   ScrollableLayerGuid::ViewID mScrollId;
   LayerPoint mResidualOffset;
   LayerIntRect mLayerBounds; // mGroupBounds converted to Layer space
   // The current bounds of the blob image
@@ -625,16 +629,17 @@ struct DIGroup {
       if (mKey) {
         // Although the contents haven't changed, the visible area *may* have,
         // so request it be updated unconditionally (wr should be able to easily
         // detect if this is a no-op on its side, if that matters)
         aResources.SetBlobImageVisibleArea(
             mKey.value().second(),
             ViewAs<ImagePixel>(mVisibleRect,
                                PixelCastJustification::LayerIsImage));
+        mLastVisibleRect = mVisibleRect;
         PushImage(aBuilder, itemBounds);
       }
       return;
     }
 
     gfx::SurfaceFormat format = gfx::SurfaceFormat::B8G8R8A8;
     std::vector<RefPtr<ScaledFont>> fonts;
     bool validFonts = true;
@@ -736,16 +741,17 @@ struct DIGroup {
         return;
       }
     }
     mFonts = std::move(fonts);
     mInvalidRect.SetEmpty();
     aResources.SetBlobImageVisibleArea(
         mKey.value().second(),
         ViewAs<ImagePixel>(mVisibleRect, PixelCastJustification::LayerIsImage));
+    mLastVisibleRect = mVisibleRect;
     PushImage(aBuilder, itemBounds);
     GP("End EndGroup\n\n");
   }
 
   void PushImage(wr::DisplayListBuilder& aBuilder,
                  const LayoutDeviceRect& bounds) {
     wr::LayoutRect dest = wr::ToLayoutRect(bounds);
     GP("PushImage: %f %f %f %f\n", dest.origin.x, dest.origin.y,
@@ -1255,18 +1261,18 @@ void Grouper::ConstructGroups(nsDisplayL
       groupData->mFollowingGroup.mLayerBounds = currentGroup->mLayerBounds;
       groupData->mFollowingGroup.mImageBounds = currentGroup->mImageBounds;
       groupData->mFollowingGroup.mClippedImageBounds =
           currentGroup->mClippedImageBounds;
       groupData->mFollowingGroup.mScale = currentGroup->mScale;
       groupData->mFollowingGroup.mResidualOffset =
           currentGroup->mResidualOffset;
       groupData->mFollowingGroup.mVisibleRect = currentGroup->mVisibleRect;
-      groupData->mFollowingGroup.mLastVisibleRect = currentGroup->mLastVisibleRect;
-      groupData->mFollowingGroup.mPreservedRect = currentGroup->mPreservedRect;
+      groupData->mFollowingGroup.mPreservedRect =
+        groupData->mFollowingGroup.mVisibleRect.Intersect(groupData->mFollowingGroup.mLastVisibleRect).ToUnknownRect();
 
       currentGroup->EndGroup(aCommandBuilder->mManager, aDisplayListBuilder,
                              aBuilder, aResources, this, startOfCurrentGroup,
                              item);
 
       {
         MOZ_ASSERT(item->GetType() != DisplayItemType::TYPE_RENDER_ROOT);
         auto spaceAndClipChain = mClipManager.SwitchItem(item);
@@ -1519,17 +1525,16 @@ void WebRenderCommandBuilder::DoGrouping
   if (const ActiveScrolledRoot* asr = aWrappingItem->GetActiveScrolledRoot()) {
     scrollId = asr->GetViewId();
   }
 
   g.mAppUnitsPerDevPixel = appUnitsPerDevPixel;
   group.mResidualOffset = residualOffset;
   group.mGroupBounds = groupBounds;
   group.mLayerBounds = layerBounds;
-  group.mLastVisibleRect = group.mVisibleRect;
   group.mVisibleRect = visibleRect;
   group.mPreservedRect = group.mVisibleRect.Intersect(group.mLastVisibleRect).ToUnknownRect();
   group.mAppUnitsPerDevPixel = appUnitsPerDevPixel;
   group.mImageBounds = layerBounds.ToUnknownRect();
   group.mClippedImageBounds = group.mImageBounds;
 
   g.mTransform = Matrix::Scaling(scale.width, scale.height)
                      .PostTranslate(residualOffset.x, residualOffset.y);
new file mode 100644
--- /dev/null
+++ b/layout/svg/crashtests/invalidation-of-opacity-0.html
@@ -0,0 +1,26 @@
+<html class="reftest-wait">
+  <script>
+  var i = 0;
+  var opac = [0.3, 0.2, 0, 0.3];
+
+  function f() {
+    document.getElementById("rim").setAttribute("opacity", opac[i]);
+    document.getElementById("circ").setAttribute("r", i + 10);
+    i++;
+    if (i > opac.length) {
+      document.documentElement.className = ""
+    } else {
+      requestAnimationFrame(f);
+    }
+  }
+  onload = () => requestAnimationFrame(f);
+</script>
+
+<body>
+  <svg height="1000" width="1000">
+    <circle cx="50" cy="50" r="40" fill="red" />
+    <g id=rim clip-path="url(#myClip)" opacity=0>
+      <circle id="circ" cx="150" cy="150" r="40" fill="red" />
+    </g>
+    <circle cx="250" cy="250" r="40" fill="red" />
+  </svg>