Backed out 2 changesets (bug 1520652) for build bustages on a CLOSED TREE
authorAndreea Pavel <apavel@mozilla.com>
Sat, 19 Jan 2019 05:36:54 +0200
changeset 454508 0553c4e622cfb2e2d536d2cddbbe2b156d642165
parent 454507 b9ca6790fee118cfb1611a9b3aafaab5c1a49443
child 454509 b86c22898543ba5cefed5b453af7ef46dcc1dfb5
push id35399
push usercsabou@mozilla.com
push dateSat, 19 Jan 2019 09:28:26 +0000
treeherdermozilla-central@64d167665c29 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1520652
milestone66.0a1
backs outb9ca6790fee118cfb1611a9b3aafaab5c1a49443
ebdc9e3d72c4a17a41be785f06832e9a1d0ee7cf
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
Backed out 2 changesets (bug 1520652) for build bustages on a CLOSED TREE Backed out changeset b9ca6790fee1 (bug 1520652) Backed out changeset ebdc9e3d72c4 (bug 1520652)
layout/painting/nsDisplayList.cpp
layout/reftests/svg/filters/css-filter-chains/reftest.list
layout/reftests/svg/filters/css-filters/blur-clip-rect.html
layout/reftests/svg/filters/css-filters/reftest.list
layout/reftests/svg/filters/css-svg-filter-chains/reftest.list
layout/svg/nsFilterInstance.cpp
layout/svg/nsFilterInstance.h
layout/svg/nsSVGIntegrationUtils.cpp
layout/svg/nsSVGIntegrationUtils.h
--- a/layout/painting/nsDisplayList.cpp
+++ b/layout/painting/nsDisplayList.cpp
@@ -9345,43 +9345,39 @@ bool nsDisplayFilters::CreateWebRenderCS
 }
 
 bool nsDisplayFilters::CreateWebRenderCommands(
     mozilla::wr::DisplayListBuilder& aBuilder,
     mozilla::wr::IpcResourceUpdateQueue& aResources,
     const StackingContextHelper& aSc,
     mozilla::layers::RenderRootStateManager* aManager,
     nsDisplayListBuilder* aDisplayListBuilder) {
+  bool snap;
   float auPerDevPixel = mFrame->PresContext()->AppUnitsPerDevPixel();
+  nsRect displayBounds = GetBounds(aDisplayListBuilder, &snap);
+  auto postFilterBounds = LayoutDeviceIntRect::Round(
+      LayoutDeviceRect::FromAppUnits(displayBounds, auPerDevPixel));
+  auto preFilterBounds = LayoutDeviceIntRect::Round(
+      LayoutDeviceRect::FromAppUnits(mBounds, auPerDevPixel));
 
   nsTArray<mozilla::wr::FilterOp> wrFilters;
-  Maybe<nsRect> filterClip;
   if (!CreateWebRenderCSSFilters(wrFilters) &&
-      !nsSVGIntegrationUtils::BuildWebRenderFilters(mFrame, wrFilters,
-                                                    filterClip)) {
+      !nsSVGIntegrationUtils::BuildWebRenderFilters(
+          mFrame, preFilterBounds, wrFilters, postFilterBounds)) {
     return false;
   }
 
-  wr::WrStackingContextClip clip;
-  if (filterClip) {
-    auto devPxRect = LayoutDeviceRect::FromAppUnits(
-        filterClip.value() + ToReferenceFrame(), auPerDevPixel);
-    wr::WrClipId clipId =
-        aBuilder.DefineClip(Nothing(), wr::ToRoundedLayoutRect(devPxRect));
-    clip = wr::WrStackingContextClip::ClipId(clipId);
-  } else {
-    clip = wr::WrStackingContextClip::ClipChain(aBuilder.CurrentClipChainId());
-  }
-
   float opacity = mFrame->StyleEffects()->mOpacity;
   StackingContextHelper sc(
       aSc, GetActiveScrolledRoot(), mFrame, this, aBuilder, wrFilters,
       LayoutDeviceRect(), nullptr, nullptr,
       opacity != 1.0f && mHandleOpacity ? &opacity : nullptr, nullptr,
-      gfx::CompositionOp::OP_OVER, true, false, Nothing(), clip);
+      wr::ReferenceFrameKind::Transform, gfx::CompositionOp::OP_OVER, true,
+      false, Nothing(),
+      wr::WrStackingContextClip::ClipChain(aBuilder.CurrentClipChainId()));
 
   nsDisplayEffectsBase::CreateWebRenderCommands(aBuilder, aResources, sc,
                                                 aManager, aDisplayListBuilder);
 
   return true;
 }
 
 #ifdef MOZ_DUMP_PAINTING
