LCOV - code coverage report
Current view: top level - image - IDecodingTask.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 42 65 64.6 %
Date: 2017-07-14 16:53:18 Functions: 10 13 76.9 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* This Source Code Form is subject to the terms of the Mozilla Public
       3             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       4             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       5             : 
       6             : #include "IDecodingTask.h"
       7             : 
       8             : #include "gfxPrefs.h"
       9             : #include "nsThreadUtils.h"
      10             : 
      11             : #include "Decoder.h"
      12             : #include "DecodePool.h"
      13             : #include "RasterImage.h"
      14             : #include "SurfaceCache.h"
      15             : 
      16             : namespace mozilla {
      17             : 
      18             : using gfx::IntRect;
      19             : 
      20             : namespace image {
      21             : 
      22             : ///////////////////////////////////////////////////////////////////////////////
      23             : // Helpers for sending notifications to the image associated with a decoder.
      24             : ///////////////////////////////////////////////////////////////////////////////
      25             : 
      26             : /* static */ void
      27          34 : IDecodingTask::NotifyProgress(NotNull<RasterImage*> aImage,
      28             :                               NotNull<Decoder*> aDecoder)
      29             : {
      30          34 :   MOZ_ASSERT(aDecoder->HasProgress() && !aDecoder->IsMetadataDecode());
      31             : 
      32             :   // Capture the decoder's state. If we need to notify asynchronously, it's
      33             :   // important that we don't wait until the lambda actually runs to capture the
      34             :   // state that we're going to notify. That would both introduce data races on
      35             :   // the decoder's state and cause inconsistencies between the NotifyProgress()
      36             :   // calls we make off-main-thread and the notifications that RasterImage
      37             :   // actually receives, which would cause bugs.
      38          34 :   Progress progress = aDecoder->TakeProgress();
      39          34 :   IntRect invalidRect = aDecoder->TakeInvalidRect();
      40          68 :   Maybe<uint32_t> frameCount = aDecoder->TakeCompleteFrameCount();
      41          34 :   DecoderFlags decoderFlags = aDecoder->GetDecoderFlags();
      42          34 :   SurfaceFlags surfaceFlags = aDecoder->GetSurfaceFlags();
      43             : 
      44             :   // Synchronously notify if we can.
      45          34 :   if (NS_IsMainThread() && !(decoderFlags & DecoderFlags::ASYNC_NOTIFY)) {
      46           0 :     aImage->NotifyProgress(progress, invalidRect, frameCount,
      47           0 :                            decoderFlags, surfaceFlags);
      48           0 :     return;
      49             :   }
      50             : 
      51             :   // We're forced to notify asynchronously.
      52          68 :   NotNull<RefPtr<RasterImage>> image = aImage;
      53          68 :   NS_DispatchToMainThread(NS_NewRunnableFunction(
      54             :                             "IDecodingTask::NotifyProgress",
      55         136 :                             [=]() -> void {
      56          34 :     image->NotifyProgress(progress, invalidRect, frameCount,
      57          68 :                           decoderFlags, surfaceFlags);
      58          68 :   }));
      59             : }
      60             : 
      61             : /* static */ void
      62          33 : IDecodingTask::NotifyDecodeComplete(NotNull<RasterImage*> aImage,
      63             :                                     NotNull<Decoder*> aDecoder)
      64             : {
      65          33 :   MOZ_ASSERT(aDecoder->HasError() || !aDecoder->InFrame(),
      66             :              "Decode complete in the middle of a frame?");
      67             : 
      68             :   // Capture the decoder's state.
      69          33 :   DecoderFinalStatus finalStatus = aDecoder->FinalStatus();
      70          66 :   ImageMetadata metadata = aDecoder->GetImageMetadata();
      71          66 :   DecoderTelemetry telemetry = aDecoder->Telemetry();
      72          33 :   Progress progress = aDecoder->TakeProgress();
      73          33 :   IntRect invalidRect = aDecoder->TakeInvalidRect();
      74          66 :   Maybe<uint32_t> frameCount = aDecoder->TakeCompleteFrameCount();
      75          33 :   DecoderFlags decoderFlags = aDecoder->GetDecoderFlags();
      76          33 :   SurfaceFlags surfaceFlags = aDecoder->GetSurfaceFlags();
      77             : 
      78             :   // Synchronously notify if we can.
      79          33 :   if (NS_IsMainThread() && !(decoderFlags & DecoderFlags::ASYNC_NOTIFY)) {
      80           0 :     aImage->NotifyDecodeComplete(finalStatus, metadata, telemetry, progress,
      81             :                                  invalidRect, frameCount, decoderFlags,
      82           0 :                                  surfaceFlags);
      83           0 :     return;
      84             :   }
      85             : 
      86             :   // We're forced to notify asynchronously.
      87          66 :   NotNull<RefPtr<RasterImage>> image = aImage;
      88          66 :   NS_DispatchToMainThread(NS_NewRunnableFunction(
      89             :                             "IDecodingTask::NotifyDecodeComplete",
      90         132 :                             [=]() -> void {
      91          33 :     image->NotifyDecodeComplete(finalStatus, metadata, telemetry, progress,
      92          33 :                                 invalidRect, frameCount, decoderFlags,
      93          66 :                                 surfaceFlags);
      94          66 :   }));
      95             : }
      96             : 
      97             : 
      98             : ///////////////////////////////////////////////////////////////////////////////
      99             : // IDecodingTask implementation.
     100             : ///////////////////////////////////////////////////////////////////////////////
     101             : 
     102             : void
     103           0 : IDecodingTask::Resume()
     104             : {
     105           0 :   DecodePool::Singleton()->AsyncRun(this);
     106           0 : }
     107             : 
     108             : 
     109             : ///////////////////////////////////////////////////////////////////////////////
     110             : // MetadataDecodingTask implementation.
     111             : ///////////////////////////////////////////////////////////////////////////////
     112             : 
     113          19 : MetadataDecodingTask::MetadataDecodingTask(NotNull<Decoder*> aDecoder)
     114             :   : mMutex("mozilla::image::MetadataDecodingTask")
     115          19 :   , mDecoder(aDecoder)
     116             : {
     117          19 :   MOZ_ASSERT(mDecoder->IsMetadataDecode(),
     118             :              "Use DecodingTask for non-metadata decodes");
     119          19 : }
     120             : 
     121             : void
     122          19 : MetadataDecodingTask::Run()
     123             : {
     124          38 :   MutexAutoLock lock(mMutex);
     125             : 
     126          38 :   LexerResult result = mDecoder->Decode(WrapNotNull(this));
     127             : 
     128          19 :   if (result.is<TerminalState>()) {
     129          19 :     NotifyDecodeComplete(mDecoder->GetImage(), mDecoder);
     130          19 :     return;  // We're done.
     131             :   }
     132             : 
     133           0 :   if (result == LexerResult(Yield::NEED_MORE_DATA)) {
     134             :     // We can't make any more progress right now. We also don't want to report
     135             :     // any progress, because it's important that metadata decode results are
     136             :     // delivered atomically. The decoder itself will ensure that we get
     137             :     // reenqueued when more data is available; just return for now.
     138           0 :     return;
     139             :   }
     140             : 
     141           0 :   MOZ_ASSERT_UNREACHABLE("Metadata decode yielded for an unexpected reason");
     142             : }
     143             : 
     144             : 
     145             : ///////////////////////////////////////////////////////////////////////////////
     146             : // AnonymousDecodingTask implementation.
     147             : ///////////////////////////////////////////////////////////////////////////////
     148             : 
     149           0 : AnonymousDecodingTask::AnonymousDecodingTask(NotNull<Decoder*> aDecoder)
     150           0 :   : mDecoder(aDecoder)
     151           0 : { }
     152             : 
     153             : void
     154           0 : AnonymousDecodingTask::Run()
     155             : {
     156             :   while (true) {
     157           0 :     LexerResult result = mDecoder->Decode(WrapNotNull(this));
     158             : 
     159           0 :     if (result.is<TerminalState>()) {
     160           0 :       return;  // We're done.
     161             :     }
     162             : 
     163           0 :     if (result == LexerResult(Yield::NEED_MORE_DATA)) {
     164             :       // We can't make any more progress right now. Let the caller decide how to
     165             :       // handle it.
     166           0 :       return;
     167             :     }
     168             : 
     169             :     // Right now we don't do anything special for other kinds of yields, so just
     170             :     // keep working.
     171           0 :     MOZ_ASSERT(result.is<Yield>());
     172           0 :   }
     173             : }
     174             : 
     175             : } // namespace image
     176             : } // namespace mozilla

Generated by: LCOV version 1.13