Bug 1291045 (Part 1) - Use a different IDecodingTask for animated images. r=dholbert,edwin
authorSeth Fowler <mark.seth.fowler@gmail.com>
Mon, 01 Aug 2016 17:02:16 -0700
changeset 349746 41ecafc5752459e2e10de8df764b403559feb28a
parent 349745 d289b7a8ad1f3374897bff0d2d59c4b1179f81cd
child 349747 50ac73a27eb3206a849e8eb397c95ab75cddd4f9
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)
reviewersdholbert, edwin
bugs1291045
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 1291045 (Part 1) - Use a different IDecodingTask for animated images. r=dholbert,edwin
image/DecoderFactory.cpp
image/IDecodingTask.cpp
image/IDecodingTask.h
--- a/image/DecoderFactory.cpp
+++ b/image/DecoderFactory.cpp
@@ -182,17 +182,17 @@ DecoderFactory::CreateAnimationDecoder(D
   SurfaceKey surfaceKey =
     RasterSurfaceKey(aIntrinsicSize, aSurfaceFlags, /* aFrameNum = */ 0);
   InsertOutcome outcome =
     SurfaceCache::InsertPlaceholder(ImageKey(aImage.get()), surfaceKey);
   if (outcome != InsertOutcome::SUCCESS) {
     return nullptr;
   }
 
-  RefPtr<IDecodingTask> task = new DecodingTask(WrapNotNull(decoder));
+  RefPtr<IDecodingTask> task = new AnimationDecodingTask(WrapNotNull(decoder));
   return task.forget();
 }
 
 /* static */ already_AddRefed<IDecodingTask>
 DecoderFactory::CreateMetadataDecoder(DecoderType aType,
                                       NotNull<RasterImage*> aImage,
                                       NotNull<SourceBuffer*> aSourceBuffer,
                                       int aSampleSize)
--- a/image/IDecodingTask.cpp
+++ b/image/IDecodingTask.cpp
@@ -87,16 +87,18 @@ IDecodingTask::Resume()
 // DecodingTask implementation.
 ///////////////////////////////////////////////////////////////////////////////
 
 DecodingTask::DecodingTask(NotNull<Decoder*> aDecoder)
   : mDecoder(aDecoder)
 {
   MOZ_ASSERT(!mDecoder->IsMetadataDecode(),
              "Use MetadataDecodingTask for metadata decodes");
+  MOZ_ASSERT(mDecoder->IsFirstFrameDecode(),
+             "Use AnimationDecodingTask for animation decodes");
 }
 
 void
 DecodingTask::Run()
 {
   while (true) {
     LexerResult result = mDecoder->Decode(WrapNotNull(this));
 
@@ -127,16 +129,66 @@ DecodingTask::Run()
 bool
 DecodingTask::ShouldPreferSyncRun() const
 {
   return mDecoder->ShouldSyncDecode(gfxPrefs::ImageMemDecodeBytesAtATime());
 }
 
 
 ///////////////////////////////////////////////////////////////////////////////
+// AnimationDecodingTask implementation.
+///////////////////////////////////////////////////////////////////////////////
+
+AnimationDecodingTask::AnimationDecodingTask(NotNull<Decoder*> aDecoder)
+  : mDecoder(aDecoder)
+{
+  MOZ_ASSERT(!mDecoder->IsMetadataDecode(),
+             "Use MetadataDecodingTask for metadata decodes");
+  MOZ_ASSERT(!mDecoder->IsFirstFrameDecode(),
+             "Use DecodingTask for single-frame image decodes");
+}
+
+void
+AnimationDecodingTask::Run()
+{
+  while (true) {
+    LexerResult result = mDecoder->Decode(WrapNotNull(this));
+
+    if (result.is<TerminalState>()) {
+      NotifyDecodeComplete(mDecoder);
+      return;  // We're done.
+    }
+
+    MOZ_ASSERT(result.is<Yield>());
+
+    // Notify for the progress we've made so far.
+    if (mDecoder->HasProgress()) {
+      NotifyProgress(mDecoder);
+    }
+
+    if (result == LexerResult(Yield::NEED_MORE_DATA)) {
+      // We can't make any more progress right now. The decoder itself will
+      // ensure that we get reenqueued when more data is available; just return
+      // for now.
+      return;
+    }
+
+    // Right now we don't do anything special for other kinds of yields, so just
+    // keep working.
+  }
+}
+
+bool
+AnimationDecodingTask::ShouldPreferSyncRun() const
+{
+  return mDecoder->ShouldSyncDecode(gfxPrefs::ImageMemDecodeBytesAtATime());
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
 // MetadataDecodingTask implementation.
 ///////////////////////////////////////////////////////////////////////////////
 
 MetadataDecodingTask::MetadataDecodingTask(NotNull<Decoder*> aDecoder)
   : mDecoder(aDecoder)
 {
   MOZ_ASSERT(mDecoder->IsMetadataDecode(),
              "Use DecodingTask for non-metadata decodes");
--- a/image/IDecodingTask.h
+++ b/image/IDecodingTask.h
@@ -51,17 +51,17 @@ public:
   virtual NotNull<Decoder*> GetDecoder() const = 0;
 
 protected:
   virtual ~IDecodingTask() { }
 };
 
 
 /**
- * An IDecodingTask implementation for full decodes of images.
+ * An IDecodingTask implementation for full decodes of single frame images.
  */
 class DecodingTask final : public IDecodingTask
 {
 public:
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(DecodingTask, override)
 
   explicit DecodingTask(NotNull<Decoder*> aDecoder);
 
@@ -77,16 +77,42 @@ public:
 private:
   virtual ~DecodingTask() { }
 
   NotNull<RefPtr<Decoder>> mDecoder;
 };
 
 
 /**
+ * An IDecodingTask implementation for full decodes of animated images.
+ */
+class AnimationDecodingTask final : public IDecodingTask
+{
+public:
+  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(AnimationDecodingTask, override)
+
+  explicit AnimationDecodingTask(NotNull<Decoder*> aDecoder);
+
+  void Run() override;
+  bool ShouldPreferSyncRun() const override;
+
+  // Full decodes are low priority compared to metadata decodes because they
+  // don't block layout or page load.
+  TaskPriority Priority() const override { return TaskPriority::eLow; }
+
+  NotNull<Decoder*> GetDecoder() const override { return mDecoder; }
+
+private:
+  virtual ~AnimationDecodingTask() { }
+
+  NotNull<RefPtr<Decoder>> mDecoder;
+};
+
+
+/**
  * An IDecodingTask implementation for metadata decodes of images.
  */
 class MetadataDecodingTask final : public IDecodingTask
 {
 public:
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MetadataDecodingTask, override)
 
   explicit MetadataDecodingTask(NotNull<Decoder*> aDecoder);