Bug 1554777 - Use SIZE_AVAILABLE rather than loaded to figure out whether to try to draw a border image. r=tnikkel
authorEmilio Cobos Álvarez <emilio@crisal.io>
Thu, 15 Aug 2019 19:03:06 +0000
changeset 488474 87ed773c0a80425133bae39146f06de4a7425974
parent 488473 da9ae31b5000eccbc38438680952ff08d06addea
child 488475 9cd5f82e915c28e57a8c35a3fe1dd9d3a75c7f71
push id92769
push userealvarez@mozilla.com
push dateFri, 16 Aug 2019 09:49:34 +0000
treeherderautoland@87ed773c0a80 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerstnikkel
bugs1554777
milestone70.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 1554777 - Use SIZE_AVAILABLE rather than loaded to figure out whether to try to draw a border image. r=tnikkel The current code needs to handle incomplete draws already due to async decoding, and this prevents the race condition where we paint between the size-available and load notifications, as the CSS image loader only invalidates for the first. Once we try to decode the image at least once, then we'd repaint properly from ImageLoader::OnFrameComplete. Differential Revision: https://phabricator.services.mozilla.com/D41006
layout/painting/nsDisplayList.cpp
layout/painting/nsDisplayList.h
layout/style/nsStyleStruct.cpp
layout/style/nsStyleStruct.h
--- a/layout/painting/nsDisplayList.cpp
+++ b/layout/painting/nsDisplayList.cpp
@@ -5630,17 +5630,17 @@ nsDisplayBorder::nsDisplayBorder(nsDispl
 
   mBounds = CalculateBounds<nsRect>(*mFrame->StyleBorder());
 }
 
 bool nsDisplayBorder::IsInvisibleInRect(const nsRect& aRect) const {
   nsRect paddingRect = GetPaddingRect();
   const nsStyleBorder* styleBorder;
   if (paddingRect.Contains(aRect) &&
-      !(styleBorder = mFrame->StyleBorder())->IsBorderImageLoaded() &&
+      !(styleBorder = mFrame->StyleBorder())->IsBorderImageSizeAvailable() &&
       !nsLayoutUtils::HasNonZeroCorner(styleBorder->mBorderRadius)) {
     // aRect is entirely inside the content rect, and no part
     // of the border is rendered inside the content rect, so we are not
     // visible
     // Skip this if there's a border-image (which draws a background
     // too) or if there is a border-radius (which makes the border draw
     // further in).
     return true;
--- a/layout/painting/nsDisplayList.h
+++ b/layout/painting/nsDisplayList.h
@@ -4263,17 +4263,17 @@ class nsDisplayBorder : public nsPainted
     *aSnap = true;
     return CalculateBounds<nsRegion>(*mFrame->StyleBorder());
   }
 
  protected:
   template <typename T>
   T CalculateBounds(const nsStyleBorder& aStyleBorder) const {
     nsRect borderBounds(ToReferenceFrame(), mFrame->GetSize());
-    if (aStyleBorder.IsBorderImageLoaded()) {
+    if (aStyleBorder.IsBorderImageSizeAvailable()) {
       borderBounds.Inflate(aStyleBorder.GetImageOutset());
       return borderBounds;
     }
 
     nsMargin border = aStyleBorder.GetComputedBorder();
     T result;
     if (border.top > 0) {
       result = nsRect(borderBounds.X(), borderBounds.Y(), borderBounds.Width(),
--- a/layout/style/nsStyleStruct.cpp
+++ b/layout/style/nsStyleStruct.cpp
@@ -1965,32 +1965,32 @@ bool nsStyleImage::IsComplete() const {
              (status & imgIRequest::STATUS_FRAME_COMPLETE);
     }
     default:
       MOZ_ASSERT_UNREACHABLE("unexpected image type");
       return false;
   }
 }
 
-bool nsStyleImage::IsLoaded() const {
+bool nsStyleImage::IsSizeAvailable() const {
   switch (mType) {
     case eStyleImageType_Null:
       return false;
     case eStyleImageType_Gradient:
     case eStyleImageType_Element:
       return true;
     case eStyleImageType_Image: {
       imgRequestProxy* req = GetImageData();
       if (!req) {
         return false;
       }
       uint32_t status = imgIRequest::STATUS_ERROR;
       return NS_SUCCEEDED(req->GetImageStatus(&status)) &&
              !(status & imgIRequest::STATUS_ERROR) &&
-             (status & imgIRequest::STATUS_LOAD_COMPLETE);
+             (status & imgIRequest::STATUS_SIZE_AVAILABLE);
     }
     default:
       MOZ_ASSERT_UNREACHABLE("unexpected image type");
       return false;
   }
 }
 
 static inline bool EqualRects(const nsStyleImage::CropRect* aRect1,
--- a/layout/style/nsStyleStruct.h
+++ b/layout/style/nsStyleStruct.h
@@ -340,21 +340,21 @@ struct nsStyleImage {
   bool IsOpaque() const;
   /**
    * @return true if this image is fully loaded, and its size is calculated;
    * always returns true if |mType| is |eStyleImageType_Gradient| or
    * |eStyleImageType_Element|.
    */
   bool IsComplete() const;
   /**
-   * @return true if this image is loaded without error;
+   * @return true if this image has an available size, and hasn't errored.
    * always returns true if |mType| is |eStyleImageType_Gradient| or
    * |eStyleImageType_Element|.
    */
-  bool IsLoaded() const;
+  bool IsSizeAvailable() const;
   /**
    * @return true if it is 100% confident that this image contains no pixel
    * to draw.
    */
   bool IsEmpty() const {
     // There are some other cases when the image will be empty, for example
     // when the crop rect is empty. However, checking the emptiness of crop
     // rect is non-trivial since each side value can be specified with
@@ -761,18 +761,18 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsSt
 
   void SetBorderStyle(mozilla::Side aSide, mozilla::StyleBorderStyle aStyle) {
     NS_ASSERTION(aSide <= mozilla::eSideLeft, "bad side");
     mBorderStyle[aSide] = aStyle;
     mComputedBorder.Side(aSide) =
         (HasVisibleStyle(aSide) ? mBorder.Side(aSide) : 0);
   }
 
-  inline bool IsBorderImageLoaded() const {
-    return mBorderImageSource.IsLoaded();
+  inline bool IsBorderImageSizeAvailable() const {
+    return mBorderImageSource.IsSizeAvailable();
   }
 
   nsMargin GetImageOutset() const;
 
   imgIRequest* GetBorderImageRequest() const {
     if (mBorderImageSource.GetType() == eStyleImageType_Image) {
       return mBorderImageSource.GetImageData();
     }