--- a/layout/reftests/svg/filters/css-filter-chains/reftest.list
+++ b/layout/reftests/svg/filters/css-filter-chains/reftest.list
@@ -1,7 +1,7 @@
 # These tests verify that CSS filter chains behave properly.
 # e.g. filter: blur(3px) grayscale(0.5) invert(0.2);
 
 # Some platforms render this complex filter chain a little differently, and that's ok.
-fuzzy(0-5,0-13638) fuzzy-if(/^Windows\x20NT\x2010\.0/.test(http.oscpu)&&layersGPUAccelerated,0-35,0-13638) fuzzy-if(webrender,4-6,12000-18946) == long-chain.html long-chain-ref.html # Win10: Bug 1258241
+fuzzy(0-5,0-13638) fuzzy-if(/^Windows\x20NT\x2010\.0/.test(http.oscpu)&&layersGPUAccelerated,0-35,0-13638) fuzzy-if(webrender,4-6,12000-18853) == long-chain.html long-chain-ref.html # Win10: Bug 1258241
 == moz-element.html moz-element-ref.html
-fuzzy-if(webrender,13-15,7682-7966) == same-filter.html same-filter-ref.html
+== same-filter.html same-filter-ref.html
deleted file mode 100644
--- a/layout/reftests/svg/filters/css-filters/blur-clip-rect.html
+++ /dev/null
@@ -1,33 +0,0 @@
-<!DOCTYPE html>
-<html>
-  <title>CSS Filters: Blur an HTML Element and clip to the blur rect</title>
-  <style type="text/css">
-    #target {
-      filter: url(#blur);
-      width: 400px;
-      height: 400px;
-    }
-    #inner {
-      position: relative;
-      left: 100px;
-      top: 100px;
-      width: 100px;
-      height: 100px;
-      background-color: #00ff00;
-    }
-    body {
-      margin: 0px;
-    }
-  </style>
-</head>
-<body>
-  <div id="target">
-    <div id="inner"></div>
-  </div>
-  <svg width="0" height="0">
-    <filter id="blur" filterUnits="userSpaceOnUse" primitiveUnits="userSpaceOnUse">
-      <feGaussianBlur in="SourceGraphic" stdDeviation="10" result="blur" x="100" y="100" width="100" height="100"/>
-    </filter>
-  </svg>
-</body>
-</html>
--- a/layout/reftests/svg/filters/css-filters/reftest.list
+++ b/layout/reftests/svg/filters/css-filters/reftest.list
@@ -1,17 +1,16 @@
 # These tests verify that CSS filters behave properly.
 # e.g. filter: blur(3px)
 
 == blur.html blur-ref.html
 == blur.svg blur-ref.svg
 == blur-calc.html blur-calc-ref.html
 == blur-calc-negative.html blur-calc-negative-ref.html
 fuzzy-if(cocoaWidget&&webrender,0-1,0-2) skip-if(d2d) == blur-cap-large-radius-on-software.html blur-cap-large-radius-on-software-ref.html
-fuzzy-if(webrender,3-4,5760-6424) == blur-clip-rect.html ../feGaussianBlur-4-ref.svg
 == blur-em-radius.html blur-em-radius-ref.html
 == blur-invalid-radius.html blur-invalid-radius-ref.html
 == blur-rem-radius.html blur-rem-radius-ref.html
 == blur-zero-radius.html blur-zero-radius-ref.html
 == blur-zoomed-page.html blur-zoomed-page-ref.html
 == brightness.html brightness-ref.html
 == brightness-darken.html brightness-darken-ref.html
 == brightness-extreme.html brightness-extreme-ref.html
