Bug 1163878 (Part 1) - Add an IsImageContainerAvailable method to imgIContainer. r=tn
authorSeth Fowler <mark.seth.fowler@gmail.com>
Wed, 13 May 2015 00:23:44 -0700
changeset 243631 66d87284ab5c18499d3e10b3134b486678975ea1
parent 243630 7da7fb5c7d383f9577d534e10d202a13a44fac0e
child 243632 c0654f3b986de3687163c5e2de8e39250414f9d6
push id59715
push usermfowler@mozilla.com
push dateWed, 13 May 2015 07:24:20 +0000
treeherdermozilla-inbound@c0654f3b986d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerstn
bugs1163878
milestone41.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 1163878 (Part 1) - Add an IsImageContainerAvailable method to imgIContainer. r=tn
image/imgIContainer.idl
image/src/ClippedImage.cpp
image/src/ClippedImage.h
image/src/DynamicImage.cpp
image/src/FrozenImage.cpp
image/src/FrozenImage.h
image/src/ImageWrapper.cpp
image/src/OrientedImage.cpp
image/src/OrientedImage.h
image/src/RasterImage.cpp
image/src/VectorImage.cpp
--- a/image/imgIContainer.idl
+++ b/image/imgIContainer.idl
@@ -111,17 +111,17 @@ native nsIntSizeByVal(nsIntSize);
 
 /**
  * imgIContainer is the interface that represents an image. It allows
  * access to frames as Thebes surfaces. It also allows drawing of images
  * onto Thebes contexts.
  *
  * Internally, imgIContainer also manages animation of images.
  */
