LCOV - code coverage report
Current view: top level - image - RasterImage.h (source / functions) Hit Total Coverage
Test: output.info Lines: 8 11 72.7 %
Date: 2017-07-14 16:53:18 Functions: 3 6 50.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
       2             :  *
       3             :  * This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : /** @file
       8             :  * This file declares the RasterImage class, which
       9             :  * handles static and animated rasterized images.
      10             :  *
      11             :  * @author  Stuart Parmenter <pavlov@netscape.com>
      12             :  * @author  Chris Saari <saari@netscape.com>
      13             :  * @author  Arron Mogge <paper@animecity.nu>
      14             :  * @author  Andrew Smith <asmith15@learn.senecac.on.ca>
      15             :  */
      16             : 
      17             : #ifndef mozilla_image_RasterImage_h
      18             : #define mozilla_image_RasterImage_h
      19             : 
      20             : #include "Image.h"
      21             : #include "nsCOMPtr.h"
      22             : #include "imgIContainer.h"
      23             : #include "nsIProperties.h"
      24             : #include "nsTArray.h"
      25             : #include "LookupResult.h"
      26             : #include "nsThreadUtils.h"
      27             : #include "DecodePool.h"
      28             : #include "DecoderFactory.h"
      29             : #include "FrameAnimator.h"
      30             : #include "ImageMetadata.h"
      31             : #include "ISurfaceProvider.h"
      32             : #include "Orientation.h"
      33             : #include "nsIObserver.h"
      34             : #include "mozilla/Attributes.h"
      35             : #include "mozilla/Maybe.h"
      36             : #include "mozilla/MemoryReporting.h"
      37             : #include "mozilla/NotNull.h"
      38             : #include "mozilla/Pair.h"
      39             : #include "mozilla/TimeStamp.h"
      40             : #include "mozilla/WeakPtr.h"
      41             : #include "mozilla/UniquePtr.h"
      42             : #include "ImageContainer.h"
      43             : #include "PlaybackType.h"
      44             : #ifdef DEBUG
      45             :   #include "imgIContainerDebug.h"
      46             : #endif
      47             : 
      48             : class nsIInputStream;
      49             : class nsIRequest;
      50             : 
      51             : #define NS_RASTERIMAGE_CID \
      52             : { /* 376ff2c1-9bf6-418a-b143-3340c00112f7 */         \
      53             :      0x376ff2c1,                                     \
      54             :      0x9bf6,                                         \
      55             :      0x418a,                                         \
      56             :     {0xb1, 0x43, 0x33, 0x40, 0xc0, 0x01, 0x12, 0xf7} \
      57             : }
      58             : 
      59             : /**
      60             :  * Handles static and animated image containers.
      61             :  *
      62             :  *
      63             :  * @par A Quick Walk Through
      64             :  * The decoder initializes this class and calls AppendFrame() to add a frame.
      65             :  * Once RasterImage detects more than one frame, it starts the animation
      66             :  * with StartAnimation(). Note that the invalidation events for RasterImage are
      67             :  * generated automatically using nsRefreshDriver.
      68             :  *
      69             :  * @par
      70             :  * StartAnimation() initializes the animation helper object and sets the time
      71             :  * the first frame was displayed to the current clock time.
      72             :  *
      73             :  * @par
      74             :  * When the refresh driver corresponding to the imgIContainer that this image is
      75             :  * a part of notifies the RasterImage that it's time to invalidate,
      76             :  * RequestRefresh() is called with a given TimeStamp to advance to. As long as
      77             :  * the timeout of the given frame (the frame's "delay") plus the time that frame
      78             :  * was first displayed is less than or equal to the TimeStamp given,
      79             :  * RequestRefresh() calls AdvanceFrame().
      80             :  *
      81             :  * @par
      82             :  * AdvanceFrame() is responsible for advancing a single frame of the animation.
      83             :  * It can return true, meaning that the frame advanced, or false, meaning that
      84             :  * the frame failed to advance (usually because the next frame hasn't been
      85             :  * decoded yet). It is also responsible for performing the final animation stop
      86             :  * procedure if the final frame of a non-looping animation is reached.
      87             :  *
      88             :  * @par
      89             :  * Each frame can have a different method of removing itself. These are
      90             :  * listed as imgIContainer::cDispose... constants.  Notify() calls
      91             :  * DoComposite() to handle any special frame destruction.
      92             :  *
      93             :  * @par
      94             :  * The basic path through DoComposite() is:
      95             :  * 1) Calculate Area that needs updating, which is at least the area of
      96             :  *    aNextFrame.
      97             :  * 2) Dispose of previous frame.
      98             :  * 3) Draw new image onto compositingFrame.
      99             :  * See comments in DoComposite() for more information and optimizations.
     100             :  *
     101             :  * @par
     102             :  * The rest of the RasterImage specific functions are used by DoComposite to
     103             :  * destroy the old frame and build the new one.
     104             :  *
     105             :  * @note
     106             :  * <li> "Mask", "Alpha", and "Alpha Level" are interchangeable phrases in
     107             :  * respects to RasterImage.
     108             :  *
     109             :  * @par
     110             :  * <li> GIFs never have more than a 1 bit alpha.
     111             :  * <li> APNGs may have a full alpha channel.
     112             :  *
     113             :  * @par
     114             :  * <li> Background color specified in GIF is ignored by web browsers.
     115             :  *
     116             :  * @par
     117             :  * <li> If Frame 3 wants to dispose by restoring previous, what it wants is to
     118             :  * restore the composition up to and including Frame 2, as well as Frame 2s
     119             :  * disposal.  So, in the middle of DoComposite when composing Frame 3, right
     120             :  * after destroying Frame 2's area, we copy compositingFrame to
     121             :  * prevCompositingFrame.  When DoComposite gets called to do Frame 4, we
     122             :  * copy prevCompositingFrame back, and then draw Frame 4 on top.
     123             :  *
     124             :  * @par
     125             :  * The mAnim structure has members only needed for animated images, so
     126             :  * it's not allocated until the second frame is added.
     127             :  */
     128             : 
     129             : namespace mozilla {
     130             : 
     131             : namespace layers {
     132             : class ImageContainer;
     133             : class Image;
     134             : } // namespace layers
     135             : 
     136             : namespace image {
     137             : 
     138             : class Decoder;
     139             : struct DecoderFinalStatus;
     140             : struct DecoderTelemetry;
     141             : class ImageMetadata;
     142             : class SourceBuffer;
     143             : 
     144             : class RasterImage final : public ImageResource
     145             :                         , public nsIProperties
     146             :                         , public SupportsWeakPtr<RasterImage>
     147             : #ifdef DEBUG
     148             :                         , public imgIContainerDebug
     149             : #endif
     150             : {
     151             :   // (no public constructor - use ImageFactory)
     152             :   virtual ~RasterImage();
     153             : 
     154             : public:
     155          21 :   MOZ_DECLARE_WEAKREFERENCE_TYPENAME(RasterImage)
     156             :   NS_DECL_THREADSAFE_ISUPPORTS
     157             :   NS_DECL_NSIPROPERTIES
     158             :   NS_DECL_IMGICONTAINER
     159             : #ifdef DEBUG
     160             :   NS_DECL_IMGICONTAINERDEBUG
     161             : #endif
     162             : 
     163             :   nsresult GetNativeSizes(nsTArray<gfx::IntSize>& aNativeSizes) const override;
     164             :   virtual nsresult StartAnimation() override;
     165             :   virtual nsresult StopAnimation() override;
     166             : 
     167             :   // Methods inherited from Image
     168             :   virtual void OnSurfaceDiscarded(const SurfaceKey& aSurfaceKey) override;
     169             : 
     170             :   virtual size_t SizeOfSourceWithComputedFallback(MallocSizeOf aMallocSizeOf)
     171             :     const override;
     172             :   virtual void CollectSizeOfSurfaces(nsTArray<SurfaceMemoryCounter>& aCounters,
     173             :                                      MallocSizeOf aMallocSizeOf) const override;
     174             : 
     175             :   /* Triggers discarding. */
     176             :   void Discard();
     177             : 
     178             : 
     179             :   //////////////////////////////////////////////////////////////////////////////
     180             :   // Decoder callbacks.
     181             :   //////////////////////////////////////////////////////////////////////////////
     182             : 
     183             :   /**
     184             :    * Sends the provided progress notifications to ProgressTracker.
     185             :    *
     186             :    * Main-thread only.
     187             :    *
     188             :    * @param aProgress    The progress notifications to send.
     189             :    * @param aInvalidRect An invalidation rect to send.
     190             :    * @param aFrameCount  If Some(), an updated count of the number of frames of
     191             :    *                     animation the decoder has finished decoding so far. This
     192             :    *                     is a lower bound for the total number of animation
     193             :    *                     frames this image has.
     194             :    * @param aDecoderFlags The decoder flags used by the decoder that generated
     195             :    *                      these notifications, or DefaultDecoderFlags() if the
     196             :    *                      notifications don't come from a decoder.
     197             :    * @param aSurfaceFlags The surface flags used by the decoder that generated
     198             :    *                      these notifications, or DefaultSurfaceFlags() if the
     199             :    *                      notifications don't come from a decoder.
     200             :    */
     201             :   void NotifyProgress(Progress aProgress,
     202             :                       const gfx::IntRect& aInvalidRect = nsIntRect(),
     203             :                       const Maybe<uint32_t>& aFrameCount = Nothing(),
     204             :                       DecoderFlags aDecoderFlags = DefaultDecoderFlags(),
     205             :                       SurfaceFlags aSurfaceFlags = DefaultSurfaceFlags());
     206             : 
     207             :   /**
     208             :    * Records decoding results, sends out any final notifications, updates the
     209             :    * state of this image, and records telemetry.
     210             :    *
     211             :    * Main-thread only.
     212             :    *
     213             :    * @param aStatus       Final status information about the decoder. (Whether it
     214             :    *                      encountered an error, etc.)
     215             :    * @param aMetadata     Metadata about this image that the decoder gathered.
     216             :    * @param aTelemetry    Telemetry data about the decoder.
     217             :    * @param aProgress     Any final progress notifications to send.
     218             :    * @param aInvalidRect  Any final invalidation rect to send.
     219             :    * @param aFrameCount   If Some(), a final updated count of the number of frames
     220             :    *                      of animation the decoder has finished decoding so far.
     221             :    *                      This is a lower bound for the total number of animation
     222             :    *                      frames this image has.
     223             :    * @param aDecoderFlags The decoder flags used by the decoder.
     224             :    * @param aSurfaceFlags The surface flags used by the decoder.
     225             :    */
     226             :   void NotifyDecodeComplete(const DecoderFinalStatus& aStatus,
     227             :                             const ImageMetadata& aMetadata,
     228             :                             const DecoderTelemetry& aTelemetry,
     229             :                             Progress aProgress,
     230             :                             const gfx::IntRect& aInvalidRect,
     231             :                             const Maybe<uint32_t>& aFrameCount,
     232             :                             DecoderFlags aDecoderFlags,
     233             :                             SurfaceFlags aSurfaceFlags);
     234             : 
     235             :   // Helper method for NotifyDecodeComplete.
     236             :   void ReportDecoderError();
     237             : 
     238             : 
     239             :   //////////////////////////////////////////////////////////////////////////////
     240             :   // Network callbacks.
     241             :   //////////////////////////////////////////////////////////////////////////////
     242             : 
     243             :   virtual nsresult OnImageDataAvailable(nsIRequest* aRequest,
     244             :                                         nsISupports* aContext,
     245             :                                         nsIInputStream* aInStr,
     246             :                                         uint64_t aSourceOffset,
     247             :                                         uint32_t aCount) override;
     248             :   virtual nsresult OnImageDataComplete(nsIRequest* aRequest,
     249             :                                        nsISupports* aContext,
     250             :                                        nsresult aStatus,
     251             :                                        bool aLastPart) override;
     252             : 
     253             :   void NotifyForLoadEvent(Progress aProgress);
     254             : 
     255             :   /**
     256             :    * A hint of the number of bytes of source data that the image contains. If
     257             :    * called early on, this can help reduce copying and reallocations by
     258             :    * appropriately preallocating the source data buffer.
     259             :    *
     260             :    * We take this approach rather than having the source data management code do
     261             :    * something more complicated (like chunklisting) because HTTP is by far the
     262             :    * dominant source of images, and the Content-Length header is quite reliable.
     263             :    * Thus, pre-allocation simplifies code and reduces the total number of
     264             :    * allocations.
     265             :    */
     266             :   nsresult SetSourceSizeHint(uint32_t aSizeHint);
     267             : 
     268          14 :  nsCString GetURIString() {
     269          14 :     nsCString spec;
     270          14 :     if (GetURI()) {
     271          14 :       GetURI()->GetSpec(spec);
     272             :     }
     273          14 :     return spec;
     274             :   }
     275             : 
     276             : private:
     277             :   nsresult Init(const char* aMimeType, uint32_t aFlags);
     278             : 
     279             :   /**
     280             :    * Tries to retrieve a surface for this image with size @aSize, surface flags
     281             :    * matching @aFlags, and a playback type of @aPlaybackType.
     282             :    *
     283             :    * If @aFlags specifies FLAG_SYNC_DECODE and we already have all the image
     284             :    * data, we'll attempt a sync decode if no matching surface is found. If
     285             :    * FLAG_SYNC_DECODE was not specified and no matching surface was found, we'll
     286             :    * kick off an async decode so that the surface is (hopefully) available next
     287             :    * time it's requested.
     288             :    *
     289             :    * @return a drawable surface, which may be empty if the requested surface
     290             :    *         could not be found.
     291             :    */
     292             :   DrawableSurface LookupFrame(const gfx::IntSize& aSize,
     293             :                               uint32_t aFlags,
     294             :                               PlaybackType aPlaybackType);
     295             : 
     296             :   /// Helper method for LookupFrame().
     297             :   LookupResult LookupFrameInternal(const gfx::IntSize& aSize,
     298             :                                    uint32_t aFlags,
     299             :                                    PlaybackType aPlaybackType);
     300             : 
     301             :   DrawResult DrawInternal(DrawableSurface&& aFrameRef,
     302             :                           gfxContext* aContext,
     303             :                           const nsIntSize& aSize,
     304             :                           const ImageRegion& aRegion,
     305             :                           gfx::SamplingFilter aSamplingFilter,
     306             :                           uint32_t aFlags,
     307             :                           float aOpacity);
     308             : 
     309             :   Pair<DrawResult, RefPtr<gfx::SourceSurface>>
     310             :     GetFrameInternal(const gfx::IntSize& aSize,
     311             :                      uint32_t aWhichFrame,
     312             :                      uint32_t aFlags);
     313             : 
     314             :   Pair<DrawResult, RefPtr<layers::Image>>
     315             :     GetCurrentImage(layers::ImageContainer* aContainer, uint32_t aFlags);
     316             : 
     317             :   void UpdateImageContainer();
     318             : 
     319             :   //////////////////////////////////////////////////////////////////////////////
     320             :   // Decoding.
     321             :   //////////////////////////////////////////////////////////////////////////////
     322             : 
     323             :   /**
     324             :    * Creates and runs a decoder, either synchronously or asynchronously
     325             :    * according to @aFlags. Decodes at the provided target size @aSize, using
     326             :    * decode flags @aFlags. Performs a single-frame decode of this image unless
     327             :    * we know the image is animated *and* @aPlaybackType is
     328             :    * PlaybackType::eAnimated.
     329             :    *
     330             :    * It's an error to call Decode() before this image's intrinsic size is
     331             :    * available. A metadata decode must successfully complete first.
     332             :    *
     333             :    * Returns true of the decode was run synchronously.
     334             :    */
     335             :   bool Decode(const gfx::IntSize& aSize,
     336             :               uint32_t aFlags,
     337             :               PlaybackType aPlaybackType);
     338             : 
     339             :   /**
     340             :    * Creates and runs a metadata decoder, either synchronously or
     341             :    * asynchronously according to @aFlags.
     342             :    */
     343             :   NS_IMETHOD DecodeMetadata(uint32_t aFlags);
     344             : 
     345             :   /**
     346             :    * Sets the size, inherent orientation, animation metadata, and other
     347             :    * information about the image gathered during decoding.
     348             :    *
     349             :    * This function may be called multiple times, but will throw an error if
     350             :    * subsequent calls do not match the first.
     351             :    *
     352             :    * @param aMetadata The metadata to set on this image.
     353             :    * @param aFromMetadataDecode True if this metadata came from a metadata
     354             :    *                            decode; false if it came from a full decode.
     355             :    * @return |true| unless a catastrophic failure was discovered. If |false| is
     356             :    * returned, it indicates that the image is corrupt in a way that requires all
     357             :    * surfaces to be discarded to recover.
     358             :    */
     359             :   bool SetMetadata(const ImageMetadata& aMetadata, bool aFromMetadataDecode);
     360             : 
     361             :   /**
     362             :    * In catastrophic circumstances like a GPU driver crash, the contents of our
     363             :    * frames may become invalid.  If the information we gathered during the
     364             :    * metadata decode proves to be wrong due to image corruption, the frames we
     365             :    * have may violate this class's invariants. Either way, we need to
     366             :    * immediately discard the invalid frames and redecode so that callers don't
     367             :    * perceive that we've entered an invalid state.
     368             :    *
     369             :    * RecoverFromInvalidFrames discards all existing frames and redecodes using
     370             :    * the provided @aSize and @aFlags.
     371             :    */
     372             :   void RecoverFromInvalidFrames(const nsIntSize& aSize, uint32_t aFlags);
     373             : 
     374             :   void OnSurfaceDiscardedInternal(bool aAnimatedFramesDiscarded);
     375             : 
     376             : private: // data
     377             :   nsIntSize                  mSize;
     378             :   nsTArray<nsIntSize>        mNativeSizes;
     379             :   Orientation                mOrientation;
     380             : 
     381             :   /// If this has a value, we're waiting for SetSize() to send the load event.
     382             :   Maybe<Progress>            mLoadProgress;
     383             : 
     384             :   nsCOMPtr<nsIProperties>   mProperties;
     385             : 
     386             :   /// If this image is animated, a FrameAnimator which manages its animation.
     387             :   UniquePtr<FrameAnimator> mFrameAnimator;
     388             : 
     389             :   /// Animation timeline and other state for animation images.
     390             :   Maybe<AnimationState> mAnimationState;
     391             : 
     392             :   // Image locking.
     393             :   uint32_t                   mLockCount;
     394             : 
     395             :   // The type of decoder this image needs. Computed from the MIME type in Init().
     396             :   DecoderType                mDecoderType;
     397             : 
     398             :   // How many times we've decoded this image.
     399             :   // This is currently only used for statistics
     400             :   int32_t                        mDecodeCount;
     401             : 
     402             :   // A weak pointer to our ImageContainer, which stays alive only as long as
     403             :   // the layer system needs it.
     404             :   WeakPtr<layers::ImageContainer> mImageContainer;
     405             : 
     406             :   layers::ImageContainer::ProducerID mImageProducerID;
     407             :   layers::ImageContainer::FrameID mLastFrameID;
     408             : 
     409             :   // If mImageContainer is non-null, this contains the DrawResult we obtained
     410             :   // the last time we updated it.
     411             :   DrawResult mLastImageContainerDrawResult;
     412             : 
     413             : #ifdef DEBUG
     414             :   uint32_t                       mFramesNotified;
     415             : #endif
     416             : 
     417             :   // The source data for this image.
     418             :   NotNull<RefPtr<SourceBuffer>>  mSourceBuffer;
     419             : 
     420             :   // Boolean flags (clustered together to conserve space):
     421             :   bool                       mHasSize:1;        // Has SetSize() been called?
     422             :   bool                       mTransient:1;      // Is the image short-lived?
     423             :   bool                       mSyncLoad:1;       // Are we loading synchronously?
     424             :   bool                       mDiscardable:1;    // Is container discardable?
     425             :   bool                       mSomeSourceData:1; // Do we have some source data?
     426             :   bool                       mAllSourceData:1;  // Do we have all the source data?
     427             :   bool                       mHasBeenDecoded:1; // Decoded at least once?
     428             : 
     429             :   // Whether we're waiting to start animation. If we get a StartAnimation() call
     430             :   // but we don't yet have more than one frame, mPendingAnimation is set so that
     431             :   // we know to start animation later if/when we have more frames.
     432             :   bool                       mPendingAnimation:1;
     433             : 
     434             :   // Whether the animation can stop, due to running out
     435             :   // of frames, or no more owning request
     436             :   bool                       mAnimationFinished:1;
     437             : 
     438             :   // Whether, once we are done doing a metadata decode, we should immediately
     439             :   // kick off a full decode.
     440             :   bool                       mWantFullDecode:1;
     441             : 
     442             :   TimeStamp mDrawStartTime;
     443             : 
     444             : 
     445             :   //////////////////////////////////////////////////////////////////////////////
     446             :   // Scaling.
     447             :   //////////////////////////////////////////////////////////////////////////////
     448             : 
     449             :   // Determines whether we can downscale during decode with the given
     450             :   // parameters.
     451             :   bool CanDownscaleDuringDecode(const nsIntSize& aSize, uint32_t aFlags);
     452             : 
     453             : 
     454             :   // Error handling.
     455             :   void DoError();
     456             : 
     457           0 :   class HandleErrorWorker : public Runnable
     458             :   {
     459             :   public:
     460             :     /**
     461             :      * Called from decoder threads when DoError() is called, since errors can't
     462             :      * be handled safely off-main-thread. Dispatches an event which reinvokes
     463             :      * DoError on the main thread if there isn't one already pending.
     464             :      */
     465             :     static void DispatchIfNeeded(RasterImage* aImage);
     466             : 
     467             :     NS_IMETHOD Run();
     468             : 
     469             :   private:
     470             :     explicit HandleErrorWorker(RasterImage* aImage);
     471             : 
     472             :     RefPtr<RasterImage> mImage;
     473             :   };
     474             : 
     475             :   // Helpers
     476             :   bool CanDiscard();
     477             : 
     478             :   bool IsOpaque();
     479             : 
     480             :   DrawableSurface RequestDecodeForSizeInternal(const gfx::IntSize& aSize, uint32_t aFlags);
     481             : 
     482             : protected:
     483             :   explicit RasterImage(ImageURL* aURI = nullptr);
     484             : 
     485             :   bool ShouldAnimate() override;
     486             : 
     487             :   friend class ImageFactory;
     488             : };
     489             : 
     490             : inline NS_IMETHODIMP
     491           0 : RasterImage::GetAnimationMode(uint16_t* aAnimationMode) {
     492           0 :   return GetAnimationModeInternal(aAnimationMode);
     493             : }
     494             : 
     495             : } // namespace image
     496             : } // namespace mozilla
     497             : 
     498             : /**
     499             :  * Casting RasterImage to nsISupports is ambiguous. This method handles that.
     500             :  */
     501             : inline nsISupports*
     502          33 : ToSupports(mozilla::image::RasterImage* p)
     503             : {
     504          33 :   return NS_ISUPPORTS_CAST(mozilla::image::ImageResource*, p);
     505             : }
     506             : 
     507             : #endif /* mozilla_image_RasterImage_h */

Generated by: LCOV version 1.13