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

commit dcbe26ea5f1021f44632b086df0b9e8c07142b12 Author: Seth Fowler <seth@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;
participants (1)
-
mikeperry@torproject.org