Bug 1291071 (Part 5) - Pass the decoder's final status explicitly to FinalizeDecoder(). r=edwin
authorSeth Fowler <mark.seth.fowler@gmail.com>
Tue, 02 Aug 2016 17:12:36 -0700
changeset 349758 55a26e91a828df3cd54b432a03014ed4801dc20f
parent 349757 eef2029cae9d33943011306ac593906492368d2b
child 349759 731d13870f6a161f47ab8bffe5ee8e2ac92d5195
push id6570
push userraliiev@mozilla.com
push dateMon, 14 Nov 2016 12:26:13 +0000
treeherdermozilla-beta@f455459b2ae5 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersedwin
bugs1291071
milestone51.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 1291071 (Part 5) - Pass the decoder's final status explicitly to FinalizeDecoder(). r=edwin
image/Decoder.cpp
image/Decoder.h
image/IDecodingTask.cpp
image/RasterImage.cpp
image/RasterImage.h
--- a/image/Decoder.cpp
+++ b/image/Decoder.cpp
@@ -262,16 +262,26 @@ Decoder::ExplicitOutputSize() const
 Maybe<uint32_t>
 Decoder::TakeCompleteFrameCount()
 {
   const bool finishedNewFrame = mFinishedNewFrame;
   mFinishedNewFrame = false;
   return finishedNewFrame ? Some(GetCompleteFrameCount()) : Nothing();
 }
 
