[tor-commits] [tor-browser/esr24] Bug 896268 - Use a stateless approach to synchronous image decoding. r=jdm, a=abillings

mikeperry at torproject.org mikeperry at torproject.org
Fri Aug 29 05:26:38 UTC 2014


commit dcbe26ea5f1021f44632b086df0b9e8c07142b12
Author: Seth Fowler <seth at mozilla.com>
Date:   Tue Dec 17 14:04:24 2013 -0800

    Bug 896268 - Use a stateless approach to synchronous image decoding. r=jdm, a=abillings
---
 image/decoders/nsBMPDecoder.cpp  |    2 +-
 image/decoders/nsBMPDecoder.h    |    2 +-
 image/decoders/nsGIFDecoder2.cpp |    2 +-
 image/decoders/nsGIFDecoder2.h   |    2 +-
 image/decoders/nsICODecoder.cpp  |   18 +++++++-------
 image/decoders/nsICODecoder.h    |    4 +--
 image/decoders/nsIconDecoder.cpp |    2 +-
 image/decoders/nsIconDecoder.h   |    2 +-
 image/decoders/nsJPEGDecoder.cpp |    9 +++++--
 image/decoders/nsJPEGDecoder.h   |    2 +-
 image/decoders/nsPNGDecoder.cpp  |    2 +-
 image/decoders/nsPNGDecoder.h    |    2 +-
 image/src/DecodeStrategy.h       |   36 +++++++++++++++++++++++++++
 image/src/Decoder.cpp            |   16 +++++++-----
 image/src/Decoder.h              |   50 +++-----------------------------------
 image/src/RasterImage.cpp        |   42 +++++++++++++++-----------------
 image/src/RasterImage.h          |   10 +++++---
 17 files changed, 103 insertions(+), 100 deletions(-)

diff --git a/image/decoders/nsBMPDecoder.cpp b/image/decoders/nsBMPDecoder.cpp
index 8f7b5ad..704c8fc 100644
--- a/image/decoders/nsBMPDecoder.cpp
+++ b/image/decoders/nsBMPDecoder.cpp
@@ -189,7 +189,7 @@ NS_METHOD nsBMPDecoder::CalcBitShift()
 }
 
 void
-nsBMPDecoder::WriteInternal(const char* aBuffer, uint32_t aCount)
+nsBMPDecoder::WriteInternal(const char* aBuffer, uint32_t aCount, DecodeStrategy)
 {
     NS_ABORT_IF_FALSE(!HasError(), "Shouldn't call WriteInternal after error!");
 
diff --git a/image/decoders/nsBMPDecoder.h b/image/decoders/nsBMPDecoder.h
index a212ec8..51f4140 100644
--- a/image/decoders/nsBMPDecoder.h
+++ b/image/decoders/nsBMPDecoder.h
@@ -45,7 +45,7 @@ public:
     // for 32BPP bitmaps.  Only use after the bitmap has been processed.
     bool HasAlphaData() const;
 
-    virtual void WriteInternal(const char* aBuffer, uint32_t aCount);
+    virtual void WriteInternal(const char* aBuffer, uint32_t aCount, DecodeStrategy aStrategy);
     virtual void FinishInternal();
 
 private:
diff --git a/image/decoders/nsGIFDecoder2.cpp b/image/decoders/nsGIFDecoder2.cpp
index 269837c..66bfd65 100644
--- a/image/decoders/nsGIFDecoder2.cpp
+++ b/image/decoders/nsGIFDecoder2.cpp
@@ -544,7 +544,7 @@ static void ConvertColormap(uint32_t *aColormap, uint32_t aColors)
 }
 
 void
