Bug 1341703 - Part 3. Ensure full decode be triggered after style-image was downloaded, draft
authorcku <cku@mozilla.com>
Mon, 17 Apr 2017 15:10:52 +0800
changeset 565191 1003c77f8987f39f6c5f6fce7ab0ed250e816d36
parent 565190 2acc71c009c277b476ec454ae66affa39b3cf724
child 565192 ac7648f0f7ce7c2d1ecff81c115c781cf7747b13
push id54804
push userbmo:cku@mozilla.com
push dateWed, 19 Apr 2017 15:30:23 +0000
bugs1341703
milestone55.0a1
Bug 1341703 - Part 3. Ensure full decode be triggered after style-image was downloaded, In nsCSSRendering::PaintBorderWithStyleBorder: DrawResult nsCSSRendering::PaintBorderWithStyleBorder() { if (aStyleBorder.IsBorderImageLoaded()) { (1) } (2) } At (1), we create a nsCSSBorderImageRenderer object. While creating it, we call imgRenderer.PrepareImage() to ensure a full image decode at [1]. PrepareImage is used in both bg-image/mask-image and border-image. The difference is, in bg-image/mask-image painting path, we unconditionally use PrepareImage(in nsCSSRendering::PrepareImageLayer), whereas in border-image painting path we use it only after border-image was downloaded. This difference does cause a problem. After border image was downloaded, the decoder will not do full decoding since we did not ask for it, so there will be no repaint notification and no chance to paint border-image again. In this patch, I try to align the behavior between bg-image/mask-image and border-image: always call nsImageRenderer::PrepareImage. This is a generic fix for both stylo-enable and stylo-disable build. We do not find this problem in reftest is because we use SYNC_DECODE in reftest harness, which hides this race condition. When dairy using firefox, if nsCSSRendering::PaintBorderWithStyleBorder is called after border-image was loaded, your program run into (1), border-image will be drawn correctly; In the case that nsCSSRendering::PaintBorderWithStyleBorder is called before border-image is loaded, your program run into (2), and you can only see border-color. [1] https://hg.mozilla.org/mozilla-central/file/a6f35285bd1e/layout/painting/nsCSSRenderingBorders.cpp#l3598 MozReview-Commit-ID: 6pidHJdPG8I
layout/painting/nsCSSRendering.cpp
layout/painting/nsCSSRenderingBorders.cpp
--- a/layout/painting/nsCSSRendering.cpp
+++ b/layout/painting/nsCSSRendering.cpp
@@ -815,34 +815,36 @@ nsCSSRendering::PaintBorderWithStyleBord
     nsITheme *theme = aPresContext->GetTheme();
     if (theme &&
         theme->ThemeSupportsWidget(aPresContext, aForFrame,
                                    displayData->UsedAppearance())) {
       return DrawResult::SUCCESS; // Let the theme handle it.
     }
   }
 
-  if (aStyleBorder.IsBorderImageLoaded()) {
-    DrawResult result;
+  if (!aStyleBorder.mBorderImageSource.IsEmpty()) {
+    DrawResult result = DrawResult::SUCCESS;
 
     uint32_t irFlags = 0;
     if (aFlags & PaintBorderFlags::SYNC_DECODE_IMAGES) {
       irFlags |= nsImageRenderer::FLAG_SYNC_DECODE_IMAGES;
     }
 
     Maybe<nsCSSBorderImageRenderer> renderer =
       nsCSSBorderImageRenderer::CreateBorderImageRenderer(aPresContext, aForFrame, aBorderArea,
                                                           aStyleBorder, aDirtyRect, aSkipSides,
                                                           irFlags, &result);
-    if (!renderer) {
-      return result;
+    if (aStyleBorder.IsBorderImageLoaded()) {
+      if (!renderer) {
+        return result;
+      }
+
+      return renderer->DrawBorderImage(aPresContext, aRenderingContext,
+                                       aForFrame, aDirtyRect);
     }
-
-    return renderer->DrawBorderImage(aPresContext, aRenderingContext,
-                                     aForFrame, aDirtyRect);
   }
 
   DrawResult result = DrawResult::SUCCESS;
 
   // If we had a border-image, but it wasn't loaded, then we should return
   // DrawResult::NOT_READY; we'll want to try again if we do a paint with sync
   // decoding enabled.
   if (aStyleBorder.mBorderImageSource.GetType() != eStyleImageType_Null) {
--- a/layout/painting/nsCSSRenderingBorders.cpp
+++ b/layout/painting/nsCSSRenderingBorders.cpp
@@ -3580,18 +3580,16 @@ nsCSSBorderImageRenderer::CreateBorderIm
                                                     nsIFrame* aForFrame,
                                                     const nsRect& aBorderArea,
                                                     const nsStyleBorder& aStyleBorder,
                                                     const nsRect& aDirtyRect,
                                                     Sides aSkipSides,
                                                     uint32_t aFlags,
                                                     DrawResult* aDrawResult)
 {
-  NS_PRECONDITION(aStyleBorder.IsBorderImageLoaded(),
-                  "drawing border image that isn't successfully loaded");
   MOZ_ASSERT(aDrawResult);
 
   if (aDirtyRect.IsEmpty()) {
     *aDrawResult = DrawResult::SUCCESS;
     return Nothing();
   }
 
   nsImageRenderer imgRenderer(aForFrame, &aStyleBorder.mBorderImageSource, aFlags);