GPUParent.cpp (26890B)
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/. */ 6 7 #ifdef XP_WIN 8 # include "WMF.h" 9 # include "WMFDecoderModule.h" 10 #endif 11 #include "FFVPXRuntimeLinker.h" 12 #include "GLContextProvider.h" 13 #include "GPUParent.h" 14 #include "GPUProcessHost.h" 15 #include "GPUProcessManager.h" 16 #include "gfxGradientCache.h" 17 #include "GfxInfoBase.h" 18 #include "VRGPUChild.h" 19 #include "VRManager.h" 20 #include "VRManagerParent.h" 21 #include "VsyncBridgeParent.h" 22 #include "cairo.h" 23 #include "gfxConfig.h" 24 #include "gfxCrashReporterUtils.h" 25 #include "gfxPlatform.h" 26 #include "MediaCodecsSupport.h" 27 #include "mozilla/Assertions.h" 28 #include "mozilla/Components.h" 29 #include "mozilla/FOGIPC.h" 30 #include "mozilla/HangDetails.h" 31 #include "mozilla/PerfStats.h" 32 #include "mozilla/Preferences.h" 33 #include "mozilla/ProcessPriorityManager.h" 34 #include "mozilla/RemoteMediaManagerChild.h" 35 #include "mozilla/RemoteMediaManagerParent.h" 36 #include "mozilla/StaticPrefs_dom.h" 37 #include "mozilla/StaticPrefs_media.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/GfxMetrics.h" 44 #include "mozilla/glean/GleanTestsTestMetrics.h" 45 #include "mozilla/image/ImageMemoryReporter.h" 46 #include "mozilla/ipc/CrashReporterClient.h" 47 #include "mozilla/ipc/ProcessChild.h" 48 #include "mozilla/ipc/ProcessUtils.h" 49 #include "mozilla/layers/APZInputBridgeParent.h" 50 #include "mozilla/layers/APZPublicUtils.h" // for apz::InitializeGlobalState 51 #include "mozilla/layers/APZThreadUtils.h" 52 #include "mozilla/layers/CompositorBridgeParent.h" 53 #include "mozilla/layers/CompositorManagerParent.h" 54 #include "mozilla/layers/CompositorThread.h" 55 #include "mozilla/layers/ImageBridgeParent.h" 56 #include "mozilla/layers/LayerTreeOwnerTracker.h" 57 #include "mozilla/layers/RemoteTextureMap.h" 58 #include "mozilla/layers/UiCompositorControllerParent.h" 59 #include "mozilla/layers/VideoBridgeParent.h" 60 #include "mozilla/webrender/RenderThread.h" 61 #include "mozilla/webrender/WebRenderAPI.h" 62 #include "nsDebugImpl.h" 63 #include "nsIGfxInfo.h" 64 #include "nsIXULRuntime.h" 65 #include "nsThreadManager.h" 66 #include "nscore.h" 67 #include "prenv.h" 68 #include "skia/include/core/SkGraphics.h" 69 #if defined(XP_MACOSX) && defined(MOZ_SANDBOX) 70 # include "mozilla/SandboxSettings.h" 71 #endif 72 #if defined(XP_WIN) 73 # include <dwrite.h> 74 # include <process.h> 75 # include <windows.h> 76 77 # include "gfxDWriteFonts.h" 78 # include "gfxWindowsPlatform.h" 79 # include "mozilla/gfx/DeviceManagerDx.h" 80 # include "mozilla/layers/CompositeProcessD3D11FencesHolderMap.h" 81 # include "mozilla/layers/GpuProcessD3D11TextureMap.h" 82 # include "mozilla/layers/TextureD3D11.h" 83 # include "mozilla/widget/WinCompositorWindowThread.h" 84 # include "WMFDecoderModule.h" 85 #else 86 # include <unistd.h> 87 #endif 88 #ifdef MOZ_WIDGET_GTK 89 # include <gtk/gtk.h> 90 91 # include "skia/include/ports/SkTypeface_cairo.h" 92 #endif 93 #ifdef ANDROID 94 # include "mozilla/layers/AndroidHardwareBuffer.h" 95 # include "skia/include/ports/SkTypeface_cairo.h" 96 #endif 97 #include "ChildProfilerController.h" 98 #include "nsAppRunner.h" 99 100 #if defined(MOZ_SANDBOX) && defined(MOZ_DEBUG) && defined(ENABLE_TESTS) 101 # include "mozilla/SandboxTestingChild.h" 102 #endif 103 104 namespace mozilla::gfx { 105 106 using namespace ipc; 107 using namespace layers; 108 109 static GPUParent* sGPUParent; 110 111 GPUParent::GPUParent() : mLaunchTime(TimeStamp::Now()) { sGPUParent = this; } 112 113 GPUParent::~GPUParent() { sGPUParent = nullptr; } 114 115 /* static */ 116 GPUParent* GPUParent::GetSingleton() { 117 MOZ_DIAGNOSTIC_ASSERT(sGPUParent); 118 return sGPUParent; 119 } 120 121 /* static */ bool GPUParent::MaybeFlushMemory() { 122 #if defined(XP_WIN) && !defined(HAVE_64BIT_BUILD) 123 MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread()); 124 if (!XRE_IsGPUProcess()) { 125 return false; 126 } 127 128 MEMORYSTATUSEX stat; 129 stat.dwLength = sizeof(stat); 130 if (!GlobalMemoryStatusEx(&stat)) { 131 return false; 132 } 133 134 // We only care about virtual process memory space in the GPU process because 135 // the UI process is already watching total memory usage. 136 static const size_t kLowVirtualMemoryThreshold = 384 * 1024 * 1024; 137 bool lowMemory = stat.ullAvailVirtual < kLowVirtualMemoryThreshold; 138 139 // We suppress more than one low memory notification until we exit the 140 // condition. The UI process goes through more effort, reporting on-going 141 // memory pressure, but rather than try to manage a shared state, we just 142 // send one notification here to try to resolve it. 143 static bool sLowMemory = false; 144 if (lowMemory && !sLowMemory) { 145 NS_DispatchToMainThread( 146 NS_NewRunnableFunction("gfx::GPUParent::FlushMemory", []() -> void { 147 (void)GPUParent::GetSingleton()->SendFlushMemory(u"low-memory"_ns); 148 })); 149 } 150 sLowMemory = lowMemory; 151 return lowMemory; 152 #else 153 return false; 154 #endif 155 } 156 157 bool GPUParent::Init(mozilla::ipc::UntypedEndpoint&& aEndpoint, 158 const char* aParentBuildID) { 159 // Initialize the thread manager before starting IPC. Otherwise, messages 160 // may be posted to the main thread and we won't be able to process them. 161 if (NS_WARN_IF(NS_FAILED(nsThreadManager::get().Init()))) { 162 return false; 163 } 164 165 // Now it's safe to start IPC. 166 if (NS_WARN_IF(!aEndpoint.Bind(this))) { 167 return false; 168 } 169 170 nsDebugImpl::SetMultiprocessMode("GPU"); 171 172 // This must be checked before any IPDL message, which may hit sentinel 173 // errors due to parent and content processes having different 174 // versions. 175 MessageChannel* channel = GetIPCChannel(); 176 if (channel && !channel->SendBuildIDsMatchMessage(aParentBuildID)) { 177 // We need to quit this process if the buildID doesn't match the parent's. 178 // This can occur when an update occurred in the background. 179 ProcessChild::QuickExit(); 180 } 181 182 if (NS_FAILED(NS_InitMinimalXPCOM())) { 183 return false; 184 } 185 186 // Ensure the observer service exists. 187 ProcessPriorityManager::Init(); 188 189 // Init crash reporter support. 190 CrashReporterClient::InitSingleton(this); 191 192 gfxConfig::Init(); 193 gfxVars::Initialize(); 194 gfxPlatform::InitNullMetadata(); 195 // Ensure our Factory is initialised, mainly for gfx logging to work. 196 gfxPlatform::InitMoz2DLogging(); 197 #if defined(XP_WIN) 198 gfxWindowsPlatform::InitMemoryReportersForGPUProcess(); 199 DeviceManagerDx::Init(); 200 CompositeProcessD3D11FencesHolderMap::Init(); 201 GpuProcessD3D11TextureMap::Init(); 202 auto rv = wmf::MediaFoundationInitializer::HasInitialized(); 203 if (!rv) { 204 NS_WARNING("Failed to init Media Foundation in the GPU process"); 205 } 206 #endif 207 208 CompositorThreadHolder::Start(); 209 RemoteTextureMap::Init(); 210 APZThreadUtils::SetControllerThread(NS_GetCurrentThread()); 211 apz::InitializeGlobalState(); 212 LayerTreeOwnerTracker::Initialize(); 213 CompositorBridgeParent::InitializeStatics(); 214 215 #if defined(XP_MACOSX) && defined(MOZ_SANDBOX) 216 // On macOS, we pass the empty string for the process name because 217 // the bundle name (CFBundleName) is the complete name already. 218 // If the sandbox is enabled, setting the executable name will fail 219 // so don't attempt it. The executable name will be shown in 220 // Activity Monitor as the process name. 221 if (!IsGPUSandboxEnabled()) { 222 mozilla::ipc::SetThisProcessName(""); 223 } 224 #elif defined(XP_MACOSX) 225 mozilla::ipc::SetThisProcessName(""); 226 #else 227 mozilla::ipc::SetThisProcessName("GPU Process"); 228 #endif // XP_MACOSX && MOZ_SANDBOX 229 230 return true; 231 } 232 233 void GPUParent::NotifyDeviceReset(DeviceResetReason aReason, 234 DeviceResetDetectPlace aPlace) { 235 // Notify the main process that there's been a device reset 236 // and that they should reset their compositors and repaint 237 GPUDeviceData data; 238 RecvGetDeviceStatus(&data); 239 (void)SendNotifyDeviceReset(data, aReason, aPlace); 240 } 241 242 void GPUParent::NotifyOverlayInfo(layers::OverlayInfo aInfo) { 243 if (!NS_IsMainThread()) { 244 NS_DispatchToMainThread(NS_NewRunnableFunction( 245 "gfx::GPUParent::NotifyOverlayInfo", [aInfo]() -> void { 246 GPUParent::GetSingleton()->NotifyOverlayInfo(aInfo); 247 })); 248 return; 249 } 250 (void)SendNotifyOverlayInfo(aInfo); 251 } 252 253 void GPUParent::NotifySwapChainInfo(layers::SwapChainInfo aInfo) { 254 if (!NS_IsMainThread()) { 255 NS_DispatchToMainThread(NS_NewRunnableFunction( 256 "gfx::GPUParent::NotifySwapChainInfo", [aInfo]() -> void { 257 GPUParent::GetSingleton()->NotifySwapChainInfo(aInfo); 258 })); 259 return; 260 } 261 (void)SendNotifySwapChainInfo(aInfo); 262 } 263 264 void GPUParent::NotifyDisableRemoteCanvas() { 265 if (!NS_IsMainThread()) { 266 NS_DispatchToMainThread(NS_NewRunnableFunction( 267 "gfx::GPUParent::NotifyDisableRemoteCanvas", []() -> void { 268 GPUParent::GetSingleton()->NotifyDisableRemoteCanvas(); 269 })); 270 return; 271 } 272 (void)SendNotifyDisableRemoteCanvas(); 273 } 274 275 mozilla::ipc::IPCResult GPUParent::RecvInit( 276 nsTArray<GfxVarUpdate>&& vars, const DevicePrefs& devicePrefs, 277 nsTArray<LayerTreeIdMapping>&& aMappings, 278 nsTArray<GfxInfoFeatureStatus>&& aFeatures, uint32_t aWrNamespace, 279 InitResolver&& aInitResolver) { 280 gfxVars::ApplyUpdate(vars); 281 282 // Inherit device preferences. 283 gfxConfig::Inherit(Feature::HW_COMPOSITING, devicePrefs.hwCompositing()); 284 gfxConfig::Inherit(Feature::D3D11_COMPOSITING, 285 devicePrefs.d3d11Compositing()); 286 gfxConfig::Inherit(Feature::OPENGL_COMPOSITING, devicePrefs.oglCompositing()); 287 gfxConfig::Inherit(Feature::D3D11_HW_ANGLE, devicePrefs.d3d11HwAngle()); 288 289 { // Let the crash reporter know if we've got WR enabled or not. For other 290 // processes this happens in gfxPlatform::InitWebRenderConfig. 291 ScopedGfxFeatureReporter reporter("WR", 292 gfxPlatform::WebRenderPrefEnabled()); 293 reporter.SetSuccessful(); 294 } 295 296 for (const LayerTreeIdMapping& map : aMappings) { 297 LayerTreeOwnerTracker::Get()->Map(map.layersId(), map.ownerId()); 298 } 299 300 widget::GfxInfoBase::SetFeatureStatus(std::move(aFeatures)); 301 302 // We bypass gfxPlatform::Init, so we must initialize any relevant libraries 303 // here that would normally be initialized there. 304 SkGraphics::Init(); 305 306 bool useRemoteCanvas = gfxVars::UseAcceleratedCanvas2D(); 307 if (useRemoteCanvas) { 308 gfxGradientCache::Init(); 309 } 310 311 #if defined(XP_WIN) 312 if (gfxConfig::IsEnabled(Feature::D3D11_COMPOSITING)) { 313 if (DeviceManagerDx::Get()->CreateCompositorDevices() && useRemoteCanvas) { 314 if (DeviceManagerDx::Get()->CreateCanvasDevice()) { 315 gfxDWriteFont::InitDWriteSupport(); 316 } else { 317 gfxWarning() << "Failed to create canvas device."; 318 } 319 } 320 } 321 DeviceManagerDx::Get()->CreateDirectCompositionDevice(); 322 // Ensure to initialize GfxInfo 323 nsCOMPtr<nsIGfxInfo> gfxInfo = components::GfxInfo::Service(); 324 (void)gfxInfo; 325 326 Factory::EnsureDWriteFactory(); 327 #endif 328 329 #if defined(MOZ_WIDGET_GTK) 330 char* display_name = PR_GetEnv("MOZ_GDK_DISPLAY"); 331 if (!display_name) { 332 bool waylandEnabled = false; 333 # ifdef MOZ_WAYLAND 334 waylandEnabled = IsWaylandEnabled(); 335 # endif 336 if (!waylandEnabled) { 337 display_name = PR_GetEnv("DISPLAY"); 338 } 339 } 340 if (display_name) { 341 int argc = 3; 342 char option_name[] = "--display"; 343 char* argv[] = {// argv0 is unused because g_set_prgname() was called in 344 // XRE_InitChildProcess(). 345 nullptr, option_name, display_name, nullptr}; 346 char** argvp = argv; 347 gtk_init(&argc, &argvp); 348 } else { 349 gtk_init(nullptr, nullptr); 350 } 351 352 // Ensure we have an FT library for font instantiation. 353 // This would normally be set by gfxPlatform::Init(). 354 // Since we bypass that, we must do it here instead. 355 FT_Library library = Factory::NewFTLibrary(); 356 MOZ_ASSERT(library); 357 Factory::SetFTLibrary(library); 358 359 // true to match gfxPlatform::FontHintingEnabled(). We must hardcode 360 // this value because we do not have a gfxPlatform instance. 361 SkInitCairoFT(true); 362 363 // Ensure that GfxInfo::Init is called on the main thread. 364 nsCOMPtr<nsIGfxInfo> gfxInfo = components::GfxInfo::Service(); 365 (void)gfxInfo; 366 #endif 367 368 #ifdef ANDROID 369 // Ensure we have an FT library for font instantiation. 370 // This would normally be set by gfxPlatform::Init(). 371 // Since we bypass that, we must do it here instead. 372 FT_Library library = Factory::NewFTLibrary(); 373 MOZ_ASSERT(library); 374 Factory::SetFTLibrary(library); 375 376 // false to match gfxAndroidPlatform::FontHintingEnabled(). We must 377 // hardcode this value because we do not have a gfxPlatform instance. 378 SkInitCairoFT(false); 379 380 if (gfxVars::UseAHardwareBufferSharedSurfaceWebglOop()) { 381 layers::AndroidHardwareBufferApi::Init(); 382 layers::AndroidHardwareBufferManager::Init(); 383 } 384 385 #endif 386 387 // Make sure to do this *after* we update gfxVars above. 388 wr::RenderThread::Start(aWrNamespace); 389 gfx::CanvasRenderThread::Start(); 390 image::ImageMemoryReporter::InitForWebRender(); 391 392 // Since gfxPlatform::Init is never called for the GPU process, ensure that 393 // common memory reporters get registered here instead. 394 gfxPlatform::InitMemoryReportersForGPUProcess(); 395 396 VRManager::ManagerInit(); 397 // Send a message to the UI process that we're done. 398 GPUDeviceData data; 399 RecvGetDeviceStatus(&data); 400 aInitResolver(data); 401 402 // Dispatch a task to background thread to determine the media codec supported 403 // result, and propagate it back to the chrome process on the main thread. 404 MOZ_ALWAYS_SUCCEEDS(NS_DispatchBackgroundTask( 405 NS_NewRunnableFunction( 406 "GPUParent::Supported", 407 []() { 408 NS_DispatchToMainThread(NS_NewRunnableFunction( 409 "GPUParent::UpdateMediaCodecsSupported", 410 [supported = media::MCSInfo::GetSupportFromFactory()]() { 411 (void)GPUParent::GetSingleton() 412 ->SendUpdateMediaCodecsSupported(supported); 413 })); 414 }), 415 nsIEventTarget::DISPATCH_NORMAL)); 416 417 glean::gpu_process::initialization_time.AccumulateRawDuration( 418 TimeStamp::Now() - mLaunchTime); 419 return IPC_OK(); 420 } 421 422 #if defined(MOZ_SANDBOX) && defined(MOZ_DEBUG) && defined(ENABLE_TESTS) 423 mozilla::ipc::IPCResult GPUParent::RecvInitSandboxTesting( 424 Endpoint<PSandboxTestingChild>&& aEndpoint) { 425 if (!SandboxTestingChild::Initialize(std::move(aEndpoint))) { 426 return IPC_FAIL( 427 this, "InitSandboxTesting failed to initialise the child process."); 428 } 429 return IPC_OK(); 430 } 431 #endif 432 433 mozilla::ipc::IPCResult GPUParent::RecvInitCompositorManager( 434 Endpoint<PCompositorManagerParent>&& aEndpoint, uint32_t aNamespace) { 435 CompositorManagerParent::Create(std::move(aEndpoint), ContentParentId(), 436 aNamespace, /* aIsRoot */ true); 437 return IPC_OK(); 438 } 439 440 mozilla::ipc::IPCResult GPUParent::RecvInitVsyncBridge( 441 Endpoint<PVsyncBridgeParent>&& aVsyncEndpoint) { 442 mVsyncBridge = VsyncBridgeParent::Start(std::move(aVsyncEndpoint)); 443 return IPC_OK(); 444 } 445 446 mozilla::ipc::IPCResult GPUParent::RecvInitImageBridge( 447 Endpoint<PImageBridgeParent>&& aEndpoint) { 448 ImageBridgeParent::CreateForGPUProcess(std::move(aEndpoint)); 449 return IPC_OK(); 450 } 451 452 mozilla::ipc::IPCResult GPUParent::RecvInitVideoBridge( 453 Endpoint<PVideoBridgeParent>&& aEndpoint, 454 const layers::VideoBridgeSource& aSource) { 455 // For GPU decoding, the video bridge would be opened in 456 // `VideoBridgeChild::StartupForGPUProcess`. 457 MOZ_ASSERT(aSource == layers::VideoBridgeSource::RddProcess || 458 aSource == layers::VideoBridgeSource::MFMediaEngineCDMProcess); 459 VideoBridgeParent::Open(std::move(aEndpoint), aSource); 460 return IPC_OK(); 461 } 462 463 mozilla::ipc::IPCResult GPUParent::RecvInitVRManager( 464 Endpoint<PVRManagerParent>&& aEndpoint) { 465 VRManagerParent::CreateForGPUProcess(std::move(aEndpoint)); 466 return IPC_OK(); 467 } 468 469 mozilla::ipc::IPCResult GPUParent::RecvInitVR( 470 Endpoint<PVRGPUChild>&& aEndpoint) { 471 gfx::VRGPUChild::InitForGPUProcess(std::move(aEndpoint)); 472 return IPC_OK(); 473 } 474 475 mozilla::ipc::IPCResult GPUParent::RecvInitUiCompositorController( 476 const LayersId& aRootLayerTreeId, 477 Endpoint<PUiCompositorControllerParent>&& aEndpoint) { 478 UiCompositorControllerParent::Start(aRootLayerTreeId, std::move(aEndpoint)); 479 return IPC_OK(); 480 } 481 482 mozilla::ipc::IPCResult GPUParent::RecvInitAPZInputBridge( 483 const LayersId& aRootLayerTreeId, 484 Endpoint<PAPZInputBridgeParent>&& aEndpoint) { 485 APZInputBridgeParent::Create(aRootLayerTreeId, std::move(aEndpoint)); 486 return IPC_OK(); 487 } 488 489 mozilla::ipc::IPCResult GPUParent::RecvInitProfiler( 490 Endpoint<PProfilerChild>&& aEndpoint) { 491 mProfilerController = ChildProfilerController::Create(std::move(aEndpoint)); 492 return IPC_OK(); 493 } 494 495 mozilla::ipc::IPCResult GPUParent::RecvUpdateVar( 496 const nsTArray<GfxVarUpdate>& aUpdate) { 497 gfxVars::ApplyUpdate(aUpdate); 498 MOZ_ALWAYS_SUCCEEDS(NS_DispatchBackgroundTask( 499 NS_NewRunnableFunction( 500 "GPUParent::RecvUpdateVar", 501 []() { 502 #ifdef XP_WIN 503 WMFDecoderModule::Init(); 504 #endif 505 if (StaticPrefs::media_ffvpx_hw_enabled()) { 506 FFVPXRuntimeLinker::Init(); 507 } 508 NS_DispatchToMainThread(NS_NewRunnableFunction( 509 "GPUParent::UpdateMediaCodecsSupported", 510 [supported = media::MCSInfo::GetSupportFromFactory( 511 true /* force refresh */)]() { 512 if (auto* gpu = GPUParent::GetSingleton()) { 513 (void)gpu->SendUpdateMediaCodecsSupported(supported); 514 } 515 })); 516 }), 517 nsIEventTarget::DISPATCH_NORMAL)); 518 return IPC_OK(); 519 } 520 521 mozilla::ipc::IPCResult GPUParent::RecvPreferenceUpdate(const Pref& aPref) { 522 Preferences::SetPreference(aPref); 523 return IPC_OK(); 524 } 525 526 mozilla::ipc::IPCResult GPUParent::RecvScreenInformationChanged() { 527 #if defined(XP_WIN) 528 DeviceManagerDx::Get()->PostUpdateMonitorInfo(); 529 #endif 530 return IPC_OK(); 531 } 532 533 mozilla::ipc::IPCResult GPUParent::RecvNotifyBatteryInfo( 534 const BatteryInformation& aBatteryInfo) { 535 wr::RenderThread::Get()->SetBatteryInfo(aBatteryInfo); 536 return IPC_OK(); 537 } 538 539 static void CopyFeatureChange(Feature aFeature, Maybe<FeatureFailure>* aOut) { 540 FeatureState& feature = gfxConfig::GetFeature(aFeature); 541 if (feature.DisabledByDefault() || feature.IsEnabled()) { 542 // No change: 543 // - Disabled-by-default means the parent process told us not to use this 544 // feature. 545 // - Enabled means we were told to use this feature, and we didn't 546 // discover anything 547 // that would prevent us from doing so. 548 *aOut = Nothing(); 549 return; 550 } 551 552 MOZ_ASSERT(!feature.IsEnabled()); 553 554 nsCString message; 555 message.AssignASCII(feature.GetFailureMessage()); 556 557 *aOut = 558 Some(FeatureFailure(feature.GetValue(), message, feature.GetFailureId())); 559 } 560 561 mozilla::ipc::IPCResult GPUParent::RecvGetDeviceStatus(GPUDeviceData* aOut) { 562 CopyFeatureChange(Feature::D3D11_COMPOSITING, &aOut->d3d11Compositing()); 563 CopyFeatureChange(Feature::OPENGL_COMPOSITING, &aOut->oglCompositing()); 564 565 #if defined(XP_WIN) 566 if (DeviceManagerDx* dm = DeviceManagerDx::Get()) { 567 D3D11DeviceStatus deviceStatus; 568 dm->ExportDeviceInfo(&deviceStatus); 569 aOut->gpuDevice() = Some(deviceStatus); 570 } 571 #else 572 aOut->gpuDevice() = Nothing(); 573 #endif 574 575 return IPC_OK(); 576 } 577 578 mozilla::ipc::IPCResult GPUParent::RecvSimulateDeviceReset() { 579 #if defined(XP_WIN) 580 DeviceManagerDx::Get()->ForceDeviceReset( 581 ForcedDeviceResetReason::COMPOSITOR_UPDATED); 582 #endif 583 wr::RenderThread::Get()->SimulateDeviceReset(); 584 return IPC_OK(); 585 } 586 587 mozilla::ipc::IPCResult GPUParent::RecvNewContentCompositorManager( 588 Endpoint<PCompositorManagerParent>&& aEndpoint, 589 const ContentParentId& aChildId, uint32_t aNamespace) { 590 CompositorManagerParent::Create(std::move(aEndpoint), aChildId, aNamespace, 591 /* aIsRoot */ false); 592 return IPC_OK(); 593 } 594 595 mozilla::ipc::IPCResult GPUParent::RecvNewContentImageBridge( 596 Endpoint<PImageBridgeParent>&& aEndpoint, const ContentParentId& aChildId) { 597 if (!ImageBridgeParent::CreateForContent(std::move(aEndpoint), aChildId)) { 598 return IPC_FAIL_NO_REASON(this); 599 } 600 return IPC_OK(); 601 } 602 603 mozilla::ipc::IPCResult GPUParent::RecvNewContentVRManager( 604 Endpoint<PVRManagerParent>&& aEndpoint, const ContentParentId& aChildId) { 605 if (!VRManagerParent::CreateForContent(std::move(aEndpoint), aChildId)) { 606 return IPC_FAIL_NO_REASON(this); 607 } 608 return IPC_OK(); 609 } 610 611 mozilla::ipc::IPCResult GPUParent::RecvNewContentRemoteMediaManager( 612 Endpoint<PRemoteMediaManagerParent>&& aEndpoint, 613 const ContentParentId& aChildId) { 614 if (!RemoteMediaManagerParent::CreateForContent(std::move(aEndpoint), 615 aChildId)) { 616 return IPC_FAIL_NO_REASON(this); 617 } 618 return IPC_OK(); 619 } 620 621 mozilla::ipc::IPCResult GPUParent::RecvAddLayerTreeIdMapping( 622 const LayerTreeIdMapping& aMapping) { 623 LayerTreeOwnerTracker::Get()->Map(aMapping.layersId(), aMapping.ownerId()); 624 return IPC_OK(); 625 } 626 627 mozilla::ipc::IPCResult GPUParent::RecvRemoveLayerTreeIdMapping( 628 const LayerTreeIdMapping& aMapping) { 629 LayerTreeOwnerTracker::Get()->Unmap(aMapping.layersId(), aMapping.ownerId()); 630 CompositorBridgeParent::DeallocateLayerTreeId(aMapping.layersId()); 631 return IPC_OK(); 632 } 633 634 mozilla::ipc::IPCResult GPUParent::RecvNotifyGpuObservers( 635 const nsCString& aTopic) { 636 nsCOMPtr<nsIObserverService> obsSvc = mozilla::services::GetObserverService(); 637 MOZ_ASSERT(obsSvc); 638 if (obsSvc) { 639 obsSvc->NotifyObservers(nullptr, aTopic.get(), nullptr); 640 } 641 return IPC_OK(); 642 } 643 644 /* static */ 645 void GPUParent::GetGPUProcessName(nsACString& aStr) { 646 auto processType = XRE_GetProcessType(); 647 unsigned pid = 0; 648 if (processType == GeckoProcessType_GPU) { 649 pid = getpid(); 650 } else { 651 MOZ_DIAGNOSTIC_ASSERT(processType == GeckoProcessType_Default); 652 pid = GPUProcessManager::Get()->GPUProcessPid(); 653 } 654 655 nsPrintfCString processName("GPU (pid %u)", pid); 656 aStr.Assign(processName); 657 } 658 659 mozilla::ipc::IPCResult GPUParent::RecvRequestMemoryReport( 660 const uint32_t& aGeneration, const bool& aAnonymize, 661 const bool& aMinimizeMemoryUsage, const Maybe<FileDescriptor>& aDMDFile, 662 const RequestMemoryReportResolver& aResolver) { 663 nsAutoCString processName; 664 GetGPUProcessName(processName); 665 666 mozilla::dom::MemoryReportRequestClient::Start( 667 aGeneration, aAnonymize, aMinimizeMemoryUsage, aDMDFile, processName, 668 [&](const MemoryReport& aReport) { 669 (void)GetSingleton()->SendAddMemoryReport(aReport); 670 }, 671 aResolver); 672 return IPC_OK(); 673 } 674 675 mozilla::ipc::IPCResult GPUParent::RecvShutdownVR() { 676 if (StaticPrefs::dom_vr_process_enabled_AtStartup()) { 677 VRGPUChild::Shutdown(); 678 } 679 return IPC_OK(); 680 } 681 682 mozilla::ipc::IPCResult GPUParent::RecvUpdatePerfStatsCollectionMask( 683 const uint64_t& aMask) { 684 PerfStats::SetCollectionMask(static_cast<PerfStats::MetricMask>(aMask)); 685 return IPC_OK(); 686 } 687 688 mozilla::ipc::IPCResult GPUParent::RecvCollectPerfStatsJSON( 689 CollectPerfStatsJSONResolver&& aResolver) { 690 aResolver(PerfStats::CollectLocalPerfStatsJSON()); 691 return IPC_OK(); 692 } 693 694 mozilla::ipc::IPCResult GPUParent::RecvFlushFOGData( 695 FlushFOGDataResolver&& aResolver) { 696 glean::FlushFOGData(std::move(aResolver)); 697 return IPC_OK(); 698 } 699 700 mozilla::ipc::IPCResult GPUParent::RecvTestTriggerMetrics( 701 TestTriggerMetricsResolver&& aResolve) { 702 mozilla::glean::test_only_ipc::a_counter.Add(nsIXULRuntime::PROCESS_TYPE_GPU); 703 aResolve(true); 704 return IPC_OK(); 705 } 706 707 mozilla::ipc::IPCResult GPUParent::RecvCrashProcess() { 708 MOZ_CRASH("Deliberate GPU process crash"); 709 return IPC_OK(); 710 } 711 712 void GPUParent::ActorDestroy(ActorDestroyReason aWhy) { 713 if (AbnormalShutdown == aWhy) { 714 NS_WARNING("Shutting down GPU process early due to a crash!"); 715 ProcessChild::QuickExit(); 716 } 717 718 // Send the last bits of Glean data over to the main process. 719 glean::FlushFOGData( 720 [](ByteBuf&& aBuf) { glean::SendFOGData(std::move(aBuf)); }); 721 722 #ifndef NS_FREE_PERMANENT_DATA 723 // No point in going through XPCOM shutdown because we don't keep persistent 724 // state. 725 ProcessChild::QuickExit(); 726 #endif 727 728 // Wait until all RemoteMediaManagerParent have closed. 729 mShutdownBlockers.WaitUntilClear(10 * 1000 /* 10s timeout*/) 730 ->Then(GetCurrentSerialEventTarget(), __func__, [self = RefPtr{this}]() { 731 if (self->mProfilerController) { 732 self->mProfilerController->Shutdown(); 733 self->mProfilerController = nullptr; 734 } 735 736 if (self->mVsyncBridge) { 737 self->mVsyncBridge->Shutdown(); 738 self->mVsyncBridge = nullptr; 739 } 740 VideoBridgeParent::Shutdown(); 741 // This could be running on either the Compositor thread, the Renderer 742 // thread, or the dedicated CanvasRender thread, so we need to shutdown 743 // before the former two. 744 CanvasRenderThread::Shutdown(); 745 CompositorThreadHolder::Shutdown(); 746 RemoteTextureMap::Shutdown(); 747 // There is a case that RenderThread exists when gfxVars::UseWebRender() 748 // is false. This could happen when WebRender was fallbacked to 749 // compositor. 750 if (wr::RenderThread::Get()) { 751 wr::RenderThread::ShutDown(); 752 } 753 #ifdef XP_WIN 754 if (widget::WinCompositorWindowThread::Get()) { 755 widget::WinCompositorWindowThread::ShutDown(); 756 } 757 #endif 758 759 image::ImageMemoryReporter::ShutdownForWebRender(); 760 761 // Shut down the default GL context provider. 762 gl::GLContextProvider::Shutdown(); 763 764 #if defined(XP_WIN) 765 // The above shutdown calls operate on the available context providers 766 // on most platforms. Windows is a "special snowflake", though, and has 767 // three context providers available, so we have to shut all of them 768 // down. We should only support the default GL provider on Windows; 769 // then, this could go away. Unfortunately, we currently support WGL 770 // (the default) for WebGL on Optimus. 771 gl::GLContextProviderEGL::Shutdown(); 772 #endif 773 774 Factory::ShutDown(); 775 776 // We bypass gfxPlatform shutdown, so we must shutdown any libraries here 777 // that would normally be handled by it. 778 #ifdef NS_FREE_PERMANENT_DATA 779 SkGraphics::PurgeFontCache(); 780 cairo_debug_reset_static_data(); 781 #endif 782 783 #if defined(XP_WIN) 784 GpuProcessD3D11TextureMap::Shutdown(); 785 CompositeProcessD3D11FencesHolderMap::Shutdown(); 786 DeviceManagerDx::Shutdown(); 787 #endif 788 LayerTreeOwnerTracker::Shutdown(); 789 gfxVars::Shutdown(); 790 gfxConfig::Shutdown(); 791 CrashReporterClient::DestroySingleton(); 792 XRE_ShutdownChildProcess(); 793 }); 794 } 795 796 } // namespace mozilla::gfx