-nsGIFDecoder2::WriteInternal(const char *aBuffer, uint32_t aCount)
+nsGIFDecoder2::WriteInternal(const char *aBuffer, uint32_t aCount, DecodeStrategy)
 {
   NS_ABORT_IF_FALSE(!HasError(), "Shouldn't call WriteInternal after error!");
 
diff --git a/image/decoders/nsGIFDecoder2.h b/image/decoders/nsGIFDecoder2.h
index d056607..328e499 100644
--- a/image/decoders/nsGIFDecoder2.h
+++ b/image/decoders/nsGIFDecoder2.h
@@ -26,7 +26,7 @@ public:
   nsGIFDecoder2(RasterImage &aImage);
   ~nsGIFDecoder2();
 
-  virtual void WriteInternal(const char* aBuffer, uint32_t aCount);
+  virtual void WriteInternal(const char* aBuffer, uint32_t aCount, DecodeStrategy aStrategy);
   virtual void FinishInternal();
   virtual Telemetry::ID SpeedHistogram();
 
diff --git a/image/decoders/nsICODecoder.cpp b/image/decoders/nsICODecoder.cpp
index 395965c..8ef2e9a 100644
--- a/image/decoders/nsICODecoder.cpp
+++ b/image/decoders/nsICODecoder.cpp
@@ -209,13 +209,13 @@ nsICODecoder::SetHotSpotIfCursor() {
 }
 
 void
-nsICODecoder::WriteInternal(const char* aBuffer, uint32_t aCount)
+nsICODecoder::WriteInternal(const char* aBuffer, uint32_t aCount, DecodeStrategy aStrategy)
 {
   NS_ABORT_IF_FALSE(!HasError(), "Shouldn't call WriteInternal after error!");
 
   if (!aCount) {
     if (mContainedDecoder) {
-      WriteToContainedDecoder(aBuffer, aCount);
+      WriteToContainedDecoder(aBuffer, aCount, aStrategy);
     }
     return;
   }
@@ -337,7 +337,7 @@ nsICODecoder::WriteInternal(const char* aBuffer, uint32_t aCount)
       mContainedDecoder->InitSharedDecoder(mImageData, mImageDataLength,
                                            mColormap, mColormapSize,
                                            mCurrentFrame);
-      if (!WriteToContainedDecoder(mSignature, PNGSIGNATURESIZE)) {
+      if (!WriteToContainedDecoder(mSignature, PNGSIGNATURESIZE, aStrategy)) {
         return;
       }
     }
@@ -345,7 +345,7 @@ nsICODecoder::WriteInternal(const char* aBuffer, uint32_t aCount)
 
   // If we have a PNG, let the PNG decoder do all of the rest of the work
   if (mIsPNG && mContainedDecoder && mPos >= mImageOffset + PNGSIGNATURESIZE) {
-    if (!WriteToContainedDecoder(aBuffer, aCount)) {
+    if (!WriteToContainedDecoder(aBuffer, aCount, aStrategy)) {
       return;
     }
 
@@ -423,7 +423,7 @@ nsICODecoder::WriteInternal(const char* aBuffer, uint32_t aCount)
       PostDataError();
       return;
     }
-    if (!WriteToContainedDecoder((const char*)bfhBuffer, sizeof(bfhBuffer))) {
+    if (!WriteToContainedDecoder((const char*)bfhBuffer, sizeof(bfhBuffer), aStrategy)) {
       return;
     }
 
@@ -444,7 +444,7 @@ nsICODecoder::WriteInternal(const char* aBuffer, uint32_t aCount)
     }
 
     // Write out the BMP's bitmap info header
-    if (!WriteToContainedDecoder(mBIHraw, sizeof(mBIHraw))) {
+    if (!WriteToContainedDecoder(mBIHraw, sizeof(mBIHraw), aStrategy)) {
       return;
     }
 
@@ -492,7 +492,7 @@ nsICODecoder::WriteInternal(const char* aBuffer, uint32_t aCount)
         toFeed = aCount;
       }
 
-      if (!WriteToContainedDecoder(aBuffer, toFeed)) {
+      if (!WriteToContainedDecoder(aBuffer, toFeed, aStrategy)) {
         return;
       }
 
@@ -568,9 +568,9 @@ nsICODecoder::WriteInternal(const char* aBuffer, uint32_t aCount)
 }
 
 bool
-nsICODecoder::WriteToContainedDecoder(const char* aBuffer, uint32_t aCount)
+nsICODecoder::WriteToContainedDecoder(const char* aBuffer, uint32_t aCount, DecodeStrategy aStrategy)
 {
-  mContainedDecoder->Write(aBuffer, aCount);
+  mContainedDecoder->Write(aBuffer, aCount, aStrategy);
   if (mContainedDecoder->HasDataError()) {
     mDataError = mContainedDecoder->HasDataError();
   }
diff --git a/image/decoders/nsICODecoder.h b/image/decoders/nsICODecoder.h
index 733d353..73576b8 100644
--- a/image/decoders/nsICODecoder.h
+++ b/image/decoders/nsICODecoder.h
@@ -37,7 +37,7 @@ public:
     return mDirEntry.mHeight == 0 ? 256 : mDirEntry.mHeight; 
   }
 
-  virtual void WriteInternal(const char* aBuffer, uint32_t aCount);
+  virtual void WriteInternal(const char* aBuffer, uint32_t aCount, DecodeStrategy aStrategy);
   virtual void FinishInternal();
   virtual bool NeedsNewFrame() const;
   virtual nsresult AllocateFrame();
@@ -45,7 +45,7 @@ public:
 private:
   // Writes to the contained decoder and sets the appropriate errors
   // Returns true if there are no errors.
-  bool WriteToContainedDecoder(const char* aBuffer, uint32_t aCount);
+  bool WriteToContainedDecoder(const char* aBuffer, uint32_t aCount, DecodeStrategy aStrategy);
 
   // Processes a single dir entry of the icon resource
   void ProcessDirEntry(IconDirEntry& aTarget);
diff --git a/image/decoders/nsIconDecoder.cpp b/image/decoders/nsIconDecoder.cpp
index f5c9d33..29abc09 100644
--- a/image/decoders/nsIconDecoder.cpp
+++ b/image/decoders/nsIconDecoder.cpp
@@ -30,7 +30,7 @@ nsIconDecoder::~nsIconDecoder()
 { }
 
 void
-nsIconDecoder::WriteInternal(const char *aBuffer, uint32_t aCount)
+nsIconDecoder::WriteInternal(const char *aBuffer, uint32_t aCount, DecodeStrategy)
 {
   NS_ABORT_IF_FALSE(!HasError(), "Shouldn't call WriteInternal after error!");
 
diff --git a/image/decoders/nsIconDecoder.h b/image/decoders/nsIconDecoder.h
index 31bf2e0..4fcffcd 100644
--- a/image/decoders/nsIconDecoder.h
+++ b/image/decoders/nsIconDecoder.h
@@ -41,7 +41,7 @@ public:
   nsIconDecoder(RasterImage &aImage);
   virtual ~nsIconDecoder();
 
-  virtual void WriteInternal(const char* aBuffer, uint32_t aCount);
+  virtual void WriteInternal(const char* aBuffer, uint32_t aCount, DecodeStrategy aStrategy);
 
   uint8_t mWidth;
   uint8_t mHeight;
diff --git a/image/decoders/nsJPEGDecoder.cpp b/image/decoders/nsJPEGDecoder.cpp
index fa580d5..24b9fd3 100644
--- a/image/decoders/nsJPEGDecoder.cpp
+++ b/image/decoders/nsJPEGDecoder.cpp
@@ -179,15 +179,20 @@ nsJPEGDecoder::FinishInternal()
    * XXXbholley - It seems wrong that this should be necessary, but at the
    * moment I'm just folding the contents of Flush() into Close() so that
    * we can get rid of it.
+   *
+   * XXX(seth): It'd be great to get rid of this. For now, we treat this as a
+   * write to a synchronous decoder, which means that this must be called only
+   * on the main thread. (That's asserted in Decoder::Finish and
+   * Decoder::FinishSharedDecoder.)
    */
   if ((mState != JPEG_DONE && mState != JPEG_SINK_NON_JPEG_TRAILER) &&
       (mState != JPEG_ERROR) &&
       !IsSizeDecode())
-    this->Write(nullptr, 0);
+    this->Write(nullptr, 0, DECODE_SYNC);
 }
 
 void
-nsJPEGDecoder::WriteInternal(const char *aBuffer, uint32_t aCount)
+nsJPEGDecoder::WriteInternal(const char *aBuffer, uint32_t aCount, DecodeStrategy)
 {
   mSegment = (const JOCTET *)aBuffer;
   mSegmentLen = aCount;
diff --git a/image/decoders/nsJPEGDecoder.h b/image/decoders/nsJPEGDecoder.h
index 00409f3..82ec3bb 100644
--- a/image/decoders/nsJPEGDecoder.h
+++ b/image/decoders/nsJPEGDecoder.h
@@ -55,7 +55,7 @@ public:
   virtual ~nsJPEGDecoder();
 
   virtual void InitInternal();
-  virtual void WriteInternal(const char* aBuffer, uint32_t aCount);
+  virtual void WriteInternal(const char* aBuffer, uint32_t aCount, DecodeStrategy aStrategy);
   virtual void FinishInternal();
 
   virtual Telemetry::ID SpeedHistogram();
diff --git a/image/decoders/nsPNGDecoder.cpp b/image/decoders/nsPNGDecoder.cpp
index 23003ea..48ed981 100644
--- a/image/decoders/nsPNGDecoder.cpp
+++ b/image/decoders/nsPNGDecoder.cpp
@@ -286,7 +286,7 @@ nsPNGDecoder::InitInternal()
 }
 
 void
-nsPNGDecoder::WriteInternal(const char *aBuffer, uint32_t aCount)
+nsPNGDecoder::WriteInternal(const char *aBuffer, uint32_t aCount, DecodeStrategy)
 {
   NS_ABORT_IF_FALSE(!HasError(), "Shouldn't call WriteInternal after error!");
 
diff --git a/image/decoders/nsPNGDecoder.h b/image/decoders/nsPNGDecoder.h
index 51f2ebd..b8c63a7 100644
--- a/image/decoders/nsPNGDecoder.h
+++ b/image/decoders/nsPNGDecoder.h
@@ -28,7 +28,7 @@ public:
   virtual ~nsPNGDecoder();
 
   virtual void InitInternal();
-  virtual void WriteInternal(const char* aBuffer, uint32_t aCount);
+  virtual void WriteInternal(const char* aBuffer, uint32_t aCount, DecodeStrategy aStrategy);
   virtual Telemetry::ID SpeedHistogram();
 
   void CreateFrame(png_uint_32 x_offset, png_uint_32 y_offset,
diff --git a/image/src/DecodeStrategy.h b/image/src/DecodeStrategy.h
new file mode 100644
index 0000000..44c64b6
--- /dev/null
+++ b/image/src/DecodeStrategy.h
@@ -0,0 +1,36 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ *
+ * 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/. */
+
+/** @file
+ * An enumeration used by RasterImage and Decoder to specify which 'strategy' to
+ * use for image decoding - synchronous or asynchronous.
+ */
+
+#ifndef mozilla_imagelib_DecodeStrategy_h_
+#define mozilla_imagelib_DecodeStrategy_h_
+
+namespace mozilla {
+namespace image {
+
+enum DecodeStrategy {
+  // DECODE_SYNC requests a synchronous decode, which will continue decoding
+  // frames as long as it has more source data. It returns to the caller only
+  // once decoding is complete (or until it needs more source data before
+  // continuing). Because DECODE_SYNC can involve allocating new imgFrames, it
+  // can only be run on the main thread.
+  DECODE_SYNC,
+
+  // DECODE_ASYNC requests an asynchronous decode, which will continue decoding
+  // until it either finishes a frame or runs out of source data. Because
+  // DECODE_ASYNC does not allocate new imgFrames, it can be safely run off the
+  // main thread. (And hence workers in the decode pool always use it.)
+  DECODE_ASYNC
+};
+
+} // namespace image
+} // namespace mozilla
+
+#endif
diff --git a/image/src/Decoder.cpp b/image/src/Decoder.cpp
index 5fa835d..85845f6 100644
--- a/image/src/Decoder.cpp
+++ b/image/src/Decoder.cpp
@@ -28,7 +28,6 @@ Decoder::Decoder(RasterImage &aImage)
   , mSizeDecode(false)
   , mInFrame(false)
   , mIsAnimated(false)
-  , mSynchronous(false)
 {
 }
 
@@ -85,9 +84,10 @@ Decoder::InitSharedDecoder(uint8_t* imageData, uint32_t imageDataLength,
 }
 
 void
-Decoder::Write(const char* aBuffer, uint32_t aCount)
+Decoder::Write(const char* aBuffer, uint32_t aCount, DecodeStrategy aStrategy)
 {
   PROFILER_LABEL("ImageDecoder", "Write");
+  MOZ_ASSERT(NS_IsMainThread() || aStrategy == DECODE_ASYNC);
 
   // We're strict about decoder errors
   NS_ABORT_IF_FALSE(!HasDecoderError(),
@@ -103,16 +103,16 @@ Decoder::Write(const char* aBuffer, uint32_t aCount)
   }
 
   // Pass the data along to the implementation
-  WriteInternal(aBuffer, aCount);
+  WriteInternal(aBuffer, aCount, aStrategy);
 
   // If we're a synchronous decoder and we need a new frame to proceed, let's
   // create one and call it again.
-  while (mSynchronous && NeedsNewFrame() && !HasDataError()) {
+  while (aStrategy == DECODE_SYNC && NeedsNewFrame() && !HasDataError()) {
     nsresult rv = AllocateFrame();
 
     if (NS_SUCCEEDED(rv)) {
       // Tell the decoder to use the data it saved when it asked for a new frame.
-      WriteInternal(nullptr, 0);
+      WriteInternal(nullptr, 0, aStrategy);
     }
   }
 }
@@ -120,6 +120,8 @@ Decoder::Write(const char* aBuffer, uint32_t aCount)
 void
 Decoder::Finish(RasterImage::eShutdownIntent aShutdownIntent)
 {
+  MOZ_ASSERT(NS_IsMainThread());
+
   // Implementation-specific finalization
   if (!HasError())
     FinishInternal();
@@ -185,6 +187,8 @@ Decoder::Finish(RasterImage::eShutdownIntent aShutdownIntent)
 void
 Decoder::FinishSharedDecoder()
 {
+  MOZ_ASSERT(NS_IsMainThread());
+
   if (!HasError()) {
     FinishInternal();
   }
@@ -274,7 +278,7 @@ Decoder::SetSizeOnImage()
  */
 
 void Decoder::InitInternal() { }
-void Decoder::WriteInternal(const char* aBuffer, uint32_t aCount) { }
+void Decoder::WriteInternal(const char* aBuffer, uint32_t aCount, DecodeStrategy aStrategy) { }
 void Decoder::FinishInternal() { }
 
 /*
diff --git a/image/src/Decoder.h b/image/src/Decoder.h
index 705cb36..285cf59 100644
--- a/image/src/Decoder.h
+++ b/image/src/Decoder.h
@@ -9,6 +9,7 @@
 #include "RasterImage.h"
 #include "imgDecoderObserver.h"
 #include "mozilla/RefPtr.h"
+#include "DecodeStrategy.h"
 #include "ImageMetadata.h"
 
 namespace mozilla {
@@ -48,7 +49,7 @@ public:
    *
    * Notifications Sent: TODO
    */
-  void Write(const char* aBuffer, uint32_t aCount);
+  void Write(const char* aBuffer, uint32_t aCount, DecodeStrategy aStrategy);
 
   /**
    * Informs the decoder that all the data has been written.
@@ -92,11 +93,6 @@ public:
     mSizeDecode = aSizeDecode;
   }
 
-  bool IsSynchronous() const
-  {
-    return mSynchronous;
-  }
-
   void SetObserver(imgDecoderObserver* aObserver)
   {
     MOZ_ASSERT(aObserver);
@@ -175,7 +171,7 @@ protected:
    * only these methods.
    */
   virtual void InitInternal();
-  virtual void WriteInternal(const char* aBuffer, uint32_t aCount);
+  virtual void WriteInternal(const char* aBuffer, uint32_t aCount, DecodeStrategy aStrategy);
   virtual void FinishInternal();
 
   /*
@@ -237,17 +233,6 @@ protected:
   bool mDataError;
 
 private:
-  // Decode in synchronous mode. This is unsafe off-main-thread since it may
-  // attempt to allocate frames. To ensure that we never accidentally leave the
-  // decoder in synchronous mode, this should only be called by
-  // AutoSetSyncDecode.
-  void SetSynchronous(bool aSynchronous)
-  {
-    mSynchronous = aSynchronous;
-  }
-
-  friend class AutoSetSyncDecode;
-
   uint32_t mFrameCount; // Number of frames, including anything in-progress
 
   nsIntRect mInvalidRect; // Tracks an invalidation region in the current frame.
@@ -284,35 +269,6 @@ private:
   bool mSizeDecode;
   bool mInFrame;
   bool mIsAnimated;
-  bool mSynchronous;
-};
-
-// A RAII helper class to automatically pair a call to SetSynchronous(true)
-// with a call to SetSynchronous(false), since failing to do so can lead us
-// to try to allocate frames off-main-thread, which is unsafe. Synchronous
-// decoding may only happen within the scope of an AutoSetSyncDecode. Nested
-// AutoSetSyncDecode's are OK.
-class AutoSetSyncDecode
-{
-public:
-  AutoSetSyncDecode(Decoder* aDecoder)
-    : mDecoder(aDecoder)
-  {
-    MOZ_ASSERT(NS_IsMainThread());
-    MOZ_ASSERT(mDecoder);
-
-    mOriginalValue = mDecoder->IsSynchronous();
-    mDecoder->SetSynchronous(true);
-  }
-
-  ~AutoSetSyncDecode()
-  {
-    mDecoder->SetSynchronous(mOriginalValue);
-  }
-
-private:
-  nsRefPtr<Decoder> mDecoder;
-  bool              mOriginalValue;
 };
 
 } // namespace image
diff --git a/image/src/RasterImage.cpp b/image/src/RasterImage.cpp
index 65f8169..8b066434 100644
--- a/image/src/RasterImage.cpp
+++ b/image/src/RasterImage.cpp
@@ -1714,8 +1714,7 @@ RasterImage::AddSourceData(const char *aBuffer, uint32_t aCount)
   // we'll queue up the data and write it out when we do.)
   if (!StoringSourceData() && mHasSize) {
     {
-      AutoSetSyncDecode syncDecode(mDecoder);
-      rv = WriteToDecoder(aBuffer, aCount);
+      rv = WriteToDecoder(aBuffer, aCount, DECODE_SYNC);
       CONTAINER_ENSURE_SUCCESS(rv);
     }
 
@@ -2261,7 +2260,7 @@ RasterImage::ShutdownDecoder(eShutdownIntent aIntent)
 
 // Writes the data to the decoder, updating the total number of bytes written.
 nsresult
-RasterImage::WriteToDecoder(const char *aBuffer, uint32_t aCount)
+RasterImage::WriteToDecoder(const char *aBuffer, uint32_t aCount, DecodeStrategy aStrategy)
 {
   mDecodingMonitor.AssertCurrentThreadIn();
 
@@ -2271,7 +2270,7 @@ RasterImage::WriteToDecoder(const char *aBuffer, uint32_t aCount)
   // Write
   nsRefPtr<Decoder> kungFuDeathGrip = mDecoder;
   mInDecoder = true;
-  mDecoder->Write(aBuffer, aCount);
+  mDecoder->Write(aBuffer, aCount, aStrategy);
   mInDecoder = false;
 
   CONTAINER_ENSURE_SUCCESS(mDecoder->GetDecoderError());
@@ -2435,8 +2434,7 @@ RasterImage::RequestDecodeCore(RequestDecodeType aDecodeType)
   // to finish decoding.
   if (!mDecoded && !mInDecoder && mHasSourceData && aDecodeType == SYNCHRONOUS_NOTIFY_AND_SOME_DECODE) {
     PROFILER_LABEL_PRINTF("RasterImage", "DecodeABitOf", "%s", GetURIString().get());
-    AutoSetSyncDecode syncDecode(mDecoder);
-    DecodePool::Singleton()->DecodeABitOf(this);
+    DecodePool::Singleton()->DecodeABitOf(this, DECODE_SYNC);
     return NS_OK;
   }
 
@@ -2518,13 +2516,9 @@ RasterImage::SyncDecode()
     CONTAINER_ENSURE_SUCCESS(rv);
   }
 
-  {
-    AutoSetSyncDecode syncDecode(mDecoder);
-
-    // Write everything we have
-    rv = DecodeSomeData(mSourceData.Length() - mBytesDecoded);
-    CONTAINER_ENSURE_SUCCESS(rv);
-  }
+  // Write everything we have
+  rv = DecodeSomeData(mSourceData.Length() - mBytesDecoded, DECODE_SYNC);
+  CONTAINER_ENSURE_SUCCESS(rv);
 
   // When we're doing a sync decode, we want to get as much information from the
   // image as possible. We've send the decoder all of our data, so now's a good
@@ -2861,7 +2855,7 @@ RasterImage::RequestDiscard()
 
 // Flushes up to aMaxBytes to the decoder.
 nsresult
-RasterImage::DecodeSomeData(uint32_t aMaxBytes)
+RasterImage::DecodeSomeData(uint32_t aMaxBytes, DecodeStrategy aStrategy)
 {
   // We should have a decoder if we get here
   NS_ABORT_IF_FALSE(mDecoder, "trying to decode without decoder!");
@@ -2873,7 +2867,7 @@ RasterImage::DecodeSomeData(uint32_t aMaxBytes)
   // passing it a null buffer.
   if (mDecodeRequest->mAllocatedNewFrame) {
     mDecodeRequest->mAllocatedNewFrame = false;
-    nsresult rv = WriteToDecoder(nullptr, 0);
+    nsresult rv = WriteToDecoder(nullptr, 0, aStrategy);
     if (NS_FAILED(rv) || mDecoder->NeedsNewFrame()) {
       return rv;
     }
@@ -2889,7 +2883,8 @@ RasterImage::DecodeSomeData(uint32_t aMaxBytes)
   uint32_t bytesToDecode = std::min(aMaxBytes,
                                     mSourceData.Length() - mBytesDecoded);
   nsresult rv = WriteToDecoder(mSourceData.Elements() + mBytesDecoded,
-                               bytesToDecode);
+                               bytesToDecode,
+                               aStrategy);
 
   return rv;
 }
@@ -3245,7 +3240,7 @@ RasterImage::DecodePool::RequestDecode(RasterImage* aImg)
 }
 
 void
-RasterImage::DecodePool::DecodeABitOf(RasterImage* aImg)
+RasterImage::DecodePool::DecodeABitOf(RasterImage* aImg, DecodeStrategy aStrategy)
 {
   MOZ_ASSERT(NS_IsMainThread());
   aImg->mDecodingMonitor.AssertCurrentThreadIn();
@@ -3257,7 +3252,7 @@ RasterImage::DecodePool::DecodeABitOf(RasterImage* aImg)
     }
   }
 
-  DecodeSomeOfImage(aImg);
+  DecodeSomeOfImage(aImg, aStrategy);
 
   aImg->FinishedSomeDecoding();
 
@@ -3325,7 +3320,7 @@ RasterImage::DecodePool::DecodeJob::Run()
     type = DECODE_TYPE_UNTIL_TIME;
   }
 
-  DecodePool::Singleton()->DecodeSomeOfImage(mImage, type, mRequest->mBytesToDecode);
+  DecodePool::Singleton()->DecodeSomeOfImage(mImage, DECODE_ASYNC, type, mRequest->mBytesToDecode);
 
   uint32_t bytesDecoded = mImage->mBytesDecoded - oldByteCount;
 
@@ -3370,7 +3365,9 @@ RasterImage::DecodePool::DecodeUntilSizeAvailable(RasterImage* aImg)
     }
   }
 
-  nsresult rv = DecodeSomeOfImage(aImg, DECODE_TYPE_UNTIL_SIZE);
+  // We use DECODE_ASYNC here because we just want to get the size information
+  // here and defer the rest of the work.
+  nsresult rv = DecodeSomeOfImage(aImg, DECODE_ASYNC, DECODE_TYPE_UNTIL_SIZE);
   if (NS_FAILED(rv)) {
     return rv;
   }
@@ -3388,6 +3385,7 @@ RasterImage::DecodePool::DecodeUntilSizeAvailable(RasterImage* aImg)
 
 nsresult
 RasterImage::DecodePool::DecodeSomeOfImage(RasterImage* aImg,
+                                           DecodeStrategy aStrategy,
                                            DecodeType aDecodeType /* = DECODE_TYPE_UNTIL_TIME */,
                                            uint32_t bytesToDecode /* = 0 */)
 {
@@ -3407,7 +3405,7 @@ RasterImage::DecodePool::DecodeSomeOfImage(RasterImage* aImg,
 
   // If we're doing synchronous decodes, and we're waiting on a new frame for
   // this image, get it now.
-  if (aImg->mDecoder->IsSynchronous() && aImg->mDecoder->NeedsNewFrame()) {
+  if (aStrategy == DECODE_SYNC && aImg->mDecoder->NeedsNewFrame()) {
     MOZ_ASSERT(NS_IsMainThread());
 
     aImg->mDecoder->AllocateFrame();
@@ -3456,7 +3454,7 @@ RasterImage::DecodePool::DecodeSomeOfImage(RasterImage* aImg,
          (aImg->mDecodeRequest && aImg->mDecodeRequest->mAllocatedNewFrame)) {
     chunkCount++;
     uint32_t chunkSize = std::min(bytesToDecode, maxBytes);
-    nsresult rv = aImg->DecodeSomeData(chunkSize);
+    nsresult rv = aImg->DecodeSomeData(chunkSize, aStrategy);
     if (NS_FAILED(rv)) {
       aImg->DoError();
       return rv;
diff --git a/image/src/RasterImage.h b/image/src/RasterImage.h
index 420a470..87d7286 100644
--- a/image/src/RasterImage.h
+++ b/image/src/RasterImage.h
@@ -27,6 +27,7 @@
 #include "nsTArray.h"
 #include "imgFrame.h"
 #include "nsThreadUtils.h"
+#include "DecodeStrategy.h"
 #include "DiscardTracker.h"
 #include "nsISupportsImpl.h"
 #include "mozilla/LinkedList.h"
@@ -314,6 +315,8 @@ public:
     eShutdownIntent_AllCount    = 3
   };
 
+  // Decode strategy
+
 private:
   imgStatusTracker& CurrentStatusTracker()
   {
@@ -417,7 +420,7 @@ private:
      * Decode aImg for a short amount of time, and post the remainder to the
      * queue.
      */
-    void DecodeABitOf(RasterImage* aImg);
+    void DecodeABitOf(RasterImage* aImg, DecodeStrategy aStrategy);
 
     /**
      * Ask the DecodePool to stop decoding this image.  Internally, we also
@@ -458,6 +461,7 @@ private:
      * UNTIL_DONE_BYTES, decode until all bytesToDecode bytes are decoded.
      */
     nsresult DecodeSomeOfImage(RasterImage* aImg,
+                               DecodeStrategy aStrategy,
                                DecodeType aDecodeType = DECODE_TYPE_UNTIL_TIME,
                                uint32_t bytesToDecode = 0);
 
@@ -751,8 +755,8 @@ private: // data
   nsresult WantDecodedFrames();
   nsresult SyncDecode();
   nsresult InitDecoder(bool aDoSizeDecode);
-  nsresult WriteToDecoder(const char *aBuffer, uint32_t aCount);
-  nsresult DecodeSomeData(uint32_t aMaxBytes);
+  nsresult WriteToDecoder(const char *aBuffer, uint32_t aCount, DecodeStrategy aStrategy);
+  nsresult DecodeSomeData(uint32_t aMaxBytes, DecodeStrategy aStrategy);
   bool     IsDecodeFinished();
   TimeStamp mDrawStartTime;
 





More information about the tor-commits mailing list