[tbb-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 tbb-commits
mailing list