--- a/layout/reftests/svg/filters/css-svg-filter-chains/reftest.list
+++ b/layout/reftests/svg/filters/css-svg-filter-chains/reftest.list
@@ -1,8 +1,8 @@
 # These tests verify that filter chains of combined CSS and SVG filters behave
 # properly.
 # e.g. filter: url(#f1) blur(3px) url(#2) grayscale(0.5);
 
 == clip-input-css-filter.html clip-input-css-filter-ref.html
-fuzzy-if(webrender,0-1,0-288) == css-filter-first.html css-filter-first-ref.html
+== css-filter-first.html css-filter-first-ref.html
 == css-filter-last.html css-filter-last-ref.html
 == css-filter-middle.html css-filter-middle-ref.html
--- a/layout/svg/nsFilterInstance.cpp
+++ b/layout/svg/nsFilterInstance.cpp
@@ -88,19 +88,20 @@ void nsFilterInstance::PaintFilteredFram
                             *metrics, filterChain, /* InputIsTainted */ true,
                             aPaintCallback, scaleMatrixInDevUnits, aDirtyArea,
                             nullptr, nullptr, nullptr);
   if (instance.IsInitialized()) {
     instance.Render(aCtx, aImgParams, aOpacity);
   }
 }
 
-bool nsFilterInstance::BuildWebRenderFilters(nsIFrame* aFilteredFrame,
-                                             nsTArray<wr::FilterOp>& aWrFilters,
-                                             Maybe<nsRect>& aPostFilterClip) {
+bool nsFilterInstance::BuildWebRenderFilters(
+    nsIFrame* aFilteredFrame, const LayoutDeviceIntRect& aPreFilterBounds,
+    nsTArray<wr::FilterOp>& aWrFilters,
+    LayoutDeviceIntRect& aPostFilterBounds) {
   aWrFilters.Clear();
 
   auto& filterChain = aFilteredFrame->StyleEffects()->mFilters;
   UniquePtr<UserSpaceMetrics> metrics =
       UserSpaceMetricsForFrame(aFilteredFrame);
 
   // TODO: simply using an identity matrix here, was pulling the scale from a
   // gfx context for the non-wr path.
@@ -115,38 +116,68 @@ bool nsFilterInstance::BuildWebRenderFil
                             *metrics, filterChain, inputIsTainted, nullptr,
                             scaleMatrixInDevUnits, nullptr, nullptr, nullptr,
                             nullptr);
 
   if (!instance.IsInitialized()) {
     return false;
   }
 
-  Maybe<IntRect> finalClip;
+  Maybe<LayoutDeviceIntRect> finalClip;
   bool srgb = true;
   // We currently apply the clip on the stacking context after applying filters,
   // but primitive subregions imply clipping after each filter and not just the
   // end of the chain. For some types of filter it doesn't matter, but for those
   // which sample outside of the location of the destination pixel like blurs,
   // only clipping after could produce incorrect results, so we bail out in this
   // case.
   // We can lift this restriction once we have added support for primitive
   // subregions to WebRender's filters.
 
+  // During the loop this tracks whether any of the previous filters in the
+  // chain affected by the primitive subregion.
+  bool chainIsAffectedByPrimSubregion = false;
+  // During the loop this tracks whether the current filter is affected by the
+  // primitive subregion.
+  bool filterIsAffectedByPrimSubregion = false;
+
   for (const auto& primitive : instance.mFilterDescription.mPrimitives) {
+    chainIsAffectedByPrimSubregion |= filterIsAffectedByPrimSubregion;
+    filterIsAffectedByPrimSubregion = false;
+
     bool primIsSrgb = primitive.OutputColorSpace() == gfx::ColorSpace::SRGB;
     if (srgb && !primIsSrgb) {
       aWrFilters.AppendElement(wr::FilterOp::SrgbToLinear());
       srgb = false;
     } else if (!srgb && primIsSrgb) {
       aWrFilters.AppendElement(wr::FilterOp::LinearToSrgb());
       srgb = true;
     }
 
     const PrimitiveAttributes& attr = primitive.Attributes();
+    auto subregion = LayoutDeviceIntRect::FromUnknownRect(
+        primitive.PrimitiveSubregion() +
+        aPreFilterBounds.TopLeft().ToUnknownPoint());
+
+    if (!subregion.Contains(aPreFilterBounds)) {
+      if (!aPostFilterBounds.Contains(subregion)) {
+        filterIsAffectedByPrimSubregion = true;
+      }
+
+      subregion = subregion.Intersect(aPostFilterBounds);
+
+      if (finalClip.isNothing()) {
+        finalClip = Some(subregion);
+      } else if (!subregion.IsEqualEdges(finalClip.value())) {
+        // We don't currently support rendering a chain of filters with
+        // different primitive subregions in WebRender so bail out in that
+        // situation.
+        return false;
+      }
+    }
 
     bool filterIsNoop = false;
 
     if (attr.is<OpacityAttributes>()) {
       float opacity = attr.as<OpacityAttributes>().mOpacity;
       aWrFilters.AppendElement(wr::FilterOp::Opacity(
           wr::PropertyBinding<float>::Value(opacity), opacity));
     } else if (attr.is<ColorMatrixAttributes>()) {
@@ -177,17 +208,17 @@ bool nsFilterInstance::BuildWebRenderFil
           transposed[0], transposed[5], transposed[10], transposed[15],
           transposed[1], transposed[6], transposed[11], transposed[16],
           transposed[2], transposed[7], transposed[12], transposed[17],
           transposed[3], transposed[8], transposed[13], transposed[18],
           transposed[4], transposed[9], transposed[14], transposed[19]};
 
       aWrFilters.AppendElement(wr::FilterOp::ColorMatrix(matrix));
     } else if (attr.is<GaussianBlurAttributes>()) {
-      if (finalClip) {
+      if (chainIsAffectedByPrimSubregion) {
         // There's a clip that needs to apply before the blur filter, but
         // WebRender only lets us apply the clip at the end of the filter
         // chain. Clipping after a blur is not equivalent to clipping before
         // a blur, so bail out.
         return false;
       }
 
       const GaussianBlurAttributes& blur = attr.as<GaussianBlurAttributes>();
@@ -199,17 +230,17 @@ bool nsFilterInstance::BuildWebRenderFil
 
       float radius = stdDev.width;
       if (radius != 0.0) {
         aWrFilters.AppendElement(wr::FilterOp::Blur(radius));
       } else {
         filterIsNoop = true;
       }
     } else if (attr.is<DropShadowAttributes>()) {
-      if (finalClip) {
+      if (chainIsAffectedByPrimSubregion) {
         // We have to bail out for the same reason we would with a blur filter.
         return false;
       }
 
       const DropShadowAttributes& shadow = attr.as<DropShadowAttributes>();
 
       const Size& stdDev = shadow.mStdDeviation;
       if (stdDev.width != stdDev.height) {
@@ -235,34 +266,28 @@ bool nsFilterInstance::BuildWebRenderFil
       // unnecessary. Remove it from the filter list.
       // This is both an optimization and a way to pass the wptest
       // css/filter-effects/filter-scale-001.html for which the needless
       // sRGB->linear->no-op->sRGB roundtrip introduces a slight error and we
       // cannot add fuzziness to the test.
       Unused << aWrFilters.PopLastElement();
       srgb = !srgb;
     }
-
-    if (!filterIsNoop) {
-      if (finalClip.isNothing()) {
-        finalClip = Some(primitive.PrimitiveSubregion());
-      } else {
-        finalClip =
-            Some(primitive.PrimitiveSubregion().Intersect(finalClip.value()));
-      }
-    }
   }
 
   if (!srgb) {
     aWrFilters.AppendElement(wr::FilterOp::LinearToSrgb());
   }
 
-  if (finalClip) {
-    aPostFilterClip = Some(instance.FilterSpaceToFrameSpace(finalClip.value()));
+  // Only adjust the post filter clip if we are able to render this without
+  // fallback.
+  if (finalClip.isSome()) {
+    aPostFilterBounds = finalClip.value();
   }
+
   return true;
 }
 
 nsRegion nsFilterInstance::GetPostFilterDirtyArea(
     nsIFrame* aFilteredFrame, const nsRegion& aPreFilterDirtyRegion) {
   if (aPreFilterDirtyRegion.IsEmpty()) {
     return nsRegion();
   }
--- a/layout/svg/nsFilterInstance.h
+++ b/layout/svg/nsFilterInstance.h
@@ -117,19 +117,21 @@ class nsFilterInstance {
   static nsRect GetPostFilterBounds(nsIFrame* aFilteredFrame,
                                     const gfxRect* aOverrideBBox = nullptr,
                                     const nsRect* aPreFilterBounds = nullptr);
 
   /**
    * Try to build WebRender filters for a frame if the filters applied to it are
    * supported.
    */
-  static bool BuildWebRenderFilters(nsIFrame* aFilteredFrame,
-                                    nsTArray<mozilla::wr::FilterOp>& aWrFilters,
-                                    mozilla::Maybe<nsRect>& aPostFilterClip);
+  static bool BuildWebRenderFilters(
+      nsIFrame* aFilteredFrame,
+      const mozilla::LayoutDeviceIntRect& aPreFilterBounds,
+      nsTArray<mozilla::wr::FilterOp>& aWrFilters,
+      mozilla::LayoutDeviceIntRect& aPostFilterBounds);
 
  private:
   /**
    * @param aTargetFrame The frame of the filtered element under consideration,
    *   may be null.
    * @param aTargetContent The filtered element itself.
    * @param aMetrics The metrics to resolve SVG lengths against.
    * @param aFilterChain The list of filters to apply.
--- a/layout/svg/nsSVGIntegrationUtils.cpp
+++ b/layout/svg/nsSVGIntegrationUtils.cpp
@@ -1081,20 +1081,22 @@ void nsSVGIntegrationUtils::PaintFilter(
                                      offsets.offsetToUserSpaceInDevPx);
   nsRegion dirtyRegion = aParams.dirtyRect - offsets.offsetToBoundingBox;
 
   nsFilterInstance::PaintFilteredFrame(frame, &context, &callback, &dirtyRegion,
                                        aParams.imgParams, opacity);
 }
 
 bool nsSVGIntegrationUtils::BuildWebRenderFilters(
-    nsIFrame* aFilteredFrame, nsTArray<mozilla::wr::FilterOp>& aWrFilters,
-    Maybe<nsRect>& aPostFilterClip) {
-  return nsFilterInstance::BuildWebRenderFilters(aFilteredFrame, aWrFilters,
-                                                 aPostFilterClip);
+    nsIFrame* aFilteredFrame,
+    const mozilla::LayoutDeviceIntRect& aPreFilterBounds,
+    nsTArray<mozilla::wr::FilterOp>& aWrFilters,
+    mozilla::LayoutDeviceIntRect& aPostFilterBounds) {
+  return nsFilterInstance::BuildWebRenderFilters(
+      aFilteredFrame, aPreFilterBounds, aWrFilters, aPostFilterBounds);
 }
 
 class PaintFrameCallback : public gfxDrawingCallback {
  public:
   PaintFrameCallback(nsIFrame* aFrame, const nsSize aPaintServerSize,
                      const IntSize aRenderSize, uint32_t aFlags)
       : mFrame(aFrame),
         mPaintServerSize(aPaintServerSize),
--- a/layout/svg/nsSVGIntegrationUtils.h
+++ b/layout/svg/nsSVGIntegrationUtils.h
@@ -190,19 +190,21 @@ class nsSVGIntegrationUtils final {
    * Paint non-SVG frame with filter and opacity effect.
    */
   static void PaintFilter(const PaintFramesParams& aParams);
 
   /**
    * Try to build WebRender filters for a frame if the filters applied to it are
    * supported.
    */
-  static bool BuildWebRenderFilters(nsIFrame* aFilteredFrame,
-                                    nsTArray<mozilla::wr::FilterOp>& aWrFilters,
-                                    mozilla::Maybe<nsRect>& aPostFilterClip);
+  static bool BuildWebRenderFilters(
+      nsIFrame* aFilteredFrame,
+      const mozilla::LayoutDeviceIntRect& aPreFilterBounds,
+      nsTArray<mozilla::wr::FilterOp>& aWrFilters,
+      mozilla::LayoutDeviceIntRect& aPostFilterBounds);
 
   /**
    * @param aRenderingContext the target rendering context in which the paint
    * server will be rendered
    * @param aTarget the target frame onto which the paint server will be
    * rendered
    * @param aPaintServer a first-continuation frame to use as the source
    * @param aFilter a filter to be applied when scaling