Bug 1890689 accumulate input in LargerReceiverBlockSizeThanDesiredBuffering GTest...
[gecko.git] / gfx / ipc / GPUParent.cpp
blobf4240a5d97d6d0227e93875120288d0e35078ac5
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 #ifdef XP_WIN
8 # include "WMF.h"
9 # include "WMFDecoderModule.h"
10 #endif
11 #include "GLContextProvider.h"
12 #include "GPUParent.h"
13 #include "GPUProcessHost.h"
14 #include "GPUProcessManager.h"
15 #include "gfxGradientCache.h"
16 #include "GfxInfoBase.h"
17 #include "VRGPUChild.h"
18 #include "VRManager.h"
19 #include "VRManagerParent.h"
20 #include "VsyncBridgeParent.h"
21 #include "cairo.h"
22 #include "gfxConfig.h"
23 #include "gfxCrashReporterUtils.h"
24 #include "gfxPlatform.h"
25 #include "mozilla/Assertions.h"
26 #include "mozilla/Components.h"
27 #include "mozilla/FOGIPC.h"
28 #include "mozilla/HangDetails.h"
29 #include "mozilla/PerfStats.h"
30 #include "mozilla/Preferences.h"
31 #include "mozilla/ProcessPriorityManager.h"
32 #include "mozilla/RemoteDecoderManagerChild.h"
33 #include "mozilla/RemoteDecoderManagerParent.h"
34 #include "mozilla/ScopeExit.h"
35 #include "mozilla/StaticPrefs_dom.h"
36 #include "mozilla/StaticPrefs_media.h"
37 #include "mozilla/Telemetry.h"
38 #include "mozilla/TimeStamp.h"
39 #include "mozilla/dom/MemoryReportRequest.h"
40 #include "mozilla/gfx/2D.h"
41 #include "mozilla/gfx/CanvasRenderThread.h"
42 #include "mozilla/gfx/gfxVars.h"
43 #include "mozilla/glean/GleanMetrics.h"
44 #include "mozilla/image/ImageMemoryReporter.h"
45 #include "mozilla/ipc/CrashReporterClient.h"
46 #include "mozilla/ipc/ProcessChild.h"
47 #include "mozilla/ipc/ProcessUtils.h"
48 #include "mozilla/layers/APZInputBridgeParent.h"
49 #include "mozilla/layers/APZPublicUtils.h" // for apz::InitializeGlobalState
50 #include "mozilla/layers/APZThreadUtils.h"
51 #include "mozilla/layers/CompositorBridgeParent.h"
52 #include "mozilla/layers/CompositorManagerParent.h"
53 #include "mozilla/layers/CompositorThread.h"
54 #include "mozilla/layers/ImageBridgeParent.h"
55 #include "mozilla/layers/LayerTreeOwnerTracker.h"
56 #include "mozilla/layers/RemoteTextureMap.h"
57 #include "mozilla/layers/UiCompositorControllerParent.h"
58 #include "mozilla/layers/VideoBridgeParent.h"
59 #include "mozilla/webrender/RenderThread.h"
60 #include "mozilla/webrender/WebRenderAPI.h"
61 #include "nsDebugImpl.h"
62 #include "nsIGfxInfo.h"
63 #include "nsIXULRuntime.h"
64 #include "nsThreadManager.h"
65 #include "nscore.h"
66 #include "prenv.h"
67 #include "skia/include/core/SkGraphics.h"
68 #if defined(XP_WIN)
69 # include <dwrite.h>
70 # include <process.h>
71 # include <windows.h>
73 # include "gfxDWriteFonts.h"
74 # include "gfxWindowsPlatform.h"
75 # include "mozilla/WindowsVersion.h"
76 # include "mozilla/gfx/DeviceManagerDx.h"
77 # include "mozilla/layers/GpuProcessD3D11TextureMap.h"
78 # include "mozilla/layers/GpuProcessD3D11QueryMap.h"
79 # include "mozilla/layers/TextureD3D11.h"
80 # include "mozilla/widget/WinCompositorWindowThread.h"
81 # include "MediaCodecsSupport.h"
82 # include "WMFDecoderModule.h"
83 #else
84 # include <unistd.h>
85 #endif
86 #ifdef MOZ_WIDGET_GTK
87 # include <gtk/gtk.h>
89 # include "skia/include/ports/SkTypeface_cairo.h"
90 #endif
91 #ifdef ANDROID
92 # include "mozilla/layers/AndroidHardwareBuffer.h"
93 # include "skia/include/ports/SkTypeface_cairo.h"
94 #endif
95 #include "ChildProfilerController.h"
96 #include "nsAppRunner.h"
98 #if defined(MOZ_SANDBOX) && defined(MOZ_DEBUG) && defined(ENABLE_TESTS)
99 # include "mozilla/SandboxTestingChild.h"
100 #endif
102 namespace mozilla::gfx {
104 using namespace ipc;
105 using namespace layers;
107 static GPUParent* sGPUParent;
109 static void ReportHardwareMediaCodecSupportIfNeeded() {
110 // We only need to report the result once.
111 static bool sReported = false;
112 if (sReported) {
113 return;
115 #if defined(XP_WIN)
116 NS_GetCurrentThread()->Dispatch(NS_NewRunnableFunction(
117 "GPUParent:ReportHardwareMediaCodecSupportIfNeeded", []() {
118 // Only report telemetry when hardware decoding is available.
119 if (!gfx::gfxVars::IsInitialized() ||
120 !gfx::gfxVars::CanUseHardwareVideoDecoding()) {
121 return;
123 sReported = true;
125 // TODO : we can remove this after HEVC is enabled by default.
126 // HEVC is not enabled. We need to force to enable it in order to know
127 // its support as well, and it would be turn off later.
128 if (StaticPrefs::media_wmf_hevc_enabled() != 1) {
129 WMFDecoderModule::Init(WMFDecoderModule::Config::ForceEnableHEVC);
131 const auto support = PDMFactory::Supported(true /* force refresh */);
132 if (support.contains(
133 mozilla::media::MediaCodecsSupport::H264HardwareDecode)) {
134 Telemetry::ScalarSet(
135 Telemetry::ScalarID::MEDIA_DEVICE_HARDWARE_DECODING_SUPPORT,
136 u"h264"_ns, true);
138 if (support.contains(
139 mozilla::media::MediaCodecsSupport::VP8HardwareDecode)) {
140 Telemetry::ScalarSet(
141 Telemetry::ScalarID::MEDIA_DEVICE_HARDWARE_DECODING_SUPPORT,
142 u"vp8"_ns, true);
144 if (support.contains(
145 mozilla::media::MediaCodecsSupport::VP9HardwareDecode)) {
146 Telemetry::ScalarSet(
147 Telemetry::ScalarID::MEDIA_DEVICE_HARDWARE_DECODING_SUPPORT,
148 u"vp9"_ns, true);
150 if (support.contains(
151 mozilla::media::MediaCodecsSupport::AV1HardwareDecode)) {
152 Telemetry::ScalarSet(
153 Telemetry::ScalarID::MEDIA_DEVICE_HARDWARE_DECODING_SUPPORT,
154 u"av1"_ns, true);
156 if (support.contains(
157 mozilla::media::MediaCodecsSupport::HEVCHardwareDecode)) {
158 Telemetry::ScalarSet(
159 Telemetry::ScalarID::MEDIA_DEVICE_HARDWARE_DECODING_SUPPORT,
160 u"hevc"_ns, true);
162 if (StaticPrefs::media_wmf_hevc_enabled() != 1) {
163 WMFDecoderModule::Init();
165 }));
166 #endif
167 // TODO : in the future, when we have GPU procss on MacOS, then we can report
168 // HEVC usage as well.
171 GPUParent::GPUParent() : mLaunchTime(TimeStamp::Now()) { sGPUParent = this; }
173 GPUParent::~GPUParent() { sGPUParent = nullptr; }
175 /* static */
176 GPUParent* GPUParent::GetSingleton() {
177 MOZ_DIAGNOSTIC_ASSERT(sGPUParent);
178 return sGPUParent;
181 /* static */ bool GPUParent::MaybeFlushMemory() {
182 #if defined(XP_WIN) && !defined(HAVE_64BIT_BUILD)
183 MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
184 if (!XRE_IsGPUProcess()) {
185 return false;
188 MEMORYSTATUSEX stat;
189 stat.dwLength = sizeof(stat);
190 if (!GlobalMemoryStatusEx(&stat)) {
191 return false;
194 // We only care about virtual process memory space in the GPU process because
195 // the UI process is already watching total memory usage.
196 static const size_t kLowVirtualMemoryThreshold = 384 * 1024 * 1024;
197 bool lowMemory = stat.ullAvailVirtual < kLowVirtualMemoryThreshold;
199 // We suppress more than one low memory notification until we exit the
200 // condition. The UI process goes through more effort, reporting on-going
201 // memory pressure, but rather than try to manage a shared state, we just
202 // send one notification here to try to resolve it.
203 static bool sLowMemory = false;
204 if (lowMemory && !sLowMemory) {
205 NS_DispatchToMainThread(
206 NS_NewRunnableFunction("gfx::GPUParent::FlushMemory", []() -> void {
207 Unused << GPUParent::GetSingleton()->SendFlushMemory(
208 u"low-memory"_ns);
209 }));
211 sLowMemory = lowMemory;
212 return lowMemory;
213 #else
214 return false;
215 #endif
218 bool GPUParent::Init(mozilla::ipc::UntypedEndpoint&& aEndpoint,
219 const char* aParentBuildID) {
220 // Initialize the thread manager before starting IPC. Otherwise, messages
221 // may be posted to the main thread and we won't be able to process them.
222 if (NS_WARN_IF(NS_FAILED(nsThreadManager::get().Init()))) {
223 return false;
226 // Now it's safe to start IPC.
227 if (NS_WARN_IF(!aEndpoint.Bind(this))) {
228 return false;
231 nsDebugImpl::SetMultiprocessMode("GPU");
233 // This must be checked before any IPDL message, which may hit sentinel
234 // errors due to parent and content processes having different
235 // versions.
236 MessageChannel* channel = GetIPCChannel();
237 if (channel && !channel->SendBuildIDsMatchMessage(aParentBuildID)) {
238 // We need to quit this process if the buildID doesn't match the parent's.
239 // This can occur when an update occurred in the background.
240 ProcessChild::QuickExit();
243 if (NS_FAILED(NS_InitMinimalXPCOM())) {
244 return false;
247 // Ensure the observer service exists.
248 ProcessPriorityManager::Init();
250 // Init crash reporter support.
251 CrashReporterClient::InitSingleton(this);
253 gfxConfig::Init();
254 gfxVars::Initialize();
255 gfxPlatform::InitNullMetadata();
256 // Ensure our Factory is initialised, mainly for gfx logging to work.
257 gfxPlatform::InitMoz2DLogging();
258 #if defined(XP_WIN)
259 gfxWindowsPlatform::InitMemoryReportersForGPUProcess();
260 DeviceManagerDx::Init();
261 GpuProcessD3D11TextureMap::Init();
262 GpuProcessD3D11QueryMap::Init();
263 #endif
265 CompositorThreadHolder::Start();
266 RemoteTextureMap::Init();
267 APZThreadUtils::SetControllerThread(NS_GetCurrentThread());
268 apz::InitializeGlobalState();
269 LayerTreeOwnerTracker::Initialize();
270 CompositorBridgeParent::InitializeStatics();
271 mozilla::ipc::SetThisProcessName("GPU Process");
273 return true;
276 void GPUParent::NotifyDeviceReset() {
277 if (!NS_IsMainThread()) {
278 NS_DispatchToMainThread(NS_NewRunnableFunction(
279 "gfx::GPUParent::NotifyDeviceReset",
280 []() -> void { GPUParent::GetSingleton()->NotifyDeviceReset(); }));
281 return;
284 // Reset and reinitialize the compositor devices
285 #ifdef XP_WIN
286 if (!DeviceManagerDx::Get()->MaybeResetAndReacquireDevices()) {
287 // If the device doesn't need to be reset then the device
288 // has already been reset by a previous NotifyDeviceReset message.
289 return;
291 #endif
293 // Notify the main process that there's been a device reset
294 // and that they should reset their compositors and repaint
295 GPUDeviceData data;
296 RecvGetDeviceStatus(&data);
297 Unused << SendNotifyDeviceReset(data);
300 void GPUParent::NotifyOverlayInfo(layers::OverlayInfo aInfo) {
301 if (!NS_IsMainThread()) {
302 NS_DispatchToMainThread(NS_NewRunnableFunction(
303 "gfx::GPUParent::NotifyOverlayInfo", [aInfo]() -> void {
304 GPUParent::GetSingleton()->NotifyOverlayInfo(aInfo);
305 }));
306 return;
308 Unused << SendNotifyOverlayInfo(aInfo);
311 void GPUParent::NotifySwapChainInfo(layers::SwapChainInfo aInfo) {
312 if (!NS_IsMainThread()) {
313 NS_DispatchToMainThread(NS_NewRunnableFunction(
314 "gfx::GPUParent::NotifySwapChainInfo", [aInfo]() -> void {
315 GPUParent::GetSingleton()->NotifySwapChainInfo(aInfo);
316 }));
317 return;
319 Unused << SendNotifySwapChainInfo(aInfo);
322 void GPUParent::NotifyDisableRemoteCanvas() {
323 if (!NS_IsMainThread()) {
324 NS_DispatchToMainThread(NS_NewRunnableFunction(
325 "gfx::GPUParent::NotifyDisableRemoteCanvas", []() -> void {
326 GPUParent::GetSingleton()->NotifyDisableRemoteCanvas();
327 }));
328 return;
330 Unused << SendNotifyDisableRemoteCanvas();
333 mozilla::ipc::IPCResult GPUParent::RecvInit(
334 nsTArray<GfxVarUpdate>&& vars, const DevicePrefs& devicePrefs,
335 nsTArray<LayerTreeIdMapping>&& aMappings,
336 nsTArray<GfxInfoFeatureStatus>&& aFeatures, uint32_t aWrNamespace) {
337 for (const auto& var : vars) {
338 gfxVars::ApplyUpdate(var);
341 // Inherit device preferences.
342 gfxConfig::Inherit(Feature::HW_COMPOSITING, devicePrefs.hwCompositing());
343 gfxConfig::Inherit(Feature::D3D11_COMPOSITING,
344 devicePrefs.d3d11Compositing());
345 gfxConfig::Inherit(Feature::OPENGL_COMPOSITING, devicePrefs.oglCompositing());
346 gfxConfig::Inherit(Feature::DIRECT2D, devicePrefs.useD2D1());
347 gfxConfig::Inherit(Feature::D3D11_HW_ANGLE, devicePrefs.d3d11HwAngle());
349 { // Let the crash reporter know if we've got WR enabled or not. For other
350 // processes this happens in gfxPlatform::InitWebRenderConfig.
351 ScopedGfxFeatureReporter reporter("WR",
352 gfxPlatform::WebRenderPrefEnabled());
353 reporter.SetSuccessful();
356 for (const LayerTreeIdMapping& map : aMappings) {
357 LayerTreeOwnerTracker::Get()->Map(map.layersId(), map.ownerId());
360 widget::GfxInfoBase::SetFeatureStatus(std::move(aFeatures));
362 // We bypass gfxPlatform::Init, so we must initialize any relevant libraries
363 // here that would normally be initialized there.
364 SkGraphics::Init();
366 bool useRemoteCanvas =
367 gfxVars::RemoteCanvasEnabled() || gfxVars::UseAcceleratedCanvas2D();
368 if (useRemoteCanvas) {
369 gfxGradientCache::Init();
372 #if defined(XP_WIN)
373 if (gfxConfig::IsEnabled(Feature::D3D11_COMPOSITING)) {
374 if (DeviceManagerDx::Get()->CreateCompositorDevices() && useRemoteCanvas) {
375 if (DeviceManagerDx::Get()->CreateCanvasDevice()) {
376 gfxDWriteFont::InitDWriteSupport();
377 } else {
378 gfxWarning() << "Failed to create canvas device.";
382 DeviceManagerDx::Get()->CreateDirectCompositionDevice();
383 // Ensure to initialize GfxInfo
384 nsCOMPtr<nsIGfxInfo> gfxInfo = components::GfxInfo::Service();
385 Unused << gfxInfo;
387 Factory::EnsureDWriteFactory();
388 #endif
390 #if defined(MOZ_WIDGET_GTK)
391 char* display_name = PR_GetEnv("MOZ_GDK_DISPLAY");
392 if (!display_name) {
393 bool waylandEnabled = false;
394 # ifdef MOZ_WAYLAND
395 waylandEnabled = IsWaylandEnabled();
396 # endif
397 if (!waylandEnabled) {
398 display_name = PR_GetEnv("DISPLAY");
401 if (display_name) {
402 int argc = 3;
403 char option_name[] = "--display";
404 char* argv[] = {// argv0 is unused because g_set_prgname() was called in
405 // XRE_InitChildProcess().
406 nullptr, option_name, display_name, nullptr};
407 char** argvp = argv;
408 gtk_init(&argc, &argvp);
409 } else {
410 gtk_init(nullptr, nullptr);
413 // Ensure we have an FT library for font instantiation.
414 // This would normally be set by gfxPlatform::Init().
415 // Since we bypass that, we must do it here instead.
416 FT_Library library = Factory::NewFTLibrary();
417 MOZ_ASSERT(library);
418 Factory::SetFTLibrary(library);
420 // true to match gfxPlatform::FontHintingEnabled(). We must hardcode
421 // this value because we do not have a gfxPlatform instance.
422 SkInitCairoFT(true);
424 // Ensure that GfxInfo::Init is called on the main thread.
425 nsCOMPtr<nsIGfxInfo> gfxInfo = components::GfxInfo::Service();
426 Unused << gfxInfo;
427 #endif
429 #ifdef ANDROID
430 // Ensure we have an FT library for font instantiation.
431 // This would normally be set by gfxPlatform::Init().
432 // Since we bypass that, we must do it here instead.
433 FT_Library library = Factory::NewFTLibrary();
434 MOZ_ASSERT(library);
435 Factory::SetFTLibrary(library);
437 // false to match gfxAndroidPlatform::FontHintingEnabled(). We must
438 // hardcode this value because we do not have a gfxPlatform instance.
439 SkInitCairoFT(false);
441 if (gfxVars::UseAHardwareBufferSharedSurfaceWebglOop()) {
442 layers::AndroidHardwareBufferApi::Init();
443 layers::AndroidHardwareBufferManager::Init();
446 #endif
448 // Make sure to do this *after* we update gfxVars above.
449 wr::RenderThread::Start(aWrNamespace);
450 gfx::CanvasRenderThread::Start();
451 image::ImageMemoryReporter::InitForWebRender();
453 VRManager::ManagerInit();
454 // Send a message to the UI process that we're done.
455 GPUDeviceData data;
456 RecvGetDeviceStatus(&data);
457 Unused << SendInitComplete(data);
459 // Dispatch a task to run when idle that will determine which codecs are
460 // usable. The primary goal is to determine if the media feature pack is
461 // installed.
462 MOZ_ALWAYS_SUCCEEDS(NS_DispatchToCurrentThreadQueue(
463 NS_NewRunnableFunction(
464 "GPUParent::Supported",
465 []() {
466 auto supported = PDMFactory::Supported();
467 Unused << GPUParent::GetSingleton()->SendUpdateMediaCodecsSupported(
468 supported);
469 ReportHardwareMediaCodecSupportIfNeeded();
471 2000 /* 2 seconds timeout */, EventQueuePriority::Idle));
473 Telemetry::AccumulateTimeDelta(Telemetry::GPU_PROCESS_INITIALIZATION_TIME_MS,
474 mLaunchTime);
475 return IPC_OK();
478 #if defined(MOZ_SANDBOX) && defined(MOZ_DEBUG) && defined(ENABLE_TESTS)
479 mozilla::ipc::IPCResult GPUParent::RecvInitSandboxTesting(
480 Endpoint<PSandboxTestingChild>&& aEndpoint) {
481 if (!SandboxTestingChild::Initialize(std::move(aEndpoint))) {
482 return IPC_FAIL(
483 this, "InitSandboxTesting failed to initialise the child process.");
485 return IPC_OK();
487 #endif
489 mozilla::ipc::IPCResult GPUParent::RecvInitCompositorManager(
490 Endpoint<PCompositorManagerParent>&& aEndpoint, uint32_t aNamespace) {
491 CompositorManagerParent::Create(std::move(aEndpoint), ContentParentId(),
492 aNamespace, /* aIsRoot */ true);
493 return IPC_OK();
496 mozilla::ipc::IPCResult GPUParent::RecvInitVsyncBridge(
497 Endpoint<PVsyncBridgeParent>&& aVsyncEndpoint) {
498 mVsyncBridge = VsyncBridgeParent::Start(std::move(aVsyncEndpoint));
499 return IPC_OK();
502 mozilla::ipc::IPCResult GPUParent::RecvInitImageBridge(
503 Endpoint<PImageBridgeParent>&& aEndpoint) {
504 ImageBridgeParent::CreateForGPUProcess(std::move(aEndpoint));
505 return IPC_OK();
508 mozilla::ipc::IPCResult GPUParent::RecvInitVideoBridge(
509 Endpoint<PVideoBridgeParent>&& aEndpoint,
510 const layers::VideoBridgeSource& aSource) {
511 // For GPU decoding, the video bridge would be opened in
512 // `VideoBridgeChild::StartupForGPUProcess`.
513 MOZ_ASSERT(aSource == layers::VideoBridgeSource::RddProcess ||
514 aSource == layers::VideoBridgeSource::MFMediaEngineCDMProcess);
515 VideoBridgeParent::Open(std::move(aEndpoint), aSource);
516 return IPC_OK();
519 mozilla::ipc::IPCResult GPUParent::RecvInitVRManager(
520 Endpoint<PVRManagerParent>&& aEndpoint) {
521 VRManagerParent::CreateForGPUProcess(std::move(aEndpoint));
522 return IPC_OK();
525 mozilla::ipc::IPCResult GPUParent::RecvInitVR(
526 Endpoint<PVRGPUChild>&& aEndpoint) {
527 gfx::VRGPUChild::InitForGPUProcess(std::move(aEndpoint));
528 return IPC_OK();
531 mozilla::ipc::IPCResult GPUParent::RecvInitUiCompositorController(
532 const LayersId& aRootLayerTreeId,
533 Endpoint<PUiCompositorControllerParent>&& aEndpoint) {
534 UiCompositorControllerParent::Start(aRootLayerTreeId, std::move(aEndpoint));
535 return IPC_OK();
538 mozilla::ipc::IPCResult GPUParent::RecvInitAPZInputBridge(
539 const LayersId& aRootLayerTreeId,
540 Endpoint<PAPZInputBridgeParent>&& aEndpoint) {
541 APZInputBridgeParent::Create(aRootLayerTreeId, std::move(aEndpoint));
542 return IPC_OK();
545 mozilla::ipc::IPCResult GPUParent::RecvInitProfiler(
546 Endpoint<PProfilerChild>&& aEndpoint) {
547 mProfilerController = ChildProfilerController::Create(std::move(aEndpoint));
548 return IPC_OK();
551 mozilla::ipc::IPCResult GPUParent::RecvUpdateVar(const GfxVarUpdate& aUpdate) {
552 #if defined(XP_WIN)
553 auto scopeExit = MakeScopeExit(
554 [couldUseHWDecoder = gfx::gfxVars::CanUseHardwareVideoDecoding()] {
555 if (couldUseHWDecoder != gfx::gfxVars::CanUseHardwareVideoDecoding()) {
556 // The capabilities of the system may have changed, force a refresh by
557 // re-initializing the WMF PDM.
558 WMFDecoderModule::Init();
559 Unused << GPUParent::GetSingleton()->SendUpdateMediaCodecsSupported(
560 PDMFactory::Supported(true /* force refresh */));
561 ReportHardwareMediaCodecSupportIfNeeded();
564 #endif
565 gfxVars::ApplyUpdate(aUpdate);
566 return IPC_OK();
569 mozilla::ipc::IPCResult GPUParent::RecvPreferenceUpdate(const Pref& aPref) {
570 Preferences::SetPreference(aPref);
571 return IPC_OK();
574 mozilla::ipc::IPCResult GPUParent::RecvScreenInformationChanged() {
575 #if defined(XP_WIN)
576 DeviceManagerDx::Get()->PostUpdateMonitorInfo();
577 #endif
578 return IPC_OK();
581 mozilla::ipc::IPCResult GPUParent::RecvNotifyBatteryInfo(
582 const BatteryInformation& aBatteryInfo) {
583 wr::RenderThread::Get()->SetBatteryInfo(aBatteryInfo);
584 return IPC_OK();
587 static void CopyFeatureChange(Feature aFeature, Maybe<FeatureFailure>* aOut) {
588 FeatureState& feature = gfxConfig::GetFeature(aFeature);
589 if (feature.DisabledByDefault() || feature.IsEnabled()) {
590 // No change:
591 // - Disabled-by-default means the parent process told us not to use this
592 // feature.
593 // - Enabled means we were told to use this feature, and we didn't
594 // discover anything
595 // that would prevent us from doing so.
596 *aOut = Nothing();
597 return;
600 MOZ_ASSERT(!feature.IsEnabled());
602 nsCString message;
603 message.AssignASCII(feature.GetFailureMessage());
605 *aOut =
606 Some(FeatureFailure(feature.GetValue(), message, feature.GetFailureId()));
609 mozilla::ipc::IPCResult GPUParent::RecvGetDeviceStatus(GPUDeviceData* aOut) {
610 CopyFeatureChange(Feature::D3D11_COMPOSITING, &aOut->d3d11Compositing());
611 CopyFeatureChange(Feature::OPENGL_COMPOSITING, &aOut->oglCompositing());
613 #if defined(XP_WIN)
614 if (DeviceManagerDx* dm = DeviceManagerDx::Get()) {
615 D3D11DeviceStatus deviceStatus;
616 dm->ExportDeviceInfo(&deviceStatus);
617 aOut->gpuDevice() = Some(deviceStatus);
619 #else
620 aOut->gpuDevice() = Nothing();
621 #endif
623 return IPC_OK();
626 mozilla::ipc::IPCResult GPUParent::RecvSimulateDeviceReset() {
627 #if defined(XP_WIN)
628 DeviceManagerDx::Get()->ForceDeviceReset(
629 ForcedDeviceResetReason::COMPOSITOR_UPDATED);
630 #endif
631 wr::RenderThread::Get()->SimulateDeviceReset();
632 return IPC_OK();
635 mozilla::ipc::IPCResult GPUParent::RecvNewContentCompositorManager(
636 Endpoint<PCompositorManagerParent>&& aEndpoint,
637 const ContentParentId& aChildId, uint32_t aNamespace) {
638 CompositorManagerParent::Create(std::move(aEndpoint), aChildId, aNamespace,
639 /* aIsRoot */ false);
640 return IPC_OK();
643 mozilla::ipc::IPCResult GPUParent::RecvNewContentImageBridge(
644 Endpoint<PImageBridgeParent>&& aEndpoint, const ContentParentId& aChildId) {
645 if (!ImageBridgeParent::CreateForContent(std::move(aEndpoint), aChildId)) {
646 return IPC_FAIL_NO_REASON(this);
648 return IPC_OK();
651 mozilla::ipc::IPCResult GPUParent::RecvNewContentVRManager(
652 Endpoint<PVRManagerParent>&& aEndpoint, const ContentParentId& aChildId) {
653 if (!VRManagerParent::CreateForContent(std::move(aEndpoint), aChildId)) {
654 return IPC_FAIL_NO_REASON(this);
656 return IPC_OK();
659 mozilla::ipc::IPCResult GPUParent::RecvNewContentRemoteDecoderManager(
660 Endpoint<PRemoteDecoderManagerParent>&& aEndpoint,
661 const ContentParentId& aChildId) {
662 if (!RemoteDecoderManagerParent::CreateForContent(std::move(aEndpoint),
663 aChildId)) {
664 return IPC_FAIL_NO_REASON(this);
666 return IPC_OK();
669 mozilla::ipc::IPCResult GPUParent::RecvAddLayerTreeIdMapping(
670 const LayerTreeIdMapping& aMapping) {
671 LayerTreeOwnerTracker::Get()->Map(aMapping.layersId(), aMapping.ownerId());
672 return IPC_OK();
675 mozilla::ipc::IPCResult GPUParent::RecvRemoveLayerTreeIdMapping(
676 const LayerTreeIdMapping& aMapping) {
677 LayerTreeOwnerTracker::Get()->Unmap(aMapping.layersId(), aMapping.ownerId());
678 CompositorBridgeParent::DeallocateLayerTreeId(aMapping.layersId());
679 return IPC_OK();
682 mozilla::ipc::IPCResult GPUParent::RecvNotifyGpuObservers(
683 const nsCString& aTopic) {
684 nsCOMPtr<nsIObserverService> obsSvc = mozilla::services::GetObserverService();
685 MOZ_ASSERT(obsSvc);
686 if (obsSvc) {
687 obsSvc->NotifyObservers(nullptr, aTopic.get(), nullptr);
689 return IPC_OK();
692 /* static */
693 void GPUParent::GetGPUProcessName(nsACString& aStr) {
694 auto processType = XRE_GetProcessType();
695 unsigned pid = 0;
696 if (processType == GeckoProcessType_GPU) {
697 pid = getpid();
698 } else {
699 MOZ_DIAGNOSTIC_ASSERT(processType == GeckoProcessType_Default);
700 pid = GPUProcessManager::Get()->GPUProcessPid();
703 nsPrintfCString processName("GPU (pid %u)", pid);
704 aStr.Assign(processName);
707 mozilla::ipc::IPCResult GPUParent::RecvRequestMemoryReport(
708 const uint32_t& aGeneration, const bool& aAnonymize,
709 const bool& aMinimizeMemoryUsage, const Maybe<FileDescriptor>& aDMDFile,
710 const RequestMemoryReportResolver& aResolver) {
711 nsAutoCString processName;
712 GetGPUProcessName(processName);
714 mozilla::dom::MemoryReportRequestClient::Start(
715 aGeneration, aAnonymize, aMinimizeMemoryUsage, aDMDFile, processName,
716 [&](const MemoryReport& aReport) {
717 Unused << GetSingleton()->SendAddMemoryReport(aReport);
719 aResolver);
720 return IPC_OK();
723 mozilla::ipc::IPCResult GPUParent::RecvShutdownVR() {
724 if (StaticPrefs::dom_vr_process_enabled_AtStartup()) {
725 VRGPUChild::Shutdown();
727 return IPC_OK();
730 mozilla::ipc::IPCResult GPUParent::RecvUpdatePerfStatsCollectionMask(
731 const uint64_t& aMask) {
732 PerfStats::SetCollectionMask(static_cast<PerfStats::MetricMask>(aMask));
733 return IPC_OK();
736 mozilla::ipc::IPCResult GPUParent::RecvCollectPerfStatsJSON(
737 CollectPerfStatsJSONResolver&& aResolver) {
738 aResolver(PerfStats::CollectLocalPerfStatsJSON());
739 return IPC_OK();
742 mozilla::ipc::IPCResult GPUParent::RecvFlushFOGData(
743 FlushFOGDataResolver&& aResolver) {
744 glean::FlushFOGData(std::move(aResolver));
745 return IPC_OK();
748 mozilla::ipc::IPCResult GPUParent::RecvTestTriggerMetrics(
749 TestTriggerMetricsResolver&& aResolve) {
750 mozilla::glean::test_only_ipc::a_counter.Add(nsIXULRuntime::PROCESS_TYPE_GPU);
751 aResolve(true);
752 return IPC_OK();
755 mozilla::ipc::IPCResult GPUParent::RecvCrashProcess() {
756 MOZ_CRASH("Deliberate GPU process crash");
757 return IPC_OK();
760 void GPUParent::ActorDestroy(ActorDestroyReason aWhy) {
761 if (AbnormalShutdown == aWhy) {
762 NS_WARNING("Shutting down GPU process early due to a crash!");
763 ProcessChild::QuickExit();
766 // Send the last bits of Glean data over to the main process.
767 glean::FlushFOGData(
768 [](ByteBuf&& aBuf) { glean::SendFOGData(std::move(aBuf)); });
770 #ifndef NS_FREE_PERMANENT_DATA
771 // No point in going through XPCOM shutdown because we don't keep persistent
772 // state.
773 ProcessChild::QuickExit();
774 #endif
776 // Wait until all RemoteDecoderManagerParent have closed.
777 mShutdownBlockers.WaitUntilClear(10 * 1000 /* 10s timeout*/)
778 ->Then(GetCurrentSerialEventTarget(), __func__, [self = RefPtr{this}]() {
779 if (self->mProfilerController) {
780 self->mProfilerController->Shutdown();
781 self->mProfilerController = nullptr;
784 if (self->mVsyncBridge) {
785 self->mVsyncBridge->Shutdown();
786 self->mVsyncBridge = nullptr;
788 VideoBridgeParent::Shutdown();
789 // This could be running on either the Compositor thread, the Renderer
790 // thread, or the dedicated CanvasRender thread, so we need to shutdown
791 // before the former two.
792 CanvasRenderThread::Shutdown();
793 CompositorThreadHolder::Shutdown();
794 RemoteTextureMap::Shutdown();
795 // There is a case that RenderThread exists when gfxVars::UseWebRender()
796 // is false. This could happen when WebRender was fallbacked to
797 // compositor.
798 if (wr::RenderThread::Get()) {
799 wr::RenderThread::ShutDown();
801 #ifdef XP_WIN
802 if (widget::WinCompositorWindowThread::Get()) {
803 widget::WinCompositorWindowThread::ShutDown();
805 #endif
807 image::ImageMemoryReporter::ShutdownForWebRender();
809 // Shut down the default GL context provider.
810 gl::GLContextProvider::Shutdown();
812 #if defined(XP_WIN)
813 // The above shutdown calls operate on the available context providers
814 // on most platforms. Windows is a "special snowflake", though, and has
815 // three context providers available, so we have to shut all of them
816 // down. We should only support the default GL provider on Windows;
817 // then, this could go away. Unfortunately, we currently support WGL
818 // (the default) for WebGL on Optimus.
819 gl::GLContextProviderEGL::Shutdown();
820 #endif
822 Factory::ShutDown();
824 // We bypass gfxPlatform shutdown, so we must shutdown any libraries here
825 // that would normally be handled by it.
826 #ifdef NS_FREE_PERMANENT_DATA
827 SkGraphics::PurgeFontCache();
828 cairo_debug_reset_static_data();
829 #endif
831 #if defined(XP_WIN)
832 GpuProcessD3D11QueryMap::Shutdown();
833 GpuProcessD3D11TextureMap::Shutdown();
834 DeviceManagerDx::Shutdown();
835 #endif
836 LayerTreeOwnerTracker::Shutdown();
837 gfxVars::Shutdown();
838 gfxConfig::Shutdown();
839 CrashReporterClient::DestroySingleton();
840 XRE_ShutdownChildProcess();
844 } // namespace mozilla::gfx