Bug 1146663 (Part 5) - Require that all image decoders support downscale-during-decode. r=tn
☠☠ backed out by 968702bfd84b ☠ ☠
authorSeth Fowler <mark.seth.fowler@gmail.com>
Sat, 19 Sep 2015 16:21:08 -0700
changeset 296044 c0d3f6e2a3e33f8b45bf4039126cbbe004448e3e
parent 296043 07d6fcc70e7c0476088f45264963505a63ebec53
child 296045 ccd6b5f5e544c1d708849144943a776941bd3794
push id5245
push userraliiev@mozilla.com
push dateThu, 29 Oct 2015 11:30:51 +0000
treeherdermozilla-beta@dac831dc1bd0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerstn
bugs1146663
milestone43.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 1146663 (Part 5) - Require that all image decoders support downscale-during-decode. r=tn
image/Decoder.cpp
image/Decoder.h
image/DecoderFactory.cpp
image/decoders/nsBMPDecoder.cpp
image/decoders/nsBMPDecoder.h
image/decoders/nsGIFDecoder2.cpp
image/decoders/nsGIFDecoder2.h
image/decoders/nsICODecoder.cpp
image/decoders/nsICODecoder.h
image/decoders/nsIconDecoder.cpp
image/decoders/nsIconDecoder.h
image/decoders/nsJPEGDecoder.cpp
image/decoders/nsJPEGDecoder.h
image/decoders/nsPNGDecoder.cpp
image/decoders/nsPNGDecoder.h
--- a/image/Decoder.cpp
+++ b/image/Decoder.cpp
@@ -240,16 +240,30 @@ Decoder::CompleteDecode()
         !(mDecoderFlags & DecoderFlags::IMAGE_IS_TRANSIENT) &&
         mCurrentFrame) {
       mCurrentFrame->SetOptimizable();
     }
   }
 }
 
 nsresult
