Bug 854287 - Don't send partial invalidations for images which have already been decoded. r=joe
authorSeth Fowler <seth@mozilla.com>
Thu, 18 Apr 2013 16:31:46 -0700
changeset 140586 61711e1aab0cb1ff2d066682ec35c1e534787927
parent 140585 bb028a52ffe3da8d3a4beaac0de7cab6a441ba6a
child 140587 aa0d00ea2c5f660f3fb3bdbe9244ba474fee8d83
push id2579
push userakeybl@mozilla.com
push dateMon, 24 Jun 2013 18:52:47 +0000
treeherdermozilla-beta@b69b7de8a05a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjoe
bugs854287
milestone23.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 854287 - Don't send partial invalidations for images which have already been decoded. r=joe
image/src/imgStatusTracker.cpp
image/src/imgStatusTracker.h
--- a/image/src/imgStatusTracker.cpp
+++ b/image/src/imgStatusTracker.cpp
@@ -295,17 +295,18 @@ private:
 
 // imgStatusTracker methods
 
 imgStatusTracker::imgStatusTracker(Image* aImage)
   : mImage(aImage),
     mState(0),
     mImageStatus(imgIRequest::STATUS_NONE),
     mIsMultipart(false),
-    mHadLastPart(false)
+    mHadLastPart(false),
+    mHasBeenDecoded(false)
 {
   mTrackerObserver = new imgStatusTrackerObserver(this);
 }
 
 // Private, used only by CloneForRecording.
 imgStatusTracker::imgStatusTracker(const imgStatusTracker& aOther)
   : mImage(aOther.mImage),
     mState(aOther.mState),
@@ -529,39 +530,49 @@ imgStatusTracker::CalculateAndApplyDiffe
   diff.mDiffState = ~mState & other->mState & ~stateRequestStarted;
   diff.mUnblockedOnload = mState & stateBlockingOnload && !(other->mState & stateBlockingOnload);
   diff.mFoundError = (mImageStatus != imgIRequest::STATUS_ERROR) && (other->mImageStatus == imgIRequest::STATUS_ERROR);
 
   // Now that we've calculated the difference in state, synchronize our state
   // with the other tracker.
 
   // First, actually synchronize our state.
-  diff.mInvalidRect = mInvalidRect.Union(other->mInvalidRect);
   mState |= diff.mDiffState | loadState;
   if (diff.mUnblockedOnload) {
     mState &= ~stateBlockingOnload;
   }
   mImageStatus = other->mImageStatus;
   mIsMultipart = other->mIsMultipart;
   mHadLastPart = other->mHadLastPart;
   mImageStatus |= other->mImageStatus;
+  mHasBeenDecoded = mHasBeenDecoded || other->mHasBeenDecoded;
 
   // The error state is sticky and overrides all other bits.
   if (mImageStatus & imgIRequest::STATUS_ERROR) {
     mImageStatus = imgIRequest::STATUS_ERROR;
   } else {
     // Unset the bits that can get unset as part of the decoding process.
     if (!(other->mImageStatus & imgIRequest::STATUS_DECODE_STARTED)) {
       mImageStatus &= ~imgIRequest::STATUS_DECODE_STARTED;
     }
   }
 
-  // Reset the invalid rectangles for another go.
-  other->mInvalidRect.SetEmpty();
-  mInvalidRect.SetEmpty();
+  // Only record partial invalidations if we haven't been decoded before.
+  // When images are re-decoded after discarding, we don't want to display
+  // partially decoded versions to the user.
+  bool doInvalidations  = !mHasBeenDecoded
+                       || mImageStatus & imgIRequest::STATUS_ERROR
+                       || mImageStatus & imgIRequest::STATUS_DECODE_COMPLETE;
+
+  // Record the invalid rectangles and reset them for another go.
+  if (doInvalidations) {
+    diff.mInvalidRect = mInvalidRect.Union(other->mInvalidRect);
+    other->mInvalidRect.SetEmpty();
+    mInvalidRect.SetEmpty();
+  }
 
   return diff;
 }
 
 void
 imgStatusTracker::SyncNotifyDifference(imgStatusTracker::StatusDiff diff)
 {
   LOG_SCOPE(GetImgLog(), "imgStatusTracker::SyncNotifyDifference");
@@ -763,16 +774,17 @@ imgStatusTracker::RecordStopDecode(nsres
 {
   NS_ABORT_IF_FALSE(mImage,
                     "RecordStopDecode called before we have an Image");
   mState |= stateDecodeStopped;
 
   if (NS_SUCCEEDED(aStatus) && mImageStatus != imgIRequest::STATUS_ERROR) {
     mImageStatus |= imgIRequest::STATUS_DECODE_COMPLETE;
     mImageStatus &= ~imgIRequest::STATUS_DECODE_STARTED;
+    mHasBeenDecoded = true;
   // If we weren't successful, clear all success status bits and set error.
   } else {
     mImageStatus = imgIRequest::STATUS_ERROR;
   }
 }
 
 void
 imgStatusTracker::SendStopDecode(imgRequestProxy* aProxy,
--- a/image/src/imgStatusTracker.h
+++ b/image/src/imgStatusTracker.h
@@ -241,11 +241,12 @@ private:
   nsTObserverArray<imgRequestProxy*> mConsumers;
 
   mozilla::RefPtr<imgDecoderObserver> mTrackerObserver;
 
   uint32_t mState;
   uint32_t mImageStatus;
   bool mIsMultipart    : 1;
   bool mHadLastPart    : 1;
+  bool mHasBeenDecoded : 1;
 };
 
 #endif