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"
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"
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)
64 # include "gfxWindowsPlatform.h"
70 using namespace mozilla::layers
;
72 enum class FallbackType
: uint32_t {
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()
94 mUnstableProcessAttempts(0),
95 mTotalProcessAttempts(0),
97 mAppInForeground(true),
100 mProcessStable(true),
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
) {}
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;
147 void GPUProcessManager::OnXPCOMShutdown() {
149 nsContentUtils::UnregisterShutdownObserver(mObserver
);
150 Preferences::RemoveObserver(mObserver
, "");
151 nsCOMPtr
<nsIObserverService
> obsServ
= services::GetObserverService();
153 obsServ
->RemoveObserver(mObserver
, "application-foreground");
154 obsServ
->RemoveObserver(mObserver
, "application-background");
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
);
172 MOZ_ASSERT(mQueuedPrefs
.IsEmpty());
173 mGPUChild
->SendPreferenceUpdate(pref
);
174 } else if (IsGPUProcessLaunching()) {
175 mQueuedPrefs
.AppendElement(pref
);
179 bool GPUProcessManager::LaunchGPUProcess() {
184 if (AppShutdown::IsInOrBeyond(ShutdownPhase::XPCOMShutdown
)) {
188 // Start listening for pref changes so we can
189 // forward them to the process once it is running.
191 mObserver
= new Observer(this);
192 nsContentUtils::RegisterShutdownObserver(mObserver
);
193 Preferences::AddStrongObserver(mObserver
, "");
194 nsCOMPtr
<nsIObserverService
> obsServ
= services::GetObserverService();
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");
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
)) {
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.
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
));
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.
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()) {
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
);
309 if (mGPUChild
->EnsureGPUReady()) {
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");
324 void GPUProcessManager::EnsureProtocolsReady() {
325 EnsureCompositorManagerChild();
326 EnsureImageBridgeChild();
330 void GPUProcessManager::EnsureCompositorManagerChild() {
331 bool gpuReady
= EnsureGPUReady();
332 if (CompositorManagerChild::IsInitialized(mProcessToken
)) {
337 CompositorManagerChild::InitSameProcess(AllocateNamespace(), mProcessToken
);
341 ipc::Endpoint
<PCompositorManagerParent
> parentPipe
;
342 ipc::Endpoint
<PCompositorManagerChild
> childPipe
;
343 nsresult rv
= PCompositorManager::CreateEndpoints(
344 mGPUChild
->OtherPid(), base::GetCurrentProcId(), &parentPipe
, &childPipe
);
346 DisableGPUProcess("Failed to create PCompositorManager endpoints");
350 mGPUChild
->SendInitCompositorManager(std::move(parentPipe
));
351 CompositorManagerChild::Init(std::move(childPipe
), AllocateNamespace(),
355 void GPUProcessManager::EnsureImageBridgeChild() {
356 if (ImageBridgeChild::GetSingleton()) {
360 if (!EnsureGPUReady()) {
361 ImageBridgeChild::InitSameProcess(AllocateNamespace());
365 ipc::Endpoint
<PImageBridgeParent
> parentPipe
;
366 ipc::Endpoint
<PImageBridgeChild
> childPipe
;
367 nsresult rv
= PImageBridge::CreateEndpoints(
368 mGPUChild
->OtherPid(), base::GetCurrentProcId(), &parentPipe
, &childPipe
);
370 DisableGPUProcess("Failed to create PImageBridge endpoints");
374 mGPUChild
->SendInitImageBridge(std::move(parentPipe
));
375 ImageBridgeChild::InitWithGPUProcess(std::move(childPipe
),
376 AllocateNamespace());
379 void GPUProcessManager::EnsureVRManager() {
380 if (VRManagerChild::IsCreated()) {
384 if (!EnsureGPUReady()) {
385 VRManagerChild::InitSameProcess();
389 ipc::Endpoint
<PVRManagerParent
> parentPipe
;
390 ipc::Endpoint
<PVRManagerChild
> childPipe
;
391 nsresult rv
= PVRManager::CreateEndpoints(
392 mGPUChild
->OtherPid(), base::GetCurrentProcId(), &parentPipe
, &childPipe
);
394 DisableGPUProcess("Failed to create PVRManager endpoints");
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
);
411 ipc::Endpoint
<PUiCompositorControllerParent
> parentPipe
;
412 ipc::Endpoint
<PUiCompositorControllerChild
> childPipe
;
413 nsresult rv
= PUiCompositorController::CreateEndpoints(
414 mGPUChild
->OtherPid(), base::GetCurrentProcId(), &parentPipe
,
417 DisableGPUProcess("Failed to create PUiCompositorController endpoints");
421 mGPUChild
->SendInitUiCompositorController(aId
, std::move(parentPipe
));
422 result
= UiCompositorControllerChild::CreateForGPUProcess(
423 mProcessToken
, std::move(childPipe
), aWidget
);
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");
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
);
451 DisableGPUProcess("Failed to create PVsyncBridge endpoints");
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
;
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
513 gfxPlatform::GetPlatform()->CompositorUpdated();
517 mGPUChild
->SendSimulateDeviceReset();
520 wr::RenderThread::Get()->SimulateDeviceReset();
524 bool GPUProcessManager::DisableWebRenderConfig(wr::WebRenderError aError
,
525 const nsCString
& aMsg
) {
526 if (!gfx::gfxVars::UseWebRender()) {
531 if (aError
== wr::WebRenderError::INITIALIZE
) {
532 wantRestart
= gfxPlatform::FallbackFromAcceleration(
533 gfx::FeatureStatus::Unavailable
, "WebRender initialization failed",
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
);
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;
576 void GPUProcessManager::DisableWebRender(wr::WebRenderError aError
,
577 const nsCString
& aMsg
) {
578 if (DisableWebRenderConfig(aError
, aMsg
)) {
580 DestroyRemoteCompositorSessions();
582 DestroyInProcessCompositorSessions();
584 NotifyListenersOnCompositeDeviceReset();
588 void GPUProcessManager::NotifyWebRenderError(wr::WebRenderError aError
) {
589 if (aError
== wr::WebRenderError::VIDEO_OVERLAY
) {
591 gfxVars::SetUseWebRenderDCompVideoOverlayWin(false);
593 MOZ_ASSERT_UNREACHABLE("unexpected to be called");
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
) {
612 // Disable double buffering when device reset happens.
613 if (!gfxVars::UseWebRender() && gfxVars::UseDoubleBufferingWithCompositor()) {
614 gfxVars::SetUseDoubleBufferingWithCompositor(false);
618 // Ignore resets for thresholding if requested.
619 if (!aTrackThreshold
) {
623 // Detect whether the device is resetting too quickly or too much
624 // indicating that we should give up and use software
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());
644 // Ensure device reset handling before re-creating in process sessions.
645 // Normally nsWindow::OnPaint() already handled it.
646 gfxWindowsPlatform::GetPlatform()->HandleDeviceReset();
648 DestroyInProcessCompositorSessions();
649 NotifyListenersOnCompositeDeviceReset();
652 void GPUProcessManager::OnRemoteProcessDeviceReset(GPUProcessHost
* aHost
) {
653 if (OnDeviceReset(/* aTrackThreshold */ true)) {
655 DisableGPUProcess("GPU processed experienced too many device resets");
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;
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
));
699 Telemetry::Accumulate(Telemetry::GPU_PROCESS_CRASH_FALLBACKS
,
700 uint32_t(FallbackType::NONE
));
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
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();
788 // If the GPU process is disabled we can reinitialize rendering immediately.
789 // This will be handled in OnProcessLaunchComplete() if the GPU process is
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",
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());
851 if (mProcessToken
!= aProcessToken
) {
852 // This token is for an older process; we can safely ignore it.
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() {
865 mVsyncIOThread
= nullptr;
868 void GPUProcessManager::KillProcess() {
873 mProcess
->KillProcess();
876 void GPUProcessManager::CrashProcess() {
881 mProcess
->CrashProcess();
884 void GPUProcessManager::DestroyProcess(bool aUnexpectedShutdown
) {
889 mProcess
->Shutdown(aUnexpectedShutdown
);
893 mQueuedPrefs
.Clear();
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
);
921 // We couldn't create a remote compositor, so abort the process.
922 DisableGPUProcess("Failed to create remote compositor");
927 session
= InProcessCompositorSession::Create(
928 aWidget
, aLayerManager
, layerTreeId
, aScale
, aOptions
,
929 aUseExternalSurfaceSize
, aSurfaceSize
, AllocateNamespace(),
933 #if defined(MOZ_WIDGET_ANDROID)
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)
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
);
960 gfxCriticalNote
<< "Failed to create CompositorBridgeChild";
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
)) {
974 if (!widget
->Initialize()) {
977 if (!child
->SendInitialize(aRootLayerTreeId
)) {
981 RefPtr
<APZCTreeManagerChild
> apz
= nullptr;
982 if (aOptions
.UseAPZ()) {
983 PAPZCTreeManagerChild
* papz
=
984 child
->SendPAPZCTreeManagerConstructor(LayersId
{0});
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
);
998 mGPUChild
->SendInitAPZInputBridge(aRootLayerTreeId
, std::move(parentPipe
));
1000 RefPtr
<APZInputBridgeChild
> inputBridge
=
1001 APZInputBridgeChild::Create(mProcessToken
, std::move(childPipe
));
1006 apz
->SetInputBridge(inputBridge
);
1009 return new RemoteCompositorSession(aWidget
, child
, widget
, apz
,
1012 gfxCriticalNote
<< "Platform does not support out-of-process compositing";
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
)) {
1029 // VideoDeocderManager is only supported in the GPU process, so we allow this
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());
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: "
1058 mGPUChild
->SendNewContentCompositorManager(std::move(parentPipe
));
1059 } else if (!CompositorManagerParent::Create(std::move(parentPipe
),
1060 /* aIsRoot */ false)) {
1064 *aOutEndpoint
= std::move(childPipe
);
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: "
1087 mGPUChild
->SendNewContentImageBridge(std::move(parentPipe
));
1089 if (!ImageBridgeParent::CreateForContent(std::move(parentPipe
))) {
1094 *aOutEndpoint
= std::move(childPipe
);
1098 base::ProcessId
GPUProcessManager::GPUProcessPid() {
1099 base::ProcessId gpuPid
=
1100 mGPUChild
? mGPUChild
->OtherPid() : base::kInvalidProcessId
;
1104 bool GPUProcessManager::CreateContentVRManager(
1105 base::ProcessId aOtherProcess
,
1106 ipc::Endpoint
<PVRManagerChild
>* aOutEndpoint
) {
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: "
1123 mGPUChild
->SendNewContentVRManager(std::move(parentPipe
));
1125 if (!VRManagerParent::CreateForContent(std::move(parentPipe
))) {
1130 *aOutEndpoint
= std::move(childPipe
);
1134 void GPUProcessManager::CreateContentRemoteDecoderManager(
1135 base::ProcessId aOtherProcess
,
1136 ipc::Endpoint
<PRemoteDecoderManagerChild
>* aOutEndpoint
) {
1137 if (!EnsureGPUReady() || !StaticPrefs::media_gpu_process_decoder() ||
1138 !mDecodeVideoOnGpuProcess
) {
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: "
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
));
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());
1204 if (mResourceId
== UINT32_MAX
) {
1205 // Move to next id namespace.
1206 mIdNamespace
= AllocateNamespace();
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
) {
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
) {
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()) {
1288 nsCString
topic(aTopic
);
1289 mGPUChild
->SendNotifyGpuObservers(topic
);
1293 class GPUMemoryReporter
: public MemoryReportingProcess
{
1295 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(GPUMemoryReporter
, override
)
1297 bool IsAlive() const override
{
1298 if (GPUProcessManager
* gpm
= GPUProcessManager::Get()) {
1299 return !!gpm
->GetGPUChild();
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();
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();
1325 GPUChild
* GetChild() const {
1326 if (GPUProcessManager
* gpm
= GPUProcessManager::Get()) {
1327 if (GPUChild
* child
= gpm
->GetGPUChild()) {
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()) {
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__
);
1358 } // namespace mozilla