2013-08-09 19:23:46 +04:00
|
|
|
/* -*- 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/. */
|
|
|
|
|
|
|
|
#ifdef MOZ_WIDGET_GONK
|
|
|
|
|
|
|
|
#include "mozilla/layers/GrallocTextureClient.h"
|
|
|
|
#include "mozilla/layers/CompositableClient.h"
|
|
|
|
#include "mozilla/layers/CompositableForwarder.h"
|
|
|
|
#include "mozilla/layers/ISurfaceAllocator.h"
|
|
|
|
#include "mozilla/layers/ShadowLayerUtilsGralloc.h"
|
2013-09-12 18:50:28 +04:00
|
|
|
#include "GrallocImages.h"
|
2013-08-09 19:23:46 +04:00
|
|
|
#include "gfx2DGlue.h"
|
|
|
|
|
|
|
|
namespace mozilla {
|
|
|
|
namespace layers {
|
|
|
|
|
2013-12-31 13:06:12 +04:00
|
|
|
using namespace mozilla::gfx;
|
2013-08-09 19:23:46 +04:00
|
|
|
using namespace android;
|
|
|
|
|
2013-09-12 18:50:28 +04:00
|
|
|
class GraphicBufferLockedTextureClientData : public TextureClientData {
|
|
|
|
public:
|
|
|
|
GraphicBufferLockedTextureClientData(GraphicBufferLocked* aBufferLocked)
|
|
|
|
: mBufferLocked(aBufferLocked)
|
|
|
|
{
|
|
|
|
MOZ_COUNT_CTOR(GrallocTextureClientData);
|
|
|
|
}
|
|
|
|
|
|
|
|
~GraphicBufferLockedTextureClientData()
|
|
|
|
{
|
|
|
|
MOZ_COUNT_DTOR(GrallocTextureClientData);
|
|
|
|
MOZ_ASSERT(!mBufferLocked, "Forgot to unlock the GraphicBufferLocked?");
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void DeallocateSharedData(ISurfaceAllocator*) MOZ_OVERRIDE
|
|
|
|
{
|
|
|
|
mBufferLocked->Unlock();
|
|
|
|
mBufferLocked = nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
RefPtr<GraphicBufferLocked> mBufferLocked;
|
|
|
|
};
|
|
|
|
|
|
|
|
class GrallocTextureClientData : public TextureClientData {
|
|
|
|
public:
|
|
|
|
GrallocTextureClientData(GrallocBufferActor* aActor)
|
|
|
|
: mGrallocActor(aActor)
|
|
|
|
{
|
|
|
|
MOZ_COUNT_CTOR(GrallocTextureClientData);
|
|
|
|
}
|
|
|
|
|
|
|
|
~GrallocTextureClientData()
|
|
|
|
{
|
|
|
|
MOZ_COUNT_DTOR(GrallocTextureClientData);
|
|
|
|
MOZ_ASSERT(!mGrallocActor, "Forgot to unlock the GraphicBufferLocked?");
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void DeallocateSharedData(ISurfaceAllocator* allocator) MOZ_OVERRIDE
|
|
|
|
{
|
|
|
|
// We just need to wrap the actor in a SurfaceDescriptor because that's what
|
|
|
|
// ISurfaceAllocator uses as input, we don't care about the other parameters.
|
|
|
|
SurfaceDescriptor sd = SurfaceDescriptorGralloc(nullptr, mGrallocActor,
|
2013-12-31 13:06:12 +04:00
|
|
|
IntSize(0, 0),
|
|
|
|
false, false);
|
2013-09-12 18:50:28 +04:00
|
|
|
allocator->DestroySharedSurface(&sd);
|
|
|
|
mGrallocActor = nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
GrallocBufferActor* mGrallocActor;
|
|
|
|
};
|
|
|
|
|
|
|
|
TextureClientData*
|
|
|
|
GrallocTextureClientOGL::DropTextureData()
|
|
|
|
{
|
|
|
|
if (mBufferLocked) {
|
|
|
|
TextureClientData* result = new GraphicBufferLockedTextureClientData(mBufferLocked);
|
|
|
|
mBufferLocked = nullptr;
|
|
|
|
mGrallocActor = nullptr;
|
|
|
|
mGraphicBuffer = nullptr;
|
|
|
|
return result;
|
|
|
|
} else {
|
|
|
|
TextureClientData* result = new GrallocTextureClientData(mGrallocActor);
|
|
|
|
mGrallocActor = nullptr;
|
|
|
|
mGraphicBuffer = nullptr;
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-08-09 19:23:46 +04:00
|
|
|
GrallocTextureClientOGL::GrallocTextureClientOGL(GrallocBufferActor* aActor,
|
|
|
|
gfx::IntSize aSize,
|
|
|
|
TextureFlags aFlags)
|
|
|
|
: BufferTextureClient(nullptr, gfx::FORMAT_UNKNOWN, aFlags)
|
2014-01-10 17:06:06 +04:00
|
|
|
, mAllocator(nullptr)
|
2013-08-09 19:23:46 +04:00
|
|
|
, mGrallocFlags(android::GraphicBuffer::USAGE_SW_READ_OFTEN)
|
|
|
|
, mMappedBuffer(nullptr)
|
|
|
|
{
|
|
|
|
InitWith(aActor, aSize);
|
|
|
|
MOZ_COUNT_CTOR(GrallocTextureClientOGL);
|
|
|
|
}
|
|
|
|
|
|
|
|
GrallocTextureClientOGL::GrallocTextureClientOGL(CompositableClient* aCompositable,
|
|
|
|
gfx::SurfaceFormat aFormat,
|
|
|
|
TextureFlags aFlags)
|
|
|
|
: BufferTextureClient(aCompositable, aFormat, aFlags)
|
2014-01-10 17:06:06 +04:00
|
|
|
, mAllocator(nullptr)
|
|
|
|
, mGrallocFlags(android::GraphicBuffer::USAGE_SW_READ_OFTEN)
|
|
|
|
, mMappedBuffer(nullptr)
|
|
|
|
{
|
|
|
|
MOZ_COUNT_CTOR(GrallocTextureClientOGL);
|
|
|
|
}
|
|
|
|
|
|
|
|
GrallocTextureClientOGL::GrallocTextureClientOGL(ISurfaceAllocator* aAllocator,
|
|
|
|
gfx::SurfaceFormat aFormat,
|
|
|
|
TextureFlags aFlags)
|
|
|
|
: BufferTextureClient(nullptr, aFormat, aFlags)
|
|
|
|
, mAllocator(aAllocator)
|
2013-08-09 19:23:46 +04:00
|
|
|
, mGrallocFlags(android::GraphicBuffer::USAGE_SW_READ_OFTEN)
|
|
|
|
, mMappedBuffer(nullptr)
|
|
|
|
{
|
|
|
|
MOZ_COUNT_CTOR(GrallocTextureClientOGL);
|
|
|
|
}
|
|
|
|
|
|
|
|
GrallocTextureClientOGL::~GrallocTextureClientOGL()
|
|
|
|
{
|
|
|
|
MOZ_COUNT_DTOR(GrallocTextureClientOGL);
|
2013-09-12 18:50:35 +04:00
|
|
|
if (ShouldDeallocateInDestructor()) {
|
|
|
|
// If the buffer has never been shared we must deallocate it or it would
|
|
|
|
// leak.
|
|
|
|
if (mBufferLocked) {
|
|
|
|
mBufferLocked->Unlock();
|
|
|
|
} else {
|
|
|
|
// We just need to wrap the actor in a SurfaceDescriptor because that's what
|
|
|
|
// ISurfaceAllocator uses as input, we don't care about the other parameters.
|
|
|
|
SurfaceDescriptor sd = SurfaceDescriptorGralloc(nullptr, mGrallocActor,
|
2013-12-31 13:06:12 +04:00
|
|
|
IntSize(0, 0),
|
|
|
|
false, false);
|
2014-01-10 17:06:06 +04:00
|
|
|
|
|
|
|
ISurfaceAllocator* allocator = GetAllocator();
|
|
|
|
allocator->DestroySharedSurface(&sd);
|
2013-09-12 18:50:35 +04:00
|
|
|
}
|
|
|
|
}
|
2013-08-09 19:23:46 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
GrallocTextureClientOGL::InitWith(GrallocBufferActor* aActor, gfx::IntSize aSize)
|
|
|
|
{
|
|
|
|
MOZ_ASSERT(aActor);
|
|
|
|
MOZ_ASSERT(!IsAllocated());
|
2013-09-06 13:04:50 +04:00
|
|
|
MOZ_ASSERT(IsValid());
|
2013-08-09 19:23:46 +04:00
|
|
|
mGrallocActor = aActor;
|
|
|
|
mGraphicBuffer = aActor->GetGraphicBuffer();
|
|
|
|
mSize = aSize;
|
|
|
|
}
|
|
|
|
|
2013-09-12 18:50:28 +04:00
|
|
|
void
|
|
|
|
GrallocTextureClientOGL::SetGraphicBufferLocked(GraphicBufferLocked* aBufferLocked)
|
|
|
|
{
|
|
|
|
mBufferLocked = aBufferLocked;
|
|
|
|
}
|
|
|
|
|
2013-08-09 19:23:46 +04:00
|
|
|
bool
|
|
|
|
GrallocTextureClientOGL::ToSurfaceDescriptor(SurfaceDescriptor& aOutDescriptor)
|
|
|
|
{
|
2013-09-06 13:04:50 +04:00
|
|
|
MOZ_ASSERT(IsValid());
|
2013-08-09 19:23:46 +04:00
|
|
|
if (!IsAllocated()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
aOutDescriptor = NewSurfaceDescriptorGralloc(nullptr, mGrallocActor, mSize);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
GrallocTextureClientOGL::Lock(OpenMode aMode)
|
|
|
|
{
|
2013-09-06 13:04:50 +04:00
|
|
|
MOZ_ASSERT(IsValid());
|
2013-08-09 19:23:46 +04:00
|
|
|
// XXX- it would be cleaner to take the openMode into account or to check
|
|
|
|
// that aMode is coherent with mGrallocFlags (which carries more information
|
|
|
|
// than OpenMode).
|
|
|
|
int32_t rv = mGraphicBuffer->lock(mGrallocFlags, reinterpret_cast<void**>(&mMappedBuffer));
|
|
|
|
if (rv) {
|
|
|
|
NS_WARNING("Couldn't lock graphic buffer");
|
|
|
|
return false;
|
|
|
|
}
|
2014-01-07 20:20:11 +04:00
|
|
|
return BufferTextureClient::Lock(aMode);
|
2013-08-09 19:23:46 +04:00
|
|
|
}
|
2014-01-07 20:20:11 +04:00
|
|
|
|
2013-08-09 19:23:46 +04:00
|
|
|
void
|
|
|
|
GrallocTextureClientOGL::Unlock()
|
|
|
|
{
|
2014-01-07 20:20:11 +04:00
|
|
|
BufferTextureClient::Unlock();
|
2013-08-09 19:23:46 +04:00
|
|
|
mMappedBuffer = nullptr;
|
|
|
|
mGraphicBuffer->unlock();
|
|
|
|
}
|
|
|
|
|
|
|
|
uint8_t*
|
|
|
|
GrallocTextureClientOGL::GetBuffer() const
|
|
|
|
{
|
2013-09-06 13:04:50 +04:00
|
|
|
MOZ_ASSERT(IsValid());
|
2013-08-09 19:23:46 +04:00
|
|
|
NS_WARN_IF_FALSE(mMappedBuffer, "Trying to get a gralloc buffer without getting the lock?");
|
|
|
|
return mMappedBuffer;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2013-12-05 22:39:22 +04:00
|
|
|
GrallocTextureClientOGL::AllocateForSurface(gfx::IntSize aSize,
|
|
|
|
TextureAllocationFlags)
|
2013-08-09 19:23:46 +04:00
|
|
|
{
|
2013-09-06 13:04:50 +04:00
|
|
|
MOZ_ASSERT(IsValid());
|
2013-08-09 19:23:46 +04:00
|
|
|
|
|
|
|
uint32_t format;
|
|
|
|
uint32_t usage = android::GraphicBuffer::USAGE_SW_READ_OFTEN;
|
|
|
|
bool swapRB = GetFlags() & TEXTURE_RB_SWAPPED;
|
|
|
|
|
|
|
|
switch (mFormat) {
|
|
|
|
case gfx::FORMAT_R8G8B8A8:
|
|
|
|
format = swapRB ? android::PIXEL_FORMAT_BGRA_8888 : android::PIXEL_FORMAT_RGBA_8888;
|
|
|
|
break;
|
|
|
|
case gfx::FORMAT_B8G8R8A8:
|
|
|
|
format = swapRB ? android::PIXEL_FORMAT_RGBA_8888 : android::PIXEL_FORMAT_BGRA_8888;
|
|
|
|
break;
|
|
|
|
case gfx::FORMAT_R8G8B8X8:
|
|
|
|
case gfx::FORMAT_B8G8R8X8:
|
|
|
|
// there is no android BGRX format?
|
|
|
|
format = android::PIXEL_FORMAT_RGBX_8888;
|
|
|
|
break;
|
|
|
|
case gfx::FORMAT_R5G6B5:
|
|
|
|
format = android::PIXEL_FORMAT_RGB_565;
|
|
|
|
break;
|
|
|
|
case gfx::FORMAT_A8:
|
|
|
|
format = android::PIXEL_FORMAT_A_8;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
NS_WARNING("Unsupported surface format");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return AllocateGralloc(aSize, format, usage);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2013-08-30 18:24:05 +04:00
|
|
|
GrallocTextureClientOGL::AllocateForYCbCr(gfx::IntSize aYSize, gfx::IntSize aCbCrSize, StereoMode aStereoMode)
|
2013-08-09 19:23:46 +04:00
|
|
|
{
|
2013-09-06 13:04:50 +04:00
|
|
|
MOZ_ASSERT(IsValid());
|
2013-08-09 19:23:46 +04:00
|
|
|
return AllocateGralloc(aYSize,
|
|
|
|
HAL_PIXEL_FORMAT_YV12,
|
|
|
|
android::GraphicBuffer::USAGE_SW_READ_OFTEN);
|
|
|
|
}
|
|
|
|
|
2014-01-10 17:06:06 +04:00
|
|
|
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::FORMAT_R8G8B8A8:
|
|
|
|
case gfx::FORMAT_B8G8R8A8:
|
|
|
|
format = android::PIXEL_FORMAT_RGBA_8888;
|
|
|
|
break;
|
|
|
|
case gfx::FORMAT_R8G8B8X8:
|
|
|
|
case gfx::FORMAT_B8G8R8X8:
|
|
|
|
// there is no android BGRX format?
|
|
|
|
format = android::PIXEL_FORMAT_RGBX_8888;
|
|
|
|
break;
|
|
|
|
case gfx::FORMAT_R5G6B5:
|
|
|
|
format = android::PIXEL_FORMAT_RGB_565;
|
|
|
|
break;
|
|
|
|
case gfx::FORMAT_A8:
|
|
|
|
format = android::PIXEL_FORMAT_A_8;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
NS_WARNING("Unsupported surface format");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return AllocateGralloc(aSize, format, usage);
|
|
|
|
}
|
|
|
|
|
2013-08-09 19:23:46 +04:00
|
|
|
bool
|
|
|
|
GrallocTextureClientOGL::AllocateGralloc(gfx::IntSize aSize,
|
|
|
|
uint32_t aAndroidFormat,
|
|
|
|
uint32_t aUsage)
|
|
|
|
{
|
2013-09-06 13:04:50 +04:00
|
|
|
MOZ_ASSERT(IsValid());
|
2014-01-10 17:06:06 +04:00
|
|
|
ISurfaceAllocator* allocator = GetAllocator();
|
2013-08-09 19:23:46 +04:00
|
|
|
|
|
|
|
MaybeMagicGrallocBufferHandle handle;
|
|
|
|
PGrallocBufferChild* actor =
|
2013-12-20 20:46:28 +04:00
|
|
|
allocator->AllocGrallocBuffer(aSize,
|
2013-08-09 19:23:46 +04:00
|
|
|
aAndroidFormat,
|
|
|
|
aUsage,
|
|
|
|
&handle);
|
|
|
|
if (!actor) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
GrallocBufferActor* gba = static_cast<GrallocBufferActor*>(actor);
|
|
|
|
gba->InitFromHandle(handle.get_MagicGrallocBufferHandle());
|
|
|
|
|
|
|
|
sp<GraphicBuffer> graphicBuffer = gba->GetGraphicBuffer();
|
|
|
|
if (!graphicBuffer.get()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (graphicBuffer->initCheck() != NO_ERROR) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
mGrallocActor = gba;
|
|
|
|
mGraphicBuffer = graphicBuffer;
|
|
|
|
mSize = aSize;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
GrallocTextureClientOGL::IsAllocated() const
|
|
|
|
{
|
|
|
|
return !!mGraphicBuffer.get();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
GrallocTextureClientOGL::Allocate(uint32_t aSize)
|
|
|
|
{
|
|
|
|
// see Bug 908196
|
|
|
|
MOZ_CRASH("This method should never be called.");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t
|
|
|
|
GrallocTextureClientOGL::GetBufferSize() const
|
|
|
|
{
|
|
|
|
// see Bug 908196
|
|
|
|
MOZ_CRASH("This method should never be called.");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-01-10 17:06:06 +04:00
|
|
|
ISurfaceAllocator*
|
|
|
|
GrallocTextureClientOGL::GetAllocator()
|
|
|
|
{
|
|
|
|
MOZ_ASSERT(mCompositable || mAllocator);
|
|
|
|
return mCompositable ?
|
|
|
|
mCompositable->GetForwarder() :
|
|
|
|
mAllocator;
|
|
|
|
}
|
|
|
|
|
2013-08-09 19:23:46 +04:00
|
|
|
} // namesapace layers
|
|
|
|
} // namesapace mozilla
|
|
|
|
|
|
|
|
#endif // MOZ_WIDGET_GONK
|