Bug 1128225 (Part 4) - Record the last draw result in nsDisplayImage and use it to decide whether to sync decode. r=tn a=lmandel
authorSeth Fowler <seth@mozilla.com>
Wed, 04 Feb 2015 13:50:56 -0800
changeset 249872 46473c5ec5b2d99cf8d65aa076916968ea4e1077
parent 249871 09b37c4063346b0a0e0bc7bba42ecbf386ec08b6
child 249873 7ea739139e3cfcfc2d1b9cc413246b1c722e30a5
push id4489
push userraliiev@mozilla.com
push dateMon, 23 Feb 2015 15:17:55 +0000
treeherdermozilla-beta@fd7c3dc24146 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerstn, lmandel
bugs1128225
milestone37.0a2
Bug 1128225 (Part 4) - Record the last draw result in nsDisplayImage and use it to decide whether to sync decode. r=tn a=lmandel
layout/generic/nsImageFrame.cpp
layout/generic/nsImageFrame.h
--- a/layout/generic/nsImageFrame.cpp
+++ b/layout/generic/nsImageFrame.cpp
@@ -74,16 +74,17 @@
 
 #include "mozilla/Preferences.h"
 
 #include "mozilla/dom/Link.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 using namespace mozilla::gfx;
+using namespace mozilla::image;
 using namespace mozilla::layers;
 
 // sizes (pixels) for image icon, padding and border frame
 #define ICON_SIZE        (16)
 #define ICON_PADDING     (3)
 #define ALT_BORDER_WIDTH (1)
 
 //we must add hooks soon
