Bug 1084136 (Part 5) - Don't reset STATUS_DECODE_STARTED when decoding finishes. r=tn
authorSeth Fowler <seth@mozilla.com>
Thu, 06 Nov 2014 17:33:58 -0800
changeset 214443 00faf185fa5bd65d678e9c05e56f40d1cc966043
parent 214442 7816c3056b65ecc8ca6bc6c3a44d14f561d17bf2
child 214444 443d2ef1ba033afd84eeb220d126e2d9489b1457
push id51493
push usermfowler@mozilla.com
push dateFri, 07 Nov 2014 02:17:12 +0000
treeherdermozilla-inbound@f245578c4fa4 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerstn
bugs1084136
milestone36.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1084136 (Part 5) - Don't reset STATUS_DECODE_STARTED when decoding finishes. r=tn
dom/base/nsImageLoadingContent.cpp
image/src/imgStatusTracker.cpp
image/src/imgStatusTracker.h
layout/xul/nsImageBoxFrame.cpp
--- a/dom/base/nsImageLoadingContent.cpp
+++ b/dom/base/nsImageLoadingContent.cpp
@@ -248,17 +248,16 @@ nsImageLoadingContent::OnStopRequest(img
   // (*) IsPaintingSuppressed returns false if we haven't gotten the initial
   // reflow yet, so we have to test !DidInitialize || IsPaintingSuppressed.
   // It's possible for painting to be suppressed for reasons other than the
   // initial paint delay (for example, being in the bfcache), but we probably
   // aren't loading images in those situations.
 
   // XXXkhuey should this be GetOurCurrentDoc?  Decoding if we're not in
   // the document seems silly.
-  bool startedDecoding = false;
   nsIDocument* doc = GetOurOwnerDoc();
   nsIPresShell* shell = doc ? doc->GetShell() : nullptr;
   if (shell && shell->IsVisible() &&
       (!shell->DidInitialize() || shell->IsPaintingSuppressed())) {
 
     nsIFrame* f = GetOurPrimaryFrame();
     // If we haven't gotten a frame yet either we aren't going to (so don't
     // bother kicking off a decode), or we will get very soon on the next
@@ -269,32 +268,30 @@ nsImageLoadingContent::OnStopRequest(img
     // first reflow.
     if (f) {
       // If we've gotten a frame and that frame has called FrameCreate and that
       // frame has been reflowed then we know that it checked it's own visibility
       // so we can trust our visible count and we don't start decode if we are not
       // visible.
       if (!mFrameCreateCalled || (f->GetStateBits() & NS_FRAME_FIRST_REFLOW) ||
           mVisibleCount > 0 || shell->AssumeAllImagesVisible()) {
-        if (NS_SUCCEEDED(mCurrentRequest->StartDecoding())) {
-          startedDecoding = true;
-        }
+        mCurrentRequest->StartDecoding();
       }
     }
   }
 
   // We want to give the decoder a chance to find errors. If we haven't found
   // an error yet and we've started decoding, either from the above
   // StartDecoding or from some other place, we must only fire these events
   // after we finish decoding.
   uint32_t reqStatus;
   aRequest->GetImageStatus(&reqStatus);
   if (NS_SUCCEEDED(aStatus) && !(reqStatus & imgIRequest::STATUS_ERROR) &&
-      (reqStatus & imgIRequest::STATUS_DECODE_STARTED ||
-       (startedDecoding && !(reqStatus & imgIRequest::STATUS_DECODE_COMPLETE)))) {
+      (reqStatus & imgIRequest::STATUS_DECODE_STARTED) &&
+      !(reqStatus & imgIRequest::STATUS_DECODE_COMPLETE)) {
     mFireEventsOnDecode = true;
   } else {
     // Fire the appropriate DOM event.
     if (NS_SUCCEEDED(aStatus)) {
       FireEvent(NS_LITERAL_STRING("load"));
     } else {
       FireEvent(NS_LITERAL_STRING("error"));
     }
--- a/image/src/imgStatusTracker.cpp
+++ b/image/src/imgStatusTracker.cpp
@@ -425,18 +425,16 @@ imgStatusTracker::SyncNotifyState(ProxyA
 
 ImageStatusDiff
 imgStatusTracker::Difference(imgStatusTracker* aOther) const
 {
   MOZ_ASSERT(aOther, "aOther cannot be null");
   ImageStatusDiff diff;
   diff.diffState = ~mState & aOther->mState & ~FLAG_REQUEST_STARTED;
   diff.diffImageStatus = ~mImageStatus & aOther->mImageStatus;
-  diff.unsetDecodeStarted = mImageStatus & imgIRequest::STATUS_DECODE_STARTED
-                         && !(aOther->mImageStatus & imgIRequest::STATUS_DECODE_STARTED);
 
   MOZ_ASSERT(!mIsMultipart || aOther->mIsMultipart, "mIsMultipart should be monotonic");
   diff.foundIsMultipart = !mIsMultipart && aOther->mIsMultipart;
   diff.foundLastPart = !mHadLastPart && aOther->mHadLastPart;
 
   diff.gotDecoded = !mHasBeenDecoded && aOther->mHasBeenDecoded;
 
   // Only record partial invalidations if we haven't been decoded before.
@@ -481,20 +479,16 @@ imgStatusTracker::ApplyDifference(const 
   mState |= aDiff.diffState | loadState;
 
   mIsMultipart = mIsMultipart || aDiff.foundIsMultipart;
   mHadLastPart = mHadLastPart || aDiff.foundLastPart;
   mHasBeenDecoded = mHasBeenDecoded || aDiff.gotDecoded;
 
   // Update the image status. There are some subtle points which are handled below.
   mImageStatus |= aDiff.diffImageStatus;
-
-  // Unset bits which can get unset as part of the decoding process.
-  if (aDiff.unsetDecodeStarted)
-    mImageStatus &= ~imgIRequest::STATUS_DECODE_STARTED;
 }
 
 void
 imgStatusTracker::SyncNotifyDifference(const ImageStatusDiff& diff)
 {
   MOZ_ASSERT(NS_IsMainThread(), "Use mConsumers on main thread only");
   LOG_SCOPE(GetImgLog(), "imgStatusTracker::SyncNotifyDifference");
 
@@ -628,18 +622,19 @@ imgStatusTracker::RecordLoaded()
   mHadLastPart = true;
 }
 
 void
 imgStatusTracker::RecordDecoded()
 {
   NS_ABORT_IF_FALSE(mImage, "RecordDecoded called before we have an Image");
   mState |= FLAG_DECODE_STARTED | FLAG_DECODE_STOPPED | FLAG_FRAME_STOPPED;
-  mImageStatus |= imgIRequest::STATUS_FRAME_COMPLETE | imgIRequest::STATUS_DECODE_COMPLETE;
-  mImageStatus &= ~imgIRequest::STATUS_DECODE_STARTED;
+  mImageStatus |= imgIRequest::STATUS_DECODE_STARTED |
+                  imgIRequest::STATUS_DECODE_COMPLETE |
+                  imgIRequest::STATUS_FRAME_COMPLETE;
 }
 
 void
 imgStatusTracker::RecordStartDecode()
 {
   NS_ABORT_IF_FALSE(mImage, "RecordStartDecode without an Image");
   mState |= FLAG_DECODE_STARTED;
   mImageStatus |= imgIRequest::STATUS_DECODE_STARTED;
@@ -698,17 +693,16 @@ imgStatusTracker::SendStopFrame(imgReque
 
 void
 imgStatusTracker::RecordStopDecode(nsresult aStatus)
 {
   MOZ_ASSERT(mImage, "RecordStopDecode called before we have an Image");
 
   mState |= FLAG_DECODE_STOPPED;
   mImageStatus |= imgIRequest::STATUS_DECODE_COMPLETE;
-  mImageStatus &= ~imgIRequest::STATUS_DECODE_STARTED;
 
   if (NS_SUCCEEDED(aStatus) && !(mImageStatus & imgIRequest::STATUS_ERROR)) {
     mHasBeenDecoded = true;
   } else {
     mImageStatus |= imgIRequest::STATUS_ERROR;
   }
 }
 
--- a/image/src/imgStatusTracker.h
+++ b/image/src/imgStatusTracker.h
@@ -41,50 +41,46 @@ enum {
 };
 
 struct ImageStatusDiff
 {
   ImageStatusDiff()
     : invalidRect()
     , diffState(0)
     , diffImageStatus(0)
-    , unsetDecodeStarted(false)
     , foundIsMultipart(false)
     , foundLastPart(false)
     , gotDecoded(false)
   { }
 
   static ImageStatusDiff NoChange() { return ImageStatusDiff(); }
   bool IsNoChange() const { return *this == NoChange(); }
 
   bool operator!=(const ImageStatusDiff& aOther) const { return !(*this == aOther); }
   bool operator==(const ImageStatusDiff& aOther) const {
     return aOther.invalidRect == invalidRect
         && aOther.diffState == diffState
         && aOther.diffImageStatus == diffImageStatus
-        && aOther.unsetDecodeStarted == unsetDecodeStarted
         && aOther.foundIsMultipart == foundIsMultipart
         && aOther.foundLastPart == foundLastPart
         && aOther.gotDecoded == gotDecoded;
   }
 
   void Combine(const ImageStatusDiff& aOther) {
     invalidRect = invalidRect.Union(aOther.invalidRect);
     diffState |= aOther.diffState;
     diffImageStatus |= aOther.diffImageStatus;
-    unsetDecodeStarted = unsetDecodeStarted || aOther.unsetDecodeStarted;
     foundIsMultipart = foundIsMultipart || aOther.foundIsMultipart;
     foundLastPart = foundLastPart || aOther.foundLastPart;
     gotDecoded = gotDecoded || aOther.gotDecoded;
   }
 
   nsIntRect invalidRect;
   uint32_t  diffState;
   uint32_t  diffImageStatus;
-  bool      unsetDecodeStarted : 1;
   bool      foundIsMultipart   : 1;
   bool      foundLastPart      : 1;
   bool      gotDecoded         : 1;
 };
 
 } // namespace image
 } // namespace mozilla
 
--- a/layout/xul/nsImageBoxFrame.cpp
+++ b/layout/xul/nsImageBoxFrame.cpp
@@ -687,17 +687,18 @@ nsresult nsImageBoxFrame::OnStopRequest(
 {
   uint32_t reqStatus;
   request->GetImageStatus(&reqStatus);
 
   // We want to give the decoder a chance to find errors. If we haven't found
   // an error yet and we've already started decoding, we must only fire these
   // events after we finish decoding.
   if (NS_SUCCEEDED(aStatus) && !(reqStatus & imgIRequest::STATUS_ERROR) &&
-      reqStatus & imgIRequest::STATUS_DECODE_STARTED) {
+      (reqStatus & imgIRequest::STATUS_DECODE_STARTED) &&
+      !(reqStatus & imgIRequest::STATUS_DECODE_COMPLETE)) {
     mFireEventOnDecode = true;
   } else {
     if (NS_SUCCEEDED(aStatus)) {
       // Fire an onload DOM event.
       FireImageDOMEvent(mContent, NS_LOAD);
     } else {
       // Fire an onerror DOM event.
       mIntrinsicSize.SizeTo(0, 0);