Backed out changeset cf8cf1a039dd (bug 1200595) Backed out changeset 65da564f952c (bug 1200595) Backed out changeset 7663208f1582 (bug 1200595) Backed out changeset fc1fbb97c8eb (bug 1200595) Backed out changeset 3ad5a4c457fe (bug 1200595) Backed out changeset add3fe9afc0c (bug 1200595) Backed out changeset 68aba6b39588 (bug 1200595) Backed out changeset ab326c34f1cf (bug 1200595) Backed out changeset ed34bc528a1b (bug 1200595) Backed out changeset 0dc93424546c (bug 1200595) Backed out changeset 8cc12f12f3d1 (bug 1200595) Backed out changeset bb84403701b7 (bug 1200595)
425 lines
12 KiB
C++
425 lines
12 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/. */
|
|
|
|
#ifdef MOZ_WIDGET_GONK
|
|
|
|
#include "mozilla/gfx/2D.h"
|
|
#include "mozilla/layers/AsyncTransactionTracker.h" // for AsyncTransactionTracker
|
|
#include "mozilla/layers/GrallocTextureClient.h"
|
|
#include "mozilla/layers/CompositableForwarder.h"
|
|
#include "mozilla/layers/ISurfaceAllocator.h"
|
|
#include "mozilla/layers/ShadowLayerUtilsGralloc.h"
|
|
#include "gfx2DGlue.h"
|
|
#include "SharedSurfaceGralloc.h"
|
|
|
|
#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17
|
|
#include <ui/Fence.h>
|
|
#endif
|
|
|
|
namespace mozilla {
|
|
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))
|
|
{
|
|
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(IsValid());
|
|
if (!IsValid() || !IsAllocated()) {
|
|
return false;
|
|
}
|
|
|
|
if (mMappedBuffer) {
|
|
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;
|
|
}
|
|
return BufferTextureClient::Lock(aMode);
|
|
}
|
|
|
|
void
|
|
GrallocTextureClientOGL::Unlock()
|
|
{
|
|
BufferTextureClient::Unlock();
|
|
mDrawTarget = nullptr;
|
|
if (mMappedBuffer) {
|
|
mMappedBuffer = nullptr;
|
|
mGraphicBuffer->unlock();
|
|
}
|
|
}
|
|
|
|
uint8_t*
|
|
GrallocTextureClientOGL::GetBuffer() const
|
|
{
|
|
MOZ_ASSERT(IsValid());
|
|
NS_WARN_IF_FALSE(mMappedBuffer, "Trying to get a gralloc buffer without getting the lock?");
|
|
return mMappedBuffer;
|
|
}
|
|
|
|
static gfx::SurfaceFormat
|
|
SurfaceFormatForPixelFormat(android::PixelFormat aFormat)
|
|
{
|
|
switch (aFormat) {
|
|
case PIXEL_FORMAT_RGBA_8888:
|
|
return gfx::SurfaceFormat::R8G8B8A8;
|
|
case PIXEL_FORMAT_BGRA_8888:
|
|
return gfx::SurfaceFormat::B8G8R8A8;
|
|
case PIXEL_FORMAT_RGBX_8888:
|
|
return gfx::SurfaceFormat::R8G8B8X8;
|
|
case PIXEL_FORMAT_RGB_565:
|
|
return gfx::SurfaceFormat::R5G6B5_UINT16;
|
|
case HAL_PIXEL_FORMAT_YV12:
|
|
return gfx::SurfaceFormat::YUV;
|
|
default:
|
|
MOZ_CRASH("Unknown gralloc pixel format");
|
|
}
|
|
return gfx::SurfaceFormat::R8G8B8A8;
|
|
}
|
|
|
|
gfx::DrawTarget*
|
|
GrallocTextureClientOGL::BorrowDrawTarget()
|
|
{
|
|
MOZ_ASSERT(IsValid());
|
|
MOZ_ASSERT(mMappedBuffer, "Calling TextureClient::BorrowDrawTarget without locking :(");
|
|
|
|
if (!IsValid() || !IsAllocated() || !mMappedBuffer) {
|
|
return nullptr;
|
|
}
|
|
|
|
if (mDrawTarget) {
|
|
return mDrawTarget;
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
void
|
|
GrallocTextureClientOGL::UpdateFromSurface(gfx::SourceSurface* aSurface)
|
|
{
|
|
MOZ_ASSERT(IsValid());
|
|
MOZ_ASSERT(mMappedBuffer, "Calling TextureClient::BorrowDrawTarget without locking :(");
|
|
|
|
if (!IsValid() || !IsAllocated() || !mMappedBuffer) {
|
|
return;
|
|
}
|
|
|
|
RefPtr<DataSourceSurface> srcSurf = aSurface->GetDataSurface();
|
|
|
|
if (!srcSurf) {
|
|
gfxCriticalError() << "Failed to GetDataSurface in UpdateFromSurface.";
|
|
return;
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
long pixelStride = mGraphicBuffer->getStride();
|
|
long byteStride = pixelStride * BytesPerPixel(format);
|
|
|
|
DataSourceSurface::MappedSurface sourceMap;
|
|
|
|
if (!srcSurf->Map(DataSourceSurface::READ, &sourceMap)) {
|
|
gfxCriticalError() << "Failed to map source surface for UpdateFromSurface.";
|
|
return;
|
|
}
|
|
|
|
uint8_t* buffer = GetBuffer();
|
|
|
|
for (int y = 0; y < srcSurf->GetSize().height; y++) {
|
|
memcpy(buffer + byteStride * y,
|
|
sourceMap.mData + sourceMap.mStride * y,
|
|
srcSurf->GetSize().width * BytesPerPixel(srcSurf->GetFormat()));
|
|
}
|
|
|
|
srcSurf->Unmap();
|
|
}
|
|
|
|
bool
|
|
GrallocTextureClientOGL::AllocateForSurface(gfx::IntSize aSize,
|
|
TextureAllocationFlags)
|
|
{
|
|
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;
|
|
}
|
|
|
|
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;
|
|
break;
|
|
case gfx::SurfaceFormat::R8G8B8X8:
|
|
case gfx::SurfaceFormat::B8G8R8X8:
|
|
// there is no android BGRX format?
|
|
format = android::PIXEL_FORMAT_RGBX_8888;
|
|
break;
|
|
case gfx::SurfaceFormat::R5G6B5_UINT16:
|
|
format = android::PIXEL_FORMAT_RGB_565;
|
|
break;
|
|
default:
|
|
NS_WARNING("Unsupported surface format");
|
|
return false;
|
|
}
|
|
|
|
return AllocateGralloc(aSize, format, usage);
|
|
}
|
|
|
|
bool
|
|
GrallocTextureClientOGL::AllocateGralloc(gfx::IntSize aSize,
|
|
uint32_t aAndroidFormat,
|
|
uint32_t aUsage)
|
|
{
|
|
MOZ_ASSERT(IsValid());
|
|
ISurfaceAllocator* allocator = GetAllocator();
|
|
|
|
MaybeMagicGrallocBufferHandle handle;
|
|
bool allocateResult =
|
|
allocator->AllocGrallocBuffer(aSize,
|
|
aAndroidFormat,
|
|
aUsage,
|
|
&handle);
|
|
if (!allocateResult) {
|
|
return false;
|
|
}
|
|
|
|
sp<GraphicBuffer> graphicBuffer = GetGraphicBufferFrom(handle);
|
|
if (!graphicBuffer.get()) {
|
|
return false;
|
|
}
|
|
|
|
if (graphicBuffer->initCheck() != NO_ERROR) {
|
|
return false;
|
|
}
|
|
|
|
mGrallocHandle = handle;
|
|
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;
|
|
}
|
|
|
|
/*static*/ already_AddRefed<TextureClient>
|
|
GrallocTextureClientOGL::FromSharedSurface(gl::SharedSurface* abstractSurf,
|
|
TextureFlags flags)
|
|
{
|
|
auto surf = gl::SharedSurface_Gralloc::Cast(abstractSurf);
|
|
|
|
RefPtr<TextureClient> ret = surf->GetTextureClient();
|
|
|
|
TextureFlags mask = TextureFlags::ORIGIN_BOTTOM_LEFT |
|
|
TextureFlags::RB_SWAPPED |
|
|
TextureFlags::NON_PREMULTIPLIED;
|
|
TextureFlags required = flags & mask;
|
|
TextureFlags present = ret->GetFlags() & mask;
|
|
|
|
if (present != required) {
|
|
printf_stderr("Present flags: 0x%x. Required: 0x%x.\n",
|
|
(uint32_t)present,
|
|
(uint32_t)required);
|
|
MOZ_CRASH("Flag requirement mismatch.");
|
|
}
|
|
return ret.forget();
|
|
}
|
|
|
|
} // namesapace layers
|
|
} // namesapace mozilla
|
|
|
|
#endif // MOZ_WIDGET_GONK
|