@@ -1354,26 +1355,39 @@ nsDisplayImage::Paint(nsDisplayListBuild
                       nsRenderingContext* aCtx) {
   uint32_t flags = imgIContainer::FLAG_NONE;
   if (aBuilder->ShouldSyncDecodeImages()) {
     flags |= imgIContainer::FLAG_SYNC_DECODE;
   }
   if (aBuilder->IsPaintingToWindow()) {
     flags |= imgIContainer::FLAG_HIGH_QUALITY_SCALING;
   }
-  static_cast<nsImageFrame*>(mFrame)->
+
+  DrawResult result = static_cast<nsImageFrame*>(mFrame)->
     PaintImage(*aCtx, ToReferenceFrame(), mVisibleRect, mImage, flags);
+
+  nsDisplayItemGenericImageGeometry::UpdateDrawResult(this, result);
+}
+
+nsDisplayItemGeometry*
+nsDisplayImage::AllocateGeometry(nsDisplayListBuilder* aBuilder)
+{
+  return new nsDisplayItemGenericImageGeometry(this, aBuilder);
 }
 
 void
 nsDisplayImage::ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
                                           const nsDisplayItemGeometry* aGeometry,
                                           nsRegion* aInvalidRegion)
 {
-  if (aBuilder->ShouldSyncDecodeImages() && mImage && !mImage->IsDecoded()) {
+  auto geometry =
+    static_cast<const nsDisplayItemGenericImageGeometry*>(aGeometry);
+
+  if (aBuilder->ShouldSyncDecodeImages() &&
+      geometry->LastDrawResult() != DrawResult::SUCCESS) {
     bool snap;
     aInvalidRegion->Or(*aInvalidRegion, GetBounds(aBuilder, &snap));
   }
 
   nsDisplayImageContainer::ComputeInvalidationRegion(aBuilder, aGeometry, aInvalidRegion);
 }
 
 already_AddRefed<ImageContainer>
@@ -1509,27 +1523,33 @@ nsDisplayImage::ConfigureLayer(ImageLaye
   aLayer->SetFilter(nsLayoutUtils::GetGraphicsFilterForFrame(mFrame));
 
   int32_t imageWidth;
   int32_t imageHeight;
   mImage->GetWidth(&imageWidth);
   mImage->GetHeight(&imageHeight);
 
   NS_ASSERTION(imageWidth != 0 && imageHeight != 0, "Invalid image size!");
+  if (imageWidth > 0 && imageHeight > 0) {
+    // We're actually using the ImageContainer. Let our frame know that it
+    // should consider itself to have painted successfully.
+    nsDisplayItemGenericImageGeometry::UpdateDrawResult(this,
+                                                        DrawResult::SUCCESS);
+  }
 
   const gfxRect destRect = GetDestRect();
 
   gfxPoint p = destRect.TopLeft() + aOffset;
   Matrix transform = Matrix::Translation(p.x, p.y);
   transform.PreScale(destRect.Width() / imageWidth,
                      destRect.Height() / imageHeight);
   aLayer->SetBaseTransform(gfx::Matrix4x4::From2D(transform));
 }
 
-void
+DrawResult
 nsImageFrame::PaintImage(nsRenderingContext& aRenderingContext, nsPoint aPt,
                          const nsRect& aDirtyRect, imgIContainer* aImage,
                          uint32_t aFlags)
 {
   DrawTarget* drawTarget = aRenderingContext.GetDrawTarget();
 
   // Render the image into our content area (the area inside
   // the borders and padding)
@@ -1544,20 +1564,21 @@ nsImageFrame::PaintImage(nsRenderingCont
 
   nsPoint anchorPoint;
   nsRect dest = nsLayoutUtils::ComputeObjectDestRect(constraintRect,
                                                      mIntrinsicSize,
                                                      mIntrinsicRatio,
                                                      StylePosition(),
                                                      &anchorPoint);
 
-  nsLayoutUtils::DrawSingleImage(*aRenderingContext.ThebesContext(),
-    PresContext(), aImage,
-    nsLayoutUtils::GetGraphicsFilterForFrame(this), dest, aDirtyRect,
-    nullptr, aFlags, &anchorPoint);
+  DrawResult result =
+    nsLayoutUtils::DrawSingleImage(*aRenderingContext.ThebesContext(),
+      PresContext(), aImage,
+      nsLayoutUtils::GetGraphicsFilterForFrame(this), dest, aDirtyRect,
+      nullptr, aFlags, &anchorPoint);
 
   nsImageMap* map = GetImageMap();
   if (map) {
     gfxPoint devPixelOffset =
       nsLayoutUtils::PointToGfxPoint(dest.TopLeft(),
                                      PresContext()->AppUnitsPerDevPixel());
     AutoRestoreTransform autoRestoreTransform(drawTarget);
     drawTarget->SetTransform(
@@ -1568,16 +1589,18 @@ nsImageFrame::PaintImage(nsRenderingCont
     map->Draw(this, *drawTarget, white);
 
     // then dashed black stroke over the top:
     ColorPattern black(ToDeviceColor(Color(0.f, 0.f, 0.f, 1.f)));
     StrokeOptions strokeOptions;
     nsLayoutUtils::InitDashPattern(strokeOptions, NS_STYLE_BORDER_STYLE_DOTTED);
     map->Draw(this, *drawTarget, black, strokeOptions);
   }
+
+  return result;
 }
 
 void
 nsImageFrame::BuildDisplayList(nsDisplayListBuilder*   aBuilder,
                                const nsRect&           aDirtyRect,
                                const nsDisplayListSet& aLists)
 {
   if (!IsVisibleForPainting(aBuilder))
--- a/layout/generic/nsImageFrame.h
+++ b/layout/generic/nsImageFrame.h
@@ -58,16 +58,17 @@ private:
   nsImageFrame *mFrame;
 };
 
 typedef nsSplittableFrame ImageFrameSuper;
 
 class nsImageFrame : public ImageFrameSuper,
                      public nsIReflowCallback {
 public:
+  typedef mozilla::image::DrawResult DrawResult;
   typedef mozilla::layers::ImageContainer ImageContainer;
   typedef mozilla::layers::ImageLayer ImageLayer;
   typedef mozilla::layers::LayerManager LayerManager;
 
   NS_DECL_FRAMEARENA_HELPERS
 
   explicit nsImageFrame(nsStyleContext* aContext);
 
@@ -209,19 +210,19 @@ protected:
                         nsRenderingContext& aContext,
                         nsFontMetrics&      aFontMetrics);
 
   void DisplayAltText(nsPresContext*      aPresContext,
                       nsRenderingContext& aRenderingContext,
                       const nsString&      aAltText,
                       const nsRect&        aRect);
 
-  void PaintImage(nsRenderingContext& aRenderingContext, nsPoint aPt,
-                  const nsRect& aDirtyRect, imgIContainer* aImage,
-                  uint32_t aFlags);
+  DrawResult PaintImage(nsRenderingContext& aRenderingContext, nsPoint aPt,
+                        const nsRect& aDirtyRect, imgIContainer* aImage,
+                        uint32_t aFlags);
 
 protected:
   friend class nsImageListener;
   friend class nsImageLoadingContent;
 
   nsresult OnSizeAvailable(imgIRequest* aRequest, imgIContainer* aImage);
   nsresult OnFrameUpdate(imgIRequest* aRequest, const nsIntRect* aRect);
   nsresult OnLoadComplete(imgIRequest* aRequest, nsresult aStatus);
@@ -378,16 +379,18 @@ public:
   nsDisplayImage(nsDisplayListBuilder* aBuilder, nsImageFrame* aFrame,
                  imgIContainer* aImage)
     : nsDisplayImageContainer(aBuilder, aFrame), mImage(aImage) {
     MOZ_COUNT_CTOR(nsDisplayImage);
   }
   virtual ~nsDisplayImage() {
     MOZ_COUNT_DTOR(nsDisplayImage);
   }
+
+  virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE;
   virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
                                          const nsDisplayItemGeometry* aGeometry,
                                          nsRegion* aInvalidRegion) MOZ_OVERRIDE;
   virtual void Paint(nsDisplayListBuilder* aBuilder,
                      nsRenderingContext* aCtx) MOZ_OVERRIDE;
 
   /**
    * Returns an ImageContainer for this image if the image type