Bug 1404222 Part 6: Update RasterImage to allow us to delay the load event until full decode.
MozReview-Commit-ID: 6tpO13NzkmP
--- a/image/RasterImage.cpp
+++ b/image/RasterImage.cpp
@@ -127,16 +127,17 @@ RasterImage::Init(const char* aMimeType,
MOZ_ASSERT_IF(aFlags & INIT_FLAG_TRANSIENT,
!(aFlags & INIT_FLAG_DISCARDABLE));
// Store initialization data
mDiscardable = !!(aFlags & INIT_FLAG_DISCARDABLE);
mWantFullDecode = !!(aFlags & INIT_FLAG_DECODE_IMMEDIATELY);
mTransient = !!(aFlags & INIT_FLAG_TRANSIENT);
mSyncLoad = !!(aFlags & INIT_FLAG_SYNC_LOAD);
+ mDelayLoadEventUntilDecode = !!(aFlags & INIT_FLAG_LOADEVENT_AFTER_DECODE);
// Use the MIME type to select a decoder type, and make sure there *is* a
// decoder for this MIME type.
NS_ENSURE_ARG_POINTER(aMimeType);
mDecoderType = DecoderFactory::GetDecoderType(aMimeType);
if (mDecoderType == DecoderType::UNKNOWN) {
return NS_ERROR_FAILURE;
}
@@ -1770,27 +1771,58 @@ RasterImage::NotifyDecodeComplete(const
if (aStatus.mHadError &&
(!mAnimationState || mAnimationState->KnownFrameCount() == 0)) {
DoError();
} else if (aStatus.mWasMetadataDecode && !mHasSize) {
DoError();
}
// XXX(aosmond): Can we get this far without mFinished == true?
- if (aStatus.mFinished && aStatus.mWasMetadataDecode) {
- // If we were waiting to fire the load event, go ahead and fire it now.
- if (mLoadProgress) {
- NotifyForLoadEvent(*mLoadProgress);
- mLoadProgress = Nothing();
- }
+ if (aStatus.mFinished) {
+ if (aStatus.mWasMetadataDecode) {
+ // If we're waiting to send the load event, and we can do that
+ // with just the metadata or we aren't requesting the full
+ // decode ourself, send the load event now.
+ if (mLoadProgress &&
+ (!mDelayLoadEventUntilDecode || !mWantFullDecode)) {
+ NotifyForLoadEvent(*mLoadProgress);
+ mLoadProgress = Nothing();
+ }
- // If we were a metadata decode and a full decode was requested, do it.
- if (mWantFullDecode) {
- mWantFullDecode = false;
- RequestDecodeForSize(mSize, DECODE_FLAGS_DEFAULT);
+ // If we were a metadata decode and a full decode was requested,
+ // do it.
+ if (mWantFullDecode) {
+ mWantFullDecode = false;
+ RequestDecodeForSize(mSize, DECODE_FLAGS_DEFAULT);
+ }
+ } else {
+ // We've decoded fully; if we're still waiting to send the
+ // load event, do it now.
+ if (mLoadProgress) {
+ // If we intentionally delayed until full decode, delay
+ // dispatch of the event itself, since we want to ensure that
+ // whatever needed the decode has time to act on it (reflow,
+ // for example).
+ Progress progress = *mLoadProgress;
+ mLoadProgress = Nothing();
+
+ if (mDelayLoadEventUntilDecode) {
+ // Dispatch the event as a runnable.
+ RefPtr<RasterImage> image = this;
+ nsCOMPtr<nsIRunnable> ev = NS_NewRunnableFunction(
+ "RasterImage::NotifyDecodeComplete",
+ [=]() -> void {
+ image->NotifyForLoadEvent(progress);
+ });
+ NS_IdleDispatchToCurrentThread(ev.forget());
+ } else {
+ // Run the event directly.
+ NotifyForLoadEvent(progress);
+ }
+ }
}
}
}
void
RasterImage::ReportDecoderError()
{
nsCOMPtr<nsIConsoleService> consoleService =
--- a/image/RasterImage.h
+++ b/image/RasterImage.h
@@ -423,16 +423,20 @@ private: // data
// Whether the animation can stop, due to running out
// of frames, or no more owning request
bool mAnimationFinished:1;
// Whether, once we are done doing a metadata decode, we should immediately
// kick off a full decode.
bool mWantFullDecode:1;
+ // Whether we should delay our load event until full decode. If false,
+ // load event will fire as soon as size is known.
+ bool mDelayLoadEventUntilDecode:1;
+
TimeStamp mDrawStartTime;
//////////////////////////////////////////////////////////////////////////////
// Scaling.
//////////////////////////////////////////////////////////////////////////////
// Determines whether we can downscale during decode with the given