gecko-dev/gfx/layers/client/TextureClient.h

833 lines
26 KiB
C++

/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
// * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef MOZILLA_GFX_TEXTURECLIENT_H
#define MOZILLA_GFX_TEXTURECLIENT_H
#include <stddef.h> // for size_t
#include <stdint.h> // for uint32_t, uint8_t, uint64_t
#include "GLTextureImage.h" // for TextureImage
#include "ImageTypes.h" // for StereoMode
#include "mozilla/Assertions.h" // for MOZ_ASSERT, etc
#include "mozilla/Attributes.h" // for override
#include "mozilla/DebugOnly.h"
#include "mozilla/RefPtr.h" // for RefPtr, RefCounted
#include "mozilla/gfx/2D.h" // for DrawTarget
#include "mozilla/gfx/Point.h" // for IntSize
#include "mozilla/gfx/Types.h" // for SurfaceFormat
#include "mozilla/layers/FenceUtils.h" // for FenceHandle
#include "mozilla/ipc/Shmem.h" // for Shmem
#include "mozilla/layers/AtomicRefCountedWithFinalize.h"
#include "mozilla/layers/CompositorTypes.h" // for TextureFlags, etc
#include "mozilla/layers/LayersTypes.h"
#include "mozilla/layers/LayersSurfaces.h" // for SurfaceDescriptor
#include "mozilla/mozalloc.h" // for operator delete
#include "mozilla/gfx/CriticalSection.h"
#include "nsCOMPtr.h" // for already_AddRefed
#include "nsISupportsImpl.h" // for TextureImage::AddRef, etc
#include "GfxTexturesReporter.h"
#include "pratom.h"
#include "nsThreadUtils.h"
class gfxImageSurface;
namespace mozilla {
// When defined, we track which pool the tile came from and test for
// any inconsistencies. This can be defined in release build as well.
#ifdef DEBUG
#define GFX_DEBUG_TRACK_CLIENTS_IN_POOL 1
#endif
namespace gl {
class SharedSurface_Gralloc;
}
namespace layers {
class AsyncTransactionWaiter;
class CompositableForwarder;
class GrallocTextureData;
class ClientIPCAllocator;
class CompositableClient;
struct PlanarYCbCrData;
class Image;
class PTextureChild;
class TextureChild;
class TextureData;
struct RawTextureBuffer;
class RawYCbCrTextureBuffer;
class TextureClient;
class ITextureClientRecycleAllocator;
#ifdef GFX_DEBUG_TRACK_CLIENTS_IN_POOL
class TextureClientPool;
#endif
class TextureForwarder;
class KeepAlive;
/**
* TextureClient is the abstraction that allows us to share data between the
* content and the compositor side.
*/
enum TextureAllocationFlags {
ALLOC_DEFAULT = 0,
ALLOC_CLEAR_BUFFER = 1 << 1, // Clear the buffer to whatever is best for the draw target
ALLOC_CLEAR_BUFFER_WHITE = 1 << 2, // explicit all white
ALLOC_CLEAR_BUFFER_BLACK = 1 << 3, // explicit all black
ALLOC_DISALLOW_BUFFERTEXTURECLIENT = 1 << 4,
// Allocate the texture for out-of-band content updates. This is mostly for
// TextureClientD3D11, which may otherwise choose D3D10 or non-KeyedMutex
// surfaces when used on the main thread.
ALLOC_FOR_OUT_OF_BAND_CONTENT = 1 << 5,
// Disable any cross-device synchronization. This is also for TextureClientD3D11,
// and creates a texture without KeyedMutex.
ALLOC_MANUAL_SYNCHRONIZATION = 1 << 6,
};
#ifdef XP_WIN
typedef void* SyncHandle;
#else
typedef uintptr_t SyncHandle;
#endif // XP_WIN
class SyncObject : public RefCounted<SyncObject>
{
public:
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(SyncObject)
virtual ~SyncObject() { }
static already_AddRefed<SyncObject> CreateSyncObject(SyncHandle aHandle);
enum class SyncType {
D3D11,
};
virtual SyncType GetSyncType() = 0;
virtual void FinalizeFrame() = 0;
protected:
SyncObject() { }
};
/**
* This class may be used to asynchronously receive an update when the content
* drawn to this texture client is available for reading in CPU memory. This
* can only be used on texture clients that support draw target creation.
*/
class TextureReadbackSink
{
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(TextureReadbackSink)
public:
/**
* Callback function to implement in order to receive a DataSourceSurface
* containing the data read back from the texture client. This will always
* be called on the main thread, and this may not hold on to the
* DataSourceSurface beyond the execution of this function.
*/
virtual void ProcessReadback(gfx::DataSourceSurface *aSourceSurface) = 0;
protected:
virtual ~TextureReadbackSink() {}
};
enum class BackendSelector
{
Content,
Canvas
};
/// Temporary object providing direct access to a Texture's memory.
///
/// see TextureClient::CanExposeMappedData() and TextureClient::BorrowMappedData().
struct MappedTextureData
{
uint8_t* data;
gfx::IntSize size;
int32_t stride;
gfx::SurfaceFormat format;
};
struct MappedYCbCrChannelData
{
uint8_t* data;
gfx::IntSize size;
int32_t stride;
int32_t skip;
bool CopyInto(MappedYCbCrChannelData& aDst);
};
struct MappedYCbCrTextureData {
MappedYCbCrChannelData y;
MappedYCbCrChannelData cb;
MappedYCbCrChannelData cr;
// Sad but because of how SharedPlanarYCbCrData is used we have to expose this for now.
uint8_t* metadata;
StereoMode stereoMode;
bool CopyInto(MappedYCbCrTextureData& aDst)
{
return y.CopyInto(aDst.y)
&& cb.CopyInto(aDst.cb)
&& cr.CopyInto(aDst.cr);
}
};
class ReadLockDescriptor;
// A class to help implement copy-on-write semantics for shared textures.
//
// A TextureClient/Host pair can opt into using a ReadLock by calling
// TextureClient::EnableReadLock. This will equip the TextureClient with a
// ReadLock object that will be automatically ReadLock()'ed by the texture itself
// when it is written into (see TextureClient::Unlock).
// A TextureReadLock's counter starts at 1 and is expected to be equal to 1 when the
// lock is destroyed. See ShmemTextureReadLock for explanations about why we use
// 1 instead of 0 as the initial state.
// TextureReadLock is mostly internally managed by the TextureClient/Host pair,
// and the compositable only has to forward it during updates. If an update message
// contains a null_t lock, it means that the texture was not written into on the
// content side, and there is no synchronization required on the compositor side
// (or it means that the texture pair did not opt into using ReadLocks).
// On the compositor side, the TextureHost can receive a ReadLock during a
// transaction, and will both ReadUnlock() it and drop it as soon as the shared
// data is available again for writing (the texture upload is done, or the compositor
// not reading the texture anymore). The lock is dropped to make sure it is
// ReadUnlock()'ed only once.
class TextureReadLock {
protected:
virtual ~TextureReadLock() {}
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(TextureReadLock)
virtual int32_t ReadLock() = 0;
virtual int32_t ReadUnlock() = 0;
virtual int32_t GetReadCount() = 0;
virtual bool IsValid() const = 0;
static already_AddRefed<TextureReadLock>
Create(ClientIPCAllocator* aAllocator);
static already_AddRefed<TextureReadLock>
Deserialize(const ReadLockDescriptor& aDescriptor, ISurfaceAllocator* aAllocator);
virtual bool Serialize(ReadLockDescriptor& aOutput) = 0;
enum LockType {
TYPE_MEMORY,
TYPE_SHMEM
};
virtual LockType GetType() = 0;
protected:
NS_DECL_OWNINGTHREAD
};
#ifdef XP_WIN
class D3D11TextureData;
#endif
class TextureData {
public:
struct Info {
gfx::IntSize size;
gfx::SurfaceFormat format;
bool hasIntermediateBuffer;
bool hasSynchronization;
bool supportsMoz2D;
bool canExposeMappedData;
Info()
: format(gfx::SurfaceFormat::UNKNOWN)
, hasIntermediateBuffer(false)
, hasSynchronization(false)
, supportsMoz2D(false)
, canExposeMappedData(false)
{}
};
TextureData() { MOZ_COUNT_CTOR(TextureData); }
virtual ~TextureData() { MOZ_COUNT_DTOR(TextureData); }
virtual void FillInfo(TextureData::Info& aInfo) const = 0;
virtual bool Lock(OpenMode aMode, FenceHandle* aFence) = 0;
virtual void Unlock() = 0;
virtual already_AddRefed<gfx::DrawTarget> BorrowDrawTarget() { return nullptr; }
virtual bool BorrowMappedData(MappedTextureData&) { return false; }
virtual bool BorrowMappedYCbCrData(MappedYCbCrTextureData&) { return false; }
virtual void Deallocate(ClientIPCAllocator* aAllocator) = 0;
/// Depending on the texture's flags either Deallocate or Forget is called.
virtual void Forget(ClientIPCAllocator* aAllocator) {}
virtual bool Serialize(SurfaceDescriptor& aDescriptor) = 0;
virtual TextureData*
CreateSimilar(ClientIPCAllocator* aAllocator,
TextureFlags aFlags = TextureFlags::DEFAULT,
TextureAllocationFlags aAllocFlags = ALLOC_DEFAULT) const { return nullptr; }
virtual bool UpdateFromSurface(gfx::SourceSurface* aSurface) { return false; };
virtual bool ReadBack(TextureReadbackSink* aReadbackSink) { return false; }
/// Ideally this should not be exposed and users of TextureClient would use Lock/Unlock
/// preoperly but that requires a few changes to SharedSurface and maybe gonk video.
virtual void WaitForFence(FenceHandle* aFence) {};
virtual void SyncWithObject(SyncObject* aFence) {};
virtual TextureFlags GetTextureFlags() const { return TextureFlags::NO_FLAGS; }
#ifdef XP_WIN
virtual D3D11TextureData* AsD3D11TextureData() {
return nullptr;
}
#endif
virtual GrallocTextureData* AsGrallocTextureData() { return nullptr; }
};
/**
* TextureClient is a thin abstraction over texture data that need to be shared
* between the content process and the compositor process. It is the
* content-side half of a TextureClient/TextureHost pair. A corresponding
* TextureHost lives on the compositor-side.
*
* TextureClient's primary purpose is to present texture data in a way that is
* understood by the IPC system. There are two ways to use it:
* - Use it to serialize image data that is not IPC-friendly (most likely
* involving a copy into shared memory)
* - preallocate it and paint directly into it, which avoids copy but requires
* the painting code to be aware of TextureClient (or at least the underlying
* shared memory).
*
* There is always one and only one TextureClient per TextureHost, and the
* TextureClient/Host pair only owns one buffer of image data through its
* lifetime. This means that the lifetime of the underlying shared data
* matches the lifetime of the TextureClient/Host pair. It also means
* TextureClient/Host do not implement double buffering, which is the
* responsibility of the compositable (which would use two Texture pairs).
* In order to send several different buffers to the compositor side, use
* several TextureClients.
*/
class TextureClient
: public AtomicRefCountedWithFinalize<TextureClient>
{
public:
explicit TextureClient(TextureData* aData, TextureFlags aFlags, ClientIPCAllocator* aAllocator);
virtual ~TextureClient();
static already_AddRefed<TextureClient>
CreateWithData(TextureData* aData, TextureFlags aFlags, ClientIPCAllocator* aAllocator);
// Creates and allocates a TextureClient usable with Moz2D.
static already_AddRefed<TextureClient>
CreateForDrawing(TextureForwarder* aAllocator,
gfx::SurfaceFormat aFormat,
gfx::IntSize aSize,
BackendSelector aSelector,
TextureFlags aTextureFlags,
TextureAllocationFlags flags = ALLOC_DEFAULT);
// Creates and allocates a TextureClient supporting the YCbCr format.
static already_AddRefed<TextureClient>
CreateForYCbCr(ClientIPCAllocator* aAllocator,
gfx::IntSize aYSize,
gfx::IntSize aCbCrSize,
StereoMode aStereoMode,
TextureFlags aTextureFlags);
// Creates and allocates a TextureClient (can be accessed through raw
// pointers).
static already_AddRefed<TextureClient>
CreateForRawBufferAccess(ClientIPCAllocator* aAllocator,
gfx::SurfaceFormat aFormat,
gfx::IntSize aSize,
gfx::BackendType aMoz2dBackend,
TextureFlags aTextureFlags,
TextureAllocationFlags flags = ALLOC_DEFAULT);
// Creates and allocates a TextureClient (can beaccessed through raw
// pointers) with a certain buffer size. It's unfortunate that we need this.
// providing format and sizes could let us do more optimization.
static already_AddRefed<TextureClient>
CreateForYCbCrWithBufferSize(ClientIPCAllocator* aAllocator,
gfx::SurfaceFormat aFormat,
size_t aSize,
TextureFlags aTextureFlags);
// Creates and allocates a TextureClient of the same type.
already_AddRefed<TextureClient>
CreateSimilar(TextureFlags aFlags = TextureFlags::DEFAULT,
TextureAllocationFlags aAllocFlags = ALLOC_DEFAULT) const;
/**
* Locks the shared data, allowing the caller to get access to it.
*
* Please always lock/unlock when accessing the shared data.
* If Lock() returns false, you should not attempt to access the shared data.
*/
bool Lock(OpenMode aMode);
void Unlock();
bool IsLocked() const { return mIsLocked; }
gfx::IntSize GetSize() const { return mInfo.size; }
gfx::SurfaceFormat GetFormat() const { return mInfo.format; }
/**
* Returns true if this texture has a synchronization mechanism (mutex, fence, etc.).
* Textures that do not implement synchronization should be immutable or should
* use immediate uploads (see TextureFlags in CompositorTypes.h)
* Even if a texture does not implement synchronization, Lock and Unlock need
* to be used appropriately since the latter are also there to map/numap data.
*/
bool HasSynchronization() const { return mInfo.hasSynchronization; }
/**
* Indicates whether the TextureClient implementation is backed by an
* in-memory buffer. The consequence of this is that locking the
* TextureClient does not contend with locking the texture on the host side.
*/
bool HasIntermediateBuffer() const { return mInfo.hasIntermediateBuffer; }
bool CanExposeDrawTarget() const { return mInfo.supportsMoz2D; }
bool CanExposeMappedData() const { return mInfo.canExposeMappedData; }
/**
* Returns a DrawTarget to draw into the TextureClient.
* This function should never be called when not on the main thread!
*
* This must never be called on a TextureClient that is not sucessfully locked.
* When called several times within one Lock/Unlock pair, this method should
* return the same DrawTarget.
* The DrawTarget is automatically flushed by the TextureClient when the latter
* is unlocked, and the DrawTarget that will be returned within the next
* lock/unlock pair may or may not be the same object.
* Do not keep references to the DrawTarget outside of the lock/unlock pair.
*
* This is typically used as follows:
*
* if (!texture->Lock(OpenMode::OPEN_READ_WRITE)) {
* return false;
* }
* {
* // Restrict this code's scope to ensure all references to dt are gone
* // when Unlock is called.
* DrawTarget* dt = texture->BorrowDrawTarget();
* // use the draw target ...
* }
* texture->Unlock();
*
*/
gfx::DrawTarget* BorrowDrawTarget();
/**
* Similar to BorrowDrawTarget but provides direct access to the texture's bits
* instead of a DrawTarget.
*/
bool BorrowMappedData(MappedTextureData&);
bool BorrowMappedYCbCrData(MappedYCbCrTextureData&);
/**
* This function can be used to update the contents of the TextureClient
* off the main thread.
*/
void UpdateFromSurface(gfx::SourceSurface* aSurface);
/**
* This method is strictly for debugging. It causes locking and
* needless copies.
*/
already_AddRefed<gfx::DataSourceSurface> GetAsSurface();
virtual void PrintInfo(std::stringstream& aStream, const char* aPrefix);
/**
* Copies a rectangle from this texture client to a position in aTarget.
* It is assumed that the necessary locks are in place; so this should at
* least have a read lock and aTarget should at least have a write lock.
*/
bool CopyToTextureClient(TextureClient* aTarget,
const gfx::IntRect* aRect,
const gfx::IntPoint* aPoint);
/**
* Allocate and deallocate a TextureChild actor.
*
* TextureChild is an implementation detail of TextureClient that is not
* exposed to the rest of the code base. CreateIPDLActor and DestroyIPDLActor
* are for use with the managing IPDL protocols only (so that they can
* implement AllocPextureChild and DeallocPTextureChild).
*/
static PTextureChild* CreateIPDLActor();
static bool DestroyIPDLActor(PTextureChild* actor);
// call this if the transaction that was supposed to destroy the actor failed.
static bool DestroyFallback(PTextureChild* actor);
/**
* Get the TextureClient corresponding to the actor passed in parameter.
*/
static already_AddRefed<TextureClient> AsTextureClient(PTextureChild* actor);
/**
* TextureFlags contain important information about various aspects
* of the texture, like how its liferime is managed, and how it
* should be displayed.
* See TextureFlags in CompositorTypes.h.
*/
TextureFlags GetFlags() const { return mFlags; }
bool HasFlags(TextureFlags aFlags) const
{
return (mFlags & aFlags) == aFlags;
}
void AddFlags(TextureFlags aFlags);
void RemoveFlags(TextureFlags aFlags);
// The TextureClient must not be locked when calling this method.
void RecycleTexture(TextureFlags aFlags);
/**
* After being shared with the compositor side, an immutable texture is never
* modified, it can only be read. It is safe to not Lock/Unlock immutable
* textures.
*/
bool IsImmutable() const { return !!(mFlags & TextureFlags::IMMUTABLE); }
void MarkImmutable() { AddFlags(TextureFlags::IMMUTABLE); }
bool IsSharedWithCompositor() const;
/**
* If this method returns false users of TextureClient are not allowed
* to access the shared data.
*/
bool IsValid() const { return !!mData; }
/**
* Called when TextureClient is added to CompositableClient.
*/
void SetAddedToCompositableClient();
/**
* If this method retuns false, TextureClient is already added to CompositableClient,
* since its creation or recycling.
*/
bool IsAddedToCompositableClient() const { return mAddedToCompositableClient; }
/**
* Create and init the TextureChild/Parent IPDL actor pair.
*
* Should be called only once per TextureClient.
* The TextureClient must not be locked when calling this method.
*/
bool InitIPDLActor(CompositableForwarder* aForwarder);
/**
* Return a pointer to the IPDLActor.
*
* This is to be used with IPDL messages only. Do not store the returned
* pointer.
*/
PTextureChild* GetIPDLActor();
/**
* Triggers the destruction of the shared data and the corresponding TextureHost.
*
* If the texture flags contain TextureFlags::DEALLOCATE_CLIENT, the destruction
* will be synchronously coordinated with the compositor side, otherwise it
* will be done asynchronously.
* If sync is true, the destruction will be synchronous regardless of the
* texture's flags (bad for performance, use with care).
*/
void Destroy(bool sync = false);
virtual void SetReleaseFenceHandle(const FenceHandle& aReleaseFenceHandle)
{
mReleaseFenceHandle.Merge(aReleaseFenceHandle);
}
virtual FenceHandle GetAndResetReleaseFenceHandle()
{
FenceHandle fence;
mReleaseFenceHandle.TransferToAnotherFenceHandle(fence);
return fence;
}
virtual void SetAcquireFenceHandle(const FenceHandle& aAcquireFenceHandle)
{
mAcquireFenceHandle = aAcquireFenceHandle;
}
virtual const FenceHandle& GetAcquireFenceHandle() const
{
return mAcquireFenceHandle;
}
/**
* This function waits until the buffer is no longer being used.
*
* XXX - Ideally we shouldn't need this method because Lock the right
* thing already.
*/
virtual void WaitForBufferOwnership(bool aWaitReleaseFence = true);
/**
* Track how much of this texture is wasted.
* For example we might allocate a 256x256 tile but only use 10x10.
*/
void SetWaste(int aWasteArea) {
mWasteTracker.Update(aWasteArea, BytesPerPixel(GetFormat()));
}
/**
* This sets the readback sink that this texture is to use. This will
* receive the data for this texture as soon as it becomes available after
* texture unlock.
*/
virtual void SetReadbackSink(TextureReadbackSink* aReadbackSink) {
mReadbackSink = aReadbackSink;
}
void SyncWithObject(SyncObject* aFence) { mData->SyncWithObject(aFence); }
ClientIPCAllocator* GetAllocator() { return mAllocator; }
ITextureClientRecycleAllocator* GetRecycleAllocator() { return mRecycleAllocator; }
void SetRecycleAllocator(ITextureClientRecycleAllocator* aAllocator);
/// If you add new code that uses this method, you are probably doing something wrong.
TextureData* GetInternalData() { return mData; }
const TextureData* GetInternalData() const { return mData; }
uint64_t GetSerial() const { return mSerial; }
bool NeedsFenceHandle()
{
#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17
if (!mData) {
return false;
}
return !!mData->AsGrallocTextureData();
#else
return false;
#endif
}
void WaitFenceHandleOnImageBridge(Mutex& aMutex);
void ClearWaitFenceHandleOnImageBridge(Mutex& aMutex);
void CancelWaitFenceHandleOnImageBridge();
void CancelWaitForRecycle();
/**
* Set last transaction id of CompositableForwarder.
*
* Called when TextureClient has TextureFlags::RECYCLE flag.
* When CompositableForwarder forwards the TextureClient with
* TextureFlags::RECYCLE, it holds TextureClient's ref until host side
* releases it. The host side sends TextureClient release message.
* The id is used to check if the message is for the last TextureClient
* forwarding.
*/
void SetLastFwdTransactionId(uint64_t aTransactionId)
{
MOZ_ASSERT(mFwdTransactionId < aTransactionId);
mFwdTransactionId = aTransactionId;
}
uint64_t GetLastFwdTransactionId() { return mFwdTransactionId; }
void EnableReadLock();
TextureReadLock* GetReadLock() { return mReadLock; }
bool IsReadLocked() const;
void SerializeReadLock(ReadLockDescriptor& aDescriptor);
private:
static void TextureClientRecycleCallback(TextureClient* aClient, void* aClosure);
/**
* Called once, during the destruction of the Texture, on the thread in which
* texture's reference count reaches 0 (could be any thread).
*
* Here goes the shut-down code that uses virtual methods.
* Must only be called by Release().
*/
void Finalize() {}
friend class AtomicRefCountedWithFinalize<TextureClient>;
friend class gl::SharedSurface_Gralloc;
protected:
/**
* Should only be called *once* per texture, in TextureClient::InitIPDLActor.
* Some texture implementations rely on the fact that the descriptor will be
* deserialized.
* Calling ToSurfaceDescriptor again after it has already returned true,
* or never constructing a TextureHost with aDescriptor may result in a memory
* leak (see TextureClientD3D9 for example).
*/
bool ToSurfaceDescriptor(SurfaceDescriptor& aDescriptor);
void LockActor() const;
void UnlockActor() const;
TextureData::Info mInfo;
RefPtr<ClientIPCAllocator> mAllocator;
RefPtr<TextureChild> mActor;
RefPtr<ITextureClientRecycleAllocator> mRecycleAllocator;
RefPtr<TextureReadLock> mReadLock;
TextureData* mData;
RefPtr<gfx::DrawTarget> mBorrowedDrawTarget;
TextureFlags mFlags;
FenceHandle mReleaseFenceHandle;
FenceHandle mAcquireFenceHandle;
RefPtr<AsyncTransactionWaiter> mFenceHandleWaiter;
gl::GfxTextureWasteTracker mWasteTracker;
OpenMode mOpenMode;
#ifdef DEBUG
uint32_t mExpectedDtRefs;
#endif
bool mIsLocked;
// This member tracks that the texture was written into until the update
// is sent to the compositor. We need this remember to lock mReadLock on
// behalf of the compositor just before sending the notification.
bool mUpdated;
bool mAddedToCompositableClient;
bool mWorkaroundAnnoyingSharedSurfaceLifetimeIssues;
bool mWorkaroundAnnoyingSharedSurfaceOwnershipIssues;
RefPtr<TextureReadbackSink> mReadbackSink;
uint64_t mFwdTransactionId;
// Serial id of TextureClient. It is unique in current process.
const uint64_t mSerial;
// Used to assign serial ids of TextureClient.
static mozilla::Atomic<uint64_t> sSerialCounter;
friend class TextureChild;
friend class RemoveTextureFromCompositableTracker;
friend void TestTextureClientSurface(TextureClient*, gfxImageSurface*);
friend void TestTextureClientYCbCr(TextureClient*, PlanarYCbCrData&);
#ifdef GFX_DEBUG_TRACK_CLIENTS_IN_POOL
public:
// Pointer to the pool this tile came from.
TextureClientPool* mPoolTracker;
#endif
};
/**
* Task that releases TextureClient pointer on a specified thread.
*/
class TextureClientReleaseTask : public Runnable
{
public:
explicit TextureClientReleaseTask(TextureClient* aClient)
: mTextureClient(aClient) {
}
NS_IMETHOD Run() override
{
mTextureClient = nullptr;
return NS_OK;
}
private:
RefPtr<TextureClient> mTextureClient;
};
// Automatically lock and unlock a texture. Since texture locking is fallible,
// Succeeded() must be checked on the guard object before proceeding.
class MOZ_RAII TextureClientAutoLock
{
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER;
public:
TextureClientAutoLock(TextureClient* aTexture, OpenMode aMode
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
: mTexture(aTexture),
mSucceeded(false)
{
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
mSucceeded = mTexture->Lock(aMode);
#ifdef DEBUG
mChecked = false;
#endif
}
~TextureClientAutoLock() {
MOZ_ASSERT(mChecked);
if (mSucceeded) {
mTexture->Unlock();
}
}
bool Succeeded() {
#ifdef DEBUG
mChecked = true;
#endif
return mSucceeded;
}
private:
TextureClient* mTexture;
#ifdef DEBUG
bool mChecked;
#endif
bool mSucceeded;
};
class KeepAlive
{
public:
virtual ~KeepAlive() {}
};
template<typename T>
class TKeepAlive : public KeepAlive
{
public:
explicit TKeepAlive(T* aData) : mData(aData) {}
protected:
RefPtr<T> mData;
};
/// Convenience function to set the content of ycbcr texture.
bool UpdateYCbCrTextureClient(TextureClient* aTexture, const PlanarYCbCrData& aData);
} // namespace layers
} // namespace mozilla
#endif