Back out bug 1148582 for static analysis bustage.
authorMarkus Stange <mstange@themasta.com>
Wed, 01 Jul 2015 01:20:59 -0400
changeset 497484 c6920f5c41fdc38e44d73e2ed8ee3268fe608786
parent 497483 5a3396411829a084c25e3a3eee8ef88435e94e6c
child 497485 fa9904c62103cacf7b9a5b5b2262ad77e226bd1c
push id76451
push userkdavis@mozilla.com
push dateWed, 01 Jul 2015 08:13:15 +0000
treeherdertry@29cc1c4473a2 [default view] [failures only]
bugs1148582
milestone42.0a1
Back out bug 1148582 for static analysis bustage.
gfx/ipc/GfxMessageUtils.h
gfx/layers/FrameMetrics.h
gfx/layers/ImageLayers.cpp
gfx/layers/LayerTreeInvalidation.cpp
gfx/layers/Layers.cpp
gfx/layers/Layers.h
gfx/layers/ReadbackProcessor.cpp
gfx/layers/apz/src/AsyncPanZoomController.cpp
gfx/layers/basic/BasicContainerLayer.cpp
gfx/layers/basic/BasicPaintedLayer.h
gfx/layers/client/ClientCanvasLayer.cpp
gfx/layers/client/ClientColorLayer.cpp
gfx/layers/client/ClientContainerLayer.h
gfx/layers/client/ClientImageLayer.cpp
gfx/layers/client/ClientLayerManager.h
gfx/layers/client/ClientPaintedLayer.cpp
gfx/layers/client/ClientTiledPaintedLayer.cpp
gfx/layers/composite/AsyncCompositionManager.cpp
gfx/layers/composite/CanvasLayerComposite.cpp
gfx/layers/composite/ColorLayerComposite.cpp
gfx/layers/composite/ContainerLayerComposite.cpp
gfx/layers/composite/ImageLayerComposite.cpp
gfx/layers/composite/LayerManagerComposite.cpp
gfx/layers/composite/LayerManagerComposite.h
gfx/layers/composite/PaintedLayerComposite.cpp
gfx/layers/ipc/CompositorParent.cpp
gfx/layers/ipc/LayerTransactionParent.cpp
gfx/layers/ipc/LayersMessages.ipdlh
gfx/layers/ipc/ShadowLayers.cpp
layout/base/FrameLayerBuilder.cpp
layout/generic/nsGfxScrollFrame.cpp
layout/generic/nsGfxScrollFrame.h
layout/generic/nsIScrollableFrame.h
--- a/gfx/ipc/GfxMessageUtils.h
+++ b/gfx/ipc/GfxMessageUtils.h
@@ -728,17 +728,16 @@ struct ParamTraits<mozilla::layers::Fram
     WriteParam(aMsg, aParam.mExtraResolution);
     WriteParam(aMsg, aParam.mBackgroundColor);
     WriteParam(aMsg, aParam.mDoSmoothScroll);
     WriteParam(aMsg, aParam.mSmoothScrollOffset);
     WriteParam(aMsg, aParam.GetLineScrollAmount());
     WriteParam(aMsg, aParam.GetPageScrollAmount());
     WriteParam(aMsg, aParam.AllowVerticalScrollWithWheel());
     WriteParam(aMsg, aParam.mClipRect);
-    WriteParam(aMsg, aParam.mMaskLayerIndex);
     WriteParam(aMsg, aParam.mIsLayersIdRoot);
     WriteParam(aMsg, aParam.mUsesContainerScrolling);
     WriteParam(aMsg, aParam.GetContentDescription());
   }
 
   static bool ReadContentDescription(const Message* aMsg, void** aIter, paramType* aResult)
   {
     nsCString str;
@@ -774,17 +773,16 @@ struct ParamTraits<mozilla::layers::Fram
             ReadParam(aMsg, aIter, &aResult->mExtraResolution) &&
             ReadParam(aMsg, aIter, &aResult->mBackgroundColor) &&
             ReadParam(aMsg, aIter, &aResult->mDoSmoothScroll) &&
             ReadParam(aMsg, aIter, &aResult->mSmoothScrollOffset) &&
             ReadParam(aMsg, aIter, &aResult->mLineScrollAmount) &&
             ReadParam(aMsg, aIter, &aResult->mPageScrollAmount) &&
             ReadParam(aMsg, aIter, &aResult->mAllowVerticalScrollWithWheel) &&
             ReadParam(aMsg, aIter, &aResult->mClipRect) &&
-            ReadParam(aMsg, aIter, &aResult->mMaskLayerIndex) &&
             ReadParam(aMsg, aIter, &aResult->mIsLayersIdRoot) &&
             ReadParam(aMsg, aIter, &aResult->mUsesContainerScrolling) &&
             ReadContentDescription(aMsg, aIter, aResult));
   }
 };
 
 template<>
 struct ParamTraits<mozilla::layers::TextureFactoryIdentifier>
--- a/gfx/layers/FrameMetrics.h
+++ b/gfx/layers/FrameMetrics.h
@@ -99,17 +99,16 @@ public:
            mScrollGeneration == aOther.mScrollGeneration &&
            mExtraResolution == aOther.mExtraResolution &&
            mBackgroundColor == aOther.mBackgroundColor &&
            mDoSmoothScroll == aOther.mDoSmoothScroll &&
            mLineScrollAmount == aOther.mLineScrollAmount &&
            mPageScrollAmount == aOther.mPageScrollAmount &&
            mAllowVerticalScrollWithWheel == aOther.mAllowVerticalScrollWithWheel &&
            mClipRect == aOther.mClipRect &&
-           mMaskLayerIndex == aOther.mMaskLayerIndex &&
            mIsLayersIdRoot == aOther.mIsLayersIdRoot &&
 		   mUsesContainerScrolling == aOther.mUsesContainerScrolling;
   }
   bool operator!=(const FrameMetrics& aOther) const
   {
     return !operator==(aOther);
   }
 
@@ -521,23 +520,16 @@ public:
   }
   bool HasClipRect() const {
     return mClipRect.isSome();
   }
   const ParentLayerIntRect& ClipRect() const {
     return mClipRect.ref();
   }
 
-  void SetMaskLayerIndex(const Maybe<size_t>& aIndex) {
-    mMaskLayerIndex = aIndex;
-  }
-  const Maybe<size_t>& GetMaskLayerIndex() const {
-    return mMaskLayerIndex;
-  }
-
   void SetIsLayersIdRoot(bool aValue) {
     mIsLayersIdRoot = aValue;
   }
   bool IsLayersIdRoot() const {
     return mIsLayersIdRoot;
   }
 
   void SetUsesContainerScrolling(bool aValue) {
@@ -717,21 +709,16 @@ private:
   LayoutDeviceIntSize mPageScrollAmount;
 
   // Whether or not the frame can be vertically scrolled with a mouse wheel.
   bool mAllowVerticalScrollWithWheel;
 
   // The clip rect to use when compositing a layer with this FrameMetrics.
   Maybe<ParentLayerIntRect> mClipRect;
 
-  // An extra clip mask layer to use when compositing a layer with this
-  // FrameMetrics. This is an index into the MetricsMaskLayers array on
-  // the Layer.
-  Maybe<size_t> mMaskLayerIndex;
-
   // Whether these framemetrics are for the root scroll frame (root element if
   // we don't have a root scroll frame) for its layers id.
   bool mIsLayersIdRoot;
 
   // True if scrolling using containers, false otherwise. This can be removed
   // when containerful scrolling is eliminated.
   bool mUsesContainerScrolling;
 
--- a/gfx/layers/ImageLayers.cpp
+++ b/gfx/layers/ImageLayers.cpp
@@ -52,13 +52,13 @@ void ImageLayer::ComputeEffectiveTransfo
 
     mEffectiveTransformForBuffer =
         SnapTransform(local, sourceRect, nullptr) *
         SnapTransformTranslation(aTransformToSurface, nullptr);
   } else {
     mEffectiveTransformForBuffer = mEffectiveTransform;
   }
 
-  ComputeEffectiveTransformForMaskLayers(aTransformToSurface);
+  ComputeEffectiveTransformForMaskLayer(aTransformToSurface);
 }
 
 }
 }
