michael@0: /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- michael@0: // * This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #ifdef MOZ_WIDGET_GONK michael@0: michael@0: #include "mozilla/gfx/2D.h" michael@0: #include "mozilla/layers/GrallocTextureClient.h" michael@0: #include "mozilla/layers/CompositableForwarder.h" michael@0: #include "mozilla/layers/ISurfaceAllocator.h" michael@0: #include "mozilla/layers/ShadowLayerUtilsGralloc.h" michael@0: #include "gfx2DGlue.h" michael@0: michael@0: namespace mozilla { michael@0: namespace layers { michael@0: michael@0: using namespace mozilla::gfx; michael@0: using namespace android; michael@0: michael@0: class GrallocTextureClientData : public TextureClientData { michael@0: public: michael@0: GrallocTextureClientData(GrallocBufferActor* aActor) michael@0: : mGrallocActor(aActor) michael@0: { michael@0: MOZ_COUNT_CTOR(GrallocTextureClientData); michael@0: } michael@0: michael@0: ~GrallocTextureClientData() michael@0: { michael@0: MOZ_COUNT_DTOR(GrallocTextureClientData); michael@0: MOZ_ASSERT(!mGrallocActor); michael@0: } michael@0: michael@0: virtual void DeallocateSharedData(ISurfaceAllocator* allocator) MOZ_OVERRIDE michael@0: { michael@0: allocator->DeallocGrallocBuffer(mGrallocActor); michael@0: mGrallocActor = nullptr; michael@0: } michael@0: michael@0: private: michael@0: GrallocBufferActor* mGrallocActor; michael@0: }; michael@0: michael@0: TextureClientData* michael@0: GrallocTextureClientOGL::DropTextureData() michael@0: { michael@0: TextureClientData* result = new GrallocTextureClientData(mGrallocActor); michael@0: mGrallocActor = nullptr; michael@0: mGraphicBuffer = nullptr; michael@0: return result; michael@0: } michael@0: michael@0: GrallocTextureClientOGL::GrallocTextureClientOGL(GrallocBufferActor* aActor, michael@0: gfx::IntSize aSize, michael@0: gfx::BackendType aMoz2dBackend, michael@0: TextureFlags aFlags) michael@0: : BufferTextureClient(nullptr, gfx::SurfaceFormat::UNKNOWN, aMoz2dBackend, aFlags) michael@0: , mMappedBuffer(nullptr) michael@0: , mMediaBuffer(nullptr) michael@0: { michael@0: InitWith(aActor, aSize); michael@0: MOZ_COUNT_CTOR(GrallocTextureClientOGL); michael@0: } michael@0: michael@0: GrallocTextureClientOGL::GrallocTextureClientOGL(ISurfaceAllocator* aAllocator, michael@0: gfx::SurfaceFormat aFormat, michael@0: gfx::BackendType aMoz2dBackend, michael@0: TextureFlags aFlags) michael@0: : BufferTextureClient(aAllocator, aFormat, aMoz2dBackend, aFlags) michael@0: , mMappedBuffer(nullptr) michael@0: , mMediaBuffer(nullptr) michael@0: { michael@0: MOZ_COUNT_CTOR(GrallocTextureClientOGL); michael@0: } michael@0: michael@0: GrallocTextureClientOGL::~GrallocTextureClientOGL() michael@0: { michael@0: MOZ_COUNT_DTOR(GrallocTextureClientOGL); michael@0: if (ShouldDeallocateInDestructor()) { michael@0: ISurfaceAllocator* allocator = GetAllocator(); michael@0: allocator->DeallocGrallocBuffer(mGrallocActor); michael@0: } michael@0: } michael@0: michael@0: void michael@0: GrallocTextureClientOGL::InitWith(GrallocBufferActor* aActor, gfx::IntSize aSize) michael@0: { michael@0: MOZ_ASSERT(aActor); michael@0: MOZ_ASSERT(!IsAllocated()); michael@0: MOZ_ASSERT(IsValid()); michael@0: mGrallocActor = aActor; michael@0: mGraphicBuffer = aActor->GetGraphicBuffer(); michael@0: mSize = aSize; michael@0: } michael@0: michael@0: bool michael@0: GrallocTextureClientOGL::ToSurfaceDescriptor(SurfaceDescriptor& aOutDescriptor) michael@0: { michael@0: MOZ_ASSERT(IsValid()); michael@0: if (!IsAllocated()) { michael@0: return false; michael@0: } michael@0: michael@0: aOutDescriptor = NewSurfaceDescriptorGralloc(nullptr, mGrallocActor, mSize); michael@0: return true; michael@0: } michael@0: michael@0: void michael@0: GrallocTextureClientOGL::SetReleaseFenceHandle(FenceHandle aReleaseFenceHandle) michael@0: { michael@0: mReleaseFenceHandle = aReleaseFenceHandle; michael@0: } michael@0: michael@0: void michael@0: GrallocTextureClientOGL::WaitReleaseFence() michael@0: { michael@0: #if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17 michael@0: if (mReleaseFenceHandle.IsValid()) { michael@0: android::sp fence = mReleaseFenceHandle.mFence; michael@0: #if ANDROID_VERSION == 17 michael@0: fence->waitForever(1000, "GrallocTextureClientOGL::Lock"); michael@0: // 1000 is what Android uses. It is warning timeout ms. michael@0: // This timeous is removed since ANDROID_VERSION 18. michael@0: #else michael@0: fence->waitForever("GrallocTextureClientOGL::Lock"); michael@0: #endif michael@0: mReleaseFenceHandle = FenceHandle(); michael@0: } michael@0: #endif michael@0: } michael@0: michael@0: bool michael@0: GrallocTextureClientOGL::Lock(OpenMode aMode) michael@0: { michael@0: MOZ_ASSERT(IsValid()); michael@0: if (!IsValid() || !IsAllocated()) { michael@0: return false; michael@0: } michael@0: michael@0: if (mMappedBuffer) { michael@0: return true; michael@0: } michael@0: michael@0: WaitReleaseFence(); michael@0: michael@0: uint32_t usage = 0; michael@0: if (aMode & OPEN_READ) { michael@0: usage |= GRALLOC_USAGE_SW_READ_OFTEN; michael@0: } michael@0: if (aMode & OPEN_WRITE) { michael@0: usage |= GRALLOC_USAGE_SW_WRITE_OFTEN; michael@0: } michael@0: int32_t rv = mGraphicBuffer->lock(usage, reinterpret_cast(&mMappedBuffer)); michael@0: if (rv) { michael@0: mMappedBuffer = nullptr; michael@0: NS_WARNING("Couldn't lock graphic buffer"); michael@0: return false; michael@0: } michael@0: return BufferTextureClient::Lock(aMode); michael@0: } michael@0: michael@0: void michael@0: GrallocTextureClientOGL::Unlock() michael@0: { michael@0: BufferTextureClient::Unlock(); michael@0: mDrawTarget = nullptr; michael@0: if (mMappedBuffer) { michael@0: mMappedBuffer = nullptr; michael@0: mGraphicBuffer->unlock(); michael@0: } michael@0: } michael@0: michael@0: uint8_t* michael@0: GrallocTextureClientOGL::GetBuffer() const michael@0: { michael@0: MOZ_ASSERT(IsValid()); michael@0: NS_WARN_IF_FALSE(mMappedBuffer, "Trying to get a gralloc buffer without getting the lock?"); michael@0: return mMappedBuffer; michael@0: } michael@0: michael@0: static gfx::SurfaceFormat michael@0: SurfaceFormatForPixelFormat(android::PixelFormat aFormat) michael@0: { michael@0: switch (aFormat) { michael@0: case PIXEL_FORMAT_RGBA_8888: michael@0: return gfx::SurfaceFormat::R8G8B8A8; michael@0: case PIXEL_FORMAT_BGRA_8888: michael@0: return gfx::SurfaceFormat::B8G8R8A8; michael@0: case PIXEL_FORMAT_RGBX_8888: michael@0: return gfx::SurfaceFormat::R8G8B8X8; michael@0: case PIXEL_FORMAT_RGB_565: michael@0: return gfx::SurfaceFormat::R5G6B5; michael@0: default: michael@0: MOZ_CRASH("Unknown gralloc pixel format"); michael@0: } michael@0: return gfx::SurfaceFormat::R8G8B8A8; michael@0: } michael@0: michael@0: TemporaryRef michael@0: GrallocTextureClientOGL::GetAsDrawTarget() michael@0: { michael@0: MOZ_ASSERT(IsValid()); michael@0: MOZ_ASSERT(mMappedBuffer, "Calling TextureClient::GetAsDrawTarget without locking :("); michael@0: michael@0: if (mDrawTarget) { michael@0: return mDrawTarget; michael@0: } michael@0: michael@0: gfx::SurfaceFormat format = SurfaceFormatForPixelFormat(mGraphicBuffer->getPixelFormat()); michael@0: long pixelStride = mGraphicBuffer->getStride(); michael@0: long byteStride = pixelStride * BytesPerPixel(format); michael@0: mDrawTarget = gfxPlatform::GetPlatform()->CreateDrawTargetForData(GetBuffer(), michael@0: mSize, michael@0: byteStride, michael@0: mFormat); michael@0: return mDrawTarget; michael@0: } michael@0: michael@0: bool michael@0: GrallocTextureClientOGL::AllocateForSurface(gfx::IntSize aSize, michael@0: TextureAllocationFlags) michael@0: { michael@0: MOZ_ASSERT(IsValid()); michael@0: michael@0: uint32_t format; michael@0: uint32_t usage = android::GraphicBuffer::USAGE_SW_READ_OFTEN | michael@0: android::GraphicBuffer::USAGE_SW_WRITE_OFTEN | michael@0: android::GraphicBuffer::USAGE_HW_TEXTURE; michael@0: michael@0: switch (mFormat) { michael@0: case gfx::SurfaceFormat::R8G8B8A8: michael@0: format = android::PIXEL_FORMAT_RGBA_8888; michael@0: break; michael@0: case gfx::SurfaceFormat::B8G8R8A8: michael@0: format = android::PIXEL_FORMAT_RGBA_8888; michael@0: mFlags |= TEXTURE_RB_SWAPPED; michael@0: break; michael@0: case gfx::SurfaceFormat::R8G8B8X8: michael@0: format = android::PIXEL_FORMAT_RGBX_8888; michael@0: break; michael@0: case gfx::SurfaceFormat::B8G8R8X8: michael@0: format = android::PIXEL_FORMAT_RGBX_8888; michael@0: mFlags |= TEXTURE_RB_SWAPPED; michael@0: break; michael@0: case gfx::SurfaceFormat::R5G6B5: michael@0: format = android::PIXEL_FORMAT_RGB_565; michael@0: break; michael@0: case gfx::SurfaceFormat::A8: michael@0: NS_WARNING("gralloc does not support gfx::SurfaceFormat::A8"); michael@0: return false; michael@0: default: michael@0: NS_WARNING("Unsupported surface format"); michael@0: return false; michael@0: } michael@0: michael@0: return AllocateGralloc(aSize, format, usage); michael@0: } michael@0: michael@0: bool michael@0: GrallocTextureClientOGL::AllocateForYCbCr(gfx::IntSize aYSize, gfx::IntSize aCbCrSize, StereoMode aStereoMode) michael@0: { michael@0: MOZ_ASSERT(IsValid()); michael@0: return AllocateGralloc(aYSize, michael@0: HAL_PIXEL_FORMAT_YV12, michael@0: android::GraphicBuffer::USAGE_SW_READ_OFTEN); michael@0: } michael@0: michael@0: bool michael@0: GrallocTextureClientOGL::AllocateForGLRendering(gfx::IntSize aSize) michael@0: { michael@0: MOZ_ASSERT(IsValid()); michael@0: michael@0: uint32_t format; michael@0: uint32_t usage = android::GraphicBuffer::USAGE_HW_RENDER | michael@0: android::GraphicBuffer::USAGE_HW_TEXTURE; michael@0: michael@0: switch (mFormat) { michael@0: case gfx::SurfaceFormat::R8G8B8A8: michael@0: case gfx::SurfaceFormat::B8G8R8A8: michael@0: format = android::PIXEL_FORMAT_RGBA_8888; michael@0: break; michael@0: case gfx::SurfaceFormat::R8G8B8X8: michael@0: case gfx::SurfaceFormat::B8G8R8X8: michael@0: // there is no android BGRX format? michael@0: format = android::PIXEL_FORMAT_RGBX_8888; michael@0: break; michael@0: case gfx::SurfaceFormat::R5G6B5: michael@0: format = android::PIXEL_FORMAT_RGB_565; michael@0: break; michael@0: default: michael@0: NS_WARNING("Unsupported surface format"); michael@0: return false; michael@0: } michael@0: michael@0: return AllocateGralloc(aSize, format, usage); michael@0: } michael@0: michael@0: bool michael@0: GrallocTextureClientOGL::AllocateGralloc(gfx::IntSize aSize, michael@0: uint32_t aAndroidFormat, michael@0: uint32_t aUsage) michael@0: { michael@0: MOZ_ASSERT(IsValid()); michael@0: ISurfaceAllocator* allocator = GetAllocator(); michael@0: michael@0: MaybeMagicGrallocBufferHandle handle; michael@0: PGrallocBufferChild* actor = michael@0: allocator->AllocGrallocBuffer(aSize, michael@0: aAndroidFormat, michael@0: aUsage, michael@0: &handle); michael@0: if (!actor) { michael@0: return false; michael@0: } michael@0: GrallocBufferActor* gba = static_cast(actor); michael@0: gba->InitFromHandle(handle.get_MagicGrallocBufferHandle()); michael@0: michael@0: sp graphicBuffer = gba->GetGraphicBuffer(); michael@0: if (!graphicBuffer.get()) { michael@0: return false; michael@0: } michael@0: michael@0: if (graphicBuffer->initCheck() != NO_ERROR) { michael@0: return false; michael@0: } michael@0: michael@0: mGrallocActor = gba; michael@0: mGraphicBuffer = graphicBuffer; michael@0: mSize = aSize; michael@0: return true; michael@0: } michael@0: michael@0: bool michael@0: GrallocTextureClientOGL::IsAllocated() const michael@0: { michael@0: return !!mGraphicBuffer.get(); michael@0: } michael@0: michael@0: bool michael@0: GrallocTextureClientOGL::Allocate(uint32_t aSize) michael@0: { michael@0: // see Bug 908196 michael@0: MOZ_CRASH("This method should never be called."); michael@0: return false; michael@0: } michael@0: michael@0: size_t michael@0: GrallocTextureClientOGL::GetBufferSize() const michael@0: { michael@0: // see Bug 908196 michael@0: MOZ_CRASH("This method should never be called."); michael@0: return 0; michael@0: } michael@0: michael@0: } // namesapace layers michael@0: } // namesapace mozilla michael@0: michael@0: #endif // MOZ_WIDGET_GONK