+Decoder::SetTargetSize(const nsIntSize& aSize)
+{
+  // Make sure the size is reasonable.
+  if (MOZ_UNLIKELY(aSize.width <= 0 || aSize.height <= 0)) {
+    return NS_ERROR_FAILURE;
+  }
+
+  // Create a downscaler that we'll filter our output through.
+  mDownscaler.emplace(aSize);
+
+  return NS_OK;
+}
+
+nsresult
 Decoder::AllocateFrame(uint32_t aFrameNum,
                        const nsIntSize& aTargetSize,
                        const nsIntRect& aFrameRect,
                        gfx::SurfaceFormat aFormat,
                        uint8_t aPaletteDepth)
 {
   mCurrentFrame = AllocateFrameInternal(aFrameNum, aTargetSize, aFrameRect,
                                         aFormat, aPaletteDepth,
--- a/image/Decoder.h
+++ b/image/Decoder.h
@@ -6,16 +6,17 @@
 #ifndef mozilla_image_Decoder_h
 #define mozilla_image_Decoder_h
 
 #include "FrameAnimator.h"
 #include "RasterImage.h"
 #include "mozilla/RefPtr.h"
 #include "DecodePool.h"
 #include "DecoderFlags.h"
+#include "Downscaler.h"
 #include "ImageMetadata.h"
 #include "Orientation.h"
 #include "SourceBuffer.h"
 #include "SurfaceFlags.h"
 
 namespace mozilla {
 
 namespace Telemetry {
@@ -107,29 +108,24 @@ public:
     mMetadataDecode = aMetadataDecode;
   }
   bool IsMetadataDecode() const { return mMetadataDecode; }
 
   /**
    * If this decoder supports downscale-during-decode, sets the target size that
    * this image should be decoded to.
    *
-   * If this decoder *doesn't* support downscale-during-decode, returns
-   * NS_ERROR_NOT_AVAILABLE. If the provided size is unacceptable, returns
-   * another error.
+   * If the provided size is unacceptable, an error is returned.
    *
    * Returning NS_OK from this method is a promise that the decoder will decode
    * the image to the requested target size unless it encounters an error.
    *
    * This must be called before Init() is called.
    */
-  virtual nsresult SetTargetSize(const nsIntSize& aSize)
-  {
-    return NS_ERROR_NOT_AVAILABLE;
-  }
+  nsresult SetTargetSize(const nsIntSize& aSize);
 
   /**
    * Set the requested sample size for this decoder. Used to implement the
    * -moz-sample-size media fragment.
    *
    *  XXX(seth): Support for -moz-sample-size will be removed in bug 1120056.
    */
   virtual void SetSampleSize(int aSampleSize) { }
@@ -398,16 +394,18 @@ protected:
   RawAccessFrameRef AllocateFrameInternal(uint32_t aFrameNum,
                                           const nsIntSize& aTargetSize,
                                           const nsIntRect& aFrameRect,
                                           gfx::SurfaceFormat aFormat,
                                           uint8_t aPaletteDepth,
                                           imgFrame* aPreviousFrame);
 
 protected:
+  Maybe<Downscaler> mDownscaler;
+
   uint8_t* mImageData;  // Pointer to image data in either Cairo or 8bit format
   uint32_t mImageDataLength;
   uint32_t* mColormap;  // Current colormap to be used in Cairo format
   uint32_t mColormapSize;
 
 private:
   nsRefPtr<RasterImage> mImage;
   Maybe<SourceBufferIterator> mIterator;
--- a/image/DecoderFactory.cpp
+++ b/image/DecoderFactory.cpp
@@ -128,18 +128,16 @@ DecoderFactory::CreateDecoder(DecoderTyp
   decoder->SetDecoderFlags(aDecoderFlags | DecoderFlags::FIRST_FRAME_ONLY);
   decoder->SetSurfaceFlags(aSurfaceFlags);
   decoder->SetSampleSize(aSampleSize);
   decoder->SetResolution(aResolution);
 
   // Set a target size for downscale-during-decode if applicable.
   if (aTargetSize) {
     DebugOnly<nsresult> rv = decoder->SetTargetSize(*aTargetSize);
-    MOZ_ASSERT(nsresult(rv) != NS_ERROR_NOT_AVAILABLE,
-               "We're downscale-during-decode but decoder doesn't support it?");
     MOZ_ASSERT(NS_SUCCEEDED(rv), "Bad downscale-during-decode target size?");
   }
 
   decoder->Init();
   if (NS_FAILED(decoder->GetDecoderError())) {
     return nullptr;
   }
 
--- a/image/decoders/nsBMPDecoder.cpp
+++ b/image/decoders/nsBMPDecoder.cpp
@@ -59,30 +59,16 @@ nsBMPDecoder::nsBMPDecoder(RasterImage* 
 nsBMPDecoder::~nsBMPDecoder()
 {
   delete[] mColors;
   if (mRow) {
       free(mRow);
   }
 }
 
-nsresult
-nsBMPDecoder::SetTargetSize(const nsIntSize& aSize)
-{
-  // Make sure the size is reasonable.
-  if (MOZ_UNLIKELY(aSize.width <= 0 || aSize.height <= 0)) {
-    return NS_ERROR_FAILURE;
-  }
-
-  // Create a downscaler that we'll filter our output through.
-  mDownscaler.emplace(aSize);
-
-  return NS_OK;
-}
-
 // Sets whether or not the BMP will use alpha data
 void
 nsBMPDecoder::SetUseAlphaData(bool useAlphaData)
 {
   mUseAlphaData = useAlphaData;
 }
 
 // Obtains the bits per pixel from the internal BIH header
--- a/image/decoders/nsBMPDecoder.h
+++ b/image/decoders/nsBMPDecoder.h
@@ -4,34 +4,31 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 
 #ifndef mozilla_image_decoders_nsBMPDecoder_h
 #define mozilla_image_decoders_nsBMPDecoder_h
 
 #include "BMPFileHeaders.h"
 #include "Decoder.h"
-#include "Downscaler.h"
 #include "gfxColor.h"
 #include "nsAutoPtr.h"
 
 namespace mozilla {
 namespace image {
 
 class RasterImage;
 
 /// Decoder for BMP-Files, as used by Windows and OS/2
 
 class nsBMPDecoder : public Decoder
 {
 public:
     ~nsBMPDecoder();
 
-    nsresult SetTargetSize(const nsIntSize& aSize) override;
-
     // Specifies whether or not the BMP file will contain alpha data
     // If set to true and the BMP is 32BPP, the alpha data will be
     // retrieved from the 4th byte of image data per pixel
     void SetUseAlphaData(bool useAlphaData);
 
     // Obtains the bits per pixel from the internal BIH header
     int32_t GetBitsPerPixel() const;
 
@@ -72,18 +69,16 @@ private:
 
     uint32_t mPos; //< Number of bytes read from aBuffer in WriteInternal()
 
     BMPFILEHEADER mBFH;
     BITMAPV5HEADER mBIH;
     char mRawBuf[BIH_INTERNAL_LENGTH::WIN_V3]; //< If this is changed,
                                                // WriteInternal() MUST be updated
 
-    Maybe<Downscaler> mDownscaler;
-
     uint32_t mLOH; //< Length of the header
 
     uint32_t mNumColors; //< The number of used colors, i.e. the number of
                          // entries in mColors
     colorTable* mColors;
 
     bitFields mBitFields;
 
--- a/image/decoders/nsGIFDecoder2.cpp
+++ b/image/decoders/nsGIFDecoder2.cpp
@@ -94,30 +94,16 @@ nsGIFDecoder2::nsGIFDecoder2(RasterImage
 }
 
 nsGIFDecoder2::~nsGIFDecoder2()
 {
   free(mGIFStruct.local_colormap);
   free(mGIFStruct.hold);
 }
 
-nsresult
-nsGIFDecoder2::SetTargetSize(const nsIntSize& aSize)
-{
-  // Make sure the size is reasonable.
-  if (MOZ_UNLIKELY(aSize.width <= 0 || aSize.height <= 0)) {
-    return NS_ERROR_FAILURE;
-  }
-
-  // Create a downscaler that we'll filter our output through.
-  mDownscaler.emplace(aSize);
-
-  return NS_OK;
-}
-
 uint8_t*
 nsGIFDecoder2::GetCurrentRowBuffer()
 {
   if (!mDownscaler) {
     MOZ_ASSERT(!mDeinterlacer, "Deinterlacer without downscaler?");
     uint32_t bpp = mGIFStruct.images_decoded == 0 ? sizeof(uint32_t)
                                                   : sizeof(uint8_t);
     return mImageData + mGIFStruct.irow * mGIFStruct.width * bpp;
--- a/image/decoders/nsGIFDecoder2.h
+++ b/image/decoders/nsGIFDecoder2.h
@@ -3,35 +3,32 @@
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_image_decoders_nsGIFDecoder2_h
 #define mozilla_image_decoders_nsGIFDecoder2_h
 
 #include "Decoder.h"
-#include "Downscaler.h"
 
 #include "GIF2.h"
 #include "nsCOMPtr.h"
 
 namespace mozilla {
 namespace image {
 class RasterImage;
 
 //////////////////////////////////////////////////////////////////////
 // nsGIFDecoder2 Definition
 
 class nsGIFDecoder2 : public Decoder
 {
 public:
   ~nsGIFDecoder2();
 
-  nsresult SetTargetSize(const nsIntSize& aSize) override;
-
   virtual void WriteInternal(const char* aBuffer, uint32_t aCount) override;
   virtual void FinishInternal() override;
   virtual Telemetry::ID SpeedHistogram() override;
 
 private:
   friend class DecoderFactory;
 
   // Decoders should only be instantiated via DecoderFactory.
@@ -68,16 +65,15 @@ private:
 
   uint8_t mCurrentPass;
   uint8_t mLastFlushedPass;
   uint8_t mColorMask;        // Apply this to the pixel to keep within colormap
   bool mGIFOpen;
   bool mSawTransparency;
 
   gif_struct mGIFStruct;
-  Maybe<Downscaler> mDownscaler;
   Maybe<Deinterlacer> mDeinterlacer;
 };
 
 } // namespace image
 } // namespace mozilla
 
 #endif // mozilla_image_decoders_nsGIFDecoder2_h
--- a/image/decoders/nsICODecoder.cpp
+++ b/image/decoders/nsICODecoder.cpp
@@ -66,30 +66,16 @@ nsICODecoder::nsICODecoder(RasterImage* 
   , mBestResourceColorDepth(0)
   , mNumIcons(0)
   , mCurrIcon(0)
   , mBPP(0)
   , mMaskRowSize(0)
   , mCurrMaskLine(0)
 { }
 
-nsresult
-nsICODecoder::SetTargetSize(const nsIntSize& aSize)
-{
-  // Make sure the size is reasonable.
-  if (MOZ_UNLIKELY(aSize.width <= 0 || aSize.height <= 0)) {
-    return NS_ERROR_FAILURE;
-  }
-
-  // Create a downscaler that we'll filter our output through.
-  mDownscaler.emplace(aSize);
-
-  return NS_OK;
-}
-
 void
 nsICODecoder::FinishInternal()
 {
   // We shouldn't be called in error cases
   MOZ_ASSERT(!HasError(), "Shouldn't call FinishInternal after error!");
 
   GetFinalStateFromContainedDecoder();
 }
--- a/image/decoders/nsICODecoder.h
+++ b/image/decoders/nsICODecoder.h
@@ -38,18 +38,16 @@ enum class ICOState
   FINISHED_RESOURCE
 };
 
 class nsICODecoder : public Decoder
 {
 public:
   virtual ~nsICODecoder() { }
 
-  nsresult SetTargetSize(const nsIntSize& aSize) override;
-
   /// @return the width of the icon directory entry @aEntry.
   static uint32_t GetRealWidth(const IconDirEntry& aEntry)
   {
     return aEntry.mWidth == 0 ? 256 : aEntry.mWidth;
   }
 
   /// @return the width of the selected directory entry (mDirEntry).
   uint32_t GetRealWidth() const { return GetRealWidth(mDirEntry); }
@@ -114,17 +112,16 @@ private:
   LexerTransition<ICOState> ReadPNG(const char* aData, uint32_t aLen);
   LexerTransition<ICOState> ReadBIH(const char* aData);
   LexerTransition<ICOState> ReadBMP(const char* aData, uint32_t aLen);
   LexerTransition<ICOState> PrepareForMask();
   LexerTransition<ICOState> ReadMaskRow(const char* aData);
   LexerTransition<ICOState> FinishResource();
 
   StreamingLexer<ICOState, 32> mLexer; // The lexer.
-  Maybe<Downscaler> mDownscaler;       // Our downscaler, if we're downscaling.
   nsRefPtr<Decoder> mContainedDecoder; // Either a BMP or PNG decoder.
   char mBIHraw[40];                    // The bitmap information header.
   IconDirEntry mDirEntry;              // The dir entry for the selected resource.
   IntSize mBiggestResourceSize;        // Used to select the intrinsic size.
   IntSize mBiggestResourceHotSpot;     // Used to select the intrinsic size.
   uint16_t mBiggestResourceColorDepth; // Used to select the intrinsic size.
   int32_t mBestResourceDelta;          // Used to select the best resource.
   uint16_t mBestResourceColorDepth;    // Used to select the best resource.
--- a/image/decoders/nsIconDecoder.cpp
+++ b/image/decoders/nsIconDecoder.cpp
@@ -28,30 +28,16 @@ nsIconDecoder::nsIconDecoder(RasterImage
  , mHeight(-1)
 {
   // Nothing to do
 }
 
 nsIconDecoder::~nsIconDecoder()
 { }
 
-nsresult
-nsIconDecoder::SetTargetSize(const nsIntSize& aSize)
-{
-  // Make sure the size is reasonable.
-  if (MOZ_UNLIKELY(aSize.width <= 0 || aSize.height <= 0)) {
-    return NS_ERROR_FAILURE;
-  }
-
-  // Create a downscaler that we'll filter our output through.
-  mDownscaler.emplace(aSize);
-
-  return NS_OK;
-}
-
 void
 nsIconDecoder::WriteInternal(const char* aBuffer, uint32_t aCount)
 {
   MOZ_ASSERT(!HasError(), "Shouldn't call WriteInternal after error!");
 
   // Loop until the input data is gone
   while (aCount > 0) {
     switch (mState) {
--- a/image/decoders/nsIconDecoder.h
+++ b/image/decoders/nsIconDecoder.h
@@ -34,28 +34,24 @@ class RasterImage;
 //
 ////////////////////////////////////////////////////////////////////////////////
 
 class nsIconDecoder : public Decoder
 {
 public:
   virtual ~nsIconDecoder();
 
-  virtual nsresult SetTargetSize(const nsIntSize& aSize) override;
-
   virtual void WriteInternal(const char* aBuffer, uint32_t aCount) override;
 
 private:
   friend class DecoderFactory;
 
   // Decoders should only be instantiated via DecoderFactory.
   explicit nsIconDecoder(RasterImage* aImage);
 
-  Maybe<Downscaler> mDownscaler;
-
   uint32_t mExpectedDataLength;
   uint32_t mPixBytesRead;
   uint32_t mState;
   uint8_t mWidth;
   uint8_t mHeight;
 };
 
 enum {
--- a/image/decoders/nsJPEGDecoder.cpp
+++ b/image/decoders/nsJPEGDecoder.cpp
@@ -131,30 +131,16 @@ nsJPEGDecoder::~nsJPEGDecoder()
 }
 
 Telemetry::ID
 nsJPEGDecoder::SpeedHistogram()
 {
   return Telemetry::IMAGE_DECODE_SPEED_JPEG;
 }
 
-nsresult
-nsJPEGDecoder::SetTargetSize(const nsIntSize& aSize)
-{
-  // Make sure the size is reasonable.
-  if (MOZ_UNLIKELY(aSize.width <= 0 || aSize.height <= 0)) {
-    return NS_ERROR_FAILURE;
-  }
-
-  // Create a downscaler that we'll filter our output through.
-  mDownscaler.emplace(aSize);
-
-  return NS_OK;
-}
-
 void
 nsJPEGDecoder::InitInternal()
 {
   mCMSMode = gfxPlatform::GetCMSMode();
   if (GetSurfaceFlags() & SurfaceFlags::NO_COLORSPACE_CONVERSION) {
     mCMSMode = eCMSMode_Off;
   }
 
--- a/image/decoders/nsJPEGDecoder.h
+++ b/image/decoders/nsJPEGDecoder.h
@@ -10,17 +10,16 @@
 #include "RasterImage.h"
 // On Windows systems, RasterImage.h brings in 'windows.h', which defines INT32.
 // But the jpeg decoder has its own definition of INT32. To avoid build issues,
 // we need to undefine the version from 'windows.h'.
 #undef INT32
 
 #include "Decoder.h"
 
-#include "Downscaler.h"
 #include "nsAutoPtr.h"
 
 #include "nsIInputStream.h"
 #include "nsIPipe.h"
 #include "qcms.h"
 
 extern "C" {
 #include "jpeglib.h"
@@ -50,36 +49,32 @@ typedef enum {
 class RasterImage;
 struct Orientation;
 
 class nsJPEGDecoder : public Decoder
 {
 public:
   virtual ~nsJPEGDecoder();
 
-  virtual nsresult SetTargetSize(const nsIntSize& aSize) override;
-
   virtual void SetSampleSize(int aSampleSize) override
   {
     mSampleSize = aSampleSize;
   }
 
   virtual void InitInternal() override;
   virtual void WriteInternal(const char* aBuffer, uint32_t aCount) override;
   virtual void FinishInternal() override;
 
   virtual Telemetry::ID SpeedHistogram() override;
   void NotifyDone();
 
 protected:
   Orientation ReadOrientationFromEXIF();
   void OutputScanlines(bool* suspend);
 
-  Maybe<Downscaler> mDownscaler;
-
 private:
   friend class DecoderFactory;
 
   // Decoders should only be instantiated via DecoderFactory.
   nsJPEGDecoder(RasterImage* aImage, Decoder::DecodeStyle aDecodeStyle);
 
 public:
   struct jpeg_decompress_struct mInfo;
--- a/image/decoders/nsPNGDecoder.cpp
+++ b/image/decoders/nsPNGDecoder.cpp
@@ -136,30 +136,16 @@ nsPNGDecoder::~nsPNGDecoder()
 
     // mTransform belongs to us only if mInProfile is non-null
     if (mTransform) {
       qcms_transform_release(mTransform);
     }
   }
 }
 
-nsresult
-nsPNGDecoder::SetTargetSize(const nsIntSize& aSize)
-{
-  // Make sure the size is reasonable.
-  if (MOZ_UNLIKELY(aSize.width <= 0 || aSize.height <= 0)) {
-    return NS_ERROR_FAILURE;
-  }
-
-  // Create a downscaler that we'll filter our output through.
-  mDownscaler.emplace(aSize);
-
-  return NS_OK;
-}
-
 void
 nsPNGDecoder::CheckForTransparency(SurfaceFormat aFormat,
                                    const IntRect& aFrameRect)
 {
   // Check if the image has a transparent color in its palette.
   if (aFormat == SurfaceFormat::B8G8R8A8) {
     PostHasTransparency();
   }
--- a/image/decoders/nsPNGDecoder.h
+++ b/image/decoders/nsPNGDecoder.h
@@ -3,17 +3,16 @@
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_image_decoders_nsPNGDecoder_h
 #define mozilla_image_decoders_nsPNGDecoder_h
 
 #include "Decoder.h"
-#include "Downscaler.h"
 
 #include "gfxTypes.h"
 
 #include "nsCOMPtr.h"
 
 #include "png.h"
 
 #include "qcms.h"
@@ -22,18 +21,16 @@ namespace mozilla {
 namespace image {
 class RasterImage;
 
 class nsPNGDecoder : public Decoder
 {
 public:
   virtual ~nsPNGDecoder();
 
-  virtual nsresult SetTargetSize(const nsIntSize& aSize) override;
-
   virtual void InitInternal() override;
   virtual void WriteInternal(const char* aBuffer, uint32_t aCount) override;
   virtual Telemetry::ID SpeedHistogram() override;
 
   nsresult CreateFrame(png_uint_32 aXOffset, png_uint_32 aYOffset,
                        int32_t aWidth, int32_t aHeight,
                        gfx::SurfaceFormat aFormat);
   void EndImageFrame();
@@ -80,17 +77,16 @@ private:
   // XXX(seth): nsICODecoder is temporarily an exception to this rule.
   explicit nsPNGDecoder(RasterImage* aImage);
 
   void PostPartialInvalidation(const IntRect& aInvalidRegion);
   void PostFullInvalidation();
 
 public:
   png_structp mPNG;
-  Maybe<Downscaler> mDownscaler;
   png_infop mInfo;
   nsIntRect mFrameRect;
   uint8_t* mCMSLine;
   uint8_t* interlacebuf;
   qcms_profile* mInProfile;
   qcms_transform* mTransform;
 
   gfx::SurfaceFormat format;