Bug 763234 - Use only one compositor thread with OMTC. r=cjones

This commit is contained in:
Nicolas Silva 2012-07-13 11:25:29 -04:00
parent 03bce61cad
commit 049d5a6366
8 changed files with 179 additions and 111 deletions

View File

@ -23,8 +23,49 @@ using base::Thread;
namespace mozilla {
namespace layers {
CompositorParent::CompositorParent(nsIWidget* aWidget, MessageLoop* aMsgLoop,
PlatformThreadId aThreadID, bool aRenderToEGLSurface,
static Thread* sCompositorThread = nsnull;
void CompositorParent::StartUp()
{
CreateThread();
}
void CompositorParent::ShutDown()
{
DestroyThread();
}
bool CompositorParent::CreateThread()
{
NS_ASSERTION(NS_IsMainThread(), "Should be on the main Thread!");
if (sCompositorThread) {
return true;
}
sCompositorThread = new Thread("Compositor");
if (!sCompositorThread->Start()) {
delete sCompositorThread;
sCompositorThread = nsnull;
return false;
}
return true;
}
void CompositorParent::DestroyThread()
{
NS_ASSERTION(NS_IsMainThread(), "Should be on the main Thread!");
if (sCompositorThread) {
delete sCompositorThread;
sCompositorThread = nsnull;
}
}
MessageLoop* CompositorParent::CompositorLoop()
{
return sCompositorThread ? sCompositorThread->message_loop() : nsnull;
}
CompositorParent::CompositorParent(nsIWidget* aWidget,
bool aRenderToEGLSurface,
int aSurfaceWidth, int aSurfaceHeight)
: mWidget(aWidget)
, mCurrentCompositeTask(NULL)
@ -33,26 +74,20 @@ CompositorParent::CompositorParent(nsIWidget* aWidget, MessageLoop* aMsgLoop,
, mYScale(1.0)
, mIsFirstPaint(false)
, mLayersUpdated(false)
, mCompositorLoop(aMsgLoop)
, mThreadID(aThreadID)
, mRenderToEGLSurface(aRenderToEGLSurface)
, mEGLSurfaceSize(aSurfaceWidth, aSurfaceHeight)
, mPauseCompositionMonitor("PauseCompositionMonitor")
, mResumeCompositionMonitor("ResumeCompositionMonitor")
{
NS_ABORT_IF_FALSE(sCompositorThread != nsnull,
"The compositor thread must be Initialized before instanciating a COmpositorParent.");
MOZ_COUNT_CTOR(CompositorParent);
}
MessageLoop*
CompositorParent::CompositorLoop()
{
return mCompositorLoop;
}
PlatformThreadId
CompositorParent::CompositorThreadID()
{
return mThreadID;
return sCompositorThread->thread_id();
}
CompositorParent::~CompositorParent()

View File

@ -23,6 +23,10 @@
class nsIWidget;
namespace base {
class Thread;
}
namespace mozilla {
namespace layers {
@ -53,8 +57,8 @@ class CompositorParent : public PCompositorParent,
{
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CompositorParent)
public:
CompositorParent(nsIWidget* aWidget, MessageLoop* aMsgLoop,
PlatformThreadId aThreadID, bool aRenderToEGLSurface = false,
CompositorParent(nsIWidget* aWidget,
bool aRenderToEGLSurface = false,
int aSurfaceWidth = -1, int aSurfaceHeight = -1);
virtual ~CompositorParent();
@ -77,6 +81,23 @@ public:
void SchedulePauseOnCompositorThread();
void ScheduleResumeOnCompositorThread(int width, int height);
/**
* Returns the compositor thread's message loop.
*
* This message loop is used by CompositorParent and ImageBridgeParent.
*/
static MessageLoop* CompositorLoop();
/**
* Creates the compositor thread and the global compositor map.
*/
static void StartUp();
/**
* Destroys the compositor thread and the global compositor map.
*/
static void ShutDown();
protected:
virtual PLayersParent* AllocPLayers(const LayersBackend& aBackendType, int* aMaxTextureSize);
virtual bool DeallocPLayers(PLayersParent* aLayers);
@ -96,9 +117,28 @@ private:
void TransformShadowTree();
inline MessageLoop* CompositorLoop();
inline PlatformThreadId CompositorThreadID();
/**
* Creates the compositor thread.
*
* All compositors live on the same thread.
* The thread is not lazily created on first access to avoid dealing with
* thread safety. Therefore it's best to create and destroy the thread when
* we know we areb't using it (So creating/destroying along with gfxPlatform
* looks like a good place).
*/
static bool CreateThread();
/**
* Destroys the compositor thread.
*
* It is safe to call this fucntion more than once, although the second call
* will have no effect.
* This function is not thread-safe.
*/
static void DestroyThread();
// Platform specific functions
/**
* Does a breadth-first search to find the first layer in the tree with a
@ -143,8 +183,6 @@ private:
// after a layers update has it set. It is cleared after that first composition.
bool mLayersUpdated;
MessageLoop* mCompositorLoop;
PlatformThreadId mThreadID;
bool mRenderToEGLSurface;
nsIntSize mEGLSurfaceSize;

View File

@ -6,10 +6,16 @@
#ifdef MOZ_LOGGING
#define FORCE_PR_LOG /* Allow logging in the release build */
#endif
#include "mozilla/layers/CompositorParent.h"
#include "prlog.h"
#include "prenv.h"
#include "gfxPlatform.h"
#include "nsXULAppAPI.h"
#if defined(XP_WIN)
#include "gfxWindowsPlatform.h"
#include "gfxD2DSurface.h"
@ -60,6 +66,7 @@
#include "nsIGfxInfo.h"
using namespace mozilla;
using namespace mozilla::layers;
gfxPlatform *gPlatform = nsnull;
static bool gEverInitialized = false;
@ -243,6 +250,30 @@ gfxPlatform::Init()
sCmapDataLog = PR_NewLogModule("cmapdata");;
#endif
bool useOffMainThreadCompositing = false;
#ifdef MOZ_X11
// On X11 platforms only use OMTC if firefox was initalized with thread-safe
// X11 (else it would crash).
useOffMainThreadCompositing = (PR_GetEnv("MOZ_USE_OMTC") != NULL);
#else
useOffMainThreadCompositing = Preferences::GetBool(
"layers.offmainthreadcomposition.enabled",
false);
// Until https://bugzilla.mozilla.org/show_bug.cgi?id=745148 lands,
// we use either omtc or content processes, but not both. Prefer
// OOP content to omtc. (Currently, this only affects b2g.)
//
// See https://bugzilla.mozilla.org/show_bug.cgi?id=761962 .
if (!Preferences::GetBool("dom.ipc.tabs.disabled", true)) {
// Disable omtc if OOP content isn't force-disabled.
useOffMainThreadCompositing = false;
}
#endif
if (useOffMainThreadCompositing && (XRE_GetProcessType() ==
GeckoProcessType_Default)) {
CompositorParent::StartUp();
}
/* Initialize the GfxInfo service.
* Note: we can't call functions on GfxInfo that depend
@ -360,6 +391,8 @@ gfxPlatform::Shutdown()
mozilla::gl::GLContextProviderEGL::Shutdown();
#endif
CompositorParent::ShutDown();
delete gPlatform;
gPlatform = nsnull;
}

View File

@ -171,7 +171,7 @@ nsWindow::~nsWindow()
top->mFocus = nsnull;
ALOG("nsWindow %p destructor", (void*)this);
#ifdef MOZ_JAVA_COMPOSITOR
SetCompositor(NULL, NULL, NULL);
SetCompositor(NULL, NULL);
#endif
}
@ -697,7 +697,7 @@ nsWindow::GetLayerManager(PLayersChild*, LayersBackend, LayerManagerPersistence,
if (useCompositor) {
CreateCompositor();
if (mLayerManager) {
SetCompositor(mCompositorParent, mCompositorChild, mCompositorThread);
SetCompositor(mCompositorParent, mCompositorChild);
return mLayerManager;
}
@ -2279,17 +2279,14 @@ nsWindow::DrawWindowOverlay(LayerManager* aManager, nsIntRect aRect)
nsRefPtr<mozilla::layers::CompositorParent> nsWindow::sCompositorParent = 0;
nsRefPtr<mozilla::layers::CompositorChild> nsWindow::sCompositorChild = 0;
base::Thread * nsWindow::sCompositorThread = 0;
bool nsWindow::sCompositorPaused = false;
void
nsWindow::SetCompositor(mozilla::layers::CompositorParent* aCompositorParent,
mozilla::layers::CompositorChild* aCompositorChild,
::base::Thread* aCompositorThread)
mozilla::layers::CompositorChild* aCompositorChild)
{
sCompositorParent = aCompositorParent;
sCompositorChild = aCompositorChild;
sCompositorThread = aCompositorThread;
}
void

View File

@ -152,8 +152,7 @@ public:
virtual void DrawWindowOverlay(LayerManager* aManager, nsIntRect aRect);
static void SetCompositor(mozilla::layers::CompositorParent* aCompositorParent,
mozilla::layers::CompositorChild* aCompositorChild,
::base::Thread* aCompositorThread);
mozilla::layers::CompositorChild* aCompositorChild);
static void ScheduleComposite();
static void SchedulePauseComposition();
static void ScheduleResumeComposition(int width, int height);
@ -219,7 +218,6 @@ private:
static nsRefPtr<mozilla::layers::CompositorParent> sCompositorParent;
static nsRefPtr<mozilla::layers::CompositorChild> sCompositorChild;
static bool sCompositorPaused;
static base::Thread *sCompositorThread;
#endif
};

View File

@ -133,13 +133,6 @@ nsWindow::nsWindow()
NS_RUNTIMEABORT("Failed to create framebufferWatcherThread, aborting...");
}
sUsingOMTC = UseOffMainThreadCompositing();
if (sUsingOMTC) {
sOMTCSurface = new gfxImageSurface(gfxIntSize(1, 1),
gfxASurface::ImageFormatRGB24);
}
// We (apparently) don't have a way to tell if allocating the
// fbs succeeded or failed.
gNativeWindow = new android::FramebufferNativeWindow();
@ -172,6 +165,20 @@ nsWindow::nsWindow()
sScreenInitialized = true;
nsAppShell::NotifyScreenInitialized();
// This is a hack to force initialization of the compositor
// resources, if we're going to use omtc.
//
// NB: GetPlatform() will create the gfxPlatform, which wants
// to know the color depth, which asks our native window.
// This has to happen after other init has finished.
gfxPlatform::GetPlatform();
sUsingOMTC = UseOffMainThreadCompositing();
if (sUsingOMTC) {
sOMTCSurface = new gfxImageSurface(gfxIntSize(1, 1),
gfxASurface::ImageFormatRGB24);
}
}
}

View File

@ -40,9 +40,6 @@ static bool debug_InSecureKeyboardInputMode = false;
static PRInt32 gNumWidgets;
#endif
static void InitOnlyOnce();
static bool sUseOffMainThreadCompositing = false;
using namespace mozilla::layers;
using namespace mozilla;
using base::Thread;
@ -84,7 +81,6 @@ nsBaseWidget::nsBaseWidget()
, mEventCallback(nsnull)
, mViewCallback(nsnull)
, mContext(nsnull)
, mCompositorThread(nsnull)
, mCursor(eCursor_standard)
, mWindowType(eWindowType_child)
, mBorderStyle(eBorderStyle_none)
@ -108,16 +104,13 @@ nsBaseWidget::nsBaseWidget()
#ifdef DEBUG
debug_RegisterPrefCallbacks();
#endif
InitOnlyOnce();
}
static void DeferredDestroyCompositor(CompositorParent* aCompositorParent,
CompositorChild* aCompositorChild,
Thread* aCompositorThread)
CompositorChild* aCompositorChild)
{
aCompositorChild->Destroy();
delete aCompositorThread;
aCompositorParent->Release();
aCompositorChild->Release();
}
@ -136,7 +129,7 @@ void nsBaseWidget::DestroyCompositor()
// handle compositor desctruction.
MessageLoop::current()->PostTask(FROM_HERE,
NewRunnableFunction(DeferredDestroyCompositor, mCompositorParent,
mCompositorChild, mCompositorThread));
mCompositorChild));
// The DestroyCompositor task we just added to the MessageLoop will handle
// releasing mCompositorParent and mCompositorChild.
mCompositorParent.forget();
@ -869,52 +862,48 @@ nsBaseWidget::GetShouldAccelerate()
void nsBaseWidget::CreateCompositor()
{
mCompositorThread = new Thread("CompositorThread");
if (mCompositorThread->Start()) {
bool renderToEGLSurface = false;
bool renderToEGLSurface = false;
#ifdef MOZ_JAVA_COMPOSITOR
renderToEGLSurface = true;
renderToEGLSurface = true;
#endif
nsIntRect rect;
GetBounds(rect);
mCompositorParent =
new CompositorParent(this, mCompositorThread->message_loop(), mCompositorThread->thread_id(),
renderToEGLSurface, rect.width, rect.height);
LayerManager* lm = CreateBasicLayerManager();
MessageLoop *childMessageLoop = mCompositorThread->message_loop();
mCompositorChild = new CompositorChild(lm);
AsyncChannel *parentChannel = mCompositorParent->GetIPCChannel();
AsyncChannel::Side childSide = mozilla::ipc::AsyncChannel::Child;
mCompositorChild->Open(parentChannel, childMessageLoop, childSide);
PRInt32 maxTextureSize;
PLayersChild* shadowManager;
if (mUseAcceleratedRendering) {
shadowManager = mCompositorChild->SendPLayersConstructor(LayerManager::LAYERS_OPENGL, &maxTextureSize);
} else {
shadowManager = mCompositorChild->SendPLayersConstructor(LayerManager::LAYERS_BASIC, &maxTextureSize);
}
nsIntRect rect;
GetBounds(rect);
mCompositorParent =
new CompositorParent(this, renderToEGLSurface, rect.width, rect.height);
LayerManager* lm = CreateBasicLayerManager();
MessageLoop *childMessageLoop = CompositorParent::CompositorLoop();
mCompositorChild = new CompositorChild(lm);
AsyncChannel *parentChannel = mCompositorParent->GetIPCChannel();
AsyncChannel::Side childSide = mozilla::ipc::AsyncChannel::Child;
mCompositorChild->Open(parentChannel, childMessageLoop, childSide);
PRInt32 maxTextureSize;
PLayersChild* shadowManager;
if (mUseAcceleratedRendering) {
shadowManager = mCompositorChild->SendPLayersConstructor(LayerManager::LAYERS_OPENGL, &maxTextureSize);
} else {
shadowManager = mCompositorChild->SendPLayersConstructor(LayerManager::LAYERS_BASIC, &maxTextureSize);
}
if (shadowManager) {
ShadowLayerForwarder* lf = lm->AsShadowForwarder();
if (!lf) {
delete lm;
mCompositorChild = nsnull;
return;
}
lf->SetShadowManager(shadowManager);
if (mUseAcceleratedRendering)
lf->SetParentBackendType(LayerManager::LAYERS_OPENGL);
else
lf->SetParentBackendType(LayerManager::LAYERS_BASIC);
lf->SetMaxTextureSize(maxTextureSize);
mLayerManager = lm;
} else {
// We don't currently want to support not having a LayersChild
NS_RUNTIMEABORT("failed to construct LayersChild");
if (shadowManager) {
ShadowLayerForwarder* lf = lm->AsShadowForwarder();
if (!lf) {
delete lm;
mCompositorChild = nsnull;
return;
}
lf->SetShadowManager(shadowManager);
if (mUseAcceleratedRendering)
lf->SetParentBackendType(LayerManager::LAYERS_OPENGL);
else
lf->SetParentBackendType(LayerManager::LAYERS_BASIC);
lf->SetMaxTextureSize(maxTextureSize);
mLayerManager = lm;
} else {
// We don't currently want to support not having a LayersChild
NS_RUNTIMEABORT("failed to construct LayersChild");
delete lm;
mCompositorChild = nsnull;
}
}
@ -922,7 +911,7 @@ bool nsBaseWidget::UseOffMainThreadCompositing()
{
bool isSmallPopup = ((mWindowType == eWindowType_popup) &&
(mPopupType != ePopupTypePanel));
return sUseOffMainThreadCompositing && !isSmallPopup;
return CompositorParent::CompositorLoop() && !isSmallPopup;
}
LayerManager* nsBaseWidget::GetLayerManager(PLayersChild* aShadowManager,
@ -1336,34 +1325,6 @@ nsBaseWidget::GetGLFrameBufferFormat()
return LOCAL_GL_NONE;
}
static void InitOnlyOnce()
{
static bool once = true;
if (!once) {
return;
}
once = false;
#ifdef MOZ_X11
// On X11 platforms only use OMTC if firefox was initalized with thread-safe
// X11 (else it would crash).
sUseOffMainThreadCompositing = (PR_GetEnv("MOZ_USE_OMTC") != NULL);
#else
sUseOffMainThreadCompositing = Preferences::GetBool(
"layers.offmainthreadcomposition.enabled",
false);
// Until https://bugzilla.mozilla.org/show_bug.cgi?id=745148 lands,
// we use either omtc or content processes, but not both. Prefer
// OOP content to omtc. (Currently, this only affects b2g.)
//
// See https://bugzilla.mozilla.org/show_bug.cgi?id=761962 .
if (!Preferences::GetBool("dom.ipc.tabs.disabled", true)) {
// Disable omtc if OOP content isn't force-disabled.
sUseOffMainThreadCompositing = false;
}
#endif
}
#ifdef DEBUG
//////////////////////////////////////////////////////////////
//

View File

@ -296,7 +296,6 @@ protected:
nsRefPtr<LayerManager> mBasicLayerManager;
nsRefPtr<CompositorChild> mCompositorChild;
nsRefPtr<CompositorParent> mCompositorParent;
Thread* mCompositorThread;
nscolor mBackground;
nscolor mForeground;
nsCursor mCursor;