LCOV - code coverage report
Current view: top level - image - ISurfaceProvider.h (source / functions) Hit Total Coverage
Test: output.info Lines: 63 76 82.9 %
Date: 2017-07-14 16:53:18 Functions: 23 29 79.3 %
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             : /**
       7             :  * An interface for objects which can either store a surface or dynamically
       8             :  * generate one, and various implementations.
       9             :  */
      10             : 
      11             : #ifndef mozilla_image_ISurfaceProvider_h
      12             : #define mozilla_image_ISurfaceProvider_h
      13             : 
      14             : #include "mozilla/Attributes.h"
      15             : #include "mozilla/Maybe.h"
      16             : #include "mozilla/MemoryReporting.h"
      17             : #include "mozilla/NotNull.h"
      18             : #include "mozilla/TimeStamp.h"
      19             : #include "mozilla/Variant.h"
      20             : #include "mozilla/gfx/2D.h"
      21             : 
      22             : #include "imgFrame.h"
      23             : #include "SurfaceCache.h"
      24             : 
      25             : namespace mozilla {
      26             : namespace image {
      27             : 
      28             : class CachedSurface;
      29             : class DrawableSurface;
      30             : 
      31             : /**
      32             :  * An interface for objects which can either store a surface or dynamically
      33             :  * generate one.
      34             :  */
      35             : class ISurfaceProvider
      36             : {
      37             : public:
      38             :   // Subclasses may or may not be XPCOM classes, so we just require that they
      39             :   // implement AddRef and Release.
      40             :   NS_INLINE_DECL_PURE_VIRTUAL_REFCOUNTING
      41             : 
      42             :   /// @return key data used for identifying which image this ISurfaceProvider is
      43             :   /// associated with in the surface cache.
      44         120 :   ImageKey GetImageKey() const { return mImageKey; }
      45             : 
      46             :   /// @return key data used to uniquely identify this ISurfaceProvider's cache
      47             :   /// entry in the surface cache.
      48         317 :   const SurfaceKey& GetSurfaceKey() const { return mSurfaceKey; }
      49             : 
      50             :   /// @return a (potentially lazily computed) drawable reference to a surface.
      51             :   virtual DrawableSurface Surface();
      52             : 
      53             :   /// @return true if DrawableRef() will return a completely decoded surface.
      54             :   virtual bool IsFinished() const = 0;
      55             : 
      56             :   /// @return the number of bytes of memory this ISurfaceProvider is expected to
      57             :   /// require. Optimizations may result in lower real memory usage. Trivial
      58             :   /// overhead is ignored. Because this value is used in bookkeeping, it's
      59             :   /// important that it be constant over the lifetime of this object.
      60             :   virtual size_t LogicalSizeInBytes() const = 0;
      61             : 
      62             :   /// @return the actual number of bytes of memory this ISurfaceProvider is
      63             :   /// using. May vary over the lifetime of the ISurfaceProvider. The default
      64             :   /// implementation is appropriate for static ISurfaceProviders.
      65           0 :   virtual void AddSizeOfExcludingThis(MallocSizeOf aMallocSizeOf,
      66             :                                       size_t& aHeapSizeOut,
      67             :                                       size_t& aNonHeapSizeOut,
      68             :                                       size_t& aSharedHandlesOut)
      69             :   {
      70           0 :     DrawableFrameRef ref = DrawableRef(/* aFrame = */ 0);
      71           0 :     if (!ref) {
      72           0 :       return;
      73             :     }
      74             : 
      75           0 :     ref->AddSizeOfExcludingThis(aMallocSizeOf, aHeapSizeOut,
      76           0 :                                 aNonHeapSizeOut, aSharedHandlesOut);
      77             :   }
      78             : 
      79             :   /// @return the availability state of this ISurfaceProvider, which indicates
      80             :   /// whether DrawableRef() could successfully return a surface. Should only be
      81             :   /// called from SurfaceCache code as it relies on SurfaceCache for
      82             :   /// synchronization.
      83         961 :   AvailabilityState& Availability() { return mAvailability; }
      84          24 :   const AvailabilityState& Availability() const { return mAvailability; }
      85             : 
      86             : protected:
      87          32 :   ISurfaceProvider(const ImageKey aImageKey,
      88             :                    const SurfaceKey& aSurfaceKey,
      89             :                    AvailabilityState aAvailability)
      90          32 :     : mImageKey(aImageKey)
      91             :     , mSurfaceKey(aSurfaceKey)
      92          32 :     , mAvailability(aAvailability)
      93             :   {
      94          32 :     MOZ_ASSERT(aImageKey, "Must have a valid image key");
      95          32 :   }
      96             : 
      97           0 :   virtual ~ISurfaceProvider() { }
      98             : 
      99             :   /// @return an eagerly computed drawable reference to a surface. For
     100             :   /// dynamically generated animation surfaces, @aFrame specifies the 0-based
     101             :   /// index of the desired frame.
     102             :   virtual DrawableFrameRef DrawableRef(size_t aFrame) = 0;
     103             : 
     104             :   /// @return true if this ISurfaceProvider is locked. (@see SetLocked())
     105             :   /// Should only be called from SurfaceCache code as it relies on SurfaceCache
     106             :   /// for synchronization.
     107             :   virtual bool IsLocked() const = 0;
     108             : 
     109             :   /// If @aLocked is true, hint that this ISurfaceProvider is in use and it
     110             :   /// should avoid releasing its resources. Should only be called from
     111             :   /// SurfaceCache code as it relies on SurfaceCache for synchronization.
     112             :   virtual void SetLocked(bool aLocked) = 0;
     113             : 
     114             : private:
     115             :   friend class CachedSurface;
     116             :   friend class DrawableSurface;
     117             : 
     118             :   const ImageKey mImageKey;
     119             :   const SurfaceKey mSurfaceKey;
     120             :   AvailabilityState mAvailability;
     121             : };
     122             : 
     123             : 
     124             : /**
     125             :  * A reference to a surface (stored in an imgFrame) that holds the surface in
     126             :  * memory, guaranteeing that it can be drawn. If you have a DrawableSurface
     127             :  * |surf| and |if (surf)| returns true, then calls to |surf->Draw()| and
     128             :  * |surf->GetSourceSurface()| are guaranteed to succeed.
     129             :  *
     130             :  * Note that the surface may be computed lazily, so a DrawableSurface should not
     131             :  * be dereferenced (i.e., operator->() should not be called) until you're
     132             :  * sure that you want to draw it.
     133             :  */
     134         408 : class MOZ_STACK_CLASS DrawableSurface final
     135             : {
     136             : public:
     137         115 :   DrawableSurface() : mHaveSurface(false) { }
     138             : 
     139          98 :   explicit DrawableSurface(DrawableFrameRef&& aDrawableRef)
     140          98 :     : mDrawableRef(Move(aDrawableRef))
     141          98 :     , mHaveSurface(bool(mDrawableRef))
     142          98 :   { }
     143             : 
     144          23 :   explicit DrawableSurface(NotNull<ISurfaceProvider*> aProvider)
     145          23 :     : mProvider(aProvider)
     146          23 :     , mHaveSurface(true)
     147          23 :   { }
     148             : 
     149         172 :   DrawableSurface(DrawableSurface&& aOther)
     150         172 :     : mDrawableRef(Move(aOther.mDrawableRef))
     151         172 :     , mProvider(Move(aOther.mProvider))
     152         344 :     , mHaveSurface(aOther.mHaveSurface)
     153             :   {
     154         172 :     aOther.mHaveSurface = false;
     155         172 :   }
     156             : 
     157          27 :   DrawableSurface& operator=(DrawableSurface&& aOther)
     158             :   {
     159          27 :     MOZ_ASSERT(this != &aOther, "Self-moves are prohibited");
     160          27 :     mDrawableRef = Move(aOther.mDrawableRef);
     161          27 :     mProvider = Move(aOther.mProvider);
     162          27 :     mHaveSurface = aOther.mHaveSurface;
     163          27 :     aOther.mHaveSurface = false;
     164          27 :     return *this;
     165             :   }
     166             : 
     167             :   /**
     168             :    * If this DrawableSurface is dynamically generated from an animation, attempt
     169             :    * to seek to frame @aFrame, where @aFrame is a 0-based index into the frames
     170             :    * of the animation. Otherwise, nothing will blow up at runtime, but we assert
     171             :    * in debug builds, since calling this in an unexpected situation probably
     172             :    * indicates a bug.
     173             :    *
     174             :    * @return a successful result if we could obtain frame @aFrame. Note that
     175             :    * |mHaveSurface| being true means that we're guaranteed to have *some* frame,
     176             :    * so the caller can dereference this DrawableSurface even if Seek() fails,
     177             :    * but while nothing will blow up, the frame won't be the one they expect.
     178             :    */
     179         156 :   nsresult Seek(size_t aFrame)
     180             :   {
     181         156 :     MOZ_ASSERT(mHaveSurface, "Trying to seek an empty DrawableSurface?");
     182             : 
     183         156 :     if (!mProvider) {
     184           0 :       MOZ_ASSERT_UNREACHABLE("Trying to seek a static DrawableSurface?");
     185             :       return NS_ERROR_FAILURE;
     186             :     }
     187             : 
     188         156 :     mDrawableRef = mProvider->DrawableRef(aFrame);
     189             : 
     190         156 :     return mDrawableRef ? NS_OK : NS_ERROR_FAILURE;
     191             :   }
     192             : 
     193         647 :   explicit operator bool() const { return mHaveSurface; }
     194         496 :   imgFrame* operator->() { return DrawableRef().get(); }
     195             : 
     196             : private:
     197             :   DrawableSurface(const DrawableSurface& aOther) = delete;
     198             :   DrawableSurface& operator=(const DrawableSurface& aOther) = delete;
     199             : 
     200         496 :   DrawableFrameRef& DrawableRef()
     201             :   {
     202         496 :     MOZ_ASSERT(mHaveSurface);
     203             : 
     204             :     // If we weren't created with a DrawableFrameRef directly, we should've been
     205             :     // created with an ISurfaceProvider which can give us one. Note that if
     206             :     // Seek() has been called, we'll already have a DrawableFrameRef, so we
     207             :     // won't need to get one here.
     208         496 :     if (!mDrawableRef) {
     209           0 :       MOZ_ASSERT(mProvider);
     210           0 :       mDrawableRef = mProvider->DrawableRef(/* aFrame = */ 0);
     211             :     }
     212             : 
     213         496 :     MOZ_ASSERT(mDrawableRef);
     214         496 :     return mDrawableRef;
     215             :   }
     216             : 
     217             :   DrawableFrameRef mDrawableRef;
     218             :   RefPtr<ISurfaceProvider> mProvider;
     219             :   bool mHaveSurface;
     220             : };
     221             : 
     222             : 
     223             : // Surface() is implemented here so that DrawableSurface's definition is
     224             : // visible. This default implementation eagerly obtains a DrawableFrameRef for
     225             : // the first frame and is intended for static ISurfaceProviders.
     226             : inline DrawableSurface
     227          90 : ISurfaceProvider::Surface()
     228             : {
     229          90 :   return DrawableSurface(DrawableRef(/* aFrame = */ 0));
     230             : }
     231             : 
     232             : 
     233             : /**
     234             :  * An ISurfaceProvider that stores a single surface.
     235             :  */
     236             : class SimpleSurfaceProvider final : public ISurfaceProvider
     237             : {
     238             : public:
     239          54 :   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(SimpleSurfaceProvider, override)
     240             : 
     241          18 :   SimpleSurfaceProvider(const ImageKey aImageKey,
     242             :                         const SurfaceKey& aSurfaceKey,
     243             :                         NotNull<imgFrame*> aSurface)
     244          18 :     : ISurfaceProvider(aImageKey, aSurfaceKey,
     245             :                        AvailabilityState::StartAvailable())
     246          18 :     , mSurface(aSurface)
     247             :   {
     248          18 :     MOZ_ASSERT(aSurfaceKey.Size() == mSurface->GetSize());
     249          18 :   }
     250             : 
     251           0 :   bool IsFinished() const override { return mSurface->IsFinished(); }
     252             : 
     253          36 :   size_t LogicalSizeInBytes() const override
     254             :   {
     255          36 :     gfx::IntSize size = mSurface->GetSize();
     256          36 :     return size.width * size.height * mSurface->GetBytesPerPixel();
     257             :   }
     258             : 
     259             : protected:
     260          55 :   DrawableFrameRef DrawableRef(size_t aFrame) override
     261             :   {
     262          55 :     MOZ_ASSERT(aFrame == 0,
     263             :                "Requesting an animation frame from a SimpleSurfaceProvider?");
     264          55 :     return mSurface->DrawableRef();
     265             :   }
     266             : 
     267         127 :   bool IsLocked() const override { return bool(mLockRef); }
     268             : 
     269          18 :   void SetLocked(bool aLocked) override
     270             :   {
     271          18 :     if (aLocked == IsLocked()) {
     272           0 :       return;  // Nothing changed.
     273             :     }
     274             : 
     275             :     // If we're locked, hold a DrawableFrameRef to |mSurface|, which will keep
     276             :     // any volatile buffer it owns in memory.
     277          36 :     mLockRef = aLocked ? mSurface->DrawableRef()
     278          18 :                        : DrawableFrameRef();
     279             :   }
     280             : 
     281             : private:
     282           0 :   virtual ~SimpleSurfaceProvider() { }
     283             : 
     284             :   NotNull<RefPtr<imgFrame>> mSurface;
     285             :   DrawableFrameRef mLockRef;
     286             : };
     287             : 
     288             : } // namespace image
     289             : } // namespace mozilla
     290             : 
     291             : #endif // mozilla_image_ISurfaceProvider_h

Generated by: LCOV version 1.13