Bug 1313898 - Part 1. Re-implement CSSMaskLayerUserData invalidation detection. draft
authorcku <cku@mozilla.com>
Tue, 15 Nov 2016 12:26:21 +0800
changeset 440216 e1d8172b0c34077cbc814f1cebe059a2a77e85ae
parent 440163 c27117f67fa3ff30bbd34bcd6c7536c0d10bd4ad
child 440217 5a11bcc7a13602d8d4b13d09c2960e921c814e6f
push id36178
push userbmo:cku@mozilla.com
push dateThu, 17 Nov 2016 04:49:39 +0000
bugs1313898
milestone53.0a1
Bug 1313898 - Part 1. Re-implement CSSMaskLayerUserData invalidation detection. MozReview-Commit-ID: 6VE7plONyaS
layout/base/FrameLayerBuilder.cpp
--- a/layout/base/FrameLayerBuilder.cpp
+++ b/layout/base/FrameLayerBuilder.cpp
@@ -1562,102 +1562,54 @@ struct MaskLayerUserData : public LayerU
 };
 
 /*
  * User data for layers which will be used as masks for css positioned mask.
  */
 struct CSSMaskLayerUserData : public LayerUserData
 {
   CSSMaskLayerUserData()
-    : mImageLayers(nsStyleImageLayers::LayerType::Mask)
+    : mFrame(nullptr)
   { }
 
-  CSSMaskLayerUserData(nsIFrame* aFrame, const nsIntRect& aBounds)
-    : mImageLayers(aFrame->StyleSVGReset()->mMask),
-      mContentRect(aFrame->GetContentRectRelativeToSelf()),
-      mPaddingRect(aFrame->GetPaddingRectRelativeToSelf()),
-      mBorderRect(aFrame->GetRectRelativeToSelf()),
-      mMarginRect(aFrame->GetMarginRectRelativeToSelf()),
-      mBounds(aBounds)
-  {
-    Hash(aFrame);
-  }
+  CSSMaskLayerUserData(nsIFrame* aFrame, const nsIntSize& aMaskSize)
+    : mFrame(aFrame),
+      mMaskSize(aMaskSize)
+  { }
 
   CSSMaskLayerUserData& operator=(const CSSMaskLayerUserData& aOther)
   {
-    mImageLayers = aOther.mImageLayers;
-
-    mContentRect = aOther.mContentRect;
-    mPaddingRect = aOther.mPaddingRect;
-    mBorderRect = aOther.mBorderRect;
-    mMarginRect = aOther.mMarginRect;
-
-    mBounds = aOther.mBounds;
-
-    mHash = aOther.mHash;
+    mFrame = aOther.mFrame;
+    mMaskSize = aOther.mMaskSize;
 
     return *this;
   }
 
   bool
   operator==(const CSSMaskLayerUserData& aOther) const
   {
-    if (mHash != aOther.mHash) {
-      return false;
-    }
-
-    if (mImageLayers.mLayers != aOther.mImageLayers.mLayers) {
+    if (mFrame != aOther.mFrame) {
       return false;
     }
 
-    if (!mContentRect.IsEqualEdges(aOther.mContentRect) ||
-        !mPaddingRect.IsEqualEdges(aOther.mPaddingRect) ||
-        !mBorderRect.IsEqualEdges(aOther.mBorderRect) ||
-        !mMarginRect.IsEqualEdges(aOther.mMarginRect)) {
-      return false;
-    }
-
-    if (!mBounds.IsEqualEdges(aOther.mBounds)) {
+    // 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;
   }
 
 private:
-  void Hash(nsIFrame* aFrame)
-  {
-    uint32_t hash = 0;
-
-    const nsStyleImageLayers& imageLayers = aFrame->StyleSVGReset()->mMask;
-    for (uint32_t i = 0; i < imageLayers.mLayers.Length(); i++) {
-      const nsStyleImageLayers::Layer& newLayer = imageLayers.mLayers[i];
-      hash = AddToHash(hash, HashBytes(&newLayer, sizeof(newLayer)));
-    }
-
-    hash = AddToHash(hash, HashBytes(&mContentRect, sizeof(mContentRect)));
-    hash = AddToHash(hash, HashBytes(&mPaddingRect, sizeof(mPaddingRect)));
-    hash = AddToHash(hash, HashBytes(&mBorderRect, sizeof(mBorderRect)));
-    hash = AddToHash(hash, HashBytes(&mMarginRect, sizeof(mMarginRect)));
-
-    hash = AddToHash(hash, HashBytes(&mBounds, sizeof(mBounds)));
-
-    mHash = hash;
-  }
-
-  nsStyleImageLayers mImageLayers;
-
-  nsRect mContentRect;
-  nsRect mPaddingRect;
-  nsRect mBorderRect;
-  nsRect mMarginRect;
-
-  nsIntRect mBounds;
-
-  uint32_t mHash;
+  nsIFrame* mFrame;
+  nsIntSize mMaskSize;
 };
 
 /*
  * 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
@@ -3910,18 +3862,19 @@ ContainerState::SetupMaskLayerForCSSMask
     );
 
   CSSMaskLayerUserData* oldUserData =
     static_cast<CSSMaskLayerUserData*>(maskLayer->GetUserData(&gCSSMaskLayerUserData));
 
   bool snap;
   nsRect bounds = aMaskItem->GetBounds(mBuilder, &snap);
   nsIntRect itemRect = ScaleToOutsidePixels(bounds, snap);
-  CSSMaskLayerUserData newUserData(aMaskItem->Frame(), itemRect);
-  if (*oldUserData == newUserData) {
+  CSSMaskLayerUserData newUserData(aMaskItem->Frame(), itemRect.Size());
+  nsRect dirtyRect;
+  if (!aMaskItem->IsInvalid(dirtyRect) && *oldUserData == newUserData) {
     aLayer->SetMaskLayer(maskLayer);
     return;
   }
 
   int32_t maxSize = mManager->GetMaxTextureSize();
   IntSize surfaceSize(std::min(itemRect.width, maxSize),
                       std::min(itemRect.height, maxSize));