Bug 1200595 - Gralloc TextureData implementation. r=sotaro

This commit is contained in:
Nicolas Silva 2015-10-15 17:53:37 +02:00
parent 99a692982e
commit 91130f23ca
20 changed files with 535 additions and 524 deletions

View File

@ -354,10 +354,10 @@ OmxDecoder::ReleaseMediaResources() {
for (std::set<TextureClient*>::iterator it=mPendingRecycleTexutreClients.begin();
it!=mPendingRecycleTexutreClients.end(); it++)
{
GrallocTextureClientOGL* client = static_cast<GrallocTextureClientOGL*>(*it);
client->ClearRecycleCallback();
GrallocTextureData* client = static_cast<GrallocTextureData*>((*it)->GetInternalData());
(*it)->ClearRecycleCallback();
if (client->GetMediaBuffer()) {
mPendingVideoBuffers.push(BufferItem(client->GetMediaBuffer(), client->GetAndResetReleaseFenceHandle()));
mPendingVideoBuffers.push(BufferItem(client->GetMediaBuffer(), (*it)->GetAndResetReleaseFenceHandle()));
}
}
mPendingRecycleTexutreClients.clear();
@ -653,8 +653,7 @@ OmxDecoder::ReadVideo(VideoFrame *aFrame, int64_t aTimeUs,
// Manually increment reference count to keep MediaBuffer alive
// during TextureClient is in use.
mVideoBuffer->add_ref();
GrallocTextureClientOGL* grallocClient = static_cast<GrallocTextureClientOGL*>(textureClient.get());
grallocClient->SetMediaBuffer(mVideoBuffer);
static_cast<GrallocTextureData*>(textureClient->GetInternalData())->SetMediaBuffer(mVideoBuffer);
// Set recycle callback for TextureClient
textureClient->SetRecycleCallback(OmxDecoder::RecycleCallback, this);
{
@ -917,9 +916,9 @@ OmxDecoder::RecycleCallbackImp(TextureClient* aClient)
return;
}
mPendingRecycleTexutreClients.erase(aClient);
GrallocTextureClientOGL* client = static_cast<GrallocTextureClientOGL*>(aClient);
if (client->GetMediaBuffer()) {
mPendingVideoBuffers.push(BufferItem(client->GetMediaBuffer(), client->GetAndResetReleaseFenceHandle()));
GrallocTextureData* grallocData = static_cast<GrallocTextureData*>(aClient->GetInternalData());
if (grallocData->GetMediaBuffer()) {
mPendingVideoBuffers.push(BufferItem(grallocData->GetMediaBuffer(), aClient->GetAndResetReleaseFenceHandle()));
}
}
sp<AMessage> notify =

View File

@ -374,14 +374,14 @@ GonkVideoDecoderManager::CreateVideoDataFromGraphicBuffer(MediaBuffer* aSource,
aPicture.height = size.height;
sp<GraphicBuffer> destBuffer =
static_cast<GrallocTextureClientOGL*>(textureClient.get())->GetGraphicBuffer();
static_cast<GrallocTextureData*>(textureClient->GetInternalData())->GetGraphicBuffer();
CopyGraphicBuffer(srcBuffer, destBuffer, aPicture);
} else {
textureClient = mNativeWindow->getTextureClientFromBuffer(srcBuffer.get());
textureClient->SetRecycleCallback(GonkVideoDecoderManager::RecycleCallback, this);
GrallocTextureClientOGL* grallocClient = static_cast<GrallocTextureClientOGL*>(textureClient.get());
grallocClient->SetMediaBuffer(aSource);
static_cast<GrallocTextureData*>(textureClient->GetInternalData())->SetMediaBuffer(aSource);
}
RefPtr<VideoData> data = VideoData::Create(mInfo.mVideo,
@ -683,7 +683,7 @@ GonkVideoDecoderManager::RecycleCallback(TextureClient* aClient, void* aClosure)
{
MOZ_ASSERT(aClient && !aClient->IsDead());
GonkVideoDecoderManager* videoManager = static_cast<GonkVideoDecoderManager*>(aClosure);
GrallocTextureClientOGL* client = static_cast<GrallocTextureClientOGL*>(aClient);
GrallocTextureData* client = static_cast<GrallocTextureData*>(aClient->GetInternalData());
aClient->ClearRecycleCallback();
FenceHandle handle = aClient->GetAndResetReleaseFenceHandle();
videoManager->PostReleaseVideoBuffer(client->GetMediaBuffer(), handle);

View File

@ -763,9 +763,8 @@ MediaEngineGonkVideoSource::RotateImage(layers::Image* aImage, uint32_t aWidth,
layers::TextureFlags::DEFAULT,
layers::ALLOC_DISALLOW_BUFFERTEXTURECLIENT);
if (textureClient) {
RefPtr<layers::GrallocTextureClientOGL> grallocTextureClient = textureClient->AsGrallocTextureClientOGL();
android::sp<android::GraphicBuffer> destBuffer = grallocTextureClient->GetGraphicBuffer();
android::sp<android::GraphicBuffer> destBuffer =
static_cast<layers::GrallocTextureData*>(textureClient->GetInternalData())->GetGraphicBuffer();
void* destMem = nullptr;
destBuffer->lock(android::GraphicBuffer::USAGE_SW_WRITE_OFTEN, &destMem);

View File

@ -63,17 +63,17 @@ SharedSurface_Gralloc::Create(GLContext* prodGL,
gfxContentType type = hasAlpha ? gfxContentType::COLOR_ALPHA
: gfxContentType::COLOR;
typedef GrallocTextureClientOGL ptrT;
RefPtr<ptrT> grallocTC = new ptrT(allocator,
gfxPlatform::GetPlatform()->Optimal2DFormatForContent(type),
gfx::BackendType::NONE, // we don't need to use it with a DrawTarget
flags);
GrallocTextureData* texData = GrallocTextureData::CreateForGLRendering(
size, gfxPlatform::GetPlatform()->Optimal2DFormatForContent(type), allocator
);
if (!grallocTC->AllocateForGLRendering(size)) {
if (!texData) {
return Move(ret);
}
sp<GraphicBuffer> buffer = grallocTC->GetGraphicBuffer();
RefPtr<TextureClient> grallocTC = new ClientTexture(texData, flags, allocator);
sp<GraphicBuffer> buffer = texData->GetGraphicBuffer();
EGLDisplay display = egl->Display();
EGLClientBuffer clientBuffer = buffer->getNativeBuffer();
@ -119,7 +119,7 @@ SharedSurface_Gralloc::SharedSurface_Gralloc(GLContext* prodGL,
bool hasAlpha,
GLLibraryEGL* egl,
layers::ISurfaceAllocator* allocator,
layers::GrallocTextureClientOGL* textureClient,
layers::TextureClient* textureClient,
GLuint prodTex)
: SharedSurface(SharedSurfaceType::Gralloc,
AttachmentType::GLTexture,
@ -287,7 +287,9 @@ bool
SharedSurface_Gralloc::ReadbackBySharedHandle(gfx::DataSourceSurface* out_surface)
{
MOZ_ASSERT(out_surface);
sp<GraphicBuffer> buffer = mTextureClient->GetGraphicBuffer();
sp<GraphicBuffer> buffer = static_cast<GrallocTextureData*>(
mTextureClient->GetInternalData()
)->GetGraphicBuffer();
const uint8_t* grallocData = nullptr;
auto result = buffer->lock(

View File

@ -13,7 +13,7 @@
namespace mozilla {
namespace layers {
class ISurfaceAllocator;
class GrallocTextureClientOGL;
class TextureClient;
}
namespace gl {
@ -41,7 +41,7 @@ protected:
GLLibraryEGL* const mEGL;
EGLSync mSync;
RefPtr<layers::ISurfaceAllocator> mAllocator;
RefPtr<layers::GrallocTextureClientOGL> mTextureClient;
RefPtr<layers::TextureClient> mTextureClient;
const GLuint mProdTex;
SharedSurface_Gralloc(GLContext* prodGL,
@ -49,7 +49,7 @@ protected:
bool hasAlpha,
GLLibraryEGL* egl,
layers::ISurfaceAllocator* allocator,
layers::GrallocTextureClientOGL* textureClient,
layers::TextureClient* textureClient,
GLuint prodTex);
static bool HasExtensions(GLLibraryEGL* egl, GLContext* gl);
@ -70,7 +70,7 @@ public:
return mProdTex;
}
layers::GrallocTextureClientOGL* GetTextureClient() {
layers::TextureClient* GetTextureClient() {
return mTextureClient;
}

View File

@ -36,7 +36,7 @@ public:
StereoMode aStereoMode,
TextureFlags aTextureFlags);
virtual bool Lock(OpenMode aMode) override { return true; }
virtual bool Lock(OpenMode aMode, FenceHandle*) override { return true; }
virtual void Unlock() override {}

View File

@ -73,25 +73,21 @@ GrallocImage::SetData(const Data& aData)
return false;
}
RefPtr<GrallocTextureClientOGL> textureClient =
new GrallocTextureClientOGL(ImageBridgeChild::GetSingleton(),
gfx::SurfaceFormat::UNKNOWN,
gfx::BackendType::NONE);
// GrallocImages are all YUV and don't support alpha.
textureClient->SetIsOpaque(true);
bool result =
textureClient->AllocateGralloc(mData.mYSize,
HAL_PIXEL_FORMAT_YV12,
ISurfaceAllocator* allocator = ImageBridgeChild::GetSingleton();
GrallocTextureData* texData = GrallocTextureData::Create(mData.mYSize, HAL_PIXEL_FORMAT_YV12,
gfx::BackendType::NONE,
GraphicBuffer::USAGE_SW_READ_OFTEN |
GraphicBuffer::USAGE_SW_WRITE_OFTEN |
GraphicBuffer::USAGE_HW_TEXTURE);
sp<GraphicBuffer> graphicBuffer = textureClient->GetGraphicBuffer();
if (!result || !graphicBuffer.get()) {
mTextureClient = nullptr;
GraphicBuffer::USAGE_HW_TEXTURE,
allocator
);
if (!texData) {
return false;
}
mTextureClient = textureClient;
mTextureClient = new ClientTexture(texData, TextureFlags::DEFAULT, allocator);
sp<GraphicBuffer> graphicBuffer = texData->GetGraphicBuffer();
void* vaddr;
if (graphicBuffer->lock(GraphicBuffer::USAGE_SW_WRITE_OFTEN,
@ -150,8 +146,7 @@ GrallocImage::SetData(const Data& aData)
void
GrallocImage::SetData(TextureClient* aGraphicBuffer, const gfx::IntSize& aSize)
{
MOZ_ASSERT(aGraphicBuffer->AsGrallocTextureClientOGL());
mTextureClient = aGraphicBuffer->AsGrallocTextureClientOGL();
mTextureClient = aGraphicBuffer;
mSize = aSize;
}
@ -443,8 +438,7 @@ GrallocImage::GetAsSourceSurface()
return nullptr;
}
android::sp<GraphicBuffer> graphicBuffer =
mTextureClient->GetGraphicBuffer();
android::sp<GraphicBuffer> graphicBuffer = GetGraphicBuffer();
RefPtr<gfx::DataSourceSurface> surface =
GetDataSourceSurfaceFrom(graphicBuffer, mSize, mData);
@ -458,7 +452,7 @@ GrallocImage::GetGraphicBuffer() const
if (!mTextureClient) {
return nullptr;
}
return mTextureClient->GetGraphicBuffer();
return static_cast<GrallocTextureData*>(mTextureClient->GetInternalData())->GetGraphicBuffer();
}
void*
@ -467,8 +461,7 @@ GrallocImage::GetNativeBuffer()
if (!mTextureClient) {
return nullptr;
}
android::sp<android::GraphicBuffer> graphicBuffer =
mTextureClient->GetGraphicBuffer();
android::sp<android::GraphicBuffer> graphicBuffer = GetGraphicBuffer();
if (!graphicBuffer.get()) {
return nullptr;
}

View File

@ -20,7 +20,7 @@
namespace mozilla {
namespace layers {
class GrallocTextureClientOGL;
class TextureClient;
already_AddRefed<gfx::DataSourceSurface>
GetDataSourceSurfaceFrom(android::sp<android::GraphicBuffer>& aGraphicBuffer,
@ -124,7 +124,7 @@ public:
}
private:
RefPtr<GrallocTextureClientOGL> mTextureClient;
RefPtr<TextureClient> mTextureClient;
};
} // namespace layers

View File

@ -14,7 +14,7 @@
namespace mozilla {
namespace layers {
static SurfaceFormat
static gfx::SurfaceFormat
HalFormatToSurfaceFormat(int aHalFormat, TextureFlags aFlags)
{
bool swapRB = bool(aFlags & TextureFlags::RB_SWAPPED);
@ -45,7 +45,7 @@ HalFormatToSurfaceFormat(int aHalFormat, TextureFlags aFlags)
return gfx::SurfaceFormat::R5G6B5_UINT16;
} else {
MOZ_CRASH("Unhandled HAL pixel format");
return SurfaceFormat::UNKNOWN; // not reached
return gfx::SurfaceFormat::UNKNOWN; // not reached
}
}
}
@ -134,7 +134,7 @@ GrallocTextureHostBasic::Lock()
NS_WARNING("Couldn't lock graphic buffer");
return false;
}
surf = Factory::CreateWrappingDataSourceSurface(
surf = gfx::Factory::CreateWrappingDataSourceSurface(
mMappedBuffer,
graphicBuffer->getStride() * gfx::BytesPerPixel(mFormat),
mCropSize,
@ -217,7 +217,7 @@ GrallocTextureHostBasic::WaitAcquireFenceHandleSyncComplete()
void
GrallocTextureHostBasic::SetCropRect(nsIntRect aCropRect)
{
MOZ_ASSERT(aCropRect.TopLeft() == IntPoint(0, 0));
MOZ_ASSERT(aCropRect.TopLeft() == gfx::IntPoint(0, 0));
MOZ_ASSERT(!aCropRect.IsEmpty());
MOZ_ASSERT(aCropRect.width <= mSize.width);
MOZ_ASSERT(aCropRect.height <= mSize.height);

View File

@ -45,7 +45,7 @@ X11TextureData::X11TextureData(gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
}
bool
X11TextureData::Lock(OpenMode aMode)
X11TextureData::Lock(OpenMode aMode, FenceHandle*)
{
return true;
}

View File

@ -21,7 +21,7 @@ public:
virtual bool Serialize(SurfaceDescriptor& aOutDescriptor) override;
virtual bool Lock(OpenMode aMode) override;
virtual bool Lock(OpenMode aMode, FenceHandle*) override;
virtual void Unlock() override;

View File

@ -212,7 +212,7 @@ ClientTexture::Lock(OpenMode aMode)
return mOpenMode == aMode;
}
mIsLocked = mData->Lock(aMode);
mIsLocked = mData->Lock(aMode, mReleaseFenceHandle.IsValid() ? &mReleaseFenceHandle : nullptr);
mOpenMode = aMode;
return mIsLocked;
@ -270,8 +270,12 @@ ClientTexture::~ClientTexture()
{
// All the destruction code that may lead to virtual method calls must
// be in Finalize() which is called just before the destructor.
// TODO[nical] temporarily integrate this with FinalizeOnIPDLThred
if (ShouldDeallocateInDestructor()) {
mData->Deallocate(mAllocator);
} else {
mData->Forget(mAllocator);
}
delete mData;
}
@ -371,6 +375,20 @@ ClientTexture::ToSurfaceDescriptor(SurfaceDescriptor& aOutDescriptor)
return mData->Serialize(aOutDescriptor);
}
void
ClientTexture::WaitForBufferOwnership(bool aWaitReleaseFence)
{
if (mRemoveFromCompositableWaiter) {
mRemoveFromCompositableWaiter->WaitComplete();
mRemoveFromCompositableWaiter = nullptr;
}
if (aWaitReleaseFence && mReleaseFenceHandle.IsValid()) {
mData->WaitForFence(&mReleaseFenceHandle);
mReleaseFenceHandle = FenceHandle();
}
}
// static
PTextureChild*
TextureClient::CreateIPDLActor()
@ -496,30 +514,6 @@ TextureClient::GetIPDLActor()
return mActor;
}
#ifdef MOZ_WIDGET_GONK
static bool
DisableGralloc(SurfaceFormat aFormat, const gfx::IntSize& aSizeHint)
{
if (gfxPrefs::DisableGralloc()) {
return true;
}
if (aFormat == gfx::SurfaceFormat::A8) {
return true;
}
#if ANDROID_VERSION <= 15
// Adreno 200 has a problem of drawing gralloc buffer width less than 64 and
// drawing gralloc buffer with a height 9px-16px.
// See Bug 983971.
if (aSizeHint.width < 64 || aSizeHint.height < 32) {
return true;
}
#endif
return false;
}
#endif
static inline gfx::BackendType
BackendTypeForBackendSelector(LayersBackend aLayersBackend, BackendSelector aSelector)
{
@ -557,7 +551,7 @@ TextureClient::CreateForDrawing(CompositableForwarder* aAllocator,
RefPtr<TextureClient> texture;
#if defined(MOZ_WIDGET_GONK) || defined(XP_WIN)
#if defined(XP_WIN)
int32_t maxTextureSize = aAllocator->GetMaxTextureSize();
#endif
@ -621,13 +615,10 @@ TextureClient::CreateForDrawing(CompositableForwarder* aAllocator,
#endif
#ifdef MOZ_WIDGET_GONK
if (!DisableGralloc(aFormat, aSize)) {
// Don't allow Gralloc texture clients to exceed the maximum texture size.
// BufferTextureClients have code to handle tiling the surface client-side.
if (aSize.width <= maxTextureSize && aSize.height <= maxTextureSize) {
texture = new GrallocTextureClientOGL(aAllocator, aFormat, moz2DBackend,
aTextureFlags);
}
texture = CreateGrallocTextureClientForDrawing(aSize, aFormat, moz2DBackend,
aTextureFlags, aAllocator);
if (texture) {
return texture.forget();
}
#endif
@ -843,6 +834,11 @@ TextureClient::ShouldDeallocateInDestructor() const
return !mShared || (GetFlags() & TextureFlags::DEALLOCATE_CLIENT);
}
void
TextureClient::SetRemoveFromCompositableWaiter(AsyncTransactionWaiter* aWaiter) {
mRemoveFromCompositableWaiter = aWaiter;
}
void
TextureClient::PrintInfo(std::stringstream& aStream, const char* aPrefix)
{

View File

@ -39,6 +39,10 @@ namespace mozilla {
#define GFX_DEBUG_TRACK_CLIENTS_IN_POOL 1
#endif
namespace gl {
class SharedSurface_Gralloc;
}
namespace layers {
class AsyncTransactionWaiter;
@ -49,6 +53,7 @@ struct PlanarYCbCrData;
class Image;
class PTextureChild;
class TextureChild;
class TextureData;
struct RawTextureBuffer;
class RawYCbCrTextureBuffer;
class TextureClient;
@ -57,7 +62,6 @@ class TextureClientRecycleAllocator;
class TextureClientPool;
#endif
class KeepAlive;
class GrallocTextureClientOGL;
/**
* TextureClient is the abstraction that allows us to share data between the
@ -247,8 +251,6 @@ public:
return false;
}
virtual GrallocTextureClientOGL* AsGrallocTextureClientOGL() { return nullptr; }
/**
* Locks the shared data, allowing the caller to get access to it.
*
@ -490,7 +492,7 @@ public:
/**
* Set AsyncTransactionTracker of RemoveTextureFromCompositableAsync() transaction.
*/
virtual void SetRemoveFromCompositableWaiter(AsyncTransactionWaiter* aWaiter) {}
virtual void SetRemoveFromCompositableWaiter(AsyncTransactionWaiter* aWaiter);
/**
* This function waits until the buffer is no longer being used.
@ -528,6 +530,9 @@ public:
TextureClientRecycleAllocator* GetRecycleAllocator() { return mRecycleAllocator; }
void SetRecycleAllocator(TextureClientRecycleAllocator* aAllocator);
/// If you add new code that uses this funtion, you are probably doing something wrong.
virtual TextureData* GetInternalData() { return nullptr; }
private:
static void TextureClientRecycleCallback(TextureClient* aClient, void* aClosure);
@ -547,7 +552,7 @@ private:
virtual void FinalizeOnIPDLThread() {}
friend class AtomicRefCountedWithFinalize<TextureClient>;
friend class gl::SharedSurface_Gralloc;
protected:
/**
* An invalid TextureClient cannot provide access to its shared data
@ -568,6 +573,8 @@ protected:
RefPtr<TextureChild> mActor;
RefPtr<ISurfaceAllocator> mAllocator;
RefPtr<TextureClientRecycleAllocator> mRecycleAllocator;
RefPtr<AsyncTransactionWaiter> mRemoveFromCompositableWaiter;
TextureFlags mFlags;
FenceHandle mReleaseFenceHandle;
FenceHandle mAcquireFenceHandle;
@ -600,7 +607,7 @@ public:
virtual gfx::SurfaceFormat GetFormat() const = 0;
virtual bool Lock(OpenMode aMode) = 0;
virtual bool Lock(OpenMode aMode, FenceHandle* aFence) = 0;
virtual void Unlock() = 0;
@ -620,6 +627,9 @@ public:
virtual void Deallocate(ISurfaceAllocator* aAllocator) = 0;
/// Depending on the texture's flags either Deallocate or Forget is called.
virtual void Forget(ISurfaceAllocator* aAllocator) {}
virtual bool Serialize(SurfaceDescriptor& aDescriptor) = 0;
virtual TextureData*
@ -628,6 +638,10 @@ public:
TextureAllocationFlags aAllocFlags = ALLOC_DEFAULT) const { return nullptr; }
virtual bool UpdateFromSurface(gfx::SourceSurface* aSurface) { 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) {};
};
/// temporary class that will be merged back into TextureClient when all texture implementations
@ -670,9 +684,14 @@ public:
virtual void UpdateFromSurface(gfx::SourceSurface* aSurface) override;
// TODO - we should be able to make this implicit and not expose the method.
virtual void WaitForBufferOwnership(bool aWaitReleaseFence = true) override;
// by construction, ClientTexture cannot be created without successful allocation.
virtual bool IsAllocated() const override { return true; }
/// If you add new code that uses this method, you are probably doing something wrong.
virtual TextureData* GetInternalData() override { return mData; }
protected:
TextureData* mData;
RefPtr<gfx::DrawTarget> mBorrowedDrawTarget;

View File

@ -54,9 +54,9 @@ void
SharedSurfaceTextureClient::SetReleaseFenceHandle(const FenceHandle& aReleaseFenceHandle)
{
#ifdef MOZ_WIDGET_GONK
SharedSurface_Gralloc* surf = nullptr;
if (mSurf->mType == SharedSurfaceType::Gralloc) {
surf = SharedSurface_Gralloc::Cast(mSurf.get());
gl::SharedSurface_Gralloc* surf = nullptr;
if (mSurf->mType == gl::SharedSurfaceType::Gralloc) {
surf = gl::SharedSurface_Gralloc::Cast(mSurf.get());
}
if (surf && surf->GetTextureClient()) {
surf->GetTextureClient()->SetReleaseFenceHandle(aReleaseFenceHandle);
@ -70,9 +70,9 @@ FenceHandle
SharedSurfaceTextureClient::GetAndResetReleaseFenceHandle()
{
#ifdef MOZ_WIDGET_GONK
SharedSurface_Gralloc* surf = nullptr;
if (mSurf->mType == SharedSurfaceType::Gralloc) {
surf = SharedSurface_Gralloc::Cast(mSurf.get());
gl::SharedSurface_Gralloc* surf = nullptr;
if (mSurf->mType == gl::SharedSurfaceType::Gralloc) {
surf = gl::SharedSurface_Gralloc::Cast(mSurf.get());
}
if (surf && surf->GetTextureClient()) {
return surf->GetTextureClient()->GetAndResetReleaseFenceHandle();
@ -85,9 +85,9 @@ void
SharedSurfaceTextureClient::SetAcquireFenceHandle(const FenceHandle& aAcquireFenceHandle)
{
#ifdef MOZ_WIDGET_GONK
SharedSurface_Gralloc* surf = nullptr;
if (mSurf->mType == SharedSurfaceType::Gralloc) {
surf = SharedSurface_Gralloc::Cast(mSurf.get());
gl::SharedSurface_Gralloc* surf = nullptr;
if (mSurf->mType == gl::SharedSurfaceType::Gralloc) {
surf = gl::SharedSurface_Gralloc::Cast(mSurf.get());
}
if (surf && surf->GetTextureClient()) {
return surf->GetTextureClient()->SetAcquireFenceHandle(aAcquireFenceHandle);
@ -100,9 +100,9 @@ const FenceHandle&
SharedSurfaceTextureClient::GetAcquireFenceHandle() const
{
#ifdef MOZ_WIDGET_GONK
SharedSurface_Gralloc* surf = nullptr;
if (mSurf->mType == SharedSurfaceType::Gralloc) {
surf = SharedSurface_Gralloc::Cast(mSurf.get());
gl::SharedSurface_Gralloc* surf = nullptr;
if (mSurf->mType == gl::SharedSurfaceType::Gralloc) {
surf = gl::SharedSurface_Gralloc::Cast(mSurf.get());
}
if (surf && surf->GetTextureClient()) {
return surf->GetTextureClient()->GetAcquireFenceHandle();

View File

@ -24,148 +24,28 @@ namespace layers {
using namespace mozilla::gfx;
using namespace android;
GrallocTextureClientOGL::GrallocTextureClientOGL(ISurfaceAllocator* aAllocator,
gfx::SurfaceFormat aFormat,
gfx::BackendType aMoz2dBackend,
TextureFlags aFlags)
: BufferTextureClient(aAllocator, aFormat, aMoz2dBackend, aFlags)
, mGrallocHandle(null_t())
, mMappedBuffer(nullptr)
, mMediaBuffer(nullptr)
, mIsOpaque(gfx::IsOpaque(aFormat))
static bool
DisableGralloc(SurfaceFormat aFormat, const gfx::IntSize& aSizeHint)
{
MOZ_COUNT_CTOR(GrallocTextureClientOGL);
}
GrallocTextureClientOGL::~GrallocTextureClientOGL()
{
MOZ_COUNT_DTOR(GrallocTextureClientOGL);
ISurfaceAllocator* allocator = GetAllocator();
if (ShouldDeallocateInDestructor()) {
allocator->DeallocGrallocBuffer(&mGrallocHandle);
} else {
allocator->DropGrallocBuffer(&mGrallocHandle);
}
}
already_AddRefed<TextureClient>
GrallocTextureClientOGL::CreateSimilar(TextureFlags aFlags,
TextureAllocationFlags aAllocFlags) const
{
RefPtr<TextureClient> tex = new GrallocTextureClientOGL(
mAllocator, mFormat, mBackend, mFlags | aFlags
);
if (!tex->AllocateForSurface(mSize, aAllocFlags)) {
return nullptr;
}
return tex.forget();
}
bool
GrallocTextureClientOGL::ToSurfaceDescriptor(SurfaceDescriptor& aOutDescriptor)
{
MOZ_ASSERT(IsValid());
if (!IsAllocated()) {
return false;
}
aOutDescriptor = NewSurfaceDescriptorGralloc(mGrallocHandle, mIsOpaque);
return true;
}
void
GrallocTextureClientOGL::SetRemoveFromCompositableWaiter(AsyncTransactionWaiter* aWaiter)
{
mRemoveFromCompositableWaiter = aWaiter;
}
void
GrallocTextureClientOGL::WaitForBufferOwnership(bool aWaitReleaseFence)
{
if (mRemoveFromCompositableWaiter) {
mRemoveFromCompositableWaiter->WaitComplete();
mRemoveFromCompositableWaiter = nullptr;
}
if (!aWaitReleaseFence) {
return;
}
#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17
if (mReleaseFenceHandle.IsValid()) {
RefPtr<FenceHandle::FdObj> fdObj = mReleaseFenceHandle.GetAndResetFdObj();
android::sp<Fence> fence = new Fence(fdObj->GetAndResetFd());
#if ANDROID_VERSION == 17
fence->waitForever(1000, "GrallocTextureClientOGL::Lock");
// 1000 is what Android uses. It is a warning timeout in ms.
// This timeout was removed in ANDROID_VERSION 18.
#else
fence->waitForever("GrallocTextureClientOGL::Lock");
#endif
mReleaseFenceHandle = FenceHandle();
}
#endif
}
bool
GrallocTextureClientOGL::Lock(OpenMode aMode)
{
MOZ_ASSERT(!mIsLocked);
MOZ_ASSERT(IsValid());
if (!IsValid() || !IsAllocated()) {
return false;
}
if (mMappedBuffer) {
if (gfxPrefs::DisableGralloc()) {
return true;
}
#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 21
WaitForBufferOwnership(false /* aWaitReleaseFence */);
#else
WaitForBufferOwnership();
#endif
uint32_t usage = 0;
if (aMode & OpenMode::OPEN_READ) {
usage |= GRALLOC_USAGE_SW_READ_OFTEN;
}
if (aMode & OpenMode::OPEN_WRITE) {
usage |= GRALLOC_USAGE_SW_WRITE_OFTEN;
}
#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 21
RefPtr<FenceHandle::FdObj> fdObj = mReleaseFenceHandle.GetAndResetFdObj();
int32_t rv = mGraphicBuffer->lockAsync(usage,
reinterpret_cast<void**>(&mMappedBuffer),
fdObj->GetAndResetFd());
#else
int32_t rv = mGraphicBuffer->lock(usage,
reinterpret_cast<void**>(&mMappedBuffer));
#endif
if (rv) {
mMappedBuffer = nullptr;
NS_WARNING("Couldn't lock graphic buffer");
return false;
}
mIsLocked = true;
if (aFormat == gfx::SurfaceFormat::A8) {
return true;
}
void
GrallocTextureClientOGL::Unlock()
{
MOZ_ASSERT(mIsLocked);
mIsLocked = false;
mDrawTarget = nullptr;
if (mMappedBuffer) {
mMappedBuffer = nullptr;
mGraphicBuffer->unlock();
}
#if ANDROID_VERSION <= 15
// Adreno 200 has a problem of drawing gralloc buffer width less than 64 and
// drawing gralloc buffer with a height 9px-16px.
// See Bug 983971.
if (aSizeHint.width < 64 || aSizeHint.height < 32) {
return true;
}
#endif
return false;
}
static gfx::SurfaceFormat
gfx::SurfaceFormat
SurfaceFormatForPixelFormat(android::PixelFormat aFormat)
{
switch (aFormat) {
@ -180,56 +60,188 @@ SurfaceFormatForPixelFormat(android::PixelFormat aFormat)
case HAL_PIXEL_FORMAT_YV12:
return gfx::SurfaceFormat::YUV;
default:
MOZ_CRASH("Unknown gralloc pixel format");
return gfx::SurfaceFormat::UNKNOWN;
}
return gfx::SurfaceFormat::R8G8B8A8;
}
gfx::DrawTarget*
GrallocTextureClientOGL::BorrowDrawTarget()
bool
IsGrallocRBSwapped(gfx::SurfaceFormat aFormat) {
switch (aFormat) {
case gfx::SurfaceFormat::B8G8R8A8:
case gfx::SurfaceFormat::B8G8R8X8:
return true;
default:
return false;
}
}
uint32_t GetAndroidFormat(gfx::SurfaceFormat aFormat)
{
MOZ_ASSERT(IsValid());
MOZ_ASSERT(mMappedBuffer, "Calling TextureClient::BorrowDrawTarget without locking :(");
if (!IsValid() || !IsAllocated() || !mMappedBuffer) {
return nullptr;
switch (aFormat) {
case gfx::SurfaceFormat::R8G8B8A8:
case gfx::SurfaceFormat::B8G8R8A8:
return android::PIXEL_FORMAT_RGBA_8888;
case gfx::SurfaceFormat::R8G8B8X8:
case gfx::SurfaceFormat::B8G8R8X8:
return android::PIXEL_FORMAT_RGBX_8888;
case gfx::SurfaceFormat::R5G6B5_UINT16:
return android::PIXEL_FORMAT_RGB_565;
case gfx::SurfaceFormat::YUV:
return HAL_PIXEL_FORMAT_YV12;
case gfx::SurfaceFormat::A8:
NS_WARNING("gralloc does not support SurfaceFormat::A8");
default:
NS_WARNING("Unsupported surface format");
return android::PIXEL_FORMAT_UNKNOWN;
}
}
if (mDrawTarget) {
return mDrawTarget;
}
GrallocTextureData::GrallocTextureData(MaybeMagicGrallocBufferHandle aGrallocHandle,
gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
gfx::BackendType aMoz2DBackend)
: mSize(aSize)
, mFormat(aFormat)
, mMoz2DBackend(aMoz2DBackend)
, mGrallocHandle(aGrallocHandle)
, mMappedBuffer(nullptr)
, mMediaBuffer(nullptr)
{
mGraphicBuffer = GetGraphicBufferFrom(aGrallocHandle);
MOZ_COUNT_CTOR(GrallocTextureData);
}
gfx::SurfaceFormat format = SurfaceFormatForPixelFormat(mGraphicBuffer->getPixelFormat());
long pixelStride = mGraphicBuffer->getStride();
long byteStride = pixelStride * BytesPerPixel(format);
mDrawTarget = gfxPlatform::GetPlatform()->CreateDrawTargetForData(GetBuffer(),
mSize,
byteStride,
mFormat);
return mDrawTarget;
GrallocTextureData::~GrallocTextureData()
{
MOZ_COUNT_DTOR(GrallocTextureData);
}
void
GrallocTextureClientOGL::UpdateFromSurface(gfx::SourceSurface* aSurface)
GrallocTextureData::Deallocate(ISurfaceAllocator* aAllocator)
{
aAllocator->DeallocGrallocBuffer(&mGrallocHandle);
mGrallocHandle = null_t();
mGraphicBuffer = nullptr;
}
void
GrallocTextureData::Forget(ISurfaceAllocator* aAllocator)
{
aAllocator->DropGrallocBuffer(&mGrallocHandle);
mGrallocHandle = null_t();
mGraphicBuffer = nullptr;
}
bool
GrallocTextureData::Serialize(SurfaceDescriptor& aOutDescriptor)
{
aOutDescriptor = NewSurfaceDescriptorGralloc(mGrallocHandle, gfx::IsOpaque(mFormat));
return true;
}
void
GrallocTextureData::WaitForFence(FenceHandle* aFence)
{
#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION < 21 && ANDROID_VERSION >= 17
if (aFence->IsValid()) {
RefPtr<FenceHandle::FdObj> fdObj = aFence->GetAndResetFdObj();
android::sp<Fence> fence = new Fence(fdObj->GetAndResetFd());
#if ANDROID_VERSION == 17
fence->waitForever(1000, "GrallocTextureData::Lock");
// 1000 is what Android uses. It is a warning timeout in ms.
// This timeout was removed in ANDROID_VERSION 18.
#else
fence->waitForever("GrallocTextureData::Lock");
#endif
}
#endif
}
bool
GrallocTextureData::Lock(OpenMode aMode, FenceHandle* aReleaseFence)
{
MOZ_ASSERT(!mMappedBuffer);
WaitForFence(aReleaseFence);
uint32_t usage = 0;
if (aMode & OpenMode::OPEN_READ) {
usage |= GRALLOC_USAGE_SW_READ_OFTEN;
}
if (aMode & OpenMode::OPEN_WRITE) {
usage |= GRALLOC_USAGE_SW_WRITE_OFTEN;
}
#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 21
RefPtr<FenceHandle::FdObj> fdObj = aReleaseFence->GetAndResetFdObj();
int32_t rv = mGraphicBuffer->lockAsync(usage,
reinterpret_cast<void**>(&mMappedBuffer),
fdObj->GetAndResetFd());
#else
int32_t rv = mGraphicBuffer->lock(usage,
reinterpret_cast<void**>(&mMappedBuffer));
#endif
if (rv) {
mMappedBuffer = nullptr;
NS_WARNING("Couldn't lock graphic buffer");
return false;
}
return true;
}
void
GrallocTextureData::Unlock()
{
MOZ_ASSERT(mMappedBuffer);
mMappedBuffer = nullptr;
mGraphicBuffer->unlock();
}
already_AddRefed<gfx::DrawTarget>
GrallocTextureData::BorrowDrawTarget()
{
MOZ_ASSERT(mMappedBuffer);
if (!mMappedBuffer) {
return nullptr;
}
long byteStride = mGraphicBuffer->getStride() * BytesPerPixel(mFormat);
return gfxPlatform::GetPlatform()->CreateDrawTargetForData(mMappedBuffer, mSize,
byteStride, mFormat);
}
bool
GrallocTextureData::BorrowMappedData(MappedTextureData& aMap)
{
if (mFormat == gfx::SurfaceFormat::YUV || !mMappedBuffer) {
return false;
}
aMap.data = mMappedBuffer;
aMap.size = mSize;
aMap.stride = mGraphicBuffer->getStride() * BytesPerPixel(mFormat);
aMap.format = mFormat;
return true;
}
bool
GrallocTextureData::UpdateFromSurface(gfx::SourceSurface* aSurface)
{
MOZ_ASSERT(IsValid());
MOZ_ASSERT(mMappedBuffer, "Calling TextureClient::BorrowDrawTarget without locking :(");
if (!IsValid() || !IsAllocated() || !mMappedBuffer) {
return;
if (!mMappedBuffer) {
return false;
}
RefPtr<DataSourceSurface> srcSurf = aSurface->GetDataSurface();
if (!srcSurf) {
gfxCriticalError() << "Failed to GetDataSurface in UpdateFromSurface.";
return;
return false;
}
gfx::SurfaceFormat format = SurfaceFormatForPixelFormat(mGraphicBuffer->getPixelFormat());
if (mSize != srcSurf->GetSize() || mFormat != srcSurf->GetFormat()) {
gfxCriticalError() << "Attempt to update texture client from a surface with a different size or format! This: " << mSize << " " << format << " Other: " << srcSurf->GetSize() << " " << srcSurf->GetFormat();
return;
return false;
}
long pixelStride = mGraphicBuffer->getStride();
@ -239,143 +251,148 @@ GrallocTextureClientOGL::UpdateFromSurface(gfx::SourceSurface* aSurface)
if (!srcSurf->Map(DataSourceSurface::READ, &sourceMap)) {
gfxCriticalError() << "Failed to map source surface for UpdateFromSurface.";
return;
return false;
}
uint8_t* buffer = GetBuffer();
for (int y = 0; y < srcSurf->GetSize().height; y++) {
memcpy(buffer + byteStride * y,
memcpy(mMappedBuffer + byteStride * y,
sourceMap.mData + sourceMap.mStride * y,
srcSurf->GetSize().width * BytesPerPixel(srcSurf->GetFormat()));
}
srcSurf->Unmap();
return true;
}
bool
GrallocTextureClientOGL::AllocateForSurface(gfx::IntSize aSize,
TextureAllocationFlags)
// static
GrallocTextureData*
GrallocTextureData::Create(gfx::IntSize aSize, AndroidFormat aAndroidFormat,
gfx::BackendType aMoz2dBackend, uint32_t aUsage,
ISurfaceAllocator* aAllocator)
{
MOZ_ASSERT(IsValid());
uint32_t format;
uint32_t usage = android::GraphicBuffer::USAGE_SW_READ_OFTEN |
android::GraphicBuffer::USAGE_SW_WRITE_OFTEN |
android::GraphicBuffer::USAGE_HW_TEXTURE;
switch (mFormat) {
case gfx::SurfaceFormat::R8G8B8A8:
format = android::PIXEL_FORMAT_RGBA_8888;
break;
case gfx::SurfaceFormat::B8G8R8A8:
format = android::PIXEL_FORMAT_RGBA_8888;
mFlags |= TextureFlags::RB_SWAPPED;
break;
case gfx::SurfaceFormat::R8G8B8X8:
format = android::PIXEL_FORMAT_RGBX_8888;
break;
case gfx::SurfaceFormat::B8G8R8X8:
format = android::PIXEL_FORMAT_RGBX_8888;
mFlags |= TextureFlags::RB_SWAPPED;
break;
case gfx::SurfaceFormat::R5G6B5_UINT16:
format = android::PIXEL_FORMAT_RGB_565;
break;
case gfx::SurfaceFormat::YUV:
format = HAL_PIXEL_FORMAT_YV12;
break;
case gfx::SurfaceFormat::A8:
NS_WARNING("gralloc does not support gfx::SurfaceFormat::A8");
return false;
default:
NS_WARNING("Unsupported surface format");
return false;
int32_t maxSize = aAllocator->GetMaxTextureSize();
if (aSize.width > maxSize || aSize.height > maxSize) {
return nullptr;
}
return AllocateGralloc(aSize, format, usage);
}
bool
GrallocTextureClientOGL::AllocateForYCbCr(gfx::IntSize aYSize, gfx::IntSize aCbCrSize, StereoMode aStereoMode)
{
MOZ_ASSERT(IsValid());
return AllocateGralloc(aYSize,
HAL_PIXEL_FORMAT_YV12,
android::GraphicBuffer::USAGE_SW_READ_OFTEN);
}
bool
GrallocTextureClientOGL::AllocateForGLRendering(gfx::IntSize aSize)
{
MOZ_ASSERT(IsValid());
uint32_t format;
uint32_t usage = android::GraphicBuffer::USAGE_HW_RENDER |
android::GraphicBuffer::USAGE_HW_TEXTURE;
switch (mFormat) {
case gfx::SurfaceFormat::R8G8B8A8:
case gfx::SurfaceFormat::B8G8R8A8:
format = android::PIXEL_FORMAT_RGBA_8888;
gfx::SurfaceFormat format;
switch (aAndroidFormat) {
case android::PIXEL_FORMAT_RGBA_8888:
format = gfx::SurfaceFormat::B8G8R8A8;
break;
case gfx::SurfaceFormat::R8G8B8X8:
case gfx::SurfaceFormat::B8G8R8X8:
// there is no android BGRX format?
format = android::PIXEL_FORMAT_RGBX_8888;
case android::PIXEL_FORMAT_BGRA_8888:
format = gfx::SurfaceFormat::B8G8R8A8;
break;
case gfx::SurfaceFormat::R5G6B5_UINT16:
format = android::PIXEL_FORMAT_RGB_565;
case android::PIXEL_FORMAT_RGBX_8888:
format = gfx::SurfaceFormat::B8G8R8X8;
break;
case android::PIXEL_FORMAT_RGB_565:
format = gfx::SurfaceFormat::R5G6B5_UINT16;
break;
case HAL_PIXEL_FORMAT_YV12:
format = gfx::SurfaceFormat::YUV;
break;
default:
NS_WARNING("Unsupported surface format");
return false;
format = gfx::SurfaceFormat::UNKNOWN;
}
return AllocateGralloc(aSize, format, usage);
}
bool
GrallocTextureClientOGL::AllocateGralloc(gfx::IntSize aSize,
uint32_t aAndroidFormat,
uint32_t aUsage)
{
MOZ_ASSERT(IsValid());
ISurfaceAllocator* allocator = GetAllocator();
if (DisableGralloc(format, aSize)) {
return nullptr;
}
MaybeMagicGrallocBufferHandle handle;
bool allocateResult =
allocator->AllocGrallocBuffer(aSize,
aAndroidFormat,
aUsage,
&handle);
if (!allocateResult) {
return false;
if (!aAllocator->AllocGrallocBuffer(aSize, aAndroidFormat, aUsage, &handle)) {
return nullptr;
}
sp<GraphicBuffer> graphicBuffer = GetGraphicBufferFrom(handle);
if (!graphicBuffer.get()) {
return false;
return nullptr;
}
if (graphicBuffer->initCheck() != NO_ERROR) {
return false;
return nullptr;
}
mGrallocHandle = handle;
mGraphicBuffer = graphicBuffer;
mSize = aSize;
return true;
return new GrallocTextureData(handle, aSize, format, aMoz2dBackend);
}
bool
GrallocTextureClientOGL::IsAllocated() const
// static
GrallocTextureData*
GrallocTextureData::CreateForDrawing(gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
gfx::BackendType aMoz2dBackend,
ISurfaceAllocator* aAllocator)
{
return !!mGraphicBuffer.get();
if (DisableGralloc(aFormat, aSize)) {
return nullptr;
}
uint32_t usage = android::GraphicBuffer::USAGE_SW_READ_OFTEN |
android::GraphicBuffer::USAGE_SW_WRITE_OFTEN |
android::GraphicBuffer::USAGE_HW_TEXTURE;
auto data = GrallocTextureData::Create(aSize, GetAndroidFormat(aFormat),
aMoz2dBackend, usage, aAllocator);
if (!data) {
return nullptr;
}
DebugOnly<gfx::SurfaceFormat> grallocFormat =
SurfaceFormatForPixelFormat(data->mGraphicBuffer->getPixelFormat());
// mFormat may be different from the format the graphic buffer reports if we
// swap the R and B channels but we should always have at least the same bytes
// per pixel!
MOZ_ASSERT(BytesPerPixel(data->mFormat) == BytesPerPixel(grallocFormat));
return data;
}
/*static*/ already_AddRefed<TextureClient>
GrallocTextureClientOGL::FromSharedSurface(gl::SharedSurface* abstractSurf,
already_AddRefed<TextureClient>
CreateGrallocTextureClientForDrawing(gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
gfx::BackendType aMoz2dBackend,
TextureFlags aFlags,
ISurfaceAllocator* aAllocator)
{
TextureData* data = GrallocTextureData::CreateForDrawing(aSize, aFormat, aMoz2dBackend,
aAllocator);
if (!data) {
return nullptr;
}
if (IsGrallocRBSwapped(aFormat)) {
aFlags |= TextureFlags::RB_SWAPPED;
}
return MakeAndAddRef<ClientTexture>(data, aFlags, aAllocator);
}
// static
GrallocTextureData*
GrallocTextureData::CreateForYCbCr(gfx::IntSize aYSize, gfx::IntSize aCbCrSize,
ISurfaceAllocator* aAllocator)
{
MOZ_ASSERT(aYSize.width == aCbCrSize.width * 2);
MOZ_ASSERT(aYSize.height == aCbCrSize.height * 2);
return GrallocTextureData::Create(aYSize, HAL_PIXEL_FORMAT_YV12,
gfx::BackendType::NONE,
android::GraphicBuffer::USAGE_SW_READ_OFTEN,
aAllocator);
}
// static
GrallocTextureData*
GrallocTextureData::CreateForGLRendering(gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
ISurfaceAllocator* aAllocator)
{
if (aFormat == gfx::SurfaceFormat::YUV) {
return nullptr;
}
uint32_t usage = android::GraphicBuffer::USAGE_HW_RENDER |
android::GraphicBuffer::USAGE_HW_TEXTURE;
return GrallocTextureData::Create(aSize, GetAndroidFormat(aFormat),
gfx::BackendType::NONE, usage, aAllocator);
}
// static
already_AddRefed<TextureClient>
GrallocTextureData::TextureClientFromSharedSurface(gl::SharedSurface* abstractSurf,
TextureFlags flags)
{
auto surf = gl::SharedSurface_Gralloc::Cast(abstractSurf);
@ -397,6 +414,18 @@ GrallocTextureClientOGL::FromSharedSurface(gl::SharedSurface* abstractSurf,
return ret.forget();
}
TextureData*
GrallocTextureData::CreateSimilar(ISurfaceAllocator* aAllocator,
TextureFlags aFlags,
TextureAllocationFlags aAllocFlags) const
{
if (mFormat == gfx::SurfaceFormat::YUV) {
return GrallocTextureData::CreateForYCbCr(mSize, mSize*2, aAllocator);
} else {
return GrallocTextureData::CreateForDrawing(mSize, mFormat, mMoz2DBackend, aAllocator);
}
}
} // namesapace layers
} // namesapace mozilla

View File

@ -25,131 +25,113 @@ class SharedSurface;
namespace layers {
/**
* A TextureClient implementation based on android::GraphicBuffer (also referred to
* as "gralloc").
*
* Gralloc lets us map texture data in memory (accessible through pointers)
* and also use it directly as an OpenGL texture without the cost of texture
* uploads.
* Gralloc buffers can also be shared accros processes.
*
* More info about Gralloc here: https://wiki.mozilla.org/Platform/GFX/Gralloc
*
* This is only used in Firefox OS
*/
class GrallocTextureClientOGL : public TextureClient
{
/// A TextureData implementation based on android::GraphicBuffer (also referred to
/// as "gralloc").
///
/// Gralloc lets us map texture data in memory (accessible through pointers)
/// and also use it directly as an OpenGL texture without the cost of texture
/// uploads.
/// Gralloc buffers can also be shared accros processes.
///
/// More info about Gralloc here: https://wiki.mozilla.org/Platform/GFX/Gralloc
///
/// This is only used in Firefox OS
class GrallocTextureData : public TextureData {
public:
GrallocTextureClientOGL(ISurfaceAllocator* aAllocator,
gfx::SurfaceFormat aFormat,
gfx::BackendType aMoz2dBackend,
TextureFlags aFlags = TextureFlags::DEFAULT);
typedef uint32_t AndroidFormat;
~GrallocTextureClientOGL();
virtual bool Serialize(SurfaceDescriptor& aOutDescriptor) override;
virtual bool Lock(OpenMode aMode) override;
virtual bool Lock(OpenMode aMode, FenceHandle* aFence) override;
virtual void Unlock() override;
virtual bool ImplementsLocking() const override { return true; }
virtual gfx::IntSize GetSize() const override { return mSize; }
virtual gfx::SurfaceFormat GetFormat() const override { return mFormat; }
virtual already_AddRefed<gfx::DrawTarget> BorrowDrawTarget() override;
virtual bool CanExposeMappedData() const override { return true; }
virtual bool BorrowMappedData(MappedTextureData& aMap) override;
virtual bool SupportsMoz2D() const override { return true; }
virtual bool HasInternalBuffer() const override { return false; }
virtual bool IsAllocated() const override;
virtual bool HasSynchronization() const override { return true; }
virtual bool ToSurfaceDescriptor(SurfaceDescriptor& aOutDescriptor) override;
virtual void Deallocate(ISurfaceAllocator*) override;
virtual void SetRemoveFromCompositableWaiter(AsyncTransactionWaiter* aWaiter) override;
virtual void Forget(ISurfaceAllocator*) override;
virtual void WaitForBufferOwnership(bool aWaitReleaseFence = true) override;
static GrallocTextureData* CreateForDrawing(gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
gfx::BackendType aMoz2dBackend,
ISurfaceAllocator* aAllocator);
GrallocTextureClientOGL* AsGrallocTextureClientOGL() override {
return this;
}
static GrallocTextureData* CreateForYCbCr(gfx::IntSize aYSize, gfx::IntSize aCbCrSize,
ISurfaceAllocator* aAllocator);
void SetTextureFlags(TextureFlags aFlags) { AddFlags(aFlags); }
static GrallocTextureData* CreateForGLRendering(gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
ISurfaceAllocator* aAllocator);
gfx::IntSize GetSize() const override { return mSize; }
static GrallocTextureData* Create(gfx::IntSize aSize, AndroidFormat aFormat,
gfx::BackendType aMoz2DBackend, uint32_t aUsage,
ISurfaceAllocator* aAllocator);
android::sp<android::GraphicBuffer> GetGraphicBuffer()
{
return mGraphicBuffer;
}
android::PixelFormat GetPixelFormat()
{
return mGraphicBuffer->getPixelFormat();
}
static already_AddRefed<TextureClient>
TextureClientFromSharedSurface(gl::SharedSurface* abstractSurf, TextureFlags flags);
virtual gfx::DrawTarget* BorrowDrawTarget() override;
virtual void UpdateFromSurface(gfx::SourceSurface* aSurface) override;
virtual bool AllocateForSurface(gfx::IntSize aSize,
TextureAllocationFlags aFlags = ALLOC_DEFAULT) override;
virtual bool AllocateForYCbCr(gfx::IntSize aYSize,
gfx::IntSize aCbCrSize,
StereoMode aStereoMode);
bool AllocateForGLRendering(gfx::IntSize aSize);
bool AllocateGralloc(gfx::IntSize aYSize, uint32_t aAndroidFormat, uint32_t aUsage);
void SetIsOpaque(bool aIsOpaque) { mIsOpaque = aIsOpaque; }
/**
* Hold android::MediaBuffer.
* MediaBuffer needs to be add refed to keep MediaBuffer alive
* during TextureClient is in use.
*/
void SetMediaBuffer(android::MediaBuffer* aMediaBuffer)
{
mMediaBuffer = aMediaBuffer;
}
android::MediaBuffer* GetMediaBuffer()
{
return mMediaBuffer;
}
virtual already_AddRefed<TextureClient>
CreateSimilar(TextureFlags aFlags = TextureFlags::DEFAULT,
virtual TextureData*
CreateSimilar(ISurfaceAllocator* aAllocator,
TextureFlags aFlags = TextureFlags::DEFAULT,
TextureAllocationFlags aAllocFlags = ALLOC_DEFAULT) const override;
static already_AddRefed<TextureClient> FromSharedSurface(gl::SharedSurface* surf,
TextureFlags flags);
// use ClientTexture's default implementation
virtual bool UpdateFromSurface(gfx::SourceSurface* aSurface) override;
/// Hold android::MediaBuffer.
/// MediaBuffer needs to be add refed to keep MediaBuffer alive while the texture
/// is in use.
///
/// TODO - ideally we should be able to put the MediaBuffer in the texture's
/// constructor and not expose these methods.
void SetMediaBuffer(android::MediaBuffer* aMediaBuffer) { mMediaBuffer = aMediaBuffer; }
android::MediaBuffer* GetMediaBuffer() { return mMediaBuffer; }
android::sp<android::GraphicBuffer> GetGraphicBuffer() { return mGraphicBuffer; }
virtual void WaitForFence(FenceHandle* aFence) override;
~GrallocTextureData();
protected:
gfx::SurfaceFormat mFormat;
GrallocTextureData(MaybeMagicGrallocBufferHandle aGrallocHandle,
gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
gfx::BackendType aMoz2DBackend);
gfx::IntSize mSize;
gfx::BackendType mBackend;
OpenMode mOpenMode;
gfx::SurfaceFormat mFormat;
gfx::BackendType mMoz2DBackend;
/**
* Unfortunately, until bug 879681 is fixed we need to use a GrallocBufferActor.
*/
MaybeMagicGrallocBufferHandle mGrallocHandle;
RefPtr<AsyncTransactionWaiter> mRemoveFromCompositableWaiter;
android::sp<android::GraphicBuffer> mGraphicBuffer;
/**
* Points to a mapped gralloc buffer between calls to lock and unlock.
* Should be null outside of the lock-unlock pair.
*/
// Points to a mapped gralloc buffer between calls to lock and unlock.
// Should be null outside of the lock-unlock pair.
uint8_t* mMappedBuffer;
RefPtr<gfx::DrawTarget> mDrawTarget;
android::MediaBuffer* mMediaBuffer;
bool mIsOpaque;
bool mLocked;
};
gfx::SurfaceFormat SurfaceFormatForPixelFormat(android::PixelFormat aFormat);
already_AddRefed<TextureClient> CreateGrallocTextureClientForDrawing(gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
gfx::BackendType aMoz2dBackend, TextureFlags aFlags,
ISurfaceAllocator* aAllocator);
} // namespace layers
} // namespace mozilla

View File

@ -421,19 +421,18 @@ status_t GonkBufferQueue::dequeueBuffer(int *outBuf, sp<Fence>* outFence,
sp<GraphicBuffer> graphicBuffer;
if (returnFlags & IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION) {
RefPtr<GrallocTextureClientOGL> textureClient =
new GrallocTextureClientOGL(ImageBridgeChild::GetSingleton(),
gfx::SurfaceFormat::UNKNOWN,
gfx::BackendType::NONE,
TextureFlags::DEALLOCATE_CLIENT);
textureClient->SetIsOpaque(true);
usage |= GraphicBuffer::USAGE_HW_TEXTURE;
bool result = textureClient->AllocateGralloc(IntSize(w, h), format, usage);
sp<GraphicBuffer> graphicBuffer = textureClient->GetGraphicBuffer();
if (!result || !graphicBuffer.get()) {
ISurfaceAllocator* allocator = ImageBridgeChild::GetSingleton();
GrallocTextureData* texData = GrallocTextureData::Create(IntSize(w,h), format,
gfx::BackendType::NONE, usage,
allocator);
if (!texData) {
ST_LOGE("dequeueBuffer: failed to alloc gralloc buffer");
return -ENOMEM;
}
RefPtr<TextureClient> textureClient = new ClientTexture(texData, TextureFlags::DEALLOCATE_CLIENT, allocator);
sp<GraphicBuffer> graphicBuffer = texData->GetGraphicBuffer();
{ // Scope for the lock
Mutex::Autolock lock(mMutex);

View File

@ -440,22 +440,19 @@ status_t GonkBufferQueue::dequeueBuffer(int *outBuf, sp<Fence>* outFence, bool a
mSlots[buf].mFence = Fence::NO_FENCE;
} // end lock scope
sp<GraphicBuffer> graphicBuffer;
if (returnFlags & IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION) {
RefPtr<GrallocTextureClientOGL> textureClient =
new GrallocTextureClientOGL(ImageBridgeChild::GetSingleton(),
gfx::SurfaceFormat::UNKNOWN,
gfx::BackendType::NONE,
TextureFlags::DEALLOCATE_CLIENT);
textureClient->SetIsOpaque(true);
ISurfaceAllocator* allocator = ImageBridgeChild::GetSingleton();
usage |= GraphicBuffer::USAGE_HW_TEXTURE;
bool result = textureClient->AllocateGralloc(IntSize(w, h), format, usage);
sp<GraphicBuffer> graphicBuffer = textureClient->GetGraphicBuffer();
if (!result || !graphicBuffer.get()) {
ALOGE("dequeueBuffer: failed to alloc gralloc buffer");
GrallocTextureData* texData = GrallocTextureData::Create(IntSize(w, h), format,
gfx::BackendType::NONE, usage,
allocator);
if (!texData) {
return -ENOMEM;
}
RefPtr<TextureClient> textureClient = new ClientTexture(texData, TextureFlags::DEALLOCATE_CLIENT, allocator);
{ // Scope for the lock
Mutex::Autolock lock(mMutex);
@ -464,7 +461,7 @@ status_t GonkBufferQueue::dequeueBuffer(int *outBuf, sp<Fence>* outFence, bool a
return NO_INIT;
}
mSlots[buf].mGraphicBuffer = graphicBuffer;
mSlots[buf].mGraphicBuffer = texData->GetGraphicBuffer();
mSlots[buf].mTextureClient = textureClient;
ALOGD("dequeueBuffer: returning slot=%d buf=%p ", buf,
mSlots[buf].mGraphicBuffer->handle);

View File

@ -341,19 +341,19 @@ status_t GonkBufferQueueProducer::dequeueBuffer(int *outSlot,
} // Autolock scope
if (returnFlags & BUFFER_NEEDS_REALLOCATION) {
RefPtr<GrallocTextureClientOGL> textureClient =
new GrallocTextureClientOGL(ImageBridgeChild::GetSingleton(),
gfx::SurfaceFormat::UNKNOWN,
gfx::BackendType::NONE,
TextureFlags::DEALLOCATE_CLIENT);
textureClient->SetIsOpaque(true);
ISurfaceAllocator* allocator = ImageBridgeChild::GetSingleton();
usage |= GraphicBuffer::USAGE_HW_TEXTURE;
bool result = textureClient->AllocateGralloc(IntSize(width, height), format, usage);
sp<GraphicBuffer> graphicBuffer = textureClient->GetGraphicBuffer();
if (!result || !graphicBuffer.get()) {
GrallocTextureData* texData = GrallocTextureData::Create(IntSize(width,height), format,
gfx::BackendType::NONE,
usage, allocator);
if (!texData) {
ALOGE("dequeueBuffer: failed to alloc gralloc buffer");
return -ENOMEM;
}
RefPtr<TextureClient> textureClient = TextureClient::CreateWithData(
texData, TextureFlags::DEALLOCATE_CLIENT, allocator);
sp<GraphicBuffer> graphicBuffer = texData->GetGraphicBuffer();
{ // Autolock scope
Mutex::Autolock lock(mCore->mMutex);

View File

@ -318,22 +318,18 @@ status_t GonkNativeWindow::dequeueBuffer(int *outBuf, uint32_t w, uint32_t h,
}
} // end lock scope
sp<GraphicBuffer> graphicBuffer;
if (alloc) {
RefPtr<GrallocTextureClientOGL> textureClient =
new GrallocTextureClientOGL(ImageBridgeChild::GetSingleton(),
gfx::SurfaceFormat::UNKNOWN,
gfx::BackendType::NONE,
TextureFlags::DEALLOCATE_CLIENT);
textureClient->SetIsOpaque(true);
ISurfaceAllocator* allocator = ImageBridgeChild::GetSingleton();
usage |= GraphicBuffer::USAGE_HW_TEXTURE;
bool result = textureClient->AllocateGralloc(IntSize(w, h), format, usage);
sp<GraphicBuffer> graphicBuffer = textureClient->GetGraphicBuffer();
if (!result || !graphicBuffer.get()) {
CNW_LOGE("dequeueBuffer: failed to alloc gralloc buffer");
GrallocTextureData* texData = GrallocTextureData::Create(IntSize(w, h), format,
gfx::BackendType::NONE, usage,
allocator);
if (!texData) {
return -ENOMEM;
}
RefPtr<TextureClient> textureClient = new ClientTexture(texData, TextureFlags::DEALLOCATE_CLIENT, allocator);
{ // Scope for the lock
Mutex::Autolock lock(mMutex);
@ -345,7 +341,7 @@ status_t GonkNativeWindow::dequeueBuffer(int *outBuf, uint32_t w, uint32_t h,
if (updateFormat) {
mPixelFormat = format;
}
mSlots[buf].mGraphicBuffer = graphicBuffer;
mSlots[buf].mGraphicBuffer = texData->GetGraphicBuffer();
mSlots[buf].mTextureClient = textureClient;
returnFlags |= ISurfaceTexture::BUFFER_NEEDS_REALLOCATION;