2015-10-15 18:53:33 +03: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/. */
# include "BufferTexture.h"
# include "mozilla/layers/ImageDataSerializer.h"
# include "mozilla/layers/ISurfaceAllocator.h"
2016-02-25 16:15:52 +03:00
# include "mozilla/layers/CompositableForwarder.h"
2015-10-15 18:53:33 +03:00
# include "mozilla/gfx/Logging.h"
# include "mozilla/gfx/2D.h"
# include "mozilla/fallible.h"
2016-06-11 04:49:46 +03:00
# include "libyuv.h"
2015-10-15 18:53:33 +03:00
2016-02-25 16:15:52 +03:00
# ifdef MOZ_WIDGET_GTK
# include "gfxPlatformGtk.h"
# endif
2015-10-15 18:53:33 +03:00
namespace mozilla {
namespace layers {
class MemoryTextureData : public BufferTextureData
{
public :
static MemoryTextureData * Create ( gfx : : IntSize aSize , gfx : : SurfaceFormat aFormat ,
2016-08-23 05:30:14 +03:00
gfx : : BackendType aMoz2DBackend ,
LayersBackend aLayersBackend ,
TextureFlags aFlags ,
2015-10-15 18:53:33 +03:00
TextureAllocationFlags aAllocFlags ,
2016-09-27 06:22:20 +03:00
LayersIPCChannel * aAllocator ) ;
2015-10-15 18:53:33 +03:00
virtual TextureData *
2016-09-27 06:22:20 +03:00
CreateSimilar ( LayersIPCChannel * aAllocator ,
LayersBackend aLayersBackend ,
2015-10-15 18:53:33 +03:00
TextureFlags aFlags = TextureFlags : : DEFAULT ,
TextureAllocationFlags aAllocFlags = ALLOC_DEFAULT ) const override ;
virtual bool Serialize ( SurfaceDescriptor & aOutDescriptor ) override ;
2016-09-27 06:22:20 +03:00
virtual void Deallocate ( LayersIPCChannel * ) override ;
2015-10-15 18:53:33 +03:00
2015-12-16 21:50:58 +03:00
MemoryTextureData ( const BufferDescriptor & aDesc ,
2015-10-15 18:53:33 +03:00
gfx : : BackendType aMoz2DBackend ,
uint8_t * aBuffer , size_t aBufferSize )
2015-12-16 21:50:58 +03:00
: BufferTextureData ( aDesc , aMoz2DBackend )
2015-10-15 18:53:33 +03:00
, mBuffer ( aBuffer )
, mBufferSize ( aBufferSize )
{
MOZ_ASSERT ( aBuffer ) ;
MOZ_ASSERT ( aBufferSize ) ;
}
virtual uint8_t * GetBuffer ( ) override { return mBuffer ; }
virtual size_t GetBufferSize ( ) override { return mBufferSize ; }
protected :
uint8_t * mBuffer ;
size_t mBufferSize ;
} ;
class ShmemTextureData : public BufferTextureData
{
public :
static ShmemTextureData * Create ( gfx : : IntSize aSize , gfx : : SurfaceFormat aFormat ,
2016-08-23 05:30:14 +03:00
gfx : : BackendType aMoz2DBackend ,
LayersBackend aLayersBackend ,
TextureFlags aFlags ,
2015-10-15 18:53:33 +03:00
TextureAllocationFlags aAllocFlags ,
2016-09-27 06:22:20 +03:00
LayersIPCChannel * aAllocator ) ;
2015-10-15 18:53:33 +03:00
virtual TextureData *
2016-09-27 06:22:20 +03:00
CreateSimilar ( LayersIPCChannel * aAllocator ,
LayersBackend aLayersBackend ,
2015-10-15 18:53:33 +03:00
TextureFlags aFlags = TextureFlags : : DEFAULT ,
TextureAllocationFlags aAllocFlags = ALLOC_DEFAULT ) const override ;
virtual bool Serialize ( SurfaceDescriptor & aOutDescriptor ) override ;
2016-09-27 06:22:20 +03:00
virtual void Deallocate ( LayersIPCChannel * aAllocator ) override ;
2015-10-15 18:53:33 +03:00
2015-12-16 21:50:58 +03:00
ShmemTextureData ( const BufferDescriptor & aDesc ,
2015-10-15 18:53:33 +03:00
gfx : : BackendType aMoz2DBackend , mozilla : : ipc : : Shmem aShmem )
2015-12-16 21:50:58 +03:00
: BufferTextureData ( aDesc , aMoz2DBackend )
2015-10-15 18:53:33 +03:00
, mShmem ( aShmem )
{
MOZ_ASSERT ( mShmem . Size < uint8_t > ( ) ) ;
}
virtual uint8_t * GetBuffer ( ) override { return mShmem . get < uint8_t > ( ) ; }
virtual size_t GetBufferSize ( ) override { return mShmem . Size < uint8_t > ( ) ; }
protected :
mozilla : : ipc : : Shmem mShmem ;
} ;
2016-02-25 16:15:52 +03:00
static bool UsingX11Compositor ( )
{
# ifdef MOZ_WIDGET_GTK
2016-08-04 21:33:44 +03:00
return gfx : : gfxVars : : UseXRender ( ) ;
2016-02-25 16:15:52 +03:00
# endif
return false ;
}
2016-07-09 04:59:59 +03:00
bool ComputeHasIntermediateBuffer ( gfx : : SurfaceFormat aFormat ,
LayersBackend aLayersBackend )
2016-02-25 16:15:52 +03:00
{
return aLayersBackend ! = LayersBackend : : LAYERS_BASIC
| | UsingX11Compositor ( )
2016-07-09 04:59:59 +03:00
| | aFormat = = gfx : : SurfaceFormat : : UNKNOWN ;
2016-02-25 16:15:52 +03:00
}
2015-10-15 18:53:33 +03:00
BufferTextureData *
BufferTextureData : : Create ( gfx : : IntSize aSize , gfx : : SurfaceFormat aFormat ,
2016-08-23 05:30:14 +03:00
gfx : : BackendType aMoz2DBackend ,
LayersBackend aLayersBackend , TextureFlags aFlags ,
2015-10-15 18:53:33 +03:00
TextureAllocationFlags aAllocFlags ,
2016-09-27 06:22:20 +03:00
LayersIPCChannel * aAllocator )
2015-10-15 18:53:33 +03:00
{
if ( ! aAllocator | | aAllocator - > IsSameProcess ( ) ) {
2016-08-23 05:30:14 +03:00
return MemoryTextureData : : Create ( aSize , aFormat , aMoz2DBackend ,
aLayersBackend , aFlags ,
2016-02-25 16:15:52 +03:00
aAllocFlags , aAllocator ) ;
2016-09-27 06:22:20 +03:00
} else {
2016-08-23 05:30:14 +03:00
return ShmemTextureData : : Create ( aSize , aFormat , aMoz2DBackend ,
aLayersBackend , aFlags ,
2016-02-25 16:15:52 +03:00
aAllocFlags , aAllocator ) ;
2015-10-15 18:53:33 +03:00
}
}
BufferTextureData *
2016-09-27 06:22:20 +03:00
BufferTextureData : : CreateInternal ( LayersIPCChannel * aAllocator ,
2015-12-16 21:50:58 +03:00
const BufferDescriptor & aDesc ,
gfx : : BackendType aMoz2DBackend ,
int32_t aBufferSize ,
TextureFlags aTextureFlags )
2015-10-15 18:53:33 +03:00
{
if ( ! aAllocator | | aAllocator - > IsSameProcess ( ) ) {
2015-12-16 21:50:58 +03:00
uint8_t * buffer = new ( fallible ) uint8_t [ aBufferSize ] ;
2015-10-15 18:53:33 +03:00
if ( ! buffer ) {
return nullptr ;
}
2016-01-06 05:26:29 +03:00
GfxMemoryImageReporter : : DidAlloc ( buffer ) ;
2015-12-16 21:50:58 +03:00
return new MemoryTextureData ( aDesc , aMoz2DBackend , buffer , aBufferSize ) ;
2016-09-27 06:22:20 +03:00
} else {
2015-10-15 18:53:33 +03:00
ipc : : Shmem shm ;
2016-09-27 06:22:20 +03:00
if ( ! aAllocator - > AllocUnsafeShmem ( aBufferSize , OptimalShmemType ( ) , & shm ) ) {
2015-10-15 18:53:33 +03:00
return nullptr ;
}
2015-12-16 21:50:58 +03:00
return new ShmemTextureData ( aDesc , aMoz2DBackend , shm ) ;
}
}
BufferTextureData *
2016-09-27 06:22:20 +03:00
BufferTextureData : : CreateForYCbCrWithBufferSize ( KnowsCompositor * aAllocator ,
2015-12-16 21:50:58 +03:00
int32_t aBufferSize ,
2016-10-12 05:46:28 +03:00
YUVColorSpace aYUVColorSpace ,
2015-12-16 21:50:58 +03:00
TextureFlags aTextureFlags )
{
if ( aBufferSize = = 0 | | ! gfx : : Factory : : CheckBufferSize ( aBufferSize ) ) {
return nullptr ;
2015-10-15 18:53:33 +03:00
}
2016-10-17 14:54:52 +03:00
bool hasIntermediateBuffer = aAllocator ? ComputeHasIntermediateBuffer ( gfx : : SurfaceFormat : : YUV ,
aAllocator - > GetCompositorBackendType ( ) )
: true ;
2016-07-09 04:59:59 +03:00
2015-10-15 18:53:33 +03:00
// Initialize the metadata with something, even if it will have to be rewritten
// afterwards since we don't know the dimensions of the texture at this point.
2015-12-16 21:50:58 +03:00
BufferDescriptor desc = YCbCrDescriptor ( gfx : : IntSize ( ) , gfx : : IntSize ( ) ,
2016-07-09 04:59:59 +03:00
0 , 0 , 0 , StereoMode : : MONO ,
2016-10-12 05:46:28 +03:00
aYUVColorSpace ,
2016-07-09 04:59:59 +03:00
hasIntermediateBuffer ) ;
2015-10-15 18:53:33 +03:00
2016-10-17 14:54:52 +03:00
return CreateInternal ( aAllocator ? aAllocator - > GetTextureForwarder ( ) : nullptr ,
desc , gfx : : BackendType : : NONE , aBufferSize , aTextureFlags ) ;
2015-10-15 18:53:33 +03:00
}
BufferTextureData *
2016-09-27 06:22:20 +03:00
BufferTextureData : : CreateForYCbCr ( KnowsCompositor * aAllocator ,
2015-10-15 18:53:33 +03:00
gfx : : IntSize aYSize ,
gfx : : IntSize aCbCrSize ,
StereoMode aStereoMode ,
2016-10-12 05:46:28 +03:00
YUVColorSpace aYUVColorSpace ,
2015-10-15 18:53:33 +03:00
TextureFlags aTextureFlags )
{
2015-12-16 21:50:58 +03:00
uint32_t bufSize = ImageDataSerializer : : ComputeYCbCrBufferSize ( aYSize , aCbCrSize ) ;
if ( bufSize = = 0 ) {
2015-10-15 18:53:33 +03:00
return nullptr ;
}
2015-12-16 21:50:58 +03:00
uint32_t yOffset ;
uint32_t cbOffset ;
uint32_t crOffset ;
ImageDataSerializer : : ComputeYCbCrOffsets ( aYSize . width , aYSize . height ,
aCbCrSize . width , aCbCrSize . height ,
yOffset , cbOffset , crOffset ) ;
2015-10-15 18:53:33 +03:00
2016-09-27 06:22:20 +03:00
bool hasIntermediateBuffer = aAllocator ? ComputeHasIntermediateBuffer ( gfx : : SurfaceFormat : : YUV ,
aAllocator - > GetCompositorBackendType ( ) )
: true ;
2016-07-09 04:59:59 +03:00
2015-12-16 21:50:58 +03:00
YCbCrDescriptor descriptor = YCbCrDescriptor ( aYSize , aCbCrSize , yOffset , cbOffset ,
2016-10-12 05:46:28 +03:00
crOffset , aStereoMode , aYUVColorSpace ,
2016-07-09 04:59:59 +03:00
hasIntermediateBuffer ) ;
2015-12-16 21:50:58 +03:00
2016-09-27 06:22:20 +03:00
return CreateInternal ( aAllocator ? aAllocator - > GetTextureForwarder ( ) : nullptr , descriptor ,
gfx : : BackendType : : NONE , bufSize , aTextureFlags ) ;
2015-12-16 21:50:58 +03:00
}
2016-04-22 19:05:26 +03:00
void
BufferTextureData : : FillInfo ( TextureData : : Info & aInfo ) const
2015-12-16 21:50:58 +03:00
{
2016-04-22 19:05:26 +03:00
aInfo . size = GetSize ( ) ;
aInfo . format = GetFormat ( ) ;
aInfo . hasSynchronization = false ;
aInfo . canExposeMappedData = true ;
2015-12-16 21:50:58 +03:00
2016-02-25 16:15:52 +03:00
if ( mDescriptor . type ( ) = = BufferDescriptor : : TYCbCrDescriptor ) {
2016-07-09 04:59:59 +03:00
aInfo . hasIntermediateBuffer = mDescriptor . get_YCbCrDescriptor ( ) . hasIntermediateBuffer ( ) ;
2016-04-22 19:05:26 +03:00
} else {
aInfo . hasIntermediateBuffer = mDescriptor . get_RGBDescriptor ( ) . hasIntermediateBuffer ( ) ;
2016-02-25 16:15:52 +03:00
}
2016-04-22 19:05:26 +03:00
switch ( aInfo . format ) {
2015-10-15 18:53:33 +03:00
case gfx : : SurfaceFormat : : YUV :
case gfx : : SurfaceFormat : : UNKNOWN :
2016-04-22 19:05:26 +03:00
aInfo . supportsMoz2D = false ;
break ;
2015-10-15 18:53:33 +03:00
default :
2016-04-22 19:05:26 +03:00
aInfo . supportsMoz2D = true ;
2015-10-15 18:53:33 +03:00
}
}
2016-04-22 19:05:26 +03:00
gfx : : IntSize
BufferTextureData : : GetSize ( ) const
{
return ImageDataSerializer : : SizeFromBufferDescriptor ( mDescriptor ) ;
}
2016-06-30 05:12:31 +03:00
Maybe < gfx : : IntSize >
BufferTextureData : : GetCbCrSize ( ) const
{
return ImageDataSerializer : : CbCrSizeFromBufferDescriptor ( mDescriptor ) ;
}
2016-10-12 05:46:28 +03:00
Maybe < YUVColorSpace >
BufferTextureData : : GetYUVColorSpace ( ) const
{
return ImageDataSerializer : : YUVColorSpaceFromBufferDescriptor ( mDescriptor ) ;
}
2016-06-30 05:12:31 +03:00
Maybe < StereoMode >
BufferTextureData : : GetStereoMode ( ) const
{
return ImageDataSerializer : : StereoModeFromBufferDescriptor ( mDescriptor ) ;
}
2016-04-22 19:05:26 +03:00
gfx : : SurfaceFormat
BufferTextureData : : GetFormat ( ) const
{
return ImageDataSerializer : : FormatFromBufferDescriptor ( mDescriptor ) ;
}
2015-10-15 18:53:33 +03:00
already_AddRefed < gfx : : DrawTarget >
BufferTextureData : : BorrowDrawTarget ( )
{
if ( mDrawTarget ) {
mDrawTarget - > SetTransform ( gfx : : Matrix ( ) ) ;
RefPtr < gfx : : DrawTarget > dt = mDrawTarget ;
return dt . forget ( ) ;
}
2015-12-16 21:50:58 +03:00
if ( mDescriptor . type ( ) ! = BufferDescriptor : : TRGBDescriptor ) {
2015-10-15 18:53:33 +03:00
return nullptr ;
}
2015-12-16 21:50:58 +03:00
const RGBDescriptor & rgb = mDescriptor . get_RGBDescriptor ( ) ;
uint32_t stride = ImageDataSerializer : : GetRGBStride ( rgb ) ;
2016-11-29 23:46:49 +03:00
if ( gfx : : Factory : : DoesBackendSupportDataDrawtarget ( mMoz2DBackend ) ) {
mDrawTarget = gfx : : Factory : : CreateDrawTargetForData ( mMoz2DBackend ,
GetBuffer ( ) , rgb . size ( ) ,
stride , rgb . format ( ) , true ) ;
} else {
// Fall back to supported platform backend. Note that mMoz2DBackend
// does not match the draw target type.
mDrawTarget = gfxPlatform : : CreateDrawTargetForData ( GetBuffer ( ) , rgb . size ( ) ,
stride , rgb . format ( ) ,
true ) ;
}
2015-12-16 21:50:58 +03:00
2015-10-15 18:53:33 +03:00
if ( mDrawTarget ) {
RefPtr < gfx : : DrawTarget > dt = mDrawTarget ;
return dt . forget ( ) ;
}
// TODO - should we warn? should we really fallback to cairo? perhaps
// at least update mMoz2DBackend...
2015-12-16 21:50:58 +03:00
if ( mMoz2DBackend ! = gfx : : BackendType : : CAIRO ) {
2016-11-29 23:46:49 +03:00
gfxCriticalNote < < " Falling to CAIRO from " < < ( int ) mMoz2DBackend ;
2015-12-16 21:50:58 +03:00
mDrawTarget = gfx : : Factory : : CreateDrawTargetForData ( gfx : : BackendType : : CAIRO ,
GetBuffer ( ) , rgb . size ( ) ,
2016-03-18 23:58:55 +03:00
stride , rgb . format ( ) , true ) ;
2015-12-16 21:50:58 +03:00
}
2015-10-15 18:53:33 +03:00
if ( ! mDrawTarget ) {
gfxCriticalNote < < " BorrowDrawTarget failure, original backend " < < ( int ) mMoz2DBackend ;
}
RefPtr < gfx : : DrawTarget > dt = mDrawTarget ;
return dt . forget ( ) ;
}
bool
BufferTextureData : : BorrowMappedData ( MappedTextureData & aData )
{
2015-12-16 21:50:58 +03:00
if ( GetFormat ( ) = = gfx : : SurfaceFormat : : YUV ) {
2015-10-15 18:53:33 +03:00
return false ;
}
2015-12-16 21:50:58 +03:00
gfx : : IntSize size = GetSize ( ) ;
2015-10-15 18:53:33 +03:00
2015-12-16 21:50:58 +03:00
aData . data = GetBuffer ( ) ;
aData . size = size ;
aData . format = GetFormat ( ) ;
aData . stride = ImageDataSerializer : : ComputeRGBStride ( aData . format , size . width ) ;
2015-10-15 18:53:33 +03:00
return true ;
}
bool
BufferTextureData : : BorrowMappedYCbCrData ( MappedYCbCrTextureData & aMap )
{
2015-12-16 21:50:58 +03:00
if ( mDescriptor . type ( ) ! = BufferDescriptor : : TYCbCrDescriptor ) {
2015-10-15 18:53:33 +03:00
return false ;
}
2015-12-16 21:50:58 +03:00
const YCbCrDescriptor & desc = mDescriptor . get_YCbCrDescriptor ( ) ;
uint8_t * data = GetBuffer ( ) ;
auto ySize = desc . ySize ( ) ;
auto cbCrSize = desc . cbCrSize ( ) ;
2015-10-15 18:53:33 +03:00
2015-12-16 21:50:58 +03:00
aMap . stereoMode = desc . stereoMode ( ) ;
aMap . metadata = nullptr ;
2015-10-15 18:53:33 +03:00
2015-12-16 21:50:58 +03:00
aMap . y . data = data + desc . yOffset ( ) ;
aMap . y . size = ySize ;
aMap . y . stride = ySize . width ;
2015-10-15 18:53:33 +03:00
aMap . y . skip = 0 ;
2015-12-16 21:50:58 +03:00
aMap . cb . data = data + desc . cbOffset ( ) ;
aMap . cb . size = cbCrSize ;
aMap . cb . stride = cbCrSize . width ;
2015-10-15 18:53:33 +03:00
aMap . cb . skip = 0 ;
2015-12-16 21:50:58 +03:00
aMap . cr . data = data + desc . crOffset ( ) ;
aMap . cr . size = cbCrSize ;
aMap . cr . stride = cbCrSize . width ;
2015-10-15 18:53:33 +03:00
aMap . cr . skip = 0 ;
return true ;
}
bool
BufferTextureData : : UpdateFromSurface ( gfx : : SourceSurface * aSurface )
{
2015-12-16 21:50:58 +03:00
if ( mDescriptor . type ( ) ! = BufferDescriptor : : TRGBDescriptor ) {
return false ;
}
const RGBDescriptor & rgb = mDescriptor . get_RGBDescriptor ( ) ;
2015-10-15 18:53:33 +03:00
2015-12-16 21:50:58 +03:00
uint32_t stride = ImageDataSerializer : : GetRGBStride ( rgb ) ;
RefPtr < gfx : : DataSourceSurface > surface =
gfx : : Factory : : CreateWrappingDataSourceSurface ( GetBuffer ( ) , stride ,
rgb . size ( ) , rgb . format ( ) ) ;
2015-10-15 18:53:33 +03:00
if ( ! surface ) {
gfxCriticalError ( ) < < " Failed to get serializer as surface! " ;
return false ;
}
RefPtr < gfx : : DataSourceSurface > srcSurf = aSurface - > GetDataSurface ( ) ;
if ( ! srcSurf ) {
2015-12-29 22:03:58 +03:00
gfxCriticalError ( ) < < " Failed to GetDataSurface in UpdateFromSurface (BT). " ;
2015-10-15 18:53:33 +03:00
return false ;
}
if ( surface - > GetSize ( ) ! = srcSurf - > GetSize ( ) | | surface - > GetFormat ( ) ! = srcSurf - > GetFormat ( ) ) {
2015-12-29 22:03:58 +03:00
gfxCriticalError ( ) < < " Attempt to update texture client from a surface with a different size or format (BT)! This: " < < surface - > GetSize ( ) < < " " < < surface - > GetFormat ( ) < < " Other: " < < aSurface - > GetSize ( ) < < " " < < aSurface - > GetFormat ( ) ;
2015-10-15 18:53:33 +03:00
return false ;
}
gfx : : DataSourceSurface : : MappedSurface sourceMap ;
gfx : : DataSourceSurface : : MappedSurface destMap ;
if ( ! srcSurf - > Map ( gfx : : DataSourceSurface : : READ , & sourceMap ) ) {
2015-12-29 22:03:58 +03:00
gfxCriticalError ( ) < < " Failed to map source surface for UpdateFromSurface (BT). " ;
2015-10-15 18:53:33 +03:00
return false ;
}
if ( ! surface - > Map ( gfx : : DataSourceSurface : : WRITE , & destMap ) ) {
srcSurf - > Unmap ( ) ;
gfxCriticalError ( ) < < " Failed to map destination surface for UpdateFromSurface. " ;
return false ;
}
for ( int y = 0 ; y < srcSurf - > GetSize ( ) . height ; y + + ) {
memcpy ( destMap . mData + destMap . mStride * y ,
sourceMap . mData + sourceMap . mStride * y ,
srcSurf - > GetSize ( ) . width * BytesPerPixel ( srcSurf - > GetFormat ( ) ) ) ;
}
srcSurf - > Unmap ( ) ;
surface - > Unmap ( ) ;
return true ;
}
2015-12-16 21:50:58 +03:00
void
BufferTextureData : : SetDesciptor ( const BufferDescriptor & aDescriptor )
{
MOZ_ASSERT ( mDescriptor . type ( ) = = BufferDescriptor : : TYCbCrDescriptor ) ;
MOZ_ASSERT ( mDescriptor . get_YCbCrDescriptor ( ) . ySize ( ) = = gfx : : IntSize ( ) ) ;
mDescriptor = aDescriptor ;
}
2015-10-15 18:53:33 +03:00
bool
MemoryTextureData : : Serialize ( SurfaceDescriptor & aOutDescriptor )
{
MOZ_ASSERT ( GetFormat ( ) ! = gfx : : SurfaceFormat : : UNKNOWN ) ;
if ( GetFormat ( ) = = gfx : : SurfaceFormat : : UNKNOWN ) {
return false ;
}
2015-12-16 21:50:58 +03:00
uintptr_t ptr = reinterpret_cast < uintptr_t > ( mBuffer ) ;
aOutDescriptor = SurfaceDescriptorBuffer ( mDescriptor , MemoryOrShmem ( ptr ) ) ;
2015-10-15 18:53:33 +03:00
return true ;
}
2016-03-12 07:24:21 +03:00
static bool
InitBuffer ( uint8_t * buf , size_t bufSize ,
gfx : : SurfaceFormat aFormat , TextureAllocationFlags aAllocFlags ,
bool aAlreadyZero )
2015-10-15 18:53:33 +03:00
{
if ( ! buf ) {
gfxDebug ( ) < < " BufferTextureData: Failed to allocate " < < bufSize < < " bytes " ;
return false ;
}
2016-02-17 18:34:37 +03:00
if ( ( aAllocFlags & ALLOC_CLEAR_BUFFER ) | |
( aAllocFlags & ALLOC_CLEAR_BUFFER_BLACK ) ) {
2016-03-18 23:58:55 +03:00
if ( aFormat = = gfx : : SurfaceFormat : : B8G8R8X8 ) {
// Even though BGRX was requested, XRGB_UINT32 is what is meant,
// so use 0xFF000000 to put alpha in the right place.
2016-06-11 04:49:46 +03:00
libyuv : : ARGBRect ( buf , bufSize , 0 , 0 , bufSize / sizeof ( uint32_t ) , 1 , 0xFF000000 ) ;
2016-03-12 07:24:21 +03:00
} else if ( ! aAlreadyZero ) {
2016-03-18 23:58:55 +03:00
memset ( buf , 0 , bufSize ) ;
}
2015-10-15 18:53:33 +03:00
}
2016-02-17 18:34:37 +03:00
2015-10-15 18:53:33 +03:00
if ( aAllocFlags & ALLOC_CLEAR_BUFFER_WHITE ) {
memset ( buf , 0xFF , bufSize ) ;
}
return true ;
}
MemoryTextureData *
MemoryTextureData : : Create ( gfx : : IntSize aSize , gfx : : SurfaceFormat aFormat ,
2016-08-23 05:30:14 +03:00
gfx : : BackendType aMoz2DBackend ,
LayersBackend aLayersBackend , TextureFlags aFlags ,
2015-10-15 18:53:33 +03:00
TextureAllocationFlags aAllocFlags ,
2016-09-27 06:22:20 +03:00
LayersIPCChannel * aAllocator )
2015-10-15 18:53:33 +03:00
{
2015-12-16 21:50:58 +03:00
// Should have used CreateForYCbCr.
MOZ_ASSERT ( aFormat ! = gfx : : SurfaceFormat : : YUV ) ;
2015-10-15 18:53:33 +03:00
if ( aSize . width < = 0 | | aSize . height < = 0 ) {
gfxDebug ( ) < < " Asking for buffer of invalid size " < < aSize . width < < " x " < < aSize . height ;
return nullptr ;
}
2015-12-16 21:50:58 +03:00
uint32_t bufSize = ImageDataSerializer : : ComputeRGBBufferSize ( aSize , aFormat ) ;
2015-10-15 18:53:33 +03:00
if ( ! bufSize ) {
return nullptr ;
}
uint8_t * buf = new ( fallible ) uint8_t [ bufSize ] ;
2016-03-12 07:24:21 +03:00
if ( ! InitBuffer ( buf , bufSize , aFormat , aAllocFlags , false ) ) {
2015-12-16 21:50:58 +03:00
return nullptr ;
2015-10-15 18:53:33 +03:00
}
2016-08-23 05:30:14 +03:00
bool hasIntermediateBuffer = ComputeHasIntermediateBuffer ( aFormat , aLayersBackend ) ;
2016-02-25 16:15:52 +03:00
2015-12-16 21:50:58 +03:00
GfxMemoryImageReporter : : DidAlloc ( buf ) ;
2016-02-25 16:15:58 +03:00
BufferDescriptor descriptor = RGBDescriptor ( aSize , aFormat , hasIntermediateBuffer ) ;
2015-12-16 21:50:58 +03:00
return new MemoryTextureData ( descriptor , aMoz2DBackend , buf , bufSize ) ;
2015-10-15 18:53:33 +03:00
}
void
2016-09-27 06:22:20 +03:00
MemoryTextureData : : Deallocate ( LayersIPCChannel * )
2015-10-15 18:53:33 +03:00
{
MOZ_ASSERT ( mBuffer ) ;
GfxMemoryImageReporter : : WillFree ( mBuffer ) ;
delete [ ] mBuffer ;
mBuffer = nullptr ;
}
TextureData *
2016-09-27 06:22:20 +03:00
MemoryTextureData : : CreateSimilar ( LayersIPCChannel * aAllocator ,
LayersBackend aLayersBackend ,
2015-10-15 18:53:33 +03:00
TextureFlags aFlags ,
TextureAllocationFlags aAllocFlags ) const
{
2015-12-16 21:50:58 +03:00
return MemoryTextureData : : Create ( GetSize ( ) , GetFormat ( ) , mMoz2DBackend ,
2016-09-27 06:22:20 +03:00
aLayersBackend , aFlags , aAllocFlags , aAllocator ) ;
2015-10-15 18:53:33 +03:00
}
bool
ShmemTextureData : : Serialize ( SurfaceDescriptor & aOutDescriptor )
{
MOZ_ASSERT ( GetFormat ( ) ! = gfx : : SurfaceFormat : : UNKNOWN ) ;
if ( GetFormat ( ) = = gfx : : SurfaceFormat : : UNKNOWN ) {
return false ;
}
2015-12-16 21:50:58 +03:00
aOutDescriptor = SurfaceDescriptorBuffer ( mDescriptor , MemoryOrShmem ( mShmem ) ) ;
2015-10-15 18:53:33 +03:00
return true ;
}
ShmemTextureData *
ShmemTextureData : : Create ( gfx : : IntSize aSize , gfx : : SurfaceFormat aFormat ,
2016-08-23 05:30:14 +03:00
gfx : : BackendType aMoz2DBackend ,
LayersBackend aLayersBackend , TextureFlags aFlags ,
2015-10-15 18:53:33 +03:00
TextureAllocationFlags aAllocFlags ,
2016-09-27 06:22:20 +03:00
LayersIPCChannel * aAllocator )
2015-10-15 18:53:33 +03:00
{
MOZ_ASSERT ( aAllocator ) ;
2015-12-16 21:50:58 +03:00
// Should have used CreateForYCbCr.
MOZ_ASSERT ( aFormat ! = gfx : : SurfaceFormat : : YUV ) ;
2016-09-27 06:22:20 +03:00
if ( ! aAllocator ) {
2015-10-15 18:53:33 +03:00
return nullptr ;
}
if ( aSize . width < = 0 | | aSize . height < = 0 ) {
gfxDebug ( ) < < " Asking for buffer of invalid size " < < aSize . width < < " x " < < aSize . height ;
return nullptr ;
}
2015-12-16 21:50:58 +03:00
uint32_t bufSize = ImageDataSerializer : : ComputeRGBBufferSize ( aSize , aFormat ) ;
2015-10-15 18:53:33 +03:00
if ( ! bufSize ) {
return nullptr ;
}
mozilla : : ipc : : Shmem shm ;
2016-09-27 06:22:20 +03:00
if ( ! aAllocator - > AllocUnsafeShmem ( bufSize , OptimalShmemType ( ) , & shm ) ) {
2015-10-15 18:53:33 +03:00
return nullptr ;
}
uint8_t * buf = shm . get < uint8_t > ( ) ;
2016-03-12 07:24:21 +03:00
if ( ! InitBuffer ( buf , bufSize , aFormat , aAllocFlags , true ) ) {
2015-12-16 21:50:58 +03:00
return nullptr ;
2015-10-15 18:53:33 +03:00
}
2016-08-23 05:30:14 +03:00
bool hasIntermediateBuffer = ComputeHasIntermediateBuffer ( aFormat , aLayersBackend ) ;
2016-02-25 16:15:52 +03:00
2016-02-25 16:15:58 +03:00
BufferDescriptor descriptor = RGBDescriptor ( aSize , aFormat , hasIntermediateBuffer ) ;
2015-12-16 21:50:58 +03:00
return new ShmemTextureData ( descriptor , aMoz2DBackend , shm ) ;
2015-10-15 18:53:33 +03:00
return nullptr ;
}
TextureData *
2016-09-27 06:22:20 +03:00
ShmemTextureData : : CreateSimilar ( LayersIPCChannel * aAllocator ,
LayersBackend aLayersBackend ,
2015-10-15 18:53:33 +03:00
TextureFlags aFlags ,
TextureAllocationFlags aAllocFlags ) const
{
2015-12-16 21:50:58 +03:00
return ShmemTextureData : : Create ( GetSize ( ) , GetFormat ( ) , mMoz2DBackend ,
2016-09-27 06:22:20 +03:00
aLayersBackend , aFlags , aAllocFlags , aAllocator ) ;
2015-10-15 18:53:33 +03:00
}
void
2016-09-27 06:22:20 +03:00
ShmemTextureData : : Deallocate ( LayersIPCChannel * aAllocator )
2015-10-15 18:53:33 +03:00
{
2016-09-27 06:22:20 +03:00
aAllocator - > DeallocShmem ( mShmem ) ;
2015-10-15 18:53:33 +03:00
}
} // namespace
} // namespace