tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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