LCOV - code coverage report
Current view: top level - gfx/layers - ImageContainer.h (source / functions) Hit Total Coverage
Test: output.info Lines: 1 137 0.7 %
Date: 2017-07-14 16:53:18 Functions: 1 83 1.2 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 20; 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             : #ifndef GFX_IMAGECONTAINER_H
       7             : #define GFX_IMAGECONTAINER_H
       8             : 
       9             : #include <stdint.h>                     // for uint32_t, uint8_t, uint64_t
      10             : #include <sys/types.h>                  // for int32_t
      11             : #include "gfxTypes.h"
      12             : #include "ImageTypes.h"                 // for ImageFormat, etc
      13             : #include "mozilla/Assertions.h"         // for MOZ_ASSERT_HELPER2
      14             : #include "mozilla/Mutex.h"              // for Mutex
      15             : #include "mozilla/ReentrantMonitor.h"   // for ReentrantMonitorAutoEnter, etc
      16             : #include "mozilla/TimeStamp.h"          // for TimeStamp
      17             : #include "mozilla/gfx/Point.h"          // For IntSize
      18             : #include "mozilla/layers/LayersTypes.h"  // for LayersBackend, etc
      19             : #include "mozilla/layers/CompositorTypes.h"
      20             : #include "mozilla/mozalloc.h"           // for operator delete, etc
      21             : #include "nsAutoPtr.h"                  // for nsRefPtr, nsAutoArrayPtr, etc
      22             : #include "nsAutoRef.h"                  // for nsCountedRef
      23             : #include "nsCOMPtr.h"                   // for already_AddRefed
      24             : #include "nsDebug.h"                    // for NS_ASSERTION
      25             : #include "nsISupportsImpl.h"            // for Image::Release, etc
      26             : #include "nsRect.h"                     // for mozilla::gfx::IntRect
      27             : #include "nsTArray.h"                   // for nsTArray
      28             : #include "mozilla/Atomics.h"
      29             : #include "mozilla/WeakPtr.h"
      30             : #include "nsThreadUtils.h"
      31             : #include "mozilla/gfx/2D.h"
      32             : #include "nsDataHashtable.h"
      33             : #include "mozilla/EnumeratedArray.h"
      34             : #include "mozilla/UniquePtr.h"
      35             : 
      36             : #ifndef XPCOM_GLUE_AVOID_NSPR
      37             : /**
      38             :  * We need to be able to hold a reference to a Moz2D SourceSurface from Image
      39             :  * subclasses. This is potentially a problem since Images can be addrefed
      40             :  * or released off the main thread. We can ensure that we never AddRef
      41             :  * a SourceSurface off the main thread, but we might want to Release due
      42             :  * to an Image being destroyed off the main thread.
      43             :  *
      44             :  * We use nsCountedRef<nsMainThreadSourceSurfaceRef> to reference the
      45             :  * SourceSurface. When AddRefing, we assert that we're on the main thread.
      46             :  * When Releasing, if we're not on the main thread, we post an event to
      47             :  * the main thread to do the actual release.
      48             :  */
      49             : class nsMainThreadSourceSurfaceRef;
      50             : 
      51             : template <>
      52           0 : class nsAutoRefTraits<nsMainThreadSourceSurfaceRef> {
      53             : public:
      54             :   typedef mozilla::gfx::SourceSurface* RawRef;
      55             : 
      56             :   /**
      57             :    * The XPCOM event that will do the actual release on the main thread.
      58             :    */
      59           0 :   class SurfaceReleaser : public mozilla::Runnable {
      60             :   public:
      61           0 :     explicit SurfaceReleaser(RawRef aRef)
      62           0 :       : mozilla::Runnable(
      63             :           "nsAutoRefTraits<nsMainThreadSourceSurfaceRef>::SurfaceReleaser")
      64           0 :       , mRef(aRef)
      65             :     {
      66           0 :     }
      67           0 :     NS_IMETHOD Run() override {
      68           0 :       mRef->Release();
      69           0 :       return NS_OK;
      70             :     }
      71             :     RawRef mRef;
      72             :   };
      73             : 
      74           0 :   static RawRef Void() { return nullptr; }
      75           0 :   static void Release(RawRef aRawRef)
      76             :   {
      77           0 :     if (NS_IsMainThread()) {
      78           0 :       aRawRef->Release();
      79           0 :       return;
      80             :     }
      81           0 :     nsCOMPtr<nsIRunnable> runnable = new SurfaceReleaser(aRawRef);
      82           0 :     NS_DispatchToMainThread(runnable);
      83             :   }
      84           0 :   static void AddRef(RawRef aRawRef)
      85             :   {
      86           0 :     NS_ASSERTION(NS_IsMainThread(),
      87             :                  "Can only add a reference on the main thread");
      88           0 :     aRawRef->AddRef();
      89           0 :   }
      90             : };
      91             : 
      92             : class nsOwningThreadSourceSurfaceRef;
      93             : 
      94             : template <>
      95           0 : class nsAutoRefTraits<nsOwningThreadSourceSurfaceRef> {
      96             : public:
      97             :   typedef mozilla::gfx::SourceSurface* RawRef;
      98             : 
      99             :   /**
     100             :    * The XPCOM event that will do the actual release on the creation thread.
     101             :    */
     102           0 :   class SurfaceReleaser : public mozilla::Runnable {
     103             :   public:
     104           0 :     explicit SurfaceReleaser(RawRef aRef)
     105           0 :       : mozilla::Runnable(
     106             :           "nsAutoRefTraits<nsOwningThreadSourceSurfaceRef>::SurfaceReleaser")
     107           0 :       , mRef(aRef)
     108             :     {
     109           0 :     }
     110           0 :     NS_IMETHOD Run() override {
     111           0 :       mRef->Release();
     112           0 :       return NS_OK;
     113             :     }
     114             :     RawRef mRef;
     115             :   };
     116             : 
     117           0 :   static RawRef Void() { return nullptr; }
     118           0 :   void Release(RawRef aRawRef)
     119             :   {
     120           0 :     MOZ_ASSERT(mOwningEventTarget);
     121           0 :     if (mOwningEventTarget->IsOnCurrentThread()) {
     122           0 :       aRawRef->Release();
     123           0 :       return;
     124             :     }
     125           0 :     nsCOMPtr<nsIRunnable> runnable = new SurfaceReleaser(aRawRef);
     126           0 :     mOwningEventTarget->Dispatch(runnable, nsIThread::DISPATCH_NORMAL);
     127             :   }
     128           0 :   void AddRef(RawRef aRawRef)
     129             :   {
     130           0 :     MOZ_ASSERT(!mOwningEventTarget);
     131           0 :     mOwningEventTarget = mozilla::GetCurrentThreadSerialEventTarget();
     132           0 :     aRawRef->AddRef();
     133           0 :   }
     134             : 
     135             : private:
     136             :   nsCOMPtr<nsISerialEventTarget> mOwningEventTarget;
     137             : };
     138             : 
     139             : #endif
     140             : 
     141             : #ifdef XP_WIN
     142             : struct ID3D10Texture2D;
     143             : struct ID3D10Device;
     144             : struct ID3D10ShaderResourceView;
     145             : #endif
     146             : 
     147             : typedef void* HANDLE;
     148             : 
     149             : namespace mozilla {
     150             : 
     151             : 
     152             : namespace layers {
     153             : 
     154             : class ImageClient;
     155             : class ImageCompositeNotification;
     156             : class ImageContainer;
     157             : class ImageContainerChild;
     158             : class SharedPlanarYCbCrImage;
     159             : class PlanarYCbCrImage;
     160             : class TextureClient;
     161             : class KnowsCompositor;
     162             : class NVImage;
     163             : #ifdef XP_WIN
     164             : class D3D11YCbCrRecycleAllocator;
     165             : #endif
     166             : 
     167             : struct ImageBackendData
     168             : {
     169             :   virtual ~ImageBackendData() {}
     170             : 
     171             : protected:
     172             :   ImageBackendData() {}
     173             : };
     174             : 
     175             : /* Forward declarations for Image derivatives. */
     176             : class GLImage;
     177             : class EGLImageImage;
     178             : class SharedRGBImage;
     179             : #ifdef MOZ_WIDGET_ANDROID
     180             : class SurfaceTextureImage;
     181             : #elif defined(XP_MACOSX)
     182             : class MacIOSurfaceImage;
     183             : #endif
     184             : 
     185             : /**
     186             :  * A class representing a buffer of pixel data. The data can be in one
     187             :  * of various formats including YCbCr.
     188             :  *
     189             :  * Create an image using an ImageContainer. Fill the image with data, and
     190             :  * then call ImageContainer::SetImage to display it. An image must not be
     191             :  * modified after calling SetImage. Image implementations do not need to
     192             :  * perform locking; when filling an Image, the Image client is responsible
     193             :  * for ensuring only one thread accesses the Image at a time, and after
     194             :  * SetImage the image is immutable.
     195             :  *
     196             :  * When resampling an Image, only pixels within the buffer should be
     197             :  * sampled. For example, cairo images should be sampled in EXTEND_PAD mode.
     198             :  */
     199             : class Image {
     200           0 :   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(Image)
     201             : 
     202             : public:
     203           0 :   ImageFormat GetFormat() { return mFormat; }
     204             :   void* GetImplData() { return mImplData; }
     205             : 
     206             :   virtual gfx::IntSize GetSize() = 0;
     207           0 :   virtual gfx::IntPoint GetOrigin()
     208             :   {
     209           0 :     return gfx::IntPoint(0, 0);
     210             :   }
     211           0 :   virtual gfx::IntRect GetPictureRect()
     212             :   {
     213           0 :     return gfx::IntRect(GetOrigin().x, GetOrigin().y, GetSize().width, GetSize().height);
     214             :   }
     215             : 
     216             :   ImageBackendData* GetBackendData(LayersBackend aBackend)
     217             :   { return mBackendData[aBackend]; }
     218             :   void SetBackendData(LayersBackend aBackend, ImageBackendData* aData)
     219             :   { mBackendData[aBackend] = aData; }
     220             : 
     221           0 :   int32_t GetSerial() { return mSerial; }
     222             : 
     223             :   virtual already_AddRefed<gfx::SourceSurface> GetAsSourceSurface() = 0;
     224             : 
     225           0 :   virtual bool IsValid() { return true; }
     226             : 
     227           0 :   virtual uint8_t* GetBuffer() { return nullptr; }
     228             : 
     229             :   /**
     230             :    * For use with the TextureForwarder only (so that the later can
     231             :    * synchronize the TextureClient with the TextureHost).
     232             :    */
     233           0 :   virtual TextureClient* GetTextureClient(KnowsCompositor* aForwarder) { return nullptr; }
     234             : 
     235             :   /* Access to derived classes. */
     236           0 :   virtual EGLImageImage* AsEGLImageImage() { return nullptr; }
     237           0 :   virtual GLImage* AsGLImage() { return nullptr; }
     238             : #ifdef MOZ_WIDGET_ANDROID
     239             :   virtual SurfaceTextureImage* AsSurfaceTextureImage() { return nullptr; }
     240             : #endif
     241             : #ifdef XP_MACOSX
     242             :   virtual MacIOSurfaceImage* AsMacIOSurfaceImage() { return nullptr; }
     243             : #endif
     244           0 :   virtual PlanarYCbCrImage* AsPlanarYCbCrImage() { return nullptr; }
     245             : 
     246           0 :   virtual NVImage* AsNVImage() { return nullptr; }
     247             : 
     248             : protected:
     249           0 :   Image(void* aImplData, ImageFormat aFormat) :
     250             :     mImplData(aImplData),
     251           0 :     mSerial(++sSerialCounter),
     252           0 :     mFormat(aFormat)
     253           0 :   {}
     254             : 
     255             :   // Protected destructor, to discourage deletion outside of Release():
     256           0 :   virtual ~Image() {}
     257             : 
     258             :   mozilla::EnumeratedArray<mozilla::layers::LayersBackend,
     259             :                            mozilla::layers::LayersBackend::LAYERS_LAST,
     260             :                            nsAutoPtr<ImageBackendData>>
     261             :     mBackendData;
     262             : 
     263             :   void* mImplData;
     264             :   int32_t mSerial;
     265             :   ImageFormat mFormat;
     266             : 
     267             :   static mozilla::Atomic<int32_t> sSerialCounter;
     268             : };
     269             : 
     270             : /**
     271             :  * A RecycleBin is owned by an ImageContainer. We store buffers in it that we
     272             :  * want to recycle from one image to the next.It's a separate object from
     273             :  * ImageContainer because images need to store a strong ref to their RecycleBin
     274             :  * and we must avoid creating a reference loop between an ImageContainer and
     275             :  * its active image.
     276             :  */
     277             : class BufferRecycleBin final {
     278           0 :   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(BufferRecycleBin)
     279             : 
     280             :   //typedef mozilla::gl::GLContext GLContext;
     281             : 
     282             : public:
     283             :   BufferRecycleBin();
     284             : 
     285             :   void RecycleBuffer(mozilla::UniquePtr<uint8_t[]> aBuffer, uint32_t aSize);
     286             :   // Returns a recycled buffer of the right size, or allocates a new buffer.
     287             :   mozilla::UniquePtr<uint8_t[]> GetBuffer(uint32_t aSize);
     288             :   virtual void ClearRecycledBuffers();
     289             : private:
     290             :   typedef mozilla::Mutex Mutex;
     291             : 
     292             :   // Private destructor, to discourage deletion outside of Release():
     293           0 :   ~BufferRecycleBin()
     294           0 :   {
     295           0 :   }
     296             : 
     297             :   // This protects mRecycledBuffers, mRecycledBufferSize, mRecycledTextures
     298             :   // and mRecycledTextureSizes
     299             :   Mutex mLock;
     300             : 
     301             :   // We should probably do something to prune this list on a timer so we don't
     302             :   // eat excess memory while video is paused...
     303             :   nsTArray<mozilla::UniquePtr<uint8_t[]>> mRecycledBuffers;
     304             :   // This is only valid if mRecycledBuffers is non-empty
     305             :   uint32_t mRecycledBufferSize;
     306             : };
     307             : 
     308             : /**
     309             :  * A class that manages Image creation for a LayerManager. The only reason
     310             :  * we need a separate class here is that LayerManagers aren't threadsafe
     311             :  * (because layers can only be used on the main thread) and we want to
     312             :  * be able to create images from any thread, to facilitate video playback
     313             :  * without involving the main thread, for example.
     314             :  * Different layer managers can implement child classes of this making it
     315             :  * possible to create layer manager specific images.
     316             :  * This class is not meant to be used directly but rather can be set on an
     317             :  * image container. This is usually done by the layer system internally and
     318             :  * not explicitly by users. For PlanarYCbCr or Cairo images the default
     319             :  * implementation will creates images whose data lives in system memory, for
     320             :  * MacIOSurfaces the default implementation will be a simple MacIOSurface
     321             :  * wrapper.
     322             :  */
     323             : 
     324             : class ImageFactory
     325             : {
     326           0 :   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(ImageFactory)
     327             : protected:
     328             :   friend class ImageContainer;
     329             : 
     330           0 :   ImageFactory() {}
     331           0 :   virtual ~ImageFactory() {}
     332             : 
     333             :   virtual RefPtr<PlanarYCbCrImage> CreatePlanarYCbCrImage(
     334             :     const gfx::IntSize& aScaleHint,
     335             :     BufferRecycleBin *aRecycleBin);
     336             : };
     337             : 
     338             : // Used to notify ImageContainer::NotifyComposite()
     339             : class ImageContainerListener final {
     340           0 :   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(ImageContainerListener)
     341             : 
     342             : public:
     343             :   explicit ImageContainerListener(ImageContainer* aImageContainer);
     344             : 
     345             :   void NotifyComposite(const ImageCompositeNotification& aNotification);
     346             :   void ClearImageContainer();
     347             : private:
     348             :   typedef mozilla::Mutex Mutex;
     349             : 
     350             :   ~ImageContainerListener();
     351             : 
     352             :   Mutex mLock;
     353             :   ImageContainer* mImageContainer;
     354             : };
     355             : 
     356             : /**
     357             :  * A class that manages Images for an ImageLayer. The only reason
     358             :  * we need a separate class here is that ImageLayers aren't threadsafe
     359             :  * (because layers can only be used on the main thread) and we want to
     360             :  * be able to set the current Image from any thread, to facilitate
     361             :  * video playback without involving the main thread, for example.
     362             :  *
     363             :  * An ImageContainer can operate in one of these modes:
     364             :  * 1) Normal. Triggered by constructing the ImageContainer with
     365             :  * DISABLE_ASYNC or when compositing is happening on the main thread.
     366             :  * SetCurrentImages changes ImageContainer state but nothing is sent to the
     367             :  * compositor until the next layer transaction.
     368             :  * 2) Asynchronous. Initiated by constructing the ImageContainer with
     369             :  * ENABLE_ASYNC when compositing is happening on the main thread.
     370             :  * SetCurrentImages sends a message through the ImageBridge to the compositor
     371             :  * thread to update the image, without going through the main thread or
     372             :  * a layer transaction.
     373             :  * The ImageContainer uses a shared memory block containing a cross-process mutex
     374             :  * to communicate with the compositor thread. SetCurrentImage synchronously
     375             :  * updates the shared state to point to the new image and the old image
     376             :  * is immediately released (not true in Normal or Asynchronous modes).
     377             :  */
     378             : class ImageContainer final : public SupportsWeakPtr<ImageContainer>
     379             : {
     380             :   friend class ImageContainerChild;
     381             : 
     382           0 :   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(ImageContainer)
     383             : 
     384             : public:
     385          21 :   MOZ_DECLARE_WEAKREFERENCE_TYPENAME(ImageContainer)
     386             : 
     387             :   enum Mode { SYNCHRONOUS = 0x0, ASYNCHRONOUS = 0x01 };
     388             : 
     389             :   static const uint64_t sInvalidAsyncContainerId = 0;
     390             : 
     391             :   explicit ImageContainer(ImageContainer::Mode flag = SYNCHRONOUS);
     392             : 
     393             :   /**
     394             :    * Create ImageContainer just to hold another ASYNCHRONOUS ImageContainer's
     395             :    * async container ID.
     396             :    * @param aAsyncContainerID async container ID for which we are a proxy
     397             :    */
     398             :   explicit ImageContainer(const CompositableHandle& aHandle);
     399             : 
     400             :   typedef uint32_t FrameID;
     401             :   typedef uint32_t ProducerID;
     402             : 
     403             :   RefPtr<PlanarYCbCrImage> CreatePlanarYCbCrImage();
     404             : 
     405             :   // Factory methods for shared image types.
     406             :   RefPtr<SharedRGBImage> CreateSharedRGBImage();
     407             : 
     408             :   struct NonOwningImage {
     409           0 :     explicit NonOwningImage(Image* aImage = nullptr,
     410             :                             TimeStamp aTimeStamp = TimeStamp(),
     411             :                             FrameID aFrameID = 0,
     412             :                             ProducerID aProducerID = 0)
     413           0 :       : mImage(aImage), mTimeStamp(aTimeStamp), mFrameID(aFrameID),
     414           0 :         mProducerID(aProducerID) {}
     415             :     Image* mImage;
     416             :     TimeStamp mTimeStamp;
     417             :     FrameID mFrameID;
     418             :     ProducerID mProducerID;
     419             :   };
     420             :   /**
     421             :    * Set aImages as the list of timestamped to display. The Images must have
     422             :    * been created by this ImageContainer.
     423             :    * Can be called on any thread. This method takes mReentrantMonitor
     424             :    * when accessing thread-shared state.
     425             :    * aImages must be non-empty. The first timestamp in the list may be
     426             :    * null but the others must not be, and the timestamps must increase.
     427             :    * Every element of aImages must have non-null mImage.
     428             :    * mFrameID can be zero, in which case you won't get meaningful
     429             :    * painted/dropped frame counts. Otherwise you should use a unique and
     430             :    * increasing ID for each decoded and submitted frame (but it's OK to
     431             :    * pass the same frame to SetCurrentImages).
     432             :    * mProducerID is a unique ID for the stream of images. A change in the
     433             :    * mProducerID means changing to a new mFrameID namespace. All frames in
     434             :    * aImages must have the same mProducerID.
     435             :    *
     436             :    * The Image data must not be modified after this method is called!
     437             :    * Note that this must not be called if ENABLE_ASYNC has not been set.
     438             :    *
     439             :    * The implementation calls CurrentImageChanged() while holding
     440             :    * mReentrantMonitor.
     441             :    *
     442             :    * If this ImageContainer has an ImageClient for async video:
     443             :    * Schedule a task to send the image to the compositor using the
     444             :    * PImageBridge protcol without using the main thread.
     445             :    */
     446             :   void SetCurrentImages(const nsTArray<NonOwningImage>& aImages);
     447             : 
     448             :   /**
     449             :    * Clear all images. Let ImageClient release all TextureClients.
     450             :    */
     451             :   void ClearAllImages();
     452             : 
     453             :   /**
     454             :    * Clear any resources that are not immediately necessary. This may be called
     455             :    * in low-memory conditions.
     456             :    */
     457             :   void ClearCachedResources();
     458             : 
     459             :   /**
     460             :    * Clear the current images.
     461             :    * This function is expect to be called only from a CompositableClient
     462             :    * that belongs to ImageBridgeChild. Created to prevent dead lock.
     463             :    * See Bug 901224.
     464             :    */
     465             :   void ClearImagesFromImageBridge();
     466             : 
     467             :   /**
     468             :    * Set an Image as the current image to display. The Image must have
     469             :    * been created by this ImageContainer.
     470             :    * Must be called on the main thread, within a layers transaction.
     471             :    *
     472             :    * This method takes mReentrantMonitor
     473             :    * when accessing thread-shared state.
     474             :    * aImage can be null. While it's null, nothing will be painted.
     475             :    *
     476             :    * The Image data must not be modified after this method is called!
     477             :    * Note that this must not be called if ENABLE_ASYNC been set.
     478             :    *
     479             :    * You won't get meaningful painted/dropped counts when using this method.
     480             :    */
     481             :   void SetCurrentImageInTransaction(Image* aImage);
     482             :   void SetCurrentImagesInTransaction(const nsTArray<NonOwningImage>& aImages);
     483             : 
     484             :   /**
     485             :    * Returns true if this ImageContainer uses the ImageBridge IPDL protocol.
     486             :    *
     487             :    * Can be called from any thread.
     488             :    */
     489             :   bool IsAsync() const;
     490             : 
     491             :   /**
     492             :    * If this ImageContainer uses ImageBridge, returns the ID associated to
     493             :    * this container, for use in the ImageBridge protocol.
     494             :    * Returns 0 if this ImageContainer does not use ImageBridge. Note that
     495             :    * 0 is always an invalid ID for asynchronous image containers.
     496             :    *
     497             :    * Can be called from any thread.
     498             :    */
     499             :   CompositableHandle GetAsyncContainerHandle();
     500             : 
     501             :   /**
     502             :    * Returns if the container currently has an image.
     503             :    * Can be called on any thread. This method takes mReentrantMonitor
     504             :    * when accessing thread-shared state.
     505             :    */
     506             :   bool HasCurrentImage();
     507             : 
     508           0 :   struct OwningImage {
     509           0 :     OwningImage() : mFrameID(0), mProducerID(0), mComposited(false) {}
     510             :     RefPtr<Image> mImage;
     511             :     TimeStamp mTimeStamp;
     512             :     FrameID mFrameID;
     513             :     ProducerID mProducerID;
     514             :     bool mComposited;
     515             :   };
     516             :   /**
     517             :    * Copy the current Image list to aImages.
     518             :    * This has to add references since otherwise there are race conditions
     519             :    * where the current image is destroyed before the caller can add
     520             :    * a reference.
     521             :    * Can be called on any thread.
     522             :    * May return an empty list to indicate there is no current image.
     523             :    * If aGenerationCounter is non-null, sets *aGenerationCounter to a value
     524             :    * that's unique for this ImageContainer state.
     525             :    */
     526             :   void GetCurrentImages(nsTArray<OwningImage>* aImages,
     527             :                         uint32_t* aGenerationCounter = nullptr);
     528             : 
     529             :   /**
     530             :    * Returns the size of the image in pixels.
     531             :    * Can be called on any thread. This method takes mReentrantMonitor when accessing
     532             :    * thread-shared state.
     533             :    */
     534             :   gfx::IntSize GetCurrentSize();
     535             : 
     536             :   /**
     537             :    * Sets a size that the image is expected to be rendered at.
     538             :    * This is a hint for image backends to optimize scaling.
     539             :    * Default implementation in this class is to ignore the hint.
     540             :    * Can be called on any thread. This method takes mReentrantMonitor
     541             :    * when accessing thread-shared state.
     542             :    */
     543           0 :   void SetScaleHint(const gfx::IntSize& aScaleHint)
     544           0 :   { mScaleHint = aScaleHint; }
     545             : 
     546           0 :   void SetImageFactory(ImageFactory *aFactory)
     547             :   {
     548           0 :     ReentrantMonitorAutoEnter mon(mReentrantMonitor);
     549           0 :     mImageFactory = aFactory ? aFactory : new ImageFactory();
     550           0 :   }
     551             : 
     552           0 :   ImageFactory* GetImageFactory() const
     553             :   {
     554           0 :     return mImageFactory;
     555             :   }
     556             : 
     557             : #ifdef XP_WIN
     558             :   D3D11YCbCrRecycleAllocator* GetD3D11YCbCrRecycleAllocator(
     559             :     KnowsCompositor* aAllocator);
     560             : #endif
     561             : 
     562             :   /**
     563             :    * Returns the delay between the last composited image's presentation
     564             :    * timestamp and when it was first composited. It's possible for the delay
     565             :    * to be negative if the first image in the list passed to SetCurrentImages
     566             :    * has a presentation timestamp greater than "now".
     567             :    * Returns 0 if the composited image had a null timestamp, or if no
     568             :    * image has been composited yet.
     569             :    */
     570           0 :   TimeDuration GetPaintDelay()
     571             :   {
     572           0 :     ReentrantMonitorAutoEnter mon(mReentrantMonitor);
     573           0 :     return mPaintDelay;
     574             :   }
     575             : 
     576             :   /**
     577             :    * Returns the number of images which have been contained in this container
     578             :    * and painted at least once.  Can be called from any thread.
     579             :    */
     580           0 :   uint32_t GetPaintCount() {
     581           0 :     ReentrantMonitorAutoEnter mon(mReentrantMonitor);
     582           0 :     return mPaintCount;
     583             :   }
     584             : 
     585             :   /**
     586             :    * An entry in the current image list "expires" when the entry has an
     587             :    * non-null timestamp, and in a SetCurrentImages call the new image list is
     588             :    * non-empty, the timestamp of the first new image is non-null and greater
     589             :    * than the timestamp associated with the image, and the first new image's
     590             :    * frameID is not the same as the entry's.
     591             :    * Every expired image that is never composited is counted as dropped.
     592             :    */
     593             :   uint32_t GetDroppedImageCount()
     594             :   {
     595             :     ReentrantMonitorAutoEnter mon(mReentrantMonitor);
     596             :     return mDroppedImageCount;
     597             :   }
     598             : 
     599             :   void NotifyComposite(const ImageCompositeNotification& aNotification);
     600             : 
     601           0 :   ImageContainerListener* GetImageContainerListener()
     602             :   {
     603           0 :     return mNotifyCompositeListener;
     604             :   }
     605             : 
     606             :   /**
     607             :    * Main thread only.
     608             :    */
     609             :   static ProducerID AllocateProducerID();
     610             : 
     611             : private:
     612             :   typedef mozilla::ReentrantMonitor ReentrantMonitor;
     613             : 
     614             :   // Private destructor, to discourage deletion outside of Release():
     615             :   ~ImageContainer();
     616             : 
     617             :   void SetCurrentImageInternal(const nsTArray<NonOwningImage>& aImages);
     618             : 
     619             :   // This is called to ensure we have an active image, this may not be true
     620             :   // when we're storing image information in a RemoteImageData structure.
     621             :   // NOTE: If we have remote data mRemoteDataMutex should be locked when
     622             :   // calling this function!
     623             :   void EnsureActiveImage();
     624             : 
     625             :   void EnsureImageClient();
     626             : 
     627             :   // ReentrantMonitor to protect thread safe access to the "current
     628             :   // image", and any other state which is shared between threads.
     629             :   ReentrantMonitor mReentrantMonitor;
     630             : 
     631             : #ifdef XP_WIN
     632             :   RefPtr<D3D11YCbCrRecycleAllocator> mD3D11YCbCrRecycleAllocator;
     633             : #endif
     634             : 
     635             :   nsTArray<OwningImage> mCurrentImages;
     636             : 
     637             :   // Updates every time mActiveImage changes
     638             :   uint32_t mGenerationCounter;
     639             : 
     640             :   // Number of contained images that have been painted at least once.  It's up
     641             :   // to the ImageContainer implementation to ensure accesses to this are
     642             :   // threadsafe.
     643             :   uint32_t mPaintCount;
     644             : 
     645             :   // See GetPaintDelay. Accessed only with mReentrantMonitor held.
     646             :   TimeDuration mPaintDelay;
     647             : 
     648             :   // See GetDroppedImageCount. Accessed only with mReentrantMonitor held.
     649             :   uint32_t mDroppedImageCount;
     650             : 
     651             :   // This is the image factory used by this container, layer managers using
     652             :   // this container can set an alternative image factory that will be used to
     653             :   // create images for this container.
     654             :   RefPtr<ImageFactory> mImageFactory;
     655             : 
     656             :   gfx::IntSize mScaleHint;
     657             : 
     658             :   RefPtr<BufferRecycleBin> mRecycleBin;
     659             : 
     660             :   // This member points to an ImageClient if this ImageContainer was
     661             :   // sucessfully created with ENABLE_ASYNC, or points to null otherwise.
     662             :   // 'unsuccessful' in this case only means that the ImageClient could not
     663             :   // be created, most likely because off-main-thread compositing is not enabled.
     664             :   // In this case the ImageContainer is perfectly usable, but it will forward
     665             :   // frames to the compositor through transactions in the main thread rather than
     666             :   // asynchronusly using the ImageBridge IPDL protocol.
     667             :   RefPtr<ImageClient> mImageClient;
     668             : 
     669             :   bool mIsAsync;
     670             :   CompositableHandle mAsyncContainerHandle;
     671             : 
     672             :   nsTArray<FrameID> mFrameIDsNotYetComposited;
     673             :   // ProducerID for last current image(s), including the frames in
     674             :   // mFrameIDsNotYetComposited
     675             :   ProducerID mCurrentProducerID;
     676             : 
     677             :   RefPtr<ImageContainerListener> mNotifyCompositeListener;
     678             : 
     679             :   static mozilla::Atomic<uint32_t> sGenerationCounter;
     680             : };
     681             : 
     682           0 : class AutoLockImage
     683             : {
     684             : public:
     685           0 :   explicit AutoLockImage(ImageContainer *aContainer)
     686           0 :   {
     687           0 :     aContainer->GetCurrentImages(&mImages);
     688           0 :   }
     689             : 
     690           0 :   bool HasImage() const { return !mImages.IsEmpty(); }
     691           0 :   Image* GetImage() const
     692             :   {
     693           0 :     return mImages.IsEmpty() ? nullptr : mImages[0].mImage.get();
     694             :   }
     695             : 
     696           0 :   Image* GetImage(TimeStamp aTimeStamp) const
     697             :   {
     698           0 :     if (mImages.IsEmpty()) {
     699           0 :       return nullptr;
     700             :     }
     701             : 
     702           0 :     MOZ_ASSERT(!aTimeStamp.IsNull());
     703           0 :     uint32_t chosenIndex = 0;
     704             : 
     705           0 :     while (chosenIndex + 1 < mImages.Length() &&
     706           0 :            mImages[chosenIndex + 1].mTimeStamp <= aTimeStamp) {
     707           0 :       ++chosenIndex;
     708             :     }
     709             : 
     710           0 :     return mImages[chosenIndex].mImage.get();
     711             :   }
     712             : 
     713             : private:
     714             :   AutoTArray<ImageContainer::OwningImage,4> mImages;
     715             : };
     716             : 
     717             : struct PlanarYCbCrData {
     718             :   // Luminance buffer
     719             :   uint8_t* mYChannel;
     720             :   int32_t mYStride;
     721             :   gfx::IntSize mYSize;
     722             :   int32_t mYSkip;
     723             :   // Chroma buffers
     724             :   uint8_t* mCbChannel;
     725             :   uint8_t* mCrChannel;
     726             :   int32_t mCbCrStride;
     727             :   gfx::IntSize mCbCrSize;
     728             :   int32_t mCbSkip;
     729             :   int32_t mCrSkip;
     730             :   // Picture region
     731             :   uint32_t mPicX;
     732             :   uint32_t mPicY;
     733             :   gfx::IntSize mPicSize;
     734             :   StereoMode mStereoMode;
     735             :   YUVColorSpace mYUVColorSpace;
     736             : 
     737           0 :   gfx::IntRect GetPictureRect() const {
     738           0 :     return gfx::IntRect(mPicX, mPicY,
     739           0 :                      mPicSize.width,
     740           0 :                      mPicSize.height);
     741             :   }
     742             : 
     743           0 :   PlanarYCbCrData()
     744           0 :     : mYChannel(nullptr), mYStride(0), mYSize(0, 0), mYSkip(0)
     745             :     , mCbChannel(nullptr), mCrChannel(nullptr)
     746             :     , mCbCrStride(0), mCbCrSize(0, 0) , mCbSkip(0), mCrSkip(0)
     747             :     , mPicX(0), mPicY(0), mPicSize(0, 0), mStereoMode(StereoMode::MONO)
     748           0 :     , mYUVColorSpace(YUVColorSpace::BT601)
     749           0 :   {}
     750             : };
     751             : 
     752             : /****** Image subtypes for the different formats ******/
     753             : 
     754             : /**
     755             :  * We assume that the image data is in the REC 470M color space (see
     756             :  * Theora specification, section 4.3.1).
     757             :  *
     758             :  * The YCbCr format can be:
     759             :  *
     760             :  * 4:4:4 - CbCr width/height are the same as Y.
     761             :  * 4:2:2 - CbCr width is half that of Y. Height is the same.
     762             :  * 4:2:0 - CbCr width and height is half that of Y.
     763             :  *
     764             :  * The color format is detected based on the height/width ratios
     765             :  * defined above.
     766             :  *
     767             :  * The Image that is rendered is the picture region defined by
     768             :  * mPicX, mPicY and mPicSize. The size of the rendered image is
     769             :  * mPicSize, not mYSize or mCbCrSize.
     770             :  *
     771             :  * mYSkip, mCbSkip, mCrSkip are added to support various output
     772             :  * formats from hardware decoder. They are per-pixel skips in the
     773             :  * source image.
     774             :  *
     775             :  * For example when image width is 640, mYStride is 670, mYSkip is 3,
     776             :  * the mYChannel buffer looks like:
     777             :  *
     778             :  * |<----------------------- mYStride ----------------------------->|
     779             :  * |<----------------- mYSize.width --------------->|
     780             :  *  0   3   6   9   12  15  18  21                659             669
     781             :  * |----------------------------------------------------------------|
     782             :  * |Y___Y___Y___Y___Y___Y___Y___Y...                      |%%%%%%%%%|
     783             :  * |Y___Y___Y___Y___Y___Y___Y___Y...                      |%%%%%%%%%|
     784             :  * |Y___Y___Y___Y___Y___Y___Y___Y...                      |%%%%%%%%%|
     785             :  * |            |<->|
     786             :  *                mYSkip
     787             :  */
     788             : class PlanarYCbCrImage : public Image {
     789             : public:
     790             :   typedef PlanarYCbCrData Data;
     791             : 
     792             :   enum {
     793             :     MAX_DIMENSION = 16384
     794             :   };
     795             : 
     796           0 :   virtual ~PlanarYCbCrImage() {}
     797             : 
     798             :   /**
     799             :    * This makes a copy of the data buffers, in order to support functioning
     800             :    * in all different layer managers.
     801             :    */
     802             :   virtual bool CopyData(const Data& aData) = 0;
     803             : 
     804             :   /**
     805             :    * This doesn't make a copy of the data buffers. Can be used when mBuffer is
     806             :    * pre allocated with AllocateAndGetNewBuffer(size) and then AdoptData is
     807             :    * called to only update the picture size, planes etc. fields in mData.
     808             :    * The GStreamer media backend uses this to decode into PlanarYCbCrImage(s)
     809             :    * directly.
     810             :    */
     811             :   virtual bool AdoptData(const Data &aData);
     812             : 
     813             :   /**
     814             :    * This allocates and returns a new buffer
     815             :    */
     816             :   virtual uint8_t* AllocateAndGetNewBuffer(uint32_t aSize) = 0;
     817             : 
     818             :   /**
     819             :    * Ask this Image to not convert YUV to RGB during SetData, and make
     820             :    * the original data available through GetData. This is optional,
     821             :    * and not all PlanarYCbCrImages will support it.
     822             :    */
     823           0 :   virtual void SetDelayedConversion(bool aDelayed) { }
     824             : 
     825             :   /**
     826             :    * Grab the original YUV data. This is optional.
     827             :    */
     828           0 :   virtual const Data* GetData() { return &mData; }
     829             : 
     830             :   /**
     831             :    * Return the number of bytes of heap memory used to store this image.
     832             :    */
     833           0 :   virtual uint32_t GetDataSize() { return mBufferSize; }
     834             : 
     835           0 :   virtual bool IsValid() { return !!mBufferSize; }
     836             : 
     837           0 :   virtual gfx::IntSize GetSize() { return mSize; }
     838             : 
     839           0 :   virtual gfx::IntPoint GetOrigin() { return mOrigin; }
     840             : 
     841             :   explicit PlanarYCbCrImage();
     842             : 
     843           0 :   virtual SharedPlanarYCbCrImage *AsSharedPlanarYCbCrImage() { return nullptr; }
     844             : 
     845           0 :   virtual size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const {
     846           0 :     return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
     847             :   }
     848             : 
     849             :   virtual size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const = 0;
     850             : 
     851           0 :   PlanarYCbCrImage* AsPlanarYCbCrImage() { return this; }
     852             : 
     853             : protected:
     854             :   already_AddRefed<gfx::SourceSurface> GetAsSourceSurface();
     855             : 
     856           0 :   void SetOffscreenFormat(gfxImageFormat aFormat) { mOffscreenFormat = aFormat; }
     857             :   gfxImageFormat GetOffscreenFormat();
     858             : 
     859             :   Data mData;
     860             :   gfx::IntPoint mOrigin;
     861             :   gfx::IntSize mSize;
     862             :   gfxImageFormat mOffscreenFormat;
     863             :   nsCountedRef<nsMainThreadSourceSurfaceRef> mSourceSurface;
     864             :   uint32_t mBufferSize;
     865             : };
     866             : 
     867             : class RecyclingPlanarYCbCrImage: public PlanarYCbCrImage {
     868             : public:
     869           0 :   explicit RecyclingPlanarYCbCrImage(BufferRecycleBin *aRecycleBin) : mRecycleBin(aRecycleBin) {}
     870             :   virtual ~RecyclingPlanarYCbCrImage() override;
     871             :   virtual bool CopyData(const Data& aData) override;
     872             :   virtual uint8_t* AllocateAndGetNewBuffer(uint32_t aSize) override;
     873             :   virtual size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const override;
     874             : protected:
     875             : 
     876             :   /**
     877             :    * Return a buffer to store image data in.
     878             :    */
     879             :   mozilla::UniquePtr<uint8_t[]> AllocateBuffer(uint32_t aSize);
     880             : 
     881             :   RefPtr<BufferRecycleBin> mRecycleBin;
     882             :   mozilla::UniquePtr<uint8_t[]> mBuffer;
     883             : };
     884             : 
     885             : /**
     886             :  * NVImage is used to store YUV420SP_NV12 and YUV420SP_NV21 data natively, which
     887             :  * are not supported by PlanarYCbCrImage. (PlanarYCbCrImage only stores YUV444P,
     888             :  * YUV422P and YUV420P, it converts YUV420SP_NV12 and YUV420SP_NV21 data into
     889             :  * YUV420P in its PlanarYCbCrImage::SetData() method.)
     890             :  *
     891             :  * PlanarYCbCrData is able to express all the YUV family and so we keep use it
     892             :  * in NVImage.
     893             :  */
     894           0 : class NVImage: public Image {
     895             :   typedef PlanarYCbCrData Data;
     896             : 
     897             : public:
     898             :   explicit NVImage();
     899             :   virtual ~NVImage() override;
     900             : 
     901             :   // Methods inherited from layers::Image.
     902             :   virtual gfx::IntSize GetSize() override;
     903             :   virtual gfx::IntRect GetPictureRect() override;
     904             :   virtual already_AddRefed<gfx::SourceSurface> GetAsSourceSurface() override;
     905             :   virtual bool IsValid() override;
     906             :   virtual NVImage* AsNVImage() override;
     907             : 
     908             :   // Methods mimic layers::PlanarYCbCrImage.
     909             :   virtual bool SetData(const Data& aData);
     910             :   virtual const Data* GetData() const;
     911             :   virtual uint32_t GetBufferSize() const;
     912             : 
     913             : protected:
     914             : 
     915             :   /**
     916             :    * Return a buffer to store image data in.
     917             :    */
     918             :   mozilla::UniquePtr<uint8_t> AllocateBuffer(uint32_t aSize);
     919             : 
     920             :   mozilla::UniquePtr<uint8_t> mBuffer;
     921             :   uint32_t mBufferSize;
     922             :   gfx::IntSize mSize;
     923             :   Data mData;
     924             :   nsCountedRef<nsMainThreadSourceSurfaceRef> mSourceSurface;
     925             : };
     926             : 
     927             : /**
     928             :  * Currently, the data in a SourceSurfaceImage surface is treated as being in the
     929             :  * device output color space. This class is very simple as all backends
     930             :  * have to know about how to deal with drawing a cairo image.
     931             :  */
     932           0 : class SourceSurfaceImage final : public Image {
     933             : public:
     934           0 :   virtual already_AddRefed<gfx::SourceSurface> GetAsSourceSurface() override
     935             :   {
     936           0 :     RefPtr<gfx::SourceSurface> surface(mSourceSurface);
     937           0 :     return surface.forget();
     938             :   }
     939             : 
     940           0 :   void SetTextureFlags(TextureFlags aTextureFlags) { mTextureFlags = aTextureFlags; }
     941             :   virtual TextureClient* GetTextureClient(KnowsCompositor* aForwarder) override;
     942             : 
     943           0 :   virtual gfx::IntSize GetSize() override { return mSize; }
     944             : 
     945             :   SourceSurfaceImage(const gfx::IntSize& aSize, gfx::SourceSurface* aSourceSurface);
     946             :   explicit SourceSurfaceImage(gfx::SourceSurface* aSourceSurface);
     947             :   ~SourceSurfaceImage();
     948             : 
     949             : private:
     950             :   gfx::IntSize mSize;
     951             :   nsCountedRef<nsOwningThreadSourceSurfaceRef> mSourceSurface;
     952             :   nsDataHashtable<nsUint32HashKey, RefPtr<TextureClient> >  mTextureClients;
     953             :   TextureFlags mTextureFlags;
     954             : };
     955             : 
     956             : } // namespace layers
     957             : } // namespace mozilla
     958             : 
     959             : #endif

Generated by: LCOV version 1.13