gecko/gfx/layers/client/TextureClient.h
Blair McBride 3b0373f215 Backed out 9 changesets (bug 987311, bug 989027, bug 989144). r=sheriff
Backed out changeset 046c061d91c2 (bug 989144)
Backed out changeset 3f1b41adeaef (bug 987311)
Backed out changeset 8d5a171564bd (bug 987311)
Backed out changeset dcc0d016de7a (bug 987311)
Backed out changeset 27f338fbc835 (bug 989027)
Backed out changeset 4a67f5144ea4 (bug 989027)
Backed out changeset 62ba0a377450 (bug 987311)
Backed out changeset 6a2542a5c865 (bug 987311)
Backed out changeset 1dfd9a457f34 (bug 987311)
2014-04-27 19:45:08 +12:00

534 lines
18 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 "GLContextTypes.h" // for GLContext (ptr only), etc
#include "GLTextureImage.h" // for TextureImage
#include "ImageTypes.h" // for StereoMode
#include "mozilla/Assertions.h" // for MOZ_ASSERT, etc
#include "mozilla/Attributes.h" // for MOZ_OVERRIDE
#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/LayersSurfaces.h" // for SurfaceDescriptor
#include "mozilla/layers/PTextureChild.h" // for PTextureChild
#include "mozilla/mozalloc.h" // for operator delete
#include "nsAutoPtr.h" // for nsRefPtr
#include "nsCOMPtr.h" // for already_AddRefed
#include "nsISupportsImpl.h" // for TextureImage::AddRef, etc
class gfxReusableSurfaceWrapper;
class gfxImageSurface;
namespace mozilla {
namespace layers {
class ContentClient;
class CompositableForwarder;
class ISurfaceAllocator;
class CompositableClient;
class PlanarYCbCrImage;
class PlanarYCbCrData;
class Image;
class PTextureChild;
class TextureChild;
class BufferTextureClient;
class TextureClient;
/**
* 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
};
/**
* Interface for TextureClients that can be updated using YCbCr data.
*/
class TextureClientYCbCr
{
public:
/**
* Copy aData into this texture client.
*
* This must never be called on a TextureClient that is not sucessfully locked.
*/
virtual bool UpdateYCbCr(const PlanarYCbCrData& aData) = 0;
/**
* Allocates for a given surface size, taking into account the pixel format
* which is part of the state of the TextureClient.
*
* Does not clear the surface, since we consider that the surface
* be painted entirely with opaque content.
*/
virtual bool AllocateForYCbCr(gfx::IntSize aYSize,
gfx::IntSize aCbCrSize,
StereoMode aStereoMode) = 0;
};
/**
* Holds the shared data of a TextureClient, to be destroyed later.
*
* TextureClient's destructor initiates the destruction sequence of the
* texture client/host pair. If the shared data is to be deallocated on the
* host side, there is nothing to do.
* On the other hand, if the client data must be deallocated on the client
* side, the CompositableClient will ask the TextureClient to drop its shared
* data in the form of a TextureClientData object. This data will be kept alive
* until the host side confirms that it is not using the data anymore and that
* it is completely safe to deallocate the shared data.
*
* See:
* - The PTexture IPDL protocol
* - CompositableChild in TextureClient.cpp
*/
class TextureClientData {
public:
virtual void DeallocateSharedData(ISurfaceAllocator* allocator) = 0;
virtual ~TextureClientData() {}
};
/**
* 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:
TextureClient(TextureFlags aFlags = TEXTURE_FLAGS_DEFAULT);
virtual ~TextureClient();
static TemporaryRef<BufferTextureClient>
CreateBufferTextureClient(ISurfaceAllocator* aAllocator,
gfx::SurfaceFormat aFormat,
TextureFlags aTextureFlags,
gfx::BackendType aMoz2dBackend);
static TemporaryRef<TextureClient>
CreateTextureClientForDrawing(ISurfaceAllocator* aAllocator,
gfx::SurfaceFormat aFormat,
TextureFlags aTextureFlags,
gfx::BackendType aMoz2dBackend,
const gfx::IntSize& aSizeHint);
virtual TextureClientYCbCr* AsTextureClientYCbCr() { return nullptr; }
/**
* 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.
*/
virtual bool Lock(OpenMode aMode) { return IsValid(); }
virtual void Unlock() {}
virtual bool IsLocked() const = 0;
virtual bool CanExposeDrawTarget() const { return false; }
/**
* Returns a DrawTarget to draw into the TextureClient.
*
* 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(OPEN_READ_WRITE)) {
* return false;
* }
* {
* // Restrict this code's scope to ensure all references to dt are gone
* // when Unlock is called.
* RefPtr<DrawTarget> dt = texture->GetAsDrawTarget();
* // use the draw target ...
* }
* texture->Unlock();
*
*/
virtual TemporaryRef<gfx::DrawTarget> GetAsDrawTarget() { return nullptr; }
// TextureClients that can expose a DrawTarget should override this method.
virtual gfx::SurfaceFormat GetFormat() const
{
return gfx::SurfaceFormat::UNKNOWN;
}
/**
* Allocates for a given surface size, taking into account the pixel format
* which is part of the state of the TextureClient.
*
* Does not clear the surface by default, clearing the surface can be done
* by passing the CLEAR_BUFFER flag.
*
* TextureClients that can expose a DrawTarget should override this method.
*/
virtual bool AllocateForSurface(gfx::IntSize aSize,
TextureAllocationFlags flags = ALLOC_DEFAULT)
{
return false;
}
/**
* 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.
*/
virtual bool CopyToTextureClient(TextureClient* aTarget,
const gfx::IntRect* aRect,
const gfx::IntPoint* aPoint);
/**
* Returns true if this texture has a lock/unlock mechanism.
* Textures that do not implement locking should be immutable or should
* use immediate uploads (see TextureFlags in CompositorTypes.h)
*/
virtual bool ImplementsLocking() const { return false; }
/**
* 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.
*/
virtual bool HasInternalBuffer() const = 0;
/**
* 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);
/**
* Get the TextureClient corresponding to the actor passed in parameter.
*/
static TextureClient* AsTextureClient(PTextureChild* actor);
virtual bool IsAllocated() const = 0;
virtual gfx::IntSize GetSize() const = 0;
/**
* 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; }
/**
* valid only for TEXTURE_RECYCLE TextureClient.
* When called this texture client will grab a strong reference and release
* it once the compositor notifies that it is done with the texture.
* NOTE: In this stage the texture client can no longer be used by the
* client in a transaction.
*/
void WaitForCompositorRecycle();
/**
* 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 & TEXTURE_IMMUTABLE; }
void MarkImmutable() { AddFlags(TEXTURE_IMMUTABLE); }
bool IsSharedWithCompositor() const { return mShared; }
bool ShouldDeallocateInDestructor() const;
/**
* If this method returns false users of TextureClient are not allowed
* to access the shared data.
*/
bool IsValid() const { return mValid; }
/**
* Create and init the TextureChild/Parent IPDL actor pair.
*
* Should be called only once per TextureClient.
*/
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 TEXTURE_DEALLOCATE_CLIENT, the destruction
* will be synchronously coordinated with the compositor side, otherwise it
* will be done asynchronously.
*/
void ForceRemove();
virtual void SetReleaseFenceHandle(FenceHandle aReleaseFenceHandle) {}
const FenceHandle& GetReleaseFenceHandle() const
{
return mReleaseFenceHandle;
}
/**
* Wait until the current buffer is no longer being read.
*
* Platform support is necessary. gonk JB supports this function.
*/
virtual void WaitReleaseFence() {}
private:
/**
* Called once, just before the destructor.
*
* Here goes the shut-down code that uses virtual methods.
* Must only be called by Release().
*/
void Finalize();
friend class AtomicRefCountedWithFinalize<TextureClient>;
protected:
/**
* An invalid TextureClient cannot provide access to its shared data
* anymore. This usually means it will soon be destroyed.
*/
void MarkInvalid() { mValid = false; }
/**
* Drop the shared data into a TextureClientData object and mark this
* TextureClient as invalid.
*
* The TextureClient must not hold any reference to the shared data
* after this method has been called.
* The TextureClientData is owned by the caller.
*/
virtual TextureClientData* DropTextureData() = 0;
/**
* 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 CairoTextureClientD3D9 for example).
*/
virtual bool ToSurfaceDescriptor(SurfaceDescriptor& aDescriptor) = 0;
void AddFlags(TextureFlags aFlags)
{
MOZ_ASSERT(!IsSharedWithCompositor());
mFlags |= aFlags;
}
RefPtr<TextureChild> mActor;
TextureFlags mFlags;
bool mShared;
bool mValid;
FenceHandle mReleaseFenceHandle;
friend class TextureChild;
friend void TestTextureClientSurface(TextureClient*, gfxImageSurface*);
friend void TestTextureClientYCbCr(TextureClient*, PlanarYCbCrData&);
};
/**
* TextureClient that wraps a random access buffer such as a Shmem or raw memory.
* This class must be inherited to implement the memory allocation and access bits.
* (see ShmemTextureClient and MemoryTextureClient)
*/
class BufferTextureClient : public TextureClient
, public TextureClientYCbCr
{
public:
BufferTextureClient(ISurfaceAllocator* aAllocator, gfx::SurfaceFormat aFormat,
gfx::BackendType aBackend, TextureFlags aFlags);
virtual ~BufferTextureClient();
virtual bool IsAllocated() const = 0;
virtual uint8_t* GetBuffer() const = 0;
virtual gfx::IntSize GetSize() const { return mSize; }
virtual bool Lock(OpenMode aMode) MOZ_OVERRIDE;
virtual void Unlock() MOZ_OVERRIDE;
virtual bool IsLocked() const MOZ_OVERRIDE { return mLocked; }
virtual bool CanExposeDrawTarget() const MOZ_OVERRIDE { return true; }
virtual TemporaryRef<gfx::DrawTarget> GetAsDrawTarget() MOZ_OVERRIDE;
virtual bool AllocateForSurface(gfx::IntSize aSize,
TextureAllocationFlags aFlags = ALLOC_DEFAULT) MOZ_OVERRIDE;
// TextureClientYCbCr
virtual TextureClientYCbCr* AsTextureClientYCbCr() MOZ_OVERRIDE { return this; }
virtual bool UpdateYCbCr(const PlanarYCbCrData& aData) MOZ_OVERRIDE;
virtual bool AllocateForYCbCr(gfx::IntSize aYSize,
gfx::IntSize aCbCrSize,
StereoMode aStereoMode) MOZ_OVERRIDE;
virtual gfx::SurfaceFormat GetFormat() const MOZ_OVERRIDE { return mFormat; }
// XXX - Bug 908196 - Make Allocate(uint32_t) and GetBufferSize() protected.
// these two methods should only be called by methods of BufferTextureClient
// that are overridden in GrallocTextureClient (which does not implement the
// two methods below)
virtual bool Allocate(uint32_t aSize) = 0;
virtual size_t GetBufferSize() const = 0;
virtual bool HasInternalBuffer() const MOZ_OVERRIDE { return true; }
ISurfaceAllocator* GetAllocator() const;
protected:
RefPtr<gfx::DrawTarget> mDrawTarget;
RefPtr<ISurfaceAllocator> mAllocator;
gfx::SurfaceFormat mFormat;
gfx::IntSize mSize;
gfx::BackendType mBackend;
OpenMode mOpenMode;
bool mUsingFallbackDrawTarget;
bool mLocked;
};
/**
* TextureClient that wraps shared memory.
* the corresponding texture on the host side is ShmemTextureHost.
*/
class ShmemTextureClient : public BufferTextureClient
{
public:
ShmemTextureClient(ISurfaceAllocator* aAllocator, gfx::SurfaceFormat aFormat,
gfx::BackendType aBackend, TextureFlags aFlags);
~ShmemTextureClient();
virtual bool ToSurfaceDescriptor(SurfaceDescriptor& aDescriptor) MOZ_OVERRIDE;
virtual bool Allocate(uint32_t aSize) MOZ_OVERRIDE;
virtual uint8_t* GetBuffer() const MOZ_OVERRIDE;
virtual size_t GetBufferSize() const MOZ_OVERRIDE;
virtual bool IsAllocated() const MOZ_OVERRIDE { return mAllocated; }
virtual TextureClientData* DropTextureData() MOZ_OVERRIDE;
virtual bool HasInternalBuffer() const MOZ_OVERRIDE { return true; }
mozilla::ipc::Shmem& GetShmem() { return mShmem; }
protected:
mozilla::ipc::Shmem mShmem;
bool mAllocated;
};
/**
* TextureClient that wraps raw memory.
* The corresponding texture on the host side is MemoryTextureHost.
* Can obviously not be used in a cross process setup.
*/
class MemoryTextureClient : public BufferTextureClient
{
public:
MemoryTextureClient(ISurfaceAllocator* aAllocator, gfx::SurfaceFormat aFormat,
gfx::BackendType aBackend, TextureFlags aFlags);
~MemoryTextureClient();
virtual bool ToSurfaceDescriptor(SurfaceDescriptor& aDescriptor) MOZ_OVERRIDE;
virtual bool Allocate(uint32_t aSize) MOZ_OVERRIDE;
virtual uint8_t* GetBuffer() const MOZ_OVERRIDE { return mBuffer; }
virtual size_t GetBufferSize() const MOZ_OVERRIDE { return mBufSize; }
virtual bool IsAllocated() const MOZ_OVERRIDE { return mBuffer != nullptr; }
virtual bool HasInternalBuffer() const MOZ_OVERRIDE { return true; }
virtual TextureClientData* DropTextureData() MOZ_OVERRIDE;
protected:
uint8_t* mBuffer;
size_t mBufSize;
};
struct TextureClientAutoUnlock
{
TextureClient* mTexture;
TextureClientAutoUnlock(TextureClient* aTexture)
: mTexture(aTexture) {}
~TextureClientAutoUnlock()
{
mTexture->Unlock();
}
};
}
}
#endif