tor-browser

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

GPUProcessManager.cpp (65969B)


      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 #include "GPUProcessManager.h"
      8 
      9 #include "gfxConfig.h"
     10 #include "gfxPlatform.h"
     11 #include "GPUProcessHost.h"
     12 #include "GPUProcessListener.h"
     13 #include "mozilla/AppShutdown.h"
     14 #include "mozilla/MemoryReportingProcess.h"
     15 #include "mozilla/Preferences.h"
     16 #include "mozilla/RDDChild.h"
     17 #include "mozilla/RDDProcessManager.h"
     18 #include "mozilla/RemoteMediaManagerChild.h"
     19 #include "mozilla/RemoteMediaManagerParent.h"
     20 #include "mozilla/Sprintf.h"
     21 #include "mozilla/StaticPtr.h"
     22 #include "mozilla/StaticPrefs_gfx.h"
     23 #include "mozilla/StaticPrefs_layers.h"
     24 #include "mozilla/StaticPrefs_media.h"
     25 #include "mozilla/dom/ContentParent.h"
     26 #include "mozilla/gfx/gfxVars.h"
     27 #include "mozilla/gfx/GPUChild.h"
     28 #include "mozilla/gfx/GPUParent.h"
     29 #include "mozilla/glean/GfxMetrics.h"
     30 #include "mozilla/ipc/Endpoint.h"
     31 #include "mozilla/ipc/ProcessChild.h"
     32 #include "mozilla/layers/APZCTreeManagerChild.h"
     33 #include "mozilla/layers/APZInputBridgeChild.h"
     34 #include "mozilla/layers/CompositorBridgeChild.h"
     35 #include "mozilla/layers/CompositorBridgeParent.h"
     36 #include "mozilla/layers/CompositorManagerChild.h"
     37 #include "mozilla/layers/CompositorManagerParent.h"
     38 #include "mozilla/layers/CompositorOptions.h"
     39 #include "mozilla/layers/ImageBridgeChild.h"
     40 #include "mozilla/layers/ImageBridgeParent.h"
     41 #include "mozilla/layers/InProcessCompositorSession.h"
     42 #include "mozilla/layers/LayerTreeOwnerTracker.h"
     43 #include "mozilla/layers/RemoteCompositorSession.h"
     44 #include "mozilla/layers/VideoBridgeParent.h"
     45 #include "mozilla/webrender/RenderThread.h"
     46 #include "mozilla/widget/PlatformWidgetTypes.h"
     47 #include "nsAppRunner.h"
     48 #include "mozilla/widget/CompositorWidget.h"
     49 #ifdef MOZ_WIDGET_SUPPORTS_OOP_COMPOSITING
     50 #  include "mozilla/widget/CompositorWidgetChild.h"
     51 #endif
     52 #include "nsIWidget.h"
     53 #include "nsContentUtils.h"
     54 #include "VRManagerChild.h"
     55 #include "VRManagerParent.h"
     56 #include "VsyncBridgeChild.h"
     57 #include "VsyncIOThreadHolder.h"
     58 #include "VsyncSource.h"
     59 #include "nsExceptionHandler.h"
     60 #include "nsPrintfCString.h"
     61 
     62 #ifdef MOZ_WMF_MEDIA_ENGINE
     63 #  include "mozilla/ipc/UtilityMediaServiceChild.h"
     64 #endif
     65 
     66 #if defined(MOZ_WIDGET_ANDROID)
     67 #  include "mozilla/java/SurfaceControlManagerWrappers.h"
     68 #  include "mozilla/widget/AndroidUiThread.h"
     69 #  include "mozilla/layers/UiCompositorControllerChild.h"
     70 #endif  // defined(MOZ_WIDGET_ANDROID)
     71 
     72 #if defined(XP_WIN)
     73 #  include "gfxWindowsPlatform.h"
     74 #  include "mozilla/gfx/DeviceManagerDx.h"
     75 #endif
     76 
     77 namespace mozilla {
     78 namespace gfx {
     79 
     80 using namespace mozilla::layers;
     81 
     82 static StaticAutoPtr<GPUProcessManager> sSingleton;
     83 
     84 GPUProcessManager* GPUProcessManager::Get() { return sSingleton; }
     85 
     86 void GPUProcessManager::Initialize() {
     87  MOZ_ASSERT(XRE_IsParentProcess());
     88  sSingleton = new GPUProcessManager();
     89 }
     90 
     91 void GPUProcessManager::Shutdown() {
     92  if (!sSingleton) {
     93    return;
     94  }
     95  sSingleton->ShutdownInternal();
     96  sSingleton = nullptr;
     97 }
     98 
     99 GPUProcessManager::GPUProcessManager()
    100    : mTaskFactory(this),
    101      mNextNamespace(0),
    102      mIdNamespace(0),
    103      mResourceId(0),
    104      mUnstableProcessAttempts(0),
    105      mTotalProcessAttempts(0),
    106      mDeviceResetCount(0),
    107      mAppInForeground(true),
    108      mProcess(nullptr),
    109      mProcessToken(0),
    110      mGPUChild(nullptr) {
    111  MOZ_COUNT_CTOR(GPUProcessManager);
    112 
    113  mIdNamespace = AllocateNamespace();
    114 
    115  mDeviceResetLastTime = TimeStamp::Now();
    116 
    117  LayerTreeOwnerTracker::Initialize();
    118  CompositorBridgeParent::InitializeStatics();
    119 }
    120 
    121 GPUProcessManager::~GPUProcessManager() {
    122  MOZ_COUNT_DTOR(GPUProcessManager);
    123 
    124  LayerTreeOwnerTracker::Shutdown();
    125 
    126  // The GPU process should have already been shut down.
    127  MOZ_ASSERT(!mProcess && !mGPUChild);
    128 
    129  // We should have already removed observers.
    130  MOZ_DIAGNOSTIC_ASSERT(!mObserver);
    131  MOZ_DIAGNOSTIC_ASSERT(!mBatteryObserver);
    132 }
    133 
    134 NS_IMPL_ISUPPORTS(GPUProcessManager::Observer, nsIObserver);
    135 
    136 GPUProcessManager::Observer::Observer() {
    137  nsContentUtils::RegisterShutdownObserver(this);
    138  Preferences::AddStrongObserver(this, "");
    139  if (nsCOMPtr<nsIObserverService> obsServ = services::GetObserverService()) {
    140    obsServ->AddObserver(this, "application-foreground", false);
    141    obsServ->AddObserver(this, "application-background", false);
    142    obsServ->AddObserver(this, "screen-information-changed", false);
    143    obsServ->AddObserver(this, "xpcom-will-shutdown", false);
    144  }
    145 }
    146 
    147 void GPUProcessManager::Observer::Shutdown() {
    148  nsContentUtils::UnregisterShutdownObserver(this);
    149  Preferences::RemoveObserver(this, "");
    150  if (nsCOMPtr<nsIObserverService> obsServ = services::GetObserverService()) {
    151    obsServ->RemoveObserver(this, "application-foreground");
    152    obsServ->RemoveObserver(this, "application-background");
    153    obsServ->RemoveObserver(this, "screen-information-changed");
    154    obsServ->RemoveObserver(this, "xpcom-will-shutdown");
    155  }
    156 }
    157 
    158 NS_IMETHODIMP
    159 GPUProcessManager::Observer::Observe(nsISupports* aSubject, const char* aTopic,
    160                                     const char16_t* aData) {
    161  if (auto* gpm = GPUProcessManager::Get()) {
    162    gpm->NotifyObserve(aTopic, aData);
    163  }
    164  return NS_OK;
    165 }
    166 
    167 void GPUProcessManager::NotifyObserve(const char* aTopic,
    168                                      const char16_t* aData) {
    169  if (!strcmp(aTopic, NS_XPCOM_WILL_SHUTDOWN_OBSERVER_ID)) {
    170    StopBatteryObserving();
    171  } else if (!strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID)) {
    172    ShutdownInternal();
    173  } else if (!strcmp(aTopic, "nsPref:changed")) {
    174    OnPreferenceChange(aData);
    175  } else if (!strcmp(aTopic, "application-foreground")) {
    176    SetAppInForeground(true);
    177  } else if (!strcmp(aTopic, "application-background")) {
    178    SetAppInForeground(false);
    179  } else if (!strcmp(aTopic, "screen-information-changed")) {
    180    ScreenInformationChanged();
    181  }
    182 }
    183 
    184 GPUProcessManager::BatteryObserver::BatteryObserver() {
    185  hal::RegisterBatteryObserver(this);
    186 }
    187 
    188 void GPUProcessManager::BatteryObserver::Notify(
    189    const hal::BatteryInformation& aBatteryInfo) {
    190  if (auto* gpm = GPUProcessManager::Get()) {
    191    gpm->NotifyBatteryInfo(aBatteryInfo);
    192  }
    193 }
    194 
    195 void GPUProcessManager::BatteryObserver::Shutdown() {
    196  hal::UnregisterBatteryObserver(this);
    197 }
    198 
    199 void GPUProcessManager::OnPreferenceChange(const char16_t* aData) {
    200  if (!mGPUChild && !IsGPUProcessLaunching()) {
    201    return;
    202  }
    203 
    204  // We know prefs are ASCII here.
    205  NS_LossyConvertUTF16toASCII strData(aData);
    206 
    207  mozilla::dom::Pref pref(strData, /* isLocked */ false,
    208                          /* isSanitized */ false, Nothing(), Nothing());
    209 
    210  Preferences::GetPreference(&pref, GeckoProcessType_GPU,
    211                             /* remoteType */ ""_ns);
    212  if (mGPUChild) {
    213    MOZ_ASSERT(mQueuedPrefs.IsEmpty());
    214    mGPUChild->SendPreferenceUpdate(pref);
    215  } else {
    216    mQueuedPrefs.AppendElement(pref);
    217  }
    218 }
    219 
    220 void GPUProcessManager::ScreenInformationChanged() {
    221 #if defined(XP_WIN)
    222  if (!!mGPUChild) {
    223    mGPUChild->SendScreenInformationChanged();
    224  }
    225 #endif
    226 }
    227 
    228 void GPUProcessManager::NotifyBatteryInfo(
    229    const hal::BatteryInformation& aBatteryInfo) {
    230  if (mGPUChild) {
    231    mGPUChild->SendNotifyBatteryInfo(aBatteryInfo);
    232  }
    233 }
    234 
    235 void GPUProcessManager::MaybeCrashIfGpuProcessOnceStable() {
    236  if (StaticPrefs::layers_gpu_process_allow_fallback_to_parent_AtStartup()) {
    237    return;
    238  }
    239  MOZ_RELEASE_ASSERT(!gfxConfig::IsEnabled(Feature::GPU_PROCESS));
    240  MOZ_RELEASE_ASSERT(!mProcessStableOnce,
    241                     "Fallback to parent process not allowed!");
    242 }
    243 
    244 void GPUProcessManager::ResetProcessStable() {
    245  mTotalProcessAttempts++;
    246  mProcessStable = false;
    247  mProcessAttemptLastTime = TimeStamp::Now();
    248 }
    249 
    250 bool GPUProcessManager::IsProcessStable(const TimeStamp& aNow) {
    251  if (mTotalProcessAttempts > 0) {
    252    auto delta = (int32_t)(aNow - mProcessAttemptLastTime).ToMilliseconds();
    253    if (delta < StaticPrefs::layers_gpu_process_stable_min_uptime_ms()) {
    254      return false;
    255    }
    256  }
    257  return mProcessStable;
    258 }
    259 
    260 nsresult GPUProcessManager::LaunchGPUProcess() {
    261  if (mProcess) {
    262    return NS_OK;
    263  }
    264 
    265  if (AppShutdown::IsInOrBeyond(ShutdownPhase::XPCOMShutdown)) {
    266    return NS_ERROR_ILLEGAL_DURING_SHUTDOWN;
    267  }
    268 
    269  // Start listening for pref changes so we can
    270  // forward them to the process once it is running.
    271  if (!mObserver) {
    272    mObserver = new Observer();
    273  }
    274 
    275  // Start the Vsync I/O thread so can use it as soon as the process launches.
    276  EnsureVsyncIOThread();
    277 
    278  mTotalProcessAttempts++;
    279  mozilla::glean::gpu_process::total_launch_attempts.Set(mTotalProcessAttempts);
    280  mProcessAttemptLastTime = TimeStamp::Now();
    281  mProcessStable = false;
    282 
    283  geckoargs::ChildProcessArgs extraArgs;
    284  ipc::ProcessChild::AddPlatformBuildID(extraArgs);
    285 
    286  // The subprocess is launched asynchronously, so we wait for a callback to
    287  // acquire the IPDL actor.
    288  mProcess = new GPUProcessHost(this);
    289  if (!mProcess->Launch(std::move(extraArgs))) {
    290    DisableGPUProcess("Failed to launch GPU process");
    291    return NS_ERROR_FAILURE;
    292  }
    293 
    294  return NS_OK;
    295 }
    296 
    297 bool GPUProcessManager::IsGPUProcessLaunching() {
    298  MOZ_ASSERT(NS_IsMainThread());
    299  return !!mProcess && !mGPUChild;
    300 }
    301 
    302 void GPUProcessManager::DisableGPUProcess(const char* aMessage) {
    303  MaybeDisableGPUProcess(aMessage, /* aAllowRestart */ false);
    304 }
    305 
    306 bool GPUProcessManager::MaybeDisableGPUProcess(const char* aMessage,
    307                                               bool aAllowRestart) {
    308  if (!gfxConfig::IsEnabled(Feature::GPU_PROCESS)) {
    309    return true;
    310  }
    311 
    312  bool wantRestart;
    313  {
    314    // Collect the gfxVar updates into a single message.
    315    gfxVarsCollectUpdates collect;
    316 
    317    if (!aAllowRestart) {
    318      gfxConfig::SetFailed(Feature::GPU_PROCESS, FeatureStatus::Failed,
    319                           aMessage);
    320      gfxVars::SetGPUProcessEnabled(false);
    321    }
    322 
    323    if (mLastError) {
    324      wantRestart =
    325          FallbackFromAcceleration(mLastError.value(), mLastErrorMsg.ref());
    326      mLastError.reset();
    327      mLastErrorMsg.reset();
    328    } else {
    329      wantRestart = gfxPlatform::FallbackFromAcceleration(
    330          FeatureStatus::Unavailable, aMessage,
    331          "FEATURE_FAILURE_GPU_PROCESS_ERROR"_ns);
    332    }
    333    if (aAllowRestart && wantRestart) {
    334      // The fallback method can make use of the GPU process.
    335      return false;
    336    }
    337 
    338    if (aAllowRestart) {
    339      gfxConfig::SetFailed(Feature::GPU_PROCESS, FeatureStatus::Failed,
    340                           aMessage);
    341      gfxVars::SetGPUProcessEnabled(false);
    342    }
    343 
    344    MOZ_ASSERT(!gfxConfig::IsEnabled(Feature::GPU_PROCESS));
    345 
    346    gfxCriticalNote << aMessage;
    347 
    348    gfxPlatform::DisableGPUProcess();
    349 
    350    MaybeCrashIfGpuProcessOnceStable();
    351  }
    352 
    353  mozilla::glean::gpu_process::feature_status.Set(
    354      gfxConfig::GetFeature(Feature::GPU_PROCESS)
    355          .GetStatusAndFailureIdString());
    356 
    357  mozilla::glean::gpu_process::crash_fallbacks.Get("disabled"_ns).Add(1);
    358 
    359  DestroyProcess();
    360  ShutdownVsyncIOThread();
    361 
    362  // Now the stability state is based upon the in process compositor session.
    363  ResetProcessStable();
    364 
    365  // We may have been in the middle of guaranteeing our various services are
    366  // available when one failed. Some callers may fallback to using the same
    367  // process equivalent, and we need to make sure those services are setup
    368  // correctly. We cannot re-enter DisableGPUProcess from this call because we
    369  // know that it is disabled in the config above.
    370  if (NS_WARN_IF(NS_FAILED(EnsureGPUReady()))) {
    371    MOZ_ASSERT(AppShutdown::IsInOrBeyond(ShutdownPhase::XPCOMShutdown));
    372  } else {
    373    DebugOnly<bool> ready = EnsureProtocolsReady();
    374    MOZ_ASSERT(ready);
    375  }
    376 
    377  // If we disable the GPU process during reinitialization after a previous
    378  // crash, then we need to tell the content processes again, because they
    379  // need to rebind to the UI process.
    380  HandleProcessLost();
    381  return true;
    382 }
    383 
    384 bool GPUProcessManager::IsGPUReady() const {
    385  // If we have disabled the GPU process, then we know we are always ready.
    386  if (!gfxConfig::IsEnabled(Feature::GPU_PROCESS)) {
    387    MOZ_ASSERT(!mProcess);
    388    MOZ_ASSERT(!mGPUChild);
    389    return true;
    390  }
    391 
    392  // If we have a GPUChild, then we know the process has finished launching.
    393  if (mGPUChild) {
    394    return mGPUChild->IsGPUReady();
    395  }
    396 
    397  return false;
    398 }
    399 
    400 nsresult GPUProcessManager::EnsureGPUReady() {
    401  MOZ_ASSERT(NS_IsMainThread());
    402 
    403  // Common case is we already have a GPU process.
    404  if (mProcess && mProcess->IsConnected() && mGPUChild) {
    405    MOZ_DIAGNOSTIC_ASSERT(mGPUChild->IsGPUReady());
    406    return NS_OK;
    407  }
    408 
    409  // Next most common case is that we are compositing in the parent process.
    410  if (!gfxConfig::IsEnabled(Feature::GPU_PROCESS)) {
    411    MOZ_DIAGNOSTIC_ASSERT(!mProcess);
    412    MOZ_DIAGNOSTIC_ASSERT(!mGPUChild);
    413    return NS_OK;
    414  }
    415 
    416  // We aren't ready and in shutdown, we should just abort.
    417  if (AppShutdown::IsInOrBeyond(ShutdownPhase::XPCOMShutdown)) {
    418    return NS_ERROR_ILLEGAL_DURING_SHUTDOWN;
    419  }
    420 
    421  while (true) {
    422    // We allow the GPU process to launch if we are:
    423    // 1) in the foreground, as the application is being actively used.
    424    // 2) if we have no launch failures, because even if we are backgrounded, we
    425    //    can try once to secure it. This is useful for geckoview-junit tests.
    426    // 3) if our pref is set to allow background launches; this is false by
    427    //    default on Android due to its issues with keeping the GPU process
    428    //    alive in the background, and true on all other platforms.
    429    //
    430    // If we are not in a position to try launching and/or waiting for the GPU
    431    // process, then we should just abort for now. The higher levels will fail
    432    // to create the content process, but all of this should get recreated when
    433    // the app comes back into the foreground.
    434    if (!mAppInForeground && mLaunchProcessAttempts > 0 &&
    435        !StaticPrefs::layers_gpu_process_launch_in_background()) {
    436      return NS_ERROR_ABORT;
    437    }
    438 
    439    // Launch the GPU process if it is enabled but hasn't been (re-)launched
    440    // yet, and wait for it to complete the handshake. As part of WaitForLaunch,
    441    // we know that OnProcessLaunchComplete has been called. If it succeeds,
    442    // we know that mGPUChild has been set and we already waited for it to be
    443    // ready. If it fails, then we know that the GPU process must have been
    444    // destroyed and/or disabled.
    445    nsresult rv = LaunchGPUProcess();
    446    if (NS_SUCCEEDED(rv) && mProcess->WaitForLaunch() && mGPUChild) {
    447      MOZ_DIAGNOSTIC_ASSERT(mGPUChild->IsGPUReady());
    448      break;
    449    }
    450 
    451    MOZ_RELEASE_ASSERT(rv != NS_ERROR_ILLEGAL_DURING_SHUTDOWN);
    452    MOZ_RELEASE_ASSERT(!mProcess);
    453    MOZ_RELEASE_ASSERT(!mGPUChild);
    454    MOZ_DIAGNOSTIC_ASSERT(mLaunchProcessAttempts > 0);
    455 
    456    if (!gfxConfig::IsEnabled(Feature::GPU_PROCESS)) {
    457      break;
    458    }
    459  }
    460 
    461  return NS_OK;
    462 }
    463 
    464 bool GPUProcessManager::EnsureProtocolsReady() {
    465  return EnsureCompositorManagerChild() && EnsureImageBridgeChild() &&
    466         EnsureVRManager();
    467 }
    468 
    469 bool GPUProcessManager::EnsureCompositorManagerChild() {
    470  MOZ_DIAGNOSTIC_ASSERT(IsGPUReady());
    471 
    472  if (CompositorManagerChild::IsInitialized(mProcessToken)) {
    473    return true;
    474  }
    475 
    476  if (!mGPUChild) {
    477    CompositorManagerChild::InitSameProcess(AllocateNamespace(), mProcessToken);
    478    return true;
    479  }
    480 
    481  ipc::Endpoint<PCompositorManagerParent> parentPipe;
    482  ipc::Endpoint<PCompositorManagerChild> childPipe;
    483  nsresult rv = PCompositorManager::CreateEndpoints(
    484      mGPUChild->OtherEndpointProcInfo(), ipc::EndpointProcInfo::Current(),
    485      &parentPipe, &childPipe);
    486  if (NS_FAILED(rv)) {
    487    DisableGPUProcess("Failed to create PCompositorManager endpoints");
    488    return true;
    489  }
    490 
    491  uint32_t cmNamespace = AllocateNamespace();
    492  mGPUChild->SendInitCompositorManager(std::move(parentPipe), cmNamespace);
    493  CompositorManagerChild::Init(std::move(childPipe), cmNamespace,
    494                               mProcessToken);
    495  return true;
    496 }
    497 
    498 bool GPUProcessManager::EnsureImageBridgeChild() {
    499  MOZ_DIAGNOSTIC_ASSERT(IsGPUReady());
    500 
    501  if (ImageBridgeChild::GetSingleton()) {
    502    return true;
    503  }
    504 
    505  if (!mGPUChild) {
    506    ImageBridgeChild::InitSameProcess(AllocateNamespace());
    507    return true;
    508  }
    509 
    510  ipc::Endpoint<PImageBridgeParent> parentPipe;
    511  ipc::Endpoint<PImageBridgeChild> childPipe;
    512  nsresult rv = PImageBridge::CreateEndpoints(
    513      mGPUChild->OtherEndpointProcInfo(), ipc::EndpointProcInfo::Current(),
    514      &parentPipe, &childPipe);
    515  if (NS_FAILED(rv)) {
    516    DisableGPUProcess("Failed to create PImageBridge endpoints");
    517    return true;
    518  }
    519 
    520  mGPUChild->SendInitImageBridge(std::move(parentPipe));
    521  ImageBridgeChild::InitWithGPUProcess(std::move(childPipe),
    522                                       AllocateNamespace());
    523  return true;
    524 }
    525 
    526 bool GPUProcessManager::EnsureVRManager() {
    527  MOZ_DIAGNOSTIC_ASSERT(IsGPUReady());
    528 
    529  if (VRManagerChild::IsCreated()) {
    530    return true;
    531  }
    532 
    533  if (!mGPUChild) {
    534    VRManagerChild::InitSameProcess();
    535    return true;
    536  }
    537 
    538  ipc::Endpoint<PVRManagerParent> parentPipe;
    539  ipc::Endpoint<PVRManagerChild> childPipe;
    540  nsresult rv = PVRManager::CreateEndpoints(mGPUChild->OtherEndpointProcInfo(),
    541                                            ipc::EndpointProcInfo::Current(),
    542                                            &parentPipe, &childPipe);
    543  if (NS_FAILED(rv)) {
    544    DisableGPUProcess("Failed to create PVRManager endpoints");
    545    return true;
    546  }
    547 
    548  mGPUChild->SendInitVRManager(std::move(parentPipe));
    549  VRManagerChild::InitWithGPUProcess(std::move(childPipe));
    550  return true;
    551 }
    552 
    553 #if defined(MOZ_WIDGET_ANDROID)
    554 RefPtr<UiCompositorControllerChild>
    555 GPUProcessManager::CreateUiCompositorController(nsIWidget* aWidget,
    556                                                const LayersId aId) {
    557  MOZ_DIAGNOSTIC_ASSERT(IsGPUReady());
    558 
    559  if (!mGPUChild) {
    560    return UiCompositorControllerChild::CreateForSameProcess(aId, aWidget);
    561  }
    562 
    563  ipc::Endpoint<PUiCompositorControllerParent> parentPipe;
    564  ipc::Endpoint<PUiCompositorControllerChild> childPipe;
    565  nsresult rv = PUiCompositorController::CreateEndpoints(
    566      mGPUChild->OtherEndpointProcInfo(), ipc::EndpointProcInfo::Current(),
    567      &parentPipe, &childPipe);
    568  if (NS_FAILED(rv)) {
    569    DisableGPUProcess("Failed to create PUiCompositorController endpoints");
    570    return nullptr;
    571  }
    572 
    573  mGPUChild->SendInitUiCompositorController(aId, std::move(parentPipe));
    574  RefPtr<UiCompositorControllerChild> result =
    575      UiCompositorControllerChild::CreateForGPUProcess(
    576          mProcessToken, std::move(childPipe), aWidget);
    577 
    578  if (result) {
    579    result->SetCompositorSurfaceManager(
    580        mProcess->GetCompositorSurfaceManager());
    581  }
    582  return result;
    583 }
    584 #endif  // defined(MOZ_WIDGET_ANDROID)
    585 
    586 void GPUProcessManager::OnProcessLaunchComplete(GPUProcessHost* aHost) {
    587  MOZ_ASSERT(mProcess && mProcess == aHost);
    588 
    589  // By definition, the process failing to launch is an unstable attempt. While
    590  // we did not get to the point where we are using the features, we should just
    591  // follow the same fallback procedure.
    592  auto* gpuChild = mProcess->GetActor();
    593  if (NS_WARN_IF(!mProcess->IsConnected()) || NS_WARN_IF(!gpuChild) ||
    594      NS_WARN_IF(!gpuChild->EnsureGPUReady())) {
    595    ++mLaunchProcessAttempts;
    596    if (mLaunchProcessAttempts >
    597        uint32_t(StaticPrefs::layers_gpu_process_max_launch_attempts())) {
    598      char disableMessage[64];
    599      SprintfLiteral(disableMessage,
    600                     "Failed to launch GPU process after %d attempts",
    601                     mLaunchProcessAttempts);
    602      DisableGPUProcess(disableMessage);
    603    } else {
    604      DestroyProcess(/* aUnexpectedShutdown */ true);
    605    }
    606    return;
    607  }
    608 
    609  mLaunchProcessAttempts = 0;
    610  mGPUChild = gpuChild;
    611  mProcessToken = mProcess->GetProcessToken();
    612 #if defined(XP_WIN)
    613  if (mAppInForeground) {
    614    SetProcessIsForeground();
    615  }
    616 #endif
    617 
    618  // Set a high priority for the newly-created gpu process.
    619  int pID = mProcess->GetChildProcessId();
    620  hal::SetProcessPriority(pID, hal::PROCESS_PRIORITY_FOREGROUND_HIGH);
    621 
    622  ipc::Endpoint<PVsyncBridgeParent> vsyncParent;
    623  ipc::Endpoint<PVsyncBridgeChild> vsyncChild;
    624  nsresult rv = PVsyncBridge::CreateEndpoints(
    625      mGPUChild->OtherEndpointProcInfo(), ipc::EndpointProcInfo::Current(),
    626      &vsyncParent, &vsyncChild);
    627  if (NS_FAILED(rv)) {
    628    DisableGPUProcess("Failed to create PVsyncBridge endpoints");
    629    return;
    630  }
    631 
    632  mVsyncBridge = VsyncBridgeChild::Create(mVsyncIOThread, mProcessToken,
    633                                          std::move(vsyncChild));
    634  mGPUChild->SendInitVsyncBridge(std::move(vsyncParent));
    635 
    636  MOZ_DIAGNOSTIC_ASSERT(!mBatteryObserver);
    637  if (!AppShutdown::IsInOrBeyond(ShutdownPhase::XPCOMWillShutdown)) {
    638    mBatteryObserver = new BatteryObserver();
    639  }
    640 
    641  // Flush any pref updates that happened during launch and weren't
    642  // included in the blobs set up in LaunchGPUProcess.
    643  for (const mozilla::dom::Pref& pref : mQueuedPrefs) {
    644    (void)NS_WARN_IF(!mGPUChild->SendPreferenceUpdate(pref));
    645  }
    646  mQueuedPrefs.Clear();
    647 
    648  CrashReporter::RecordAnnotationCString(
    649      CrashReporter::Annotation::GPUProcessStatus, "Running");
    650 
    651  CrashReporter::RecordAnnotationU32(
    652      CrashReporter::Annotation::GPUProcessLaunchCount, mTotalProcessAttempts);
    653 
    654  ReinitializeRendering();
    655 }
    656 
    657 void GPUProcessManager::OnProcessDeclaredStable() { mProcessStable = true; }
    658 
    659 static bool ShouldLimitDeviceResets(uint32_t count, int32_t deltaMilliseconds) {
    660  // We decide to limit by comparing the amount of resets that have happened
    661  // and time since the last reset to two prefs.
    662  int32_t timeLimit = StaticPrefs::gfx_device_reset_threshold_ms_AtStartup();
    663  int32_t countLimit = StaticPrefs::gfx_device_reset_limit_AtStartup();
    664 
    665  bool hasTimeLimit = timeLimit >= 0;
    666  bool hasCountLimit = countLimit >= 0;
    667 
    668  bool triggeredTime = deltaMilliseconds < timeLimit;
    669  bool triggeredCount = count > (uint32_t)countLimit;
    670 
    671  // If we have both prefs set then it needs to trigger both limits,
    672  // otherwise we only test the pref that is set or none
    673  if (hasTimeLimit && hasCountLimit) {
    674    return triggeredTime && triggeredCount;
    675  } else if (hasTimeLimit) {
    676    return triggeredTime;
    677  } else if (hasCountLimit) {
    678    return triggeredCount;
    679  }
    680 
    681  return false;
    682 }
    683 
    684 void GPUProcessManager::ResetCompositors() {
    685  // Note: this will recreate devices in addition to recreating compositors.
    686  // This isn't optimal, but this is only used on linux where acceleration
    687  // isn't enabled by default, and this way we don't need a new code path.
    688  SimulateDeviceReset();
    689 }
    690 
    691 void GPUProcessManager::SimulateDeviceReset() {
    692  // Make sure we rebuild environment and configuration for accelerated
    693  // features.
    694  gfxPlatform::GetPlatform()->CompositorUpdated();
    695 
    696  if (mProcess) {
    697    if (mGPUChild) {
    698      mGPUChild->SendSimulateDeviceReset();
    699    }
    700  } else {
    701    wr::RenderThread::Get()->SimulateDeviceReset();
    702  }
    703 }
    704 
    705 bool GPUProcessManager::FallbackFromAcceleration(wr::WebRenderError aError,
    706                                                 const nsCString& aMsg) {
    707  if (aError == wr::WebRenderError::INITIALIZE) {
    708    return gfxPlatform::FallbackFromAcceleration(
    709        gfx::FeatureStatus::Unavailable, "WebRender initialization failed",
    710        aMsg);
    711  } else if (aError == wr::WebRenderError::MAKE_CURRENT) {
    712    return gfxPlatform::FallbackFromAcceleration(
    713        gfx::FeatureStatus::Unavailable,
    714        "Failed to make render context current",
    715        "FEATURE_FAILURE_WEBRENDER_MAKE_CURRENT"_ns);
    716  } else if (aError == wr::WebRenderError::RENDER) {
    717    return gfxPlatform::FallbackFromAcceleration(
    718        gfx::FeatureStatus::Unavailable, "Failed to render WebRender",
    719        "FEATURE_FAILURE_WEBRENDER_RENDER"_ns);
    720  } else if (aError == wr::WebRenderError::NEW_SURFACE) {
    721    // If we cannot create a new Surface even in the final fallback
    722    // configuration then force a crash.
    723    return gfxPlatform::FallbackFromAcceleration(
    724        gfx::FeatureStatus::Unavailable, "Failed to create new surface",
    725        "FEATURE_FAILURE_WEBRENDER_NEW_SURFACE"_ns,
    726        /* aCrashAfterFinalFallback */ true);
    727  } else if (aError == wr::WebRenderError::BEGIN_DRAW) {
    728    return gfxPlatform::FallbackFromAcceleration(
    729        gfx::FeatureStatus::Unavailable, "BeginDraw() failed",
    730        "FEATURE_FAILURE_WEBRENDER_BEGIN_DRAW"_ns);
    731  } else if (aError == wr::WebRenderError::EXCESSIVE_RESETS) {
    732    return gfxPlatform::FallbackFromAcceleration(
    733        gfx::FeatureStatus::Unavailable, "Device resets exceeded threshold",
    734        "FEATURE_FAILURE_WEBRENDER_EXCESSIVE_RESETS"_ns);
    735  } else {
    736    MOZ_ASSERT_UNREACHABLE("Invalid value");
    737    return gfxPlatform::FallbackFromAcceleration(
    738        gfx::FeatureStatus::Unavailable, "Unhandled failure reason",
    739        "FEATURE_FAILURE_WEBRENDER_UNHANDLED"_ns);
    740  }
    741 }
    742 
    743 void GPUProcessManager::DisableWebRenderConfig(wr::WebRenderError aError,
    744                                               const nsCString& aMsg) {
    745  // Clear out any cached errors from a remote device reset.
    746  mLastError.reset();
    747  mLastErrorMsg.reset();
    748 
    749  bool wantRestart;
    750  {
    751    // Collect the gfxVar updates into a single message.
    752    gfxVarsCollectUpdates collect;
    753 
    754    // Disable WebRender
    755    wantRestart = FallbackFromAcceleration(aError, aMsg);
    756    gfxVars::SetUseWebRenderDCompVideoHwOverlayWin(false);
    757    gfxVars::SetUseWebRenderDCompVideoSwOverlayWin(false);
    758  }
    759 
    760  // If we still have the GPU process, and we fallback to a new configuration
    761  // that prefers to have the GPU process, reset the counter. Because we
    762  // updated the gfxVars, we call GPUChild::EnsureGPUReady to force us to wait
    763  // for the update to be processed before creating new compositor sessions.
    764  // Otherwise we risk them being out of sync with the content/parent processes.
    765  if (wantRestart && mProcess && mGPUChild) {
    766    mUnstableProcessAttempts = 1;
    767    mGPUChild->EnsureGPUReady(/* aForceSync */ true);
    768  }
    769 }
    770 
    771 void GPUProcessManager::DisableWebRender(wr::WebRenderError aError,
    772                                         const nsCString& aMsg) {
    773  DisableWebRenderConfig(aError, aMsg);
    774  if (mProcess) {
    775    DestroyRemoteCompositorSessions();
    776  } else {
    777    DestroyInProcessCompositorSessions();
    778  }
    779  NotifyListenersOnCompositeDeviceReset();
    780 }
    781 
    782 void GPUProcessManager::NotifyWebRenderError(wr::WebRenderError aError) {
    783  gfxCriticalNote << "Handling webrender error " << (unsigned int)aError;
    784 #ifdef XP_WIN
    785  if (aError == wr::WebRenderError::VIDEO_OVERLAY) {
    786    gfxVarsCollectUpdates collect;
    787    gfxVars::SetUseWebRenderDCompVideoHwOverlayWin(false);
    788    gfxVars::SetUseWebRenderDCompVideoSwOverlayWin(false);
    789    return;
    790  }
    791  if (aError == wr::WebRenderError::VIDEO_HW_OVERLAY) {
    792    gfxVars::SetUseWebRenderDCompVideoHwOverlayWin(false);
    793    return;
    794  }
    795  if (aError == wr::WebRenderError::VIDEO_SW_OVERLAY) {
    796    gfxVars::SetUseWebRenderDCompVideoSwOverlayWin(false);
    797    return;
    798  }
    799  if (aError == wr::WebRenderError::DCOMP_TEXTURE_OVERLAY) {
    800    gfxVars::SetUseWebRenderDCompositionTextureOverlayWin(false);
    801    return;
    802  }
    803 #else
    804  if (aError == wr::WebRenderError::VIDEO_OVERLAY ||
    805      aError == wr::WebRenderError::VIDEO_HW_OVERLAY ||
    806      aError == wr::WebRenderError::VIDEO_SW_OVERLAY ||
    807      aError == wr::WebRenderError::DCOMP_TEXTURE_OVERLAY) {
    808    MOZ_ASSERT_UNREACHABLE("unexpected to be called");
    809    return;
    810  }
    811 #endif
    812 
    813  // If we have a stable GPU process, this may just be due to an OOM or bad
    814  // driver state. In that case, we should consider restarting the GPU process
    815  // to hopefully alleviate the situation.
    816  if (mProcess && (IsProcessStable(TimeStamp::Now()) ||
    817                   (kIsAndroid && !mAppInForeground))) {
    818    mProcess->KillProcess(/* aGenerateMinidump */ false);
    819    mLastError = Some(aError);
    820    mLastErrorMsg = Some(""_ns);
    821    return;
    822  }
    823 
    824  DisableWebRender(aError, ""_ns);
    825 }
    826 
    827 /* static */
    828 void GPUProcessManager::RecordDeviceReset(DeviceResetReason aReason) {
    829  if (aReason != DeviceResetReason::FORCED_RESET) {
    830    glean::gfx::device_reset_reason.AccumulateSingleSample(uint32_t(aReason));
    831  }
    832 
    833  CrashReporter::RecordAnnotationU32(
    834      CrashReporter::Annotation::DeviceResetReason,
    835      static_cast<uint32_t>(aReason));
    836 }
    837 
    838 /* static */
    839 void GPUProcessManager::NotifyDeviceReset(DeviceResetReason aReason,
    840                                          DeviceResetDetectPlace aPlace) {
    841  if (!NS_IsMainThread()) {
    842    NS_DispatchToMainThread(NS_NewRunnableFunction(
    843        "gfx::GPUProcessManager::NotifyDeviceReset",
    844        [aReason, aPlace]() -> void {
    845          gfx::GPUProcessManager::NotifyDeviceReset(aReason, aPlace);
    846        }));
    847    return;
    848  }
    849 
    850 #ifdef XP_WIN
    851  // Reset and reinitialize the compositor devices
    852  if (auto* deviceManager = DeviceManagerDx::Get()) {
    853    deviceManager->MaybeResetAndReacquireDevices();
    854  }
    855 #else
    856  gfx::GPUProcessManager::RecordDeviceReset(aReason);
    857 #endif
    858 
    859  if (XRE_IsGPUProcess()) {
    860    if (auto* gpuParent = GPUParent::GetSingleton()) {
    861      // End up to GPUProcessManager::OnRemoteProcessDeviceReset()
    862      gpuParent->NotifyDeviceReset(aReason, aPlace);
    863    } else {
    864      MOZ_ASSERT_UNREACHABLE("unexpected to be called");
    865    }
    866    return;
    867  }
    868 
    869  MOZ_ASSERT(XRE_IsParentProcess());
    870  if (auto* gpm = GPUProcessManager::Get()) {
    871    gpm->OnInProcessDeviceReset(aReason, aPlace);
    872  } else {
    873    MOZ_ASSERT_UNREACHABLE("unexpected to be called");
    874  }
    875 }
    876 
    877 bool GPUProcessManager::OnDeviceReset(bool aTrackThreshold) {
    878  // Ignore resets for thresholding if requested.
    879  if (!aTrackThreshold) {
    880    return false;
    881  }
    882 
    883  // Detect whether the device is resetting too quickly or too much
    884  // indicating that we should give up and use software
    885  mDeviceResetCount++;
    886 
    887  auto newTime = TimeStamp::Now();
    888  auto delta = (int32_t)(newTime - mDeviceResetLastTime).ToMilliseconds();
    889  mDeviceResetLastTime = newTime;
    890 
    891  // Returns true if we should disable acceleration due to the reset.
    892  return ShouldLimitDeviceResets(mDeviceResetCount, delta);
    893 }
    894 
    895 void GPUProcessManager::OnInProcessDeviceReset(DeviceResetReason aReason,
    896                                               DeviceResetDetectPlace aPlace) {
    897  gfxCriticalNote << "Detect DeviceReset " << aReason << " " << aPlace
    898                  << " in Parent process";
    899 
    900  bool guilty;
    901  switch (aReason) {
    902    case DeviceResetReason::HUNG:
    903    case DeviceResetReason::RESET:
    904    case DeviceResetReason::INVALID_CALL:
    905      guilty = true;
    906      break;
    907    default:
    908      guilty = false;
    909      break;
    910  }
    911 
    912  if (OnDeviceReset(guilty)) {
    913    gfxCriticalNoteOnce << "In-process device reset threshold exceeded";
    914 #ifdef MOZ_WIDGET_GTK
    915    // FIXME(aosmond): Should we disable WebRender on other platforms?
    916    DisableWebRenderConfig(wr::WebRenderError::EXCESSIVE_RESETS, nsCString());
    917 #endif
    918  }
    919 #ifdef XP_WIN
    920  // Ensure device reset handling before re-creating in process sessions.
    921  // Normally nsWindow::OnPaint() already handled it.
    922  gfxWindowsPlatform::GetPlatform()->HandleDeviceReset();
    923 #endif
    924  DestroyInProcessCompositorSessions();
    925  NotifyListenersOnCompositeDeviceReset();
    926 }
    927 
    928 void GPUProcessManager::OnRemoteProcessDeviceReset(
    929    GPUProcessHost* aHost, const DeviceResetReason& aReason,
    930    const DeviceResetDetectPlace& aPlace) {
    931  gfxCriticalNote << "Detect DeviceReset " << aReason << " " << aPlace
    932                  << " in GPU process";
    933 
    934  if (OnDeviceReset(/* aTrackThreshold */ true)) {
    935    // If we have a stable GPU process, this may just be due to an OOM or bad
    936    // driver state. In that case, we should consider restarting the GPU process
    937    // to hopefully alleviate the situation.
    938    if (mProcess && (IsProcessStable(TimeStamp::Now()) ||
    939                     (kIsAndroid && !mAppInForeground))) {
    940      mProcess->KillProcess(/* aGenerateMinidump */ false);
    941      mLastError = Some(wr::WebRenderError::EXCESSIVE_RESETS);
    942      mLastErrorMsg = Some(""_ns);
    943      return;
    944    }
    945 
    946    DisableWebRenderConfig(wr::WebRenderError::EXCESSIVE_RESETS, ""_ns);
    947  }
    948 
    949  DestroyRemoteCompositorSessions();
    950  NotifyListenersOnCompositeDeviceReset();
    951 }
    952 
    953 void GPUProcessManager::NotifyListenersOnCompositeDeviceReset() {
    954  nsTArray<RefPtr<GPUProcessListener>> listeners;
    955  listeners.AppendElements(mListeners);
    956  for (const auto& listener : listeners) {
    957    listener->OnCompositorDeviceReset();
    958  }
    959 }
    960 
    961 void GPUProcessManager::OnProcessUnexpectedShutdown(GPUProcessHost* aHost) {
    962  MOZ_ASSERT(mProcess && mProcess == aHost);
    963 
    964  if (StaticPrefs::layers_gpu_process_crash_also_crashes_browser()) {
    965    MOZ_CRASH("GPU process crashed and pref is set to crash the browser.");
    966  }
    967 
    968  CompositorManagerChild::OnGPUProcessLost(aHost->GetProcessToken());
    969  DestroyProcess(/* aUnexpectedShutdown */ true);
    970 
    971  // If the process didn't live long enough, increment our unstable attempts
    972  // counter so that we don't end up in a restart loop. If the process did live
    973  // long enough, reset the counter so that we don't disable the process too
    974  // eagerly.
    975  if (IsProcessStable(TimeStamp::Now())) {
    976    mProcessStableOnce = true;
    977    mUnstableProcessAttempts = 0;
    978  } else if (kIsAndroid && !mAppInForeground) {
    979    // On Android if the process is lost whilst in the background it was
    980    // probably killed by the OS, and it may never have had a chance to have
    981    // been declared stable prior to being killed. We don't want this happening
    982    // repeatedly to result in the GPU process being disabled, so treat any
    983    // process lost whilst in the background as stable.
    984    mUnstableProcessAttempts = 0;
    985  } else {
    986    mUnstableProcessAttempts++;
    987    mozilla::glean::gpu_process::unstable_launch_attempts.Set(
    988        mUnstableProcessAttempts);
    989  }
    990 
    991  if (mUnstableProcessAttempts >
    992      uint32_t(StaticPrefs::layers_gpu_process_max_restarts())) {
    993    char disableMessage[64];
    994    SprintfLiteral(disableMessage, "GPU process disabled after %d attempts",
    995                   mTotalProcessAttempts);
    996    if (!MaybeDisableGPUProcess(disableMessage, /* aAllowRestart */ true)) {
    997      // Fallback wants the GPU process. Reset our counter.
    998      MOZ_DIAGNOSTIC_ASSERT(gfxConfig::IsEnabled(Feature::GPU_PROCESS));
    999      mUnstableProcessAttempts = 0;
   1000      HandleProcessLost();
   1001    } else {
   1002      MOZ_DIAGNOSTIC_ASSERT(!gfxConfig::IsEnabled(Feature::GPU_PROCESS));
   1003    }
   1004  } else if (mUnstableProcessAttempts >
   1005                 uint32_t(StaticPrefs::
   1006                              layers_gpu_process_max_restarts_with_decoder()) &&
   1007             mDecodeVideoOnGpuProcess) {
   1008    mDecodeVideoOnGpuProcess = false;
   1009    mozilla::glean::gpu_process::crash_fallbacks.Get("decoding_disabled"_ns)
   1010        .Add(1);
   1011    HandleProcessLost();
   1012  } else {
   1013    mozilla::glean::gpu_process::crash_fallbacks.Get("none"_ns).Add(1);
   1014    HandleProcessLost();
   1015  }
   1016 }
   1017 
   1018 void GPUProcessManager::HandleProcessLost() {
   1019  MOZ_ASSERT(NS_IsMainThread());
   1020 
   1021  // The shutdown and restart sequence for the GPU process is as follows:
   1022  //
   1023  //  (1) The GPU process dies. IPDL will enqueue an ActorDestroy message on
   1024  //      each channel owning a bridge to the GPU process, on the thread owning
   1025  //      that channel.
   1026  //
   1027  //  (2) The first channel to process its ActorDestroy message will post a
   1028  //      message to the main thread to call NotifyRemoteActorDestroyed on the
   1029  //      GPUProcessManager, which calls OnProcessUnexpectedShutdown if it has
   1030  //      not handled shutdown for this process yet. OnProcessUnexpectedShutdown
   1031  //      is responsible for tearing down the old process and deciding whether
   1032  //      or not to disable the GPU process. It then calls this function,
   1033  //      HandleProcessLost.
   1034  //
   1035  //  (3) We then notify each widget that its session with the compositor is now
   1036  //      invalid. The widget is responsible for destroying its layer manager
   1037  //      and CompositorBridgeChild. Note that at this stage, not all actors may
   1038  //      have received ActorDestroy yet. CompositorBridgeChild may attempt to
   1039  //      send messages, and if this happens, it will probably report a
   1040  //      MsgDropped error. This is okay.
   1041  //
   1042  //  (4) At this point, the UI process has a clean slate: no layers should
   1043  //      exist for the old compositor. We may make a decision on whether or not
   1044  //      to re-launch the GPU process. Or, on Android if the app is in the
   1045  //      background we may decide to wait until it comes to the foreground
   1046  //      before re-launching.
   1047  //
   1048  //  (5) When we do decide to re-launch, or continue without a GPU process, we
   1049  //      notify each ContentParent of the lost connection. It will request new
   1050  //      endpoints from the GPUProcessManager and forward them to its
   1051  //      ContentChild. The parent-side of these endpoints may come from the
   1052  //      compositor thread of the UI process, or the compositor thread of the
   1053  //      GPU process. However, no actual compositors should exist yet.
   1054  //
   1055  //  (6) Each ContentChild will receive new endpoints. It will destroy its
   1056  //      Compositor/ImageBridgeChild singletons and recreate them, as well
   1057  //      as invalidate all retained layers.
   1058  //
   1059  //  (7) In addition, each ContentChild will ask each of its BrowserChildren
   1060  //      to re-request association with the compositor for the window
   1061  //      owning the tab. The sequence of calls looks like:
   1062  //        (a) [CONTENT] ContentChild::RecvReinitRendering
   1063  //        (b) [CONTENT] BrowserChild::ReinitRendering
   1064  //        (c) [CONTENT] BrowserChild::SendEnsureLayersConnected
   1065  //        (d)      [UI] BrowserParent::RecvEnsureLayersConnected
   1066  //        (e)      [UI] RemoteLayerTreeOwner::EnsureLayersConnected
   1067  //        (f)      [UI] CompositorBridgeChild::SendNotifyChildRecreated
   1068  //
   1069  //      Note that at step (e), RemoteLayerTreeOwner will call
   1070  //      GetWindowRenderer on the nsIWidget owning the tab. This step ensures
   1071  //      that a compositor exists for the window. If we decided to launch a new
   1072  //      GPU Process, at this point we block until the process has launched and
   1073  //      we're able to create a new window compositor. Otherwise, if
   1074  //      compositing is now in-process, this will simply create a new
   1075  //      CompositorBridgeParent in the UI process. If there are multiple tabs
   1076  //      in the same window, additional tabs will simply return the already-
   1077  //      established compositor.
   1078  //
   1079  //      Finally, this step serves one other crucial function: tabs must be
   1080  //      associated with a window compositor or else they can't forward
   1081  //      layer transactions. So this step both ensures that a compositor
   1082  //      exists, and that the tab can forward layers.
   1083  //
   1084  //  (8) Last, if the window had no remote tabs, step (7) will not have
   1085  //      applied, and the window will not have a new compositor just yet. The
   1086  //      next refresh tick and paint will ensure that one exists, again via
   1087  //      nsIWidget::GetWindowRenderer. On Android, we called
   1088  //      nsIWidgetListener::RequestRepaint back in step (3) to ensure this
   1089  //      tick occurs, but on other platforms this is not necessary.
   1090 
   1091  DestroyRemoteCompositorSessions();
   1092 
   1093 #ifdef MOZ_WIDGET_ANDROID
   1094  java::SurfaceControlManager::GetInstance()->OnGpuProcessLoss();
   1095 #endif
   1096 
   1097  // Re-launch the process if immediately if the GPU process is still enabled.
   1098  // Except on Android if the app is in the background, where we want to wait
   1099  // until the app is in the foreground again.
   1100  if (gfxConfig::IsEnabled(Feature::GPU_PROCESS)) {
   1101 #ifdef MOZ_WIDGET_ANDROID
   1102    if (mAppInForeground) {
   1103 #else
   1104    {
   1105 #endif
   1106      (void)LaunchGPUProcess();
   1107    }
   1108  } else {
   1109    // If the GPU process is disabled we can reinitialize rendering immediately.
   1110    // This will be handled in OnProcessLaunchComplete() if the GPU process is
   1111    // enabled.
   1112    ReinitializeRendering();
   1113  }
   1114 }
   1115 
   1116 void GPUProcessManager::ReinitializeRendering() {
   1117  // Notify content. This will ensure that each content process re-establishes
   1118  // a connection to the compositor thread (whether it's in-process or in a
   1119  // newly launched GPU process).
   1120  nsTArray<RefPtr<GPUProcessListener>> listeners;
   1121  listeners.AppendElements(mListeners);
   1122  // Make sure any fallback renderers get destroyed first.
   1123  for (const auto& listener : listeners) {
   1124    listener->OnCompositorDestroyBackgrounded();
   1125  }
   1126  // Then do the recreations.
   1127  for (const auto& listener : listeners) {
   1128    listener->OnCompositorUnexpectedShutdown();
   1129  }
   1130 
   1131  // Notify any observers that the compositor has been reinitialized,
   1132  // eg the ZoomConstraintsClients for parent process documents.
   1133  nsCOMPtr<nsIObserverService> observerService = services::GetObserverService();
   1134  if (observerService) {
   1135    observerService->NotifyObservers(nullptr, "compositor-reinitialized",
   1136                                     nullptr);
   1137  }
   1138 }
   1139 
   1140 void GPUProcessManager::DestroyRemoteCompositorSessions() {
   1141  // Build a list of sessions to notify, since notification might delete
   1142  // entries from the list.
   1143  nsTArray<RefPtr<RemoteCompositorSession>> sessions;
   1144  for (auto& session : mRemoteSessions) {
   1145    sessions.AppendElement(session);
   1146  }
   1147 
   1148  // Notify each widget that we have lost the GPU process. This will ensure
   1149  // that each widget destroys its layer manager and CompositorBridgeChild.
   1150  for (const auto& session : sessions) {
   1151    session->NotifySessionLost();
   1152  }
   1153 }
   1154 
   1155 void GPUProcessManager::DestroyInProcessCompositorSessions() {
   1156  // Build a list of sessions to notify, since notification might delete
   1157  // entries from the list.
   1158  nsTArray<RefPtr<InProcessCompositorSession>> sessions;
   1159  for (auto& session : mInProcessSessions) {
   1160    sessions.AppendElement(session);
   1161  }
   1162 
   1163  // Notify each widget that we have lost the GPU process. This will ensure
   1164  // that each widget destroys its layer manager and CompositorBridgeChild.
   1165  for (const auto& session : sessions) {
   1166    session->NotifySessionLost();
   1167  }
   1168 
   1169  // Ensure our stablility state is reset so that we don't necessarily crash
   1170  // right away on some WebRender errors.
   1171  CompositorBridgeParent::ResetStable();
   1172  ResetProcessStable();
   1173 }
   1174 
   1175 void GPUProcessManager::NotifyRemoteActorDestroyed(
   1176    const uint64_t& aProcessToken) {
   1177  if (!NS_IsMainThread()) {
   1178    RefPtr<Runnable> task = mTaskFactory.NewRunnableMethod(
   1179        &GPUProcessManager::NotifyRemoteActorDestroyed, aProcessToken);
   1180    NS_DispatchToMainThread(task.forget());
   1181    return;
   1182  }
   1183 
   1184  if (mProcessToken != aProcessToken) {
   1185    // This token is for an older process; we can safely ignore it.
   1186    return;
   1187  }
   1188 
   1189  // One of the bridged top-level actors for the GPU process has been
   1190  // prematurely terminated, and we're receiving a notification. This
   1191  // can happen if the ActorDestroy for a bridged protocol fires
   1192  // before the ActorDestroy for PGPUChild.
   1193  OnProcessUnexpectedShutdown(mProcess);
   1194 }
   1195 
   1196 void GPUProcessManager::ShutdownInternal() {
   1197  if (mObserver) {
   1198    mObserver->Shutdown();
   1199    mObserver = nullptr;
   1200  }
   1201 
   1202  DestroyProcess();
   1203  mVsyncIOThread = nullptr;
   1204 }
   1205 
   1206 void GPUProcessManager::KillProcess(bool aGenerateMinidump) {
   1207  if (!NS_IsMainThread()) {
   1208    RefPtr<Runnable> task = mTaskFactory.NewRunnableMethod(
   1209        &GPUProcessManager::KillProcess, aGenerateMinidump);
   1210    NS_DispatchToMainThread(task.forget());
   1211    return;
   1212  }
   1213 
   1214  if (!mProcess) {
   1215    return;
   1216  }
   1217 
   1218  mProcess->KillProcess(aGenerateMinidump);
   1219 }
   1220 
   1221 void GPUProcessManager::CrashProcess() {
   1222  if (!mProcess) {
   1223    return;
   1224  }
   1225 
   1226  mProcess->CrashProcess();
   1227 }
   1228 
   1229 void GPUProcessManager::DestroyProcess(bool aUnexpectedShutdown) {
   1230  if (!mProcess) {
   1231    return;
   1232  }
   1233 
   1234  mProcess->Shutdown(aUnexpectedShutdown);
   1235  mProcessToken = 0;
   1236  mProcess = nullptr;
   1237  mGPUChild = nullptr;
   1238  mQueuedPrefs.Clear();
   1239  if (mVsyncBridge) {
   1240    mVsyncBridge->Close();
   1241    mVsyncBridge = nullptr;
   1242  }
   1243  StopBatteryObserving();
   1244 
   1245  CrashReporter::RecordAnnotationCString(
   1246      CrashReporter::Annotation::GPUProcessStatus, "Destroyed");
   1247 }
   1248 
   1249 void GPUProcessManager::StopBatteryObserving() {
   1250  if (mBatteryObserver) {
   1251    mBatteryObserver->Shutdown();
   1252    mBatteryObserver = nullptr;
   1253  }
   1254 }
   1255 
   1256 already_AddRefed<CompositorSession> GPUProcessManager::CreateTopLevelCompositor(
   1257    nsIWidget* aWidget, WebRenderLayerManager* aLayerManager,
   1258    CSSToLayoutDeviceScale aScale, const CompositorOptions& aOptions,
   1259    bool aUseExternalSurfaceSize, const gfx::IntSize& aSurfaceSize,
   1260    uint64_t aInnerWindowId, bool* aRetryOut) {
   1261  MOZ_DIAGNOSTIC_ASSERT(IsGPUReady());
   1262  MOZ_ASSERT(aRetryOut);
   1263 
   1264  if (!EnsureProtocolsReady()) {
   1265    *aRetryOut = false;
   1266    return nullptr;
   1267  }
   1268 
   1269  LayersId layerTreeId = AllocateLayerTreeId();
   1270  RefPtr<CompositorSession> session;
   1271  if (mGPUChild) {
   1272    session = CreateRemoteSession(aWidget, aLayerManager, layerTreeId, aScale,
   1273                                  aOptions, aUseExternalSurfaceSize,
   1274                                  aSurfaceSize, aInnerWindowId);
   1275    if (NS_WARN_IF(!session)) {
   1276      // This may have failed for intermittent reasons, or perhaps indicates we
   1277      // are fundamentally unable to use acceleration.
   1278      // OnProcessUnexpectedShutdown will first attempt to relaunch the GPU
   1279      // process in the same configuration a number of times, then fallback from
   1280      // acceleration, then finally disable the GPU process if it continues to
   1281      // fail.
   1282      OnProcessUnexpectedShutdown(mProcess);
   1283      *aRetryOut = true;
   1284      return nullptr;
   1285    }
   1286  } else {
   1287    session = InProcessCompositorSession::Create(
   1288        aWidget, aLayerManager, layerTreeId, aScale, aOptions,
   1289        aUseExternalSurfaceSize, aSurfaceSize, AllocateNamespace(),
   1290        aInnerWindowId);
   1291  }
   1292 
   1293 #if defined(MOZ_WIDGET_ANDROID)
   1294  if (session) {
   1295    // Nothing to do if controller gets a nullptr
   1296    auto controller =
   1297        CreateUiCompositorController(aWidget, session->RootLayerTreeId());
   1298    MOZ_ASSERT(controller);
   1299    session->SetUiCompositorControllerChild(std::move(controller));
   1300  }
   1301 #endif  // defined(MOZ_WIDGET_ANDROID)
   1302 
   1303  *aRetryOut = false;
   1304  return session.forget();
   1305 }
   1306 
   1307 RefPtr<CompositorSession> GPUProcessManager::CreateRemoteSession(
   1308    nsIWidget* aWidget, WebRenderLayerManager* aLayerManager,
   1309    const LayersId& aRootLayerTreeId, CSSToLayoutDeviceScale aScale,
   1310    const CompositorOptions& aOptions, bool aUseExternalSurfaceSize,
   1311    const gfx::IntSize& aSurfaceSize, uint64_t aInnerWindowId) {
   1312 #ifdef MOZ_WIDGET_SUPPORTS_OOP_COMPOSITING
   1313  widget::CompositorWidgetInitData initData;
   1314  aWidget->GetCompositorWidgetInitData(&initData);
   1315 
   1316  RefPtr<CompositorBridgeChild> child =
   1317      CompositorManagerChild::CreateWidgetCompositorBridge(
   1318          mProcessToken, aLayerManager, AllocateNamespace(), aScale, aOptions,
   1319          aUseExternalSurfaceSize, aSurfaceSize, aInnerWindowId);
   1320  if (!child) {
   1321    gfxCriticalNote << "Failed to create CompositorBridgeChild";
   1322    return nullptr;
   1323  }
   1324 
   1325  RefPtr<CompositorVsyncDispatcher> dispatcher =
   1326      aWidget->GetCompositorVsyncDispatcher();
   1327  RefPtr<widget::CompositorWidgetVsyncObserver> observer =
   1328      new widget::CompositorWidgetVsyncObserver(mVsyncBridge, aRootLayerTreeId);
   1329 
   1330  widget::CompositorWidgetChild* widget =
   1331      new widget::CompositorWidgetChild(dispatcher, observer, initData);
   1332  if (!child->SendPCompositorWidgetConstructor(widget, std::move(initData))) {
   1333    return nullptr;
   1334  }
   1335  if (!widget->Initialize(aOptions)) {
   1336    return nullptr;
   1337  }
   1338  if (!child->SendInitialize(aRootLayerTreeId)) {
   1339    return nullptr;
   1340  }
   1341 
   1342  RefPtr<APZCTreeManagerChild> apz = nullptr;
   1343  if (aOptions.UseAPZ()) {
   1344    PAPZCTreeManagerChild* papz =
   1345        child->SendPAPZCTreeManagerConstructor(LayersId{0});
   1346    if (!papz) {
   1347      return nullptr;
   1348    }
   1349    apz = static_cast<APZCTreeManagerChild*>(papz);
   1350 
   1351    ipc::Endpoint<PAPZInputBridgeParent> parentPipe;
   1352    ipc::Endpoint<PAPZInputBridgeChild> childPipe;
   1353    nsresult rv = PAPZInputBridge::CreateEndpoints(
   1354        mGPUChild->OtherEndpointProcInfo(), ipc::EndpointProcInfo::Current(),
   1355        &parentPipe, &childPipe);
   1356    if (NS_FAILED(rv)) {
   1357      return nullptr;
   1358    }
   1359    mGPUChild->SendInitAPZInputBridge(aRootLayerTreeId, std::move(parentPipe));
   1360 
   1361    RefPtr<APZInputBridgeChild> inputBridge =
   1362        APZInputBridgeChild::Create(mProcessToken, std::move(childPipe));
   1363    if (!inputBridge) {
   1364      return nullptr;
   1365    }
   1366 
   1367    apz->SetInputBridge(inputBridge);
   1368  }
   1369 
   1370  return new RemoteCompositorSession(aWidget, child, widget, apz,
   1371                                     aRootLayerTreeId);
   1372 #else
   1373  gfxCriticalNote << "Platform does not support out-of-process compositing";
   1374  return nullptr;
   1375 #endif
   1376 }
   1377 
   1378 bool GPUProcessManager::CreateContentBridges(
   1379    ipc::EndpointProcInfo aOtherProcess,
   1380    ipc::Endpoint<PCompositorManagerChild>* aOutCompositor,
   1381    ipc::Endpoint<PImageBridgeChild>* aOutImageBridge,
   1382    ipc::Endpoint<PVRManagerChild>* aOutVRBridge,
   1383    ipc::Endpoint<PRemoteMediaManagerChild>* aOutVideoManager,
   1384    dom::ContentParentId aChildId, nsTArray<uint32_t>* aNamespaces) {
   1385  const uint32_t cmNamespace = AllocateNamespace();
   1386  if (!CreateContentCompositorManager(aOtherProcess, aChildId, cmNamespace,
   1387                                      aOutCompositor) ||
   1388      !CreateContentImageBridge(aOtherProcess, aChildId, aOutImageBridge) ||
   1389      !CreateContentVRManager(aOtherProcess, aChildId, aOutVRBridge)) {
   1390    return false;
   1391  }
   1392  // RemoteMediaManager is only supported in the GPU process, so we allow this
   1393  // to be fallible.
   1394  CreateContentRemoteMediaManager(aOtherProcess, aChildId, aOutVideoManager);
   1395  // Allocates 3 namespaces(for CompositorManagerChild, CompositorBridgeChild
   1396  // and ImageBridgeChild)
   1397  aNamespaces->AppendElement(cmNamespace);
   1398  aNamespaces->AppendElement(AllocateNamespace());
   1399  aNamespaces->AppendElement(AllocateNamespace());
   1400  return true;
   1401 }
   1402 
   1403 bool GPUProcessManager::CreateContentCompositorManager(
   1404    ipc::EndpointProcInfo aOtherProcess, dom::ContentParentId aChildId,
   1405    uint32_t aNamespace, ipc::Endpoint<PCompositorManagerChild>* aOutEndpoint) {
   1406  MOZ_DIAGNOSTIC_ASSERT(IsGPUReady());
   1407 
   1408  ipc::Endpoint<PCompositorManagerParent> parentPipe;
   1409  ipc::Endpoint<PCompositorManagerChild> childPipe;
   1410 
   1411  ipc::EndpointProcInfo parentInfo = mGPUChild
   1412                                         ? mGPUChild->OtherEndpointProcInfo()
   1413                                         : ipc::EndpointProcInfo::Current();
   1414 
   1415  nsresult rv = PCompositorManager::CreateEndpoints(parentInfo, aOtherProcess,
   1416                                                    &parentPipe, &childPipe);
   1417  if (NS_FAILED(rv)) {
   1418    gfxCriticalNote << "Could not create content compositor manager: "
   1419                    << hexa(int(rv));
   1420    return false;
   1421  }
   1422 
   1423  if (mGPUChild) {
   1424    mGPUChild->SendNewContentCompositorManager(std::move(parentPipe), aChildId,
   1425                                               aNamespace);
   1426  } else if (!CompositorManagerParent::Create(std::move(parentPipe), aChildId,
   1427                                              aNamespace,
   1428                                              /* aIsRoot */ false)) {
   1429    return false;
   1430  }
   1431 
   1432  *aOutEndpoint = std::move(childPipe);
   1433  return true;
   1434 }
   1435 
   1436 bool GPUProcessManager::CreateContentImageBridge(
   1437    ipc::EndpointProcInfo aOtherProcess, dom::ContentParentId aChildId,
   1438    ipc::Endpoint<PImageBridgeChild>* aOutEndpoint) {
   1439  MOZ_DIAGNOSTIC_ASSERT(IsGPUReady());
   1440 
   1441  if (!EnsureImageBridgeChild()) {
   1442    return false;
   1443  }
   1444 
   1445  ipc::EndpointProcInfo parentInfo = mGPUChild
   1446                                         ? mGPUChild->OtherEndpointProcInfo()
   1447                                         : ipc::EndpointProcInfo::Current();
   1448 
   1449  ipc::Endpoint<PImageBridgeParent> parentPipe;
   1450  ipc::Endpoint<PImageBridgeChild> childPipe;
   1451  nsresult rv = PImageBridge::CreateEndpoints(parentInfo, aOtherProcess,
   1452                                              &parentPipe, &childPipe);
   1453  if (NS_FAILED(rv)) {
   1454    gfxCriticalNote << "Could not create content compositor bridge: "
   1455                    << hexa(int(rv));
   1456    return false;
   1457  }
   1458 
   1459  if (mGPUChild) {
   1460    mGPUChild->SendNewContentImageBridge(std::move(parentPipe), aChildId);
   1461  } else {
   1462    if (!ImageBridgeParent::CreateForContent(std::move(parentPipe), aChildId)) {
   1463      return false;
   1464    }
   1465  }
   1466 
   1467  *aOutEndpoint = std::move(childPipe);
   1468  return true;
   1469 }
   1470 
   1471 base::ProcessId GPUProcessManager::GPUProcessPid() {
   1472  base::ProcessId gpuPid =
   1473      mGPUChild ? mGPUChild->OtherPid() : base::kInvalidProcessId;
   1474  return gpuPid;
   1475 }
   1476 
   1477 ipc::EndpointProcInfo GPUProcessManager::GPUEndpointProcInfo() {
   1478  return mGPUChild ? mGPUChild->OtherEndpointProcInfo()
   1479                   : ipc::EndpointProcInfo::Invalid();
   1480 }
   1481 
   1482 bool GPUProcessManager::CreateContentVRManager(
   1483    ipc::EndpointProcInfo aOtherProcess, dom::ContentParentId aChildId,
   1484    ipc::Endpoint<PVRManagerChild>* aOutEndpoint) {
   1485  MOZ_DIAGNOSTIC_ASSERT(IsGPUReady());
   1486 
   1487  if (NS_WARN_IF(!EnsureVRManager())) {
   1488    return false;
   1489  }
   1490 
   1491  ipc::EndpointProcInfo parentInfo = mGPUChild
   1492                                         ? mGPUChild->OtherEndpointProcInfo()
   1493                                         : ipc::EndpointProcInfo::Current();
   1494 
   1495  ipc::Endpoint<PVRManagerParent> parentPipe;
   1496  ipc::Endpoint<PVRManagerChild> childPipe;
   1497  nsresult rv = PVRManager::CreateEndpoints(parentInfo, aOtherProcess,
   1498                                            &parentPipe, &childPipe);
   1499  if (NS_FAILED(rv)) {
   1500    gfxCriticalNote << "Could not create content compositor bridge: "
   1501                    << hexa(int(rv));
   1502    return false;
   1503  }
   1504 
   1505  if (mGPUChild) {
   1506    mGPUChild->SendNewContentVRManager(std::move(parentPipe), aChildId);
   1507  } else {
   1508    if (!VRManagerParent::CreateForContent(std::move(parentPipe), aChildId)) {
   1509      return false;
   1510    }
   1511  }
   1512 
   1513  *aOutEndpoint = std::move(childPipe);
   1514  return true;
   1515 }
   1516 
   1517 void GPUProcessManager::CreateContentRemoteMediaManager(
   1518    ipc::EndpointProcInfo aOtherProcess, dom::ContentParentId aChildId,
   1519    ipc::Endpoint<PRemoteMediaManagerChild>* aOutEndpoint) {
   1520  MOZ_DIAGNOSTIC_ASSERT(IsGPUReady());
   1521 
   1522  if (!mGPUChild || !StaticPrefs::media_gpu_process_decoder() ||
   1523      !mDecodeVideoOnGpuProcess) {
   1524    return;
   1525  }
   1526 
   1527  ipc::Endpoint<PRemoteMediaManagerParent> parentPipe;
   1528  ipc::Endpoint<PRemoteMediaManagerChild> childPipe;
   1529 
   1530  nsresult rv = PRemoteMediaManager::CreateEndpoints(
   1531      mGPUChild->OtherEndpointProcInfo(), aOtherProcess, &parentPipe,
   1532      &childPipe);
   1533  if (NS_FAILED(rv)) {
   1534    gfxCriticalNote << "Could not create content video decoder: "
   1535                    << hexa(int(rv));
   1536    return;
   1537  }
   1538 
   1539  mGPUChild->SendNewContentRemoteMediaManager(std::move(parentPipe), aChildId);
   1540 
   1541  *aOutEndpoint = std::move(childPipe);
   1542 }
   1543 
   1544 #ifdef MOZ_WMF_MEDIA_ENGINE
   1545 nsresult GPUProcessManager::CreateUtilityMFCDMVideoBridge(
   1546    mozilla::ipc::UtilityMediaServiceChild* aChild,
   1547    mozilla::ipc::EndpointProcInfo aOtherProcess) {
   1548  MOZ_ASSERT(aChild);
   1549  MOZ_ASSERT(aChild->CanSend());
   1550 
   1551  ipc::Endpoint<PVideoBridgeChild> childPipe;
   1552  nsresult rv = EnsureVideoBridge(VideoBridgeSource::MFMediaEngineCDMProcess,
   1553                                  aOtherProcess, &childPipe);
   1554  if (NS_WARN_IF(NS_FAILED(rv))) {
   1555    return rv;
   1556  }
   1557 
   1558  gfx::ContentDeviceData contentDeviceData;
   1559  gfxPlatform::GetPlatform()->BuildContentDeviceData(&contentDeviceData);
   1560  aChild->SendInitVideoBridge(std::move(childPipe), contentDeviceData);
   1561  return NS_OK;
   1562 }
   1563 #endif
   1564 
   1565 nsresult GPUProcessManager::CreateRddVideoBridge(RDDProcessManager* aRDD,
   1566                                                 RDDChild* aChild) {
   1567  MOZ_ASSERT(aRDD);
   1568  MOZ_ASSERT(aChild);
   1569  MOZ_ASSERT(aChild->CanSend());
   1570 
   1571  ipc::Endpoint<PVideoBridgeChild> childPipe;
   1572  nsresult rv = EnsureVideoBridge(VideoBridgeSource::RddProcess,
   1573                                  aChild->OtherEndpointProcInfo(), &childPipe);
   1574  if (NS_WARN_IF(NS_FAILED(rv))) {
   1575    return rv;
   1576  }
   1577 
   1578  gfx::ContentDeviceData contentDeviceData;
   1579  gfxPlatform::GetPlatform()->BuildContentDeviceData(&contentDeviceData);
   1580  aChild->SendInitVideoBridge(std::move(childPipe),
   1581                              !aRDD->AttemptedRDDProcess(), contentDeviceData);
   1582  return NS_OK;
   1583 }
   1584 
   1585 nsresult GPUProcessManager::EnsureVideoBridge(
   1586    layers::VideoBridgeSource aSource,
   1587    mozilla::ipc::EndpointProcInfo aOtherProcess,
   1588    mozilla::ipc::Endpoint<layers::PVideoBridgeChild>* aOutChildPipe) {
   1589  MOZ_ASSERT(aOutChildPipe);
   1590  MOZ_DIAGNOSTIC_ASSERT(IsGPUReady());
   1591 
   1592  ipc::EndpointProcInfo gpuInfo = mGPUChild ? mGPUChild->OtherEndpointProcInfo()
   1593                                            : ipc::EndpointProcInfo::Current();
   1594 
   1595  // The child end is the producer of video frames; the parent end is the
   1596  // consumer.
   1597  ipc::Endpoint<PVideoBridgeParent> parentPipe;
   1598  nsresult rv = PVideoBridge::CreateEndpoints(gpuInfo, aOtherProcess,
   1599                                              &parentPipe, aOutChildPipe);
   1600  if (NS_WARN_IF(NS_FAILED(rv))) {
   1601    return rv;
   1602  }
   1603 
   1604  if (mGPUChild) {
   1605    mGPUChild->SendInitVideoBridge(std::move(parentPipe), aSource);
   1606  } else {
   1607    VideoBridgeParent::Open(std::move(parentPipe), aSource);
   1608  }
   1609  return NS_OK;
   1610 }
   1611 
   1612 void GPUProcessManager::UnmapLayerTreeId(LayersId aLayersId,
   1613                                         base::ProcessId aOwningId) {
   1614  // If the GPU process is down, but not disabled, there is no need to relaunch
   1615  // here because the layers ID is already invalid.
   1616  if (mGPUChild) {
   1617    mGPUChild->SendRemoveLayerTreeIdMapping(
   1618        LayerTreeIdMapping(aLayersId, aOwningId));
   1619  } else if (!gfxConfig::IsEnabled(Feature::GPU_PROCESS)) {
   1620    CompositorBridgeParent::DeallocateLayerTreeId(aLayersId);
   1621  }
   1622 
   1623  LayerTreeOwnerTracker::Get()->Unmap(aLayersId, aOwningId);
   1624 }
   1625 
   1626 bool GPUProcessManager::IsLayerTreeIdMapped(LayersId aLayersId,
   1627                                            base::ProcessId aRequestingId) {
   1628  return LayerTreeOwnerTracker::Get()->IsMapped(aLayersId, aRequestingId);
   1629 }
   1630 
   1631 LayersId GPUProcessManager::AllocateLayerTreeId() {
   1632  // Allocate tree id by using id namespace.
   1633  // By it, tree id does not conflict with external image id and
   1634  // async image pipeline id.
   1635  MOZ_ASSERT(NS_IsMainThread());
   1636  // Increment the resource id by two instead of one so that each
   1637  // WebRenderLayerManager and WebRenderBridgeParent gets two distinct
   1638  // pipeline IDs they can use.
   1639  // This is gross but the steps to create a temporary pipeline
   1640  // ID from the content process or the compositor thread are too
   1641  // complex and expensive.
   1642  // TODO: Ideally, we'd allocate only the namespace here and let the
   1643  // WR layer manager produce any number of pipeline IDs.
   1644  mResourceId += 2;
   1645  if (mResourceId >= UINT32_MAX - 1) {
   1646    // Move to next id namespace.
   1647    mIdNamespace = AllocateNamespace();
   1648    mResourceId = 2;
   1649  }
   1650 
   1651  uint64_t layerTreeId = mIdNamespace;
   1652  layerTreeId = (layerTreeId << 32) | mResourceId;
   1653  return LayersId{layerTreeId};
   1654 }
   1655 
   1656 // See the comment in AllocateLayerTreeId above.
   1657 // For now this is only used for view-transition snapshots of the old state,
   1658 // it's probably best to avoid using this for anything else.
   1659 wr::PipelineId GetTemporaryWebRenderPipelineId(wr::PipelineId aMainPipeline) {
   1660  // Sanity check that we are have the expected even number for
   1661  // the main pipeline handle.
   1662  MOZ_ASSERT(aMainPipeline.mHandle % 2 == 0);
   1663  auto id = aMainPipeline;
   1664  id.mHandle += 1;
   1665  return id;
   1666 }
   1667 
   1668 uint32_t GPUProcessManager::AllocateNamespace() {
   1669  MOZ_ASSERT(NS_IsMainThread());
   1670  return ++mNextNamespace;
   1671 }
   1672 
   1673 bool GPUProcessManager::AllocateAndConnectLayerTreeId(
   1674    PCompositorBridgeChild* aCompositorBridge, base::ProcessId aOtherPid,
   1675    LayersId* aOutLayersId, CompositorOptions* aOutCompositorOptions) {
   1676  MOZ_ASSERT(aOutLayersId);
   1677 
   1678  LayersId layersId = AllocateLayerTreeId();
   1679  *aOutLayersId = layersId;
   1680 
   1681  // We always map the layer ID in the parent process so that we can recover
   1682  // from GPU process crashes. In that case, the tree will be shared with the
   1683  // new GPU process at initialization.
   1684  LayerTreeOwnerTracker::Get()->Map(layersId, aOtherPid);
   1685 
   1686  if (NS_WARN_IF(NS_FAILED(EnsureGPUReady()))) {
   1687    return false;
   1688  }
   1689 
   1690  // If we have a CompositorBridgeChild, then we need to call
   1691  // CompositorBridgeParent::NotifyChildCreated. If this is in the GPU process,
   1692  // we can combine it with LayerTreeOwnerTracker::Map to minimize IPC.
   1693  // messages.
   1694  if (aCompositorBridge) {
   1695    if (mGPUChild) {
   1696      return aCompositorBridge->SendMapAndNotifyChildCreated(
   1697          layersId, aOtherPid, aOutCompositorOptions);
   1698    }
   1699    return aCompositorBridge->SendNotifyChildCreated(layersId,
   1700                                                     aOutCompositorOptions);
   1701  }
   1702 
   1703  // If we don't have a CompositorBridgeChild, we just need to call
   1704  // LayerTreeOwnerTracker::Map in the compositing process.
   1705  if (mGPUChild) {
   1706    mGPUChild->SendAddLayerTreeIdMapping(
   1707        LayerTreeIdMapping(layersId, aOtherPid));
   1708  }
   1709  return false;
   1710 }
   1711 
   1712 void GPUProcessManager::EnsureVsyncIOThread() {
   1713  if (mVsyncIOThread) {
   1714    return;
   1715  }
   1716 
   1717  mVsyncIOThread = new VsyncIOThreadHolder();
   1718  MOZ_RELEASE_ASSERT(mVsyncIOThread->Start());
   1719 }
   1720 
   1721 void GPUProcessManager::ShutdownVsyncIOThread() { mVsyncIOThread = nullptr; }
   1722 
   1723 void GPUProcessManager::RegisterRemoteProcessSession(
   1724    RemoteCompositorSession* aSession) {
   1725  mRemoteSessions.AppendElement(aSession);
   1726 }
   1727 
   1728 void GPUProcessManager::UnregisterRemoteProcessSession(
   1729    RemoteCompositorSession* aSession) {
   1730  mRemoteSessions.RemoveElement(aSession);
   1731 }
   1732 
   1733 void GPUProcessManager::RegisterInProcessSession(
   1734    InProcessCompositorSession* aSession) {
   1735  mInProcessSessions.AppendElement(aSession);
   1736 }
   1737 
   1738 void GPUProcessManager::UnregisterInProcessSession(
   1739    InProcessCompositorSession* aSession) {
   1740  mInProcessSessions.RemoveElement(aSession);
   1741 }
   1742 
   1743 void GPUProcessManager::AddListener(GPUProcessListener* aListener) {
   1744  if (!mListeners.Contains(aListener)) {
   1745    mListeners.AppendElement(aListener);
   1746  }
   1747 }
   1748 
   1749 void GPUProcessManager::RemoveListener(GPUProcessListener* aListener) {
   1750  mListeners.RemoveElement(aListener);
   1751 }
   1752 
   1753 bool GPUProcessManager::NotifyGpuObservers(const char* aTopic) {
   1754  if (mGPUChild) {
   1755    nsCString topic(aTopic);
   1756    mGPUChild->SendNotifyGpuObservers(topic);
   1757    return true;
   1758  }
   1759 
   1760  if (!gfxConfig::IsEnabled(Feature::GPU_PROCESS)) {
   1761    nsCOMPtr<nsIObserverService> obsSvc =
   1762        mozilla::services::GetObserverService();
   1763    MOZ_ASSERT(obsSvc);
   1764    if (obsSvc) {
   1765      obsSvc->NotifyObservers(nullptr, aTopic, nullptr);
   1766    }
   1767    return true;
   1768  }
   1769 
   1770  // If we still are using a GPU process, but do not have one ready at the
   1771  // moment, we can drop these notifications since there is nothing to do.
   1772  return false;
   1773 }
   1774 
   1775 class GPUMemoryReporter : public MemoryReportingProcess {
   1776 public:
   1777  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(GPUMemoryReporter, override)
   1778 
   1779  bool IsAlive() const override {
   1780    if (GPUProcessManager* gpm = GPUProcessManager::Get()) {
   1781      return !!gpm->GetGPUChild();
   1782    }
   1783    return false;
   1784  }
   1785 
   1786  bool SendRequestMemoryReport(
   1787      const uint32_t& aGeneration, const bool& aAnonymize,
   1788      const bool& aMinimizeMemoryUsage,
   1789      const Maybe<ipc::FileDescriptor>& aDMDFile) override {
   1790    GPUChild* child = GetChild();
   1791    if (!child) {
   1792      return false;
   1793    }
   1794 
   1795    return child->SendRequestMemoryReport(aGeneration, aAnonymize,
   1796                                          aMinimizeMemoryUsage, aDMDFile);
   1797  }
   1798 
   1799  int32_t Pid() const override {
   1800    if (GPUChild* child = GetChild()) {
   1801      return (int32_t)child->OtherPid();
   1802    }
   1803    return 0;
   1804  }
   1805 
   1806 private:
   1807  GPUChild* GetChild() const {
   1808    if (GPUProcessManager* gpm = GPUProcessManager::Get()) {
   1809      return gpm->GetGPUChild();
   1810    }
   1811    return nullptr;
   1812  }
   1813 
   1814 protected:
   1815  ~GPUMemoryReporter() = default;
   1816 };
   1817 
   1818 RefPtr<MemoryReportingProcess> GPUProcessManager::GetProcessMemoryReporter() {
   1819  // If we are in the middle of launching a GPU process, we can wait for it to
   1820  // finish, otherwise if there is no GPU process, we should just return now to
   1821  // avoid launching it again.
   1822  if (!mProcess || AppShutdown::IsInOrBeyond(ShutdownPhase::XPCOMShutdown) ||
   1823      !mProcess->WaitForLaunch()) {
   1824    return nullptr;
   1825  }
   1826  return MakeRefPtr<GPUMemoryReporter>();
   1827 }
   1828 
   1829 void GPUProcessManager::SetAppInForeground(bool aInForeground) {
   1830  if (mAppInForeground == aInForeground) {
   1831    return;
   1832  }
   1833 
   1834  mAppInForeground = aInForeground;
   1835 #if defined(XP_WIN)
   1836  SetProcessIsForeground();
   1837 #endif
   1838 
   1839  // If we moved into the foreground, then we need to make sure the GPU process
   1840  // completes its launch. Otherwise listeners may be left dangling from
   1841  // previous calls that returned NS_ERROR_ABORT due to being in the background.
   1842  if (aInForeground && gfxConfig::IsEnabled(Feature::GPU_PROCESS)) {
   1843    (void)LaunchGPUProcess();
   1844  }
   1845 }
   1846 
   1847 #if defined(XP_WIN)
   1848 void GPUProcessManager::SetProcessIsForeground() {
   1849  NTSTATUS WINAPI NtSetInformationProcess(
   1850      IN HANDLE process_handle, IN ULONG info_class,
   1851      IN PVOID process_information, IN ULONG information_length);
   1852  constexpr unsigned int NtProcessInformationForeground = 25;
   1853 
   1854  static bool alreadyInitialized = false;
   1855  static decltype(NtSetInformationProcess)* setInformationProcess = nullptr;
   1856  if (!alreadyInitialized) {
   1857    alreadyInitialized = true;
   1858    nsModuleHandle module(LoadLibrary(L"ntdll.dll"));
   1859    if (module) {
   1860      setInformationProcess =
   1861          (decltype(NtSetInformationProcess)*)GetProcAddress(
   1862              module, "NtSetInformationProcess");
   1863    }
   1864  }
   1865  if (MOZ_UNLIKELY(!setInformationProcess)) {
   1866    return;
   1867  }
   1868 
   1869  unsigned pid = GPUProcessPid();
   1870  if (pid <= 0) {
   1871    return;
   1872  }
   1873  // Using the handle from mProcess->GetChildProcessHandle() fails;
   1874  // the PROCESS_SET_INFORMATION permission is probably missing.
   1875  nsAutoHandle processHandle(
   1876      ::OpenProcess(PROCESS_SET_INFORMATION, FALSE, pid));
   1877  if (!processHandle) {
   1878    return;
   1879  }
   1880 
   1881  BOOLEAN foreground = mAppInForeground;
   1882  setInformationProcess(processHandle, NtProcessInformationForeground,
   1883                        (PVOID)&foreground, sizeof(foreground));
   1884 }
   1885 #endif
   1886 
   1887 RefPtr<PGPUChild::TestTriggerMetricsPromise>
   1888 GPUProcessManager::TestTriggerMetrics() {
   1889  if (!NS_WARN_IF(!mGPUChild)) {
   1890    return mGPUChild->SendTestTriggerMetrics();
   1891  }
   1892 
   1893  return PGPUChild::TestTriggerMetricsPromise::CreateAndReject(
   1894      ipc::ResponseRejectReason::SendError, __func__);
   1895 }
   1896 
   1897 }  // namespace gfx
   1898 }  // namespace mozilla