+DecoderFinalStatus
+Decoder::FinalStatus() const
+{
+  return DecoderFinalStatus(IsMetadataDecode(),
+                            GetDecodeDone(),
+                            WasAborted(),
+                            HasError(),
+                            ShouldReportError());
+}
+
 DecoderTelemetry
 Decoder::Telemetry() const
 {
   MOZ_ASSERT(mIterator);
   return DecoderTelemetry(SpeedHistogram(),
                           mIterator->ByteCount(),
                           mIterator->ChunkCount(),
                           mDecodeTime);
--- a/image/Decoder.h
+++ b/image/Decoder.h
@@ -23,16 +23,49 @@
 namespace mozilla {
 
 namespace Telemetry {
   enum ID : uint32_t;
 } // namespace Telemetry
 
 namespace image {
 
+struct DecoderFinalStatus final
+{
+  DecoderFinalStatus(bool aWasMetadataDecode,
+                     bool aFinished,
+                     bool aWasAborted,
+                     bool aHadError,
+                     bool aShouldReportError)
+    : mWasMetadataDecode(aWasMetadataDecode)
+    , mFinished(aFinished)
+    , mWasAborted(aWasAborted)
+    , mHadError(aHadError)
+    , mShouldReportError(aShouldReportError)
+  { }
+
+  /// True if this was a metadata decode.
+  const bool mWasMetadataDecode : 1;
+
+  /// True if this decoder finished, whether successfully or due to failure.
+  const bool mFinished : 1;
+
+  /// True if this decoder was asynchronously aborted. This normally happens
+  /// when a decoder fails to insert a surface into the surface cache, indicating
+  /// that another decoding beat it to the punch.
+  const bool mWasAborted : 1;
+
+  /// True if this decoder encountered an error.
+  const bool mHadError : 1;
+
+  /// True if this decoder encountered the kind of error that should be reported
+  /// to the console.
+  const bool mShouldReportError : 1;
+};
+
 struct DecoderTelemetry final
 {
   DecoderTelemetry(Maybe<Telemetry::ID> aSpeedHistogram,
                    size_t aBytesDecoded,
                    uint32_t aChunkCount,
                    TimeDuration aDecodeTime)
     : mSpeedHistogram(aSpeedHistogram)
     , mBytesDecoded(aBytesDecoded)
@@ -332,16 +365,20 @@ public:
    *
    * Illegal to call if HasSize() returns false.
    */
   gfx::IntRect FullOutputFrame() const
   {
     return gfx::IntRect(gfx::IntPoint(), OutputSize());
   }
 
+  /// @return final status information about this decoder. Should be called
+  /// after we decide we're not going to run the decoder anymore.
+  DecoderFinalStatus FinalStatus() const;
+
   /// @return the metadata we collected about this image while decoding.
   const ImageMetadata& GetImageMetadata() { return mImageMetadata; }
 
   /// @return performance telemetry we collected while decoding.
   DecoderTelemetry Telemetry() const;
 
   /**
    * @return a weak pointer to the image associated with this decoder. Illegal
--- a/image/IDecodingTask.cpp
+++ b/image/IDecodingTask.cpp
@@ -59,37 +59,38 @@ IDecodingTask::NotifyProgress(NotNull<Ra
 /* static */ void
 IDecodingTask::NotifyDecodeComplete(NotNull<RasterImage*> aImage,
                                     NotNull<Decoder*> aDecoder)
 {
   MOZ_ASSERT(aDecoder->HasError() || !aDecoder->InFrame(),
              "Decode complete in the middle of a frame?");
 
   // Capture the decoder's state.
+  DecoderFinalStatus finalStatus = aDecoder->FinalStatus();
   ImageMetadata metadata = aDecoder->GetImageMetadata();
   DecoderTelemetry telemetry = aDecoder->Telemetry();
   Progress progress = aDecoder->TakeProgress();
   IntRect invalidRect = aDecoder->TakeInvalidRect();
   Maybe<uint32_t> frameCount = aDecoder->TakeCompleteFrameCount();
   SurfaceFlags surfaceFlags = aDecoder->GetSurfaceFlags();
 
   // Synchronously notify if we can.
   if (NS_IsMainThread() &&
       !(aDecoder->GetDecoderFlags() & DecoderFlags::ASYNC_NOTIFY)) {
-    aImage->FinalizeDecoder(aDecoder, metadata, telemetry, progress,
+    aImage->FinalizeDecoder(aDecoder, finalStatus, metadata, telemetry, progress,
                             invalidRect, frameCount, surfaceFlags);
     return;
   }
 
   // We're forced to notify asynchronously.
   NotNull<RefPtr<RasterImage>> image = aImage;
   NotNull<RefPtr<Decoder>> decoder = aDecoder;
   NS_DispatchToMainThread(NS_NewRunnableFunction([=]() -> void {
-    image->FinalizeDecoder(decoder.get(), metadata, telemetry, progress,
-                           invalidRect, frameCount, surfaceFlags);
+    image->FinalizeDecoder(decoder.get(), finalStatus, metadata, telemetry,
+                           progress, invalidRect, frameCount, surfaceFlags);
   }));
 }
 
 
 ///////////////////////////////////////////////////////////////////////////////
 // IDecodingTask implementation.
 ///////////////////////////////////////////////////////////////////////////////
 
--- a/image/RasterImage.cpp
+++ b/image/RasterImage.cpp
@@ -1558,94 +1558,92 @@ RasterImage::NotifyProgress(Progress aPr
   }
 
   // Tell the observers what happened.
   image->mProgressTracker->SyncNotifyProgress(aProgress, aInvalidRect);
 }
 
 void
 RasterImage::FinalizeDecoder(Decoder* aDecoder,
+                             const DecoderFinalStatus& aStatus,
                              const ImageMetadata& aMetadata,
                              const DecoderTelemetry& aTelemetry,
                              Progress aProgress,
                              const IntRect& aInvalidRect,
                              const Maybe<uint32_t>& aFrameCount,
                              SurfaceFlags aSurfaceFlags)
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(aDecoder);
 
-  bool wasMetadata = aDecoder->IsMetadataDecode();
-  bool done = aDecoder->GetDecodeDone();
-
   // If the decoder detected an error, log it to the error console.
-  if (aDecoder->ShouldReportError() && !aDecoder->WasAborted()) {
+  if (aStatus.mShouldReportError && !aStatus.mWasAborted) {
     ReportDecoderError(aDecoder);
   }
 
   // Record all the metadata the decoder gathered about this image.
-  bool metadataOK = SetMetadata(aMetadata, wasMetadata);
+  bool metadataOK = SetMetadata(aMetadata, aStatus.mWasMetadataDecode);
   if (!metadataOK) {
     // This indicates a serious error that requires us to discard all existing
     // surfaces and redecode to recover. We'll drop the results from this
     // decoder on the floor, since they aren't valid.
     RecoverFromInvalidFrames(mSize,
                              FromSurfaceFlags(aSurfaceFlags));
     return;
   }
 
   MOZ_ASSERT(mError || mHasSize || !aMetadata.HasSize(),
              "SetMetadata should've gotten a size");
 
-  if (!wasMetadata && aDecoder->GetDecodeDone() && !aDecoder->WasAborted()) {
+  if (!aStatus.mWasMetadataDecode && aStatus.mFinished && !aStatus.mWasAborted) {
     // Flag that we've been decoded before.
     mHasBeenDecoded = true;
   }
 
   // Send out any final notifications.
   NotifyProgress(aProgress, aInvalidRect, aFrameCount, aSurfaceFlags);
 
   if (mHasBeenDecoded && mAnimationState) {
     // We're done decoding and our AnimationState has been notified about all
     // our frames, so let it know not to expect anymore.
     mAnimationState->SetDoneDecoding(true);
   }
 
-  if (!wasMetadata && aTelemetry.mChunkCount) {
+  if (!aStatus.mWasMetadataDecode && aTelemetry.mChunkCount) {
     Telemetry::Accumulate(Telemetry::IMAGE_DECODE_CHUNKS, aTelemetry.mChunkCount);
   }
 
-  if (done) {
+  if (aStatus.mFinished) {
     // Do some telemetry if this isn't a metadata decode.
-    if (!wasMetadata) {
+    if (!aStatus.mWasMetadataDecode) {
       Telemetry::Accumulate(Telemetry::IMAGE_DECODE_TIME,
                             int32_t(aTelemetry.mDecodeTime.ToMicroseconds()));
 
       if (aTelemetry.mSpeedHistogram) {
         Telemetry::Accumulate(*aTelemetry.mSpeedHistogram, aTelemetry.Speed());
       }
     }
 
     // Detect errors.
-    if (aDecoder->HasError() && !aDecoder->WasAborted()) {
+    if (aStatus.mHadError && !aStatus.mWasAborted) {
       DoError();
-    } else if (wasMetadata && !mHasSize) {
+    } else if (aStatus.mWasMetadataDecode && !mHasSize) {
       DoError();
     }
 
     // If we were waiting to fire the load event, go ahead and fire it now.
-    if (mLoadProgress && wasMetadata) {
+    if (mLoadProgress && aStatus.mWasMetadataDecode) {
       NotifyForLoadEvent(*mLoadProgress);
       mLoadProgress = Nothing();
       NotifyProgress(FLAG_ONLOAD_UNBLOCKED);
     }
   }
 
   // If we were a metadata decode and a full decode was requested, do it.
-  if (done && wasMetadata && mWantFullDecode) {
+  if (aStatus.mFinished && aStatus.mWasMetadataDecode && mWantFullDecode) {
     mWantFullDecode = false;
     RequestDecodeForSize(mSize, DECODE_FLAGS_DEFAULT);
   }
 }
 
 void
 RasterImage::ReportDecoderError(Decoder* aDecoder)
 {
--- a/image/RasterImage.h
+++ b/image/RasterImage.h
@@ -130,16 +130,17 @@ namespace mozilla {
 namespace layers {
 class ImageContainer;
 class Image;
 } // namespace layers
 
 namespace image {
 
 class Decoder;
+struct DecoderFinalStatus;
 struct DecoderTelemetry;
 class ImageMetadata;
 class SourceBuffer;
 
 class RasterImage final : public ImageResource
                         , public nsIProperties
                         , public SupportsWeakPtr<RasterImage>
 #ifdef DEBUG
@@ -198,16 +199,17 @@ public:
                       SurfaceFlags aSurfaceFlags = DefaultSurfaceFlags());
 
   /**
    * Records telemetry and does final teardown of the provided decoder.
    *
    * Main-thread only.
    */
   void FinalizeDecoder(Decoder* aDecoder,
+                       const DecoderFinalStatus& aStatus,
                        const ImageMetadata& aMetadata,
                        const DecoderTelemetry& aTelemetry,
                        Progress aProgress,
                        const gfx::IntRect& aInvalidRect,
                        const Maybe<uint32_t>& aFrameCount,
                        SurfaceFlags aSurfaceFlags);
 
   // Helper method for FinalizeDecoder.