-[scriptable, builtinclass, uuid(e3261ae7-4749-4cf6-bf06-59946233366f)]
+[scriptable, builtinclass, uuid(f5e1230a-3733-477f-b49b-fee8717a786b)]
 interface imgIContainer : nsISupports
 {
   /**
    * The width of the container rectangle.  In the case of any error,
    * zero is returned, and an exception will be thrown.
    */
   readonly attribute int32_t width;
 
@@ -265,18 +265,27 @@ interface imgIContainer : nsISupports
                                                      in uint32_t aFlags);
 
   /**
    * Whether this image is opaque (i.e., needs a background painted behind it).
    */
   [notxpcom] boolean isOpaque();
 
   /**
+   * @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. Only valid for RASTER type images.
+   * frame.
+   *
+   * 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.
--- a/image/src/ClippedImage.cpp
+++ b/image/src/ClippedImage.cpp
@@ -263,30 +263,39 @@ ClippedImage::GetFrameInternal(const nsI
                                                    aSVGContext, frameToDraw,
                                                    aFlags);
   }
 
   MOZ_ASSERT(mCachedSurface, "Should have a cached surface now");
   return mCachedSurface->Surface();
 }
 
+NS_IMETHODIMP_(bool)
+ClippedImage::IsImageContainerAvailable(LayerManager* aManager, uint32_t aFlags)
+{
+  if (!ShouldClip()) {
+    return InnerImage()->IsImageContainerAvailable(aManager, aFlags);
+  }
+  return false;
+}
+
 NS_IMETHODIMP_(already_AddRefed<ImageContainer>)
 ClippedImage::GetImageContainer(LayerManager* aManager, 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()->GetImageContainer(aManager, aFlags);
   }
 
-  return (nullptr);
+  return nullptr;
 }
 
 static bool
 MustCreateSurface(gfxContext* aContext,
                   const nsIntSize& aSize,
                   const ImageRegion& aRegion,
                   const uint32_t aFlags)
 {
--- a/image/src/ClippedImage.h
+++ b/image/src/ClippedImage.h
@@ -32,16 +32,18 @@ public:
   NS_DECL_ISUPPORTS_INHERITED
 
   NS_IMETHOD GetWidth(int32_t* aWidth) override;
   NS_IMETHOD GetHeight(int32_t* aHeight) override;
   NS_IMETHOD GetIntrinsicSize(nsSize* aSize) override;
   NS_IMETHOD GetIntrinsicRatio(nsSize* aRatio) override;
   NS_IMETHOD_(TemporaryRef<SourceSurface>)
     GetFrame(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_(DrawResult) Draw(gfxContext* aContext,
                                const nsIntSize& aSize,
                                const ImageRegion& aRegion,
                                uint32_t aWhichFrame,
                                GraphicsFilter aFilter,
--- a/image/src/DynamicImage.cpp
+++ b/image/src/DynamicImage.cpp
@@ -189,16 +189,22 @@ DynamicImage::GetFrame(uint32_t aWhichFr
 NS_IMETHODIMP_(bool)
 DynamicImage::IsOpaque()
 {
   // XXX(seth): For performance reasons it'd be better to return true here, but
   // I'm not sure how we can guarantee it for an arbitrary gfxDrawable.
   return false;
 }
 
+NS_IMETHODIMP_(bool)
+DynamicImage::IsImageContainerAvailable(LayerManager* aManager, uint32_t aFlags)
+{
+  return false;
+}
+
 NS_IMETHODIMP_(already_AddRefed<ImageContainer>)
 DynamicImage::GetImageContainer(LayerManager* aManager, uint32_t aFlags)
 {
   return nullptr;
 }
 
 NS_IMETHODIMP_(DrawResult)
 DynamicImage::Draw(gfxContext* aContext,
--- a/image/src/FrozenImage.cpp
+++ b/image/src/FrozenImage.cpp
@@ -39,16 +39,22 @@ FrozenImage::GetAnimated(bool* aAnimated
 
 NS_IMETHODIMP_(TemporaryRef<SourceSurface>)
 FrozenImage::GetFrame(uint32_t aWhichFrame,
                       uint32_t aFlags)
 {
   return InnerImage()->GetFrame(FRAME_FIRST, aFlags);
 }
 
+NS_IMETHODIMP_(bool)
+FrozenImage::IsImageContainerAvailable(LayerManager* aManager, uint32_t aFlags)
+{
+  return false;
+}
+
 NS_IMETHODIMP_(already_AddRefed<ImageContainer>)
 FrozenImage::GetImageContainer(layers::LayerManager* aManager, 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.
--- a/image/src/FrozenImage.h
+++ b/image/src/FrozenImage.h
@@ -32,16 +32,18 @@ public:
   NS_DECL_ISUPPORTS_INHERITED
 
   virtual void IncrementAnimationConsumers() override;
   virtual void DecrementAnimationConsumers() override;
 
   NS_IMETHOD GetAnimated(bool* aAnimated) override;
   NS_IMETHOD_(TemporaryRef<SourceSurface>)
     GetFrame(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_(DrawResult) Draw(gfxContext* aContext,
                                const nsIntSize& aSize,
                                const ImageRegion& aRegion,
                                uint32_t aWhichFrame,
                                GraphicsFilter aFilter,
--- a/image/src/ImageWrapper.cpp
+++ b/image/src/ImageWrapper.cpp
@@ -175,16 +175,22 @@ ImageWrapper::GetFrame(uint32_t aWhichFr
 }
 
 NS_IMETHODIMP_(bool)
 ImageWrapper::IsOpaque()
 {
   return mInnerImage->IsOpaque();
 }
 
+NS_IMETHODIMP_(bool)
+ImageWrapper::IsImageContainerAvailable(LayerManager* aManager, uint32_t aFlags)
+{
+  return mInnerImage->IsImageContainerAvailable(aManager, aFlags);
+}
+
 NS_IMETHODIMP_(already_AddRefed<ImageContainer>)
 ImageWrapper::GetImageContainer(LayerManager* aManager, uint32_t aFlags)
 {
   return mInnerImage->GetImageContainer(aManager, aFlags);
 }
 
 NS_IMETHODIMP_(DrawResult)
 ImageWrapper::Draw(gfxContext* aContext,
--- a/image/src/OrientedImage.cpp
+++ b/image/src/OrientedImage.cpp
@@ -117,16 +117,25 @@ OrientedImage::GetFrame(uint32_t aWhichF
   ctx->Multiply(OrientationMatrix(size));
   gfxUtils::DrawPixelSnapped(ctx, drawable, size,
                              ImageRegion::Create(size),
                              surfaceFormat, GraphicsFilter::FILTER_FAST);
 
   return target->Snapshot();
 }
 
+NS_IMETHODIMP_(bool)
+OrientedImage::IsImageContainerAvailable(LayerManager* aManager, uint32_t aFlags)
+{
+  if (mOrientation.IsIdentity()) {
+    return InnerImage()->IsImageContainerAvailable(aManager, aFlags);
+  }
+  return false;
+}
+
 NS_IMETHODIMP_(already_AddRefed<ImageContainer>)
 OrientedImage::GetImageContainer(LayerManager* aManager, 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.
--- a/image/src/OrientedImage.h
+++ b/image/src/OrientedImage.h
@@ -29,16 +29,18 @@ public:
   NS_DECL_ISUPPORTS_INHERITED
 
   NS_IMETHOD GetWidth(int32_t* aWidth) override;
   NS_IMETHOD GetHeight(int32_t* aHeight) override;
   NS_IMETHOD GetIntrinsicSize(nsSize* aSize) override;
   NS_IMETHOD GetIntrinsicRatio(nsSize* aRatio) override;
   NS_IMETHOD_(TemporaryRef<SourceSurface>)
     GetFrame(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_(DrawResult) Draw(gfxContext* aContext,
                                const nsIntSize& aSize,
                                const ImageRegion& aRegion,
                                uint32_t aWhichFrame,
                                GraphicsFilter aFilter,
--- a/image/src/RasterImage.cpp
+++ b/image/src/RasterImage.cpp
@@ -800,16 +800,28 @@ RasterImage::GetCurrentImage(ImageContai
     aContainer->CreateImage(ImageFormat::CAIRO_SURFACE);
   MOZ_ASSERT(image);
 
   static_cast<CairoImage*>(image.get())->SetData(cairoData);
 
   return MakePair(result.first(), Move(image));
 }
 
+NS_IMETHODIMP_(bool)
+RasterImage::IsImageContainerAvailable(LayerManager* aManager, uint32_t aFlags)
+{
+  int32_t maxTextureSize = aManager->GetMaxTextureSize();
+  if (!mHasSize ||
+      mSize.width > maxTextureSize ||
+      mSize.height > maxTextureSize) {
+    return false;
+  }
+
+  return true;
+}
 
 NS_IMETHODIMP_(already_AddRefed<ImageContainer>)
 RasterImage::GetImageContainer(LayerManager* aManager, uint32_t aFlags)
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(aManager);
   MOZ_ASSERT((aFlags & ~(FLAG_SYNC_DECODE |
                          FLAG_SYNC_DECODE_IF_FAST |
--- a/image/src/VectorImage.cpp
+++ b/image/src/VectorImage.cpp
@@ -707,16 +707,22 @@ VectorImage::GetFrame(uint32_t aWhichFra
   auto result = Draw(context, imageIntSize,
                      ImageRegion::Create(imageIntSize),
                      aWhichFrame, GraphicsFilter::FILTER_NEAREST,
                      Nothing(), aFlags);
 
   return result == DrawResult::SUCCESS ? dt->Snapshot() : nullptr;
 }
 
+NS_IMETHODIMP_(bool)
+VectorImage::IsImageContainerAvailable(LayerManager* aManager, uint32_t aFlags)
+{
+  return false;
+}
+
 //******************************************************************************
 /* [noscript] ImageContainer getImageContainer(); */
 NS_IMETHODIMP_(already_AddRefed<ImageContainer>)
 VectorImage::GetImageContainer(LayerManager* aManager, uint32_t aFlags)
 {
   return nullptr;
 }