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;
tor-commits@lists.torproject.org