Bug 1368776 - Part 9. Expose getting an image container at a given size. r=tnikkel
authorAndrew Osmond <aosmond@mozilla.com>
Fri, 17 Nov 2017 06:45:26 -0500
changeset 446742 0cd5200c5f768b8d10ef23ac8986003c0c71375b
parent 446741 9402cc966061e6954409bbe7ca8047ba1fd0eec1
child 446743 837f7f805c531e85d0c89d4a76049da0e748eb62
push id1648
push usermtabara@mozilla.com
push dateThu, 01 Mar 2018 12:45:47 +0000
treeherdermozilla-release@cbb9688c2eeb [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 9. Expose getting an image container at a given size. r=tnikkel This adds IsImageContainerAvailableAtSize and GetImageContainerAtSize to the imgIContainer interface, as well as stubbing it for all of the classes which implement it. The real implementations will follow for the more complicated classes (RasterImage, VectorImage).
image/ClippedImage.cpp
image/ClippedImage.h
image/DynamicImage.cpp
image/FrozenImage.cpp
image/FrozenImage.h
image/ImageWrapper.cpp
image/OrientedImage.cpp
image/OrientedImage.h
image/RasterImage.cpp
image/VectorImage.cpp
image/imgIContainer.idl
--- a/image/ClippedImage.cpp
+++ b/image/ClippedImage.cpp
@@ -351,16 +351,45 @@ ClippedImage::GetImageContainer(LayerMan
 
   if (!ShouldClip()) {
     return InnerImage()->GetImageContainer(aManager, aFlags);
   }
 
   return nullptr;
 }
 
+NS_IMETHODIMP_(bool)
+ClippedImage::IsImageContainerAvailableAtSize(LayerManager* aManager,
+                                              const IntSize& aSize,
+                                              uint32_t aFlags)
+{
+  if (!ShouldClip()) {
+    return InnerImage()->IsImageContainerAvailableAtSize(aManager, aSize, aFlags);
+  }
+  return false;
+}
+
+NS_IMETHODIMP_(already_AddRefed<ImageContainer>)
+ClippedImage::GetImageContainerAtSize(LayerManager* aManager,
+                                      const IntSize& aSize,
+                                      uint32_t aFlags)
+{
+  // XXX(seth): We currently don't have a way of clipping the result of
+  // GetImageContainer. We work around this by always returning null, but if it
+  // ever turns out that ClippedImage is widely used on codepaths that can
+  // actually benefit from GetImageContainer, it would be a good idea to fix
+  // that method for performance reasons.
+
+  if (!ShouldClip()) {
+    return InnerImage()->GetImageContainerAtSize(aManager, aSize, aFlags);
+  }
+
+  return nullptr;
+}
+
 static bool
 MustCreateSurface(gfxContext* aContext,
                   const nsIntSize& aSize,
                   const ImageRegion& aRegion,
                   const uint32_t aFlags)
 {
   gfxRect imageRect(0, 0, aSize.width, aSize.height);
   bool willTile = !imageRect.Contains(aRegion.Rect()) &&
--- a/image/ClippedImage.h
+++ b/image/ClippedImage.h
@@ -42,16 +42,24 @@ public:
     GetFrameAtSize(const gfx::IntSize& aSize,
                    uint32_t aWhichFrame,
                    uint32_t aFlags) override;
   NS_IMETHOD_(bool) IsImageContainerAvailable(layers::LayerManager* aManager,
                                               uint32_t aFlags) override;
   NS_IMETHOD_(already_AddRefed<layers::ImageContainer>)
     GetImageContainer(layers::LayerManager* aManager,
                       uint32_t aFlags) override;
+  NS_IMETHOD_(bool)
+    IsImageContainerAvailableAtSize(layers::LayerManager* aManager,
+                                    const gfx::IntSize& aSize,
+                                    uint32_t aFlags) override;
+  NS_IMETHOD_(already_AddRefed<layers::ImageContainer>)
+    GetImageContainerAtSize(layers::LayerManager* aManager,
+                            const gfx::IntSize& aSize,
+                            uint32_t aFlags) override;
   NS_IMETHOD_(DrawResult) Draw(gfxContext* aContext,
                                const nsIntSize& aSize,
                                const ImageRegion& aRegion,
                                uint32_t aWhichFrame,
                                gfx::SamplingFilter aSamplingFilter,
                                const Maybe<SVGImageContext>& aSVGContext,
                                uint32_t aFlags,
                                float aOpacity) override;
--- a/image/DynamicImage.cpp
+++ b/image/DynamicImage.cpp
@@ -221,16 +221,32 @@ DynamicImage::IsImageContainerAvailable(
 }
 
 NS_IMETHODIMP_(already_AddRefed<ImageContainer>)
 DynamicImage::GetImageContainer(LayerManager* aManager, uint32_t aFlags)
 {
   return nullptr;
 }
 
+NS_IMETHODIMP_(bool)
+DynamicImage::IsImageContainerAvailableAtSize(LayerManager* aManager,
+                                              const IntSize& aSize,
+                                              uint32_t aFlags)
+{
+  return false;
+}
+
+NS_IMETHODIMP_(already_AddRefed<ImageContainer>)
+DynamicImage::GetImageContainerAtSize(LayerManager* aManager,
+                                      const IntSize& aSize,
+                                      uint32_t aFlags)
+{
+  return nullptr;
+}
+
 NS_IMETHODIMP_(DrawResult)
 DynamicImage::Draw(gfxContext* aContext,
                    const nsIntSize& aSize,
                    const ImageRegion& aRegion,
                    uint32_t aWhichFrame,
                    SamplingFilter aSamplingFilter,
                    const Maybe<SVGImageContext>& aSVGContext,
                    uint32_t aFlags,
--- a/image/FrozenImage.cpp
+++ b/image/FrozenImage.cpp
@@ -66,16 +66,37 @@ FrozenImage::GetImageContainer(layers::L
   // XXX(seth): GetImageContainer does not currently support anything but the
   // current frame. We work around this by always returning null, but if it ever
   // turns out that FrozenImage is widely used on codepaths that can actually
   // benefit from GetImageContainer, it would be a good idea to fix that method
   // for performance reasons.
   return nullptr;
 }
 
+NS_IMETHODIMP_(bool)
+FrozenImage::IsImageContainerAvailableAtSize(LayerManager* aManager,
+                                             const IntSize& aSize,
+                                             uint32_t aFlags)
+{
+  return false;
+}
+
+NS_IMETHODIMP_(already_AddRefed<ImageContainer>)
+FrozenImage::GetImageContainerAtSize(layers::LayerManager* aManager,
+                                     const IntSize& aSize,
+                                     uint32_t aFlags)
+{
+  // XXX(seth): GetImageContainer does not currently support anything but the
+  // current frame. We work around this by always returning null, but if it ever
+  // turns out that FrozenImage is widely used on codepaths that can actually
+  // benefit from GetImageContainer, it would be a good idea to fix that method
+  // for performance reasons.
+  return nullptr;
+}
+
 NS_IMETHODIMP_(DrawResult)
 FrozenImage::Draw(gfxContext* aContext,
                   const nsIntSize& aSize,
                   const ImageRegion& aRegion,
                   uint32_t /* aWhichFrame - ignored */,
                   SamplingFilter aSamplingFilter,
                   const Maybe<SVGImageContext>& aSVGContext,
                   uint32_t aFlags,
--- a/image/FrozenImage.h
+++ b/image/FrozenImage.h
@@ -41,16 +41,24 @@ public:
     GetFrameAtSize(const gfx::IntSize& aSize,
                    uint32_t aWhichFrame,
                    uint32_t aFlags) override;
   NS_IMETHOD_(bool) IsImageContainerAvailable(layers::LayerManager* aManager,
                                               uint32_t aFlags) override;
   NS_IMETHOD_(already_AddRefed<layers::ImageContainer>)
     GetImageContainer(layers::LayerManager* aManager,
                       uint32_t aFlags) override;
+  NS_IMETHOD_(bool)
+    IsImageContainerAvailableAtSize(layers::LayerManager* aManager,
+                                    const gfx::IntSize& aSize,
+                                    uint32_t aFlags) override;
+  NS_IMETHOD_(already_AddRefed<layers::ImageContainer>)
+    GetImageContainerAtSize(layers::LayerManager* aManager,
+                            const gfx::IntSize& aSize,
+                            uint32_t aFlags) override;
   NS_IMETHOD_(DrawResult) Draw(gfxContext* aContext,
                                const nsIntSize& aSize,
                                const ImageRegion& aRegion,
                                uint32_t aWhichFrame,
                                gfx::SamplingFilter aSamplingFilter,
                                const Maybe<SVGImageContext>& aSVGContext,
                                uint32_t aFlags,
                                float aOpacity) override;
--- a/image/ImageWrapper.cpp
+++ b/image/ImageWrapper.cpp
@@ -209,16 +209,32 @@ ImageWrapper::IsImageContainerAvailable(
 }
 
 NS_IMETHODIMP_(already_AddRefed<ImageContainer>)
 ImageWrapper::GetImageContainer(LayerManager* aManager, uint32_t aFlags)
 {
   return mInnerImage->GetImageContainer(aManager, aFlags);
 }
 
+NS_IMETHODIMP_(bool)
+ImageWrapper::IsImageContainerAvailableAtSize(LayerManager* aManager,
+                                              const IntSize& aSize,
+                                              uint32_t aFlags)
+{
+  return mInnerImage->IsImageContainerAvailableAtSize(aManager, aSize, aFlags);
+}
+
+NS_IMETHODIMP_(already_AddRefed<ImageContainer>)
+ImageWrapper::GetImageContainerAtSize(LayerManager* aManager,
+                                      const IntSize& aSize,
+                                      uint32_t aFlags)
+{
+  return mInnerImage->GetImageContainerAtSize(aManager, aSize, aFlags);
+}
+
 NS_IMETHODIMP_(DrawResult)
 ImageWrapper::Draw(gfxContext* aContext,
                    const nsIntSize& aSize,
                    const ImageRegion& aRegion,
                    uint32_t aWhichFrame,
                    SamplingFilter aSamplingFilter,
                    const Maybe<SVGImageContext>& aSVGContext,
                    uint32_t aFlags,
--- a/image/OrientedImage.cpp
+++ b/image/OrientedImage.cpp
@@ -168,16 +168,45 @@ OrientedImage::GetImageContainer(LayerMa
 
   if (mOrientation.IsIdentity()) {
     return InnerImage()->GetImageContainer(aManager, aFlags);
   }
 
   return nullptr;
 }
 
+NS_IMETHODIMP_(bool)
+OrientedImage::IsImageContainerAvailableAtSize(LayerManager* aManager,
+                                               const IntSize& aSize,
+                                               uint32_t aFlags)
+{
+  if (mOrientation.IsIdentity()) {
+    return InnerImage()->IsImageContainerAvailableAtSize(aManager, aSize, aFlags);
+  }
+  return false;
+}
+
+NS_IMETHODIMP_(already_AddRefed<ImageContainer>)
+OrientedImage::GetImageContainerAtSize(LayerManager* aManager,
+                                       const IntSize& aSize,
+                                       uint32_t aFlags)
+{
+  // XXX(seth): We currently don't have a way of orienting the result of
+  // GetImageContainer. We work around this by always returning null, but if it
+  // ever turns out that OrientedImage is widely used on codepaths that can
+  // actually benefit from GetImageContainer, it would be a good idea to fix
+  // that method for performance reasons.
+
+  if (mOrientation.IsIdentity()) {
+    return InnerImage()->GetImageContainerAtSize(aManager, aSize, aFlags);
+  }
+
+  return nullptr;
+}
+
 struct MatrixBuilder
 {
   explicit MatrixBuilder(bool aInvert) : mInvert(aInvert) { }
 
   gfxMatrix Build() { return mMatrix; }
 
   void Scale(gfxFloat aX, gfxFloat aY)
   {
--- a/image/OrientedImage.h
+++ b/image/OrientedImage.h
@@ -39,16 +39,24 @@ public:
     GetFrameAtSize(const gfx::IntSize& aSize,
                    uint32_t aWhichFrame,
                    uint32_t aFlags) override;
   NS_IMETHOD_(bool) IsImageContainerAvailable(layers::LayerManager* aManager,
                                               uint32_t aFlags) override;
   NS_IMETHOD_(already_AddRefed<layers::ImageContainer>)
     GetImageContainer(layers::LayerManager* aManager,
                       uint32_t aFlags) override;
+  NS_IMETHOD_(bool)
+    IsImageContainerAvailableAtSize(layers::LayerManager* aManager,
+                                    const gfx::IntSize& aSize,
+                                    uint32_t aFlags) override;
+  NS_IMETHOD_(already_AddRefed<layers::ImageContainer>)
+    GetImageContainerAtSize(layers::LayerManager* aManager,
+                            const gfx::IntSize& aSize,
+                            uint32_t aFlags) override;
   NS_IMETHOD_(DrawResult) Draw(gfxContext* aContext,
                                const nsIntSize& aSize,
                                const ImageRegion& aRegion,
                                uint32_t aWhichFrame,
                                gfx::SamplingFilter aSamplingFilter,
                                const Maybe<SVGImageContext>& aSVGContext,
                                uint32_t aFlags,
                                float aOpacity) override;
--- a/image/RasterImage.cpp
+++ b/image/RasterImage.cpp
@@ -634,16 +634,32 @@ RasterImage::IsImageContainerAvailable(L
 }
 
 NS_IMETHODIMP_(already_AddRefed<ImageContainer>)
 RasterImage::GetImageContainer(LayerManager* aManager, uint32_t aFlags)
 {
   return GetImageContainerImpl(aManager, mSize, aFlags);
 }
 
+NS_IMETHODIMP_(bool)
+RasterImage::IsImageContainerAvailableAtSize(LayerManager* aManager,
+                                             const IntSize& aSize,
+                                             uint32_t aFlags)
+{
+  return false;
+}
+
+NS_IMETHODIMP_(already_AddRefed<ImageContainer>)
+RasterImage::GetImageContainerAtSize(LayerManager* aManager,
+                                     const IntSize& aSize,
+                                     uint32_t aFlags)
+{
+  return nullptr;
+}
+
 size_t
 RasterImage::SizeOfSourceWithComputedFallback(SizeOfState& aState) const
 {
   return mSourceBuffer->SizeOfIncludingThisWithComputedFallback(
     aState.mMallocSizeOf);
 }
 
 void
--- a/image/VectorImage.cpp
+++ b/image/VectorImage.cpp
@@ -765,30 +765,49 @@ VectorImage::GetFrameAtSize(const IntSiz
 
   auto result = Draw(context, aSize, ImageRegion::Create(aSize),
                      aWhichFrame, SamplingFilter::POINT, Nothing(), aFlags,
                      1.0);
 
   return result == DrawResult::SUCCESS ? dt->Snapshot() : nullptr;
 }
 
+//******************************************************************************
 NS_IMETHODIMP_(bool)
 VectorImage::IsImageContainerAvailable(LayerManager* aManager, uint32_t aFlags)
 {
   return false;
 }
 
 //******************************************************************************
 NS_IMETHODIMP_(already_AddRefed<ImageContainer>)
 VectorImage::GetImageContainer(LayerManager* aManager, uint32_t aFlags)
 {
   return nullptr;
 }
 
 //******************************************************************************
+NS_IMETHODIMP_(bool)
+VectorImage::IsImageContainerAvailableAtSize(LayerManager* aManager,
+                                             const IntSize& aSize,
+                                             uint32_t aFlags)
+{
+  return false;
+}
+
+//******************************************************************************
+NS_IMETHODIMP_(already_AddRefed<ImageContainer>)
+VectorImage::GetImageContainerAtSize(LayerManager* aManager,
+                                     const IntSize& aSize,
+                                     uint32_t aFlags)
+{
+  return nullptr;
+}
+
+//******************************************************************************
 NS_IMETHODIMP_(DrawResult)
 VectorImage::Draw(gfxContext* aContext,
                   const nsIntSize& aSize,
                   const ImageRegion& aRegion,
                   uint32_t aWhichFrame,
                   SamplingFilter aSamplingFilter,
                   const Maybe<SVGImageContext>& aSVGContext,
                   uint32_t aFlags,
--- a/image/imgIContainer.idl
+++ b/image/imgIContainer.idl
@@ -275,32 +275,63 @@ interface imgIContainer : nsISupports
    * @return true if getImageContainer() is expected to return a valid
    *         ImageContainer when passed the given @Manager and @Flags
    *         parameters.
    */
   [noscript, notxpcom] boolean isImageContainerAvailable(in LayerManager aManager,
                                                          in uint32_t aFlags);
   /**
    * Attempts to create an ImageContainer (and Image) containing the current
-   * frame.
+   * frame at its native size.
    *
    * Avoid calling this unless you're actually going to layerize this image.
    *
    * @param aManager The LayerManager which will be used to create the
    *                 ImageContainer.
    * @param aFlags Decoding / drawing flags (in other words, FLAG_* flags).
    *               Currently only FLAG_SYNC_DECODE and FLAG_SYNC_DECODE_IF_FAST
    *               are supported.
    * @return An ImageContainer for the current frame, or nullptr if one could
    *         not be created.
    */
   [noscript, notxpcom] TempRefImageContainer getImageContainer(in LayerManager aManager,
                                                                in uint32_t aFlags);
 
   /**
+   * @return true if getImageContainer() is expected to return a valid
+   *         ImageContainer when passed the given @Manager, @Size and @Flags
+   *         parameters.
+   */
+  [noscript, notxpcom] boolean isImageContainerAvailableAtSize(in LayerManager aManager,
+                                                               [const] in nsIntSize aSize,
+                                                               in uint32_t aFlags);
+
+  /**
+   * Attempts to create an ImageContainer (and Image) containing the current
+   * frame at the given size. Match the requested size is best effort; it's
+   * not guaranteed that the surface you get will be a perfect match. (Some
+   * reasons you may get a surface of a different size include: if you
+   * requested upscaling, or if downscale-during-decode is disabled.)
+   *
+   * Avoid calling this unless you're actually going to layerize this image.
+   *
+   * @param aManager The LayerManager which will be used to create the
+   *                 ImageContainer.
+   * @param aSize  The size to decode the frame at.
+   * @param aFlags Decoding / drawing flags (in other words, FLAG_* flags).
+   *               Currently only FLAG_SYNC_DECODE and FLAG_SYNC_DECODE_IF_FAST
+   *               are supported.
+   * @return An ImageContainer for the current frame, or nullptr if one could
+   *         not be created.
+   */
+  [noscript, notxpcom] TempRefImageContainer getImageContainerAtSize(in LayerManager aManager,
+                                                                     [const] in nsIntSize aSize,
+                                                                     in uint32_t aFlags);
+
+  /**
    * Draw the requested frame of this image onto the context specified.
    *
    * Drawing an image involves scaling it to a certain size (which may be
    * implemented as a "smart" scale by substituting an HQ-scaled frame or
    * rendering at a high DPI), and then selecting a region of that image to
    * draw. That region is drawn onto the graphics context and in the process
    * transformed by the context matrix, which determines the final area that is
    * filled. The basic process looks like this: