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
2014-02-13 18:46:59 +04:00
# include "mozilla/gfx/2D.h"
2014-05-24 20:14:45 +04:00
# include "mozilla/layers/AsyncTransactionTracker.h" // for AsyncTransactionTracker
2013-08-09 19:23:46 +04:00
# include "mozilla/layers/GrallocTextureClient.h"
# include "mozilla/layers/CompositableForwarder.h"
# include "mozilla/layers/ISurfaceAllocator.h"
# include "mozilla/layers/ShadowLayerUtilsGralloc.h"
# include "gfx2DGlue.h"
2014-10-08 08:11:54 +04:00
# include "SharedSurfaceGralloc.h"
2013-08-09 19:23:46 +04:00
2015-05-20 09:40:00 +03:00
# if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17
# include <ui/Fence.h>
# endif
2013-08-09 19:23:46 +04:00
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 ;
2014-01-10 17:06:06 +04:00
GrallocTextureClientOGL : : GrallocTextureClientOGL ( ISurfaceAllocator * aAllocator ,
gfx : : SurfaceFormat aFormat ,
2014-03-18 01:35:20 +04:00
gfx : : BackendType aMoz2dBackend ,
2014-01-10 17:06:06 +04:00
TextureFlags aFlags )
2014-03-18 01:35:20 +04:00
: BufferTextureClient ( aAllocator , aFormat , aMoz2dBackend , aFlags )
2014-05-21 00:50:25 +04:00
, mGrallocHandle ( null_t ( ) )
2013-08-09 19:23:46 +04:00
, mMappedBuffer ( nullptr )
2014-03-31 19:24:28 +04:00
, mMediaBuffer ( nullptr )
2014-10-30 05:32:40 +03:00
, mIsOpaque ( gfx : : IsOpaque ( aFormat ) )
2013-08-09 19:23:46 +04:00
{
MOZ_COUNT_CTOR ( GrallocTextureClientOGL ) ;
}
GrallocTextureClientOGL : : ~ GrallocTextureClientOGL ( )
{
MOZ_COUNT_DTOR ( GrallocTextureClientOGL ) ;
2014-07-19 16:33:12 +04:00
ISurfaceAllocator * allocator = GetAllocator ( ) ;
if ( ShouldDeallocateInDestructor ( ) ) {
2014-05-01 05:52:00 +04:00
allocator - > DeallocGrallocBuffer ( & mGrallocHandle ) ;
2014-07-19 16:33:12 +04:00
} else {
allocator - > DropGrallocBuffer ( & mGrallocHandle ) ;
2013-09-12 18:50:35 +04:00
}
2013-08-09 19:23:46 +04:00
}
2015-06-17 17:00:52 +03:00
already_AddRefed < TextureClient >
2014-07-25 13:24:46 +04:00
GrallocTextureClientOGL : : CreateSimilar ( TextureFlags aFlags ,
TextureAllocationFlags aAllocFlags ) const
{
RefPtr < TextureClient > tex = new GrallocTextureClientOGL (
mAllocator , mFormat , mBackend , mFlags | aFlags
) ;
if ( ! tex - > AllocateForSurface ( mSize , aAllocFlags ) ) {
return nullptr ;
}
2015-05-01 16:14:16 +03:00
return tex . forget ( ) ;
2014-07-25 13:24:46 +04:00
}
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 ;
}
2015-07-20 02:02:51 +03:00
aOutDescriptor = NewSurfaceDescriptorGralloc ( mGrallocHandle , mIsOpaque ) ;
2013-08-09 19:23:46 +04:00
return true ;
}
2014-03-27 05:01:15 +04:00
void
2015-05-12 06:36:49 +03:00
GrallocTextureClientOGL : : SetRemoveFromCompositableWaiter ( AsyncTransactionWaiter * aWaiter )
2014-03-27 05:01:15 +04:00
{
2015-05-12 06:36:49 +03:00
mRemoveFromCompositableWaiter = aWaiter ;
2014-05-24 20:14:45 +04:00
}
void
2015-01-27 21:05:35 +03:00
GrallocTextureClientOGL : : WaitForBufferOwnership ( bool aWaitReleaseFence )
2014-05-24 20:14:45 +04:00
{
2015-05-12 06:36:49 +03:00
if ( mRemoveFromCompositableWaiter ) {
mRemoveFromCompositableWaiter - > WaitComplete ( ) ;
mRemoveFromCompositableWaiter = nullptr ;
2014-05-24 20:14:45 +04:00
}
2015-01-27 21:05:35 +03:00
if ( ! aWaitReleaseFence ) {
return ;
}
2014-03-27 05:01:15 +04:00
# if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17
if ( mReleaseFenceHandle . IsValid ( ) ) {
2015-05-13 02:42:00 +03:00
nsRefPtr < FenceHandle : : FdObj > fdObj = mReleaseFenceHandle . GetAndResetFdObj ( ) ;
android : : sp < Fence > fence = new Fence ( fdObj - > GetAndResetFd ( ) ) ;
2014-03-27 05:01:15 +04:00
# if ANDROID_VERSION == 17
fence - > waitForever ( 1000 , " GrallocTextureClientOGL::Lock " ) ;
2014-10-09 00:04:19 +04:00
// 1000 is what Android uses. It is a warning timeout in ms.
// This timeout was removed in ANDROID_VERSION 18.
2014-03-27 05:01:15 +04:00
# else
fence - > waitForever ( " GrallocTextureClientOGL::Lock " ) ;
# endif
mReleaseFenceHandle = FenceHandle ( ) ;
}
# endif
}
2013-08-09 19:23:46 +04:00
bool
GrallocTextureClientOGL : : Lock ( OpenMode aMode )
{
2013-09-06 13:04:50 +04:00
MOZ_ASSERT ( IsValid ( ) ) ;
2014-01-24 18:25:04 +04:00
if ( ! IsValid ( ) | | ! IsAllocated ( ) ) {
return false ;
}
2014-02-13 18:46:59 +04:00
if ( mMappedBuffer ) {
return true ;
}
2014-02-25 08:23:41 +04:00
2015-01-27 21:05:35 +03:00
# if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 21
WaitForBufferOwnership ( false /* aWaitReleaseFence */ ) ;
# else
2014-05-24 20:14:45 +04:00
WaitForBufferOwnership ( ) ;
2015-01-27 21:05:35 +03:00
# endif
2014-02-25 08:23:41 +04:00
2014-02-13 18:46:59 +04:00
uint32_t usage = 0 ;
2014-04-26 06:34:06 +04:00
if ( aMode & OpenMode : : OPEN_READ ) {
2014-02-13 18:46:59 +04:00
usage | = GRALLOC_USAGE_SW_READ_OFTEN ;
}
2014-04-26 06:34:06 +04:00
if ( aMode & OpenMode : : OPEN_WRITE ) {
2014-02-13 18:46:59 +04:00
usage | = GRALLOC_USAGE_SW_WRITE_OFTEN ;
}
2015-01-27 21:05:35 +03:00
# if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 21
2015-05-13 02:42:00 +03:00
nsRefPtr < FenceHandle : : FdObj > fdObj = mReleaseFenceHandle . GetAndResetFdObj ( ) ;
2015-01-27 21:05:35 +03:00
int32_t rv = mGraphicBuffer - > lockAsync ( usage ,
reinterpret_cast < void * * > ( & mMappedBuffer ) ,
2015-05-13 02:42:00 +03:00
fdObj - > GetAndResetFd ( ) ) ;
2015-01-27 21:05:35 +03:00
# else
int32_t rv = mGraphicBuffer - > lock ( usage ,
reinterpret_cast < void * * > ( & mMappedBuffer ) ) ;
# endif
2013-08-09 19:23:46 +04:00
if ( rv ) {
2014-02-13 18:46:59 +04:00
mMappedBuffer = nullptr ;
2013-08-09 19:23:46 +04:00
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 ( ) ;
2014-02-13 18:46:59 +04:00
mDrawTarget = nullptr ;
if ( mMappedBuffer ) {
mMappedBuffer = nullptr ;
mGraphicBuffer - > unlock ( ) ;
}
2013-08-09 19:23:46 +04:00
}
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 ;
}
2014-02-13 18:46:59 +04:00
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 ;
2014-12-16 18:11:48 +03:00
case HAL_PIXEL_FORMAT_YV12 :
return gfx : : SurfaceFormat : : YUV ;
2014-02-13 18:46:59 +04:00
default :
MOZ_CRASH ( " Unknown gralloc pixel format " ) ;
}
return gfx : : SurfaceFormat : : R8G8B8A8 ;
}
2014-06-11 22:57:58 +04:00
gfx : : DrawTarget *
GrallocTextureClientOGL : : BorrowDrawTarget ( )
2014-02-13 18:46:59 +04:00
{
MOZ_ASSERT ( IsValid ( ) ) ;
2014-06-11 22:57:58 +04:00
MOZ_ASSERT ( mMappedBuffer , " Calling TextureClient::BorrowDrawTarget without locking :( " ) ;
2014-02-13 18:46:59 +04:00
2014-09-16 16:32:24 +04:00
if ( ! IsValid ( ) | | ! IsAllocated ( ) | | ! mMappedBuffer ) {
2014-05-22 17:17:03 +04:00
return nullptr ;
}
2014-02-13 18:46:59 +04:00
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 ;
}
2015-07-27 18:47:29 +03:00
void
GrallocTextureClientOGL : : UpdateFromSurface ( gfx : : DataSourceSurface * aSurface )
{
MOZ_ASSERT ( IsValid ( ) ) ;
MOZ_ASSERT ( mMappedBuffer , " Calling TextureClient::BorrowDrawTarget without locking :( " ) ;
if ( ! IsValid ( ) | | ! IsAllocated ( ) | | ! mMappedBuffer ) {
return ;
}
gfx : : SurfaceFormat format = SurfaceFormatForPixelFormat ( mGraphicBuffer - > getPixelFormat ( ) ) ;
if ( mSize ! = aSurface - > GetSize ( ) | | mFormat ! = aSurface - > GetFormat ( ) ) {
gfxCriticalError ( ) < < " Attempt to update texture client from a surface with a different size or format! This: " < < mSize < < " " < < format < < " Other: " < < aSurface - > GetSize ( ) < < " " < < aSurface - > GetFormat ( ) ;
return ;
}
long pixelStride = mGraphicBuffer - > getStride ( ) ;
long byteStride = pixelStride * BytesPerPixel ( format ) ;
DataSourceSurface : : MappedSurface sourceMap ;
aSurface - > Map ( DataSourceSurface : : READ , & sourceMap ) ;
uint8_t * buffer = GetBuffer ( ) ;
for ( int y = 0 ; y < aSurface - > GetSize ( ) . height ; y + + ) {
memcpy ( buffer + byteStride * y ,
sourceMap . mData + sourceMap . mStride * y ,
aSurface - > GetSize ( ) . width * BytesPerPixel ( aSurface - > GetFormat ( ) ) ) ;
}
aSurface - > Unmap ( ) ;
}
2013-08-09 19:23:46 +04:00
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 ;
2014-02-13 18:46:59 +04:00
uint32_t usage = android : : GraphicBuffer : : USAGE_SW_READ_OFTEN |
android : : GraphicBuffer : : USAGE_SW_WRITE_OFTEN |
android : : GraphicBuffer : : USAGE_HW_TEXTURE ;
2013-08-09 19:23:46 +04:00
switch ( mFormat ) {
2014-01-10 23:06:16 +04:00
case gfx : : SurfaceFormat : : R8G8B8A8 :
2014-02-13 18:46:59 +04:00
format = android : : PIXEL_FORMAT_RGBA_8888 ;
2013-08-09 19:23:46 +04:00
break ;
2014-01-10 23:06:16 +04:00
case gfx : : SurfaceFormat : : B8G8R8A8 :
2014-02-13 18:46:59 +04:00
format = android : : PIXEL_FORMAT_RGBA_8888 ;
2014-04-26 06:34:05 +04:00
mFlags | = TextureFlags : : RB_SWAPPED ;
2013-08-09 19:23:46 +04:00
break ;
2014-01-10 23:06:16 +04:00
case gfx : : SurfaceFormat : : R8G8B8X8 :
2013-08-09 19:23:46 +04:00
format = android : : PIXEL_FORMAT_RGBX_8888 ;
break ;
2014-02-13 18:46:59 +04:00
case gfx : : SurfaceFormat : : B8G8R8X8 :
format = android : : PIXEL_FORMAT_RGBX_8888 ;
2014-04-26 06:34:05 +04:00
mFlags | = TextureFlags : : RB_SWAPPED ;
2014-02-13 18:46:59 +04:00
break ;
2014-01-10 23:06:16 +04:00
case gfx : : SurfaceFormat : : R5G6B5 :
2013-08-09 19:23:46 +04:00
format = android : : PIXEL_FORMAT_RGB_565 ;
break ;
2014-12-16 18:11:48 +03:00
case gfx : : SurfaceFormat : : YUV :
format = HAL_PIXEL_FORMAT_YV12 ;
break ;
2014-02-13 18:46:59 +04:00
case gfx : : SurfaceFormat : : A8 :
NS_WARNING ( " gralloc does not support gfx::SurfaceFormat::A8 " ) ;
return false ;
2013-08-09 19:23:46 +04:00
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 ) {
2014-01-10 23:06:16 +04:00
case gfx : : SurfaceFormat : : R8G8B8A8 :
case gfx : : SurfaceFormat : : B8G8R8A8 :
2014-01-10 17:06:06 +04:00
format = android : : PIXEL_FORMAT_RGBA_8888 ;
break ;
2014-01-10 23:06:16 +04:00
case gfx : : SurfaceFormat : : R8G8B8X8 :
case gfx : : SurfaceFormat : : B8G8R8X8 :
2014-01-10 17:06:06 +04:00
// there is no android BGRX format?
format = android : : PIXEL_FORMAT_RGBX_8888 ;
break ;
2014-01-10 23:06:16 +04:00
case gfx : : SurfaceFormat : : R5G6B5 :
2014-01-10 17:06:06 +04:00
format = android : : PIXEL_FORMAT_RGB_565 ;
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 ;
2014-05-01 05:52:00 +04:00
bool allocateResult =
2013-12-20 20:46:28 +04:00
allocator - > AllocGrallocBuffer ( aSize ,
2013-08-09 19:23:46 +04:00
aAndroidFormat ,
aUsage ,
& handle ) ;
2014-05-01 05:52:00 +04:00
if ( ! allocateResult ) {
2013-08-09 19:23:46 +04:00
return false ;
}
2014-05-01 05:52:00 +04:00
sp < GraphicBuffer > graphicBuffer = GetGraphicBufferFrom ( handle ) ;
2013-08-09 19:23:46 +04:00
if ( ! graphicBuffer . get ( ) ) {
return false ;
}
if ( graphicBuffer - > initCheck ( ) ! = NO_ERROR ) {
return false ;
}
2014-05-01 05:52:00 +04:00
mGrallocHandle = handle ;
2013-08-09 19:23:46 +04:00
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 ;
}
2015-06-17 17:00:52 +03:00
/*static*/ already_AddRefed < TextureClient >
2014-10-09 00:04:19 +04:00
GrallocTextureClientOGL : : FromSharedSurface ( gl : : SharedSurface * abstractSurf ,
TextureFlags flags )
2014-10-08 08:11:54 +04:00
{
auto surf = gl : : SharedSurface_Gralloc : : Cast ( abstractSurf ) ;
RefPtr < TextureClient > ret = surf - > GetTextureClient ( ) ;
2014-11-18 04:02:19 +03:00
TextureFlags mask = TextureFlags : : ORIGIN_BOTTOM_LEFT |
2014-10-08 08:11:54 +04:00
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 ( ) ;
}
2013-08-09 19:23:46 +04:00
} // namesapace layers
} // namesapace mozilla
# endif // MOZ_WIDGET_GONK