2014-05-01 01:50:00 +00:00
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* vim : sw = 2 ts = 8 et :
*/
/* 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 "base/task.h" // for NewRunnableFunction, etc
# include "base/thread.h" // for Thread
# include "base/tracked.h" // for FROM_HERE
# include "mozilla/layers/SharedBufferManagerChild.h"
# include "mozilla/layers/SharedBufferManagerParent.h"
# include "mozilla/StaticPtr.h" // for StaticRefPtr
# include "mozilla/ReentrantMonitor.h" // for ReentrantMonitor, etc
# include "nsThreadUtils.h" // fo NS_IsMainThread
# ifdef MOZ_NUWA_PROCESS
# include "ipc/Nuwa.h"
# endif
# ifdef MOZ_WIDGET_GONK
# define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "SBMChild", ## args)
# endif
using namespace mozilla : : gfx ;
namespace mozilla {
namespace layers {
// Singleton
SharedBufferManagerChild * SharedBufferManagerChild : : sSharedBufferManagerChildSingleton = nullptr ;
SharedBufferManagerParent * SharedBufferManagerChild : : sSharedBufferManagerParentSingleton = nullptr ;
base : : Thread * SharedBufferManagerChild : : sSharedBufferManagerChildThread = nullptr ;
SharedBufferManagerChild : : SharedBufferManagerChild ( )
# ifdef MOZ_HAVE_SURFACEDESCRIPTORGRALLOC
: mBufferMutex ( " BufferMonitor " )
# endif
{
}
static bool
InSharedBufferManagerChildThread ( )
{
return SharedBufferManagerChild : : sSharedBufferManagerChildThread - > thread_id ( ) = = PlatformThread : : CurrentId ( ) ;
}
// dispatched function
static void
DeleteSharedBufferManagerSync ( ReentrantMonitor * aBarrier , bool * aDone )
{
ReentrantMonitorAutoEnter autoMon ( * aBarrier ) ;
NS_ABORT_IF_FALSE ( InSharedBufferManagerChildThread ( ) ,
" Should be in SharedBufferManagerChild thread. " ) ;
SharedBufferManagerChild : : sSharedBufferManagerChildSingleton = nullptr ;
SharedBufferManagerChild : : sSharedBufferManagerParentSingleton = nullptr ;
* aDone = true ;
aBarrier - > NotifyAll ( ) ;
}
// dispatched function
static void
ConnectSharedBufferManager ( SharedBufferManagerChild * child , SharedBufferManagerParent * parent )
{
MessageLoop * parentMsgLoop = parent - > GetMessageLoop ( ) ;
ipc : : MessageChannel * parentChannel = parent - > GetIPCChannel ( ) ;
child - > Open ( parentChannel , parentMsgLoop , mozilla : : ipc : : ChildSide ) ;
}
base : : Thread *
SharedBufferManagerChild : : GetThread ( ) const
{
return sSharedBufferManagerChildThread ;
}
SharedBufferManagerChild *
SharedBufferManagerChild : : GetSingleton ( )
{
return sSharedBufferManagerChildSingleton ;
}
bool
SharedBufferManagerChild : : IsCreated ( )
{
return GetSingleton ( ) ! = nullptr ;
}
void
SharedBufferManagerChild : : StartUp ( )
{
NS_ASSERTION ( NS_IsMainThread ( ) , " Should be on the main Thread! " ) ;
SharedBufferManagerChild : : StartUpOnThread ( new base : : Thread ( " BufferMgrChild " ) ) ;
}
static void
ConnectSharedBufferManagerInChildProcess ( mozilla : : ipc : : Transport * aTransport ,
base : : ProcessHandle aOtherProcess )
{
// Bind the IPC channel to the shared buffer manager thread.
SharedBufferManagerChild : : sSharedBufferManagerChildSingleton - > Open ( aTransport , aOtherProcess ,
XRE_GetIOMessageLoop ( ) ,
ipc : : ChildSide ) ;
# ifdef MOZ_NUWA_PROCESS
if ( IsNuwaProcess ( ) ) {
SharedBufferManagerChild : : sSharedBufferManagerChildThread
- > message_loop ( ) - > PostTask ( FROM_HERE ,
NewRunnableFunction ( NuwaMarkCurrentThread ,
( void ( * ) ( void * ) ) nullptr ,
( void * ) nullptr ) ) ;
}
# endif
}
PSharedBufferManagerChild *
SharedBufferManagerChild : : StartUpInChildProcess ( Transport * aTransport ,
base : : ProcessId aOtherProcess )
{
NS_ASSERTION ( NS_IsMainThread ( ) , " Should be on the main Thread! " ) ;
ProcessHandle processHandle ;
if ( ! base : : OpenProcessHandle ( aOtherProcess , & processHandle ) ) {
return nullptr ;
}
sSharedBufferManagerChildThread = new base : : Thread ( " BufferMgrChild " ) ;
if ( ! sSharedBufferManagerChildThread - > Start ( ) ) {
return nullptr ;
}
sSharedBufferManagerChildSingleton = new SharedBufferManagerChild ( ) ;
sSharedBufferManagerChildSingleton - > GetMessageLoop ( ) - > PostTask (
FROM_HERE ,
NewRunnableFunction ( ConnectSharedBufferManagerInChildProcess ,
aTransport , processHandle ) ) ;
return sSharedBufferManagerChildSingleton ;
}
void
SharedBufferManagerChild : : ShutDown ( )
{
NS_ASSERTION ( NS_IsMainThread ( ) , " Should be on the main Thread! " ) ;
if ( IsCreated ( ) ) {
SharedBufferManagerChild : : DestroyManager ( ) ;
delete sSharedBufferManagerChildThread ;
sSharedBufferManagerChildThread = nullptr ;
}
}
bool
SharedBufferManagerChild : : StartUpOnThread ( base : : Thread * aThread )
{
NS_ABORT_IF_FALSE ( aThread , " SharedBufferManager needs a thread. " ) ;
if ( sSharedBufferManagerChildSingleton ! = nullptr )
return false ;
sSharedBufferManagerChildThread = aThread ;
if ( ! aThread - > IsRunning ( ) ) {
aThread - > Start ( ) ;
}
sSharedBufferManagerChildSingleton = new SharedBufferManagerChild ( ) ;
char thrname [ 128 ] ;
base : : snprintf ( thrname , 128 , " BufMgrParent#%d " , base : : Process : : Current ( ) . pid ( ) ) ;
sSharedBufferManagerParentSingleton = new SharedBufferManagerParent (
nullptr , base : : Process : : Current ( ) . pid ( ) , new base : : Thread ( thrname ) ) ;
sSharedBufferManagerChildSingleton - > ConnectAsync ( sSharedBufferManagerParentSingleton ) ;
return true ;
}
void
SharedBufferManagerChild : : DestroyManager ( )
{
NS_ABORT_IF_FALSE ( ! InSharedBufferManagerChildThread ( ) ,
" This method must not be called in this thread. " ) ;
// ...because we are about to dispatch synchronous messages to the
// BufferManagerChild thread.
if ( ! IsCreated ( ) ) {
return ;
}
ReentrantMonitor barrier ( " BufferManagerDestroyTask lock " ) ;
ReentrantMonitorAutoEnter autoMon ( barrier ) ;
bool done = false ;
sSharedBufferManagerChildSingleton - > GetMessageLoop ( ) - > PostTask ( FROM_HERE ,
NewRunnableFunction ( & DeleteSharedBufferManagerSync , & barrier , & done ) ) ;
while ( ! done ) {
barrier . Wait ( ) ;
}
}
MessageLoop *
SharedBufferManagerChild : : GetMessageLoop ( ) const
{
return sSharedBufferManagerChildThread ! = nullptr ?
sSharedBufferManagerChildThread - > message_loop ( ) :
nullptr ;
}
void
SharedBufferManagerChild : : ConnectAsync ( SharedBufferManagerParent * aParent )
{
GetMessageLoop ( ) - > PostTask ( FROM_HERE , NewRunnableFunction ( & ConnectSharedBufferManager ,
this , aParent ) ) ;
}
// dispatched function
void
SharedBufferManagerChild : : AllocGrallocBufferSync ( const GrallocParam & aParam ,
Monitor * aBarrier ,
bool * aDone )
{
MonitorAutoLock autoMon ( * aBarrier ) ;
sSharedBufferManagerChildSingleton - > AllocGrallocBufferNow ( aParam . size ,
aParam . format ,
aParam . usage ,
aParam . buffer ) ;
* aDone = true ;
aBarrier - > NotifyAll ( ) ;
}
// dispatched function
void
SharedBufferManagerChild : : DeallocGrallocBufferSync ( const mozilla : : layers : : MaybeMagicGrallocBufferHandle & aBuffer )
{
SharedBufferManagerChild : : sSharedBufferManagerChildSingleton - >
DeallocGrallocBufferNow ( aBuffer ) ;
}
bool
SharedBufferManagerChild : : AllocGrallocBuffer ( const gfx : : IntSize & aSize ,
const uint32_t & aFormat ,
const uint32_t & aUsage ,
mozilla : : layers : : MaybeMagicGrallocBufferHandle * aBuffer )
{
if ( InSharedBufferManagerChildThread ( ) ) {
return SharedBufferManagerChild : : AllocGrallocBufferNow ( aSize , aFormat , aUsage , aBuffer ) ;
}
Monitor barrier ( " AllocSurfaceDescriptorGralloc Lock " ) ;
MonitorAutoLock autoMon ( barrier ) ;
bool done = false ;
GetMessageLoop ( ) - > PostTask (
FROM_HERE ,
NewRunnableFunction ( & AllocGrallocBufferSync ,
GrallocParam ( aSize , aFormat , aUsage , aBuffer ) , & barrier , & done ) ) ;
while ( ! done ) {
barrier . Wait ( ) ;
}
return true ;
}
bool
SharedBufferManagerChild : : AllocGrallocBufferNow ( const IntSize & aSize ,
const uint32_t & aFormat ,
const uint32_t & aUsage ,
mozilla : : layers : : MaybeMagicGrallocBufferHandle * aHandle )
{
# ifdef MOZ_HAVE_SURFACEDESCRIPTORGRALLOC
mozilla : : layers : : MaybeMagicGrallocBufferHandle handle ;
SendAllocateGrallocBuffer ( aSize , aFormat , aUsage , & handle ) ;
if ( handle . type ( ) ! = mozilla : : layers : : MaybeMagicGrallocBufferHandle : : TMagicGrallocBufferHandle )
return false ;
* aHandle = handle . get_MagicGrallocBufferHandle ( ) . mRef ;
{
MutexAutoLock lock ( mBufferMutex ) ;
mBuffers [ handle . get_MagicGrallocBufferHandle ( ) . mRef . mKey ] = handle . get_MagicGrallocBufferHandle ( ) . mGraphicBuffer ;
}
return true ;
# else
NS_RUNTIMEABORT ( " No GrallocBuffer for you " ) ;
return true ;
# endif
}
void
SharedBufferManagerChild : : DeallocGrallocBuffer ( const mozilla : : layers : : MaybeMagicGrallocBufferHandle & aBuffer )
{
if ( InSharedBufferManagerChildThread ( ) ) {
return SharedBufferManagerChild : : DeallocGrallocBufferNow ( aBuffer ) ;
}
GetMessageLoop ( ) - > PostTask ( FROM_HERE , NewRunnableFunction ( & DeallocGrallocBufferSync ,
aBuffer ) ) ;
}
void
SharedBufferManagerChild : : DeallocGrallocBufferNow ( const mozilla : : layers : : MaybeMagicGrallocBufferHandle & aBuffer )
{
# ifdef MOZ_HAVE_SURFACEDESCRIPTORGRALLOC
2014-05-01 01:52:00 +00:00
NS_ASSERTION ( aBuffer . type ( ) ! = mozilla : : layers : : MaybeMagicGrallocBufferHandle : : TMagicGrallocBufferHandle , " We shouldn't trying to do IPC with real buffer " ) ;
2014-05-01 01:50:00 +00:00
{
MutexAutoLock lock ( mBufferMutex ) ;
mBuffers . erase ( aBuffer . get_GrallocBufferRef ( ) . mKey ) ;
}
SendDropGrallocBuffer ( aBuffer ) ;
# else
NS_RUNTIMEABORT ( " No GrallocBuffer for you " ) ;
# endif
}
bool SharedBufferManagerChild : : RecvDropGrallocBuffer ( const mozilla : : layers : : MaybeMagicGrallocBufferHandle & handle )
{
# ifdef MOZ_HAVE_SURFACEDESCRIPTORGRALLOC
NS_ASSERTION ( handle . type ( ) = = mozilla : : layers : : MaybeMagicGrallocBufferHandle : : TGrallocBufferRef , " shouldn't go this way " ) ;
int bufferKey = handle . get_GrallocBufferRef ( ) . mKey ;
{
MutexAutoLock lock ( mBufferMutex ) ;
NS_ASSERTION ( mBuffers . count ( bufferKey ) ! = 0 , " Not my buffer " ) ;
mBuffers . erase ( bufferKey ) ;
}
# endif
return true ;
}
# ifdef MOZ_HAVE_SURFACEDESCRIPTORGRALLOC
android : : sp < android : : GraphicBuffer >
SharedBufferManagerChild : : GetGraphicBuffer ( int key )
{
MutexAutoLock lock ( mBufferMutex ) ;
if ( mBuffers . count ( key ) = = 0 )
return nullptr ;
return mBuffers [ key ] ;
}
# endif
} /* namespace layers */
} /* namespace mozilla */