Bug 1471583. Don't record a successful image draw if the image isn't marked complete. r=mattwoodrow
authorTimothy Nikkel <tnikkel@gmail.com>
Wed, 29 Aug 2018 00:53:06 -0500
changeset 488866 5955f883a957e165be245385c640fa3a64fabd8d
parent 488865 e471c532fd11675b0cfafa7c161a2e5e147944b3
child 488867 851b26405a346d8aff55d96bc26ed9bb12995701
push id9734
push usershindli@mozilla.com
push dateThu, 30 Aug 2018 12:18:07 +0000
treeherdermozilla-beta@71c71ab3afae [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmattwoodrow
bugs1471583
milestone63.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 1471583. Don't record a successful image draw if the image isn't marked complete. r=mattwoodrow The image can be decoded but we haven't notified such (and hence the image state doesn't indicate such). We are able to draw the image at this point because painting has special access to the image that bypasses the image state (this happens via nsStyleImage::StartDecoding -> imgIRequest::StartDecodingWithResult). In this state if we record a successful draw then any parts of the image that we newly drew but weren't invalidated for some other reason won't get updated. When the async decode notification gets processed it will invalidate the image and that will result in it getting updated. But if we get a paint that asks for sync decoding of images before this it will see that we sucessfully drew the image and not invalidate its area and the sync decode paint won't update the image. So we still draw the image but we don't record a successful draw unless the image state is complete and hence the decode notification has been processed (image state and notifications are always in sync). Note that we still have to draw the image in this state because if we get a normal paint after a sync decode paint we have to draw the image because if we don't we effectively erase the image.
layout/painting/nsImageRenderer.cpp
--- a/layout/painting/nsImageRenderer.cpp
+++ b/layout/painting/nsImageRenderer.cpp
@@ -553,16 +553,20 @@ nsImageRenderer::Draw(nsPresContext*    
                       Rect(0, 0, tmpDTRect.width, tmpDTRect.height),
                       DrawSurfaceOptions(SamplingFilter::POINT),
                       DrawOptions(1.0f, aRenderingContext.CurrentOp()));
     }
 
     dt->SetTransform(oldTransform);
   }
 
+  if (!mImage->IsComplete()) {
+    result &= ImgDrawResult::INCOMPLETE;
+  }
+
   return result;
 }
 
 ImgDrawResult
 nsImageRenderer::BuildWebRenderDisplayItems(nsPresContext* aPresContext,
                                             mozilla::wr::DisplayListBuilder& aBuilder,
                                             mozilla::wr::IpcResourceUpdateQueue& aResources,
                                             const mozilla::layers::StackingContextHelper& aSc,
@@ -652,17 +656,17 @@ nsImageRenderer::BuildWebRenderDisplayIt
                          wr::ToLayoutSize(destRect.Size()), wr::ToLayoutSize(gapSize),
                          wr::ToImageRendering(samplingFilter), key.value());
       break;
     }
     default:
       break;
   }
 
-  return ImgDrawResult::SUCCESS;
+  return mImage->IsComplete() ? ImgDrawResult::SUCCESS : ImgDrawResult::INCOMPLETE;
 }
 
 already_AddRefed<gfxDrawable>
 nsImageRenderer::DrawableForElement(const nsRect& aImageRect,
                                     gfxContext&  aContext)
 {
   NS_ASSERTION(mType == eStyleImageType_Element,
                "DrawableForElement only makes sense if backed by an element");
@@ -928,36 +932,51 @@ nsImageRenderer::DrawBorderImageComponen
     }
 
     MOZ_ASSERT(!aSVGViewportSize ||
                subImage->GetType() == imgIContainer::TYPE_VECTOR);
 
     SamplingFilter samplingFilter = nsLayoutUtils::GetSamplingFilterForFrame(mForFrame);
 
     if (!RequiresScaling(aFill, aHFill, aVFill, aUnitSize)) {
-      return nsLayoutUtils::DrawSingleImage(aRenderingContext,
-                                            aPresContext,
-                                            subImage,
-                                            samplingFilter,
-                                            aFill, aDirtyRect,
-                                            /* no SVGImageContext */ Nothing(),
-                                            drawFlags);
+      ImgDrawResult result =
+        nsLayoutUtils::DrawSingleImage(aRenderingContext,
+                                       aPresContext,
+                                       subImage,
+                                       samplingFilter,
+                                       aFill, aDirtyRect,
+                                       /* no SVGImageContext */ Nothing(),
+                                       drawFlags);
+
+      if (!mImage->IsComplete()) {
+        result &= ImgDrawResult::INCOMPLETE;
+      }
+
+      return result;
     }
 
     nsSize repeatSize;
     nsRect fillRect(aFill);
     nsRect tile = ComputeTile(fillRect, aHFill, aVFill, aUnitSize, repeatSize);
     CSSIntSize imageSize(srcRect.width, srcRect.height);
-    return nsLayoutUtils::DrawBackgroundImage(aRenderingContext,
-                                              mForFrame, aPresContext,
-                                              subImage, imageSize, samplingFilter,
-                                              tile, fillRect, repeatSize,
-                                              tile.TopLeft(), aDirtyRect,
-                                              drawFlags,
-                                              ExtendMode::CLAMP, 1.0);
+
+    ImgDrawResult result =
+      nsLayoutUtils::DrawBackgroundImage(aRenderingContext,
+                                         mForFrame, aPresContext,
+                                         subImage, imageSize, samplingFilter,
+                                         tile, fillRect, repeatSize,
+                                         tile.TopLeft(), aDirtyRect,
+                                         drawFlags,
+                                         ExtendMode::CLAMP, 1.0);
+
+      if (!mImage->IsComplete()) {
+        result &= ImgDrawResult::INCOMPLETE;
+      }
+
+      return result;
   }
 
   nsSize repeatSize(aFill.Size());
   nsRect fillRect(aFill);
   nsRect destTile = RequiresScaling(fillRect, aHFill, aVFill, aUnitSize)
                   ? ComputeTile(fillRect, aHFill, aVFill, aUnitSize, repeatSize)
                   : fillRect;