Bug 1769952 - Fix running raptor on a Win10-64 VM r=sparky
[gecko.git] / gfx / ipc / GPUProcessManager.cpp
blob8ce0395e39387481e89667f2389b8765c364e566
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "GPUProcessManager.h"
9 #include "gfxConfig.h"
10 #include "gfxPlatform.h"
11 #include "GPUProcessHost.h"
12 #include "GPUProcessListener.h"
13 #include "mozilla/AppShutdown.h"
14 #include "mozilla/MemoryReportingProcess.h"
15 #include "mozilla/Preferences.h"
16 #include "mozilla/Sprintf.h"
17 #include "mozilla/StaticPtr.h"
18 #include "mozilla/StaticPrefs_gfx.h"
19 #include "mozilla/StaticPrefs_layers.h"
20 #include "mozilla/StaticPrefs_media.h"
21 #include "mozilla/RemoteDecoderManagerChild.h"
22 #include "mozilla/RemoteDecoderManagerParent.h"
23 #include "mozilla/Telemetry.h"
24 #include "mozilla/dom/ContentParent.h"
25 #include "mozilla/gfx/gfxVars.h"
26 #include "mozilla/gfx/GPUChild.h"
27 #include "mozilla/ipc/Endpoint.h"
28 #include "mozilla/ipc/ProcessChild.h"
29 #include "mozilla/layers/APZCTreeManagerChild.h"
30 #include "mozilla/layers/APZInputBridgeChild.h"
31 #include "mozilla/layers/CompositorBridgeChild.h"
32 #include "mozilla/layers/CompositorBridgeParent.h"
33 #include "mozilla/layers/CompositorManagerChild.h"
34 #include "mozilla/layers/CompositorManagerParent.h"
35 #include "mozilla/layers/CompositorOptions.h"
36 #include "mozilla/layers/ImageBridgeChild.h"
37 #include "mozilla/layers/ImageBridgeParent.h"
38 #include "mozilla/layers/InProcessCompositorSession.h"
39 #include "mozilla/layers/LayerTreeOwnerTracker.h"
40 #include "mozilla/layers/RemoteCompositorSession.h"
41 #include "mozilla/webrender/RenderThread.h"
42 #include "mozilla/widget/PlatformWidgetTypes.h"
43 #include "nsAppRunner.h"
44 #include "mozilla/widget/CompositorWidget.h"
45 #ifdef MOZ_WIDGET_SUPPORTS_OOP_COMPOSITING
46 # include "mozilla/widget/CompositorWidgetChild.h"
47 #endif
48 #include "nsBaseWidget.h"
49 #include "nsContentUtils.h"
50 #include "VRManagerChild.h"
51 #include "VRManagerParent.h"
52 #include "VsyncBridgeChild.h"
53 #include "VsyncIOThreadHolder.h"
54 #include "VsyncSource.h"
55 #include "nsExceptionHandler.h"
56 #include "nsPrintfCString.h"
58 #if defined(MOZ_WIDGET_ANDROID)
59 # include "mozilla/widget/AndroidUiThread.h"
60 # include "mozilla/layers/UiCompositorControllerChild.h"
61 #endif // defined(MOZ_WIDGET_ANDROID)
63 #if defined(XP_WIN)
64 # include "gfxWindowsPlatform.h"
65 #endif
67 namespace mozilla {
68 namespace gfx {
70 using namespace mozilla::layers;
72 enum class FallbackType : uint32_t {
73 NONE = 0,
74 DECODINGDISABLED,
75 DISABLED,
78 static StaticAutoPtr<GPUProcessManager> sSingleton;
80 GPUProcessManager* GPUProcessManager::Get() { return sSingleton; }
82 void GPUProcessManager::Initialize() {
83 MOZ_ASSERT(XRE_IsParentProcess());
84 sSingleton = new GPUProcessManager();
87 void GPUProcessManager::Shutdown() { sSingleton = nullptr; }
89 GPUProcessManager::GPUProcessManager()
90 : mTaskFactory(this),
91 mNextNamespace(0),
92 mIdNamespace(0),
93 mResourceId(0),
94 mUnstableProcessAttempts(0),
95 mTotalProcessAttempts(0),
96 mDeviceResetCount(0),
97 mAppInForeground(true),
98 mProcess(nullptr),
99 mProcessToken(0),
100 mProcessStable(true),
101 mGPUChild(nullptr) {
102 MOZ_COUNT_CTOR(GPUProcessManager);
104 mIdNamespace = AllocateNamespace();
106 mDeviceResetLastTime = TimeStamp::Now();
108 LayerTreeOwnerTracker::Initialize();
109 CompositorBridgeParent::InitializeStatics();
112 GPUProcessManager::~GPUProcessManager() {
113 MOZ_COUNT_DTOR(GPUProcessManager);
115 LayerTreeOwnerTracker::Shutdown();
117 // The GPU process should have already been shut down.
118 MOZ_ASSERT(!mProcess && !mGPUChild);
120 // We should have already removed observers.
121 MOZ_ASSERT(!mObserver);
124 NS_IMPL_ISUPPORTS(GPUProcessManager::Observer, nsIObserver);
126 GPUProcessManager::Observer::Observer(GPUProcessManager* aManager)
127 : mManager(aManager) {}
129 NS_IMETHODIMP
130 GPUProcessManager::Observer::Observe(nsISupports* aSubject, const char* aTopic,
131 const char16_t* aData) {
132 if (!strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID)) {
133 mManager->OnXPCOMShutdown();
134 } else if (!strcmp(aTopic, "nsPref:changed")) {
135 mManager->OnPreferenceChange(aData);
136 } else if (!strcmp(aTopic, "application-foreground")) {
137 mManager->mAppInForeground = true;
138 if (!mManager->mProcess && gfxConfig::IsEnabled(Feature::GPU_PROCESS)) {
139 Unused << mManager->LaunchGPUProcess();
141 } else if (!strcmp(aTopic, "application-background")) {
142 mManager->mAppInForeground = false;
144 return NS_OK;
147 void GPUProcessManager::OnXPCOMShutdown() {
148 if (mObserver) {
149 nsContentUtils::UnregisterShutdownObserver(mObserver);
150 Preferences::RemoveObserver(mObserver, "");
151 nsCOMPtr<nsIObserverService> obsServ = services::GetObserverService();
152 if (obsServ) {
153 obsServ->RemoveObserver(mObserver, "application-foreground");
154 obsServ->RemoveObserver(mObserver, "application-background");
156 mObserver = nullptr;
159 CleanShutdown();
162 void GPUProcessManager::OnPreferenceChange(const char16_t* aData) {
163 // We know prefs are ASCII here.
164 NS_LossyConvertUTF16toASCII strData(aData);
166 mozilla::dom::Pref pref(strData, /* isLocked */ false,
167 /* isSanitized */ false, Nothing(), Nothing());
169 Preferences::GetPreference(&pref, GeckoProcessType_GPU,
170 /* remoteType */ ""_ns);
171 if (!!mGPUChild) {
172 MOZ_ASSERT(mQueuedPrefs.IsEmpty());
173 mGPUChild->SendPreferenceUpdate(pref);
174 } else if (IsGPUProcessLaunching()) {
175 mQueuedPrefs.AppendElement(pref);
179 bool GPUProcessManager::LaunchGPUProcess() {
180 if (mProcess) {
181 return true;
184 if (AppShutdown::IsInOrBeyond(ShutdownPhase::XPCOMShutdown)) {
185 return false;
188 // Start listening for pref changes so we can
189 // forward them to the process once it is running.
190 if (!mObserver) {
191 mObserver = new Observer(this);
192 nsContentUtils::RegisterShutdownObserver(mObserver);
193 Preferences::AddStrongObserver(mObserver, "");
194 nsCOMPtr<nsIObserverService> obsServ = services::GetObserverService();
195 if (obsServ) {
196 obsServ->AddObserver(mObserver, "application-foreground", false);
197 obsServ->AddObserver(mObserver, "application-background", false);
201 // Start the Vsync I/O thread so can use it as soon as the process launches.
202 EnsureVsyncIOThread();
204 // If the process didn't live long enough, reset the stable flag so that we
205 // don't end up in a restart loop.
206 auto newTime = TimeStamp::Now();
207 if (mTotalProcessAttempts > 0) {
208 auto delta = (int32_t)(newTime - mProcessAttemptLastTime).ToMilliseconds();
209 if (delta < StaticPrefs::layers_gpu_process_stable_min_uptime_ms()) {
210 mProcessStable = false;
213 mProcessAttemptLastTime = newTime;
215 if (!mProcessStable) {
216 mUnstableProcessAttempts++;
218 mTotalProcessAttempts++;
219 mProcessStable = false;
221 std::vector<std::string> extraArgs;
222 ipc::ProcessChild::AddPlatformBuildID(extraArgs);
224 // The subprocess is launched asynchronously, so we wait for a callback to
225 // acquire the IPDL actor.
226 mProcess = new GPUProcessHost(this);
227 if (!mProcess->Launch(extraArgs)) {
228 DisableGPUProcess("Failed to launch GPU process");
231 return true;
234 bool GPUProcessManager::IsGPUProcessLaunching() {
235 MOZ_ASSERT(NS_IsMainThread());
236 return !!mProcess && !mGPUChild;
239 void GPUProcessManager::DisableGPUProcess(const char* aMessage) {
240 MaybeDisableGPUProcess(aMessage, /* aAllowRestart */ false);
243 bool GPUProcessManager::MaybeDisableGPUProcess(const char* aMessage,
244 bool aAllowRestart) {
245 if (!gfxConfig::IsEnabled(Feature::GPU_PROCESS)) {
246 return true;
249 if (!aAllowRestart) {
250 gfxConfig::SetFailed(Feature::GPU_PROCESS, FeatureStatus::Failed, aMessage);
253 bool wantRestart = gfxPlatform::FallbackFromAcceleration(
254 FeatureStatus::Unavailable, "GPU Process is disabled",
255 "FEATURE_FAILURE_GPU_PROCESS_DISABLED"_ns);
256 if (aAllowRestart && wantRestart) {
257 // The fallback method can make use of the GPU process.
258 return false;
261 if (aAllowRestart) {
262 gfxConfig::SetFailed(Feature::GPU_PROCESS, FeatureStatus::Failed, aMessage);
265 gfxCriticalNote << aMessage;
267 gfxPlatform::DisableGPUProcess();
269 Telemetry::Accumulate(Telemetry::GPU_PROCESS_CRASH_FALLBACKS,
270 uint32_t(FallbackType::DISABLED));
272 DestroyProcess();
273 ShutdownVsyncIOThread();
275 // We may have been in the middle of guaranteeing our various services are
276 // available when one failed. Some callers may fallback to using the same
277 // process equivalent, and we need to make sure those services are setup
278 // correctly. We cannot re-enter DisableGPUProcess from this call because we
279 // know that it is disabled in the config above.
280 EnsureProtocolsReady();
282 // If we disable the GPU process during reinitialization after a previous
283 // crash, then we need to tell the content processes again, because they
284 // need to rebind to the UI process.
285 HandleProcessLost();
286 return true;
289 bool GPUProcessManager::EnsureGPUReady() {
290 MOZ_ASSERT(NS_IsMainThread());
292 // Launch the GPU process if it is enabled but hasn't been (re-)launched yet.
293 if (!mProcess && gfxConfig::IsEnabled(Feature::GPU_PROCESS)) {
294 if (!LaunchGPUProcess()) {
295 return false;
299 if (mProcess && !mProcess->IsConnected()) {
300 if (!mProcess->WaitForLaunch()) {
301 // If this fails, we should have fired OnProcessLaunchComplete and
302 // removed the process.
303 MOZ_ASSERT(!mProcess && !mGPUChild);
304 return false;
308 if (mGPUChild) {
309 if (mGPUChild->EnsureGPUReady()) {
310 return true;
313 // If the initialization above fails, we likely have a GPU process teardown
314 // waiting in our message queue (or will soon). We need to ensure we don't
315 // restart it later because if we fail here, our callers assume they should
316 // fall back to a combined UI/GPU process. This also ensures our internal
317 // state is consistent (e.g. process token is reset).
318 DisableGPUProcess("Failed to initialize GPU process");
321 return false;
324 void GPUProcessManager::EnsureProtocolsReady() {
325 EnsureCompositorManagerChild();
326 EnsureImageBridgeChild();
327 EnsureVRManager();
330 void GPUProcessManager::EnsureCompositorManagerChild() {
331 bool gpuReady = EnsureGPUReady();
332 if (CompositorManagerChild::IsInitialized(mProcessToken)) {
333 return;
336 if (!gpuReady) {
337 CompositorManagerChild::InitSameProcess(AllocateNamespace(), mProcessToken);
338 return;
341 ipc::Endpoint<PCompositorManagerParent> parentPipe;
342 ipc::Endpoint<PCompositorManagerChild> childPipe;
343 nsresult rv = PCompositorManager::CreateEndpoints(
344 mGPUChild->OtherPid(), base::GetCurrentProcId(), &parentPipe, &childPipe);
345 if (NS_FAILED(rv)) {
346 DisableGPUProcess("Failed to create PCompositorManager endpoints");
347 return;
350 mGPUChild->SendInitCompositorManager(std::move(parentPipe));
351 CompositorManagerChild::Init(std::move(childPipe), AllocateNamespace(),
352 mProcessToken);
355 void GPUProcessManager::EnsureImageBridgeChild() {
356 if (ImageBridgeChild::GetSingleton()) {
357 return;
360 if (!EnsureGPUReady()) {
361 ImageBridgeChild::InitSameProcess(AllocateNamespace());
362 return;
365 ipc::Endpoint<PImageBridgeParent> parentPipe;
366 ipc::Endpoint<PImageBridgeChild> childPipe;
367 nsresult rv = PImageBridge::CreateEndpoints(
368 mGPUChild->OtherPid(), base::GetCurrentProcId(), &parentPipe, &childPipe);
369 if (NS_FAILED(rv)) {
370 DisableGPUProcess("Failed to create PImageBridge endpoints");
371 return;
374 mGPUChild->SendInitImageBridge(std::move(parentPipe));
375 ImageBridgeChild::InitWithGPUProcess(std::move(childPipe),
376 AllocateNamespace());
379 void GPUProcessManager::EnsureVRManager() {
380 if (VRManagerChild::IsCreated()) {
381 return;
384 if (!EnsureGPUReady()) {
385 VRManagerChild::InitSameProcess();
386 return;
389 ipc::Endpoint<PVRManagerParent> parentPipe;
390 ipc::Endpoint<PVRManagerChild> childPipe;
391 nsresult rv = PVRManager::CreateEndpoints(
392 mGPUChild->OtherPid(), base::GetCurrentProcId(), &parentPipe, &childPipe);
393 if (NS_FAILED(rv)) {
394 DisableGPUProcess("Failed to create PVRManager endpoints");
395 return;
398 mGPUChild->SendInitVRManager(std::move(parentPipe));
399 VRManagerChild::InitWithGPUProcess(std::move(childPipe));
402 #if defined(MOZ_WIDGET_ANDROID)
403 already_AddRefed<UiCompositorControllerChild>
404 GPUProcessManager::CreateUiCompositorController(nsBaseWidget* aWidget,
405 const LayersId aId) {
406 RefPtr<UiCompositorControllerChild> result;
408 if (!EnsureGPUReady()) {
409 result = UiCompositorControllerChild::CreateForSameProcess(aId, aWidget);
410 } else {
411 ipc::Endpoint<PUiCompositorControllerParent> parentPipe;
412 ipc::Endpoint<PUiCompositorControllerChild> childPipe;
413 nsresult rv = PUiCompositorController::CreateEndpoints(
414 mGPUChild->OtherPid(), base::GetCurrentProcId(), &parentPipe,
415 &childPipe);
416 if (NS_FAILED(rv)) {
417 DisableGPUProcess("Failed to create PUiCompositorController endpoints");
418 return nullptr;
421 mGPUChild->SendInitUiCompositorController(aId, std::move(parentPipe));
422 result = UiCompositorControllerChild::CreateForGPUProcess(
423 mProcessToken, std::move(childPipe), aWidget);
425 if (result) {
426 result->SetCompositorSurfaceManager(
427 mProcess->GetCompositorSurfaceManager());
430 return result.forget();
432 #endif // defined(MOZ_WIDGET_ANDROID)
434 void GPUProcessManager::OnProcessLaunchComplete(GPUProcessHost* aHost) {
435 MOZ_ASSERT(mProcess && mProcess == aHost);
437 if (!mProcess->IsConnected()) {
438 DisableGPUProcess("Failed to connect GPU process");
439 return;
442 mGPUChild = mProcess->GetActor();
443 mProcessToken = mProcess->GetProcessToken();
445 ipc::Endpoint<PVsyncBridgeParent> vsyncParent;
446 ipc::Endpoint<PVsyncBridgeChild> vsyncChild;
447 nsresult rv = PVsyncBridge::CreateEndpoints(mGPUChild->OtherPid(),
448 base::GetCurrentProcId(),
449 &vsyncParent, &vsyncChild);
450 if (NS_FAILED(rv)) {
451 DisableGPUProcess("Failed to create PVsyncBridge endpoints");
452 return;
455 mVsyncBridge = VsyncBridgeChild::Create(mVsyncIOThread, mProcessToken,
456 std::move(vsyncChild));
457 mGPUChild->SendInitVsyncBridge(std::move(vsyncParent));
459 // Flush any pref updates that happened during launch and weren't
460 // included in the blobs set up in LaunchGPUProcess.
461 for (const mozilla::dom::Pref& pref : mQueuedPrefs) {
462 Unused << NS_WARN_IF(!mGPUChild->SendPreferenceUpdate(pref));
464 mQueuedPrefs.Clear();
466 CrashReporter::AnnotateCrashReport(
467 CrashReporter::Annotation::GPUProcessStatus, "Running"_ns);
469 CrashReporter::AnnotateCrashReport(
470 CrashReporter::Annotation::GPUProcessLaunchCount,
471 static_cast<int>(mTotalProcessAttempts));
473 ReinitializeRendering();
476 void GPUProcessManager::OnProcessDeclaredStable() { mProcessStable = true; }
478 static bool ShouldLimitDeviceResets(uint32_t count, int32_t deltaMilliseconds) {
479 // We decide to limit by comparing the amount of resets that have happened
480 // and time since the last reset to two prefs.
481 int32_t timeLimit = StaticPrefs::gfx_device_reset_threshold_ms_AtStartup();
482 int32_t countLimit = StaticPrefs::gfx_device_reset_limit_AtStartup();
484 bool hasTimeLimit = timeLimit >= 0;
485 bool hasCountLimit = countLimit >= 0;
487 bool triggeredTime = deltaMilliseconds < timeLimit;
488 bool triggeredCount = count > (uint32_t)countLimit;
490 // If we have both prefs set then it needs to trigger both limits,
491 // otherwise we only test the pref that is set or none
492 if (hasTimeLimit && hasCountLimit) {
493 return triggeredTime && triggeredCount;
494 } else if (hasTimeLimit) {
495 return triggeredTime;
496 } else if (hasCountLimit) {
497 return triggeredCount;
500 return false;
503 void GPUProcessManager::ResetCompositors() {
504 // Note: this will recreate devices in addition to recreating compositors.
505 // This isn't optimal, but this is only used on linux where acceleration
506 // isn't enabled by default, and this way we don't need a new code path.
507 SimulateDeviceReset();
510 void GPUProcessManager::SimulateDeviceReset() {
511 // Make sure we rebuild environment and configuration for accelerated
512 // features.
513 gfxPlatform::GetPlatform()->CompositorUpdated();
515 if (mProcess) {
516 if (mGPUChild) {
517 mGPUChild->SendSimulateDeviceReset();
519 } else {
520 wr::RenderThread::Get()->SimulateDeviceReset();
524 bool GPUProcessManager::DisableWebRenderConfig(wr::WebRenderError aError,
525 const nsCString& aMsg) {
526 if (!gfx::gfxVars::UseWebRender()) {
527 return false;
529 // Disable WebRender
530 bool wantRestart;
531 if (aError == wr::WebRenderError::INITIALIZE) {
532 wantRestart = gfxPlatform::FallbackFromAcceleration(
533 gfx::FeatureStatus::Unavailable, "WebRender initialization failed",
534 aMsg);
535 } else if (aError == wr::WebRenderError::MAKE_CURRENT) {
536 wantRestart = gfxPlatform::FallbackFromAcceleration(
537 gfx::FeatureStatus::Unavailable,
538 "Failed to make render context current",
539 "FEATURE_FAILURE_WEBRENDER_MAKE_CURRENT"_ns);
540 } else if (aError == wr::WebRenderError::RENDER) {
541 wantRestart = gfxPlatform::FallbackFromAcceleration(
542 gfx::FeatureStatus::Unavailable, "Failed to render WebRender",
543 "FEATURE_FAILURE_WEBRENDER_RENDER"_ns);
544 } else if (aError == wr::WebRenderError::NEW_SURFACE) {
545 // If we cannot create a new Surface even in the final fallback
546 // configuration then force a crash.
547 wantRestart = gfxPlatform::FallbackFromAcceleration(
548 gfx::FeatureStatus::Unavailable, "Failed to create new surface",
549 "FEATURE_FAILURE_WEBRENDER_NEW_SURFACE"_ns,
550 /* aCrashAfterFinalFallback */ true);
551 } else if (aError == wr::WebRenderError::BEGIN_DRAW) {
552 wantRestart = gfxPlatform::FallbackFromAcceleration(
553 gfx::FeatureStatus::Unavailable, "BeginDraw() failed",
554 "FEATURE_FAILURE_WEBRENDER_BEGIN_DRAW"_ns);
555 } else if (aError == wr::WebRenderError::EXCESSIVE_RESETS) {
556 wantRestart = gfxPlatform::FallbackFromAcceleration(
557 gfx::FeatureStatus::Unavailable, "Device resets exceeded threshold",
558 "FEATURE_FAILURE_WEBRENDER_EXCESSIVE_RESETS"_ns);
559 } else {
560 MOZ_ASSERT_UNREACHABLE("Invalid value");
561 wantRestart = gfxPlatform::FallbackFromAcceleration(
562 gfx::FeatureStatus::Unavailable, "Unhandled failure reason",
563 "FEATURE_FAILURE_WEBRENDER_UNHANDLED"_ns);
565 gfx::gfxVars::SetUseWebRenderDCompVideoOverlayWin(false);
567 // If we still have the GPU process, and we fallback to a new configuration
568 // that prefers to have the GPU process, reset the counter.
569 if (wantRestart && mProcess) {
570 mUnstableProcessAttempts = 1;
573 return true;
576 void GPUProcessManager::DisableWebRender(wr::WebRenderError aError,
577 const nsCString& aMsg) {
578 if (DisableWebRenderConfig(aError, aMsg)) {
579 if (mProcess) {
580 DestroyRemoteCompositorSessions();
581 } else {
582 DestroyInProcessCompositorSessions();
584 NotifyListenersOnCompositeDeviceReset();
588 void GPUProcessManager::NotifyWebRenderError(wr::WebRenderError aError) {
589 if (aError == wr::WebRenderError::VIDEO_OVERLAY) {
590 #ifdef XP_WIN
591 gfxVars::SetUseWebRenderDCompVideoOverlayWin(false);
592 #else
593 MOZ_ASSERT_UNREACHABLE("unexpected to be called");
594 #endif
595 return;
597 DisableWebRender(aError, nsCString());
600 /* static */ void GPUProcessManager::RecordDeviceReset(
601 DeviceResetReason aReason) {
602 if (aReason != DeviceResetReason::FORCED_RESET) {
603 Telemetry::Accumulate(Telemetry::DEVICE_RESET_REASON, uint32_t(aReason));
606 CrashReporter::AnnotateCrashReport(
607 CrashReporter::Annotation::DeviceResetReason, int(aReason));
610 bool GPUProcessManager::OnDeviceReset(bool aTrackThreshold) {
611 #ifdef XP_WIN
612 // Disable double buffering when device reset happens.
613 if (!gfxVars::UseWebRender() && gfxVars::UseDoubleBufferingWithCompositor()) {
614 gfxVars::SetUseDoubleBufferingWithCompositor(false);
616 #endif
618 // Ignore resets for thresholding if requested.
619 if (!aTrackThreshold) {
620 return false;
623 // Detect whether the device is resetting too quickly or too much
624 // indicating that we should give up and use software
625 mDeviceResetCount++;
627 auto newTime = TimeStamp::Now();
628 auto delta = (int32_t)(newTime - mDeviceResetLastTime).ToMilliseconds();
629 mDeviceResetLastTime = newTime;
631 // Returns true if we should disable acceleration due to the reset.
632 return ShouldLimitDeviceResets(mDeviceResetCount, delta);
635 void GPUProcessManager::OnInProcessDeviceReset(bool aTrackThreshold) {
636 if (OnDeviceReset(aTrackThreshold)) {
637 gfxCriticalNoteOnce << "In-process device reset threshold exceeded";
638 #ifdef MOZ_WIDGET_GTK
639 // FIXME(aosmond): Should we disable WebRender on other platforms?
640 DisableWebRenderConfig(wr::WebRenderError::EXCESSIVE_RESETS, nsCString());
641 #endif
643 #ifdef XP_WIN
644 // Ensure device reset handling before re-creating in process sessions.
645 // Normally nsWindow::OnPaint() already handled it.
646 gfxWindowsPlatform::GetPlatform()->HandleDeviceReset();
647 #endif
648 DestroyInProcessCompositorSessions();
649 NotifyListenersOnCompositeDeviceReset();
652 void GPUProcessManager::OnRemoteProcessDeviceReset(GPUProcessHost* aHost) {
653 if (OnDeviceReset(/* aTrackThreshold */ true)) {
654 DestroyProcess();
655 DisableGPUProcess("GPU processed experienced too many device resets");
656 HandleProcessLost();
657 return;
660 DestroyRemoteCompositorSessions();
661 NotifyListenersOnCompositeDeviceReset();
664 void GPUProcessManager::NotifyListenersOnCompositeDeviceReset() {
665 for (const auto& listener : mListeners) {
666 listener->OnCompositorDeviceReset();
670 void GPUProcessManager::OnProcessUnexpectedShutdown(GPUProcessHost* aHost) {
671 MOZ_ASSERT(mProcess && mProcess == aHost);
673 if (StaticPrefs::layers_gpu_process_crash_also_crashes_browser()) {
674 MOZ_CRASH("GPU process crashed and pref is set to crash the browser.");
677 CompositorManagerChild::OnGPUProcessLost(aHost->GetProcessToken());
678 DestroyProcess(/* aUnexpectedShutdown */ true);
680 if (mUnstableProcessAttempts >
681 uint32_t(StaticPrefs::layers_gpu_process_max_restarts())) {
682 char disableMessage[64];
683 SprintfLiteral(disableMessage, "GPU process disabled after %d attempts",
684 mTotalProcessAttempts);
685 if (!MaybeDisableGPUProcess(disableMessage, /* aAllowRestart */ true)) {
686 // Fallback wants the GPU process. Reset our counter.
687 mUnstableProcessAttempts = 0;
688 HandleProcessLost();
690 } else if (mUnstableProcessAttempts >
691 uint32_t(StaticPrefs::
692 layers_gpu_process_max_restarts_with_decoder()) &&
693 mDecodeVideoOnGpuProcess) {
694 mDecodeVideoOnGpuProcess = false;
695 Telemetry::Accumulate(Telemetry::GPU_PROCESS_CRASH_FALLBACKS,
696 uint32_t(FallbackType::DECODINGDISABLED));
697 HandleProcessLost();
698 } else {
699 Telemetry::Accumulate(Telemetry::GPU_PROCESS_CRASH_FALLBACKS,
700 uint32_t(FallbackType::NONE));
701 HandleProcessLost();
705 void GPUProcessManager::HandleProcessLost() {
706 MOZ_ASSERT(NS_IsMainThread());
708 // The shutdown and restart sequence for the GPU process is as follows:
710 // (1) The GPU process dies. IPDL will enqueue an ActorDestroy message on
711 // each channel owning a bridge to the GPU process, on the thread owning
712 // that channel.
714 // (2) The first channel to process its ActorDestroy message will post a
715 // message to the main thread to call NotifyRemoteActorDestroyed on the
716 // GPUProcessManager, which calls OnProcessUnexpectedShutdown if it has
717 // not handled shutdown for this process yet. OnProcessUnexpectedShutdown
718 // is responsible for tearing down the old process and deciding whether
719 // or not to disable the GPU process. It then calls this function,
720 // HandleProcessLost.
722 // (3) We then notify each widget that its session with the compositor is now
723 // invalid. The widget is responsible for destroying its layer manager
724 // and CompositorBridgeChild. Note that at this stage, not all actors may
725 // have received ActorDestroy yet. CompositorBridgeChild may attempt to
726 // send messages, and if this happens, it will probably report a
727 // MsgDropped error. This is okay.
729 // (4) At this point, the UI process has a clean slate: no layers should
730 // exist for the old compositor. We may make a decision on whether or not
731 // to re-launch the GPU process. Or, on Android if the app is in the
732 // background we may decide to wait until it comes to the foreground
733 // before re-launching.
735 // (5) When we do decide to re-launch, or continue without a GPU process, we
736 // notify each ContentParent of the lost connection. It will request new
737 // endpoints from the GPUProcessManager and forward them to its
738 // ContentChild. The parent-side of these endpoints may come from the
739 // compositor thread of the UI process, or the compositor thread of the
740 // GPU process. However, no actual compositors should exist yet.
742 // (6) Each ContentChild will receive new endpoints. It will destroy its
743 // Compositor/ImageBridgeChild singletons and recreate them, as well
744 // as invalidate all retained layers.
746 // (7) In addition, each ContentChild will ask each of its BrowserChildren
747 // to re-request association with the compositor for the window
748 // owning the tab. The sequence of calls looks like:
749 // (a) [CONTENT] ContentChild::RecvReinitRendering
750 // (b) [CONTENT] BrowserChild::ReinitRendering
751 // (c) [CONTENT] BrowserChild::SendEnsureLayersConnected
752 // (d) [UI] BrowserParent::RecvEnsureLayersConnected
753 // (e) [UI] RemoteLayerTreeOwner::EnsureLayersConnected
754 // (f) [UI] CompositorBridgeChild::SendNotifyChildRecreated
756 // Note that at step (e), RemoteLayerTreeOwner will call
757 // GetWindowRenderer on the nsIWidget owning the tab. This step ensures
758 // that a compositor exists for the window. If we decided to launch a new
759 // GPU Process, at this point we block until the process has launched and
760 // we're able to create a new window compositor. Otherwise, if
761 // compositing is now in-process, this will simply create a new
762 // CompositorBridgeParent in the UI process. If there are multiple tabs
763 // in the same window, additional tabs will simply return the already-
764 // established compositor.
766 // Finally, this step serves one other crucial function: tabs must be
767 // associated with a window compositor or else they can't forward
768 // layer transactions. So this step both ensures that a compositor
769 // exists, and that the tab can forward layers.
771 // (8) Last, if the window had no remote tabs, step (7) will not have
772 // applied, and the window will not have a new compositor just yet. The
773 // next refresh tick and paint will ensure that one exists, again via
774 // nsIWidget::GetWindowRenderer. On Android, we called
775 // nsIWidgetListener::RequestRepaint back in step (3) to ensure this
776 // tick occurs, but on other platforms this is not necessary.
778 DestroyRemoteCompositorSessions();
780 // Re-launch the process if immediately if the GPU process is still enabled.
781 // Except on Android if the app is in the background, where we want to wait
782 // until the app is in the foreground again.
783 if (gfxConfig::IsEnabled(Feature::GPU_PROCESS)) {
784 if (mAppInForeground) {
785 Unused << LaunchGPUProcess();
787 } else {
788 // If the GPU process is disabled we can reinitialize rendering immediately.
789 // This will be handled in OnProcessLaunchComplete() if the GPU process is
790 // enabled.
791 ReinitializeRendering();
795 void GPUProcessManager::ReinitializeRendering() {
796 // Notify content. This will ensure that each content process re-establishes
797 // a connection to the compositor thread (whether it's in-process or in a
798 // newly launched GPU process).
799 for (const auto& listener : mListeners) {
800 listener->OnCompositorUnexpectedShutdown();
803 // Notify any observers that the compositor has been reinitialized,
804 // eg the ZoomConstraintsClients for parent process documents.
805 nsCOMPtr<nsIObserverService> observerService = services::GetObserverService();
806 if (observerService) {
807 observerService->NotifyObservers(nullptr, "compositor-reinitialized",
808 nullptr);
812 void GPUProcessManager::DestroyRemoteCompositorSessions() {
813 // Build a list of sessions to notify, since notification might delete
814 // entries from the list.
815 nsTArray<RefPtr<RemoteCompositorSession>> sessions;
816 for (auto& session : mRemoteSessions) {
817 sessions.AppendElement(session);
820 // Notify each widget that we have lost the GPU process. This will ensure
821 // that each widget destroys its layer manager and CompositorBridgeChild.
822 for (const auto& session : sessions) {
823 session->NotifySessionLost();
827 void GPUProcessManager::DestroyInProcessCompositorSessions() {
828 // Build a list of sessions to notify, since notification might delete
829 // entries from the list.
830 nsTArray<RefPtr<InProcessCompositorSession>> sessions;
831 for (auto& session : mInProcessSessions) {
832 sessions.AppendElement(session);
835 // Notify each widget that we have lost the GPU process. This will ensure
836 // that each widget destroys its layer manager and CompositorBridgeChild.
837 for (const auto& session : sessions) {
838 session->NotifySessionLost();
842 void GPUProcessManager::NotifyRemoteActorDestroyed(
843 const uint64_t& aProcessToken) {
844 if (!NS_IsMainThread()) {
845 RefPtr<Runnable> task = mTaskFactory.NewRunnableMethod(
846 &GPUProcessManager::NotifyRemoteActorDestroyed, aProcessToken);
847 NS_DispatchToMainThread(task.forget());
848 return;
851 if (mProcessToken != aProcessToken) {
852 // This token is for an older process; we can safely ignore it.
853 return;
856 // One of the bridged top-level actors for the GPU process has been
857 // prematurely terminated, and we're receiving a notification. This
858 // can happen if the ActorDestroy for a bridged protocol fires
859 // before the ActorDestroy for PGPUChild.
860 OnProcessUnexpectedShutdown(mProcess);
863 void GPUProcessManager::CleanShutdown() {
864 DestroyProcess();
865 mVsyncIOThread = nullptr;
868 void GPUProcessManager::KillProcess() {
869 if (!mProcess) {
870 return;
873 mProcess->KillProcess();
876 void GPUProcessManager::CrashProcess() {
877 if (!mProcess) {
878 return;
881 mProcess->CrashProcess();
884 void GPUProcessManager::DestroyProcess(bool aUnexpectedShutdown) {
885 if (!mProcess) {
886 return;
889 mProcess->Shutdown(aUnexpectedShutdown);
890 mProcessToken = 0;
891 mProcess = nullptr;
892 mGPUChild = nullptr;
893 mQueuedPrefs.Clear();
894 if (mVsyncBridge) {
895 mVsyncBridge->Close();
896 mVsyncBridge = nullptr;
899 CrashReporter::AnnotateCrashReport(
900 CrashReporter::Annotation::GPUProcessStatus, "Destroyed"_ns);
903 already_AddRefed<CompositorSession> GPUProcessManager::CreateTopLevelCompositor(
904 nsBaseWidget* aWidget, WebRenderLayerManager* aLayerManager,
905 CSSToLayoutDeviceScale aScale, const CompositorOptions& aOptions,
906 bool aUseExternalSurfaceSize, const gfx::IntSize& aSurfaceSize,
907 uint64_t aInnerWindowId, bool* aRetryOut) {
908 MOZ_ASSERT(aRetryOut);
910 LayersId layerTreeId = AllocateLayerTreeId();
912 EnsureProtocolsReady();
914 RefPtr<CompositorSession> session;
916 if (EnsureGPUReady()) {
917 session = CreateRemoteSession(aWidget, aLayerManager, layerTreeId, aScale,
918 aOptions, aUseExternalSurfaceSize,
919 aSurfaceSize, aInnerWindowId);
920 if (!session) {
921 // We couldn't create a remote compositor, so abort the process.
922 DisableGPUProcess("Failed to create remote compositor");
923 *aRetryOut = true;
924 return nullptr;
926 } else {
927 session = InProcessCompositorSession::Create(
928 aWidget, aLayerManager, layerTreeId, aScale, aOptions,
929 aUseExternalSurfaceSize, aSurfaceSize, AllocateNamespace(),
930 aInnerWindowId);
933 #if defined(MOZ_WIDGET_ANDROID)
934 if (session) {
935 // Nothing to do if controller gets a nullptr
936 RefPtr<UiCompositorControllerChild> controller =
937 CreateUiCompositorController(aWidget, session->RootLayerTreeId());
938 session->SetUiCompositorControllerChild(controller);
940 #endif // defined(MOZ_WIDGET_ANDROID)
942 *aRetryOut = false;
943 return session.forget();
946 RefPtr<CompositorSession> GPUProcessManager::CreateRemoteSession(
947 nsBaseWidget* aWidget, WebRenderLayerManager* aLayerManager,
948 const LayersId& aRootLayerTreeId, CSSToLayoutDeviceScale aScale,
949 const CompositorOptions& aOptions, bool aUseExternalSurfaceSize,
950 const gfx::IntSize& aSurfaceSize, uint64_t aInnerWindowId) {
951 #ifdef MOZ_WIDGET_SUPPORTS_OOP_COMPOSITING
952 widget::CompositorWidgetInitData initData;
953 aWidget->GetCompositorWidgetInitData(&initData);
955 RefPtr<CompositorBridgeChild> child =
956 CompositorManagerChild::CreateWidgetCompositorBridge(
957 mProcessToken, aLayerManager, AllocateNamespace(), aScale, aOptions,
958 aUseExternalSurfaceSize, aSurfaceSize, aInnerWindowId);
959 if (!child) {
960 gfxCriticalNote << "Failed to create CompositorBridgeChild";
961 return nullptr;
964 RefPtr<CompositorVsyncDispatcher> dispatcher =
965 aWidget->GetCompositorVsyncDispatcher();
966 RefPtr<widget::CompositorWidgetVsyncObserver> observer =
967 new widget::CompositorWidgetVsyncObserver(mVsyncBridge, aRootLayerTreeId);
969 widget::CompositorWidgetChild* widget =
970 new widget::CompositorWidgetChild(dispatcher, observer, initData);
971 if (!child->SendPCompositorWidgetConstructor(widget, initData)) {
972 return nullptr;
974 if (!widget->Initialize()) {
975 return nullptr;
977 if (!child->SendInitialize(aRootLayerTreeId)) {
978 return nullptr;
981 RefPtr<APZCTreeManagerChild> apz = nullptr;
982 if (aOptions.UseAPZ()) {
983 PAPZCTreeManagerChild* papz =
984 child->SendPAPZCTreeManagerConstructor(LayersId{0});
985 if (!papz) {
986 return nullptr;
988 apz = static_cast<APZCTreeManagerChild*>(papz);
990 ipc::Endpoint<PAPZInputBridgeParent> parentPipe;
991 ipc::Endpoint<PAPZInputBridgeChild> childPipe;
992 nsresult rv = PAPZInputBridge::CreateEndpoints(mGPUChild->OtherPid(),
993 base::GetCurrentProcId(),
994 &parentPipe, &childPipe);
995 if (NS_FAILED(rv)) {
996 return nullptr;
998 mGPUChild->SendInitAPZInputBridge(aRootLayerTreeId, std::move(parentPipe));
1000 RefPtr<APZInputBridgeChild> inputBridge =
1001 APZInputBridgeChild::Create(mProcessToken, std::move(childPipe));
1002 if (!inputBridge) {
1003 return nullptr;
1006 apz->SetInputBridge(inputBridge);
1009 return new RemoteCompositorSession(aWidget, child, widget, apz,
1010 aRootLayerTreeId);
1011 #else
1012 gfxCriticalNote << "Platform does not support out-of-process compositing";
1013 return nullptr;
1014 #endif
1017 bool GPUProcessManager::CreateContentBridges(
1018 base::ProcessId aOtherProcess,
1019 ipc::Endpoint<PCompositorManagerChild>* aOutCompositor,
1020 ipc::Endpoint<PImageBridgeChild>* aOutImageBridge,
1021 ipc::Endpoint<PVRManagerChild>* aOutVRBridge,
1022 ipc::Endpoint<PRemoteDecoderManagerChild>* aOutVideoManager,
1023 nsTArray<uint32_t>* aNamespaces) {
1024 if (!CreateContentCompositorManager(aOtherProcess, aOutCompositor) ||
1025 !CreateContentImageBridge(aOtherProcess, aOutImageBridge) ||
1026 !CreateContentVRManager(aOtherProcess, aOutVRBridge)) {
1027 return false;
1029 // VideoDeocderManager is only supported in the GPU process, so we allow this
1030 // to be fallible.
1031 CreateContentRemoteDecoderManager(aOtherProcess, aOutVideoManager);
1032 // Allocates 3 namespaces(for CompositorManagerChild, CompositorBridgeChild
1033 // and ImageBridgeChild)
1034 aNamespaces->AppendElement(AllocateNamespace());
1035 aNamespaces->AppendElement(AllocateNamespace());
1036 aNamespaces->AppendElement(AllocateNamespace());
1037 return true;
1040 bool GPUProcessManager::CreateContentCompositorManager(
1041 base::ProcessId aOtherProcess,
1042 ipc::Endpoint<PCompositorManagerChild>* aOutEndpoint) {
1043 ipc::Endpoint<PCompositorManagerParent> parentPipe;
1044 ipc::Endpoint<PCompositorManagerChild> childPipe;
1046 base::ProcessId parentPid =
1047 EnsureGPUReady() ? mGPUChild->OtherPid() : base::GetCurrentProcId();
1049 nsresult rv = PCompositorManager::CreateEndpoints(parentPid, aOtherProcess,
1050 &parentPipe, &childPipe);
1051 if (NS_FAILED(rv)) {
1052 gfxCriticalNote << "Could not create content compositor manager: "
1053 << hexa(int(rv));
1054 return false;
1057 if (mGPUChild) {
1058 mGPUChild->SendNewContentCompositorManager(std::move(parentPipe));
1059 } else if (!CompositorManagerParent::Create(std::move(parentPipe),
1060 /* aIsRoot */ false)) {
1061 return false;
1064 *aOutEndpoint = std::move(childPipe);
1065 return true;
1068 bool GPUProcessManager::CreateContentImageBridge(
1069 base::ProcessId aOtherProcess,
1070 ipc::Endpoint<PImageBridgeChild>* aOutEndpoint) {
1071 EnsureImageBridgeChild();
1073 base::ProcessId parentPid =
1074 EnsureGPUReady() ? mGPUChild->OtherPid() : base::GetCurrentProcId();
1076 ipc::Endpoint<PImageBridgeParent> parentPipe;
1077 ipc::Endpoint<PImageBridgeChild> childPipe;
1078 nsresult rv = PImageBridge::CreateEndpoints(parentPid, aOtherProcess,
1079 &parentPipe, &childPipe);
1080 if (NS_FAILED(rv)) {
1081 gfxCriticalNote << "Could not create content compositor bridge: "
1082 << hexa(int(rv));
1083 return false;
1086 if (mGPUChild) {
1087 mGPUChild->SendNewContentImageBridge(std::move(parentPipe));
1088 } else {
1089 if (!ImageBridgeParent::CreateForContent(std::move(parentPipe))) {
1090 return false;
1094 *aOutEndpoint = std::move(childPipe);
1095 return true;
1098 base::ProcessId GPUProcessManager::GPUProcessPid() {
1099 base::ProcessId gpuPid =
1100 mGPUChild ? mGPUChild->OtherPid() : base::kInvalidProcessId;
1101 return gpuPid;
1104 bool GPUProcessManager::CreateContentVRManager(
1105 base::ProcessId aOtherProcess,
1106 ipc::Endpoint<PVRManagerChild>* aOutEndpoint) {
1107 EnsureVRManager();
1109 base::ProcessId parentPid =
1110 EnsureGPUReady() ? mGPUChild->OtherPid() : base::GetCurrentProcId();
1112 ipc::Endpoint<PVRManagerParent> parentPipe;
1113 ipc::Endpoint<PVRManagerChild> childPipe;
1114 nsresult rv = PVRManager::CreateEndpoints(parentPid, aOtherProcess,
1115 &parentPipe, &childPipe);
1116 if (NS_FAILED(rv)) {
1117 gfxCriticalNote << "Could not create content compositor bridge: "
1118 << hexa(int(rv));
1119 return false;
1122 if (mGPUChild) {
1123 mGPUChild->SendNewContentVRManager(std::move(parentPipe));
1124 } else {
1125 if (!VRManagerParent::CreateForContent(std::move(parentPipe))) {
1126 return false;
1130 *aOutEndpoint = std::move(childPipe);
1131 return true;
1134 void GPUProcessManager::CreateContentRemoteDecoderManager(
1135 base::ProcessId aOtherProcess,
1136 ipc::Endpoint<PRemoteDecoderManagerChild>* aOutEndpoint) {
1137 if (!EnsureGPUReady() || !StaticPrefs::media_gpu_process_decoder() ||
1138 !mDecodeVideoOnGpuProcess) {
1139 return;
1142 ipc::Endpoint<PRemoteDecoderManagerParent> parentPipe;
1143 ipc::Endpoint<PRemoteDecoderManagerChild> childPipe;
1145 nsresult rv = PRemoteDecoderManager::CreateEndpoints(
1146 mGPUChild->OtherPid(), aOtherProcess, &parentPipe, &childPipe);
1147 if (NS_FAILED(rv)) {
1148 gfxCriticalNote << "Could not create content video decoder: "
1149 << hexa(int(rv));
1150 return;
1153 mGPUChild->SendNewContentRemoteDecoderManager(std::move(parentPipe));
1155 *aOutEndpoint = std::move(childPipe);
1158 void GPUProcessManager::InitVideoBridge(
1159 ipc::Endpoint<PVideoBridgeParent>&& aVideoBridge) {
1160 if (EnsureGPUReady()) {
1161 mGPUChild->SendInitVideoBridge(std::move(aVideoBridge));
1165 void GPUProcessManager::MapLayerTreeId(LayersId aLayersId,
1166 base::ProcessId aOwningId) {
1167 if (EnsureGPUReady()) {
1168 mGPUChild->SendAddLayerTreeIdMapping(
1169 LayerTreeIdMapping(aLayersId, aOwningId));
1172 // Must do this *after* the call to EnsureGPUReady, so that if the
1173 // process is launched as a result then it is initialized without this
1174 // LayersId, meaning it can be successfully mapped.
1175 LayerTreeOwnerTracker::Get()->Map(aLayersId, aOwningId);
1178 void GPUProcessManager::UnmapLayerTreeId(LayersId aLayersId,
1179 base::ProcessId aOwningId) {
1180 if (EnsureGPUReady()) {
1181 mGPUChild->SendRemoveLayerTreeIdMapping(
1182 LayerTreeIdMapping(aLayersId, aOwningId));
1183 } else {
1184 CompositorBridgeParent::DeallocateLayerTreeId(aLayersId);
1187 // Must do this *after* the call to EnsureGPUReady, so that if the
1188 // process is launched as a result then it is initialized with this
1189 // LayersId, meaning it can be successfully unmapped.
1190 LayerTreeOwnerTracker::Get()->Unmap(aLayersId, aOwningId);
1193 bool GPUProcessManager::IsLayerTreeIdMapped(LayersId aLayersId,
1194 base::ProcessId aRequestingId) {
1195 return LayerTreeOwnerTracker::Get()->IsMapped(aLayersId, aRequestingId);
1198 LayersId GPUProcessManager::AllocateLayerTreeId() {
1199 // Allocate tree id by using id namespace.
1200 // By it, tree id does not conflict with external image id and
1201 // async image pipeline id.
1202 MOZ_ASSERT(NS_IsMainThread());
1203 ++mResourceId;
1204 if (mResourceId == UINT32_MAX) {
1205 // Move to next id namespace.
1206 mIdNamespace = AllocateNamespace();
1207 mResourceId = 1;
1210 uint64_t layerTreeId = mIdNamespace;
1211 layerTreeId = (layerTreeId << 32) | mResourceId;
1212 return LayersId{layerTreeId};
1215 uint32_t GPUProcessManager::AllocateNamespace() {
1216 MOZ_ASSERT(NS_IsMainThread());
1217 return ++mNextNamespace;
1220 bool GPUProcessManager::AllocateAndConnectLayerTreeId(
1221 PCompositorBridgeChild* aCompositorBridge, base::ProcessId aOtherPid,
1222 LayersId* aOutLayersId, CompositorOptions* aOutCompositorOptions) {
1223 LayersId layersId = AllocateLayerTreeId();
1224 *aOutLayersId = layersId;
1226 if (!mGPUChild || !aCompositorBridge) {
1227 // If we're not remoting to another process, or there is no compositor,
1228 // then we'll send at most one message. In this case we can just keep
1229 // the old behavior of making sure the mapping occurs, and maybe sending
1230 // a creation notification.
1231 MapLayerTreeId(layersId, aOtherPid);
1232 if (!aCompositorBridge) {
1233 return false;
1235 return aCompositorBridge->SendNotifyChildCreated(layersId,
1236 aOutCompositorOptions);
1239 // Use the combined message path.
1240 LayerTreeOwnerTracker::Get()->Map(layersId, aOtherPid);
1241 return aCompositorBridge->SendMapAndNotifyChildCreated(layersId, aOtherPid,
1242 aOutCompositorOptions);
1245 void GPUProcessManager::EnsureVsyncIOThread() {
1246 if (mVsyncIOThread) {
1247 return;
1250 mVsyncIOThread = new VsyncIOThreadHolder();
1251 MOZ_RELEASE_ASSERT(mVsyncIOThread->Start());
1254 void GPUProcessManager::ShutdownVsyncIOThread() { mVsyncIOThread = nullptr; }
1256 void GPUProcessManager::RegisterRemoteProcessSession(
1257 RemoteCompositorSession* aSession) {
1258 mRemoteSessions.AppendElement(aSession);
1261 void GPUProcessManager::UnregisterRemoteProcessSession(
1262 RemoteCompositorSession* aSession) {
1263 mRemoteSessions.RemoveElement(aSession);
1266 void GPUProcessManager::RegisterInProcessSession(
1267 InProcessCompositorSession* aSession) {
1268 mInProcessSessions.AppendElement(aSession);
1271 void GPUProcessManager::UnregisterInProcessSession(
1272 InProcessCompositorSession* aSession) {
1273 mInProcessSessions.RemoveElement(aSession);
1276 void GPUProcessManager::AddListener(GPUProcessListener* aListener) {
1277 mListeners.AppendElement(aListener);
1280 void GPUProcessManager::RemoveListener(GPUProcessListener* aListener) {
1281 mListeners.RemoveElement(aListener);
1284 bool GPUProcessManager::NotifyGpuObservers(const char* aTopic) {
1285 if (!EnsureGPUReady()) {
1286 return false;
1288 nsCString topic(aTopic);
1289 mGPUChild->SendNotifyGpuObservers(topic);
1290 return true;
1293 class GPUMemoryReporter : public MemoryReportingProcess {
1294 public:
1295 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(GPUMemoryReporter, override)
1297 bool IsAlive() const override {
1298 if (GPUProcessManager* gpm = GPUProcessManager::Get()) {
1299 return !!gpm->GetGPUChild();
1301 return false;
1304 bool SendRequestMemoryReport(
1305 const uint32_t& aGeneration, const bool& aAnonymize,
1306 const bool& aMinimizeMemoryUsage,
1307 const Maybe<ipc::FileDescriptor>& aDMDFile) override {
1308 GPUChild* child = GetChild();
1309 if (!child) {
1310 return false;
1313 return child->SendRequestMemoryReport(aGeneration, aAnonymize,
1314 aMinimizeMemoryUsage, aDMDFile);
1317 int32_t Pid() const override {
1318 if (GPUChild* child = GetChild()) {
1319 return (int32_t)child->OtherPid();
1321 return 0;
1324 private:
1325 GPUChild* GetChild() const {
1326 if (GPUProcessManager* gpm = GPUProcessManager::Get()) {
1327 if (GPUChild* child = gpm->GetGPUChild()) {
1328 return child;
1331 return nullptr;
1334 protected:
1335 ~GPUMemoryReporter() = default;
1338 RefPtr<MemoryReportingProcess> GPUProcessManager::GetProcessMemoryReporter() {
1339 // Ensure mProcess is non-null before calling EnsureGPUReady, to avoid
1340 // launching the process if it has not already been launched.
1341 if (!mProcess || !EnsureGPUReady()) {
1342 return nullptr;
1344 return new GPUMemoryReporter();
1347 RefPtr<PGPUChild::TestTriggerMetricsPromise>
1348 GPUProcessManager::TestTriggerMetrics() {
1349 if (!NS_WARN_IF(!mGPUChild)) {
1350 return mGPUChild->SendTestTriggerMetrics();
1353 return PGPUChild::TestTriggerMetricsPromise::CreateAndReject(
1354 ipc::ResponseRejectReason::SendError, __func__);
1357 } // namespace gfx
1358 } // namespace mozilla