Backed out 5 changesets (bug 1079653) for mochitest-dt asserts on a CLOSED TREE.

Backed out changeset aaac8c671299 (bug 1079653)
Backed out changeset 59d1754eb01f (bug 1079653)
Backed out changeset dfb0890b02be (bug 1079653)
Backed out changeset 546f90c14465 (bug 1079653)
Backed out changeset a8e760faf784 (bug 1079653)
This commit is contained in:
Ryan VanderMeulen 2014-10-15 19:00:12 -04:00
parent c4efcdc11c
commit 94b7009ab9
4 changed files with 167 additions and 137 deletions

View File

@ -19,7 +19,6 @@ Decoder::Decoder(RasterImage &aImage)
, mCurrentFrame(nullptr)
, mImageData(nullptr)
, mColormap(nullptr)
, mChunkCount(0)
, mDecodeFlags(0)
, mBytesDecoded(0)
, mDecodeDone(false)
@ -27,7 +26,6 @@ Decoder::Decoder(RasterImage &aImage)
, mFrameCount(0)
, mFailCode(NS_OK)
, mNeedsNewFrame(false)
, mNeedsToFlushData(false)
, mInitialized(false)
, mSizeDecode(false)
, mInFrame(false)
@ -99,20 +97,10 @@ Decoder::Write(const char* aBuffer, uint32_t aCount, DecodeStrategy aStrategy)
MOZ_ASSERT(!HasDecoderError(),
"Not allowed to make more decoder calls after error!");
// Begin recording telemetry data.
TimeStamp start = TimeStamp::Now();
mChunkCount++;
// Keep track of the total number of bytes written.
mBytesDecoded += aCount;
// If we're flushing data, clear the flag.
if (aBuffer == nullptr && aCount == 0) {
MOZ_ASSERT(mNeedsToFlushData, "Flushing when we don't need to");
mNeedsToFlushData = false;
}
// If a data error occured, just ignore future data.
// If a data error occured, just ignore future data
if (HasDataError())
return;
@ -134,9 +122,6 @@ Decoder::Write(const char* aBuffer, uint32_t aCount, DecodeStrategy aStrategy)
WriteInternal(nullptr, 0, aStrategy);
}
}
// Finish telemetry.
mDecodeTime += (TimeStamp::Now() - start);
}
void
@ -257,12 +242,6 @@ Decoder::AllocateFrame()
// so they can tell us if they need yet another.
mNeedsNewFrame = false;
// If we've received any data at all, we may have pending data that needs to
// be flushed now that we have a frame to decode into.
if (mBytesDecoded > 0) {
mNeedsToFlushData = true;
}
return rv;
}

View File

