Add skeletal code for launching a GPU process. (bug 1271180 part 4, r=billm,jrmuizel)

--HG--
extra : rebase_source : 332f5cf6ca5e1f78fb2283a7e79b6b21654e9e59
This commit is contained in:
David Anderson 2016-06-10 22:27:24 -04:00
parent 39defbc2f7
commit d2678d4141
17 changed files with 658 additions and 2 deletions

View File

@ -22,6 +22,7 @@ namespace gfx {
_(D3D9_COMPOSITING, Feature, "Direct3D9 Compositing") \
_(DIRECT2D, Feature, "Direct2D") \
_(D3D11_HW_ANGLE, Feature, "Direct3D11 hardware ANGLE") \
_(GPU_PROCESS, Feature, "GPU Process") \
/* Add new entries above this comment */
enum class Feature : uint32_t {

22
gfx/ipc/GPUChild.cpp Normal file
View File

@ -0,0 +1,22 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=99: */
/* 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 "GPUChild.h"
namespace mozilla {
namespace gfx {
GPUChild::GPUChild()
{
MOZ_COUNT_CTOR(GPUChild);
}
GPUChild::~GPUChild()
{
MOZ_COUNT_DTOR(GPUChild);
}
} // namespace gfx
} // namespace mozilla

24
gfx/ipc/GPUChild.h Normal file
View File

@ -0,0 +1,24 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=99: */
/* 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/. */
#ifndef _include_mozilla_gfx_ipc_GPUChild_h_
#define _include_mozilla_gfx_ipc_GPUChild_h_
#include "mozilla/gfx/PGPUChild.h"
namespace mozilla {
namespace gfx {
class GPUChild final : public PGPUChild
{
public:
GPUChild();
~GPUChild();
};
} // namespace gfx
} // namespace mozilla
#endif // _include_mozilla_gfx_ipc_GPUChild_h_

55
gfx/ipc/GPUParent.cpp Normal file
View File

@ -0,0 +1,55 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=99: */
/* 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 "GPUParent.h"
#include "gfxConfig.h"
#include "GPUProcessHost.h"
#include "mozilla/Assertions.h"
#include "mozilla/ipc/ProcessChild.h"
namespace mozilla {
namespace gfx {
using namespace ipc;
GPUParent::GPUParent()
{
}
GPUParent::~GPUParent()
{
}
bool
GPUParent::Init(base::ProcessId aParentPid,
MessageLoop* aIOLoop,
IPC::Channel* aChannel)
{
if (NS_WARN_IF(!Open(aChannel, aParentPid, aIOLoop))) {
return false;
}
return true;
}
bool
GPUParent::RecvBeginShutdown()
{
return true;
}
void
GPUParent::ActorDestroy(ActorDestroyReason aWhy)
{
if (AbnormalShutdown == aWhy) {
NS_WARNING("Shutting down GPU process early due to a crash!");
ProcessChild::QuickExit();
}
XRE_ShutdownChildProcess();
}
} // namespace gfx
} // namespace mozilla

32
gfx/ipc/GPUParent.h Normal file
View File

@ -0,0 +1,32 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=99: */
/* 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/. */
#ifndef _include_gfx_ipc_GPUParent_h__
#define _include_gfx_ipc_GPUParent_h__
#include "mozilla/gfx/PGPUParent.h"
namespace mozilla {
namespace gfx {
class GPUParent final : public PGPUParent
{
public:
GPUParent();
~GPUParent();
bool Init(base::ProcessId aParentPid,
MessageLoop* aIOLoop,
IPC::Channel* aChannel);
bool RecvBeginShutdown() override;
void ActorDestroy(ActorDestroyReason aWhy) override;
};
} // namespace gfx
} // namespace mozilla
#endif // _include_gfx_ipc_GPUParent_h__

150
gfx/ipc/GPUProcessHost.cpp Normal file
View File

@ -0,0 +1,150 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: sts=8 sw=2 ts=2 tw=99 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 "gfxPrefs.h"
#include "GPUProcessHost.h"
#include "mozilla/gfx/Logging.h"
namespace mozilla {
namespace gfx {
GPUProcessHost::GPUProcessHost(Listener* aListener)
: GeckoChildProcessHost(GeckoProcessType_GPU),
mListener(aListener),
mTaskFactory(this),
mLaunchPhase(LaunchPhase::Unlaunched)
{
MOZ_COUNT_CTOR(GPUProcessHost);
}
GPUProcessHost::~GPUProcessHost()
{
MOZ_COUNT_DTOR(GPUProcessHost);
}
bool
GPUProcessHost::Launch()
{
MOZ_ASSERT(mLaunchPhase == LaunchPhase::Unlaunched);
MOZ_ASSERT(!mGPUChild);
mLaunchPhase = LaunchPhase::Waiting;
if (!GeckoChildProcessHost::AsyncLaunch()) {
mLaunchPhase = LaunchPhase::Complete;
return false;
}
return true;
}
bool
GPUProcessHost::WaitForLaunch()
{
if (mLaunchPhase == LaunchPhase::Complete) {
return !!mGPUChild;
}
int32_t timeoutMs = gfxPrefs::GPUProcessDevTimeoutMs();
// Our caller expects the connection to be finished after we return, so we
// immediately set up the IPDL actor and fire callbacks. The IO thread will
// still dispatch a notification to the main thread - we'll just ignore it.
bool result = GeckoChildProcessHost::WaitUntilConnected(timeoutMs);
InitAfterConnect(result);
return result;
}
void
GPUProcessHost::OnChannelConnected(int32_t peer_pid)
{
MOZ_ASSERT(!NS_IsMainThread());
GeckoChildProcessHost::OnChannelConnected(peer_pid);
// Post a task to the main thread. Take the lock because mTaskFactory is not
// thread-safe.
RefPtr<Runnable> runnable;
{
MonitorAutoLock lock(mMonitor);
runnable = mTaskFactory.NewRunnableMethod(&GPUProcessHost::OnChannelConnectedTask);
}
NS_DispatchToMainThread(runnable);
}
void
GPUProcessHost::OnChannelError()
{
MOZ_ASSERT(!NS_IsMainThread());
GeckoChildProcessHost::OnChannelError();
// Post a task to the main thread. Take the lock because mTaskFactory is not
// thread-safe.
RefPtr<Runnable> runnable;
{
MonitorAutoLock lock(mMonitor);
runnable = mTaskFactory.NewRunnableMethod(&GPUProcessHost::OnChannelErrorTask);
}
NS_DispatchToMainThread(runnable);
}
void
GPUProcessHost::OnChannelConnectedTask()
{
if (mLaunchPhase == LaunchPhase::Waiting) {
InitAfterConnect(true);
}
}
void
GPUProcessHost::OnChannelErrorTask()
{
if (mLaunchPhase == LaunchPhase::Waiting) {
InitAfterConnect(false);
}
}
void
GPUProcessHost::InitAfterConnect(bool aSucceeded)
{
MOZ_ASSERT(mLaunchPhase == LaunchPhase::Waiting);
MOZ_ASSERT(!mGPUChild);
mLaunchPhase = LaunchPhase::Complete;
if (aSucceeded) {
mGPUChild = MakeUnique<GPUChild>();
DebugOnly<bool> rv =
mGPUChild->Open(GetChannel(), base::GetProcId(GetChildProcessHandle()));
MOZ_ASSERT(rv);
}
if (mListener) {
mListener->OnProcessLaunchComplete(this);
}
}
void
GPUProcessHost::Shutdown()
{
mListener = nullptr;
DestroyProcess();
}
void
GPUProcessHost::DestroyProcess()
{
// Cancel all tasks. We don't want anything triggering after our caller
// expects this to go away.
{
MonitorAutoLock lock(mMonitor);
mTaskFactory.RevokeAll();
}
DissociateActor();
}
} // namespace gfx
} // namespace mozilla

103
gfx/ipc/GPUProcessHost.h Normal file
View File

@ -0,0 +1,103 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: sts=8 sw=2 ts=2 tw=99 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/. */
#ifndef _include_mozilla_gfx_ipc_GPUProcessHost_h_
#define _include_mozilla_gfx_ipc_GPUProcessHost_h_
#include "mozilla/Function.h"
#include "mozilla/Maybe.h"
#include "mozilla/UniquePtr.h"
#include "mozilla/ipc/GeckoChildProcessHost.h"
#include "mozilla/ipc/TaskFactory.h"
namespace mozilla {
namespace gfx {
class GPUChild;
// GPUProcessHost is the "parent process" container for a subprocess handle and
// IPC connection. It owns the parent process IPDL actor, which in this case,
// is a GPUChild.
//
// GPUProcessHosts are allocated and managed by GPUProcessManager. For all
// intents and purposes it is a singleton, though more than one may be allocated
// at a time due to its shutdown being asynchronous.
class GPUProcessHost final : public ipc::GeckoChildProcessHost
{
public:
class Listener {
public:
virtual void OnProcessLaunchComplete(GPUProcessHost* aHost)
{}
};
public:
GPUProcessHost(Listener* listener);
~GPUProcessHost();
// Launch the subprocess asynchronously. On failure, false is returned.
// Otherwise, true is returned, and the OnLaunchComplete listener callback
// will be invoked either when a connection has been established, or if a
// connection could not be established due to an asynchronous error.
bool Launch();
// If the process is being launched, block until it has launched and
// connected. If a launch task is pending, it will fire immediately.
//
// Returns true if the process is successfully connected; false otherwise.
bool WaitForLaunch();
// Inform the process that it should clean up its resources and shut down.
// This initiates an asynchronous shutdown sequence. After this method returns,
// it is safe for the caller to forget its pointer to the GPUProcessHost.
//
// After this returns, the attached Listener is no longer used.
void Shutdown();
// Return the actor for the top-level actor of the process. If the process
// has not connected yet, this returns null.
GPUChild* GetActor() const {
return mGPUChild.get();
}
bool IsConnected() const {
return !!mGPUChild;
}
// Called on the IO thread.
void OnChannelConnected(int32_t peer_pid) override;
void OnChannelError() override;
private:
// Called on the main thread.
void OnChannelConnectedTask();
void OnChannelErrorTask();
// Called on the main thread after a connection has been established.
void InitAfterConnect(bool aSucceeded);
void DestroyProcess();
private:
DISALLOW_COPY_AND_ASSIGN(GPUProcessHost);
Listener* mListener;
ipc::TaskFactory<GPUProcessHost> mTaskFactory;
enum class LaunchPhase {
Unlaunched,
Waiting,
Complete
};
LaunchPhase mLaunchPhase;
UniquePtr<GPUChild> mGPUChild;
};
} // namespace gfx
} // namespace mozilla
#endif // _include_mozilla_gfx_ipc_GPUProcessHost_h_

View File

@ -0,0 +1,37 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=99: */
/* 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 "GPUProcessImpl.h"
#include "mozilla/ipc/IOThreadChild.h"
namespace mozilla {
namespace gfx {
using namespace ipc;
GPUProcessImpl::GPUProcessImpl(ProcessId aParentPid)
: ProcessChild(aParentPid)
{
}
GPUProcessImpl::~GPUProcessImpl()
{
}
bool
GPUProcessImpl::Init()
{
return mGPU.Init(ParentPid(),
IOThreadChild::message_loop(),
IOThreadChild::channel());
}
void
GPUProcessImpl::CleanUp()
{
}
} // namespace gfx
} // namespace mozilla

34
gfx/ipc/GPUProcessImpl.h Normal file
View File

@ -0,0 +1,34 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=99: */
/* 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/. */
#ifndef _include_gfx_ipc_GPUProcessImpl_h__
#define _include_gfx_ipc_GPUProcessImpl_h__
#include "mozilla/ipc/ProcessChild.h"
#include "GPUParent.h"
namespace mozilla {
namespace gfx {
// This class owns the subprocess instance of a PGPU - which in this case,
// is a GPUParent. It is instantiated as a singleton in XRE_InitChildProcess.
class GPUProcessImpl final : public ipc::ProcessChild
{
public:
explicit GPUProcessImpl(ProcessId aParentPid);
~GPUProcessImpl();
bool Init() override;
void CleanUp() override;
private:
DISALLOW_COPY_AND_ASSIGN(GPUProcessImpl);
GPUParent mGPU;
};
} // namespace gfx
} // namespace mozilla
#endif // _include_gfx_ipc_GPUProcessImpl_h__

View File

@ -4,8 +4,10 @@
* 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 "GPUProcessManager.h"
#include "GPUProcessHost.h"
#include "mozilla/layers/CompositorSession.h"
#include "mozilla/StaticPtr.h"
#include "nsContentUtils.h"
namespace mozilla {
namespace gfx {
@ -34,11 +36,109 @@ GPUProcessManager::Shutdown()
}
GPUProcessManager::GPUProcessManager()
: mProcess(nullptr),
mGPUChild(nullptr)
{
mObserver = new Observer(this);
nsContentUtils::RegisterShutdownObserver(mObserver);
}
GPUProcessManager::~GPUProcessManager()
{
// The GPU process should have already been shut down.
MOZ_ASSERT(!mProcess && !mGPUChild);
// We should have already removed observers.
MOZ_ASSERT(!mObserver);
}
NS_IMPL_ISUPPORTS(GPUProcessManager::Observer, nsIObserver);
GPUProcessManager::Observer::Observer(GPUProcessManager* aManager)
: mManager(aManager)
{
}
NS_IMETHODIMP
GPUProcessManager::Observer::Observe(nsISupports* aSubject, const char* aTopic, const char16_t* aData)
{
if (!strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID)) {
mManager->OnXPCOMShutdown();
}
return NS_OK;
}
void
GPUProcessManager::OnXPCOMShutdown()
{
if (mObserver) {
nsContentUtils::UnregisterShutdownObserver(mObserver);
mObserver = nullptr;
}
DestroyProcess();
}
void
GPUProcessManager::EnableGPUProcess()
{
if (mProcess) {
return;
}
// The subprocess is launched asynchronously, so we wait for a callback to
// acquire the IPDL actor.
mProcess = new GPUProcessHost(this);
if (!mProcess->Launch()) {
DisableGPUProcess("Failed to launch GPU process");
}
}
void
GPUProcessManager::DisableGPUProcess(const char* aMessage)
{
gfxConfig::SetFailed(Feature::GPU_PROCESS, FeatureStatus::Failed, aMessage);
gfxCriticalNote << aMessage;
DestroyProcess();
}
void
GPUProcessManager::EnsureGPUReady()
{
if (mProcess && mProcess->IsConnected()) {
if (!mProcess->WaitForLaunch()) {
// If this fails, we should have fired OnProcessLaunchComplete and
// removed the process.
MOZ_ASSERT(!mProcess && !mGPUChild);
return;
}
}
}
void
GPUProcessManager::OnProcessLaunchComplete(GPUProcessHost* aHost)
{
MOZ_ASSERT(mProcess && mProcess == aHost);
if (!mProcess->IsConnected()) {
DisableGPUProcess("Failed to launch GPU process");
return;
}
mGPUChild = mProcess->GetActor();
}
void
GPUProcessManager::DestroyProcess()
{
if (!mProcess) {
return;
}
mProcess->Shutdown();
mProcess = nullptr;
mGPUChild = nullptr;
}
already_AddRefed<CompositorSession>

View File

@ -10,7 +10,9 @@
#include "base/process.h"
#include "Units.h"
#include "mozilla/dom/ipc/IdType.h"
#include "mozilla/gfx/GPUProcessHost.h"
#include "mozilla/ipc/Transport.h"
#include "nsIObserverService.h"
namespace mozilla {
namespace layers {
@ -32,10 +34,12 @@ class GeckoChildProcessHost;
} // namespace ipc
namespace gfx {
class GPUChild;
// The GPUProcessManager is a singleton responsible for creating GPU-bound
// objects that may live in another process. Currently, it provides access
// to the compositor via CompositorBridgeParent.
class GPUProcessManager final
class GPUProcessManager final : public GPUProcessHost::Listener
{
typedef layers::APZCTreeManager APZCTreeManager;
typedef layers::CompositorUpdateObserver CompositorUpdateObserver;
@ -47,6 +51,14 @@ public:
~GPUProcessManager();
// If not using a GPU process, launch a new GPU process asynchronously.
void EnableGPUProcess();
// Ensure that GPU-bound methods can be used. If no GPU process is being
// used, or one is launched and ready, this function returns immediately.
// Otherwise it blocks until the GPU process has finished launching.
void EnsureGPUReady();
already_AddRefed<layers::CompositorSession> CreateTopLevelCompositor(
widget::CompositorWidgetProxy* aProxy,
layers::ClientLayerManager* aLayerManager,
@ -92,10 +104,40 @@ public:
const dom::TabId& aTabId,
dom::TabParent* aBrowserParent);
void OnProcessLaunchComplete(GPUProcessHost* aHost) override;
private:
// Called from our xpcom-shutdown observer.
void OnXPCOMShutdown();
private:
GPUProcessManager();
// Permanently disable the GPU process and record a message why.
void DisableGPUProcess(const char* aMessage);
// Shutdown the GPU process.
void DestroyProcess();
DISALLOW_COPY_AND_ASSIGN(GPUProcessManager);
class Observer final : public nsIObserver {
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIOBSERVER
Observer(GPUProcessManager* aManager);
protected:
~Observer() {}
GPUProcessManager* mManager;
};
friend class Observer;
private:
RefPtr<Observer> mObserver;
GPUProcessHost* mProcess;
GPUChild* mGPUChild;
};
} // namespace gfx

17
gfx/ipc/PGPU.ipdl Normal file
View File

@ -0,0 +1,17 @@
/* -*- Mode: C++; tab-width: 8; 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/. */
namespace mozilla {
namespace gfx {
sync protocol PGPU
{
parent:
// Sent by the UI process to initiate shutdown.
async BeginShutdown();
};
} // namespace gfx
} // namespace mozilla

View File

@ -10,6 +10,10 @@ EXPORTS.mozilla += [
]
EXPORTS.mozilla.gfx += [
'GPUChild.h',
'GPUParent.h',
'GPUProcessHost.h',
'GPUProcessImpl.h',
'GPUProcessManager.h',
'SharedDIB.h',
]
@ -31,12 +35,17 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
UNIFIED_SOURCES += [
'CompositorSession.cpp',
'D3DMessageUtils.cpp',
'GPUChild.cpp',
'GPUParent.cpp',
'GPUProcessHost.cpp',
'GPUProcessImpl.cpp',
'GPUProcessManager.cpp',
'SharedDIB.cpp',
]
IPDL_SOURCES = [
'GraphicsMessages.ipdlh',
'PGPU.ipdl',
]
include('/ipc/chromium/chromium-config.mozbuild')

View File

@ -142,6 +142,7 @@ class mozilla::gl::SkiaGLGlue : public GenericAtomicRefCounted {
#include "mozilla/dom/ContentChild.h"
#include "gfxVR.h"
#include "VRManagerChild.h"
#include "mozilla/gfx/GPUParent.h"
namespace mozilla {
namespace layers {
@ -2119,6 +2120,23 @@ gfxPlatform::InitAcceleration()
"media.hardware-video-decoding.failed",
false);
if (XRE_IsParentProcess()) {
if (gfxPrefs::GPUProcessDevEnabled()) {
// We want to hide this from about:support, so only set a default if the
// pref is known to be true.
gfxConfig::SetDefaultFromPref(
Feature::GPU_PROCESS,
gfxPrefs::GetGPUProcessDevEnabledPrefName(),
true,
gfxPrefs::GetGPUProcessDevEnabledPrefDefault());
}
if (gfxConfig::IsEnabled(Feature::GPU_PROCESS)) {
GPUProcessManager* gpu = GPUProcessManager::Get();
gpu->EnableGPUProcess();
}
}
sLayersAccelerationPrefsInitialized = true;
}

View File

@ -71,7 +71,7 @@ class PreferenceAccessImpl;
class gfxPrefs;
class gfxPrefs final
{
private:
private:
/// See Logging.h. This lets Moz2D access preference values it owns.
PreferenceAccessImpl* mMoz2DPrefAccess;
@ -365,6 +365,8 @@ private:
DECL_GFX_PREF(Live, "layers.flash-borders", FlashLayerBorders, bool, false);
DECL_GFX_PREF(Once, "layers.force-shmem-tiles", ForceShmemTiles, bool, false);
DECL_GFX_PREF(Live, "layers.frame-counter", DrawFrameCounter, bool, false);
DECL_GFX_PREF(Once, "layers.gpu-process.dev.enabled", GPUProcessDevEnabled, bool, false);
DECL_GFX_PREF(Once, "layers.gpu-process.dev.timeout_ms", GPUProcessDevTimeoutMs, int32_t, 5000);
DECL_GFX_PREF(Once, "layers.gralloc.disable", DisableGralloc, bool, false);
DECL_GFX_PREF(Live, "layers.low-precision-buffer", UseLowPrecisionBuffer, bool, false);
DECL_GFX_PREF(Live, "layers.low-precision-opacity", LowPrecisionOpacity, float, 1.0f);

View File

@ -1072,6 +1072,8 @@ GeckoChildProcessHost::PerformAsyncLaunchInternal(std::vector<std::string>& aExt
shouldSandboxCurrentProcess = true;
}
break;
case GeckoProcessType_GPU:
break;
case GeckoProcessType_Default:
default:
MOZ_CRASH("Bad process type in GeckoChildProcessHost");

View File

@ -73,6 +73,7 @@
#include "GMPProcessChild.h"
#include "GMPLoader.h"
#include "mozilla/gfx/GPUProcessImpl.h"
#include "GeckoProfiler.h"
@ -566,6 +567,9 @@ XRE_InitChildProcess(int aArgc,
case GeckoProcessType_GMPlugin:
uiLoopType = MessageLoop::TYPE_DEFAULT;
break;
case GeckoProcessType_GPU:
uiLoopType = MessageLoop::TYPE_UI;
break;
default:
uiLoopType = MessageLoop::TYPE_UI;
break;
@ -621,6 +625,10 @@ XRE_InitChildProcess(int aArgc,
process = new gmp::GMPProcessChild(parentPID);
break;
case GeckoProcessType_GPU:
process = new gfx::GPUProcessImpl(parentPID);
break;
default:
NS_RUNTIMEABORT("Unknown main thread class");
}