Bug 1329091 - Keep mask style value to determine whether cached mask layer is corrupt. r=mstange
authorcku <cku@mozilla.com>
Fri, 06 Jan 2017 17:53:30 +0800
changeset 375576 253205df9e44f52070872e796bd8f8097065ddd7
parent 375575 fd4b40c65e7e42d51568e30df4547611cd259dcc
child 375577 755b68896241529dc6c5c4e5de066e296154a114
push id1419
push userjlund@mozilla.com
push dateMon, 10 Apr 2017 20:44:07 +0000
treeherdermozilla-release@5e6801b73ef6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmstange
bugs1329091
milestone53.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1329091 - Keep mask style value to determine whether cached mask layer is corrupt. r=mstange MozReview-Commit-ID: J2CFFi5pN7H
layout/painting/FrameLayerBuilder.cpp
layout/style/nsStyleStruct.cpp
layout/style/nsStyleStruct.h
--- a/layout/painting/FrameLayerBuilder.cpp
+++ b/layout/painting/FrameLayerBuilder.cpp
@@ -1571,54 +1571,49 @@ struct MaskLayerUserData : public LayerU
 };
 
 /*
  * User data for layers which will be used as masks for css positioned mask.
  */
 struct CSSMaskLayerUserData : public LayerUserData
 {
   CSSMaskLayerUserData()
-    : mFrame(nullptr)
+    : mMaskStyle(nsStyleImageLayers::LayerType::Mask)
   { }
 
   CSSMaskLayerUserData(nsIFrame* aFrame, const nsIntSize& aMaskSize)
-    : mFrame(aFrame),
-      mMaskSize(aMaskSize)
-  { }
-
-  CSSMaskLayerUserData& operator=(const CSSMaskLayerUserData& aOther)
+    : mMaskSize(aMaskSize),
+      mMaskStyle(aFrame->StyleSVGReset()->mMask)
   {
-    mFrame = aOther.mFrame;
+  }
+
+  void operator=(CSSMaskLayerUserData&& aOther)
+  {
     mMaskSize = aOther.mMaskSize;
-
-    return *this;
+    mMaskStyle = Move(aOther.mMaskStyle);
   }
 
   bool
   operator==(const CSSMaskLayerUserData& aOther) const
   {
-    if (mFrame != aOther.mFrame) {
-      return false;
-    }
-
     // Even if the frame is valid, check the size of the display item's
     // boundary is still necessary. For example, if we scale the masked frame
     // by adding a transform property on it, the masked frame is valid itself
     // but we have to regenerate mask according to the new size in device
     // space.
     if (mMaskSize != aOther.mMaskSize) {
       return false;
     }
 
-    return true;
+    return mMaskStyle == aOther.mMaskStyle;
   }
 
 private:
-  nsIFrame* mFrame;
   nsIntSize mMaskSize;
+  nsStyleImageLayers mMaskStyle;
 };
 
 /*
  * A helper object to create a draw target for painting mask and create a
  * image container to hold the drawing result. The caller can then bind this
  * image container with a image mask layer via ImageLayer::SetContainer.
  */
 class MaskImageData
@@ -3928,17 +3923,17 @@ ContainerState::SetupMaskLayerForCSSMask
 
   RefPtr<ImageContainer> imgContainer =
     imageData.CreateImageAndImageContainer();
   if (!imgContainer) {
     return;
   }
   maskLayer->SetContainer(imgContainer);
 
