Bug 1720986 - Reinstate clipping filters within SVG to the building rect. r=jrmuizel
authorMatt Woodrow <mwoodrow@mozilla.com>
Sun, 25 Jul 2021 08:31:25 +0000
changeset 586585 bde3abc2dfe93996e148aef340326e71a14b66a2
parent 586584 cdd6ccd2d2426e1551d31b316086409326f14aa0
child 586586 3881437c0949a33a0a3ef4fd529a7647458c12ed
push id38641
push userabutkovits@mozilla.com
push dateSun, 25 Jul 2021 21:23:34 +0000
treeherdermozilla-central@3881437c0949 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjrmuizel
bugs1720986
milestone92.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 1720986 - Reinstate clipping filters within SVG to the building rect. r=jrmuizel Differential Revision: https://phabricator.services.mozilla.com/D120695
gfx/layers/wr/WebRenderCommandBuilder.cpp
layout/reftests/svg/filters/filter-giant.svg
layout/reftests/svg/filters/reftest.list
--- a/gfx/layers/wr/WebRenderCommandBuilder.cpp
+++ b/gfx/layers/wr/WebRenderCommandBuilder.cpp
@@ -254,16 +254,22 @@ static bool IsContainerLayerItem(nsDispl
   }
 }
 
 #include <sstream>
 
 static bool DetectContainerLayerPropertiesBoundsChange(
     nsDisplayItem* aItem, BlobItemData* aData,
     nsDisplayItemGeometry& aGeometry) {
+  if (aItem->GetType() == DisplayItemType::TYPE_FILTER) {
+    // Filters get clipped to the BuildingRect since they can
+    // have huge bounds outside of the visible area.
+    aGeometry.mBounds = aGeometry.mBounds.Intersect(aItem->GetBuildingRect());
+  }
+
   return !aGeometry.mBounds.IsEqualEdges(aData->mGeometry->mBounds);
 }
 
 struct DIGroup {
   // XXX: Storing owning pointers to the BlobItemData in a hash table is not
   // a good choice. There are two better options:
   //
   // 1. We should just be using a linked list for this stuff.
@@ -1005,18 +1011,20 @@ void Grouper::PaintContainerItem(DIGroup
       GP("Paint Filter\n");
       // Painting will cause us to include the item's recording in the blob. We
       // only want to do that if it is dirty, because otherwise the recording
       // might change (e.g. due to factor of 2 scaling of images giving
       // different results) and the merging will discard it because it is
       // outside the invalid rect.
       if (aDirty) {
         auto filterItem = static_cast<nsDisplayFilters*>(aItem);
-        filterItem->SetPaintRect(
-            filterItem->GetClippedBounds(mDisplayListBuilder));
+
+        nsRegion visible(aItem->GetClippedBounds(mDisplayListBuilder));
+        visible.And(visible, aItem->GetBuildingRect());
+        aItem->SetPaintRect(visible.GetBounds());
 
         filterItem->Paint(mDisplayListBuilder, aContext);
         TakeExternalSurfaces(aRecorder, aData->mExternalSurfaces, aRootManager,
                              aResources);
       }
       aContext->GetDrawTarget()->FlushItem(aItemBounds);
       break;
     }
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/filters/filter-giant.svg
@@ -0,0 +1,12 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%">
+<defs>
+<filter id="dropShadow" x="0" y="0" width="200%" height="200%">
+  <feOffset result="offOut" in="SourceAlpha" dx="1.5" dy="1.5"/>
+  <feGaussianBlur result="blurOut" in="offOut" stdDeviation="2"/>
+  <feBlend in="SourceGraphic" in2="blurOut" mode="normal"/>
+</filter>
+</defs>
+<g filter="url(#dropShadow)">
+  <rect x="-20000" y="-20000" width="40000" height="40000" fill="lime" />
+</g>
+</svg>
--- a/layout/reftests/svg/filters/reftest.list
+++ b/layout/reftests/svg/filters/reftest.list
@@ -134,8 +134,9 @@ fails-if(useDrawSnapshot) == fePointLigh
 fuzzy(0-1,0-10000) == feTurbulence-zero-baseFreq-01.svg feTurbulence-zero-baseFreq-01-ref.svg
 != feTurbulence-zero-baseFreq-02.svg about:blank
 
 == outside-sourcegraphic-1.svg outside-sourcegraphic-ref.svg
 # These failures are caused by bug 1586055
 fails-if(!useDrawSnapshot&&webrender) == outside-sourcegraphic-2.svg outside-sourcegraphic-ref.svg
 fails-if(!useDrawSnapshot&&webrender) == outside-sourcegraphic-3.svg outside-sourcegraphic-ref.svg
 == nested-filter.html nested-filter-ref.html
+== filter-giant.svg pass.svg