Bug 1079653 (Part 4) - Move decode status tracking onto RasterImage and remove DecodeRequest. r=tn

This commit is contained in:
Seth Fowler 2014-11-18 12:06:27 -08:00
parent 550967dd4b
commit ae5c2d16a1
2 changed files with 53 additions and 107 deletions

View File

@ -320,6 +320,7 @@ RasterImage::RasterImage(ProgressTracker* aProgressTracker,
#endif
mDecodingMonitor("RasterImage Decoding Monitor"),
mDecoder(nullptr),
mDecodeStatus(DecodeStatus::INACTIVE),
mNotifyProgress(NoProgress),
mNotifying(false),
mHasSize(false),
@ -1665,7 +1666,6 @@ RasterImage::OnImageDataComplete(nsIRequest*, nsISupports*, nsresult aStatus, bo
{
ReentrantMonitorAutoEnter lock(mDecodingMonitor);
FinishedSomeDecoding(eShutdownIntent_Done,
nullptr,
LoadCompleteProgress(aLastPart, mError, finalStatus));
}
@ -1732,7 +1732,7 @@ RasterImage::OnNewSourceData()
mHasSourceData = false;
mHasSize = false;
mWantFullDecode = true;
mDecodeRequest = nullptr;
mDecodeStatus = DecodeStatus::INACTIVE;
if (mAnim) {
mAnim->SetDoneDecoding(false);
@ -1833,7 +1833,7 @@ RasterImage::Discard(bool force)
if (mProgressTracker)
mProgressTracker->OnDiscard();
mDecodeRequest = nullptr;
mDecodeStatus = DecodeStatus::INACTIVE;
if (force)
DiscardTracker::Remove(&mDiscardTrackerNode);
@ -1953,9 +1953,6 @@ RasterImage::InitDecoder(bool aDoSizeDecode)
}
// Initialize the decoder
if (!mDecodeRequest) {
mDecodeRequest = new DecodeRequest(this);
}
mDecoder->SetSizeDecode(aDoSizeDecode);
mDecoder->SetDecodeFlags(mFrameDecodeFlags);
if (!aDoSizeDecode) {
@ -2168,8 +2165,7 @@ RasterImage::RequestDecodeCore(RequestDecodeType aDecodeType)
}
// If the image is waiting for decode work to be notified, go ahead and do that.
if (mDecodeRequest &&
mDecodeRequest->mRequestStatus == DecodeRequest::REQUEST_WORK_DONE &&
if (mDecodeStatus == DecodeStatus::WORK_DONE &&
aDecodeType == SYNCHRONOUS_NOTIFY) {
ReentrantMonitorAutoEnter lock(mDecodingMonitor);
nsresult rv = FinishedSomeDecoding();
@ -2205,9 +2201,7 @@ 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 (mDecodeRequest &&
mDecodeRequest->mRequestStatus == DecodeRequest::REQUEST_WORK_DONE &&
aDecodeType != ASYNCHRONOUS) {
if (mDecodeStatus == DecodeStatus::WORK_DONE && aDecodeType != ASYNCHRONOUS) {
nsresult rv = FinishedSomeDecoding();
CONTAINER_ENSURE_SUCCESS(rv);
}
@ -2292,12 +2286,10 @@ RasterImage::SyncDecode()
ReentrantMonitorAutoEnter lock(mDecodingMonitor);
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);
}
// 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);
}
nsresult rv;
@ -2894,20 +2886,12 @@ RasterImage::RequestDecodeIfNeeded(nsresult aStatus,
nsresult
RasterImage::FinishedSomeDecoding(eShutdownIntent aIntent /* = eShutdownIntent_Done */,
DecodeRequest* aRequest /* = nullptr */,
Progress aProgress /* = NoProgress */)
{
MOZ_ASSERT(NS_IsMainThread());
mDecodingMonitor.AssertCurrentThreadIn();
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.
nsRefPtr<RasterImage> image(this);
@ -2942,7 +2926,7 @@ RasterImage::FinishedSomeDecoding(eShutdownIntent aIntent /* = eShutdownIntent_D
wasSize = decoder->IsSizeDecode();
// Do some telemetry if this isn't a size decode.
if (request && !wasSize) {
if (!wasSize) {
Telemetry::Accumulate(Telemetry::IMAGE_DECODE_TIME,
int32_t(decoder->DecodeTime().ToMicroseconds()));
@ -3140,15 +3124,15 @@ 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->mDecodeRequest->mRequestStatus == DecodeRequest::REQUEST_PENDING ||
aImg->mDecodeRequest->mRequestStatus == DecodeRequest::REQUEST_ACTIVE) {
if (aImg->mDecodeStatus == DecodeStatus::PENDING ||
aImg->mDecodeStatus == DecodeStatus::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->mDecodeRequest->mRequestStatus = DecodeRequest::REQUEST_PENDING;
nsRefPtr<DecodeJob> job = new DecodeJob(aImg->mDecodeRequest, aImg);
aImg->mDecodeStatus = DecodeStatus::PENDING;
nsRefPtr<DecodeJob> job = new DecodeJob(aImg);
MutexAutoLock threadPoolLock(mThreadPoolMutex);
if (!gfxPrefs::ImageMTDecodingEnabled() || !mThreadPool) {
@ -3165,11 +3149,9 @@ RasterImage::DecodePool::DecodeABitOf(RasterImage* aImg, DecodeStrategy aStrateg
MOZ_ASSERT(NS_IsMainThread());
aImg->mDecodingMonitor.AssertCurrentThreadIn();
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();
}
// If the image is waiting for decode work to be notified, go ahead and do that.
if (aImg->mDecodeStatus == DecodeStatus::WORK_DONE) {
aImg->FinishedSomeDecoding();
}
DecodeSomeOfImage(aImg, aStrategy);
@ -3199,9 +3181,7 @@ 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.)
if (aImg->mDecodeRequest) {
aImg->mDecodeRequest->mRequestStatus = DecodeRequest::REQUEST_STOPPED;
}
aImg->mDecodeStatus = DecodeStatus::STOPPED;
}
NS_IMETHODIMP
@ -3210,14 +3190,14 @@ RasterImage::DecodePool::DecodeJob::Run()
ReentrantMonitorAutoEnter lock(mImage->mDecodingMonitor);
// If we were interrupted, we shouldn't do any work.
if (mRequest->mRequestStatus == DecodeRequest::REQUEST_STOPPED) {
DecodeDoneWorker::NotifyFinishedSomeDecoding(mImage, mRequest);
if (mImage->mDecodeStatus == DecodeStatus::STOPPED) {
DecodeDoneWorker::NotifyFinishedSomeDecoding(mImage);
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, mRequest);
DecodeDoneWorker::NotifyFinishedSomeDecoding(mImage);
return NS_OK;
}
@ -3228,7 +3208,7 @@ RasterImage::DecodePool::DecodeJob::Run()
return NS_OK;
}
mRequest->mRequestStatus = DecodeRequest::REQUEST_ACTIVE;
mImage->mDecodeStatus = DecodeStatus::ACTIVE;
size_t oldByteCount = mImage->mDecoder->BytesDecoded();
@ -3247,7 +3227,7 @@ RasterImage::DecodePool::DecodeJob::Run()
size_t bytesDecoded = mImage->mDecoder->BytesDecoded() - oldByteCount;
mRequest->mRequestStatus = DecodeRequest::REQUEST_WORK_DONE;
mImage->mDecodeStatus = DecodeStatus::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.
@ -3265,7 +3245,7 @@ RasterImage::DecodePool::DecodeJob::Run()
DecodePool::Singleton()->RequestDecode(mImage);
} else {
// Nothing more for us to do - let everyone know what happened.
DecodeDoneWorker::NotifyFinishedSomeDecoding(mImage, mRequest);
DecodeDoneWorker::NotifyFinishedSomeDecoding(mImage);
}
return NS_OK;
@ -3293,14 +3273,12 @@ RasterImage::DecodePool::DecodeUntilSizeAvailable(RasterImage* aImg)
MOZ_ASSERT(NS_IsMainThread());
ReentrantMonitorAutoEnter lock(aImg->mDecodingMonitor);
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;
}
// 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;
}
}
@ -3411,17 +3389,16 @@ RasterImage::DecodePool::DecodeSomeOfImage(RasterImage* aImg,
return NS_OK;
}
RasterImage::DecodeDoneWorker::DecodeDoneWorker(RasterImage* image, DecodeRequest* request)
: mImage(image)
, mRequest(request)
{}
RasterImage::DecodeDoneWorker::DecodeDoneWorker(RasterImage* aImage)
: mImage(aImage)
{ }
void
RasterImage::DecodeDoneWorker::NotifyFinishedSomeDecoding(RasterImage* image, DecodeRequest* request)
RasterImage::DecodeDoneWorker::NotifyFinishedSomeDecoding(RasterImage* aImage)
{
image->mDecodingMonitor.AssertCurrentThreadIn();
aImage->mDecodingMonitor.AssertCurrentThreadIn();
nsCOMPtr<nsIRunnable> worker = new DecodeDoneWorker(image, request);
nsCOMPtr<nsIRunnable> worker = new DecodeDoneWorker(aImage);
NS_DispatchToMainThread(worker);
}
@ -3431,7 +3408,7 @@ RasterImage::DecodeDoneWorker::Run()
MOZ_ASSERT(NS_IsMainThread());
ReentrantMonitorAutoEnter lock(mImage->mDecodingMonitor);
mImage->FinishedSomeDecoding(eShutdownIntent_Done, mRequest);
mImage->FinishedSomeDecoding(eShutdownIntent_Done);
return NS_OK;
}

View File

@ -33,6 +33,7 @@
#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"
@ -136,6 +137,14 @@ 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>
@ -306,39 +315,7 @@ public:
eShutdownIntent_AllCount = 3
};
// Decode strategy
private:
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)
, mRequestStatus(REQUEST_INACTIVE)
{ }
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(DecodeRequest)
RasterImage* mImage;
enum DecodeRequestStatus
{
REQUEST_INACTIVE,
REQUEST_PENDING,
REQUEST_ACTIVE,
REQUEST_WORK_DONE,
REQUEST_STOPPED
} mRequestStatus;
private:
~DecodeRequest() {}
};
/*
* DecodePool is a singleton class we use when decoding large images.
*
@ -426,18 +403,14 @@ private:
class DecodeJob : public nsRunnable
{
public:
DecodeJob(DecodeRequest* aRequest, RasterImage* aImg)
: mRequest(aRequest)
, mImage(aImg)
{}
DecodeJob(RasterImage* aImage) : mImage(aImage) { }
NS_IMETHOD Run();
NS_IMETHOD Run() MOZ_OVERRIDE;
protected:
virtual ~DecodeJob();
private:
nsRefPtr<DecodeRequest> mRequest;
nsRefPtr<RasterImage> mImage;
};
@ -460,17 +433,14 @@ private:
* Ensures the decode state accumulated by the decoding process gets
* applied to the image.
*/
static void NotifyFinishedSomeDecoding(RasterImage* image, DecodeRequest* request);
static void NotifyFinishedSomeDecoding(RasterImage* aImage);
NS_IMETHOD Run();
private: /* methods */
DecodeDoneWorker(RasterImage* image, DecodeRequest* request);
private: /* members */
private:
DecodeDoneWorker(RasterImage* aImage);
nsRefPtr<RasterImage> mImage;
nsRefPtr<DecodeRequest> mRequest;
};
class FrameNeededWorker : public nsRunnable
@ -481,7 +451,7 @@ private:
* decoder that it needs a new frame to be allocated on the main thread.
*
* Dispatches an event to do so, which will further dispatch a
* DecodeRequest event to continue decoding.
* RequestDecode event to continue decoding.
*/
static void GetNewFrame(RasterImage* image);
@ -496,7 +466,6 @@ private:
};
nsresult FinishedSomeDecoding(eShutdownIntent intent = eShutdownIntent_Done,
DecodeRequest* request = nullptr,
Progress aProgress = NoProgress);
void DrawWithPreDownscaleIfNeeded(DrawableFrameRef&& aFrameRef,
@ -621,7 +590,7 @@ private: // data
// Decoder and friends
nsRefPtr<Decoder> mDecoder;
nsRefPtr<DecodeRequest> mDecodeRequest;
DecodeStatus mDecodeStatus;
// END LOCKED MEMBER VARIABLES
// Notification state. Used to avoid recursive notifications.