Bug 1368776 - Part 11. Add ImageResource::GetImageContainerSize to determine the appropriate size for a requested container. r=tnikkel
authorAndrew Osmond <aosmond@mozilla.com>
Fri, 17 Nov 2017 06:45:26 -0500
changeset 392472 c069e359ee49cc80fc5c8c59de93c7929c63720e
parent 392471 837f7f805c531e85d0c89d4a76049da0e748eb62
child 392473 4375bb4cf0a8de4465ad95a97913b27ed4807aac
push id32921
push usernerli@mozilla.com
push dateFri, 17 Nov 2017 22:02:18 +0000
treeherdermozilla-central@daa0dcd1616c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerstnikkel
bugs1368776
milestone59.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 1368776 - Part 11. Add ImageResource::GetImageContainerSize to determine the appropriate size for a requested container. r=tnikkel
image/Image.cpp
image/Image.h
image/RasterImage.cpp
image/RasterImage.h
--- a/image/Image.cpp
+++ b/image/Image.cpp
@@ -103,31 +103,32 @@ ImageResource::GetImageContainerImpl(Lay
   MOZ_ASSERT(aManager);
   MOZ_ASSERT((aFlags & ~(FLAG_SYNC_DECODE |
                          FLAG_SYNC_DECODE_IF_FAST |
                          FLAG_ASYNC_NOTIFY |
                          FLAG_HIGH_QUALITY_SCALING))
                == FLAG_NONE,
              "Unsupported flag passed to GetImageContainer");
 
-  if (!IsImageContainerAvailable(aManager, aFlags)) {
+  IntSize size = GetImageContainerSize(aManager, aSize, aFlags);
+  if (size.IsEmpty()) {
     return nullptr;
   }
 
   if (mAnimationConsumers == 0) {
     SendOnUnlockedDraw(aFlags);
   }
 
   RefPtr<layers::ImageContainer> container;
   ImageContainerEntry* entry = nullptr;
   int i = mImageContainers.Length() - 1;
   for (; i >= 0; --i) {
     entry = &mImageContainers[i];
     container = entry->mContainer.get();
-    if (aSize == entry->mSize) {
+    if (size == entry->mSize) {
       // Lack of a container is handled below.
       break;
     } else if (!container) {
       // Stop tracking if our weak pointer to the image container was freed.
       mImageContainers.RemoveElementAt(i);
     }
   }
 
@@ -151,26 +152,26 @@ ImageResource::GetImageContainerImpl(Lay
   } else {
     // We need a new ImageContainer, so create one.
     container = LayerManager::CreateImageContainer();
 
     if (i >= 0) {
       entry->mContainer = container;
     } else {
       entry = mImageContainers.AppendElement(
-        ImageContainerEntry(aSize, container.get()));
+        ImageContainerEntry(size, container.get()));
     }
   }
 
 #ifdef DEBUG
   NotifyDrawingObservers();
 #endif
 
   entry->mLastDrawResult =
-    AddCurrentImage(container, aSize, aFlags, true);
+    AddCurrentImage(container, size, aFlags, true);
   return container.forget();
 }
 
 void
 ImageResource::UpdateImageContainer()
 {
   MOZ_ASSERT(NS_IsMainThread());
 
--- a/image/Image.h
+++ b/image/Image.h
@@ -339,16 +339,29 @@ protected:
   virtual Pair<DrawResult, RefPtr<gfx::SourceSurface>>
     GetFrameInternal(const gfx::IntSize& aSize,
                      uint32_t aWhichFrame,
                      uint32_t aFlags)
   {
     return MakePair(DrawResult::BAD_IMAGE, RefPtr<gfx::SourceSurface>());
   }
 
+  /**
+   * Calculate the estimated size to use for an image container with the given
+   * parameters. It may not be the same as the given size, and it may not be
+   * the same as the size of the surface in the image container, but it is the
+   * best effort estimate.
+   */
+  virtual gfx::IntSize GetImageContainerSize(layers::LayerManager* aManager,
+                                             const gfx::IntSize& aSize,
+                                             uint32_t aFlags)
+  {
+    return gfx::IntSize(0, 0);
+  }
+
   already_AddRefed<layers::ImageContainer>
     GetImageContainerImpl(layers::LayerManager* aManager,
                           const gfx::IntSize& aSize,
                           uint32_t aFlags);
 
   void UpdateImageContainer();
 
   void ReleaseImageContainer();
--- a/image/RasterImage.cpp
+++ b/image/RasterImage.cpp
@@ -615,16 +615,32 @@ RasterImage::GetFrameInternal(const IntS
 
   if (!surface->IsFinished()) {
     return MakePair(DrawResult::INCOMPLETE, Move(sourceSurface));
   }
 
   return MakePair(DrawResult::SUCCESS, Move(sourceSurface));
 }
 
+IntSize
+RasterImage::GetImageContainerSize(LayerManager* aManager,
+                                   const IntSize& aSize,
+                                   uint32_t aFlags)
+{
+  if (!IsImageContainerAvailableAtSize(aManager, aSize, aFlags)) {
+    return IntSize(0, 0);
+  }
+
+  if (!CanDownscaleDuringDecode(aSize, aFlags)) {
+    return mSize;
+  }
+
+  return aSize;
+}
+
 NS_IMETHODIMP_(bool)
 RasterImage::IsImageContainerAvailable(LayerManager* aManager, uint32_t aFlags)
 {
   return IsImageContainerAvailableAtSize(aManager, mSize, aFlags);
 }
 
 NS_IMETHODIMP_(already_AddRefed<ImageContainer>)
 RasterImage::GetImageContainer(LayerManager* aManager, uint32_t aFlags)
--- a/image/RasterImage.h
+++ b/image/RasterImage.h
@@ -126,16 +126,17 @@ class nsIRequest;
  * it's not allocated until the second frame is added.
  */
 
 namespace mozilla {
 
 namespace layers {
 class ImageContainer;
 class Image;
+class LayersManager;
 } // namespace layers
 
 namespace image {
 
 class Decoder;
 struct DecoderFinalStatus;
 struct DecoderTelemetry;
 class ImageMetadata;
@@ -307,16 +308,20 @@ private:
                           uint32_t aFlags,
                           float aOpacity);
 
   Pair<DrawResult, RefPtr<gfx::SourceSurface>>
     GetFrameInternal(const gfx::IntSize& aSize,
                      uint32_t aWhichFrame,
                      uint32_t aFlags) override;
 
+  gfx::IntSize GetImageContainerSize(layers::LayerManager* aManager,
+                                     const gfx::IntSize& aSize,
+                                     uint32_t aFlags) override;
+
   //////////////////////////////////////////////////////////////////////////////
   // Decoding.
   //////////////////////////////////////////////////////////////////////////////
 
   /**
    * Creates and runs a decoder, either synchronously or asynchronously
    * according to @aFlags. Decodes at the provided target size @aSize, using
    * decode flags @aFlags. Performs a single-frame decode of this image unless