-  *oldUserData = newUserData;
+  *oldUserData = Move(newUserData);
   aLayer->SetMaskLayer(maskLayer);
 }
 
 /*
  * Iterate through the non-clip items in aList and its descendants.
  * For each item we compute the effective clip rect. Each item is assigned
  * to a layer. We invalidate the areas in PaintedLayers where an item
  * has moved from one PaintedLayer to another. Also,
--- a/layout/style/nsStyleStruct.cpp
+++ b/layout/style/nsStyleStruct.cpp
@@ -2598,16 +2598,89 @@ nsStyleImageLayers::operator=(const nsSt
     mMaskModeCount = std::max(mMaskModeCount, count);
     mBlendModeCount = std::max(mBlendModeCount, count);
     mCompositeCount = std::max(mCompositeCount, count);
   }
 
   return *this;
 }
 
+nsStyleImageLayers&
+nsStyleImageLayers::operator=(nsStyleImageLayers&& aOther)
+{
+  mAttachmentCount = aOther.mAttachmentCount;
+  mClipCount = aOther.mClipCount;
+  mOriginCount = aOther.mOriginCount;
+  mRepeatCount = aOther.mRepeatCount;
+  mPositionXCount = aOther.mPositionXCount;
+  mPositionYCount = aOther.mPositionYCount;
+  mImageCount = aOther.mImageCount;
+  mSizeCount = aOther.mSizeCount;
+  mMaskModeCount = aOther.mMaskModeCount;
+  mBlendModeCount = aOther.mBlendModeCount;
+  mCompositeCount = aOther.mCompositeCount;
+  mLayers = Move(aOther.mLayers);
+
+  uint32_t count = mLayers.Length();
+  if (count != aOther.mLayers.Length()) {
+    NS_WARNING("truncating counts due to out-of-memory");
+    mAttachmentCount = std::max(mAttachmentCount, count);
+    mClipCount = std::max(mClipCount, count);
+    mOriginCount = std::max(mOriginCount, count);
+    mRepeatCount = std::max(mRepeatCount, count);
+    mPositionXCount = std::max(mPositionXCount, count);
+    mPositionYCount = std::max(mPositionYCount, count);
+    mImageCount = std::max(mImageCount, count);
+    mSizeCount = std::max(mSizeCount, count);
+    mMaskModeCount = std::max(mMaskModeCount, count);
+    mBlendModeCount = std::max(mBlendModeCount, count);
+    mCompositeCount = std::max(mCompositeCount, count);
+  }
+
+  return *this;
+}
+
+bool nsStyleImageLayers::operator==(const nsStyleImageLayers& aOther) const
+{
+  if (mAttachmentCount != aOther.mAttachmentCount ||
+      mClipCount != aOther.mClipCount ||
+      mOriginCount != aOther.mOriginCount ||
+      mRepeatCount != aOther.mRepeatCount ||
+      mPositionXCount != aOther.mPositionXCount ||
+      mPositionYCount != aOther.mPositionYCount ||
+      mImageCount != aOther.mImageCount ||
+      mSizeCount != aOther.mSizeCount ||
+      mMaskModeCount != aOther.mMaskModeCount ||
+      mBlendModeCount != aOther.mBlendModeCount) {
+    return false;
+  }
+
+  if (mLayers.Length() != aOther.mLayers.Length()) {
+    return false;
+  }
+
+  for (uint32_t i = 0; i < mLayers.Length(); i++) {
+    if (mLayers[i].mPosition != aOther.mLayers[i].mPosition ||
+        !DefinitelyEqualURIs(mLayers[i].mSourceURI, aOther.mLayers[i].mSourceURI) ||
+        mLayers[i].mImage != aOther.mLayers[i].mImage ||
+        mLayers[i].mSize != aOther.mLayers[i].mSize ||
+        mLayers[i].mClip != aOther.mLayers[i].mClip ||
+        mLayers[i].mOrigin != aOther.mLayers[i].mOrigin ||
+        mLayers[i].mAttachment != aOther.mLayers[i].mAttachment ||
+        mLayers[i].mBlendMode != aOther.mLayers[i].mBlendMode ||
+        mLayers[i].mComposite != aOther.mLayers[i].mComposite ||
+        mLayers[i].mMaskMode != aOther.mLayers[i].mMaskMode ||
+        mLayers[i].mRepeat != aOther.mLayers[i].mRepeat) {
+      return false;
+    }
+  }
+
+  return true;
+}
+
 bool
 nsStyleImageLayers::IsInitialPositionForLayerType(Position aPosition, LayerType aType)
 {
   if (aPosition.mXPosition.mPercent == 0.0f &&
       aPosition.mXPosition.mLength == 0 &&
       aPosition.mXPosition.mHasPercent &&
       aPosition.mYPosition.mPercent == 0.0f &&
       aPosition.mYPosition.mLength == 0 &&
--- a/layout/style/nsStyleStruct.h
+++ b/layout/style/nsStyleStruct.h
@@ -620,16 +620,23 @@ public:
     return Length() == aOther.Length() &&
            mFirstElement == aOther.mFirstElement &&
            mOtherElements == aOther.mOtherElements;
   }
   bool operator!=(const nsStyleAutoArray& aOther) const {
     return !(*this == aOther);
   }
 
+  nsStyleAutoArray& operator=(nsStyleAutoArray&& aOther) {
+    mFirstElement = aOther.mFirstElement;
+    mOtherElements.SwapElements(aOther.mOtherElements);
+
+    return *this;
+  }
+
   size_t Length() const {
     return mOtherElements.Length() + 1;
   }
   const T& operator[](size_t aIndex) const {
     return aIndex == 0 ? mFirstElement : mOtherElements[aIndex - 1];
   }
   T& operator[](size_t aIndex) {
     return aIndex == 0 ? mFirstElement : mOtherElements[aIndex - 1];
@@ -894,16 +901,18 @@ struct nsStyleImageLayers {
     }
   }
 
   nsChangeHint CalcDifference(const nsStyleImageLayers& aNewLayers,
                               nsStyleImageLayers::LayerType aType) const;
 
   bool HasLayerWithImage() const;
   nsStyleImageLayers& operator=(const nsStyleImageLayers& aOther);
+  nsStyleImageLayers& operator=(nsStyleImageLayers&& aOther);
+  bool operator==(const nsStyleImageLayers& aOther) const;
 
   static const nsCSSPropertyID kBackgroundLayerTable[];
   static const nsCSSPropertyID kMaskLayerTable[];
 
   #define NS_FOR_VISIBLE_IMAGE_LAYERS_BACK_TO_FRONT(var_, layers_) \
     for (uint32_t var_ = (layers_).mImageCount; var_-- != 0; )
   #define NS_FOR_VISIBLE_IMAGE_LAYERS_BACK_TO_FRONT_WITH_RANGE(var_, layers_, start_, count_) \
     NS_ASSERTION((int32_t)(start_) >= 0 && (uint32_t)(start_) < (layers_).mImageCount, "Invalid layer start!"); \