@ -44,11 +44,6 @@ public:
/**
* Writes data to the decoder.
*
* If aBuffer is null and aCount is 0, Write() flushes any buffered data to
* the decoder. Data is buffered if the decoder wasn't able to completely
* decode it because it needed a new frame. If it's necessary to flush data,
* NeedsToFlushData() will return true.
*
* @param aBuffer buffer containing the data to be written
* @param aCount the number of bytes to write
*
@ -108,12 +103,6 @@ public:
size_t BytesDecoded() const { return mBytesDecoded; }
// The amount of time we've spent inside Write() so far for this decoder.
TimeDuration DecodeTime() const { return mDecodeTime; }
// The number of times Write() has been called so far for this decoder.
uint32_t ChunkCount() const { return mChunkCount; }
// The number of frames we have, including anything in-progress. Thus, this
// is only 0 if we haven't begun any frames.
uint32_t GetFrameCount() { return mFrameCount; }
@ -169,11 +158,6 @@ public:
virtual bool NeedsNewFrame() const { return mNeedsNewFrame; }
// Returns true if we may have stored data that we need to flush now that we
// have a new frame to decode into. Callers can use Write() to actually
// flush the data; see the documentation for that method.
bool NeedsToFlushData() const { return mNeedsToFlushData; }
// Try to allocate a frame as described in mNewFrameData and return the
// status code from that attempt. Clears mNewFrameData.
virtual nsresult AllocateFrame();
@ -251,10 +235,6 @@ protected:
uint32_t* mColormap; // Current colormap to be used in Cairo format
uint32_t mColormapSize;
// Telemetry data for this decoder.
TimeDuration mDecodeTime;
uint32_t mChunkCount;
uint32_t mDecodeFlags;
size_t mBytesDecoded;
bool mDecodeDone;
@ -293,7 +273,6 @@ private:
};
NewFrameData mNewFrameData;
bool mNeedsNewFrame;
bool mNeedsToFlushData;
bool mInitialized;
bool mSizeDecode;
bool mInFrame;

View File

@ -321,7 +321,6 @@ RasterImage::RasterImage(imgStatusTracker* aStatusTracker,
#endif
mDecodingMonitor("RasterImage Decoding Monitor"),
mDecoder(nullptr),
mDecodeStatus(DecodeStatus::INACTIVE),
mInDecoder(false),
mStatusDiff(ImageStatusDiff::NoChange()),
mNotifying(false),
@ -1767,8 +1766,7 @@ RasterImage::OnNewSourceData()
mHasSourceData = false;
mHasSize = false;
mWantFullDecode = true;
mDecodeStatus = DecodeStatus::INACTIVE;
mDecodeStatusTracker = nullptr;
mDecodeRequest = nullptr;
if (mAnim) {
mAnim->SetDoneDecoding(false);
@ -1869,8 +1867,7 @@ RasterImage::Discard(bool force)
if (mStatusTracker)
mStatusTracker->OnDiscard();
mDecodeStatus = DecodeStatus::INACTIVE;
mDecodeStatusTracker = nullptr;
mDecodeRequest = nullptr;
if (force)
DiscardTracker::Remove(&mDiscardTrackerNode);
@ -1990,12 +1987,12 @@ RasterImage::InitDecoder(bool aDoSizeDecode)
}
// Initialize the decoder
if (!mDecodeStatusTracker) {
MOZ_ASSERT(mStatusTracker, "Should have an imgStatusTracker");
mDecodeStatusTracker = mStatusTracker->CloneForRecording();
if (!mDecodeRequest) {
mDecodeRequest = new DecodeRequest(this);
}
MOZ_ASSERT(mDecodeStatusTracker->GetDecoderObserver());
mDecoder->SetObserver(mDecodeStatusTracker->GetDecoderObserver());
MOZ_ASSERT(mDecodeRequest->mStatusTracker);
MOZ_ASSERT(mDecodeRequest->mStatusTracker->GetDecoderObserver());
mDecoder->SetObserver(mDecodeRequest->mStatusTracker->GetDecoderObserver());
mDecoder->SetSizeDecode(aDoSizeDecode);
mDecoder->SetDecodeFlags(mFrameDecodeFlags);
if (!aDoSizeDecode) {
@ -2231,7 +2228,8 @@ RasterImage::RequestDecodeCore(RequestDecodeType aDecodeType)
}
// If the image is waiting for decode work to be notified, go ahead and do that.
if (mDecodeStatus == DecodeStatus::WORK_DONE &&
if (mDecodeRequest &&
mDecodeRequest->mRequestStatus == DecodeRequest::REQUEST_WORK_DONE &&
aDecodeType == SYNCHRONOUS_NOTIFY) {
ReentrantMonitorAutoEnter lock(mDecodingMonitor);
nsresult rv = FinishedSomeDecoding();
@ -2267,7 +2265,9 @@ RasterImage::RequestDecodeCore(RequestDecodeType aDecodeType)
// we need to repeat the following three checks after getting the lock.
// If the image is waiting for decode work to be notified, go ahead and do that.
if (mDecodeStatus == DecodeStatus::WORK_DONE && aDecodeType != ASYNCHRONOUS) {
if (mDecodeRequest &&
mDecodeRequest->mRequestStatus == DecodeRequest::REQUEST_WORK_DONE &&
aDecodeType != ASYNCHRONOUS) {
nsresult rv = FinishedSomeDecoding();
CONTAINER_ENSURE_SUCCESS(rv);
}
@ -2358,10 +2358,12 @@ RasterImage::SyncDecode()
// disallow this type of call in the API, and check for it in API methods.
NS_ABORT_IF_FALSE(!mInDecoder, "Yikes, forcing sync in reentrant call!");
// If the image is waiting for decode work to be notified, go ahead and do that.
if (mDecodeStatus == DecodeStatus::WORK_DONE) {
nsresult rv = FinishedSomeDecoding();
CONTAINER_ENSURE_SUCCESS(rv);
if (mDecodeRequest) {
// If the image is waiting for decode work to be notified, go ahead and do that.
if (mDecodeRequest->mRequestStatus == DecodeRequest::REQUEST_WORK_DONE) {
nsresult rv = FinishedSomeDecoding();
CONTAINER_ENSURE_SUCCESS(rv);
}
}
nsresult rv;
@ -2394,9 +2396,11 @@ RasterImage::SyncDecode()
}
}
// If we're currently waiting on a new frame for this image, create it now.
// If we're currently waiting on a new frame for this image, we have to create
// it now.
if (mDecoder && mDecoder->NeedsNewFrame()) {
mDecoder->AllocateFrame();
mDecodeRequest->mAllocatedNewFrame = true;
}
// If we don't have a decoder, create one
@ -2776,7 +2780,8 @@ RasterImage::DecodeSomeData(size_t aMaxBytes, DecodeStrategy aStrategy)
// First, if we've just been called because we allocated a frame on the main
// thread, let the decoder deal with the data it set aside at that time by
// passing it a null buffer.
if (mDecoder->NeedsToFlushData()) {
if (mDecodeRequest->mAllocatedNewFrame) {
mDecodeRequest->mAllocatedNewFrame = false;
nsresult rv = WriteToDecoder(nullptr, 0, aStrategy);
if (NS_FAILED(rv) || mDecoder->NeedsNewFrame()) {
return rv;
@ -2822,7 +2827,8 @@ RasterImage::IsDecodeFinished()
// If the decoder returned because it needed a new frame and we haven't
// written to it since then, the decoder may be storing data that it hasn't
// decoded yet.
if (mDecoder->NeedsNewFrame() || mDecoder->NeedsToFlushData()) {
if (mDecoder->NeedsNewFrame() ||
(mDecodeRequest && mDecodeRequest->mAllocatedNewFrame)) {
return false;
}
@ -2976,15 +2982,18 @@ RasterImage::RequestDecodeIfNeeded(nsresult aStatus,
nsresult
RasterImage::FinishedSomeDecoding(eShutdownIntent aIntent /* = eShutdownIntent_Done */,
imgStatusTracker* aDecodeTracker /* = nullptr */)
DecodeRequest* aRequest /* = nullptr */)
{
MOZ_ASSERT(NS_IsMainThread());
mDecodingMonitor.AssertCurrentThreadIn();
nsRefPtr<imgStatusTracker> statusTracker = aDecodeTracker
? aDecodeTracker
: mDecodeStatusTracker.get();
nsRefPtr<DecodeRequest> request;
if (aRequest) {
request = aRequest;
} else {
request = mDecodeRequest;
}
// Ensure that, if the decoder is the last reference to the image, we don't
// destroy it by destroying the decoder.
@ -2995,9 +3004,8 @@ RasterImage::FinishedSomeDecoding(eShutdownIntent aIntent /* = eShutdownIntent_D
nsresult rv = NS_OK;
if (image->mDecoder) {
if (!image->mDecoder->IsSizeDecode() && image->mDecoder->ChunkCount()) {
Telemetry::Accumulate(Telemetry::IMAGE_DECODE_CHUNKS,
image->mDecoder->ChunkCount());
if (request && request->mChunkCount && !image->mDecoder->IsSizeDecode()) {
Telemetry::Accumulate(Telemetry::IMAGE_DECODE_CHUNKS, request->mChunkCount);
}
if (!image->mHasSize && image->mDecoder->HasSize()) {
@ -3015,16 +3023,16 @@ RasterImage::FinishedSomeDecoding(eShutdownIntent aIntent /* = eShutdownIntent_D
wasSize = decoder->IsSizeDecode();
// Do some telemetry if this isn't a size decode.
if (!wasSize) {
if (request && !wasSize) {
Telemetry::Accumulate(Telemetry::IMAGE_DECODE_TIME,
int32_t(decoder->DecodeTime().ToMicroseconds()));
int32_t(request->mDecodeTime.ToMicroseconds()));
// We record the speed for only some decoders. The rest have
// SpeedHistogram return HistogramCount.
Telemetry::ID id = decoder->SpeedHistogram();
if (id < Telemetry::HistogramCount) {
int32_t KBps = int32_t(decoder->BytesDecoded() /
(1024 * decoder->DecodeTime().ToSeconds()));
(1024 * request->mDecodeTime.ToSeconds()));
Telemetry::Accumulate(id, KBps);
}
}
@ -3038,9 +3046,9 @@ RasterImage::FinishedSomeDecoding(eShutdownIntent aIntent /* = eShutdownIntent_D
}
}
ImageStatusDiff diff = statusTracker
? image->mStatusTracker->Difference(statusTracker)
: image->mStatusTracker->DecodeStateAsDifference();
ImageStatusDiff diff =
request ? image->mStatusTracker->Difference(request->mStatusTracker)
: image->mStatusTracker->DecodeStateAsDifference();
image->mStatusTracker->ApplyDifference(diff);
if (mNotifying) {
@ -3197,15 +3205,20 @@ RasterImage::DecodePool::RequestDecode(RasterImage* aImg)
// If we're currently waiting on a new frame for this image, we can't do any
// decoding.
if (!aImg->mDecoder->NeedsNewFrame()) {
if (aImg->mDecodeStatus == DecodeStatus::PENDING ||
aImg->mDecodeStatus == DecodeStatus::ACTIVE) {
// No matter whether this is currently being decoded, we need to update the
// number of bytes we want it to decode.
aImg->mDecodeRequest->mBytesToDecode =
aImg->mSourceData.Length() - aImg->mDecoder->BytesDecoded();
if (aImg->mDecodeRequest->mRequestStatus == DecodeRequest::REQUEST_PENDING ||
aImg->mDecodeRequest->mRequestStatus == DecodeRequest::REQUEST_ACTIVE) {
// The image is already in our list of images to decode, or currently being
// decoded, so we don't have to do anything else.
return;
}
aImg->mDecodeStatus = DecodeStatus::PENDING;
nsRefPtr<DecodeJob> job = new DecodeJob(aImg);
aImg->mDecodeRequest->mRequestStatus = DecodeRequest::REQUEST_PENDING;
nsRefPtr<DecodeJob> job = new DecodeJob(aImg->mDecodeRequest, aImg);
MutexAutoLock threadPoolLock(mThreadPoolMutex);
if (!gfxPrefs::ImageMTDecodingEnabled() || !mThreadPool) {
@ -3222,9 +3235,11 @@ RasterImage::DecodePool::DecodeABitOf(RasterImage* aImg, DecodeStrategy aStrateg
MOZ_ASSERT(NS_IsMainThread());
aImg->mDecodingMonitor.AssertCurrentThreadIn();
// If the image is waiting for decode work to be notified, go ahead and do that.
if (aImg->mDecodeStatus == DecodeStatus::WORK_DONE) {
aImg->FinishedSomeDecoding();
if (aImg->mDecodeRequest) {
// If the image is waiting for decode work to be notified, go ahead and do that.
if (aImg->mDecodeRequest->mRequestStatus == DecodeRequest::REQUEST_WORK_DONE) {
aImg->FinishedSomeDecoding();
}
}
DecodeSomeOfImage(aImg, aStrategy);
@ -3254,7 +3269,9 @@ RasterImage::DecodePool::StopDecoding(RasterImage* aImg)
// If we haven't got a decode request, we're not currently decoding. (Having
// a decode request doesn't imply we *are* decoding, though.)
aImg->mDecodeStatus = DecodeStatus::STOPPED;
if (aImg->mDecodeRequest) {
aImg->mDecodeRequest->mRequestStatus = DecodeRequest::REQUEST_STOPPED;
}
}
NS_IMETHODIMP
@ -3263,16 +3280,14 @@ RasterImage::DecodePool::DecodeJob::Run()
ReentrantMonitorAutoEnter lock(mImage->mDecodingMonitor);
// If we were interrupted, we shouldn't do any work.
if (mImage->mDecodeStatus == DecodeStatus::STOPPED) {
DecodeDoneWorker::NotifyFinishedSomeDecoding(mImage,
mImage->mDecodeStatusTracker);
if (mRequest->mRequestStatus == DecodeRequest::REQUEST_STOPPED) {
DecodeDoneWorker::NotifyFinishedSomeDecoding(mImage, mRequest);
return NS_OK;
}
// If someone came along and synchronously decoded us, there's nothing for us to do.
if (!mImage->mDecoder || mImage->IsDecodeFinished()) {
DecodeDoneWorker::NotifyFinishedSomeDecoding(mImage,
mImage->mDecodeStatusTracker);
DecodeDoneWorker::NotifyFinishedSomeDecoding(mImage, mRequest);
return NS_OK;
}
@ -3283,7 +3298,7 @@ RasterImage::DecodePool::DecodeJob::Run()
return NS_OK;
}
mImage->mDecodeStatus = DecodeStatus::ACTIVE;
mRequest->mRequestStatus = DecodeRequest::REQUEST_ACTIVE;
size_t oldByteCount = mImage->mDecoder->BytesDecoded();
@ -3295,14 +3310,11 @@ RasterImage::DecodePool::DecodeJob::Run()
type = DECODE_TYPE_UNTIL_TIME;
}
size_t maxBytes = mImage->mSourceData.Length() -
mImage->mDecoder->BytesDecoded();
DecodePool::Singleton()->DecodeSomeOfImage(mImage, DECODE_ASYNC,
type, maxBytes);
DecodePool::Singleton()->DecodeSomeOfImage(mImage, DECODE_ASYNC, type, mRequest->mBytesToDecode);
size_t bytesDecoded = mImage->mDecoder->BytesDecoded() - oldByteCount;
mImage->mDecodeStatus = DecodeStatus::WORK_DONE;
mRequest->mRequestStatus = DecodeRequest::REQUEST_WORK_DONE;
// If the decoder needs a new frame, enqueue an event to get it; that event
// will enqueue another decode request when it's done.
@ -3315,13 +3327,12 @@ RasterImage::DecodePool::DecodeJob::Run()
!mImage->mError &&
!mImage->mPendingError &&
!mImage->IsDecodeFinished() &&
bytesDecoded < maxBytes &&
bytesDecoded < mRequest->mBytesToDecode &&
bytesDecoded > 0) {
DecodePool::Singleton()->RequestDecode(mImage);
} else {
// Nothing more for us to do - let everyone know what happened.
DecodeDoneWorker::NotifyFinishedSomeDecoding(mImage,
mImage->mDecodeStatusTracker);
DecodeDoneWorker::NotifyFinishedSomeDecoding(mImage, mRequest);
}
return NS_OK;
@ -3349,12 +3360,14 @@ RasterImage::DecodePool::DecodeUntilSizeAvailable(RasterImage* aImg)
MOZ_ASSERT(NS_IsMainThread());
ReentrantMonitorAutoEnter lock(aImg->mDecodingMonitor);
// If the image is waiting for decode work to be notified, go ahead and do that.
if (aImg->mDecodeStatus == DecodeStatus::WORK_DONE) {
nsresult rv = aImg->FinishedSomeDecoding();
if (NS_FAILED(rv)) {
aImg->DoError();
return rv;
if (aImg->mDecodeRequest) {
// If the image is waiting for decode work to be notified, go ahead and do that.
if (aImg->mDecodeRequest->mRequestStatus == DecodeRequest::REQUEST_WORK_DONE) {
nsresult rv = aImg->FinishedSomeDecoding();
if (NS_FAILED(rv)) {
aImg->DoError();
return rv;
}
}
}
@ -3405,7 +3418,9 @@ RasterImage::DecodePool::DecodeSomeOfImage(RasterImage* aImg,
// this image, get it now.
if (aStrategy == DECODE_SYNC && aImg->mDecoder->NeedsNewFrame()) {
MOZ_ASSERT(NS_IsMainThread());
aImg->mDecoder->AllocateFrame();
aImg->mDecodeRequest->mAllocatedNewFrame = true;
}
// If we're not synchronous, we can't allocate a frame right now.
@ -3431,8 +3446,9 @@ RasterImage::DecodePool::DecodeSomeOfImage(RasterImage* aImg,
bytesToDecode = aImg->mSourceData.Length() - aImg->mDecoder->BytesDecoded();
}
TimeStamp deadline = TimeStamp::Now() +
TimeDuration::FromMilliseconds(gfxPrefs::ImageMemMaxMSBeforeYield());
int32_t chunkCount = 0;
TimeStamp start = TimeStamp::Now();
TimeStamp deadline = start + TimeDuration::FromMilliseconds(gfxPrefs::ImageMemMaxMSBeforeYield());
// We keep decoding chunks until:
// * we don't have any data left to decode,
@ -3446,7 +3462,8 @@ RasterImage::DecodePool::DecodeSomeOfImage(RasterImage* aImg,
!aImg->IsDecodeFinished() &&
!(aDecodeType == DECODE_TYPE_UNTIL_SIZE && aImg->mHasSize) &&
!aImg->mDecoder->NeedsNewFrame()) ||
aImg->mDecoder->NeedsToFlushData()) {
(aImg->mDecodeRequest && aImg->mDecodeRequest->mAllocatedNewFrame)) {
chunkCount++;
uint32_t chunkSize = std::min(bytesToDecode, maxBytes);
nsresult rv = aImg->DecodeSomeData(chunkSize, aStrategy);
if (NS_FAILED(rv)) {
@ -3462,6 +3479,11 @@ RasterImage::DecodePool::DecodeSomeOfImage(RasterImage* aImg,
break;
}
if (aImg->mDecodeRequest) {
aImg->mDecodeRequest->mDecodeTime += (TimeStamp::Now() - start);
aImg->mDecodeRequest->mChunkCount += chunkCount;
}
// Flush invalidations (and therefore paint) now that we've decoded all the
// chunks we're going to.
//
@ -3490,13 +3512,17 @@ RasterImage::DecodePool::DecodeSomeOfImage(RasterImage* aImg,
return NS_OK;
}
void
RasterImage::DecodeDoneWorker::NotifyFinishedSomeDecoding(RasterImage* aImage,
imgStatusTracker* aTracker)
{
aImage->mDecodingMonitor.AssertCurrentThreadIn();
RasterImage::DecodeDoneWorker::DecodeDoneWorker(RasterImage* image, DecodeRequest* request)
: mImage(image)
, mRequest(request)
{}
nsCOMPtr<nsIRunnable> worker = new DecodeDoneWorker(aImage, aTracker);
void
RasterImage::DecodeDoneWorker::NotifyFinishedSomeDecoding(RasterImage* image, DecodeRequest* request)
{
image->mDecodingMonitor.AssertCurrentThreadIn();
nsCOMPtr<nsIRunnable> worker = new DecodeDoneWorker(image, request);
NS_DispatchToMainThread(worker);
}
@ -3506,7 +3532,7 @@ RasterImage::DecodeDoneWorker::Run()
MOZ_ASSERT(NS_IsMainThread());
ReentrantMonitorAutoEnter lock(mImage->mDecodingMonitor);
mImage->FinishedSomeDecoding(eShutdownIntent_Done, mTracker);
mImage->FinishedSomeDecoding(eShutdownIntent_Done, mRequest);
return NS_OK;
}
@ -3533,6 +3559,7 @@ RasterImage::FrameNeededWorker::Run()
// anything.
if (mImage->mDecoder && mImage->mDecoder->NeedsNewFrame()) {
rv = mImage->mDecoder->AllocateFrame();
mImage->mDecodeRequest->mAllocatedNewFrame = true;
}
if (NS_SUCCEEDED(rv) && mImage->mDecoder) {

View File

@ -33,7 +33,6 @@
#include "mozilla/Mutex.h"
#include "mozilla/ReentrantMonitor.h"
#include "mozilla/TimeStamp.h"
#include "mozilla/TypedEnum.h"
#include "mozilla/StaticPtr.h"
#include "mozilla/WeakPtr.h"
#include "mozilla/UniquePtr.h"
@ -137,14 +136,6 @@ class Decoder;
class FrameAnimator;
class ScaleRunner;
MOZ_BEGIN_ENUM_CLASS(DecodeStatus, uint8_t)
INACTIVE,
PENDING,
ACTIVE,
WORK_DONE,
STOPPED
MOZ_END_ENUM_CLASS(DecodeStatus)
class RasterImage MOZ_FINAL : public ImageResource
, public nsIProperties
, public SupportsWeakPtr<RasterImage>
@ -322,12 +313,67 @@ private:
{
mDecodingMonitor.AssertCurrentThreadIn();
nsRefPtr<imgStatusTracker> statusTracker;
statusTracker = mDecodeStatusTracker ? mDecodeStatusTracker
: mStatusTracker;
statusTracker = mDecodeRequest ? mDecodeRequest->mStatusTracker
: mStatusTracker;
MOZ_ASSERT(statusTracker);
return statusTracker.forget();
}
nsresult OnImageDataCompleteCore(nsIRequest* aRequest, nsISupports*, nsresult aStatus);
/**
* Each RasterImage has a pointer to one or zero heap-allocated
* DecodeRequests.
*/
struct DecodeRequest
{
explicit DecodeRequest(RasterImage* aImage)
: mImage(aImage)
, mBytesToDecode(0)
, mRequestStatus(REQUEST_INACTIVE)
, mChunkCount(0)
, mAllocatedNewFrame(false)
{
MOZ_ASSERT(aImage, "aImage cannot be null");
MOZ_ASSERT(aImage->mStatusTracker,
"aImage should have an imgStatusTracker");
mStatusTracker = aImage->mStatusTracker->CloneForRecording();
}
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(DecodeRequest)
// The status tracker that is associated with a given decode request, to
// ensure their lifetimes are linked.
nsRefPtr<imgStatusTracker> mStatusTracker;
RasterImage* mImage;
size_t mBytesToDecode;
enum DecodeRequestStatus
{
REQUEST_INACTIVE,
REQUEST_PENDING,
REQUEST_ACTIVE,
REQUEST_WORK_DONE,
REQUEST_STOPPED
} mRequestStatus;
/* Keeps track of how much time we've burned decoding this particular decode
* request. */
TimeDuration mDecodeTime;
/* The number of chunks it took to decode this image. */
int32_t mChunkCount;
/* True if a new frame has been allocated, but DecodeSomeData hasn't yet
* been called to flush data to it */
bool mAllocatedNewFrame;
private:
~DecodeRequest() {}
};
/*
* DecodePool is a singleton class we use when decoding large images.
*
@ -415,14 +461,18 @@ private:
class DecodeJob : public nsRunnable
{
public:
DecodeJob(RasterImage* aImage) : mImage(aImage) { }
DecodeJob(DecodeRequest* aRequest, RasterImage* aImg)
: mRequest(aRequest)
, mImage(aImg)
{}
NS_IMETHOD Run() MOZ_OVERRIDE;
NS_IMETHOD Run();
protected:
virtual ~DecodeJob();
private:
nsRefPtr<DecodeRequest> mRequest;
nsRefPtr<RasterImage> mImage;
};
@ -445,21 +495,17 @@ private:
* Ensures the decode state accumulated by the decoding process gets
* applied to the image.
*/
static void NotifyFinishedSomeDecoding(RasterImage* aImage,
imgStatusTracker* aTracker);
static void NotifyFinishedSomeDecoding(RasterImage* image, DecodeRequest* request);
NS_IMETHOD Run();
private: /* methods */
DecodeDoneWorker(RasterImage* aImage, imgStatusTracker* aTracker)
: mImage(aImage)
, mTracker(aTracker)
{ }
DecodeDoneWorker(RasterImage* image, DecodeRequest* request);
private: /* members */
nsRefPtr<RasterImage> mImage;
nsRefPtr<imgStatusTracker> mTracker;
nsRefPtr<DecodeRequest> mRequest;
};
class FrameNeededWorker : public nsRunnable
@ -484,8 +530,8 @@ private:
nsRefPtr<RasterImage> mImage;
};
nsresult FinishedSomeDecoding(eShutdownIntent aIntent = eShutdownIntent_Done,
imgStatusTracker* aDecodeTracker = nullptr);
nsresult FinishedSomeDecoding(eShutdownIntent intent = eShutdownIntent_Done,
DecodeRequest* request = nullptr);
void DrawWithPreDownscaleIfNeeded(DrawableFrameRef&& aFrameRef,
gfxContext* aContext,
@ -609,8 +655,7 @@ private: // data
// Decoder and friends
nsRefPtr<Decoder> mDecoder;
nsRefPtr<imgStatusTracker> mDecodeStatusTracker;
DecodeStatus mDecodeStatus;
nsRefPtr<DecodeRequest> mDecodeRequest;
bool mInDecoder;
// END LOCKED MEMBER VARIABLES