tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

TextureClient.h (29105B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
      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 #ifndef MOZILLA_GFX_TEXTURECLIENT_H
      8 #define MOZILLA_GFX_TEXTURECLIENT_H
      9 
     10 #include <stddef.h>  // for size_t
     11 #include <stdint.h>  // for uint32_t, uint8_t, uint64_t
     12 
     13 #include "GLTextureImage.h"  // for TextureImage
     14 #include "GfxTexturesReporter.h"
     15 #include "ImageTypes.h"          // for StereoMode
     16 #include "mozilla/Assertions.h"  // for MOZ_ASSERT, etc
     17 #include "mozilla/Atomics.h"
     18 #include "mozilla/Attributes.h"  // for override
     19 #include "mozilla/Mutex.h"
     20 #include "mozilla/RefPtr.h"  // for RefPtr, RefCounted
     21 #include "mozilla/dom/ipc/IdType.h"
     22 #include "mozilla/gfx/2D.h"  // for DrawTarget
     23 #include "mozilla/gfx/CriticalSection.h"
     24 #include "mozilla/gfx/Point.h"  // for IntSize
     25 #include "mozilla/gfx/Types.h"  // for SurfaceFormat
     26 #include "mozilla/ipc/Shmem.h"  // for Shmem
     27 #include "mozilla/layers/AtomicRefCountedWithFinalize.h"
     28 #include "mozilla/layers/CompositorTypes.h"  // for TextureFlags, etc
     29 #include "mozilla/layers/ISurfaceAllocator.h"
     30 #include "mozilla/layers/LayersSurfaces.h"  // for SurfaceDescriptor
     31 #include "mozilla/layers/LayersTypes.h"
     32 #include "mozilla/layers/SyncObject.h"
     33 #include "mozilla/mozalloc.h"             // for operator delete
     34 #include "mozilla/UniquePtrExtensions.h"  // for UniqueFileHandle
     35 #include "mozilla/webrender/WebRenderTypes.h"
     36 #include "nsCOMPtr.h"         // for already_AddRefed
     37 #include "nsISupportsImpl.h"  // for TextureImage::AddRef, etc
     38 #include "nsThreadUtils.h"
     39 #include "pratom.h"
     40 
     41 class gfxImageSurface;
     42 struct ID3D11Device;
     43 
     44 namespace mozilla {
     45 
     46 namespace layers {
     47 
     48 class AndroidHardwareBufferTextureData;
     49 class BufferTextureData;
     50 class CompositableForwarder;
     51 class FwdTransactionTracker;
     52 class KnowsCompositor;
     53 class LayersIPCChannel;
     54 class CompositableClient;
     55 struct PlanarYCbCrData;
     56 class Image;
     57 class PTextureChild;
     58 class TextureChild;
     59 class TextureData;
     60 class GPUVideoTextureData;
     61 class TextureClient;
     62 class ITextureClientRecycleAllocator;
     63 class SharedSurfaceTextureData;
     64 class TextureForwarder;
     65 class RecordedTextureData;
     66 struct RemoteTextureOwnerId;
     67 
     68 /**
     69 * TextureClient is the abstraction that allows us to share data between the
     70 * content and the compositor side.
     71 */
     72 
     73 enum TextureAllocationFlags {
     74  ALLOC_DEFAULT = 0,
     75  ALLOC_CLEAR_BUFFER =
     76      1 << 1,  // Clear the buffer to whatever is best for the draw target
     77  ALLOC_CLEAR_BUFFER_WHITE = 1 << 2,  // explicit all white
     78  ALLOC_CLEAR_BUFFER_BLACK = 1 << 3,  // explicit all black
     79  ALLOC_DISALLOW_BUFFERTEXTURECLIENT = 1 << 4,
     80 
     81  // Allocate the texture for out-of-band content updates. This is mostly for
     82  // TextureClientD3D11, which may otherwise choose D3D10 or non-KeyedMutex
     83  // surfaces when used on the main thread.
     84  ALLOC_FOR_OUT_OF_BAND_CONTENT = 1 << 5,
     85 
     86  // Disable any cross-device synchronization. This is also for
     87  // TextureClientD3D11, and creates a texture without KeyedMutex.
     88  ALLOC_MANUAL_SYNCHRONIZATION = 1 << 6,
     89 
     90  // The texture is going to be updated using UpdateFromSurface and needs to
     91  // support that call.
     92  ALLOC_UPDATE_FROM_SURFACE = 1 << 7,
     93 
     94  // Do not use an accelerated texture type.
     95  ALLOC_DO_NOT_ACCELERATE = 1 << 8,
     96 
     97  // Force allocation of remote/recorded texture, or fail if not possible.
     98  ALLOC_FORCE_REMOTE = 1 << 9,
     99 
    100  // Prefer to use keyed mutex than D3D11Fence on Windows
    101  USE_D3D11_KEYED_MUTEX = 1 << 10,
    102 };
    103 
    104 enum class BackendSelector { Content, Canvas };
    105 
    106 /// Temporary object providing direct access to a Texture's memory.
    107 ///
    108 /// see TextureClient::CanExposeMappedData() and
    109 /// TextureClient::BorrowMappedData().
    110 struct MappedTextureData {
    111  uint8_t* data;
    112  gfx::IntSize size;
    113  int32_t stride;
    114  gfx::SurfaceFormat format;
    115 };
    116 
    117 struct MappedYCbCrChannelData {
    118  uint8_t* data;
    119  gfx::IntSize size;
    120  int32_t stride;
    121  int32_t skip;
    122  uint32_t bytesPerPixel;
    123 
    124  bool CopyInto(MappedYCbCrChannelData& aDst);
    125 };
    126 
    127 struct MappedYCbCrTextureData {
    128  MappedYCbCrChannelData y;
    129  MappedYCbCrChannelData cb;
    130  MappedYCbCrChannelData cr;
    131  // Sad but because of how SharedPlanarYCbCrData is used we have to expose this
    132  // for now.
    133  uint8_t* metadata;
    134  StereoMode stereoMode;
    135 
    136  bool CopyInto(MappedYCbCrTextureData& aDst) {
    137    return y.CopyInto(aDst.y) && cb.CopyInto(aDst.cb) && cr.CopyInto(aDst.cr);
    138  }
    139 };
    140 
    141 class ReadLockDescriptor;
    142 class NonBlockingTextureReadLock;
    143 
    144 // A class to help implement copy-on-write semantics for shared textures.
    145 //
    146 // A TextureClient/Host pair can opt into using a ReadLock by calling
    147 // TextureClient::EnableReadLock. This will equip the TextureClient with a
    148 // ReadLock object that will be automatically ReadLock()'ed by the texture
    149 // itself when it is written into (see TextureClient::Unlock). A
    150 // TextureReadLock's counter starts at 1 and is expected to be equal to 1 when
    151 // the lock is destroyed. See ShmemTextureReadLock for explanations about why we
    152 // use 1 instead of 0 as the initial state. TextureReadLock is mostly internally
    153 // managed by the TextureClient/Host pair, and the compositable only has to
    154 // forward it during updates. If an update message contains a null_t lock, it
    155 // means that the texture was not written into on the content side, and there is
    156 // no synchronization required on the compositor side (or it means that the
    157 // texture pair did not opt into using ReadLocks). On the compositor side, the
    158 // TextureHost can receive a ReadLock during a transaction, and will both
    159 // ReadUnlock() it and drop it as soon as the shared data is available again for
    160 // writing (the texture upload is done, or the compositor not reading the
    161 // texture anymore). The lock is dropped to make sure it is ReadUnlock()'ed only
    162 // once.
    163 class TextureReadLock {
    164 protected:
    165  virtual ~TextureReadLock() = default;
    166 
    167 public:
    168  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(TextureReadLock)
    169 
    170  virtual bool ReadLock() = 0;
    171  virtual bool TryReadLock(TimeDuration aTimeout) { return ReadLock(); }
    172  virtual int32_t ReadUnlock() = 0;
    173  virtual bool IsValid() const = 0;
    174 
    175  static already_AddRefed<TextureReadLock> Deserialize(
    176      ReadLockDescriptor&& aDescriptor, ISurfaceAllocator* aAllocator);
    177 
    178  virtual bool Serialize(ReadLockDescriptor& aOutput,
    179                         base::ProcessId aOther) = 0;
    180 
    181  enum LockType {
    182    TYPE_NONBLOCKING_MEMORY,
    183    TYPE_NONBLOCKING_SHMEM,
    184    TYPE_CROSS_PROCESS_SEMAPHORE
    185  };
    186  virtual LockType GetType() = 0;
    187 
    188  virtual NonBlockingTextureReadLock* AsNonBlockingLock() { return nullptr; }
    189 };
    190 
    191 class NonBlockingTextureReadLock : public TextureReadLock {
    192 public:
    193  virtual int32_t GetReadCount() = 0;
    194 
    195  static already_AddRefed<TextureReadLock> Create(LayersIPCChannel* aAllocator);
    196 
    197  NonBlockingTextureReadLock* AsNonBlockingLock() override { return this; }
    198 };
    199 
    200 #ifdef XP_WIN
    201 class D3D11TextureData;
    202 class DXGIYCbCrTextureData;
    203 #endif
    204 
    205 class TextureData {
    206 public:
    207  struct Info {
    208    gfx::IntSize size;
    209    gfx::SurfaceFormat format;
    210    bool hasSynchronization;
    211    bool supportsMoz2D;
    212    bool canExposeMappedData;
    213    bool canConcurrentlyReadLock;
    214 
    215    Info()
    216        : format(gfx::SurfaceFormat::UNKNOWN),
    217          hasSynchronization(false),
    218          supportsMoz2D(false),
    219          canExposeMappedData(false),
    220          canConcurrentlyReadLock(true) {}
    221  };
    222 
    223  static TextureData* Create(
    224      TextureType aTextureType, gfx::SurfaceFormat aFormat,
    225      const gfx::IntSize& aSize, TextureAllocationFlags aAllocFlags,
    226      gfx::BackendType aBackendType = gfx::BackendType::NONE);
    227  static TextureData* Create(TextureForwarder* aAllocator,
    228                             gfx::SurfaceFormat aFormat, gfx::IntSize aSize,
    229                             KnowsCompositor* aKnowsCompositor,
    230                             BackendSelector aSelector,
    231                             TextureFlags aTextureFlags,
    232                             TextureAllocationFlags aAllocFlags);
    233 
    234  static bool IsRemote(KnowsCompositor* aKnowsCompositor,
    235                       BackendSelector aSelector,
    236                       gfx::SurfaceFormat aFormat = gfx::SurfaceFormat::UNKNOWN,
    237                       gfx::IntSize aSize = gfx::IntSize(1, 1));
    238 
    239  MOZ_COUNTED_DTOR_VIRTUAL(TextureData)
    240 
    241  virtual TextureType GetTextureType() const { return TextureType::Last; }
    242 
    243  virtual void FillInfo(TextureData::Info& aInfo) const = 0;
    244 
    245  virtual void InvalidateContents() {}
    246 
    247  virtual bool Lock(OpenMode aMode) = 0;
    248 
    249  virtual void Unlock() = 0;
    250 
    251  virtual already_AddRefed<gfx::DrawTarget> BorrowDrawTarget() {
    252    return nullptr;
    253  }
    254 
    255  virtual void ReturnDrawTarget(already_AddRefed<gfx::DrawTarget> aDT);
    256 
    257  /**
    258   * When the TextureData is not being Unlocked, this can be used to inform a
    259   * TextureData that drawing has finished until the next BorrowDrawTarget.
    260   */
    261  virtual void EndDraw() {}
    262 
    263  virtual already_AddRefed<gfx::SourceSurface> BorrowSnapshot() {
    264    return nullptr;
    265  }
    266 
    267  virtual void ReturnSnapshot(already_AddRefed<gfx::SourceSurface> aSnapshot);
    268 
    269  virtual bool BorrowMappedData(MappedTextureData&) { return false; }
    270 
    271  virtual bool BorrowMappedYCbCrData(MappedYCbCrTextureData&) { return false; }
    272 
    273  virtual void Deallocate(LayersIPCChannel* aAllocator) = 0;
    274 
    275  /// Depending on the texture's flags either Deallocate or Forget is called.
    276  virtual void Forget(LayersIPCChannel* aAllocator) {}
    277 
    278  virtual bool Serialize(SurfaceDescriptor& aDescriptor) = 0;
    279  virtual void GetSubDescriptor(RemoteDecoderVideoSubDescriptor* aOutDesc) {}
    280 
    281  virtual void OnForwardedToHost() {}
    282 
    283  virtual TextureData* CreateSimilar(
    284      LayersIPCChannel* aAllocator, LayersBackend aLayersBackend,
    285      TextureFlags aFlags = TextureFlags::DEFAULT,
    286      TextureAllocationFlags aAllocFlags = ALLOC_DEFAULT) const {
    287    return nullptr;
    288  }
    289 
    290  virtual bool UpdateFromSurface(gfx::SourceSurface* aSurface) {
    291    return false;
    292  };
    293 
    294  virtual void SyncWithObject(RefPtr<SyncObjectClient> aSyncObject) {};
    295 
    296  virtual TextureFlags GetTextureFlags() const {
    297    return TextureFlags::NO_FLAGS;
    298  }
    299 
    300 #ifdef XP_WIN
    301  virtual D3D11TextureData* AsD3D11TextureData() { return nullptr; }
    302  virtual DXGIYCbCrTextureData* AsDXGIYCbCrTextureData() { return nullptr; }
    303 #endif
    304 
    305  virtual BufferTextureData* AsBufferTextureData() { return nullptr; }
    306 
    307  virtual GPUVideoTextureData* AsGPUVideoTextureData() { return nullptr; }
    308 
    309  virtual AndroidHardwareBufferTextureData*
    310  AsAndroidHardwareBufferTextureData() {
    311    return nullptr;
    312  }
    313 
    314  virtual RecordedTextureData* AsRecordedTextureData() { return nullptr; }
    315 
    316  // It is used by AndroidHardwareBufferTextureData and
    317  // SharedSurfaceTextureData. Returns buffer id when it owns
    318  // AndroidHardwareBuffer. It is used only on android.
    319  virtual Maybe<uint64_t> GetBufferId() const { return Nothing(); }
    320 
    321  // The acquire fence is a fence that is used for waiting until rendering to
    322  // its AHardwareBuffer is completed.
    323  // It is used only on android.
    324  virtual UniqueFileHandle GetAcquireFence() { return UniqueFileHandle(); }
    325 
    326  virtual bool RequiresRefresh() const { return false; }
    327 
    328  virtual already_AddRefed<FwdTransactionTracker> UseCompositableForwarder(
    329      CompositableForwarder* aForwarder) {
    330    return nullptr;
    331  }
    332 
    333 protected:
    334  MOZ_COUNTED_DEFAULT_CTOR(TextureData)
    335 };
    336 
    337 /**
    338 * TextureClient is a thin abstraction over texture data that need to be shared
    339 * between the content process and the compositor process. It is the
    340 * content-side half of a TextureClient/TextureHost pair. A corresponding
    341 * TextureHost lives on the compositor-side.
    342 *
    343 * TextureClient's primary purpose is to present texture data in a way that is
    344 * understood by the IPC system. There are two ways to use it:
    345 * - Use it to serialize image data that is not IPC-friendly (most likely
    346 * involving a copy into shared memory)
    347 * - preallocate it and paint directly into it, which avoids copy but requires
    348 * the painting code to be aware of TextureClient (or at least the underlying
    349 * shared memory).
    350 *
    351 * There is always one and only one TextureClient per TextureHost, and the
    352 * TextureClient/Host pair only owns one buffer of image data through its
    353 * lifetime. This means that the lifetime of the underlying shared data
    354 * matches the lifetime of the TextureClient/Host pair. It also means
    355 * TextureClient/Host do not implement double buffering, which is the
    356 * responsibility of the compositable (which would use pairs of Textures).
    357 * In order to send several different buffers to the compositor side, use
    358 * several TextureClients.
    359 */
    360 class TextureClient : public AtomicRefCountedWithFinalize<TextureClient> {
    361 public:
    362  TextureClient(TextureData* aData, TextureFlags aFlags,
    363                LayersIPCChannel* aAllocator);
    364 
    365  virtual ~TextureClient();
    366 
    367  static already_AddRefed<TextureClient> CreateWithData(
    368      TextureData* aData, TextureFlags aFlags, LayersIPCChannel* aAllocator);
    369 
    370  // Creates and allocates a TextureClient usable with Moz2D.
    371  static already_AddRefed<TextureClient> CreateForDrawing(
    372      KnowsCompositor* aAllocator, gfx::SurfaceFormat aFormat,
    373      gfx::IntSize aSize, BackendSelector aSelector, TextureFlags aTextureFlags,
    374      TextureAllocationFlags flags = ALLOC_DEFAULT);
    375 
    376  static already_AddRefed<TextureClient> CreateFromSurface(
    377      KnowsCompositor* aAllocator, gfx::SourceSurface* aSurface,
    378      BackendSelector aSelector, TextureFlags aTextureFlags,
    379      TextureAllocationFlags aAllocFlags);
    380 
    381  // Creates and allocates a TextureClient supporting the YCbCr format.
    382  static already_AddRefed<TextureClient> CreateForYCbCr(
    383      KnowsCompositor* aAllocator, const gfx::IntRect& aDisplay,
    384      const gfx::IntSize& aYSize, uint32_t aYStride,
    385      const gfx::IntSize& aCbCrSize, uint32_t aCbCrStride,
    386      StereoMode aStereoMode, gfx::ColorDepth aColorDepth,
    387      gfx::YUVColorSpace aYUVColorSpace, gfx::ColorRange aColorRange,
    388      gfx::ChromaSubsampling aSubsampling, TextureFlags aTextureFlags);
    389 
    390  // Creates and allocates a TextureClient (can be accessed through raw
    391  // pointers).
    392  static already_AddRefed<TextureClient> CreateForRawBufferAccess(
    393      KnowsCompositor* aAllocator, gfx::SurfaceFormat aFormat,
    394      gfx::IntSize aSize, gfx::BackendType aMoz2dBackend,
    395      TextureFlags aTextureFlags, TextureAllocationFlags flags = ALLOC_DEFAULT);
    396 
    397  // Creates and allocates a TextureClient of the same type.
    398  already_AddRefed<TextureClient> CreateSimilar(
    399      LayersBackend aLayersBackend = LayersBackend::LAYERS_NONE,
    400      TextureFlags aFlags = TextureFlags::DEFAULT,
    401      TextureAllocationFlags aAllocFlags = ALLOC_DEFAULT) const;
    402 
    403  /**
    404   * Locks the shared data, allowing the caller to get access to it.
    405   *
    406   * Please always lock/unlock when accessing the shared data.
    407   * If Lock() returns false, you should not attempt to access the shared data.
    408   */
    409  bool Lock(OpenMode aMode);
    410 
    411  void Unlock();
    412 
    413  bool IsLocked() const { return mIsLocked; }
    414 
    415  gfx::IntSize GetSize() const { return mInfo.size; }
    416 
    417  gfx::SurfaceFormat GetFormat() const { return mInfo.format; }
    418 
    419  /**
    420   * Returns true if this texture has a synchronization mechanism (mutex, fence,
    421   * etc.). Textures that do not implement synchronization should be immutable
    422   * or should use immediate uploads (see TextureFlags in CompositorTypes.h)
    423   * Even if a texture does not implement synchronization, Lock and Unlock need
    424   * to be used appropriately since the latter are also there to map/numap data.
    425   */
    426  bool HasSynchronization() const { return mInfo.hasSynchronization; }
    427 
    428  bool CanExposeDrawTarget() const { return mInfo.supportsMoz2D; }
    429 
    430  bool CanExposeMappedData() const { return mInfo.canExposeMappedData; }
    431 
    432  /**
    433   * Returns a DrawTarget to draw into the TextureClient.
    434   * This function should never be called when not on the main thread!
    435   *
    436   * This must never be called on a TextureClient that is not sucessfully
    437   * locked. When called several times within one Lock/Unlock pair, this method
    438   * should return the same DrawTarget. The DrawTarget is automatically flushed
    439   * by the TextureClient when the latter is unlocked, and the DrawTarget that
    440   * will be returned within the next lock/unlock pair may or may not be the
    441   * same object. Do not keep references to the DrawTarget outside of the
    442   * lock/unlock pair.
    443   *
    444   * This is typically used as follows:
    445   *
    446   * if (!texture->Lock(OpenMode::OPEN_READ_WRITE)) {
    447   *   return false;
    448   * }
    449   * {
    450   *   // Restrict this code's scope to ensure all references to dt are gone
    451   *   // when Unlock is called.
    452   *   DrawTarget* dt = texture->BorrowDrawTarget();
    453   *   // use the draw target ...
    454   * }
    455   * texture->Unlock();
    456   *
    457   */
    458  gfx::DrawTarget* BorrowDrawTarget();
    459 
    460  /**
    461   * When the TextureClient is not being Unlocked, this can be used to inform it
    462   * that drawing has finished until the next BorrowDrawTarget.
    463   */
    464  void EndDraw();
    465 
    466  already_AddRefed<gfx::SourceSurface> BorrowSnapshot();
    467 
    468  void ReturnSnapshot(already_AddRefed<gfx::SourceSurface> aSnapshot);
    469 
    470  /**
    471   * Similar to BorrowDrawTarget but provides direct access to the texture's
    472   * bits instead of a DrawTarget.
    473   */
    474  bool BorrowMappedData(MappedTextureData&);
    475  bool BorrowMappedYCbCrData(MappedYCbCrTextureData&);
    476 
    477  /**
    478   * This function can be used to update the contents of the TextureClient
    479   * off the main thread.
    480   */
    481  void UpdateFromSurface(gfx::SourceSurface* aSurface);
    482 
    483  /**
    484   * This method is strictly for debugging. It causes locking and
    485   * needless copies.
    486   */
    487  already_AddRefed<gfx::DataSourceSurface> GetAsSurface();
    488 
    489  /**
    490   * Copies a rectangle from this texture client to a position in aTarget.
    491   * It is assumed that the necessary locks are in place; so this should at
    492   * least have a read lock and aTarget should at least have a write lock.
    493   */
    494  bool CopyToTextureClient(TextureClient* aTarget, const gfx::IntRect* aRect,
    495                           const gfx::IntPoint* aPoint);
    496 
    497  /**
    498   * Allocate and deallocate a TextureChild actor.
    499   *
    500   * TextureChild is an implementation detail of TextureClient that is not
    501   * exposed to the rest of the code base. CreateIPDLActor and DestroyIPDLActor
    502   * are for use with the managing IPDL protocols only (so that they can
    503   * implement AllocPextureChild and DeallocPTextureChild).
    504   */
    505  static PTextureChild* CreateIPDLActor();
    506  static bool DestroyIPDLActor(PTextureChild* actor);
    507 
    508  /**
    509   * Get the TextureClient corresponding to the actor passed in parameter.
    510   */
    511  static already_AddRefed<TextureClient> AsTextureClient(PTextureChild* actor);
    512 
    513  /**
    514   * TextureFlags contain important information about various aspects
    515   * of the texture, like how its liferime is managed, and how it
    516   * should be displayed.
    517   * See TextureFlags in CompositorTypes.h.
    518   */
    519  TextureFlags GetFlags() const { return mFlags; }
    520 
    521  bool HasFlags(TextureFlags aFlags) const {
    522    return (mFlags & aFlags) == aFlags;
    523  }
    524 
    525  void AddFlags(TextureFlags aFlags);
    526 
    527  void RemoveFlags(TextureFlags aFlags);
    528 
    529  // Must not be called when TextureClient is in use by CompositableClient.
    530  void RecycleTexture(TextureFlags aFlags);
    531 
    532  /**
    533   * After being shared with the compositor side, an immutable texture is never
    534   * modified, it can only be read. It is safe to not Lock/Unlock immutable
    535   * textures.
    536   */
    537  bool IsImmutable() const { return !!(mFlags & TextureFlags::IMMUTABLE); }
    538 
    539  void MarkImmutable() { AddFlags(TextureFlags::IMMUTABLE); }
    540 
    541  bool IsSharedWithCompositor() const;
    542 
    543  /**
    544   * If this method returns false users of TextureClient are not allowed
    545   * to access the shared data.
    546   */
    547  bool IsValid() const { return !!mData; }
    548 
    549  /**
    550   * Called when TextureClient is added to CompositableClient.
    551   */
    552  void SetAddedToCompositableClient();
    553 
    554  /**
    555   * If this method retuns false, TextureClient is already added to
    556   * CompositableClient, since its creation or recycling.
    557   */
    558  bool IsAddedToCompositableClient() const {
    559    return mAddedToCompositableClient;
    560  }
    561 
    562  /**
    563   * Create and init the TextureChild/Parent IPDL actor pair
    564   * with a CompositableForwarder.
    565   *
    566   * Should be called only once per TextureClient.
    567   * The TextureClient must not be locked when calling this method.
    568   */
    569  bool InitIPDLActor(CompositableForwarder* aForwarder);
    570 
    571  /**
    572   * Create and init the TextureChild/Parent IPDL actor pair
    573   * with a TextureForwarder.
    574   *
    575   * Should be called only once per TextureClient.
    576   * The TextureClient must not be locked when calling this method.
    577   */
    578  bool InitIPDLActor(KnowsCompositor* aKnowsCompositor,
    579                     const dom::ContentParentId& aContentId);
    580 
    581  /**
    582   * Return a pointer to the IPDLActor.
    583   *
    584   * This is to be used with IPDL messages only. Do not store the returned
    585   * pointer.
    586   */
    587  PTextureChild* GetIPDLActor();
    588 
    589  /**
    590   * Triggers the destruction of the shared data and the corresponding
    591   * TextureHost.
    592   *
    593   * If the texture flags contain TextureFlags::DEALLOCATE_CLIENT, the
    594   * destruction will be synchronously coordinated with the compositor side,
    595   * otherwise it will be done asynchronously.
    596   */
    597  void Destroy();
    598 
    599  /**
    600   * Track how much of this texture is wasted.
    601   * For example we might allocate a 256x256 tile but only use 10x10.
    602   */
    603  void SetWaste(int aWasteArea) {
    604    mWasteTracker.Update(aWasteArea, BytesPerPixel(GetFormat()));
    605  }
    606 
    607  void SyncWithObject(RefPtr<SyncObjectClient> aSyncObject) {
    608    mData->SyncWithObject(aSyncObject);
    609  }
    610 
    611  LayersIPCChannel* GetAllocator() { return mAllocator; }
    612 
    613  ITextureClientRecycleAllocator* GetRecycleAllocator() {
    614    return mRecycleAllocator;
    615  }
    616  void SetRecycleAllocator(ITextureClientRecycleAllocator* aAllocator);
    617 
    618  /// If you add new code that uses this method, you are probably doing
    619  /// something wrong.
    620  TextureData* GetInternalData() { return mData; }
    621  const TextureData* GetInternalData() const { return mData; }
    622 
    623  uint64_t GetSerial() const { return mSerial; }
    624  void GetSurfaceDescriptorRemoteDecoder(
    625      SurfaceDescriptorRemoteDecoder* aOutDesc);
    626 
    627  void CancelWaitForNotifyNotUsed();
    628 
    629  /**
    630   * Set last transaction id of CompositableForwarder.
    631   *
    632   * Called when TextureClient has TextureFlags::RECYCLE flag.
    633   * When CompositableForwarder forwards the TextureClient with
    634   * TextureFlags::RECYCLE, it holds TextureClient's ref until host side
    635   * releases it. The host side sends TextureClient release message.
    636   * The id is used to check if the message is for the last TextureClient
    637   * forwarding.
    638   */
    639  void SetLastFwdTransactionId(uint64_t aTransactionId) {
    640    MOZ_ASSERT(mFwdTransactionId <= aTransactionId);
    641    mFwdTransactionId = aTransactionId;
    642  }
    643 
    644  uint64_t GetLastFwdTransactionId() { return mFwdTransactionId; }
    645 
    646  bool HasReadLock() const {
    647    MutexAutoLock lock(mMutex);
    648    return !!mReadLock;
    649  }
    650 
    651  int32_t GetNonBlockingReadLockCount() {
    652    MutexAutoLock lock(mMutex);
    653    if (NS_WARN_IF(!mReadLock)) {
    654      MOZ_ASSERT_UNREACHABLE("No read lock created yet?");
    655      return 0;
    656    }
    657    MOZ_ASSERT(mReadLock->AsNonBlockingLock(),
    658               "Can only check locked for non-blocking locks!");
    659    return mReadLock->AsNonBlockingLock()->GetReadCount();
    660  }
    661 
    662  bool IsReadLocked();
    663 
    664  bool ShouldReadLock() const {
    665    return bool(mFlags & (TextureFlags::NON_BLOCKING_READ_LOCK |
    666                          TextureFlags::BLOCKING_READ_LOCK));
    667  }
    668 
    669  bool TryReadLock();
    670  void ReadUnlock();
    671 
    672  void SetUpdated() { mUpdated = true; }
    673 
    674  void OnPrepareForwardToHost();
    675  void OnAbandonForwardToHost();
    676  bool OnForwardedToHost();
    677 
    678  // Mark that the TextureClient will be used by the paint thread, and should
    679  // not free its underlying texture data. This must only be called from the
    680  // main thread.
    681  void AddPaintThreadRef();
    682 
    683  // Mark that the TextureClient is no longer in use by the PaintThread. This
    684  // must only be called from the PaintThread.
    685  void DropPaintThreadRef();
    686 
    687  wr::MaybeExternalImageId GetExternalImageKey() { return mExternalImageId; }
    688 
    689 private:
    690  static void TextureClientRecycleCallback(TextureClient* aClient,
    691                                           void* aClosure);
    692 
    693  static already_AddRefed<TextureClient> CreateForDrawing(
    694      TextureForwarder* aAllocator, gfx::SurfaceFormat aFormat,
    695      gfx::IntSize aSize, KnowsCompositor* aKnowsCompositor,
    696      BackendSelector aSelector, TextureFlags aTextureFlags,
    697      TextureAllocationFlags aAllocFlags = ALLOC_DEFAULT);
    698 
    699  static already_AddRefed<TextureClient> CreateForRawBufferAccess(
    700      LayersIPCChannel* aAllocator, gfx::SurfaceFormat aFormat,
    701      gfx::IntSize aSize, gfx::BackendType aMoz2dBackend,
    702      LayersBackend aLayersBackend, TextureFlags aTextureFlags,
    703      TextureAllocationFlags flags = ALLOC_DEFAULT);
    704 
    705  void EnsureHasReadLock() MOZ_REQUIRES(mMutex);
    706  void EnableReadLock() MOZ_REQUIRES(mMutex);
    707  void EnableBlockingReadLock() MOZ_REQUIRES(mMutex);
    708 
    709  /**
    710   * Called once, during the destruction of the Texture, on the thread in which
    711   * texture's reference count reaches 0 (could be any thread).
    712   *
    713   * Here goes the shut-down code that uses virtual methods.
    714   * Must only be called by Release().
    715   */
    716  void Finalize() {}
    717 
    718  friend class AtomicRefCountedWithFinalize<TextureClient>;
    719 
    720 protected:
    721  /**
    722   * Should only be called *once* per texture, in TextureClient::InitIPDLActor.
    723   * Some texture implementations rely on the fact that the descriptor will be
    724   * deserialized.
    725   * Calling ToSurfaceDescriptor again after it has already returned true,
    726   * or never constructing a TextureHost with aDescriptor may result in a memory
    727   * leak (see TextureClientD3D9 for example).
    728   */
    729  bool ToSurfaceDescriptor(SurfaceDescriptor& aDescriptor);
    730 
    731  void LockActor() const;
    732  void UnlockActor() const;
    733 
    734  TextureData::Info mInfo;
    735  mutable Mutex mMutex;
    736 
    737  RefPtr<LayersIPCChannel> mAllocator;
    738  RefPtr<TextureChild> mActor;
    739  RefPtr<ITextureClientRecycleAllocator> mRecycleAllocator;
    740  RefPtr<TextureReadLock> mReadLock MOZ_GUARDED_BY(mMutex);
    741 
    742  TextureData* mData;
    743  RefPtr<gfx::DrawTarget> mBorrowedDrawTarget;
    744  bool mBorrowedSnapshot = false;
    745 
    746  TextureFlags mFlags;
    747 
    748  gl::GfxTextureWasteTracker mWasteTracker;
    749 
    750  OpenMode mOpenMode;
    751  bool mIsLocked;
    752  bool mIsReadLocked MOZ_GUARDED_BY(mMutex);
    753  bool mIsPendingForwardReadLocked MOZ_GUARDED_BY(mMutex) = false;
    754  // This member tracks that the texture was written into until the update
    755  // is sent to the compositor. We need this remember to lock mReadLock on
    756  // behalf of the compositor just before sending the notification.
    757  bool mUpdated;
    758 
    759  // Used when TextureClient is recycled with TextureFlags::RECYCLE flag.
    760  bool mAddedToCompositableClient;
    761 
    762  uint64_t mFwdTransactionId;
    763 
    764  // Serial id of TextureClient. It is unique in current process.
    765  const uint64_t mSerial;
    766 
    767  // When non-zero, texture data must not be freed.
    768  mozilla::Atomic<uintptr_t> mPaintThreadRefs;
    769 
    770  // External image id. It is unique if it is allocated.
    771  // The id is allocated in TextureClient::InitIPDLActor().
    772  // Its allocation is supported by
    773  // CompositorBridgeChild and ImageBridgeChild for now.
    774  wr::MaybeExternalImageId mExternalImageId;
    775 
    776  // Used to assign serial ids of TextureClient.
    777  static mozilla::Atomic<uint64_t> sSerialCounter;
    778 
    779  friend class TextureChild;
    780  friend void TestTextureClientSurface(TextureClient*, gfxImageSurface*);
    781  friend void TestTextureClientYCbCr(TextureClient*, PlanarYCbCrData&);
    782  friend already_AddRefed<TextureHost> CreateTextureHostWithBackend(
    783      TextureClient*, ISurfaceAllocator*, LayersBackend&);
    784 };
    785 
    786 /**
    787 * Task that releases TextureClient pointer on a specified thread.
    788 */
    789 class TextureClientReleaseTask : public Runnable {
    790 public:
    791  explicit TextureClientReleaseTask(TextureClient* aClient)
    792      : Runnable("layers::TextureClientReleaseTask"), mTextureClient(aClient) {}
    793 
    794  NS_IMETHOD Run() override {
    795    mTextureClient = nullptr;
    796    return NS_OK;
    797  }
    798 
    799 private:
    800  RefPtr<TextureClient> mTextureClient;
    801 };
    802 
    803 // Automatically lock and unlock a texture. Since texture locking is fallible,
    804 // Succeeded() must be checked on the guard object before proceeding.
    805 class MOZ_RAII TextureClientAutoLock {
    806 public:
    807  TextureClientAutoLock(TextureClient* aTexture, OpenMode aMode)
    808      : mTexture(aTexture), mSucceeded(false) {
    809    mSucceeded = mTexture->Lock(aMode);
    810 #ifdef DEBUG
    811    mChecked = false;
    812 #endif
    813  }
    814  ~TextureClientAutoLock() {
    815    MOZ_ASSERT(mChecked);
    816    if (mSucceeded) {
    817      mTexture->Unlock();
    818    }
    819  }
    820 
    821  bool Succeeded() {
    822 #ifdef DEBUG
    823    mChecked = true;
    824 #endif
    825    return mSucceeded;
    826  }
    827 
    828 private:
    829  TextureClient* mTexture;
    830 #ifdef DEBUG
    831  bool mChecked;
    832 #endif
    833  bool mSucceeded;
    834 };
    835 
    836 /// Convenience function to set the content of ycbcr texture.
    837 bool UpdateYCbCrTextureClient(TextureClient* aTexture,
    838                              const PlanarYCbCrData& aData);
    839 
    840 TextureType PreferredCanvasTextureType(KnowsCompositor* aKnowsCompositor);
    841 
    842 }  // namespace layers
    843 }  // namespace mozilla
    844 
    845 #endif