2016-07-18 04:24:28 +00:00
|
|
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
2017-10-27 23:10:06 +00:00
|
|
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
2016-05-23 07:27:01 +00:00
|
|
|
/* 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/. */
|
2017-02-14 22:01:59 +00:00
|
|
|
|
2016-05-23 07:27:01 +00:00
|
|
|
#include "GPUProcessManager.h"
|
2017-02-14 22:01:59 +00:00
|
|
|
|
|
|
|
#include "gfxPrefs.h"
|
2016-06-11 02:27:24 +00:00
|
|
|
#include "GPUProcessHost.h"
|
2016-09-20 08:18:50 +00:00
|
|
|
#include "GPUProcessListener.h"
|
2017-01-27 00:35:54 +00:00
|
|
|
#include "mozilla/MemoryReportingProcess.h"
|
2016-11-15 18:58:29 +00:00
|
|
|
#include "mozilla/Sprintf.h"
|
2016-07-18 04:24:28 +00:00
|
|
|
#include "mozilla/StaticPtr.h"
|
2016-08-16 20:59:13 +00:00
|
|
|
#include "mozilla/dom/ContentParent.h"
|
Bug 1354411 - Rebuild CompositorSessions if WebRender is disabled r=kats
When WebRender creation is failed, WebRender is disabled in gecko. There is a case that WebRenderBridgeParents exist when WebRender is disabled. To handle this, gecko needs to rebuild all CompositorSessions.
There is also a problem related to gfxVars::UseWebRender on compositor thread. If e10s is enabled, but no-gpu process(default on linux and mac), gfxVars::UseWebRender change is soon notified by compositor thread tasks. If WebRender creation failure happens at 2nd WebRender creation, several WebRenderBridgeParents for 1st WebRender could exist. IPC messages from WebRenderLayerManager are normally async, then there is a chance that the WebRenderBridgeParents receive the messages after the gfxVars::UseWebRender change. Further the gfxVars::UseWebRender change in content process could be delayed than WebRenderBridgeParents, then content process does not have a way to stop sending PWebRenderBridge IPC until the change of gfxVars::UseWebRender is received. WebRenderBridgeParent related tasks handle the message, but some tasks are done based on gfxVars::UseWebRender. At this time, gfxVars::UseWebRender returned false on compositor thread, then it cause unexpected result for WebRenderBridgeParent and WebRender. To addres this inconsistent situation, WebRenderBridgeParent related tasks on compositor thread stop to use gfxVars::UseWebRender.
2017-08-04 05:36:41 +00:00
|
|
|
#include "mozilla/gfx/gfxVars.h"
|
2016-08-16 20:59:13 +00:00
|
|
|
#include "mozilla/layers/APZCTreeManager.h"
|
2016-08-29 13:18:00 +00:00
|
|
|
#include "mozilla/layers/APZCTreeManagerChild.h"
|
2016-07-18 04:24:28 +00:00
|
|
|
#include "mozilla/layers/CompositorBridgeParent.h"
|
2017-06-14 15:39:59 +00:00
|
|
|
#include "mozilla/layers/CompositorManagerChild.h"
|
|
|
|
#include "mozilla/layers/CompositorManagerParent.h"
|
2017-01-12 22:29:41 +00:00
|
|
|
#include "mozilla/layers/CompositorOptions.h"
|
2016-07-20 07:17:28 +00:00
|
|
|
#include "mozilla/layers/ImageBridgeChild.h"
|
2016-07-20 07:18:30 +00:00
|
|
|
#include "mozilla/layers/ImageBridgeParent.h"
|
2016-07-18 04:24:28 +00:00
|
|
|
#include "mozilla/layers/InProcessCompositorSession.h"
|
2016-08-16 20:59:13 +00:00
|
|
|
#include "mozilla/layers/LayerTreeOwnerTracker.h"
|
2016-07-18 04:24:28 +00:00
|
|
|
#include "mozilla/layers/RemoteCompositorSession.h"
|
|
|
|
#include "mozilla/widget/PlatformWidgetTypes.h"
|
|
|
|
#ifdef MOZ_WIDGET_SUPPORTS_OOP_COMPOSITING
|
|
|
|
# include "mozilla/widget/CompositorWidgetChild.h"
|
|
|
|
#endif
|
2016-07-19 18:56:07 +00:00
|
|
|
#include "nsBaseWidget.h"
|
2016-06-11 02:27:24 +00:00
|
|
|
#include "nsContentUtils.h"
|
2016-07-21 07:14:59 +00:00
|
|
|
#include "VRManagerChild.h"
|
2016-07-21 07:14:59 +00:00
|
|
|
#include "VRManagerParent.h"
|
2016-07-19 18:56:06 +00:00
|
|
|
#include "VsyncBridgeChild.h"
|
|
|
|
#include "VsyncIOThreadHolder.h"
|
2016-07-26 08:57:11 +00:00
|
|
|
#include "VsyncSource.h"
|
2016-09-21 09:25:33 +00:00
|
|
|
#include "mozilla/dom/VideoDecoderManagerChild.h"
|
|
|
|
#include "mozilla/dom/VideoDecoderManagerParent.h"
|
2016-11-08 02:21:35 +00:00
|
|
|
#include "MediaPrefs.h"
|
2017-07-13 17:27:00 +00:00
|
|
|
#include "nsPrintfCString.h"
|
2016-05-23 07:27:01 +00:00
|
|
|
|
2017-11-22 22:11:44 +00:00
|
|
|
#ifdef MOZ_CRASHREPORTER
|
|
|
|
# include "nsExceptionHandler.h"
|
|
|
|
#endif
|
|
|
|
|
2017-01-05 19:04:38 +00:00
|
|
|
#if defined(MOZ_WIDGET_ANDROID)
|
|
|
|
#include "mozilla/widget/AndroidUiThread.h"
|
|
|
|
#include "mozilla/layers/UiCompositorControllerChild.h"
|
|
|
|
#endif // defined(MOZ_WIDGET_ANDROID)
|
|
|
|
|
2016-05-23 07:27:01 +00:00
|
|
|
namespace mozilla {
|
|
|
|
namespace gfx {
|
|
|
|
|
|
|
|
using namespace mozilla::layers;
|
|
|
|
|
2017-04-14 21:36:42 +00:00
|
|
|
enum class FallbackType : uint32_t
|
|
|
|
{
|
|
|
|
NONE = 0,
|
|
|
|
DECODINGDISABLED,
|
|
|
|
DISABLED,
|
|
|
|
};
|
|
|
|
|
2016-05-23 07:27:01 +00:00
|
|
|
static StaticAutoPtr<GPUProcessManager> sSingleton;
|
|
|
|
|
|
|
|
GPUProcessManager*
|
|
|
|
GPUProcessManager::Get()
|
|
|
|
{
|
|
|
|
return sSingleton;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
GPUProcessManager::Initialize()
|
|
|
|
{
|
2016-06-27 06:33:20 +00:00
|
|
|
MOZ_ASSERT(XRE_IsParentProcess());
|
2016-05-23 07:27:01 +00:00
|
|
|
sSingleton = new GPUProcessManager();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
GPUProcessManager::Shutdown()
|
|
|
|
{
|
|
|
|
sSingleton = nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
GPUProcessManager::GPUProcessManager()
|
2016-07-18 04:24:28 +00:00
|
|
|
: mTaskFactory(this),
|
2017-04-14 08:06:09 +00:00
|
|
|
mNextNamespace(0),
|
2017-05-30 00:59:44 +00:00
|
|
|
mIdNamespace(0),
|
|
|
|
mResourceId(0),
|
2016-09-30 08:21:21 +00:00
|
|
|
mNumProcessAttempts(0),
|
2016-11-10 02:57:04 +00:00
|
|
|
mDeviceResetCount(0),
|
2016-07-18 04:24:27 +00:00
|
|
|
mProcess(nullptr),
|
2017-11-16 10:31:51 +00:00
|
|
|
mProcessToken(0),
|
2016-09-28 20:54:03 +00:00
|
|
|
mGPUChild(nullptr)
|
2016-05-23 07:27:01 +00:00
|
|
|
{
|
2016-10-07 07:07:10 +00:00
|
|
|
MOZ_COUNT_CTOR(GPUProcessManager);
|
|
|
|
|
2017-05-30 00:59:44 +00:00
|
|
|
mIdNamespace = AllocateNamespace();
|
2016-06-11 02:27:24 +00:00
|
|
|
mObserver = new Observer(this);
|
|
|
|
nsContentUtils::RegisterShutdownObserver(mObserver);
|
2016-08-16 20:59:13 +00:00
|
|
|
|
2016-11-10 02:57:04 +00:00
|
|
|
mDeviceResetLastTime = TimeStamp::Now();
|
|
|
|
|
2016-08-16 20:59:13 +00:00
|
|
|
LayerTreeOwnerTracker::Initialize();
|
2016-05-23 07:27:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
GPUProcessManager::~GPUProcessManager()
|
|
|
|
{
|
2016-10-07 07:07:10 +00:00
|
|
|
MOZ_COUNT_DTOR(GPUProcessManager);
|
|
|
|
|
2016-08-16 20:59:13 +00:00
|
|
|
LayerTreeOwnerTracker::Shutdown();
|
|
|
|
|
2016-06-11 02:27:24 +00:00
|
|
|
// 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;
|
|
|
|
}
|
|
|
|
|
2016-07-19 18:56:06 +00:00
|
|
|
CleanShutdown();
|
2016-06-11 02:27:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2016-09-30 08:21:21 +00:00
|
|
|
GPUProcessManager::LaunchGPUProcess()
|
2016-06-11 02:27:24 +00:00
|
|
|
{
|
|
|
|
if (mProcess) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-07-19 18:56:06 +00:00
|
|
|
// Start the Vsync I/O thread so can use it as soon as the process launches.
|
|
|
|
EnsureVsyncIOThread();
|
|
|
|
|
2016-09-30 08:21:21 +00:00
|
|
|
mNumProcessAttempts++;
|
|
|
|
|
2016-06-11 02:27:24 +00:00
|
|
|
// 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)
|
|
|
|
{
|
2016-09-30 08:21:21 +00:00
|
|
|
if (!gfxConfig::IsEnabled(Feature::GPU_PROCESS)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-06-11 02:27:24 +00:00
|
|
|
gfxConfig::SetFailed(Feature::GPU_PROCESS, FeatureStatus::Failed, aMessage);
|
|
|
|
gfxCriticalNote << aMessage;
|
|
|
|
|
2017-02-09 06:33:54 +00:00
|
|
|
gfxPlatform::NotifyGPUProcessDisabled();
|
|
|
|
|
2017-04-14 21:36:42 +00:00
|
|
|
Telemetry::Accumulate(Telemetry::GPU_PROCESS_CRASH_FALLBACKS,
|
|
|
|
uint32_t(FallbackType::DISABLED));
|
|
|
|
|
2016-06-11 02:27:24 +00:00
|
|
|
DestroyProcess();
|
2016-07-19 18:56:06 +00:00
|
|
|
ShutdownVsyncIOThread();
|
2017-06-28 18:31:42 +00:00
|
|
|
|
|
|
|
// We may have been in the middle of guaranteeing our various services are
|
|
|
|
// available when one failed. Some callers may fallback to using the same
|
|
|
|
// process equivalent, and we need to make sure those services are setup
|
|
|
|
// correctly. We cannot re-enter DisableGPUProcess from this call because we
|
|
|
|
// know that it is disabled in the config above.
|
|
|
|
EnsureProtocolsReady();
|
2017-07-20 13:20:22 +00:00
|
|
|
|
|
|
|
// If we disable the GPU process during reinitialization after a previous
|
|
|
|
// crash, then we need to tell the content processes again, because they
|
|
|
|
// need to rebind to the UI process.
|
|
|
|
HandleProcessLost();
|
2016-06-11 02:27:24 +00:00
|
|
|
}
|
|
|
|
|
2017-03-30 01:23:24 +00:00
|
|
|
bool
|
2016-06-11 02:27:24 +00:00
|
|
|
GPUProcessManager::EnsureGPUReady()
|
|
|
|
{
|
2016-10-31 23:03:41 +00:00
|
|
|
if (mProcess && !mProcess->IsConnected()) {
|
2016-06-11 02:27:24 +00:00
|
|
|
if (!mProcess->WaitForLaunch()) {
|
|
|
|
// If this fails, we should have fired OnProcessLaunchComplete and
|
|
|
|
// removed the process.
|
|
|
|
MOZ_ASSERT(!mProcess && !mGPUChild);
|
2017-03-30 01:23:24 +00:00
|
|
|
return false;
|
2016-06-11 02:27:24 +00:00
|
|
|
}
|
|
|
|
}
|
2016-08-21 03:59:11 +00:00
|
|
|
|
2017-03-30 01:23:24 +00:00
|
|
|
if (mGPUChild && mGPUChild->EnsureGPUReady()) {
|
|
|
|
return true;
|
2016-08-21 03:59:11 +00:00
|
|
|
}
|
2017-03-30 01:23:24 +00:00
|
|
|
|
|
|
|
return false;
|
2016-06-11 02:27:24 +00:00
|
|
|
}
|
|
|
|
|
2017-06-28 18:31:42 +00:00
|
|
|
void
|
|
|
|
GPUProcessManager::EnsureProtocolsReady()
|
|
|
|
{
|
|
|
|
EnsureCompositorManagerChild();
|
|
|
|
EnsureImageBridgeChild();
|
|
|
|
EnsureVRManager();
|
|
|
|
}
|
|
|
|
|
2017-06-14 15:39:59 +00:00
|
|
|
void
|
|
|
|
GPUProcessManager::EnsureCompositorManagerChild()
|
|
|
|
{
|
2017-09-26 17:21:52 +00:00
|
|
|
bool gpuReady = EnsureGPUReady();
|
|
|
|
if (CompositorManagerChild::IsInitialized(mProcessToken)) {
|
2017-06-14 15:39:59 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-09-26 17:21:52 +00:00
|
|
|
if (!gpuReady) {
|
|
|
|
CompositorManagerChild::InitSameProcess(AllocateNamespace(), mProcessToken);
|
2017-06-14 15:39:59 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
ipc::Endpoint<PCompositorManagerParent> parentPipe;
|
|
|
|
ipc::Endpoint<PCompositorManagerChild> childPipe;
|
|
|
|
nsresult rv = PCompositorManager::CreateEndpoints(
|
|
|
|
mGPUChild->OtherPid(),
|
|
|
|
base::GetCurrentProcId(),
|
|
|
|
&parentPipe,
|
|
|
|
&childPipe);
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
DisableGPUProcess("Failed to create PCompositorManager endpoints");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
mGPUChild->SendInitCompositorManager(Move(parentPipe));
|
2017-09-26 17:21:52 +00:00
|
|
|
CompositorManagerChild::Init(Move(childPipe), AllocateNamespace(),
|
|
|
|
mProcessToken);
|
2017-06-14 15:39:59 +00:00
|
|
|
}
|
|
|
|
|
2016-07-20 07:17:28 +00:00
|
|
|
void
|
|
|
|
GPUProcessManager::EnsureImageBridgeChild()
|
|
|
|
{
|
2016-09-13 23:30:57 +00:00
|
|
|
if (ImageBridgeChild::GetSingleton()) {
|
2016-07-20 07:19:27 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-03-30 01:23:24 +00:00
|
|
|
if (!EnsureGPUReady()) {
|
2017-04-14 08:06:09 +00:00
|
|
|
ImageBridgeChild::InitSameProcess(AllocateNamespace());
|
2016-07-20 07:19:27 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
ipc::Endpoint<PImageBridgeParent> parentPipe;
|
|
|
|
ipc::Endpoint<PImageBridgeChild> childPipe;
|
|
|
|
nsresult rv = PImageBridge::CreateEndpoints(
|
|
|
|
mGPUChild->OtherPid(),
|
|
|
|
base::GetCurrentProcId(),
|
|
|
|
&parentPipe,
|
|
|
|
&childPipe);
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
DisableGPUProcess("Failed to create PImageBridge endpoints");
|
|
|
|
return;
|
2016-07-20 07:17:28 +00:00
|
|
|
}
|
2016-07-20 07:19:27 +00:00
|
|
|
|
|
|
|
mGPUChild->SendInitImageBridge(Move(parentPipe));
|
2017-04-14 08:06:09 +00:00
|
|
|
ImageBridgeChild::InitWithGPUProcess(Move(childPipe), AllocateNamespace());
|
2016-07-20 07:17:28 +00:00
|
|
|
}
|
|
|
|
|
2016-07-21 07:14:59 +00:00
|
|
|
void
|
|
|
|
GPUProcessManager::EnsureVRManager()
|
|
|
|
{
|
|
|
|
if (VRManagerChild::IsCreated()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-03-30 01:23:24 +00:00
|
|
|
if (!EnsureGPUReady()) {
|
2016-07-21 07:14:59 +00:00
|
|
|
VRManagerChild::InitSameProcess();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
ipc::Endpoint<PVRManagerParent> parentPipe;
|
|
|
|
ipc::Endpoint<PVRManagerChild> childPipe;
|
|
|
|
nsresult rv = PVRManager::CreateEndpoints(
|
|
|
|
mGPUChild->OtherPid(),
|
|
|
|
base::GetCurrentProcId(),
|
|
|
|
&parentPipe,
|
|
|
|
&childPipe);
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
DisableGPUProcess("Failed to create PVRManager endpoints");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
mGPUChild->SendInitVRManager(Move(parentPipe));
|
|
|
|
VRManagerChild::InitWithGPUProcess(Move(childPipe));
|
|
|
|
}
|
|
|
|
|
2017-01-05 19:04:38 +00:00
|
|
|
#if defined(MOZ_WIDGET_ANDROID)
|
2017-04-05 22:42:50 +00:00
|
|
|
already_AddRefed<UiCompositorControllerChild>
|
|
|
|
GPUProcessManager::CreateUiCompositorController(nsBaseWidget* aWidget, const uint64_t aId)
|
2017-01-05 19:04:38 +00:00
|
|
|
{
|
2017-04-05 22:42:50 +00:00
|
|
|
RefPtr<UiCompositorControllerChild> result;
|
2017-01-05 19:04:38 +00:00
|
|
|
|
2017-03-30 01:23:24 +00:00
|
|
|
if (!EnsureGPUReady()) {
|
2017-04-05 22:42:50 +00:00
|
|
|
result = UiCompositorControllerChild::CreateForSameProcess(aId);
|
|
|
|
} else {
|
|
|
|
ipc::Endpoint<PUiCompositorControllerParent> parentPipe;
|
|
|
|
ipc::Endpoint<PUiCompositorControllerChild> childPipe;
|
|
|
|
nsresult rv = PUiCompositorController::CreateEndpoints(
|
|
|
|
mGPUChild->OtherPid(),
|
|
|
|
base::GetCurrentProcId(),
|
|
|
|
&parentPipe,
|
|
|
|
&childPipe);
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
DisableGPUProcess("Failed to create PUiCompositorController endpoints");
|
|
|
|
return nullptr;
|
|
|
|
}
|
2017-01-05 19:04:38 +00:00
|
|
|
|
2017-04-05 22:42:50 +00:00
|
|
|
mGPUChild->SendInitUiCompositorController(aId, Move(parentPipe));
|
|
|
|
result = UiCompositorControllerChild::CreateForGPUProcess(mProcessToken, Move(childPipe));
|
2017-01-05 19:04:38 +00:00
|
|
|
}
|
2017-04-05 22:42:50 +00:00
|
|
|
if (result) {
|
|
|
|
result->SetBaseWidget(aWidget);
|
|
|
|
}
|
|
|
|
return result.forget();
|
2017-01-05 19:04:38 +00:00
|
|
|
}
|
|
|
|
#endif // defined(MOZ_WIDGET_ANDROID)
|
|
|
|
|
2016-06-11 02:27:24 +00:00
|
|
|
void
|
|
|
|
GPUProcessManager::OnProcessLaunchComplete(GPUProcessHost* aHost)
|
|
|
|
{
|
|
|
|
MOZ_ASSERT(mProcess && mProcess == aHost);
|
|
|
|
|
|
|
|
if (!mProcess->IsConnected()) {
|
2016-11-11 22:51:25 +00:00
|
|
|
DisableGPUProcess("Failed to connect GPU process");
|
2016-06-11 02:27:24 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
mGPUChild = mProcess->GetActor();
|
2016-07-18 04:24:28 +00:00
|
|
|
mProcessToken = mProcess->GetProcessToken();
|
2016-07-19 18:56:06 +00:00
|
|
|
|
|
|
|
Endpoint<PVsyncBridgeParent> vsyncParent;
|
|
|
|
Endpoint<PVsyncBridgeChild> vsyncChild;
|
|
|
|
nsresult rv = PVsyncBridge::CreateEndpoints(
|
|
|
|
mGPUChild->OtherPid(),
|
|
|
|
base::GetCurrentProcId(),
|
|
|
|
&vsyncParent,
|
|
|
|
&vsyncChild);
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
DisableGPUProcess("Failed to create PVsyncBridge endpoints");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
mVsyncBridge = VsyncBridgeChild::Create(mVsyncIOThread, mProcessToken, Move(vsyncChild));
|
|
|
|
mGPUChild->SendInitVsyncBridge(Move(vsyncParent));
|
2016-11-02 20:55:07 +00:00
|
|
|
|
2017-11-22 22:11:44 +00:00
|
|
|
#ifdef MOZ_CRASHREPORTER
|
2017-04-03 22:11:27 +00:00
|
|
|
CrashReporter::AnnotateCrashReport(
|
|
|
|
NS_LITERAL_CSTRING("GPUProcessStatus"),
|
|
|
|
NS_LITERAL_CSTRING("Running"));
|
2017-07-13 17:27:00 +00:00
|
|
|
|
|
|
|
CrashReporter::AnnotateCrashReport(
|
|
|
|
NS_LITERAL_CSTRING("GPUProcessLaunchCount"),
|
|
|
|
nsPrintfCString("%d", mNumProcessAttempts));
|
2017-11-22 22:11:44 +00:00
|
|
|
#endif
|
2016-06-11 02:27:24 +00:00
|
|
|
}
|
|
|
|
|
2016-11-10 02:57:04 +00:00
|
|
|
static bool
|
|
|
|
ShouldLimitDeviceResets(uint32_t count, int32_t deltaMilliseconds)
|
|
|
|
{
|
|
|
|
// We decide to limit by comparing the amount of resets that have happened
|
2017-06-15 18:34:00 +00:00
|
|
|
// and time since the last reset to two prefs.
|
2016-11-10 02:57:04 +00:00
|
|
|
int32_t timeLimit = gfxPrefs::DeviceResetThresholdMilliseconds();
|
|
|
|
int32_t countLimit = gfxPrefs::DeviceResetLimitCount();
|
|
|
|
|
2016-11-14 23:27:14 +00:00
|
|
|
bool hasTimeLimit = timeLimit >= 0;
|
|
|
|
bool hasCountLimit = countLimit >= 0;
|
2016-11-10 02:57:04 +00:00
|
|
|
|
|
|
|
bool triggeredTime = deltaMilliseconds < timeLimit;
|
|
|
|
bool triggeredCount = count > (uint32_t)countLimit;
|
|
|
|
|
|
|
|
// If we have both prefs set then it needs to trigger both limits,
|
|
|
|
// otherwise we only test the pref that is set or none
|
|
|
|
if (hasTimeLimit && hasCountLimit) {
|
|
|
|
return triggeredTime && triggeredCount;
|
|
|
|
} else if (hasTimeLimit) {
|
|
|
|
return triggeredTime;
|
|
|
|
} else if (hasCountLimit) {
|
|
|
|
return triggeredCount;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2017-08-11 07:51:23 +00:00
|
|
|
void
|
|
|
|
GPUProcessManager::ResetCompositors()
|
|
|
|
{
|
|
|
|
// Note: this will recreate devices in addition to recreating compositors.
|
|
|
|
// This isn't optimal, but this is only used on linux where acceleration
|
|
|
|
// isn't enabled by default, and this way we don't need a new code path.
|
|
|
|
SimulateDeviceReset();
|
|
|
|
}
|
|
|
|
|
2016-11-06 19:01:52 +00:00
|
|
|
void
|
2017-07-11 02:30:52 +00:00
|
|
|
GPUProcessManager::SimulateDeviceReset()
|
2017-06-15 18:34:00 +00:00
|
|
|
{
|
2017-07-11 02:30:52 +00:00
|
|
|
// Make sure we rebuild environment and configuration for accelerated features.
|
|
|
|
gfxPlatform::GetPlatform()->CompositorUpdated();
|
|
|
|
|
2017-06-15 18:34:00 +00:00
|
|
|
if (mProcess) {
|
2017-11-03 08:06:37 +00:00
|
|
|
GPUDeviceData data;
|
|
|
|
if (mGPUChild->SendSimulateDeviceReset(&data)) {
|
|
|
|
gfxPlatform::GetPlatform()->ImportGPUDeviceData(data);
|
|
|
|
}
|
2017-06-15 18:34:00 +00:00
|
|
|
OnRemoteProcessDeviceReset(mProcess);
|
|
|
|
} else {
|
|
|
|
OnInProcessDeviceReset();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Bug 1354411 - Rebuild CompositorSessions if WebRender is disabled r=kats
When WebRender creation is failed, WebRender is disabled in gecko. There is a case that WebRenderBridgeParents exist when WebRender is disabled. To handle this, gecko needs to rebuild all CompositorSessions.
There is also a problem related to gfxVars::UseWebRender on compositor thread. If e10s is enabled, but no-gpu process(default on linux and mac), gfxVars::UseWebRender change is soon notified by compositor thread tasks. If WebRender creation failure happens at 2nd WebRender creation, several WebRenderBridgeParents for 1st WebRender could exist. IPC messages from WebRenderLayerManager are normally async, then there is a chance that the WebRenderBridgeParents receive the messages after the gfxVars::UseWebRender change. Further the gfxVars::UseWebRender change in content process could be delayed than WebRenderBridgeParents, then content process does not have a way to stop sending PWebRenderBridge IPC until the change of gfxVars::UseWebRender is received. WebRenderBridgeParent related tasks handle the message, but some tasks are done based on gfxVars::UseWebRender. At this time, gfxVars::UseWebRender returned false on compositor thread, then it cause unexpected result for WebRenderBridgeParent and WebRender. To addres this inconsistent situation, WebRenderBridgeParent related tasks on compositor thread stop to use gfxVars::UseWebRender.
2017-08-04 05:36:41 +00:00
|
|
|
void
|
2017-08-30 00:10:22 +00:00
|
|
|
GPUProcessManager::DisableWebRender(wr::WebRenderError aError)
|
Bug 1354411 - Rebuild CompositorSessions if WebRender is disabled r=kats
When WebRender creation is failed, WebRender is disabled in gecko. There is a case that WebRenderBridgeParents exist when WebRender is disabled. To handle this, gecko needs to rebuild all CompositorSessions.
There is also a problem related to gfxVars::UseWebRender on compositor thread. If e10s is enabled, but no-gpu process(default on linux and mac), gfxVars::UseWebRender change is soon notified by compositor thread tasks. If WebRender creation failure happens at 2nd WebRender creation, several WebRenderBridgeParents for 1st WebRender could exist. IPC messages from WebRenderLayerManager are normally async, then there is a chance that the WebRenderBridgeParents receive the messages after the gfxVars::UseWebRender change. Further the gfxVars::UseWebRender change in content process could be delayed than WebRenderBridgeParents, then content process does not have a way to stop sending PWebRenderBridge IPC until the change of gfxVars::UseWebRender is received. WebRenderBridgeParent related tasks handle the message, but some tasks are done based on gfxVars::UseWebRender. At this time, gfxVars::UseWebRender returned false on compositor thread, then it cause unexpected result for WebRenderBridgeParent and WebRender. To addres this inconsistent situation, WebRenderBridgeParent related tasks on compositor thread stop to use gfxVars::UseWebRender.
2017-08-04 05:36:41 +00:00
|
|
|
{
|
|
|
|
if (!gfx::gfxVars::UseWebRender()) {
|
|
|
|
return;
|
|
|
|
}
|
2017-09-01 13:39:28 +00:00
|
|
|
// Disable WebRender
|
2017-08-30 00:10:22 +00:00
|
|
|
if (aError == wr::WebRenderError::INITIALIZE) {
|
|
|
|
gfx::gfxConfig::GetFeature(gfx::Feature::WEBRENDER).ForceDisable(
|
|
|
|
gfx::FeatureStatus::Unavailable,
|
|
|
|
"WebRender initialization failed",
|
|
|
|
NS_LITERAL_CSTRING("FEATURE_FAILURE_WEBRENDER_INITIALIZE"));
|
|
|
|
} else if (aError == wr::WebRenderError::MAKE_CURRENT) {
|
|
|
|
gfx::gfxConfig::GetFeature(gfx::Feature::WEBRENDER).ForceDisable(
|
|
|
|
gfx::FeatureStatus::Unavailable,
|
|
|
|
"Failed to make render context current",
|
|
|
|
NS_LITERAL_CSTRING("FEATURE_FAILURE_WEBRENDER_MAKE_CURRENT"));
|
2017-09-01 13:39:28 +00:00
|
|
|
} else if (aError == wr::WebRenderError::RENDER) {
|
|
|
|
gfx::gfxConfig::GetFeature(gfx::Feature::WEBRENDER).ForceDisable(
|
|
|
|
gfx::FeatureStatus::Unavailable,
|
|
|
|
"Failed to render WebRender",
|
|
|
|
NS_LITERAL_CSTRING("FEATURE_FAILURE_WEBRENDER_RENDER"));
|
2017-08-30 00:10:22 +00:00
|
|
|
} else {
|
|
|
|
MOZ_ASSERT_UNREACHABLE("Invalid value");
|
|
|
|
}
|
Bug 1354411 - Rebuild CompositorSessions if WebRender is disabled r=kats
When WebRender creation is failed, WebRender is disabled in gecko. There is a case that WebRenderBridgeParents exist when WebRender is disabled. To handle this, gecko needs to rebuild all CompositorSessions.
There is also a problem related to gfxVars::UseWebRender on compositor thread. If e10s is enabled, but no-gpu process(default on linux and mac), gfxVars::UseWebRender change is soon notified by compositor thread tasks. If WebRender creation failure happens at 2nd WebRender creation, several WebRenderBridgeParents for 1st WebRender could exist. IPC messages from WebRenderLayerManager are normally async, then there is a chance that the WebRenderBridgeParents receive the messages after the gfxVars::UseWebRender change. Further the gfxVars::UseWebRender change in content process could be delayed than WebRenderBridgeParents, then content process does not have a way to stop sending PWebRenderBridge IPC until the change of gfxVars::UseWebRender is received. WebRenderBridgeParent related tasks handle the message, but some tasks are done based on gfxVars::UseWebRender. At this time, gfxVars::UseWebRender returned false on compositor thread, then it cause unexpected result for WebRenderBridgeParent and WebRender. To addres this inconsistent situation, WebRenderBridgeParent related tasks on compositor thread stop to use gfxVars::UseWebRender.
2017-08-04 05:36:41 +00:00
|
|
|
gfx::gfxVars::SetUseWebRender(false);
|
|
|
|
|
|
|
|
if (mProcess) {
|
|
|
|
OnRemoteProcessDeviceReset(mProcess);
|
|
|
|
} else {
|
|
|
|
OnInProcessDeviceReset();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-08-30 00:10:22 +00:00
|
|
|
void
|
|
|
|
GPUProcessManager::NotifyWebRenderError(wr::WebRenderError aError)
|
|
|
|
{
|
|
|
|
DisableWebRender(aError);
|
|
|
|
}
|
|
|
|
|
2017-06-15 18:34:00 +00:00
|
|
|
void
|
|
|
|
GPUProcessManager::OnInProcessDeviceReset()
|
|
|
|
{
|
|
|
|
RebuildInProcessSessions();
|
|
|
|
NotifyListenersOnCompositeDeviceReset();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
GPUProcessManager::OnRemoteProcessDeviceReset(GPUProcessHost* aHost)
|
2016-11-06 19:01:52 +00:00
|
|
|
{
|
2016-11-10 02:57:04 +00:00
|
|
|
// Detect whether the device is resetting too quickly or too much
|
|
|
|
// indicating that we should give up and use software
|
|
|
|
mDeviceResetCount++;
|
|
|
|
|
|
|
|
auto newTime = TimeStamp::Now();
|
|
|
|
auto delta = (int32_t)(newTime - mDeviceResetLastTime).ToMilliseconds();
|
|
|
|
mDeviceResetLastTime = newTime;
|
|
|
|
|
|
|
|
if (ShouldLimitDeviceResets(mDeviceResetCount, delta)) {
|
|
|
|
DestroyProcess();
|
|
|
|
DisableGPUProcess("GPU processed experienced too many device resets");
|
|
|
|
|
2017-06-28 16:27:03 +00:00
|
|
|
// Reaches the limited TDR attempts, fallback to software solution.
|
|
|
|
gfxConfig::SetFailed(Feature::HW_COMPOSITING,
|
|
|
|
FeatureStatus::Blocked,
|
|
|
|
"Too many attemps of D3D11 creation, fallback to software solution.");
|
|
|
|
gfxConfig::SetFailed(Feature::D3D11_COMPOSITING,
|
|
|
|
FeatureStatus::Blocked,
|
|
|
|
"Too many attemps of D3D11 creation, fallback to software solution.");
|
|
|
|
gfxConfig::SetFailed(Feature::DIRECT2D,
|
|
|
|
FeatureStatus::Blocked,
|
|
|
|
"Too many attemps of D3D11 creation, fallback to software solution.");
|
|
|
|
|
2016-11-10 02:57:04 +00:00
|
|
|
HandleProcessLost();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-05-12 05:44:27 +00:00
|
|
|
RebuildRemoteSessions();
|
2017-06-15 18:34:00 +00:00
|
|
|
NotifyListenersOnCompositeDeviceReset();
|
|
|
|
}
|
2017-05-12 05:44:27 +00:00
|
|
|
|
2017-06-15 18:34:00 +00:00
|
|
|
void
|
|
|
|
GPUProcessManager::NotifyListenersOnCompositeDeviceReset()
|
|
|
|
{
|
2017-05-12 05:44:27 +00:00
|
|
|
for (const auto& listener : mListeners) {
|
|
|
|
listener->OnCompositorDeviceReset();
|
2016-11-06 19:01:52 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-06-11 02:37:03 +00:00
|
|
|
void
|
|
|
|
GPUProcessManager::OnProcessUnexpectedShutdown(GPUProcessHost* aHost)
|
|
|
|
{
|
|
|
|
MOZ_ASSERT(mProcess && mProcess == aHost);
|
|
|
|
|
2017-09-26 17:21:52 +00:00
|
|
|
CompositorManagerChild::OnGPUProcessLost(aHost->GetProcessToken());
|
2016-06-11 02:37:03 +00:00
|
|
|
DestroyProcess();
|
2016-09-20 08:16:03 +00:00
|
|
|
|
2017-01-17 07:51:24 +00:00
|
|
|
if (mNumProcessAttempts > uint32_t(gfxPrefs::GPUProcessMaxRestarts())) {
|
2016-11-11 22:51:25 +00:00
|
|
|
char disableMessage[64];
|
|
|
|
SprintfLiteral(disableMessage, "GPU process disabled after %d attempts",
|
|
|
|
mNumProcessAttempts);
|
|
|
|
DisableGPUProcess(disableMessage);
|
2017-04-14 21:36:42 +00:00
|
|
|
} else if (mNumProcessAttempts > uint32_t(gfxPrefs::GPUProcessMaxRestartsWithDecoder()) &&
|
|
|
|
mDecodeVideoOnGpuProcess) {
|
2017-04-14 21:34:01 +00:00
|
|
|
mDecodeVideoOnGpuProcess = false;
|
2017-04-14 21:36:42 +00:00
|
|
|
Telemetry::Accumulate(Telemetry::GPU_PROCESS_CRASH_FALLBACKS,
|
|
|
|
uint32_t(FallbackType::DECODINGDISABLED));
|
2017-07-20 13:20:22 +00:00
|
|
|
HandleProcessLost();
|
2017-04-14 21:36:42 +00:00
|
|
|
} else {
|
|
|
|
Telemetry::Accumulate(Telemetry::GPU_PROCESS_CRASH_FALLBACKS,
|
|
|
|
uint32_t(FallbackType::NONE));
|
2017-07-20 13:20:22 +00:00
|
|
|
HandleProcessLost();
|
2016-09-30 08:21:21 +00:00
|
|
|
}
|
2016-11-10 02:57:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
GPUProcessManager::HandleProcessLost()
|
|
|
|
{
|
2016-09-30 08:21:21 +00:00
|
|
|
if (gfxConfig::IsEnabled(Feature::GPU_PROCESS)) {
|
|
|
|
LaunchGPUProcess();
|
|
|
|
}
|
|
|
|
|
2016-09-20 08:18:50 +00:00
|
|
|
// The shutdown and restart sequence for the GPU process is as follows:
|
|
|
|
//
|
|
|
|
// (1) The GPU process dies. IPDL will enqueue an ActorDestroy message on
|
|
|
|
// each channel owning a bridge to the GPU process, on the thread
|
|
|
|
// owning that channel.
|
|
|
|
//
|
|
|
|
// (2) The first channel to process its ActorDestroy message will post a
|
|
|
|
// message to the main thread to call NotifyRemoteActorDestroyed on
|
|
|
|
// the GPUProcessManager, which calls OnProcessUnexpectedShutdown if
|
|
|
|
// it has not handled shutdown for this process yet.
|
|
|
|
//
|
|
|
|
// (3) We then notify each widget that its session with the compositor is
|
|
|
|
// now invalid. The widget is responsible for destroying its layer
|
|
|
|
// manager and CompositorBridgeChild. Note that at this stage, not
|
|
|
|
// all actors may have received ActorDestroy yet. CompositorBridgeChild
|
|
|
|
// may attempt to send messages, and if this happens, it will probably
|
|
|
|
// report a MsgDropped error. This is okay.
|
|
|
|
//
|
|
|
|
// (4) At this point, the UI process has a clean slate: no layers should
|
|
|
|
// exist for the old compositor. We may make a decision on whether or
|
|
|
|
// not to re-launch the GPU process. Currently, we do not relaunch it,
|
|
|
|
// and any new compositors will be created in-process and will default
|
|
|
|
// to software.
|
|
|
|
//
|
|
|
|
// (5) Next we notify each ContentParent of the lost connection. It will
|
|
|
|
// request new endpoints from the GPUProcessManager and forward them
|
|
|
|
// to its ContentChild. The parent-side of these endpoints may come
|
|
|
|
// from the compositor thread of the UI process, or the compositor
|
|
|
|
// thread of the GPU process. However, no actual compositors should
|
|
|
|
// exist yet.
|
|
|
|
//
|
|
|
|
// (6) Each ContentChild will receive new endpoints. It will destroy its
|
|
|
|
// Compositor/ImageBridgeChild singletons and recreate them, as well
|
|
|
|
// as invalidate all retained layers.
|
|
|
|
//
|
|
|
|
// (7) In addition, each ContentChild will ask each of its TabChildren
|
|
|
|
// to re-request association with the compositor for the window
|
|
|
|
// owning the tab. The sequence of calls looks like:
|
|
|
|
// (a) [CONTENT] ContentChild::RecvReinitRendering
|
|
|
|
// (b) [CONTENT] TabChild::ReinitRendering
|
|
|
|
// (c) [CONTENT] TabChild::SendEnsureLayersConnected
|
|
|
|
// (d) [UI] TabParent::RecvEnsureLayersConnected
|
|
|
|
// (e) [UI] RenderFrameParent::EnsureLayersConnected
|
|
|
|
// (f) [UI] CompositorBridgeChild::SendNotifyChildRecreated
|
|
|
|
//
|
|
|
|
// Note that at step (e), RenderFrameParent will call GetLayerManager
|
|
|
|
// on the nsIWidget owning the tab. This step ensures that a compositor
|
|
|
|
// exists for the window. If we decided to launch a new GPU Process,
|
|
|
|
// at this point we block until the process has launched and we're
|
|
|
|
// able to create a new window compositor. Otherwise, if compositing
|
|
|
|
// is now in-process, this will simply create a new
|
|
|
|
// CompositorBridgeParent in the UI process. If there are multiple tabs
|
|
|
|
// in the same window, additional tabs will simply return the already-
|
|
|
|
// established compositor.
|
|
|
|
//
|
|
|
|
// Finally, this step serves one other crucial function: tabs must be
|
|
|
|
// associated with a window compositor or else they can't forward
|
|
|
|
// layer transactions. So this step both ensures that a compositor
|
|
|
|
// exists, and that the tab can forward layers.
|
|
|
|
//
|
2017-06-15 18:34:00 +00:00
|
|
|
// (8) Last, if the window had no remote tabs, step (7) will not have
|
2016-09-20 08:18:50 +00:00
|
|
|
// applied, and the window will not have a new compositor just yet.
|
|
|
|
// The next refresh tick and paint will ensure that one exists, again
|
|
|
|
// via nsIWidget::GetLayerManager.
|
2017-05-12 05:44:27 +00:00
|
|
|
RebuildRemoteSessions();
|
|
|
|
|
|
|
|
// Notify content. This will ensure that each content process re-establishes
|
|
|
|
// a connection to the compositor thread (whether it's in-process or in a
|
|
|
|
// newly launched GPU process).
|
|
|
|
for (const auto& listener : mListeners) {
|
|
|
|
listener->OnCompositorUnexpectedShutdown();
|
|
|
|
}
|
|
|
|
}
|
2016-09-20 08:18:50 +00:00
|
|
|
|
2017-05-12 05:44:27 +00:00
|
|
|
void
|
|
|
|
GPUProcessManager::RebuildRemoteSessions()
|
|
|
|
{
|
2016-09-20 08:16:03 +00:00
|
|
|
// Build a list of sessions to notify, since notification might delete
|
|
|
|
// entries from the list.
|
|
|
|
nsTArray<RefPtr<RemoteCompositorSession>> sessions;
|
|
|
|
for (auto& session : mRemoteSessions) {
|
|
|
|
sessions.AppendElement(session);
|
|
|
|
}
|
|
|
|
|
2016-09-20 08:18:50 +00:00
|
|
|
// Notify each widget that we have lost the GPU process. This will ensure
|
|
|
|
// that each widget destroys its layer manager and CompositorBridgeChild.
|
2016-09-20 08:16:03 +00:00
|
|
|
for (const auto& session : sessions) {
|
|
|
|
session->NotifySessionLost();
|
|
|
|
}
|
2016-06-11 02:37:03 +00:00
|
|
|
}
|
|
|
|
|
2017-06-15 18:34:00 +00:00
|
|
|
void
|
|
|
|
GPUProcessManager::RebuildInProcessSessions()
|
|
|
|
{
|
|
|
|
// Build a list of sessions to notify, since notification might delete
|
|
|
|
// entries from the list.
|
|
|
|
nsTArray<RefPtr<InProcessCompositorSession>> sessions;
|
|
|
|
for (auto& session : mInProcessSessions) {
|
|
|
|
sessions.AppendElement(session);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Notify each widget that we have lost the GPU process. This will ensure
|
|
|
|
// that each widget destroys its layer manager and CompositorBridgeChild.
|
|
|
|
for (const auto& session : sessions) {
|
|
|
|
session->NotifySessionLost();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-07-18 04:24:28 +00:00
|
|
|
void
|
|
|
|
GPUProcessManager::NotifyRemoteActorDestroyed(const uint64_t& aProcessToken)
|
|
|
|
{
|
|
|
|
if (!NS_IsMainThread()) {
|
|
|
|
RefPtr<Runnable> task = mTaskFactory.NewRunnableMethod(
|
|
|
|
&GPUProcessManager::NotifyRemoteActorDestroyed, aProcessToken);
|
|
|
|
NS_DispatchToMainThread(task.forget());
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mProcessToken != aProcessToken) {
|
|
|
|
// This token is for an older process; we can safely ignore it.
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// One of the bridged top-level actors for the GPU process has been
|
|
|
|
// prematurely terminated, and we're receiving a notification. This
|
|
|
|
// can happen if the ActorDestroy for a bridged protocol fires
|
|
|
|
// before the ActorDestroy for PGPUChild.
|
2016-09-20 08:16:03 +00:00
|
|
|
OnProcessUnexpectedShutdown(mProcess);
|
2016-07-18 04:24:28 +00:00
|
|
|
}
|
|
|
|
|
2016-07-19 18:56:06 +00:00
|
|
|
void
|
|
|
|
GPUProcessManager::CleanShutdown()
|
|
|
|
{
|
|
|
|
DestroyProcess();
|
2016-10-07 07:07:10 +00:00
|
|
|
mVsyncIOThread = nullptr;
|
2016-07-19 18:56:06 +00:00
|
|
|
}
|
|
|
|
|
2016-10-31 19:44:40 +00:00
|
|
|
void
|
|
|
|
GPUProcessManager::KillProcess()
|
|
|
|
{
|
|
|
|
if (!mProcess) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
mProcess->KillProcess();
|
|
|
|
}
|
|
|
|
|
2016-06-11 02:27:24 +00:00
|
|
|
void
|
|
|
|
GPUProcessManager::DestroyProcess()
|
|
|
|
{
|
|
|
|
if (!mProcess) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
mProcess->Shutdown();
|
2016-07-18 04:24:28 +00:00
|
|
|
mProcessToken = 0;
|
2016-06-11 02:27:24 +00:00
|
|
|
mProcess = nullptr;
|
|
|
|
mGPUChild = nullptr;
|
2016-11-02 23:45:38 +00:00
|
|
|
if (mVsyncBridge) {
|
|
|
|
mVsyncBridge->Close();
|
|
|
|
mVsyncBridge = nullptr;
|
|
|
|
}
|
2017-04-03 22:11:27 +00:00
|
|
|
|
2017-11-22 22:11:44 +00:00
|
|
|
#ifdef MOZ_CRASHREPORTER
|
2017-04-03 22:11:27 +00:00
|
|
|
CrashReporter::AnnotateCrashReport(
|
|
|
|
NS_LITERAL_CSTRING("GPUProcessStatus"),
|
|
|
|
NS_LITERAL_CSTRING("Destroyed"));
|
2017-11-22 22:11:44 +00:00
|
|
|
#endif
|
2016-05-23 07:27:01 +00:00
|
|
|
}
|
|
|
|
|
2017-07-20 13:20:22 +00:00
|
|
|
already_AddRefed<CompositorSession>
|
2016-07-19 18:56:07 +00:00
|
|
|
GPUProcessManager::CreateTopLevelCompositor(nsBaseWidget* aWidget,
|
2016-11-08 15:42:19 +00:00
|
|
|
LayerManager* aLayerManager,
|
2016-05-23 07:27:01 +00:00
|
|
|
CSSToLayoutDeviceScale aScale,
|
2017-01-12 22:29:41 +00:00
|
|
|
const CompositorOptions& aOptions,
|
2016-05-23 07:27:01 +00:00
|
|
|
bool aUseExternalSurfaceSize,
|
2017-07-20 13:20:22 +00:00
|
|
|
const gfx::IntSize& aSurfaceSize,
|
|
|
|
bool* aRetryOut)
|
2016-05-23 07:27:01 +00:00
|
|
|
{
|
2017-07-20 13:20:22 +00:00
|
|
|
MOZ_ASSERT(aRetryOut);
|
|
|
|
|
2016-07-18 04:24:27 +00:00
|
|
|
uint64_t layerTreeId = AllocateLayerTreeId();
|
|
|
|
|
2017-06-28 18:31:42 +00:00
|
|
|
EnsureProtocolsReady();
|
2017-04-05 22:42:50 +00:00
|
|
|
|
|
|
|
RefPtr<CompositorSession> session;
|
2016-07-20 07:17:28 +00:00
|
|
|
|
2017-03-30 01:23:24 +00:00
|
|
|
if (EnsureGPUReady()) {
|
2017-04-05 22:42:50 +00:00
|
|
|
session = CreateRemoteSession(
|
2016-07-18 04:24:28 +00:00
|
|
|
aWidget,
|
|
|
|
aLayerManager,
|
|
|
|
layerTreeId,
|
|
|
|
aScale,
|
2017-01-12 22:29:41 +00:00
|
|
|
aOptions,
|
2016-07-18 04:24:28 +00:00
|
|
|
aUseExternalSurfaceSize,
|
|
|
|
aSurfaceSize);
|
2017-04-05 22:42:50 +00:00
|
|
|
if (!session) {
|
|
|
|
// We couldn't create a remote compositor, so abort the process.
|
|
|
|
DisableGPUProcess("Failed to create remote compositor");
|
2017-07-20 13:20:22 +00:00
|
|
|
*aRetryOut = true;
|
|
|
|
return nullptr;
|
2016-07-18 04:24:28 +00:00
|
|
|
}
|
2017-07-20 13:20:22 +00:00
|
|
|
} else {
|
2017-04-05 22:42:50 +00:00
|
|
|
session = InProcessCompositorSession::Create(
|
|
|
|
aWidget,
|
|
|
|
aLayerManager,
|
|
|
|
layerTreeId,
|
|
|
|
aScale,
|
|
|
|
aOptions,
|
|
|
|
aUseExternalSurfaceSize,
|
|
|
|
aSurfaceSize,
|
|
|
|
AllocateNamespace());
|
2016-07-18 04:24:28 +00:00
|
|
|
}
|
|
|
|
|
2017-04-05 22:42:50 +00:00
|
|
|
#if defined(MOZ_WIDGET_ANDROID)
|
|
|
|
if (session) {
|
|
|
|
// Nothing to do if controller gets a nullptr
|
|
|
|
RefPtr<UiCompositorControllerChild> controller = CreateUiCompositorController(aWidget, session->RootLayerTreeId());
|
|
|
|
session->SetUiCompositorControllerChild(controller);
|
|
|
|
}
|
|
|
|
#endif // defined(MOZ_WIDGET_ANDROID)
|
|
|
|
|
2017-07-20 13:20:22 +00:00
|
|
|
*aRetryOut = false;
|
|
|
|
return session.forget();
|
2016-05-23 07:27:01 +00:00
|
|
|
}
|
|
|
|
|
2016-07-18 04:24:28 +00:00
|
|
|
RefPtr<CompositorSession>
|
2016-07-19 18:56:07 +00:00
|
|
|
GPUProcessManager::CreateRemoteSession(nsBaseWidget* aWidget,
|
2016-11-08 15:42:19 +00:00
|
|
|
LayerManager* aLayerManager,
|
2016-07-18 04:24:28 +00:00
|
|
|
const uint64_t& aRootLayerTreeId,
|
|
|
|
CSSToLayoutDeviceScale aScale,
|
2017-01-12 22:29:41 +00:00
|
|
|
const CompositorOptions& aOptions,
|
2016-07-18 04:24:28 +00:00
|
|
|
bool aUseExternalSurfaceSize,
|
|
|
|
const gfx::IntSize& aSurfaceSize)
|
|
|
|
{
|
|
|
|
#ifdef MOZ_WIDGET_SUPPORTS_OOP_COMPOSITING
|
2017-06-13 19:45:03 +00:00
|
|
|
CompositorWidgetInitData initData;
|
|
|
|
aWidget->GetCompositorWidgetInitData(&initData);
|
|
|
|
|
2017-06-14 15:39:59 +00:00
|
|
|
RefPtr<CompositorBridgeChild> child =
|
|
|
|
CompositorManagerChild::CreateWidgetCompositorBridge(
|
|
|
|
mProcessToken,
|
|
|
|
aLayerManager,
|
|
|
|
AllocateNamespace(),
|
|
|
|
aScale,
|
|
|
|
aOptions,
|
|
|
|
aUseExternalSurfaceSize,
|
|
|
|
aSurfaceSize);
|
|
|
|
if (!child) {
|
|
|
|
gfxCriticalNote << "Failed to create CompositorBridgeChild";
|
2017-06-13 19:45:03 +00:00
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2016-07-19 18:56:07 +00:00
|
|
|
RefPtr<CompositorVsyncDispatcher> dispatcher = aWidget->GetCompositorVsyncDispatcher();
|
|
|
|
RefPtr<CompositorWidgetVsyncObserver> observer =
|
|
|
|
new CompositorWidgetVsyncObserver(mVsyncBridge, aRootLayerTreeId);
|
|
|
|
|
|
|
|
CompositorWidgetChild* widget = new CompositorWidgetChild(dispatcher, observer);
|
2016-07-20 07:19:27 +00:00
|
|
|
if (!child->SendPCompositorWidgetConstructor(widget, initData)) {
|
2016-07-18 04:24:28 +00:00
|
|
|
return nullptr;
|
2016-07-20 07:19:27 +00:00
|
|
|
}
|
|
|
|
if (!child->SendInitialize(aRootLayerTreeId)) {
|
2016-07-18 04:24:28 +00:00
|
|
|
return nullptr;
|
2016-07-20 07:19:27 +00:00
|
|
|
}
|
2016-07-18 04:24:28 +00:00
|
|
|
|
2016-08-29 13:18:00 +00:00
|
|
|
RefPtr<APZCTreeManagerChild> apz = nullptr;
|
2017-01-12 22:29:41 +00:00
|
|
|
if (aOptions.UseAPZ()) {
|
2016-08-29 13:18:00 +00:00
|
|
|
PAPZCTreeManagerChild* papz = child->SendPAPZCTreeManagerConstructor(0);
|
|
|
|
if (!papz) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
apz = static_cast<APZCTreeManagerChild*>(papz);
|
|
|
|
}
|
|
|
|
|
2016-07-18 04:24:28 +00:00
|
|
|
RefPtr<RemoteCompositorSession> session =
|
2016-09-20 08:16:03 +00:00
|
|
|
new RemoteCompositorSession(aWidget, child, widget, apz, aRootLayerTreeId);
|
2016-07-18 04:24:28 +00:00
|
|
|
return session.forget();
|
|
|
|
#else
|
|
|
|
gfxCriticalNote << "Platform does not support out-of-process compositing";
|
|
|
|
return nullptr;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2016-09-20 08:15:49 +00:00
|
|
|
bool
|
|
|
|
GPUProcessManager::CreateContentBridges(base::ProcessId aOtherProcess,
|
2017-06-14 15:39:59 +00:00
|
|
|
ipc::Endpoint<PCompositorManagerChild>* aOutCompositor,
|
2016-09-20 08:15:49 +00:00
|
|
|
ipc::Endpoint<PImageBridgeChild>* aOutImageBridge,
|
2016-11-08 02:21:35 +00:00
|
|
|
ipc::Endpoint<PVRManagerChild>* aOutVRBridge,
|
2017-04-14 08:06:09 +00:00
|
|
|
ipc::Endpoint<dom::PVideoDecoderManagerChild>* aOutVideoManager,
|
|
|
|
nsTArray<uint32_t>* aNamespaces)
|
2016-09-20 08:15:49 +00:00
|
|
|
{
|
2017-06-14 15:39:59 +00:00
|
|
|
if (!CreateContentCompositorManager(aOtherProcess, aOutCompositor) ||
|
2016-09-20 08:15:49 +00:00
|
|
|
!CreateContentImageBridge(aOtherProcess, aOutImageBridge) ||
|
|
|
|
!CreateContentVRManager(aOtherProcess, aOutVRBridge))
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
2016-11-08 02:21:35 +00:00
|
|
|
// VideoDeocderManager is only supported in the GPU process, so we allow this to be
|
|
|
|
// fallible.
|
|
|
|
CreateContentVideoDecoderManager(aOtherProcess, aOutVideoManager);
|
2017-06-14 15:39:59 +00:00
|
|
|
// Allocates 3 namespaces(for CompositorManagerChild, CompositorBridgeChild and ImageBridgeChild)
|
|
|
|
aNamespaces->AppendElement(AllocateNamespace());
|
2017-04-14 08:06:09 +00:00
|
|
|
aNamespaces->AppendElement(AllocateNamespace());
|
|
|
|
aNamespaces->AppendElement(AllocateNamespace());
|
2016-09-20 08:15:49 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2016-07-18 04:24:28 +00:00
|
|
|
bool
|
2017-06-14 15:39:59 +00:00
|
|
|
GPUProcessManager::CreateContentCompositorManager(base::ProcessId aOtherProcess,
|
|
|
|
ipc::Endpoint<PCompositorManagerChild>* aOutEndpoint)
|
2016-05-23 07:28:51 +00:00
|
|
|
{
|
2017-06-14 15:39:59 +00:00
|
|
|
ipc::Endpoint<PCompositorManagerParent> parentPipe;
|
|
|
|
ipc::Endpoint<PCompositorManagerChild> childPipe;
|
2016-07-18 04:24:28 +00:00
|
|
|
|
2017-06-29 18:35:45 +00:00
|
|
|
base::ProcessId parentPid = EnsureGPUReady()
|
|
|
|
? mGPUChild->OtherPid()
|
|
|
|
: base::GetCurrentProcId();
|
2016-07-18 04:24:28 +00:00
|
|
|
|
2017-06-14 15:39:59 +00:00
|
|
|
nsresult rv = PCompositorManager::CreateEndpoints(
|
2017-06-29 18:35:45 +00:00
|
|
|
parentPid,
|
2016-07-18 04:24:28 +00:00
|
|
|
aOtherProcess,
|
|
|
|
&parentPipe,
|
|
|
|
&childPipe);
|
|
|
|
if (NS_FAILED(rv)) {
|
2017-06-14 15:39:59 +00:00
|
|
|
gfxCriticalNote << "Could not create content compositor manager: " << hexa(int(rv));
|
2016-07-18 04:24:28 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2017-06-29 18:35:45 +00:00
|
|
|
if (mGPUChild) {
|
2017-06-14 15:39:59 +00:00
|
|
|
mGPUChild->SendNewContentCompositorManager(Move(parentPipe));
|
2016-07-18 04:24:28 +00:00
|
|
|
} else {
|
2017-06-14 15:39:59 +00:00
|
|
|
CompositorManagerParent::Create(Move(parentPipe));
|
2016-07-18 04:24:28 +00:00
|
|
|
}
|
2016-07-18 04:24:28 +00:00
|
|
|
|
|
|
|
*aOutEndpoint = Move(childPipe);
|
|
|
|
return true;
|
2016-05-23 07:28:51 +00:00
|
|
|
}
|
|
|
|
|
2016-07-20 07:18:30 +00:00
|
|
|
bool
|
|
|
|
GPUProcessManager::CreateContentImageBridge(base::ProcessId aOtherProcess,
|
|
|
|
ipc::Endpoint<PImageBridgeChild>* aOutEndpoint)
|
|
|
|
{
|
|
|
|
EnsureImageBridgeChild();
|
|
|
|
|
2017-06-29 18:35:45 +00:00
|
|
|
base::ProcessId parentPid = EnsureGPUReady()
|
|
|
|
? mGPUChild->OtherPid()
|
|
|
|
: base::GetCurrentProcId();
|
2016-07-20 07:18:30 +00:00
|
|
|
|
|
|
|
ipc::Endpoint<PImageBridgeParent> parentPipe;
|
|
|
|
ipc::Endpoint<PImageBridgeChild> childPipe;
|
|
|
|
nsresult rv = PImageBridge::CreateEndpoints(
|
2017-06-29 18:35:45 +00:00
|
|
|
parentPid,
|
2016-07-20 07:18:30 +00:00
|
|
|
aOtherProcess,
|
|
|
|
&parentPipe,
|
|
|
|
&childPipe);
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
gfxCriticalNote << "Could not create content compositor bridge: " << hexa(int(rv));
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2017-06-29 18:35:45 +00:00
|
|
|
if (mGPUChild) {
|
2016-07-20 07:19:27 +00:00
|
|
|
mGPUChild->SendNewContentImageBridge(Move(parentPipe));
|
|
|
|
} else {
|
|
|
|
if (!ImageBridgeParent::CreateForContent(Move(parentPipe))) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
2016-07-20 07:18:30 +00:00
|
|
|
|
|
|
|
*aOutEndpoint = Move(childPipe);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2016-10-31 19:44:40 +00:00
|
|
|
base::ProcessId
|
|
|
|
GPUProcessManager::GPUProcessPid()
|
|
|
|
{
|
|
|
|
base::ProcessId gpuPid = mGPUChild
|
|
|
|
? mGPUChild->OtherPid()
|
|
|
|
: -1;
|
|
|
|
return gpuPid;
|
|
|
|
}
|
|
|
|
|
2016-07-21 07:14:59 +00:00
|
|
|
bool
|
|
|
|
GPUProcessManager::CreateContentVRManager(base::ProcessId aOtherProcess,
|
|
|
|
ipc::Endpoint<PVRManagerChild>* aOutEndpoint)
|
|
|
|
{
|
2016-07-21 07:14:59 +00:00
|
|
|
EnsureVRManager();
|
|
|
|
|
2017-06-29 18:35:45 +00:00
|
|
|
base::ProcessId parentPid = EnsureGPUReady()
|
|
|
|
? mGPUChild->OtherPid()
|
|
|
|
: base::GetCurrentProcId();
|
2016-07-21 07:14:59 +00:00
|
|
|
|
|
|
|
ipc::Endpoint<PVRManagerParent> parentPipe;
|
|
|
|
ipc::Endpoint<PVRManagerChild> childPipe;
|
|
|
|
nsresult rv = PVRManager::CreateEndpoints(
|
2017-06-29 18:35:45 +00:00
|
|
|
parentPid,
|
2016-07-21 07:14:59 +00:00
|
|
|
aOtherProcess,
|
|
|
|
&parentPipe,
|
|
|
|
&childPipe);
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
gfxCriticalNote << "Could not create content compositor bridge: " << hexa(int(rv));
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2017-06-29 18:35:45 +00:00
|
|
|
if (mGPUChild) {
|
2016-07-21 07:14:59 +00:00
|
|
|
mGPUChild->SendNewContentVRManager(Move(parentPipe));
|
|
|
|
} else {
|
|
|
|
if (!VRManagerParent::CreateForContent(Move(parentPipe))) {
|
|
|
|
return false;
|
|
|
|
}
|
2016-07-21 07:14:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
*aOutEndpoint = Move(childPipe);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2016-11-08 02:21:35 +00:00
|
|
|
void
|
2016-09-21 09:25:33 +00:00
|
|
|
GPUProcessManager::CreateContentVideoDecoderManager(base::ProcessId aOtherProcess,
|
|
|
|
ipc::Endpoint<dom::PVideoDecoderManagerChild>* aOutEndpoint)
|
|
|
|
{
|
2017-04-14 21:34:01 +00:00
|
|
|
if (!EnsureGPUReady() ||
|
|
|
|
!MediaPrefs::PDMUseGPUDecoder() ||
|
|
|
|
!mDecodeVideoOnGpuProcess) {
|
2016-11-08 02:21:35 +00:00
|
|
|
return;
|
2016-09-21 09:25:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ipc::Endpoint<dom::PVideoDecoderManagerParent> parentPipe;
|
|
|
|
ipc::Endpoint<dom::PVideoDecoderManagerChild> childPipe;
|
|
|
|
|
|
|
|
nsresult rv = dom::PVideoDecoderManager::CreateEndpoints(
|
|
|
|
mGPUChild->OtherPid(),
|
|
|
|
aOtherProcess,
|
|
|
|
&parentPipe,
|
|
|
|
&childPipe);
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
gfxCriticalNote << "Could not create content video decoder: " << hexa(int(rv));
|
2016-11-08 02:21:35 +00:00
|
|
|
return;
|
2016-09-21 09:25:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
mGPUChild->SendNewContentVideoDecoderManager(Move(parentPipe));
|
|
|
|
|
|
|
|
*aOutEndpoint = Move(childPipe);
|
|
|
|
}
|
|
|
|
|
2016-07-20 11:37:00 +00:00
|
|
|
already_AddRefed<IAPZCTreeManager>
|
2016-05-23 07:27:51 +00:00
|
|
|
GPUProcessManager::GetAPZCTreeManagerForLayers(uint64_t aLayersId)
|
|
|
|
{
|
|
|
|
return CompositorBridgeParent::GetAPZCTreeManager(aLayersId);
|
|
|
|
}
|
|
|
|
|
2016-08-16 20:59:13 +00:00
|
|
|
void
|
|
|
|
GPUProcessManager::MapLayerTreeId(uint64_t aLayersId, base::ProcessId aOwningId)
|
|
|
|
{
|
|
|
|
LayerTreeOwnerTracker::Get()->Map(aLayersId, aOwningId);
|
|
|
|
|
2017-03-30 01:23:24 +00:00
|
|
|
if (EnsureGPUReady()) {
|
2017-04-03 22:13:38 +00:00
|
|
|
mGPUChild->SendAddLayerTreeIdMapping(LayerTreeIdMapping(aLayersId, aOwningId));
|
2016-11-02 20:55:07 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
GPUProcessManager::UnmapLayerTreeId(uint64_t aLayersId, base::ProcessId aOwningId)
|
|
|
|
{
|
|
|
|
LayerTreeOwnerTracker::Get()->Unmap(aLayersId, aOwningId);
|
|
|
|
|
2017-03-30 01:23:24 +00:00
|
|
|
if (EnsureGPUReady()) {
|
2016-11-02 20:55:07 +00:00
|
|
|
mGPUChild->SendRemoveLayerTreeIdMapping(LayerTreeIdMapping(aLayersId, aOwningId));
|
|
|
|
return;
|
2016-08-16 20:59:13 +00:00
|
|
|
}
|
2016-11-02 20:55:07 +00:00
|
|
|
CompositorBridgeParent::DeallocateLayerTreeId(aLayersId);
|
2016-08-16 20:59:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
GPUProcessManager::IsLayerTreeIdMapped(uint64_t aLayersId, base::ProcessId aRequestingId)
|
|
|
|
{
|
|
|
|
return LayerTreeOwnerTracker::Get()->IsMapped(aLayersId, aRequestingId);
|
|
|
|
}
|
|
|
|
|
2016-05-23 07:27:57 +00:00
|
|
|
uint64_t
|
|
|
|
GPUProcessManager::AllocateLayerTreeId()
|
|
|
|
{
|
2017-05-30 00:59:44 +00:00
|
|
|
// Allocate tree id by using id namespace.
|
|
|
|
// By it, tree id does not conflict with external image id and
|
|
|
|
// async image pipeline id.
|
2016-07-18 04:24:27 +00:00
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
2017-05-30 00:59:44 +00:00
|
|
|
++mResourceId;
|
|
|
|
if (mResourceId == UINT32_MAX) {
|
|
|
|
// Move to next id namespace.
|
|
|
|
mIdNamespace = AllocateNamespace();
|
|
|
|
mResourceId = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint64_t layerTreeId = mIdNamespace;
|
|
|
|
layerTreeId = (layerTreeId << 32) | mResourceId;
|
|
|
|
return layerTreeId;
|
2016-05-23 07:27:57 +00:00
|
|
|
}
|
|
|
|
|
2017-04-14 08:06:09 +00:00
|
|
|
uint32_t
|
|
|
|
GPUProcessManager::AllocateNamespace()
|
|
|
|
{
|
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
|
|
|
return ++mNextNamespace;
|
|
|
|
}
|
|
|
|
|
2017-04-03 22:13:37 +00:00
|
|
|
bool
|
|
|
|
GPUProcessManager::AllocateAndConnectLayerTreeId(PCompositorBridgeChild* aCompositorBridge,
|
|
|
|
base::ProcessId aOtherPid,
|
2017-04-09 21:30:27 +00:00
|
|
|
uint64_t* aOutLayersId,
|
|
|
|
CompositorOptions* aOutCompositorOptions)
|
2017-04-03 22:13:37 +00:00
|
|
|
{
|
|
|
|
uint64_t layersId = AllocateLayerTreeId();
|
|
|
|
*aOutLayersId = layersId;
|
|
|
|
|
|
|
|
if (!mGPUChild || !aCompositorBridge) {
|
|
|
|
// If we're not remoting to another process, or there is no compositor,
|
|
|
|
// then we'll send at most one message. In this case we can just keep
|
|
|
|
// the old behavior of making sure the mapping occurs, and maybe sending
|
|
|
|
// a creation notification.
|
|
|
|
MapLayerTreeId(layersId, aOtherPid);
|
|
|
|
if (!aCompositorBridge) {
|
|
|
|
return false;
|
|
|
|
}
|
2017-04-09 21:30:27 +00:00
|
|
|
return aCompositorBridge->SendNotifyChildCreated(layersId, aOutCompositorOptions);
|
2017-04-03 22:13:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Use the combined message path.
|
|
|
|
LayerTreeOwnerTracker::Get()->Map(layersId, aOtherPid);
|
2017-04-09 21:30:27 +00:00
|
|
|
return aCompositorBridge->SendMapAndNotifyChildCreated(layersId, aOtherPid, aOutCompositorOptions);
|
2017-04-03 22:13:37 +00:00
|
|
|
}
|
|
|
|
|
2016-07-19 18:56:06 +00:00
|
|
|
void
|
|
|
|
GPUProcessManager::EnsureVsyncIOThread()
|
|
|
|
{
|
|
|
|
if (mVsyncIOThread) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
mVsyncIOThread = new VsyncIOThreadHolder();
|
|
|
|
MOZ_RELEASE_ASSERT(mVsyncIOThread->Start());
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
GPUProcessManager::ShutdownVsyncIOThread()
|
|
|
|
{
|
|
|
|
mVsyncIOThread = nullptr;
|
|
|
|
}
|
|
|
|
|
2016-09-20 08:16:03 +00:00
|
|
|
void
|
2017-06-15 18:34:00 +00:00
|
|
|
GPUProcessManager::RegisterRemoteProcessSession(RemoteCompositorSession* aSession)
|
2016-09-20 08:16:03 +00:00
|
|
|
{
|
|
|
|
mRemoteSessions.AppendElement(aSession);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-06-15 18:34:00 +00:00
|
|
|
GPUProcessManager::UnregisterRemoteProcessSession(RemoteCompositorSession* aSession)
|
2016-09-20 08:16:03 +00:00
|
|
|
{
|
|
|
|
mRemoteSessions.RemoveElement(aSession);
|
|
|
|
}
|
|
|
|
|
2017-06-15 18:34:00 +00:00
|
|
|
void
|
|
|
|
GPUProcessManager::RegisterInProcessSession(InProcessCompositorSession* aSession)
|
|
|
|
{
|
|
|
|
mInProcessSessions.AppendElement(aSession);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
GPUProcessManager::UnregisterInProcessSession(InProcessCompositorSession* aSession)
|
|
|
|
{
|
|
|
|
mInProcessSessions.RemoveElement(aSession);
|
|
|
|
}
|
|
|
|
|
2016-09-20 08:18:50 +00:00
|
|
|
void
|
|
|
|
GPUProcessManager::AddListener(GPUProcessListener* aListener)
|
|
|
|
{
|
|
|
|
mListeners.AppendElement(aListener);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
GPUProcessManager::RemoveListener(GPUProcessListener* aListener)
|
|
|
|
{
|
|
|
|
mListeners.RemoveElement(aListener);
|
|
|
|
}
|
|
|
|
|
2016-10-15 12:45:02 +00:00
|
|
|
bool
|
|
|
|
GPUProcessManager::NotifyGpuObservers(const char* aTopic)
|
|
|
|
{
|
2017-03-30 01:23:24 +00:00
|
|
|
if (!EnsureGPUReady()) {
|
2016-10-15 12:45:02 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
nsCString topic(aTopic);
|
|
|
|
mGPUChild->SendNotifyGpuObservers(topic);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2017-01-27 00:35:54 +00:00
|
|
|
class GPUMemoryReporter : public MemoryReportingProcess
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(GPUMemoryReporter, override)
|
|
|
|
|
|
|
|
bool IsAlive() const override {
|
|
|
|
if (GPUProcessManager* gpm = GPUProcessManager::Get()) {
|
|
|
|
return !!gpm->GetGPUChild();
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SendRequestMemoryReport(const uint32_t& aGeneration,
|
|
|
|
const bool& aAnonymize,
|
|
|
|
const bool& aMinimizeMemoryUsage,
|
|
|
|
const dom::MaybeFileDesc& aDMDFile) override
|
|
|
|
{
|
|
|
|
GPUChild* child = GetChild();
|
|
|
|
if (!child) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return child->SendRequestMemoryReport(
|
|
|
|
aGeneration, aAnonymize, aMinimizeMemoryUsage, aDMDFile);
|
|
|
|
}
|
|
|
|
|
|
|
|
int32_t Pid() const override {
|
|
|
|
if (GPUChild* child = GetChild()) {
|
|
|
|
return (int32_t)child->OtherPid();
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
GPUChild* GetChild() const {
|
|
|
|
if (GPUProcessManager* gpm = GPUProcessManager::Get()) {
|
|
|
|
if (GPUChild* child = gpm->GetGPUChild()) {
|
|
|
|
return child;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
protected:
|
|
|
|
~GPUMemoryReporter() = default;
|
|
|
|
};
|
|
|
|
|
|
|
|
RefPtr<MemoryReportingProcess>
|
|
|
|
GPUProcessManager::GetProcessMemoryReporter()
|
|
|
|
{
|
2017-03-30 01:23:24 +00:00
|
|
|
if (!EnsureGPUReady()) {
|
2017-01-27 00:35:54 +00:00
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
return new GPUMemoryReporter();
|
|
|
|
}
|
|
|
|
|
2016-05-23 07:27:01 +00:00
|
|
|
} // namespace gfx
|
|
|
|
} // namespace mozilla
|