--- a/gfx/layers/LayerTreeInvalidation.cpp
+++ b/gfx/layers/LayerTreeInvalidation.cpp
@@ -78,20 +78,16 @@ static void
 NotifySubdocumentInvalidationRecursive(Layer* aLayer, NotifySubDocInvalidationFunc aCallback)
 {
   aLayer->ClearInvalidRect();
   ContainerLayer* container = aLayer->AsContainerLayer();
 
   if (aLayer->GetMaskLayer()) {
     NotifySubdocumentInvalidationRecursive(aLayer->GetMaskLayer(), aCallback);
   }
-  for (size_t i = 0; i < aLayer->GetAncestorMaskLayerCount(); i++) {
-    Layer* maskLayer = aLayer->GetAncestorMaskLayerAt(i);
-    NotifySubdocumentInvalidationRecursive(maskLayer, aCallback);
-  }
 
   if (!container) {
     return;
   }
 
   for (Layer* child = container->GetFirstChild(); child; child = child->GetNextSibling()) {
     NotifySubdocumentInvalidationRecursive(child, aCallback);
   }
@@ -110,20 +106,16 @@ struct LayerPropertiesBase : public Laye
     , mPostYScale(aLayer->GetPostYScale())
     , mOpacity(aLayer->GetLocalOpacity())
     , mUseClipRect(!!aLayer->GetClipRect())
   {
     MOZ_COUNT_CTOR(LayerPropertiesBase);
     if (aLayer->GetMaskLayer()) {
       mMaskLayer = CloneLayerTreePropertiesInternal(aLayer->GetMaskLayer(), true);
     }
-    for (size_t i = 0; i < aLayer->GetAncestorMaskLayerCount(); i++) {
-      Layer* maskLayer = aLayer->GetAncestorMaskLayerAt(i);
-      mAncestorMaskLayers.AppendElement(CloneLayerTreePropertiesInternal(maskLayer, true));
-    }
     if (mUseClipRect) {
       mClipRect = *aLayer->GetClipRect();
     }
     mTransform = aLayer->GetLocalTransform();
   }
   LayerPropertiesBase()
     : mLayer(nullptr)
     , mMaskLayer(nullptr)
@@ -142,32 +134,20 @@ struct LayerPropertiesBase : public Laye
   virtual void MoveBy(const IntPoint& aOffset);
 
   nsIntRegion ComputeChange(NotifySubDocInvalidationFunc aCallback,
                             bool& aGeometryChanged)
   {
     bool transformChanged = !mTransform.FuzzyEqualsMultiplicative(mLayer->GetLocalTransform()) ||
                             mLayer->GetPostXScale() != mPostXScale ||
                             mLayer->GetPostYScale() != mPostYScale;
+    Layer* otherMask = mLayer->GetMaskLayer();
     const Maybe<ParentLayerIntRect>& otherClip = mLayer->GetClipRect();
     nsIntRegion result;
-
-    bool ancestorMaskChanged = mAncestorMaskLayers.Length() != mLayer->GetAncestorMaskLayerCount();
-    if (!ancestorMaskChanged) {
-      for (size_t i = 0; i < mAncestorMaskLayers.Length(); i++) {
-        if (mLayer->GetAncestorMaskLayerAt(i) != mAncestorMaskLayers[i]->mLayer) {
-          ancestorMaskChanged = true;
-          break;
-        }
-      }
-    }
-
-    Layer* otherMask = mLayer->GetMaskLayer();
     if ((mMaskLayer ? mMaskLayer->mLayer : nullptr) != otherMask ||
-        ancestorMaskChanged ||
         (mUseClipRect != !!otherClip) ||
         mLayer->GetLocalOpacity() != mOpacity ||
         transformChanged) 
     {
       aGeometryChanged = true;
       result = OldTransformedBounds();
       AddRegion(result, NewTransformedBounds());
 
@@ -177,25 +157,16 @@ struct LayerPropertiesBase : public Laye
     AddRegion(result, ComputeChangeInternal(aCallback, aGeometryChanged));
     AddTransformedRegion(result, mLayer->GetInvalidRegion(), mTransform);
 
     if (mMaskLayer && otherMask) {
       AddTransformedRegion(result, mMaskLayer->ComputeChange(aCallback, aGeometryChanged),
                            mTransform);
     }
 
-    for (size_t i = 0;
-         i < std::min(mAncestorMaskLayers.Length(), mLayer->GetAncestorMaskLayerCount());
-         i++)
-    {
-      AddTransformedRegion(result,
-                           mAncestorMaskLayers[i]->ComputeChange(aCallback, aGeometryChanged),
-                           mTransform);
-    }
-
     if (mUseClipRect && otherClip) {
       if (!mClipRect.IsEqualInterior(*otherClip)) {
         aGeometryChanged = true;
         nsIntRegion tmp; 
         tmp.Xor(ParentLayerIntRect::ToUntyped(mClipRect), ParentLayerIntRect::ToUntyped(*otherClip)); 
         AddRegion(result, tmp);
       }
     }
@@ -217,17 +188,16 @@ struct LayerPropertiesBase : public Laye
   virtual nsIntRegion ComputeChangeInternal(NotifySubDocInvalidationFunc aCallback,
                                             bool& aGeometryChanged)
   {
     return IntRect();
   }
 
   nsRefPtr<Layer> mLayer;
   UniquePtr<LayerPropertiesBase> mMaskLayer;
-  nsTArray<UniquePtr<LayerPropertiesBase>> mAncestorMaskLayers;
   nsIntRegion mVisibleRegion;
   nsIntRegion mInvalidRegion;
   Matrix4x4 mTransform;
   float mPostXScale;
   float mPostYScale;
   float mOpacity;
   ParentLayerIntRect mClipRect;
   bool mUseClipRect;
@@ -468,19 +438,16 @@ LayerProperties::CloneFrom(Layer* aRoot)
 
 /* static */ void 
 LayerProperties::ClearInvalidations(Layer *aLayer)
 {
   aLayer->ClearInvalidRect();
   if (aLayer->GetMaskLayer()) {
     ClearInvalidations(aLayer->GetMaskLayer());
   }
-  for (size_t i = 0; i < aLayer->GetAncestorMaskLayerCount(); i++) {
-    ClearInvalidations(aLayer->GetAncestorMaskLayerAt(i));
-  }
 
   ContainerLayer* container = aLayer->AsContainerLayer();
   if (!container) {
     return;
   }
 
   for (Layer* child = container->GetFirstChild(); child; child = child->GetNextSibling()) {
     ClearInvalidations(child);
--- a/gfx/layers/Layers.cpp
+++ b/gfx/layers/Layers.cpp
@@ -852,41 +852,31 @@ Layer::GetEffectiveMixBlendMode()
 
 gfxContext::GraphicsOperator
 Layer::DeprecatedGetEffectiveMixBlendMode()
 {
   return ThebesOp(GetEffectiveMixBlendMode());
 }
 
 void
-Layer::ComputeEffectiveTransformForMaskLayers(const gfx::Matrix4x4& aTransformToSurface)
+Layer::ComputeEffectiveTransformForMaskLayer(const Matrix4x4& aTransformToSurface)
 {
-  if (GetMaskLayer()) {
-    ComputeEffectiveTransformForMaskLayer(GetMaskLayer(), aTransformToSurface);
-  }
-  for (size_t i = 0; i < GetAncestorMaskLayerCount(); i++) {
-    Layer* maskLayer = GetAncestorMaskLayerAt(i);
-    ComputeEffectiveTransformForMaskLayer(maskLayer, aTransformToSurface);
-  }
-}
-
-/* static */ void
-Layer::ComputeEffectiveTransformForMaskLayer(Layer* aMaskLayer, const gfx::Matrix4x4& aTransformToSurface)
-{
-  aMaskLayer->mEffectiveTransform = aTransformToSurface;
+  if (mMaskLayer) {
+    mMaskLayer->mEffectiveTransform = aTransformToSurface;
 
 #ifdef DEBUG
-  bool maskIs2D = aMaskLayer->GetTransform().CanDraw2D();
-  NS_ASSERTION(maskIs2D, "How did we end up with a 3D transform here?!");
+    bool maskIs2D = mMaskLayer->GetTransform().CanDraw2D();
+    NS_ASSERTION(maskIs2D, "How did we end up with a 3D transform here?!");
 #endif
-  // The mask layer can have an async transform applied to it in some
-  // situations, so be sure to use its GetLocalTransform() rather than
-  // its GetTransform().
-  aMaskLayer->mEffectiveTransform = aMaskLayer->GetLocalTransform() *
-    aMaskLayer->mEffectiveTransform;
+    // The mask layer can have an async transform applied to it in some
+    // situations, so be sure to use its GetLocalTransform() rather than
+    // its GetTransform().
+    mMaskLayer->mEffectiveTransform = mMaskLayer->GetLocalTransform() *
+      mMaskLayer->mEffectiveTransform;
+  }
 }
 
 RenderTargetRect
 Layer::TransformRectToRenderTarget(const LayerIntRect& aRect)
 {
   LayerRect rect(aRect);
   RenderTargetRect quad = RenderTargetRect::FromUnknown(
     GetEffectiveTransform().TransformBounds(
@@ -1195,17 +1185,17 @@ void
 ContainerLayer::DefaultComputeEffectiveTransforms(const Matrix4x4& aTransformToSurface)
 {
   Matrix residual;
   Matrix4x4 idealTransform = GetLocalTransform() * aTransformToSurface;
   idealTransform.ProjectTo2D();
   mEffectiveTransform = SnapTransformTranslation(idealTransform, &residual);
 
   bool useIntermediateSurface;
-  if (HasMaskLayers() ||
+  if (GetMaskLayer() ||
       GetForceIsolatedGroup()) {
     useIntermediateSurface = true;
 #ifdef MOZ_DUMP_PAINTING
   } else if (gfxUtils::sDumpPaintingIntermediate) {
     useIntermediateSurface = true;
 #endif
   } else {
     float opacity = GetEffectiveOpacity();
@@ -1224,36 +1214,36 @@ ContainerLayer::DefaultComputeEffectiveT
         for (Layer* child = GetFirstChild(); child; child = child->GetNextSibling()) {
           const Maybe<ParentLayerIntRect>& clipRect = child->GetEffectiveClipRect();
           /* We can't (easily) forward our transform to children with a non-empty clip
            * rect since it would need to be adjusted for the transform. See
            * the calculations performed by CalculateScissorRect above.
            * Nor for a child with a mask layer.
            */
           if ((clipRect && !clipRect->IsEmpty() && !child->GetVisibleRegion().IsEmpty()) ||
-              child->HasMaskLayers()) {
+              child->GetMaskLayer()) {
             useIntermediateSurface = true;
             break;
           }
         }
       }
     }
   }
 
   mUseIntermediateSurface = useIntermediateSurface && !GetEffectiveVisibleRegion().IsEmpty();
   if (useIntermediateSurface) {
     ComputeEffectiveTransformsForChildren(Matrix4x4::From2D(residual));
   } else {
     ComputeEffectiveTransformsForChildren(idealTransform);
   }
 
   if (idealTransform.CanDraw2D()) {
-    ComputeEffectiveTransformForMaskLayers(aTransformToSurface);
+    ComputeEffectiveTransformForMaskLayer(aTransformToSurface);
   } else {
-    ComputeEffectiveTransformForMaskLayers(Matrix4x4());
+    ComputeEffectiveTransformForMaskLayer(Matrix4x4());
   }
 }
 
 void
 ContainerLayer::DefaultComputeSupportsComponentAlphaChildren(bool* aNeedsSurfaceCopy)
 {
   if (!(GetContentFlags() & Layer::CONTENT_COMPONENT_ALPHA_DESCENDANT) ||
       !Manager()->AreComponentAlphaLayersEnabled()) {
@@ -1526,23 +1516,16 @@ Layer::Dump(std::stringstream& aStream, 
 
   if (Layer* mask = GetMaskLayer()) {
     aStream << nsPrintfCString("%s  Mask layer:\n", aPrefix).get();
     nsAutoCString pfx(aPrefix);
     pfx += "    ";
     mask->Dump(aStream, pfx.get(), aDumpHtml);
   }
 
-  for (size_t i = 0; i < GetAncestorMaskLayerCount(); i++) {
-    aStream << nsPrintfCString("%s  Ancestor mask layer %d:\n", aPrefix, uint32_t(i)).get();
-    nsAutoCString pfx(aPrefix);
-    pfx += "    ";
-    GetAncestorMaskLayerAt(i)->Dump(aStream, pfx.get(), aDumpHtml);
-  }
-
 #ifdef MOZ_DUMP_PAINTING
   for (size_t i = 0; i < mExtraDumpInfo.Length(); i++) {
     const nsCString& str = mExtraDumpInfo[i];
     aStream << aPrefix << "  Info:\n" << str.get();
   }
 #endif
 
   if (Layer* kid = GetFirstChild()) {
--- a/gfx/layers/Layers.h
+++ b/gfx/layers/Layers.h
@@ -1055,28 +1055,16 @@ public:
       MOZ_LAYERS_LOG_IF_SHADOWABLE(this, ("Layer::Mutated(%p) MaskLayer", this));
       mMaskLayer = aMaskLayer;
       Mutated();
     }
   }
 
   /**
    * CONSTRUCTION PHASE ONLY
-   * Add a FrameMetrics-associated mask layer.
-   */
-  void SetAncestorMaskLayers(const nsTArray<nsRefPtr<Layer>>& aLayers) {
-    if (aLayers != mAncestorMaskLayers) {
-      MOZ_LAYERS_LOG_IF_SHADOWABLE(this, ("Layer::Mutated(%p) AncestorMaskLayers", this));
-      mAncestorMaskLayers = aLayers;
-      Mutated();
-    }
-  }
-
-  /**
-   * CONSTRUCTION PHASE ONLY
    * Tell this layer what its transform should be. The transformation
    * is applied when compositing the layer into its parent container.
    */
   void SetBaseTransform(const gfx::Matrix4x4& aMatrix)
   {
     NS_ASSERTION(!aMatrix.IsSingular(),
                  "Shouldn't be trying to draw with a singular matrix!");
     mPendingTransform = nullptr;
@@ -1278,29 +1266,16 @@ public:
   const LayerRect& GetStickyScrollRangeOuter() { return mStickyPositionData->mOuter; }
   const LayerRect& GetStickyScrollRangeInner() { return mStickyPositionData->mInner; }
   FrameMetrics::ViewID GetScrollbarTargetContainerId() { return mScrollbarTargetId; }
   ScrollDirection GetScrollbarDirection() { return mScrollbarDirection; }
   float GetScrollbarThumbRatio() { return mScrollbarThumbRatio; }
   bool IsScrollbarContainer() { return mIsScrollbarContainer; }
   Layer* GetMaskLayer() const { return mMaskLayer; }
 
-  // Ancestor mask layers are associated with FrameMetrics, but for simplicity
-  // in maintaining the layer tree structure we attach them to the layer.
-  size_t GetAncestorMaskLayerCount() const {
-    return mAncestorMaskLayers.Length();
-  }
-  Layer* GetAncestorMaskLayerAt(size_t aIndex) const {
-    return mAncestorMaskLayers.ElementAt(aIndex);
-  }
-
-  bool HasMaskLayers() const {
-    return GetMaskLayer() || mAncestorMaskLayers.Length() > 0;
-  }
-
   /*
    * Get the combined clip rect of the Layer clip and all clips on FrameMetrics.
    * This is intended for use in Layout. The compositor needs to apply async
    * transforms to find the combined clip.
    */
   Maybe<ParentLayerIntRect> GetCombinedClipRect() const;
 
   /**
@@ -1509,21 +1484,19 @@ public:
    * pixel grid (whatever aTransformToSurface is relative to).
    *
    * We promise that when this is called on a layer, all ancestor layers
    * have already had ComputeEffectiveTransforms called.
    */
   virtual void ComputeEffectiveTransforms(const gfx::Matrix4x4& aTransformToSurface) = 0;
 
   /**
-   * Computes the effective transform for mask layers, if this layer has any.
+   * computes the effective transform for a mask layer, if this layer has one
    */
-  void ComputeEffectiveTransformForMaskLayers(const gfx::Matrix4x4& aTransformToSurface);
-  static void ComputeEffectiveTransformForMaskLayer(Layer* aMaskLayer,
-                                                    const gfx::Matrix4x4& aTransformToSurface);
+  void ComputeEffectiveTransformForMaskLayer(const gfx::Matrix4x4& aTransformToSurface);
 
   /**
    * Calculate the scissor rect required when rendering this layer.
    * Returns a rectangle relative to the intermediate surface belonging to the
    * nearest ancestor that has an intermediate surface, or relative to the root
    * viewport if no ancestor has an intermediate surface, corresponding to the
    * clip rect for this layer intersected with aCurrentScissorRect.
    */
@@ -1717,17 +1690,16 @@ protected:
                                gfx::Matrix* aResidualTransform);
 
   LayerManager* mManager;
   ContainerLayer* mParent;
   Layer* mNextSibling;
   Layer* mPrevSibling;
   void* mImplData;
   nsRefPtr<Layer> mMaskLayer;
-  nsTArray<nsRefPtr<Layer>> mAncestorMaskLayers;
   gfx::UserData mUserData;
   gfx::IntRect mLayerBounds;
   nsIntRegion mVisibleRegion;
   nsTArray<FrameMetrics> mFrameMetrics;
   EventRegions mEventRegions;
   gfx::Matrix4x4 mTransform;
   // A mutation of |mTransform| that we've queued to be applied at the
   // end of the next transaction (if nothing else overrides it in the
@@ -1829,17 +1801,17 @@ public:
                  "Residual transform can only be a translation");
     if (!gfx::ThebesPoint(residual.GetTranslation()).WithinEpsilonOf(mResidualTranslation, 1e-3f)) {
       mResidualTranslation = gfx::ThebesPoint(residual.GetTranslation());
       NS_ASSERTION(-0.5 <= mResidualTranslation.x && mResidualTranslation.x < 0.5 &&
                    -0.5 <= mResidualTranslation.y && mResidualTranslation.y < 0.5,
                    "Residual translation out of range");
       mValidRegion.SetEmpty();
     }
-    ComputeEffectiveTransformForMaskLayers(aTransformToSurface);
+    ComputeEffectiveTransformForMaskLayer(aTransformToSurface);
   }
 
   LayerManager::PaintedLayerCreationHint GetCreationHint() const { return mCreationHint; }
 
   bool UsedForReadback() { return mUsedForReadback; }
   void SetUsedForReadback(bool aUsed) { mUsedForReadback = aUsed; }
   /**
    * Returns the residual translation. Apply this translation when drawing
@@ -2140,17 +2112,17 @@ public:
   virtual const gfxRGBA& GetColor() { return mColor; }
 
   MOZ_LAYER_DECL_NAME("ColorLayer", TYPE_COLOR)
 
   virtual void ComputeEffectiveTransforms(const gfx::Matrix4x4& aTransformToSurface) override
   {
     gfx::Matrix4x4 idealTransform = GetLocalTransform() * aTransformToSurface;
     mEffectiveTransform = SnapTransformTranslation(idealTransform, nullptr);
-    ComputeEffectiveTransformForMaskLayers(aTransformToSurface);
+    ComputeEffectiveTransformForMaskLayer(aTransformToSurface);
   }
 
 protected:
   ColorLayer(LayerManager* aManager, void* aImplData)
     : Layer(aManager, aImplData),
       mColor(0.0, 0.0, 0.0, 0.0)
   {}
 
@@ -2292,17 +2264,17 @@ public:
     // Snap our local transform first, and snap the inherited transform as well.
     // This makes our snapping equivalent to what would happen if our content
     // was drawn into a PaintedLayer (gfxContext would snap using the local
     // transform, then we'd snap again when compositing the PaintedLayer).
     mEffectiveTransform =
         SnapTransform(GetLocalTransform(), gfxRect(0, 0, mBounds.width, mBounds.height),
                       nullptr)*
         SnapTransformTranslation(aTransformToSurface, nullptr);
-    ComputeEffectiveTransformForMaskLayers(aTransformToSurface);
+    ComputeEffectiveTransformForMaskLayer(aTransformToSurface);
   }
 
 protected:
   CanvasLayer(LayerManager* aManager, void* aImplData)
     : Layer(aManager, aImplData)
     , mPreTransCallback(nullptr)
     , mPreTransCallbackData(nullptr)
     , mPostTransCallback(nullptr)
--- a/gfx/layers/ReadbackProcessor.cpp
+++ b/gfx/layers/ReadbackProcessor.cpp
@@ -68,21 +68,19 @@ FindBackgroundLayer(ReadbackLayer* aLaye
     if (!visibleRegion.Intersects(rectInBackground))
       continue;
     // Since l is present in the background, from here on we either choose l
     // or nothing.
     if (!visibleRegion.Contains(rectInBackground))
       return nullptr;
 
     if (l->GetEffectiveOpacity() != 1.0 ||
-        l->HasMaskLayers() ||
+        l->GetMaskLayer() ||
         !(l->GetContentFlags() & Layer::CONTENT_OPAQUE))
-    {
       return nullptr;
-    }
 
     // cliprects are post-transform
     const Maybe<ParentLayerIntRect>& clipRect = l->GetEffectiveClipRect();
     if (clipRect && !clipRect->Contains(ViewAs<ParentLayerPixel>(IntRect(transformOffset, aLayer->GetSize()))))
       return nullptr;
 
     Layer::LayerType type = l->GetType();
     if (type != Layer::TYPE_COLOR && type != Layer::TYPE_PAINTED)
--- a/gfx/layers/apz/src/AsyncPanZoomController.cpp
+++ b/gfx/layers/apz/src/AsyncPanZoomController.cpp
@@ -2912,17 +2912,16 @@ void AsyncPanZoomController::NotifyLayer
     mFrameMetrics.SetCompositionBounds(aLayerMetrics.GetCompositionBounds());
     mFrameMetrics.SetRootCompositionSize(aLayerMetrics.GetRootCompositionSize());
     mFrameMetrics.SetPresShellResolution(aLayerMetrics.GetPresShellResolution());
     mFrameMetrics.SetCumulativeResolution(aLayerMetrics.GetCumulativeResolution());
     mFrameMetrics.SetHasScrollgrab(aLayerMetrics.GetHasScrollgrab());
     mFrameMetrics.SetLineScrollAmount(aLayerMetrics.GetLineScrollAmount());
     mFrameMetrics.SetPageScrollAmount(aLayerMetrics.GetPageScrollAmount());
     mFrameMetrics.SetClipRect(aLayerMetrics.GetClipRect());
-    mFrameMetrics.SetMaskLayerIndex(aLayerMetrics.GetMaskLayerIndex());
     mFrameMetrics.SetIsLayersIdRoot(aLayerMetrics.IsLayersIdRoot());
     mFrameMetrics.SetUsesContainerScrolling(aLayerMetrics.UsesContainerScrolling());
 
     if (scrollOffsetUpdated) {
       APZC_LOG("%p updating scroll offset from %s to %s\n", this,
         ToString(mFrameMetrics.GetScrollOffset()).c_str(),
         ToString(aLayerMetrics.GetScrollOffset()).c_str());
 
--- a/gfx/layers/basic/BasicContainerLayer.cpp
+++ b/gfx/layers/basic/BasicContainerLayer.cpp
@@ -39,27 +39,27 @@ BasicContainerLayer::ComputeEffectiveTra
   // containers.
   Matrix residual;
   Matrix4x4 idealTransform = GetLocalTransform() * aTransformToSurface;
   idealTransform.ProjectTo2D();
 
   if (!idealTransform.CanDraw2D()) {
     mEffectiveTransform = idealTransform;
     ComputeEffectiveTransformsForChildren(Matrix4x4());
-    ComputeEffectiveTransformForMaskLayers(Matrix4x4());
+    ComputeEffectiveTransformForMaskLayer(Matrix4x4());
     mUseIntermediateSurface = true;
     return;
   }
 
   mEffectiveTransform = SnapTransformTranslation(idealTransform, &residual);
   // We always pass the ideal matrix down to our children, so there is no
   // need to apply any compensation using the residual from SnapTransformTranslation.
   ComputeEffectiveTransformsForChildren(idealTransform);
 
-  ComputeEffectiveTransformForMaskLayers(aTransformToSurface);
+  ComputeEffectiveTransformForMaskLayer(aTransformToSurface);
 
   Layer* child = GetFirstChild();
   bool hasSingleBlendingChild = false;
   if (!HasMultipleChildren() && child) {
     hasSingleBlendingChild = child->GetMixBlendMode() != CompositionOp::OP_OVER;
   }
 
   /* If we have a single childand it is not blending,, it can just inherit our opacity,
--- a/gfx/layers/basic/BasicPaintedLayer.h
+++ b/gfx/layers/basic/BasicPaintedLayer.h
@@ -81,17 +81,17 @@ public:
     if (!BasicManager()->IsRetained()) {
       // Don't do any snapping of our transform, since we're just going to
       // draw straight through without intermediate buffers.
       mEffectiveTransform = GetLocalTransform() * aTransformToSurface;
       if (gfxPoint(0,0) != mResidualTranslation) {
         mResidualTranslation = gfxPoint(0,0);
         mValidRegion.SetEmpty();
       }
-      ComputeEffectiveTransformForMaskLayers(aTransformToSurface);
+      ComputeEffectiveTransformForMaskLayer(aTransformToSurface);
       return;
     }
     PaintedLayer::ComputeEffectiveTransforms(aTransformToSurface);
   }
 
   BasicLayerManager* BasicManager()
   {
     return static_cast<BasicLayerManager*>(mManager);
--- a/gfx/layers/client/ClientCanvasLayer.cpp
+++ b/gfx/layers/client/ClientCanvasLayer.cpp
@@ -128,17 +128,19 @@ ClientCanvasLayer::Initialize(const Data
 }
 
 void
 ClientCanvasLayer::RenderLayer()
 {
   PROFILER_LABEL("ClientCanvasLayer", "RenderLayer",
     js::ProfileEntry::Category::GRAPHICS);
 
-  RenderMaskLayers(this);
+  if (GetMaskLayer()) {
+    ToClientLayer(GetMaskLayer())->RenderLayer();
+  }
 
   if (!IsDirty()) {
     return;
   }
   Painted();
 
   if (!mCanvasClient) {
     TextureFlags flags = TextureFlags::IMMEDIATE_UPLOAD;
--- a/gfx/layers/client/ClientColorLayer.cpp
+++ b/gfx/layers/client/ClientColorLayer.cpp
@@ -38,17 +38,19 @@ public:
   {
     NS_ASSERTION(ClientManager()->InConstruction(),
                  "Can only set properties in construction phase");
     ColorLayer::SetVisibleRegion(aRegion);
   }
 
   virtual void RenderLayer()
   {
-    RenderMaskLayers(this);
+    if (GetMaskLayer()) {
+      ToClientLayer(GetMaskLayer())->RenderLayer();
+    }
   }
 
   virtual void FillSpecificAttributes(SpecificLayerAttributes& aAttrs)
   {
     aAttrs = ColorLayerAttributes(GetColor(), GetBounds());
   }
 
   virtual Layer* AsLayer() { return this; }
--- a/gfx/layers/client/ClientContainerLayer.h
+++ b/gfx/layers/client/ClientContainerLayer.h
@@ -42,17 +42,19 @@ protected:
     }
 
     MOZ_COUNT_DTOR(ClientContainerLayer);
   }
 
 public:
   virtual void RenderLayer() override
   {
-    RenderMaskLayers(this);
+    if (GetMaskLayer()) {
+      ToClientLayer(GetMaskLayer())->RenderLayer();
+    }
     
     DefaultComputeSupportsComponentAlphaChildren();
 
     nsAutoTArray<Layer*, 12> children;
     SortChildrenBy3DZOrder(children);
 
     ReadbackProcessor readback;
     readback.BuildUpdates(this);
--- a/gfx/layers/client/ClientImageLayer.cpp
+++ b/gfx/layers/client/ClientImageLayer.cpp
@@ -121,17 +121,19 @@ protected:
 
   RefPtr<ImageClient> mImageClient;
   CompositableType mImageClientTypeContainer;
 };
 
 void
 ClientImageLayer::RenderLayer()
 {
-  RenderMaskLayers(this);
+  if (GetMaskLayer()) {
+    ToClientLayer(GetMaskLayer())->RenderLayer();
+  }
 
   if (!mContainer) {
      return;
   }
 
   if (mImageClient) {
     mImageClient->OnTransaction();
   }
--- a/gfx/layers/client/ClientLayerManager.h
+++ b/gfx/layers/client/ClientLayerManager.h
@@ -385,26 +385,16 @@ public:
 
   virtual ClientPaintedLayer* AsThebes() { return nullptr; }
 
   static inline ClientLayer *
   ToClientLayer(Layer* aLayer)
   {
     return static_cast<ClientLayer*>(aLayer->ImplData());
   }
-
-  template <typename LayerType>
-  static inline void RenderMaskLayers(LayerType* aLayer) {
-    if (aLayer->GetMaskLayer()) {
-      ToClientLayer(aLayer->GetMaskLayer())->RenderLayer();
-    }
-    for (size_t i = 0; i < aLayer->GetAncestorMaskLayerCount(); i++) {
-      ToClientLayer(aLayer->GetAncestorMaskLayerAt(i))->RenderLayer();
-    }
-  }
 };
 
 // Create a shadow layer (PLayerChild) for aLayer, if we're forwarding
 // our layer tree to a parent process.  Record the new layer creation
 // in the current open transaction as a side effect.
 template<typename CreatedMethod> void
 CreateShadowFor(ClientLayer* aLayer,
                 ClientLayerManager* aMgr,
--- a/gfx/layers/client/ClientPaintedLayer.cpp
+++ b/gfx/layers/client/ClientPaintedLayer.cpp
@@ -112,17 +112,19 @@ ClientPaintedLayer::PaintThebes()
                                  mVisibleRegion,
                                  state.mDidSelfCopy);
   }
 }
 
 void
 ClientPaintedLayer::RenderLayerWithReadback(ReadbackProcessor *aReadback)
 {
-  RenderMaskLayers(this);
+  if (GetMaskLayer()) {
+    ToClientLayer(GetMaskLayer())->RenderLayer();
+  }
   
   if (!mContentClient) {
     mContentClient = ContentClient::CreateContentClient(ClientManager()->AsShadowForwarder());
     if (!mContentClient) {
       return;
     }
     mContentClient->Connect();
     ClientManager()->AsShadowForwarder()->Attach(mContentClient, this);
--- a/gfx/layers/client/ClientTiledPaintedLayer.cpp
+++ b/gfx/layers/client/ClientTiledPaintedLayer.cpp
@@ -438,18 +438,20 @@ ClientTiledPaintedLayer::RenderLayer()
   nsIntRegion invalidRegion;
   invalidRegion.Sub(neededRegion, mValidRegion);
   if (invalidRegion.IsEmpty()) {
     EndPaint();
     return;
   }
 
   if (!ClientManager()->IsRepeatTransaction()) {
-    // Only paint the mask layers on the first transaction.
-    RenderMaskLayers(this);
+    // Only paint the mask layer on the first transaction.
+    if (GetMaskLayer()) {
+      ToClientLayer(GetMaskLayer())->RenderLayer();
+    }
 
     // For more complex cases we need to calculate a bunch of metrics before we
     // can do the paint.
     BeginPaint();
     if (mPaintData.mPaintFinished) {
       return;
     }
 
--- a/gfx/layers/composite/AsyncCompositionManager.cpp
+++ b/gfx/layers/composite/AsyncCompositionManager.cpp
@@ -609,28 +609,16 @@ AsyncCompositionManager::ApplyAsyncConte
   // Each layer has multiple clips. Its local clip, which must move with async
   // transforms, and its scrollframe clips, which are the clips between each
   // scrollframe and its ancestor scrollframe. Scrollframe clips include the
   // composition bounds and any other clips induced by layout.
   //
   // The final clip for the layer is the intersection of these clips.
   Maybe<ParentLayerIntRect> asyncClip = aLayer->GetClipRect();
 
-  // The transform of a mask layer is relative to the masked layer's parent
-  // layer. So whenever we apply an async transform to a layer, we need to
-  // apply that same transform to the layer's own mask layer.
-  // A layer can also have "ancestor" mask layers for any rounded clips from
-  // its ancestor scroll frames. A scroll frame mask layer only needs to be
-  // async transformed for async scrolls of this scroll frame's ancestor
-  // scroll frames, not for async scrolls of this scroll frame itself.
-  // In the loop below, we iterate over scroll frames from inside to outside.
-  // At each iteration, this array contains the layer's ancestor mask layers 
-  // of all scroll frames inside the current one.
-  nsTArray<Layer*> ancestorMaskLayers;
-
   for (uint32_t i = 0; i < aLayer->GetFrameMetricsCount(); i++) {
     AsyncPanZoomController* controller = aLayer->GetAsyncPanZoomController(i);
     if (!controller) {
       continue;
     }
 
     hasAsyncTransform = true;
 
@@ -683,53 +671,32 @@ AsyncCompositionManager::ApplyAsyncConte
       ParentLayerIntRect clip = metrics.ClipRect();
       if (asyncClip) {
         asyncClip = Some(clip.Intersect(*asyncClip));
       } else {
         asyncClip = Some(clip);
       }
     }
 
-    // Do the same for the ancestor mask layers: ancestorMaskLayers contains
-    // the ancestor mask layers for scroll frames *inside* the current scroll
-    // frame, so these are the ones we need to shift by our async transform.
-    for (Layer* ancestorMaskLayer : ancestorMaskLayers) {
-      SetShadowTransform(ancestorMaskLayer,
-          ancestorMaskLayer->GetLocalTransform() * asyncTransform);
-    }
-
-    // Append the ancestor mask layer for this scroll frame to ancestorMaskLayers.
-    if (metrics.GetMaskLayerIndex()) {
-      size_t maskLayerIndex = metrics.GetMaskLayerIndex().value();
-      Layer* ancestorMaskLayer = aLayer->GetAncestorMaskLayerAt(maskLayerIndex);
-      ancestorMaskLayers.AppendElement(ancestorMaskLayer);
-    }
-
     combinedAsyncTransformWithoutOverscroll *= asyncTransformWithoutOverscroll;
     combinedAsyncTransform *= asyncTransform;
   }
 
   if (hasAsyncTransform) {
     if (asyncClip) {
       aLayer->AsLayerComposite()->SetShadowClipRect(asyncClip);
     }
 
     // Apply the APZ transform on top of GetLocalTransform() here (rather than
     // GetTransform()) in case the OMTA code in SampleAnimations already set a
     // shadow transform; in that case we want to apply ours on top of that one
     // rather than clobber it.
     SetShadowTransform(aLayer,
         aLayer->GetLocalTransform() * AdjustForClip(combinedAsyncTransform, aLayer));
 
-    // Do the same for the layer's own mask layer, if it has one.
-    if (Layer* maskLayer = aLayer->GetMaskLayer()) {
-      SetShadowTransform(maskLayer,
-          maskLayer->GetLocalTransform() * combinedAsyncTransform);
-    }
-
     const FrameMetrics& bottom = LayerMetricsWrapper::BottommostScrollableMetrics(aLayer);
     MOZ_ASSERT(bottom.IsScrollable());  // must be true because hasAsyncTransform is true
 
     // For the purpose of aligning fixed and sticky layers, we disregard
     // the overscroll transform as well as any OMTA transform when computing the
     // 'aCurrentTransformForRoot' parameter. This ensures that the overscroll
     // and OMTA transforms are not unapplied, and therefore that the visual
     // effects apply to fixed and sticky layers. We do this by using
--- a/gfx/layers/composite/CanvasLayerComposite.cpp
+++ b/gfx/layers/composite/CanvasLayerComposite.cpp
@@ -90,25 +90,27 @@ CanvasLayerComposite::RenderLayer(const 
 
 #ifdef MOZ_DUMP_PAINTING
   if (gfxUtils::sDumpPainting) {
     RefPtr<gfx::DataSourceSurface> surf = mCompositableHost->GetAsSurface();
     WriteSnapshotToDumpFile(this, surf);
   }
 #endif
 
-  RenderWithAllMasks(this, mCompositor, aClipRect,
-                     [&](EffectChain& effectChain, const Rect& clipRect) {
-    mCompositableHost->Composite(effectChain,
-                          GetEffectiveOpacity(),
-                          GetEffectiveTransform(),
-                          GetEffectFilter(),
-                          clipRect);
-  });
+  EffectChain effectChain(this);
+  AddBlendModeEffect(effectChain);
+
+  LayerManagerComposite::AutoAddMaskEffect autoMaskEffect(mMaskLayer, effectChain);
+  gfx::Rect clipRect(aClipRect.x, aClipRect.y, aClipRect.width, aClipRect.height);
 
+  mCompositableHost->Composite(effectChain,
+                        GetEffectiveOpacity(),
+                        GetEffectiveTransform(),
+                        GetEffectFilter(),
+                        clipRect);
   mCompositableHost->BumpFlashCounter();
 }
 
 CompositableHost*
 CanvasLayerComposite::GetCompositableHost()
 {
   if (mCompositableHost && mCompositableHost->IsAttached()) {
     return mCompositableHost.get();
--- a/gfx/layers/composite/ColorLayerComposite.cpp
+++ b/gfx/layers/composite/ColorLayerComposite.cpp
@@ -16,27 +16,38 @@
 #include "mozilla/mozalloc.h"           // for operator delete, etc
 
 namespace mozilla {
 namespace layers {
 
 void
 ColorLayerComposite::RenderLayer(const gfx::IntRect& aClipRect)
 {
-  gfx::Rect rect(GetBounds());
-  const gfx::Matrix4x4& transform = GetEffectiveTransform();
+  EffectChain effects(this);
+
+  GenEffectChain(effects);
+
+  gfx::IntRect boundRect = GetBounds();
+
+  LayerManagerComposite::AutoAddMaskEffect autoMaskEffect(GetMaskLayer(),
+                                                          effects);
 
-  RenderWithAllMasks(this, mCompositor, aClipRect,
-                     [&](EffectChain& effectChain, const Rect& clipRect) {
-    GenEffectChain(effectChain);
-    mCompositor->DrawQuad(rect, clipRect, effectChain, GetEffectiveOpacity(), transform);
-  });
+  gfx::Rect rect(boundRect.x, boundRect.y,
+                 boundRect.width, boundRect.height);
+  gfx::Rect clipRect(aClipRect.x, aClipRect.y,
+                     aClipRect.width, aClipRect.height);
+
+  float opacity = GetEffectiveOpacity();
 
+  AddBlendModeEffect(effects);
+
+  const gfx::Matrix4x4& transform = GetEffectiveTransform();
+  mCompositor->DrawQuad(rect, clipRect, effects, opacity, transform);
   mCompositor->DrawDiagnostics(DiagnosticFlags::COLOR,
-                               rect, Rect(aClipRect),
+                               rect, clipRect,
                                transform);
 }
 
 void
 ColorLayerComposite::GenEffectChain(EffectChain& aEffect)
 {
   aEffect.mLayerRef = this;
   gfxRGBA color(GetColor());
--- a/gfx/layers/composite/ContainerLayerComposite.cpp
+++ b/gfx/layers/composite/ContainerLayerComposite.cpp
@@ -508,34 +508,44 @@ ContainerRender(ContainerT* aContainer,
       surface = aContainer->mPrepared->mTmpTarget;
     }
 
     if (!surface) {
       aContainer->mPrepared = nullptr;
       return;
     }
 
-    gfx::Rect visibleRect(aContainer->GetEffectiveVisibleRegion().GetBounds());
-    Compositor* compositor = aManager->GetCompositor();
+    float opacity = aContainer->GetEffectiveOpacity();
+
+    gfx::IntRect visibleRect = aContainer->GetEffectiveVisibleRegion().GetBounds();
 #ifdef MOZ_DUMP_PAINTING
     if (gfxUtils::sDumpPainting) {
-      RefPtr<gfx::DataSourceSurface> surf = surface->Dump(compositor);
+      RefPtr<gfx::DataSourceSurface> surf = surface->Dump(aManager->GetCompositor());
       if (surf) {
         WriteSnapshotToDumpFile(aContainer, surf);
       }
     }
 #endif
 
-    RenderWithAllMasks(aContainer, compositor, aClipRect,
-                       [&](EffectChain& effectChain, const Rect& clipRect) {
-      effectChain.mPrimaryEffect = new EffectRenderTarget(surface);
-      compositor->DrawQuad(visibleRect, clipRect, effectChain,
-                           aContainer->GetEffectiveOpacity(),
-                           aContainer->GetEffectiveTransform());
-    });
+    EffectChain effectChain(aContainer);
+    LayerManagerComposite::AutoAddMaskEffect autoMaskEffect(aContainer->GetMaskLayer(),
+                                                            effectChain,
+                                                            !aContainer->GetTransform().CanDraw2D());
+    if (autoMaskEffect.Failed()) {
+      NS_WARNING("Failed to apply a mask effect.");
+      return;
+    }
+
+    aContainer->AddBlendModeEffect(effectChain);
+    effectChain.mPrimaryEffect = new EffectRenderTarget(surface);
+
+    gfx::Rect rect(visibleRect.x, visibleRect.y, visibleRect.width, visibleRect.height);
+    gfx::Rect clipRect(aClipRect.x, aClipRect.y, aClipRect.width, aClipRect.height);
+    aManager->GetCompositor()->DrawQuad(rect, clipRect, effectChain, opacity,
+                                        aContainer->GetEffectiveTransform());
   } else {
     RenderLayers(aContainer, aManager, RenderTargetPixel::FromUntyped(aClipRect));
   }
   aContainer->mPrepared = nullptr;
 
   // If it is a scrollable container layer with no child layers, and one of the APZCs
   // attached to it has a nonempty async transform, then that transform is not applied
   // to any visible content. Display a warning box (conditioned on the FPS display being
--- a/gfx/layers/composite/ImageLayerComposite.cpp
+++ b/gfx/layers/composite/ImageLayerComposite.cpp
@@ -90,25 +90,27 @@ ImageLayerComposite::RenderLayer(const I
   if (gfxUtils::sDumpPainting) {
     RefPtr<gfx::DataSourceSurface> surf = mImageHost->GetAsSurface();
     WriteSnapshotToDumpFile(this, surf);
   }
 #endif
 
   mCompositor->MakeCurrent();
 
-  RenderWithAllMasks(this, mCompositor, aClipRect,
-                     [&](EffectChain& effectChain, const Rect& clipRect) {
-    mImageHost->SetCompositor(mCompositor);
-    mImageHost->Composite(effectChain,
-                          GetEffectiveOpacity(),
-                          GetEffectiveTransformForBuffer(),
-                          GetEffectFilter(),
-                          clipRect);
-  });
+  EffectChain effectChain(this);
+  LayerManagerComposite::AutoAddMaskEffect autoMaskEffect(mMaskLayer, effectChain);
+  AddBlendModeEffect(effectChain);
+
+  gfx::Rect clipRect(aClipRect.x, aClipRect.y, aClipRect.width, aClipRect.height);
+  mImageHost->SetCompositor(mCompositor);
+  mImageHost->Composite(effectChain,
+                        GetEffectiveOpacity(),
+                        GetEffectiveTransformForBuffer(),
+                        GetEffectFilter(),
+                        clipRect);
   mImageHost->BumpFlashCounter();
 }
 
 void
 ImageLayerComposite::ComputeEffectiveTransforms(const gfx::Matrix4x4& aTransformToSurface)
 {
   gfx::Matrix4x4 local = GetLocalTransform();
 
@@ -136,17 +138,17 @@ ImageLayerComposite::ComputeEffectiveTra
 
     mEffectiveTransformForBuffer =
         SnapTransform(local, sourceRect, nullptr) *
         SnapTransformTranslation(aTransformToSurface, nullptr);
   } else {
     mEffectiveTransformForBuffer = mEffectiveTransform;
   }
 
-  ComputeEffectiveTransformForMaskLayers(aTransformToSurface);
+  ComputeEffectiveTransformForMaskLayer(aTransformToSurface);
 }
 
 CompositableHost*
 ImageLayerComposite::GetCompositableHost()
 {
   if (mImageHost && mImageHost->IsAttached()) {
     return mImageHost.get();
   }
--- a/gfx/layers/composite/LayerManagerComposite.cpp
+++ b/gfx/layers/composite/LayerManagerComposite.cpp
@@ -229,17 +229,17 @@ LayerManagerComposite::ApplyOcclusionCul
   // contribute to localOpaque.
   for (Layer* child = aLayer->GetLastChild(); child; child = child->GetPrevSibling()) {
     ApplyOcclusionCulling(child, localOpaque);
   }
 
   // If we have a simple transform, then we can add our opaque area into
   // aOpaqueRegion.
   if (isTranslation &&
-      !aLayer->HasMaskLayers() &&
+      !aLayer->GetMaskLayer() &&
       aLayer->GetLocalOpacity() == 1.0f) {
     if (aLayer->GetContentFlags() & Layer::CONTENT_OPAQUE) {
       localOpaque.Or(localOpaque, composite->GetFullyRenderedRegion());
     }
     localOpaque.MoveBy(transform2d._31, transform2d._32);
     const Maybe<ParentLayerIntRect>& clip = aLayer->GetEffectiveClipRect();
     if (clip) {
       localOpaque.And(localOpaque, ParentLayerIntRect::ToUntyped(*clip));
--- a/gfx/layers/composite/LayerManagerComposite.h
+++ b/gfx/layers/composite/LayerManagerComposite.h
@@ -13,17 +13,16 @@
 #include "mozilla/Assertions.h"         // for MOZ_ASSERT, etc
 #include "mozilla/Attributes.h"         // for override
 #include "mozilla/RefPtr.h"             // for RefPtr, already_AddRefed
 #include "mozilla/gfx/2D.h"
 #include "mozilla/gfx/Point.h"          // for IntSize
 #include "mozilla/gfx/Rect.h"           // for Rect
 #include "mozilla/gfx/Types.h"          // for SurfaceFormat
 #include "mozilla/layers/CompositorTypes.h"
-#include "mozilla/layers/Effects.h"     // for EffectChain
 #include "mozilla/layers/LayersTypes.h"  // for LayersBackend, etc
 #include "mozilla/Maybe.h"              // for Maybe
 #include "mozilla/RefPtr.h"
 #include "mozilla/UniquePtr.h"
 #include "nsAString.h"
 #include "nsRefPtr.h"                   // for nsRefPtr
 #include "nsCOMPtr.h"                   // for already_AddRefed
 #include "nsDebug.h"                    // for NS_ASSERTION
@@ -453,145 +452,13 @@ protected:
   RefPtr<Compositor> mCompositor;
   float mShadowOpacity;
   bool mShadowTransformSetByAnimation;
   bool mDestroyed;
   bool mLayerComposited;
   gfx::IntRect mClearRect;
 };
 
-// Render aLayer using aCompositor and apply all mask layers of aLayer: The
-// layer's own mask layer (aLayer->GetMaskLayer()), and any ancestor mask
-// layers.
-// If more than one mask layer needs to be applied, we use intermediate surfaces
-// (CompositingRenderTargets) for rendering, applying one mask layer at a time.
-// Callers need to provide a callback function aRenderCallback that does the
-// actual rendering of the source. It needs to have the following form:
-// void (EffectChain& effectChain, const Rect& clipRect)
-// aRenderCallback is called exactly once, inside this function, unless aLayer's
-// visible region is completely clipped out (in that case, aRenderCallback won't
-// be called at all).
-// This function calls aLayer->AsLayerComposite()->AddBlendModeEffect for the
-// final rendering pass.
-//
-// (This function should really live in LayerManagerComposite.cpp, but we
-// need to use templates for passing lambdas until bug 1164522 is resolved.)
-template<typename RenderCallbackType>
-void
-RenderWithAllMasks(Layer* aLayer, Compositor* aCompositor,
-                   const gfx::IntRect& aClipRect,
-                   RenderCallbackType aRenderCallback)
-{
-  Layer* firstMask = nullptr;
-  size_t maskLayerCount = 0;
-  size_t nextAncestorMaskLayer = 0;
-
-  size_t ancestorMaskLayerCount = aLayer->GetAncestorMaskLayerCount();
-  if (Layer* ownMask = aLayer->GetMaskLayer()) {
-    firstMask = ownMask;
-    maskLayerCount = ancestorMaskLayerCount + 1;
-    nextAncestorMaskLayer = 0;
-  } else if (ancestorMaskLayerCount > 0) {
-    firstMask = aLayer->GetAncestorMaskLayerAt(0);
-    maskLayerCount = ancestorMaskLayerCount;
-    nextAncestorMaskLayer = 1;
-  } else {
-    // no mask layers at all
-  }
-
-  bool firstMaskIs3D = false;
-  if (ContainerLayer* container = aLayer->AsContainerLayer()) {
-    firstMaskIs3D = !container->GetTransform().CanDraw2D();
-  }
-
-  if (maskLayerCount <= 1) {
-    // This is the common case. Render in one pass and return.
-    EffectChain effectChain(aLayer);
-    LayerManagerComposite::AutoAddMaskEffect
-      autoMaskEffect(firstMask, effectChain, firstMaskIs3D);
-    aLayer->AsLayerComposite()->AddBlendModeEffect(effectChain);
-    aRenderCallback(effectChain, gfx::Rect(aClipRect));
-    return;
-  }
-
-  // We have multiple mask layers.
-  // We split our list of mask layers into three parts:
-  //  (1) The first mask
-  //  (2) The list of intermediate masks (every mask except first and last)
-  //  (3) The final mask.
-  // Part (2) can be empty.
-  // For parts (1) and (2) we need to allocate intermediate surfaces to render
-  // into. The final mask gets rendered into the original render target.
-
-  // Calculate the size of the intermediate surfaces.
-  gfx::Rect visibleRect(aLayer->GetEffectiveVisibleRegion().GetBounds());
-  gfx::Matrix4x4 transform = aLayer->GetEffectiveTransform();
-  // TODO: Use RenderTargetIntRect and TransformTo<...> here
-  gfx::IntRect surfaceRect =
-    RoundedOut(transform.TransformBounds(visibleRect)).Intersect(aClipRect);
-  if (surfaceRect.IsEmpty()) {
-    return;
-  }
-
-  RefPtr<CompositingRenderTarget> originalTarget =
-    aCompositor->GetCurrentRenderTarget();
-
-  RefPtr<CompositingRenderTarget> firstTarget =
-    aCompositor->CreateRenderTarget(surfaceRect, INIT_MODE_CLEAR);
-  if (!firstTarget) {
-    return;
-  }
-
-  // Render the source while applying the first mask.
-  aCompositor->SetRenderTarget(firstTarget);
-  {
-    EffectChain firstEffectChain(aLayer);
-    LayerManagerComposite::AutoAddMaskEffect
-      firstMaskEffect(firstMask, firstEffectChain, firstMaskIs3D);
-    aRenderCallback(firstEffectChain, gfx::Rect(aClipRect - surfaceRect.TopLeft()));
-    // firstTarget now contains the transformed source with the first mask and
-    // opacity already applied.
-  }
-
-  // Apply the intermediate masks.
-  gfx::Rect intermediateClip(surfaceRect - surfaceRect.TopLeft());
-  RefPtr<CompositingRenderTarget> previousTarget = firstTarget;
-  for (size_t i = nextAncestorMaskLayer; i < ancestorMaskLayerCount - 1; i++) {
-    Layer* intermediateMask = aLayer->GetAncestorMaskLayerAt(i);
-    RefPtr<CompositingRenderTarget> intermediateTarget =
-      aCompositor->CreateRenderTarget(surfaceRect, INIT_MODE_CLEAR);
-    if (!intermediateTarget) {
-      break;
-    }
-    aCompositor->SetRenderTarget(intermediateTarget);
-    EffectChain intermediateEffectChain(aLayer);
-    LayerManagerComposite::AutoAddMaskEffect
-      intermediateMaskEffect(intermediateMask, intermediateEffectChain);
-    if (intermediateMaskEffect.Failed()) {
-      continue;
-    }
-    intermediateEffectChain.mPrimaryEffect = new EffectRenderTarget(previousTarget);
-    aCompositor->DrawQuad(gfx::Rect(surfaceRect), intermediateClip,
-                          intermediateEffectChain, 1.0, gfx::Matrix4x4());
-    previousTarget = intermediateTarget;
-  }
-
-  aCompositor->SetRenderTarget(originalTarget);
-
-  // Apply the final mask, rendering into originalTarget.
-  EffectChain finalEffectChain(aLayer);
-  finalEffectChain.mPrimaryEffect = new EffectRenderTarget(previousTarget);
-  Layer* finalMask = aLayer->GetAncestorMaskLayerAt(ancestorMaskLayerCount - 1);
-
-  // The blend mode needs to be applied in this final step, because this is
-  // where we're blending with the actual background (which is in originalTarget).
-  aLayer->AsLayerComposite()->AddBlendModeEffect(finalEffectChain);
-  LayerManagerComposite::AutoAddMaskEffect autoMaskEffect(finalMask, finalEffectChain);
-  if (!autoMaskEffect.Failed()) {
-    aCompositor->DrawQuad(gfx::Rect(surfaceRect), gfx::Rect(aClipRect),
-                          finalEffectChain, 1.0, gfx::Matrix4x4());
-  }
-}
 
 } /* layers */
 } /* mozilla */
 
 #endif /* GFX_LayerManagerComposite_H */
--- a/gfx/layers/composite/PaintedLayerComposite.cpp
+++ b/gfx/layers/composite/PaintedLayerComposite.cpp
@@ -114,49 +114,47 @@ void
 PaintedLayerComposite::RenderLayer(const gfx::IntRect& aClipRect)
 {
   if (!mBuffer || !mBuffer->IsAttached()) {
     return;
   }
   PROFILER_LABEL("PaintedLayerComposite", "RenderLayer",
     js::ProfileEntry::Category::GRAPHICS);
 
-  Compositor* compositor = mCompositeManager->GetCompositor();
-
-  MOZ_ASSERT(mBuffer->GetCompositor() == compositor &&
+  MOZ_ASSERT(mBuffer->GetCompositor() == mCompositeManager->GetCompositor() &&
              mBuffer->GetLayer() == this,
              "buffer is corrupted");
 
   const nsIntRegion& visibleRegion = GetEffectiveVisibleRegion();
+  gfx::Rect clipRect(aClipRect.x, aClipRect.y, aClipRect.width, aClipRect.height);
 
 #ifdef MOZ_DUMP_PAINTING
   if (gfxUtils::sDumpPainting) {
     RefPtr<gfx::DataSourceSurface> surf = mBuffer->GetAsSurface();
     if (surf) {
       WriteSnapshotToDumpFile(this, surf);
     }
   }
 #endif
 
+  EffectChain effectChain(this);
+  LayerManagerComposite::AutoAddMaskEffect autoMaskEffect(mMaskLayer, effectChain);
+  AddBlendModeEffect(effectChain);
 
-  RenderWithAllMasks(this, compositor, aClipRect,
-                     [&](EffectChain& effectChain, const Rect& clipRect) {
-    mBuffer->SetPaintWillResample(MayResample());
+  mBuffer->SetPaintWillResample(MayResample());
 
-    mBuffer->Composite(effectChain,
-                       GetEffectiveOpacity(),
-                       GetEffectiveTransform(),
-                       GetEffectFilter(),
-                       clipRect,
-                       &visibleRegion);
-  });
-
+  mBuffer->Composite(effectChain,
+                     GetEffectiveOpacity(),
+                     GetEffectiveTransform(),
+                     GetEffectFilter(),
+                     clipRect,
+                     &visibleRegion);
   mBuffer->BumpFlashCounter();
 
-  compositor->MakeCurrent();
+  mCompositeManager->GetCompositor()->MakeCurrent();
 }
 
 CompositableHost*
 PaintedLayerComposite::GetCompositableHost()
 {
   if (mBuffer && mBuffer->IsAttached()) {
     return mBuffer.get();
   }
--- a/gfx/layers/ipc/CompositorParent.cpp
+++ b/gfx/layers/ipc/CompositorParent.cpp
@@ -1066,19 +1066,16 @@ CompositorParent::ScheduleComposition()
 // Go down the composite layer tree, setting properties to match their
 // content-side counterparts.
 /* static */ void
 CompositorParent::SetShadowProperties(Layer* aLayer)
 {
   if (Layer* maskLayer = aLayer->GetMaskLayer()) {
     SetShadowProperties(maskLayer);
   }
-  for (size_t i = 0; i < aLayer->GetAncestorMaskLayerCount(); i++) {
-    SetShadowProperties(aLayer->GetAncestorMaskLayerAt(i));
-  }
 
   // FIXME: Bug 717688 -- Do these updates in LayerTransactionParent::RecvUpdate.
   LayerComposite* layerComposite = aLayer->AsLayerComposite();
   // Set the layerComposite's base transform to the layer's base transform.
   layerComposite->SetShadowTransform(aLayer->GetBaseTransform());
   layerComposite->SetShadowTransformSetByAnimation(false);
   layerComposite->SetShadowVisibleRegion(aLayer->GetVisibleRegion());
   layerComposite->SetShadowClipRect(aLayer->GetClipRect());
--- a/gfx/layers/ipc/LayerTransactionParent.cpp
+++ b/gfx/layers/ipc/LayerTransactionParent.cpp
@@ -347,23 +347,16 @@ LayerTransactionParent::RecvUpdate(Infal
         layer->SetMaskLayer(cast(maskLayer)->AsLayer());
       } else {
         layer->SetMaskLayer(nullptr);
       }
       layer->SetAnimations(common.animations());
       layer->SetInvalidRegion(common.invalidRegion());
       layer->SetFrameMetrics(common.metrics());
 
-      nsTArray<nsRefPtr<Layer>> maskLayers;
-      for (size_t i = 0; i < common.ancestorMaskLayersParent().Length(); i++) {
-        Layer* maskLayer = cast(common.ancestorMaskLayersParent().ElementAt(i))->AsLayer();
-        maskLayers.AppendElement(maskLayer);
-      }
-      layer->SetAncestorMaskLayers(maskLayers);
-
       typedef SpecificLayerAttributes Specific;
       const SpecificLayerAttributes& specific = attrs.specific();
       switch (specific.type()) {
       case Specific::Tnull_t:
         break;
 
       case Specific::TPaintedLayerAttributes: {
         MOZ_LAYERS_LOG(("[ParentSide]   painted layer"));
--- a/gfx/layers/ipc/LayersMessages.ipdlh
+++ b/gfx/layers/ipc/LayersMessages.ipdlh
@@ -220,17 +220,16 @@ struct CommonLayerAttributes {
   LayerRect stickyScrollRangeOuter;
   LayerRect stickyScrollRangeInner;
   uint64_t scrollbarTargetContainerId;
   uint32_t scrollbarDirection;
   float scrollbarThumbRatio;
   int8_t mixBlendMode;
   bool forceIsolatedGroup;
   nullable PLayer maskLayer;
-  PLayer[] ancestorMaskLayers;
   // Animated colors will only honored for ColorLayers.
   Animation[] animations;
   nsIntRegion invalidRegion;
   FrameMetrics[] metrics;
   string contentDescription;
 };
 
 struct PaintedLayerAttributes {
--- a/gfx/layers/ipc/ShadowLayers.cpp
+++ b/gfx/layers/ipc/ShadowLayers.cpp
@@ -602,20 +602,16 @@ ShadowLayerForwarder::EndTransaction(Inf
       common.maskLayerChild() = Shadow(maskLayer->AsShadowableLayer());
     } else {
       common.maskLayerChild() = nullptr;
     }
     common.maskLayerParent() = nullptr;
     common.animations() = mutant->GetAnimations();
     common.invalidRegion() = mutant->GetInvalidRegion();
     common.metrics() = mutant->GetAllFrameMetrics();
-    for (size_t i = 0; i < mutant->GetAncestorMaskLayerCount(); i++) {
-      auto layer = Shadow(mutant->GetAncestorMaskLayerAt(i)->AsShadowableLayer());
-      common.ancestorMaskLayersChild().AppendElement(layer);
-    }
     attrs.specific() = null_t();
     mutant->FillSpecificAttributes(attrs.specific());
 
     MOZ_LAYERS_LOG(("[LayersForwarder] OpSetLayerAttributes(%p)\n", mutant));
 
     mTxn->AddEdit(OpSetLayerAttributes(nullptr, Shadow(shadow), attrs));
   }
 
--- a/layout/base/FrameLayerBuilder.cpp
+++ b/layout/base/FrameLayerBuilder.cpp
@@ -1083,24 +1083,18 @@ protected:
    * Grab the next recyclable ImageLayer, or create one if there are no
    * more recyclable ImageLayers.
    */
   already_AddRefed<ImageLayer> CreateOrRecycleImageLayer(PaintedLayer* aPainted);
   /**
    * Grab a recyclable ImageLayer for use as a mask layer for aLayer (that is a
    * mask layer which has been used for aLayer before), or create one if such
    * a layer doesn't exist.
-   *
-   * Since mask layers can exist either on the layer directly, or as a side-
-   * attachment to FrameMetrics (for ancestor scrollframe clips), we key the
-   * recycle operation on both the originating layer and the mask layer's
-   * index in the layer, if any.
    */
-  struct MaskLayerKey;
-  already_AddRefed<ImageLayer> CreateOrRecycleMaskImageLayerFor(const MaskLayerKey& aKey);
+  already_AddRefed<ImageLayer> CreateOrRecycleMaskImageLayerFor(Layer* aLayer);
   /**
    * Grabs all PaintedLayers and ColorLayers from the ContainerLayer and makes them
    * available for recycling.
    */
   void CollectOldLayers();
   /**
    * If aItem used to belong to a PaintedLayer, invalidates the area of
    * aItem in that layer. If aNewLayer is a PaintedLayer, invalidates the area of
@@ -1192,22 +1186,16 @@ protected:
    * aRoundedRectClipCount is used when building mask layers for PaintedLayers,
    * SetupMaskLayer will build a mask layer for only the first
    * aRoundedRectClipCount rounded rects in aClip
    */
   void SetupMaskLayer(Layer *aLayer, const DisplayItemClip& aClip,
                       const nsIntRegion& aLayerVisibleRegion,
                       uint32_t aRoundedRectClipCount = UINT32_MAX);
 
-  already_AddRefed<Layer> CreateMaskLayer(
-    Layer *aLayer, const DisplayItemClip& aClip,
-    const nsIntRegion& aLayerVisibleRegion,
-    const Maybe<size_t>& aForAncestorMaskLayer,
-    uint32_t aRoundedRectClipCount = UINT32_MAX);
-
   bool ChooseAnimatedGeometryRoot(const nsDisplayList& aList,
                                   const nsIFrame **aAnimatedGeometryRoot);
 
   nsDisplayListBuilder*            mBuilder;
   LayerManager*                    mManager;
   FrameLayerBuilder*               mLayerBuilder;
   nsIFrame*                        mContainerFrame;
   nsIFrame*                        mContainerReferenceFrame;
@@ -1230,43 +1218,21 @@ protected:
    * PaintedLayers have two entries in this array: the second one is used only if
    * the PaintedLayer is optimized away to a ColorLayer or ImageLayer.
    * It's essential that this array is only appended to, since PaintedLayerData
    * records the index of its PaintedLayer in this array.
    */
   typedef nsAutoTArray<NewLayerEntry,1> AutoLayersArray;
   AutoLayersArray                  mNewChildLayers;
   nsTHashtable<nsRefPtrHashKey<PaintedLayer>> mPaintedLayersAvailableForRecycling;
+  nsDataHashtable<nsPtrHashKey<Layer>, nsRefPtr<ImageLayer> >
+    mRecycledMaskImageLayers;
   nscoord                          mAppUnitsPerDevPixel;
   bool                             mSnappingEnabled;
   bool                             mFlattenToSingleLayer;
-
-  struct MaskLayerKey {
-    MaskLayerKey() : mLayer(nullptr) {}
-    MaskLayerKey(Layer* aLayer, const Maybe<size_t>& aAncestorIndex)
-      : mLayer(aLayer),
-        mAncestorIndex(aAncestorIndex)
-    {}
-
-    PLDHashNumber Hash() const {
-      // Hash the layer and add the layer index to the hash.
-      return (NS_PTR_TO_UINT32(mLayer) >> 2)
-             + (mAncestorIndex ? (*mAncestorIndex + 1) : 0);
-    }
-    bool operator ==(const MaskLayerKey& aOther) const {
-      return mLayer == aOther.mLayer &&
-             mAncestorIndex == aOther.mAncestorIndex;
-    }
-
-    Layer* mLayer;
-    Maybe<size_t> mAncestorIndex;
-  };
-
-  nsDataHashtable<nsGenericHashKey<MaskLayerKey>, nsRefPtr<ImageLayer>>
-    mRecycledMaskImageLayers;
 };
 
 class PaintedDisplayItemLayerUserData : public LayerUserData
 {
 public:
   PaintedDisplayItemLayerUserData() :
     mMaskClipCount(0),
     mForcedBackgroundColor(NS_RGBA(0,0,0,0)),
@@ -1956,22 +1922,22 @@ ContainerState::CreateOrRecycleImageLaye
 
     // Remove other layer types we might have stored for this PaintedLayer
     data->mColorLayer = nullptr;
   }
   return layer.forget();
 }
 
 already_AddRefed<ImageLayer>
-ContainerState::CreateOrRecycleMaskImageLayerFor(const MaskLayerKey& aKey)
+ContainerState::CreateOrRecycleMaskImageLayerFor(Layer* aLayer)
 {
-  nsRefPtr<ImageLayer> result = mRecycledMaskImageLayers.Get(aKey);
+  nsRefPtr<ImageLayer> result = mRecycledMaskImageLayers.Get(aLayer);
   if (result) {
-    mRecycledMaskImageLayers.Remove(aKey);
-    aKey.mLayer->ClearExtraDumpInfo();
+    mRecycledMaskImageLayers.Remove(aLayer);
+    aLayer->ClearExtraDumpInfo();
     // XXX if we use clip on mask layers, null it out here
   } else {
     // Create a new layer
     result = mManager->CreateImageLayer();
     if (!result)
       return nullptr;
     result->SetUserData(&gMaskLayerUserData, new MaskLayerUserData());
     result->SetDisallowBigImage(true);
@@ -4349,24 +4315,17 @@ ContainerState::CollectOldLayers()
     if (layer->HasUserData(&gPaintedDisplayItemLayerUserData)) {
       NS_ASSERTION(layer->AsPaintedLayer(), "Wrong layer type");
       mPaintedLayersAvailableForRecycling.PutEntry(static_cast<PaintedLayer*>(layer));
     }
 
     if (Layer* maskLayer = layer->GetMaskLayer()) {
       NS_ASSERTION(maskLayer->GetType() == Layer::TYPE_IMAGE,
                    "Could not recycle mask layer, unsupported layer type.");
-      mRecycledMaskImageLayers.Put(MaskLayerKey(layer, Nothing()), static_cast<ImageLayer*>(maskLayer));
-    }
-    for (size_t i = 0; i < layer->GetAncestorMaskLayerCount(); i++) {
-      Layer* maskLayer = layer->GetAncestorMaskLayerAt(i);
-
-      NS_ASSERTION(maskLayer->GetType() == Layer::TYPE_IMAGE,
-                   "Could not recycle mask layer, unsupported layer type.");
-      mRecycledMaskImageLayers.Put(MaskLayerKey(layer, Some(i)), static_cast<ImageLayer*>(maskLayer));
+      mRecycledMaskImageLayers.Put(layer, static_cast<ImageLayer*>(maskLayer));
     }
   }
 }
 
 struct OpaqueRegionEntry {
   const nsIFrame* mAnimatedGeometryRoot;
   const nsIFrame* mFixedPosFrameForLayerData;
   nsIntRegion mOpaqueRegion;
@@ -4394,26 +4353,19 @@ ContainerState::SetupScrollingMetadata(N
     // animated geometry roots are forced to all match, so we can't
     // use them and we don't get async scrolling.
     return;
   }
 
   nsAutoTArray<FrameMetrics,2> metricsArray;
   if (aEntry->mBaseFrameMetrics) {
     metricsArray.AppendElement(*aEntry->mBaseFrameMetrics);
-
-    // The base FrameMetrics was not computed by the nsIScrollableframe, so it
-    // should not have a mask layer.
-    MOZ_ASSERT(!aEntry->mBaseFrameMetrics->GetMaskLayerIndex());
   }
   uint32_t baseLength = metricsArray.Length();
 
-  // Any extra mask layers we need to attach to FrameMetrics.
-  nsTArray<nsRefPtr<Layer>> maskLayers;
-
   nsIFrame* fParent;
   for (const nsIFrame* f = aEntry->mAnimatedGeometryRoot;
        f != mContainerAnimatedGeometryRoot;
        f = nsLayoutUtils::GetAnimatedGeometryRootForFrame(this->mBuilder,
            fParent, mContainerAnimatedGeometryRoot)) {
     fParent = nsLayoutUtils::GetCrossDocParentFrame(f);
     if (!fParent) {
       // This means mContainerAnimatedGeometryRoot was not an ancestor
@@ -4428,48 +4380,21 @@ ContainerState::SetupScrollingMetadata(N
       return;
     }
 
     nsIScrollableFrame* scrollFrame = nsLayoutUtils::GetScrollableFrameFor(f);
     if (!scrollFrame) {
       continue;
     }
 
-    Maybe<FrameMetricsAndClip> info =
-      scrollFrame->ComputeFrameMetrics(aEntry->mLayer, mContainerReferenceFrame, mParameters);
-    if (!info) {
-      continue;
-    }
-
-    FrameMetrics& metrics = info->metrics;
-    const DisplayItemClip* clip = info->clip;
-
-    if (clip &&
-        clip->HasClip() &&
-        clip->GetRoundedRectCount() > 0)
-    {
-      // The clip in between this scrollframe and its ancestor scrollframe
-      // requires a mask layer. Since this mask layer should not move with
-      // the APZC associated with this FrameMetrics, we attach the mask
-      // layer as an additional, separate clip.
-      Maybe<size_t> nextIndex = Some(maskLayers.Length());
-      nsRefPtr<Layer> maskLayer =
-        CreateMaskLayer(aEntry->mLayer, *clip, aEntry->mVisibleRegion, nextIndex, clip->GetRoundedRectCount());
-      if (maskLayer) {
-        metrics.SetMaskLayerIndex(nextIndex);
-        maskLayers.AppendElement(maskLayer);
-      }
-    }
-
-    metricsArray.AppendElement(metrics);
-  }
-
+    scrollFrame->ComputeFrameMetrics(aEntry->mLayer, mContainerReferenceFrame,
+                                     mParameters, &metricsArray);
+  }
   // Watch out for FrameMetrics copies in profiles
   aEntry->mLayer->SetFrameMetrics(metricsArray);
-  aEntry->mLayer->SetAncestorMaskLayers(maskLayers);
 }
 
 static void
 InvalidateVisibleBoundsChangesForScrolledLayer(PaintedLayer* aLayer)
 {
   PaintedDisplayItemLayerUserData* data =
     static_cast<PaintedDisplayItemLayerUserData*>(aLayer->GetUserData(&gPaintedDisplayItemLayerUserData));
 
@@ -5707,49 +5632,31 @@ ContainerState::SetupMaskLayer(Layer *aL
   nsIntRect layerBounds = aLayerVisibleRegion.GetBounds();
   if (aClip.GetRoundedRectCount() == 0 ||
       aRoundedRectClipCount == 0 ||
       layerBounds.IsEmpty()) {
     SetClipCount(paintedData, 0);
     return;
   }
 
-  nsRefPtr<Layer> maskLayer =
-    CreateMaskLayer(aLayer, aClip, aLayerVisibleRegion, Nothing(), aRoundedRectClipCount);
-
-  if (!maskLayer) {
-    SetClipCount(paintedData, 0);
-    return;
-  }
-
-  aLayer->SetMaskLayer(maskLayer);
-  SetClipCount(paintedData, aRoundedRectClipCount);
-}
-
-already_AddRefed<Layer>
-ContainerState::CreateMaskLayer(Layer *aLayer,
-                               const DisplayItemClip& aClip,
-                               const nsIntRegion& aLayerVisibleRegion,
-                               const Maybe<size_t>& aForAncestorMaskLayer,
-                               uint32_t aRoundedRectClipCount)
-{
   // check if we can re-use the mask layer
-  MaskLayerKey recycleKey(aLayer, aForAncestorMaskLayer);
-  nsRefPtr<ImageLayer> maskLayer = CreateOrRecycleMaskImageLayerFor(recycleKey);
+  nsRefPtr<ImageLayer> maskLayer =  CreateOrRecycleMaskImageLayerFor(aLayer);
   MaskLayerUserData* userData = GetMaskLayerUserData(maskLayer);
 
   MaskLayerUserData newData;
   aClip.AppendRoundedRects(&newData.mRoundedClipRects, aRoundedRectClipCount);
   newData.mScaleX = mParameters.mXScale;
   newData.mScaleY = mParameters.mYScale;
   newData.mOffset = mParameters.mOffset;
   newData.mAppUnitsPerDevPixel = mContainerFrame->PresContext()->AppUnitsPerDevPixel();
 
   if (*userData == newData) {
-    return maskLayer.forget();
+    aLayer->SetMaskLayer(maskLayer);
+    SetClipCount(paintedData, aRoundedRectClipCount);
+    return;
   }
 
   // calculate a more precise bounding rect
   gfx::Rect boundingRect = CalculateBounds(newData.mRoundedClipRects,
                                            newData.mAppUnitsPerDevPixel);
   boundingRect.Scale(mParameters.mXScale, mParameters.mYScale);
 
   uint32_t maxSize = mManager->GetMaxTextureSize();
@@ -5792,17 +5699,18 @@ ContainerState::CreateMaskLayer(Layer *a
                            NSToIntCeil(surfaceSize.height));
     // no existing mask image, so build a new one
     RefPtr<DrawTarget> dt =
       aLayer->Manager()->CreateOptimalMaskDrawTarget(surfaceSizeInt);
 
     // fail if we can't get the right surface
     if (!dt) {
       NS_WARNING("Could not create DrawTarget for mask layer.");
-      return nullptr;
+      SetClipCount(paintedData, 0);
+      return;
     }
 
     nsRefPtr<gfxContext> context = new gfxContext(dt);
     context->Multiply(ThebesMatrix(imageTransform));
 
     // paint the clipping rects with alpha to create the mask
     aClip.FillIntersectionOfRoundedRectClips(context,
                                              Color(1.f, 1.f, 1.f, 1.f),
@@ -5837,12 +5745,14 @@ ContainerState::CreateMaskLayer(Layer *a
   // save the details of the clip in user data
   userData->mScaleX = newData.mScaleX;
   userData->mScaleY = newData.mScaleY;
   userData->mOffset = newData.mOffset;
   userData->mAppUnitsPerDevPixel = newData.mAppUnitsPerDevPixel;
   userData->mRoundedClipRects.SwapElements(newData.mRoundedClipRects);
   userData->mImageKey = lookupKey;
 
-  return maskLayer.forget();
+  aLayer->SetMaskLayer(maskLayer);
+  SetClipCount(paintedData, aRoundedRectClipCount);
+  return;
 }
 
 } // namespace mozilla
--- a/layout/generic/nsGfxScrollFrame.cpp
+++ b/layout/generic/nsGfxScrollFrame.cpp
@@ -2937,28 +2937,16 @@ ScrollFrameHelper::BuildDisplayList(nsDi
     // of scroll layers, and we want to maintain consistent behaviour between scroll layers
     // and scroll info layers.
     nsDisplayListBuilder::AutoCurrentScrollParentIdSetter idSetter(
         aBuilder,
         shouldBuildLayer && mScrolledFrame->GetContent()
             ? nsLayoutUtils::FindOrCreateIDFor(mScrolledFrame->GetContent())
             : aBuilder->GetCurrentScrollParentId());
     DisplayListClipState::AutoSaveRestore clipState(aBuilder);
-    if (!mIsRoot || !usingDisplayport) {
-      nsRect clip = mScrollPort + aBuilder->ToReferenceFrame(mOuter);
-      nscoord radii[8];
-      bool haveRadii = mOuter->GetPaddingBoxBorderRadii(radii);
-      // Our override of GetBorderRadii ensures we never have a radius at
-      // the corners where we have a scrollbar.
-      if (mClipAllDescendants) {
-        clipState.ClipContentDescendants(clip, haveRadii ? radii : nullptr);
-      } else {
-        clipState.ClipContainingBlockDescendants(clip, haveRadii ? radii : nullptr);
-      }
-    }
 
     if (usingDisplayport) {
       // Capture the clip state of the parent scroll frame. This will be saved
       // on FrameMetrics for layers with this frame as their animated geoemetry
       // root.
       mAncestorClip = aBuilder->ClipState().GetCurrentCombinedClip(aBuilder);
 
       // If we are using a display port, then ignore any pre-existing clip
@@ -2969,16 +2957,27 @@ ScrollFrameHelper::BuildDisplayList(nsDi
       //   - The pre-existing clip state will be restored when the
       //     AutoSaveRestore goes out of scope, so there is no permanent change
       //     to this clip state.
       //   - We still set a clip to the scroll port further below where we
       //     build the scroll wrapper. This doesn't prevent us from painting
       //     the entire displayport, but it lets the compositor know to
       //     clip to the scroll port after compositing.
       clipState.Clear();
+    } else {
+      nsRect clip = mScrollPort + aBuilder->ToReferenceFrame(mOuter);
+      nscoord radii[8];
+      bool haveRadii = mOuter->GetPaddingBoxBorderRadii(radii);
+      // Our override of GetBorderRadii ensures we never have a radius at
+      // the corners where we have a scrollbar.
+      if (mClipAllDescendants) {
+        clipState.ClipContentDescendants(clip, haveRadii ? radii : nullptr);
+      } else {
+        clipState.ClipContainingBlockDescendants(clip, haveRadii ? radii : nullptr);
+      }
     }
 
     aBuilder->StoreDirtyRectForScrolledContents(mOuter, dirtyRect);
     mOuter->BuildDisplayListForChild(aBuilder, mScrolledFrame, dirtyRect, scrolledContent);
 
     if (idSetter.ShouldForceLayerForScrollParent() &&
         !gfxPrefs::LayoutUseContainersForRootFrames())
     {
@@ -3048,23 +3047,24 @@ ScrollFrameHelper::BuildDisplayList(nsDi
     }
   }
   // Now display overlay scrollbars and the resizer, if we have one.
   AppendScrollPartsTo(aBuilder, aDirtyRect, scrolledContent, usingDisplayport,
                       createLayersForScrollbars, true);
   scrolledContent.MoveTo(aLists);
 }
 
-Maybe<FrameMetricsAndClip>
+void
 ScrollFrameHelper::ComputeFrameMetrics(Layer* aLayer,
                                        nsIFrame* aContainerReferenceFrame,
-                                       const ContainerLayerParameters& aParameters) const
+                                       const ContainerLayerParameters& aParameters,
+                                       nsTArray<FrameMetrics>* aOutput) const
 {
   if (!mShouldBuildScrollableLayer || mIsScrollableLayerInRootContainer) {
-    return Nothing();
+    return;
   }
 
   bool needsParentLayerClip = true;
   if (gfxPrefs::LayoutUseContainersForRootFrames() && !mAddClipRectToLayer) {
     // For containerful frames, the clip is on the container frame.
     needsParentLayerClip = false;
   }
 
@@ -3112,31 +3112,27 @@ ScrollFrameHelper::ComputeFrameMetrics(L
         layerClip = displayportClip.Intersect(*origClip);
       } else {
         layerClip = displayportClip;
       }
       aLayer->SetClipRect(Some(layerClip));
     }
 
     // Return early, since if we don't use APZ we don't need FrameMetrics.
-    return Nothing();
+    return;
   }
 
   MOZ_ASSERT(mScrolledFrame->GetContent());
 
-  FrameMetricsAndClip result;
-
   nsRect scrollport = mScrollPort + toReferenceFrame;
-  result.metrics = nsLayoutUtils::ComputeFrameMetrics(
-    mScrolledFrame, mOuter, mOuter->GetContent(),
-    aContainerReferenceFrame, aLayer, mScrollParentID,
-    scrollport, parentLayerClip, isRootContent, aParameters);
-  result.clip = mAncestorClip;
-
-  return Some(result);
+  *aOutput->AppendElement() =
+      nsLayoutUtils::ComputeFrameMetrics(
+        mScrolledFrame, mOuter, mOuter->GetContent(),
+        aContainerReferenceFrame, aLayer, mScrollParentID,
+        scrollport, parentLayerClip, isRootContent, aParameters);
 }
 
 bool
 ScrollFrameHelper::IsRectNearlyVisible(const nsRect& aRect) const
 {
   // Use the right rect depending on if a display port is set.
   nsRect displayPort;
   bool usingDisplayport = nsLayoutUtils::GetDisplayPort(mOuter->GetContent(), &displayPort);
--- a/layout/generic/nsGfxScrollFrame.h
+++ b/layout/generic/nsGfxScrollFrame.h
@@ -372,19 +372,19 @@ public:
   nsPoint LastScrollDestination() const { return mDestination; }
   void ResetScrollInfoIfGeneration(uint32_t aGeneration) {
     if (aGeneration == mScrollGeneration) {
       mLastScrollOrigin = nullptr;
       mLastSmoothScrollOrigin = nullptr;
     }
   }
   bool WantAsyncScroll() const;
-  Maybe<FrameMetricsAndClip> ComputeFrameMetrics(
-    Layer* aLayer, nsIFrame* aContainerReferenceFrame,
-    const ContainerLayerParameters& aParameters) const;
+  void ComputeFrameMetrics(Layer* aLayer, nsIFrame* aContainerReferenceFrame,
+                           const ContainerLayerParameters& aParameters,
+                           nsTArray<FrameMetrics>* aOutput) const;
 
   // nsIScrollbarMediator
   void ScrollByPage(nsScrollbarFrame* aScrollbar, int32_t aDirection,
                     nsIScrollbarMediator::ScrollSnapMode aSnap
                       = nsIScrollbarMediator::DISABLE_SNAP);
   void ScrollByWhole(nsScrollbarFrame* aScrollbar, int32_t aDirection,
                      nsIScrollbarMediator::ScrollSnapMode aSnap
                        = nsIScrollbarMediator::DISABLE_SNAP);
@@ -829,21 +829,21 @@ public:
     return mHelper.LastScrollDestination();
   }
   virtual void ResetScrollInfoIfGeneration(uint32_t aGeneration) override {
     mHelper.ResetScrollInfoIfGeneration(aGeneration);
   }
   virtual bool WantAsyncScroll() const override {
     return mHelper.WantAsyncScroll();
   }
-  virtual mozilla::Maybe<mozilla::FrameMetricsAndClip> ComputeFrameMetrics(
-    Layer* aLayer, nsIFrame* aContainerReferenceFrame,
-    const ContainerLayerParameters& aParameters) const override
-  {
-    return mHelper.ComputeFrameMetrics(aLayer, aContainerReferenceFrame, aParameters);
+  virtual void ComputeFrameMetrics(Layer* aLayer, nsIFrame* aContainerReferenceFrame,
+                                   const ContainerLayerParameters& aParameters,
+                                   nsTArray<FrameMetrics>* aOutput) const override {
+    mHelper.ComputeFrameMetrics(aLayer, aContainerReferenceFrame,
+                                aParameters, aOutput);
   }
   virtual bool IsIgnoringViewportClipping() const override {
     return mHelper.IsIgnoringViewportClipping();
   }
   virtual void MarkScrollbarsDirtyForReflow() const override {
     mHelper.MarkScrollbarsDirtyForReflow();
   }
   virtual bool UsesContainerScrolling() const override {
@@ -1224,21 +1224,21 @@ public:
     return mHelper.LastScrollDestination();
   }
   virtual void ResetScrollInfoIfGeneration(uint32_t aGeneration) override {
     mHelper.ResetScrollInfoIfGeneration(aGeneration);
   }
   virtual bool WantAsyncScroll() const override {
     return mHelper.WantAsyncScroll();
   }
-  virtual mozilla::Maybe<mozilla::FrameMetricsAndClip> ComputeFrameMetrics(
-    Layer* aLayer, nsIFrame* aContainerReferenceFrame,
-    const ContainerLayerParameters& aParameters) const override
-  {
-    return mHelper.ComputeFrameMetrics(aLayer, aContainerReferenceFrame, aParameters);
+  virtual void ComputeFrameMetrics(Layer* aLayer, nsIFrame* aContainerReferenceFrame,
+                                   const ContainerLayerParameters& aParameters,
+                                   nsTArray<FrameMetrics>* aOutput) const override {
+    mHelper.ComputeFrameMetrics(aLayer, aContainerReferenceFrame,
+                                aParameters, aOutput);
   }
   virtual bool IsIgnoringViewportClipping() const override {
     return mHelper.IsIgnoringViewportClipping();
   }
   virtual void MarkScrollbarsDirtyForReflow() const override {
     mHelper.MarkScrollbarsDirtyForReflow();
   }
 
--- a/layout/generic/nsIScrollableFrame.h
+++ b/layout/generic/nsIScrollableFrame.h
@@ -27,28 +27,20 @@ class nsIFrame;
 class nsPresContext;
 class nsIContent;
 class nsRenderingContext;
 class nsIAtom;
 class nsDisplayListBuilder;
 
 namespace mozilla {
 struct ContainerLayerParameters;
-class DisplayItemClip;
 namespace layers {
 class Layer;
 }
-
-struct FrameMetricsAndClip
-{
-  layers::FrameMetrics metrics;
-  const DisplayItemClip* clip;
-};
-
-} // namespace mozilla
+}
 
 /**
  * Interface for frames that are scrollable. This interface exposes
  * APIs for examining scroll state, observing changes to scroll state,
  * and triggering scrolling.
  */
 class nsIScrollableFrame : public nsIScrollbarMediator {
 public:
@@ -418,20 +410,20 @@ public:
    * Determine whether it is desirable to be able to asynchronously scroll this
    * scroll frame.
    */
   virtual bool WantAsyncScroll() const = 0;
   /**
    * aLayer's animated geometry root is this frame. If there needs to be a
    * FrameMetrics contributed by this frame, append it to aOutput.
    */
-  virtual mozilla::Maybe<mozilla::FrameMetricsAndClip> ComputeFrameMetrics(
-    mozilla::layers::Layer* aLayer,
-    nsIFrame* aContainerReferenceFrame,
-    const ContainerLayerParameters& aParameters) const = 0;
+  virtual void ComputeFrameMetrics(mozilla::layers::Layer* aLayer,
+                                   nsIFrame* aContainerReferenceFrame,
+                                   const ContainerLayerParameters& aParameters,
+                                   nsTArray<FrameMetrics>* aOutput) const = 0;
 
   /**
    * If this scroll frame is ignoring viewporting clipping
    */
   virtual bool IsIgnoringViewportClipping() const = 0;
 
   /**
    * Mark the scrollbar frames for reflow.