LCOV - code coverage report
Current view: top level - gfx/ipc - GPUProcessManager.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 137 462 29.7 %
Date: 2017-07-14 16:53:18 Functions: 22 66 33.3 %
Legend: Lines: hit not hit

          Line data    Source code
       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=99: */
       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 "gfxPrefs.h"
      10             : #include "GPUProcessHost.h"
      11             : #include "GPUProcessListener.h"
      12             : #include "mozilla/MemoryReportingProcess.h"
      13             : #include "mozilla/Sprintf.h"
      14             : #include "mozilla/StaticPtr.h"
      15             : #include "mozilla/dom/ContentParent.h"
      16             : #include "mozilla/layers/APZCTreeManager.h"
      17             : #include "mozilla/layers/APZCTreeManagerChild.h"
      18             : #include "mozilla/layers/CompositorBridgeParent.h"
      19             : #include "mozilla/layers/CompositorManagerChild.h"
      20             : #include "mozilla/layers/CompositorManagerParent.h"
      21             : #include "mozilla/layers/CompositorOptions.h"
      22             : #include "mozilla/layers/ImageBridgeChild.h"
      23             : #include "mozilla/layers/ImageBridgeParent.h"
      24             : #include "mozilla/layers/InProcessCompositorSession.h"
      25             : #include "mozilla/layers/LayerTreeOwnerTracker.h"
      26             : #include "mozilla/layers/RemoteCompositorSession.h"
      27             : #include "mozilla/widget/PlatformWidgetTypes.h"
      28             : #ifdef MOZ_WIDGET_SUPPORTS_OOP_COMPOSITING
      29             : # include "mozilla/widget/CompositorWidgetChild.h"
      30             : #endif
      31             : #include "nsBaseWidget.h"
      32             : #include "nsContentUtils.h"
      33             : #include "VRManagerChild.h"
      34             : #include "VRManagerParent.h"
      35             : #include "VsyncBridgeChild.h"
      36             : #include "VsyncIOThreadHolder.h"
      37             : #include "VsyncSource.h"
      38             : #include "mozilla/dom/VideoDecoderManagerChild.h"
      39             : #include "mozilla/dom/VideoDecoderManagerParent.h"
      40             : #include "MediaPrefs.h"
      41             : 
      42             : #ifdef MOZ_CRASHREPORTER
      43             : # include "nsExceptionHandler.h"
      44             : #endif
      45             : 
      46             : #if defined(MOZ_WIDGET_ANDROID)
      47             : #include "mozilla/widget/AndroidUiThread.h"
      48             : #include "mozilla/layers/UiCompositorControllerChild.h"
      49             : #endif // defined(MOZ_WIDGET_ANDROID)
      50             : 
      51             : namespace mozilla {
      52             : namespace gfx {
      53             : 
      54             : using namespace mozilla::layers;
      55             : 
      56             : enum class FallbackType : uint32_t
      57             : {
      58             :   NONE = 0,
      59             :   DECODINGDISABLED,
      60             :   DISABLED,
      61             : };
      62             : 
      63           3 : static StaticAutoPtr<GPUProcessManager> sSingleton;
      64             : 
      65             : GPUProcessManager*
      66           7 : GPUProcessManager::Get()
      67             : {
      68           7 :   return sSingleton;
      69             : }
      70             : 
      71             : void
      72           1 : GPUProcessManager::Initialize()
      73             : {
      74           1 :   MOZ_ASSERT(XRE_IsParentProcess());
      75           1 :   sSingleton = new GPUProcessManager();
      76           1 : }
      77             : 
      78             : void
      79           0 : GPUProcessManager::Shutdown()
      80             : {
      81           0 :   sSingleton = nullptr;
      82           0 : }
      83             : 
      84           1 : GPUProcessManager::GPUProcessManager()
      85             :  : mTaskFactory(this),
      86             :    mNextNamespace(0),
      87             :    mIdNamespace(0),
      88             :    mResourceId(0),
      89             :    mNumProcessAttempts(0),
      90             :    mDeviceResetCount(0),
      91             :    mProcess(nullptr),
      92           1 :    mGPUChild(nullptr)
      93             : {
      94           1 :   MOZ_COUNT_CTOR(GPUProcessManager);
      95             : 
      96           1 :   mIdNamespace = AllocateNamespace();
      97           1 :   mObserver = new Observer(this);
      98           1 :   nsContentUtils::RegisterShutdownObserver(mObserver);
      99             : 
     100           1 :   mDeviceResetLastTime = TimeStamp::Now();
     101             : 
     102           1 :   LayerTreeOwnerTracker::Initialize();
     103           1 : }
     104             : 
     105           0 : GPUProcessManager::~GPUProcessManager()
     106             : {
     107           0 :   MOZ_COUNT_DTOR(GPUProcessManager);
     108             : 
     109           0 :   LayerTreeOwnerTracker::Shutdown();
     110             : 
     111             :   // The GPU process should have already been shut down.
     112           0 :   MOZ_ASSERT(!mProcess && !mGPUChild);
     113             : 
     114             :   // We should have already removed observers.
     115           0 :   MOZ_ASSERT(!mObserver);
     116           0 : }
     117             : 
     118           2 : NS_IMPL_ISUPPORTS(GPUProcessManager::Observer, nsIObserver);
     119             : 
     120           1 : GPUProcessManager::Observer::Observer(GPUProcessManager* aManager)
     121           1 :  : mManager(aManager)
     122             : {
     123           1 : }
     124             : 
     125             : NS_IMETHODIMP
     126           0 : GPUProcessManager::Observer::Observe(nsISupports* aSubject, const char* aTopic, const char16_t* aData)
     127             : {
     128           0 :   if (!strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID)) {
     129           0 :     mManager->OnXPCOMShutdown();
     130             :   }
     131           0 :   return NS_OK;
     132             : }
     133             : 
     134             : void
     135           0 : GPUProcessManager::OnXPCOMShutdown()
     136             : {
     137           0 :   if (mObserver) {
     138           0 :     nsContentUtils::UnregisterShutdownObserver(mObserver);
     139           0 :     mObserver = nullptr;
     140             :   }
     141             : 
     142           0 :   CleanShutdown();
     143           0 : }
     144             : 
     145             : void
     146           0 : GPUProcessManager::LaunchGPUProcess()
     147             : {
     148           0 :   if (mProcess) {
     149           0 :     return;
     150             :   }
     151             : 
     152             :   // Start the Vsync I/O thread so can use it as soon as the process launches.
     153           0 :   EnsureVsyncIOThread();
     154             : 
     155           0 :   mNumProcessAttempts++;
     156             : 
     157             :   // The subprocess is launched asynchronously, so we wait for a callback to
     158             :   // acquire the IPDL actor.
     159           0 :   mProcess = new GPUProcessHost(this);
     160           0 :   if (!mProcess->Launch()) {
     161           0 :     DisableGPUProcess("Failed to launch GPU process");
     162             :   }
     163             : }
     164             : 
     165             : void
     166           0 : GPUProcessManager::DisableGPUProcess(const char* aMessage)
     167             : {
     168           0 :   if (!gfxConfig::IsEnabled(Feature::GPU_PROCESS)) {
     169           0 :     return;
     170             :   }
     171             : 
     172           0 :   gfxConfig::SetFailed(Feature::GPU_PROCESS, FeatureStatus::Failed, aMessage);
     173           0 :   gfxCriticalNote << aMessage;
     174             : 
     175           0 :   gfxPlatform::NotifyGPUProcessDisabled();
     176             : 
     177             :   Telemetry::Accumulate(Telemetry::GPU_PROCESS_CRASH_FALLBACKS,
     178           0 :                         uint32_t(FallbackType::DISABLED));
     179             : 
     180           0 :   DestroyProcess();
     181           0 :   ShutdownVsyncIOThread();
     182             : 
     183             :   // We may have been in the middle of guaranteeing our various services are
     184             :   // available when one failed. Some callers may fallback to using the same
     185             :   // process equivalent, and we need to make sure those services are setup
     186             :   // correctly. We cannot re-enter DisableGPUProcess from this call because we
     187             :   // know that it is disabled in the config above.
     188           0 :   EnsureProtocolsReady();
     189             : }
     190             : 
     191             : bool
     192          16 : GPUProcessManager::EnsureGPUReady()
     193             : {
     194          16 :   if (mProcess && !mProcess->IsConnected()) {
     195           0 :     if (!mProcess->WaitForLaunch()) {
     196             :       // If this fails, we should have fired OnProcessLaunchComplete and
     197             :       // removed the process.
     198           0 :       MOZ_ASSERT(!mProcess && !mGPUChild);
     199           0 :       return false;
     200             :     }
     201             :   }
     202             : 
     203          16 :   if (mGPUChild && mGPUChild->EnsureGPUReady()) {
     204           0 :     return true;
     205             :   }
     206             : 
     207          16 :   return false;
     208             : }
     209             : 
     210             : void
     211           1 : GPUProcessManager::EnsureProtocolsReady()
     212             : {
     213           1 :   EnsureCompositorManagerChild();
     214           1 :   EnsureImageBridgeChild();
     215           1 :   EnsureVRManager();
     216           1 : }
     217             : 
     218             : void
     219           1 : GPUProcessManager::EnsureCompositorManagerChild()
     220             : {
     221           1 :   base::ProcessId gpuPid = EnsureGPUReady()
     222           1 :                            ? mGPUChild->OtherPid()
     223           1 :                            : base::GetCurrentProcId();
     224             : 
     225           1 :   if (CompositorManagerChild::IsInitialized(gpuPid)) {
     226           1 :     return;
     227             :   }
     228             : 
     229           1 :   if (!EnsureGPUReady()) {
     230           1 :     CompositorManagerChild::InitSameProcess(AllocateNamespace());
     231           1 :     return;
     232             :   }
     233             : 
     234           0 :   ipc::Endpoint<PCompositorManagerParent> parentPipe;
     235           0 :   ipc::Endpoint<PCompositorManagerChild> childPipe;
     236           0 :   nsresult rv = PCompositorManager::CreateEndpoints(
     237           0 :     mGPUChild->OtherPid(),
     238             :     base::GetCurrentProcId(),
     239             :     &parentPipe,
     240           0 :     &childPipe);
     241           0 :   if (NS_FAILED(rv)) {
     242           0 :     DisableGPUProcess("Failed to create PCompositorManager endpoints");
     243           0 :     return;
     244             :   }
     245             : 
     246           0 :   mGPUChild->SendInitCompositorManager(Move(parentPipe));
     247           0 :   CompositorManagerChild::Init(Move(childPipe), AllocateNamespace());
     248             : }
     249             : 
     250             : void
     251           3 : GPUProcessManager::EnsureImageBridgeChild()
     252             : {
     253           3 :   if (ImageBridgeChild::GetSingleton()) {
     254           5 :     return;
     255             :   }
     256             : 
     257           1 :   if (!EnsureGPUReady()) {
     258           1 :     ImageBridgeChild::InitSameProcess(AllocateNamespace());
     259           1 :     return;
     260             :   }
     261             : 
     262           0 :   ipc::Endpoint<PImageBridgeParent> parentPipe;
     263           0 :   ipc::Endpoint<PImageBridgeChild> childPipe;
     264           0 :   nsresult rv = PImageBridge::CreateEndpoints(
     265           0 :     mGPUChild->OtherPid(),
     266             :     base::GetCurrentProcId(),
     267             :     &parentPipe,
     268           0 :     &childPipe);
     269           0 :   if (NS_FAILED(rv)) {
     270           0 :     DisableGPUProcess("Failed to create PImageBridge endpoints");
     271           0 :     return;
     272             :   }
     273             : 
     274           0 :   mGPUChild->SendInitImageBridge(Move(parentPipe));
     275           0 :   ImageBridgeChild::InitWithGPUProcess(Move(childPipe), AllocateNamespace());
     276             : }
     277             : 
     278             : void
     279           3 : GPUProcessManager::EnsureVRManager()
     280             : {
     281           3 :   if (VRManagerChild::IsCreated()) {
     282           5 :     return;
     283             :   }
     284             : 
     285           1 :   if (!EnsureGPUReady()) {
     286           1 :     VRManagerChild::InitSameProcess();
     287           1 :     return;
     288             :   }
     289             : 
     290           0 :   ipc::Endpoint<PVRManagerParent> parentPipe;
     291           0 :   ipc::Endpoint<PVRManagerChild> childPipe;
     292           0 :   nsresult rv = PVRManager::CreateEndpoints(
     293           0 :     mGPUChild->OtherPid(),
     294             :     base::GetCurrentProcId(),
     295             :     &parentPipe,
     296           0 :     &childPipe);
     297           0 :   if (NS_FAILED(rv)) {
     298           0 :     DisableGPUProcess("Failed to create PVRManager endpoints");
     299           0 :     return;
     300             :   }
     301             : 
     302           0 :   mGPUChild->SendInitVRManager(Move(parentPipe));
     303           0 :   VRManagerChild::InitWithGPUProcess(Move(childPipe));
     304             : }
     305             : 
     306             : #if defined(MOZ_WIDGET_ANDROID)
     307             : already_AddRefed<UiCompositorControllerChild>
     308             : GPUProcessManager::CreateUiCompositorController(nsBaseWidget* aWidget, const uint64_t aId)
     309             : {
     310             :   RefPtr<UiCompositorControllerChild> result;
     311             : 
     312             :   if (!EnsureGPUReady()) {
     313             :     result = UiCompositorControllerChild::CreateForSameProcess(aId);
     314             :   } else {
     315             :     ipc::Endpoint<PUiCompositorControllerParent> parentPipe;
     316             :     ipc::Endpoint<PUiCompositorControllerChild> childPipe;
     317             :     nsresult rv = PUiCompositorController::CreateEndpoints(
     318             :       mGPUChild->OtherPid(),
     319             :       base::GetCurrentProcId(),
     320             :       &parentPipe,
     321             :       &childPipe);
     322             :     if (NS_FAILED(rv)) {
     323             :       DisableGPUProcess("Failed to create PUiCompositorController endpoints");
     324             :       return nullptr;
     325             :     }
     326             : 
     327             :     mGPUChild->SendInitUiCompositorController(aId, Move(parentPipe));
     328             :     result = UiCompositorControllerChild::CreateForGPUProcess(mProcessToken, Move(childPipe));
     329             :   }
     330             :   if (result) {
     331             :     result->SetBaseWidget(aWidget);
     332             :   }
     333             :   return result.forget();
     334             : }
     335             : #endif // defined(MOZ_WIDGET_ANDROID)
     336             : 
     337             : void
     338           0 : GPUProcessManager::OnProcessLaunchComplete(GPUProcessHost* aHost)
     339             : {
     340           0 :   MOZ_ASSERT(mProcess && mProcess == aHost);
     341             : 
     342           0 :   if (!mProcess->IsConnected()) {
     343           0 :     DisableGPUProcess("Failed to connect GPU process");
     344           0 :     return;
     345             :   }
     346             : 
     347           0 :   mGPUChild = mProcess->GetActor();
     348           0 :   mProcessToken = mProcess->GetProcessToken();
     349             : 
     350           0 :   Endpoint<PVsyncBridgeParent> vsyncParent;
     351           0 :   Endpoint<PVsyncBridgeChild> vsyncChild;
     352           0 :   nsresult rv = PVsyncBridge::CreateEndpoints(
     353           0 :     mGPUChild->OtherPid(),
     354             :     base::GetCurrentProcId(),
     355             :     &vsyncParent,
     356           0 :     &vsyncChild);
     357           0 :   if (NS_FAILED(rv)) {
     358           0 :     DisableGPUProcess("Failed to create PVsyncBridge endpoints");
     359           0 :     return;
     360             :   }
     361             : 
     362           0 :   mVsyncBridge = VsyncBridgeChild::Create(mVsyncIOThread, mProcessToken, Move(vsyncChild));
     363           0 :   mGPUChild->SendInitVsyncBridge(Move(vsyncParent));
     364             : 
     365             : #ifdef MOZ_CRASHREPORTER
     366           0 :   CrashReporter::AnnotateCrashReport(
     367           0 :     NS_LITERAL_CSTRING("GPUProcessStatus"),
     368           0 :     NS_LITERAL_CSTRING("Running"));
     369             : #endif
     370             : }
     371             : 
     372             : static bool
     373           0 : ShouldLimitDeviceResets(uint32_t count, int32_t deltaMilliseconds)
     374             : {
     375             :   // We decide to limit by comparing the amount of resets that have happened
     376             :   // and time since the last reset to two prefs.
     377           0 :   int32_t timeLimit = gfxPrefs::DeviceResetThresholdMilliseconds();
     378           0 :   int32_t countLimit = gfxPrefs::DeviceResetLimitCount();
     379             : 
     380           0 :   bool hasTimeLimit = timeLimit >= 0;
     381           0 :   bool hasCountLimit = countLimit >= 0;
     382             : 
     383           0 :   bool triggeredTime = deltaMilliseconds < timeLimit;
     384           0 :   bool triggeredCount = count > (uint32_t)countLimit;
     385             : 
     386             :   // If we have both prefs set then it needs to trigger both limits,
     387             :   // otherwise we only test the pref that is set or none
     388           0 :   if (hasTimeLimit && hasCountLimit) {
     389           0 :     return triggeredTime && triggeredCount;
     390           0 :   } else if (hasTimeLimit) {
     391           0 :     return triggeredTime;
     392           0 :   } else if (hasCountLimit) {
     393           0 :     return triggeredCount;
     394             :   }
     395             : 
     396           0 :   return false;
     397             : }
     398             : 
     399             : void
     400           0 : GPUProcessManager::SimulateDeviceReset()
     401             : {
     402             :   // Make sure we rebuild environment and configuration for accelerated features.
     403           0 :   gfxPlatform::GetPlatform()->CompositorUpdated();
     404             : 
     405           0 :   if (mProcess) {
     406           0 :     OnRemoteProcessDeviceReset(mProcess);
     407             :   } else {
     408           0 :     OnInProcessDeviceReset();
     409             :   }
     410           0 : }
     411             : 
     412             : void
     413           0 : GPUProcessManager::OnInProcessDeviceReset()
     414             : {
     415           0 :   RebuildInProcessSessions();
     416           0 :   NotifyListenersOnCompositeDeviceReset();
     417           0 : }
     418             : 
     419             : void
     420           0 : GPUProcessManager::OnRemoteProcessDeviceReset(GPUProcessHost* aHost)
     421             : {
     422             :   // Detect whether the device is resetting too quickly or too much
     423             :   // indicating that we should give up and use software
     424           0 :   mDeviceResetCount++;
     425             : 
     426           0 :   auto newTime = TimeStamp::Now();
     427           0 :   auto delta = (int32_t)(newTime - mDeviceResetLastTime).ToMilliseconds();
     428           0 :   mDeviceResetLastTime = newTime;
     429             : 
     430           0 :   if (ShouldLimitDeviceResets(mDeviceResetCount, delta)) {
     431           0 :     DestroyProcess();
     432           0 :     DisableGPUProcess("GPU processed experienced too many device resets");
     433             : 
     434             :     // Reaches the limited TDR attempts, fallback to software solution.
     435           0 :     gfxConfig::SetFailed(Feature::HW_COMPOSITING,
     436             :       FeatureStatus::Blocked,
     437           0 :       "Too many attemps of D3D11 creation, fallback to software solution.");
     438           0 :     gfxConfig::SetFailed(Feature::D3D11_COMPOSITING,
     439             :       FeatureStatus::Blocked,
     440           0 :       "Too many attemps of D3D11 creation, fallback to software solution.");
     441           0 :     gfxConfig::SetFailed(Feature::DIRECT2D,
     442             :       FeatureStatus::Blocked,
     443           0 :       "Too many attemps of D3D11 creation, fallback to software solution.");
     444             : 
     445           0 :     HandleProcessLost();
     446           0 :     return;
     447             :   }
     448             : 
     449           0 :   RebuildRemoteSessions();
     450           0 :   NotifyListenersOnCompositeDeviceReset();
     451             : }
     452             : 
     453             : void
     454           0 : GPUProcessManager::NotifyListenersOnCompositeDeviceReset()
     455             : {
     456           0 :   for (const auto& listener : mListeners) {
     457           0 :     listener->OnCompositorDeviceReset();
     458             :   }
     459           0 : }
     460             : 
     461             : void
     462           0 : GPUProcessManager::OnProcessUnexpectedShutdown(GPUProcessHost* aHost)
     463             : {
     464           0 :   MOZ_ASSERT(mProcess && mProcess == aHost);
     465             : 
     466           0 :   DestroyProcess();
     467             : 
     468           0 :   if (mNumProcessAttempts > uint32_t(gfxPrefs::GPUProcessMaxRestarts())) {
     469             :     char disableMessage[64];
     470           0 :     SprintfLiteral(disableMessage, "GPU process disabled after %d attempts",
     471           0 :                    mNumProcessAttempts);
     472           0 :     DisableGPUProcess(disableMessage);
     473           0 :   } else if (mNumProcessAttempts > uint32_t(gfxPrefs::GPUProcessMaxRestartsWithDecoder()) &&
     474           0 :              mDecodeVideoOnGpuProcess) {
     475           0 :     mDecodeVideoOnGpuProcess = false;
     476             :     Telemetry::Accumulate(Telemetry::GPU_PROCESS_CRASH_FALLBACKS,
     477           0 :                                      uint32_t(FallbackType::DECODINGDISABLED));
     478             :   } else {
     479             :     Telemetry::Accumulate(Telemetry::GPU_PROCESS_CRASH_FALLBACKS,
     480           0 :                                      uint32_t(FallbackType::NONE));
     481             :   }
     482             : 
     483           0 :   HandleProcessLost();
     484           0 : }
     485             : 
     486             : void
     487           0 : GPUProcessManager::HandleProcessLost()
     488             : {
     489           0 :   if (gfxConfig::IsEnabled(Feature::GPU_PROCESS)) {
     490           0 :     LaunchGPUProcess();
     491             :   }
     492             : 
     493             :   // The shutdown and restart sequence for the GPU process is as follows:
     494             :   //
     495             :   //  (1) The GPU process dies. IPDL will enqueue an ActorDestroy message on
     496             :   //      each channel owning a bridge to the GPU process, on the thread
     497             :   //      owning that channel.
     498             :   //
     499             :   //  (2) The first channel to process its ActorDestroy message will post a
     500             :   //      message to the main thread to call NotifyRemoteActorDestroyed on
     501             :   //      the GPUProcessManager, which calls OnProcessUnexpectedShutdown if
     502             :   //      it has not handled shutdown for this process yet.
     503             :   //
     504             :   //  (3) We then notify each widget that its session with the compositor is
     505             :   //      now invalid. The widget is responsible for destroying its layer
     506             :   //      manager and CompositorBridgeChild. Note that at this stage, not
     507             :   //      all actors may have received ActorDestroy yet. CompositorBridgeChild
     508             :   //      may attempt to send messages, and if this happens, it will probably
     509             :   //      report a MsgDropped error. This is okay.
     510             :   //
     511             :   //  (4) At this point, the UI process has a clean slate: no layers should
     512             :   //      exist for the old compositor. We may make a decision on whether or
     513             :   //      not to re-launch the GPU process. Currently, we do not relaunch it,
     514             :   //      and any new compositors will be created in-process and will default
     515             :   //      to software.
     516             :   //
     517             :   //  (5) Next we notify each ContentParent of the lost connection. It will
     518             :   //      request new endpoints from the GPUProcessManager and forward them
     519             :   //      to its ContentChild. The parent-side of these endpoints may come
     520             :   //      from the compositor thread of the UI process, or the compositor
     521             :   //      thread of the GPU process. However, no actual compositors should
     522             :   //      exist yet.
     523             :   //
     524             :   //  (6) Each ContentChild will receive new endpoints. It will destroy its
     525             :   //      Compositor/ImageBridgeChild singletons and recreate them, as well
     526             :   //      as invalidate all retained layers.
     527             :   //
     528             :   //  (7) In addition, each ContentChild will ask each of its TabChildren
     529             :   //      to re-request association with the compositor for the window
     530             :   //      owning the tab. The sequence of calls looks like:
     531             :   //        (a) [CONTENT] ContentChild::RecvReinitRendering
     532             :   //        (b) [CONTENT] TabChild::ReinitRendering
     533             :   //        (c) [CONTENT] TabChild::SendEnsureLayersConnected
     534             :   //        (d)      [UI] TabParent::RecvEnsureLayersConnected
     535             :   //        (e)      [UI] RenderFrameParent::EnsureLayersConnected
     536             :   //        (f)      [UI] CompositorBridgeChild::SendNotifyChildRecreated
     537             :   //
     538             :   //      Note that at step (e), RenderFrameParent will call GetLayerManager
     539             :   //      on the nsIWidget owning the tab. This step ensures that a compositor
     540             :   //      exists for the window. If we decided to launch a new GPU Process,
     541             :   //      at this point we block until the process has launched and we're
     542             :   //      able to create a new window compositor. Otherwise, if compositing
     543             :   //      is now in-process, this will simply create a new
     544             :   //      CompositorBridgeParent in the UI process. If there are multiple tabs
     545             :   //      in the same window, additional tabs will simply return the already-
     546             :   //      established compositor.
     547             :   //
     548             :   //      Finally, this step serves one other crucial function: tabs must be
     549             :   //      associated with a window compositor or else they can't forward
     550             :   //      layer transactions. So this step both ensures that a compositor
     551             :   //      exists, and that the tab can forward layers.
     552             :   //
     553             :   //  (8) Last, if the window had no remote tabs, step (7) will not have
     554             :   //      applied, and the window will not have a new compositor just yet.
     555             :   //      The next refresh tick and paint will ensure that one exists, again
     556             :   //      via nsIWidget::GetLayerManager.
     557           0 :   RebuildRemoteSessions();
     558             : 
     559             :   // Notify content. This will ensure that each content process re-establishes
     560             :   // a connection to the compositor thread (whether it's in-process or in a
     561             :   // newly launched GPU process).
     562           0 :   for (const auto& listener : mListeners) {
     563           0 :     listener->OnCompositorUnexpectedShutdown();
     564             :   }
     565           0 : }
     566             : 
     567             : void
     568           0 : GPUProcessManager::RebuildRemoteSessions()
     569             : {
     570             :   // Build a list of sessions to notify, since notification might delete
     571             :   // entries from the list.
     572           0 :   nsTArray<RefPtr<RemoteCompositorSession>> sessions;
     573           0 :   for (auto& session : mRemoteSessions) {
     574           0 :     sessions.AppendElement(session);
     575             :   }
     576             : 
     577             :   // Notify each widget that we have lost the GPU process. This will ensure
     578             :   // that each widget destroys its layer manager and CompositorBridgeChild.
     579           0 :   for (const auto& session : sessions) {
     580           0 :     session->NotifySessionLost();
     581             :   }
     582           0 : }
     583             : 
     584             : void
     585           0 : GPUProcessManager::RebuildInProcessSessions()
     586             : {
     587             :   // Build a list of sessions to notify, since notification might delete
     588             :   // entries from the list.
     589           0 :   nsTArray<RefPtr<InProcessCompositorSession>> sessions;
     590           0 :   for (auto& session : mInProcessSessions) {
     591           0 :     sessions.AppendElement(session);
     592             :   }
     593             : 
     594             :   // Notify each widget that we have lost the GPU process. This will ensure
     595             :   // that each widget destroys its layer manager and CompositorBridgeChild.
     596           0 :   for (const auto& session : sessions) {
     597           0 :     session->NotifySessionLost();
     598             :   }
     599           0 : }
     600             : 
     601             : void
     602           0 : GPUProcessManager::NotifyRemoteActorDestroyed(const uint64_t& aProcessToken)
     603             : {
     604           0 :   if (!NS_IsMainThread()) {
     605           0 :     RefPtr<Runnable> task = mTaskFactory.NewRunnableMethod(
     606           0 :       &GPUProcessManager::NotifyRemoteActorDestroyed, aProcessToken);
     607           0 :     NS_DispatchToMainThread(task.forget());
     608           0 :     return;
     609             :   }
     610             : 
     611           0 :   if (mProcessToken != aProcessToken) {
     612             :     // This token is for an older process; we can safely ignore it.
     613           0 :     return;
     614             :   }
     615             : 
     616             :   // One of the bridged top-level actors for the GPU process has been
     617             :   // prematurely terminated, and we're receiving a notification. This
     618             :   // can happen if the ActorDestroy for a bridged protocol fires
     619             :   // before the ActorDestroy for PGPUChild.
     620           0 :   OnProcessUnexpectedShutdown(mProcess);
     621             : }
     622             : 
     623             : void
     624           0 : GPUProcessManager::CleanShutdown()
     625             : {
     626           0 :   DestroyProcess();
     627           0 :   mVsyncIOThread = nullptr;
     628           0 : }
     629             : 
     630             : void
     631           0 : GPUProcessManager::KillProcess()
     632             : {
     633           0 :   if (!mProcess) {
     634           0 :     return;
     635             :   }
     636             : 
     637           0 :   mProcess->KillProcess();
     638             : }
     639             : 
     640             : void
     641           0 : GPUProcessManager::DestroyProcess()
     642             : {
     643           0 :   if (!mProcess) {
     644           0 :     return;
     645             :   }
     646             : 
     647           0 :   mProcess->Shutdown();
     648           0 :   mProcessToken = 0;
     649           0 :   mProcess = nullptr;
     650           0 :   mGPUChild = nullptr;
     651           0 :   if (mVsyncBridge) {
     652           0 :     mVsyncBridge->Close();
     653           0 :     mVsyncBridge = nullptr;
     654             :   }
     655             : 
     656             : #ifdef MOZ_CRASHREPORTER
     657           0 :   CrashReporter::AnnotateCrashReport(
     658           0 :     NS_LITERAL_CSTRING("GPUProcessStatus"),
     659           0 :     NS_LITERAL_CSTRING("Destroyed"));
     660             : #endif
     661             : }
     662             : 
     663             : RefPtr<CompositorSession>
     664           1 : GPUProcessManager::CreateTopLevelCompositor(nsBaseWidget* aWidget,
     665             :                                             LayerManager* aLayerManager,
     666             :                                             CSSToLayoutDeviceScale aScale,
     667             :                                             const CompositorOptions& aOptions,
     668             :                                             bool aUseExternalSurfaceSize,
     669             :                                             const gfx::IntSize& aSurfaceSize)
     670             : {
     671           1 :   uint64_t layerTreeId = AllocateLayerTreeId();
     672             : 
     673           1 :   EnsureProtocolsReady();
     674             : 
     675           1 :   RefPtr<CompositorSession> session;
     676             : 
     677           1 :   if (EnsureGPUReady()) {
     678           0 :     session = CreateRemoteSession(
     679             :       aWidget,
     680             :       aLayerManager,
     681             :       layerTreeId,
     682             :       aScale,
     683             :       aOptions,
     684             :       aUseExternalSurfaceSize,
     685           0 :       aSurfaceSize);
     686           0 :     if (!session) {
     687             :       // We couldn't create a remote compositor, so abort the process.
     688           0 :       DisableGPUProcess("Failed to create remote compositor");
     689             :     }
     690             :   }
     691             : 
     692           1 :   if (!session) {
     693           3 :     session = InProcessCompositorSession::Create(
     694             :       aWidget,
     695             :       aLayerManager,
     696             :       layerTreeId,
     697             :       aScale,
     698             :       aOptions,
     699             :       aUseExternalSurfaceSize,
     700             :       aSurfaceSize,
     701           2 :       AllocateNamespace());
     702             :   }
     703             : 
     704             : #if defined(MOZ_WIDGET_ANDROID)
     705             :   if (session) {
     706             :     // Nothing to do if controller gets a nullptr
     707             :     RefPtr<UiCompositorControllerChild> controller = CreateUiCompositorController(aWidget, session->RootLayerTreeId());
     708             :     session->SetUiCompositorControllerChild(controller);
     709             :   }
     710             : #endif // defined(MOZ_WIDGET_ANDROID)
     711             : 
     712           1 :   return session;
     713             : }
     714             : 
     715             : RefPtr<CompositorSession>
     716           0 : GPUProcessManager::CreateRemoteSession(nsBaseWidget* aWidget,
     717             :                                        LayerManager* aLayerManager,
     718             :                                        const uint64_t& aRootLayerTreeId,
     719             :                                        CSSToLayoutDeviceScale aScale,
     720             :                                        const CompositorOptions& aOptions,
     721             :                                        bool aUseExternalSurfaceSize,
     722             :                                        const gfx::IntSize& aSurfaceSize)
     723             : {
     724             : #ifdef MOZ_WIDGET_SUPPORTS_OOP_COMPOSITING
     725           0 :   CompositorWidgetInitData initData;
     726           0 :   aWidget->GetCompositorWidgetInitData(&initData);
     727             : 
     728             :   RefPtr<CompositorBridgeChild> child =
     729           0 :     CompositorManagerChild::CreateWidgetCompositorBridge(
     730             :       mProcessToken,
     731             :       aLayerManager,
     732             :       AllocateNamespace(),
     733             :       aScale,
     734             :       aOptions,
     735             :       aUseExternalSurfaceSize,
     736           0 :       aSurfaceSize);
     737           0 :   if (!child) {
     738           0 :     gfxCriticalNote << "Failed to create CompositorBridgeChild";
     739           0 :     return nullptr;
     740             :   }
     741             : 
     742           0 :   RefPtr<CompositorVsyncDispatcher> dispatcher = aWidget->GetCompositorVsyncDispatcher();
     743             :   RefPtr<CompositorWidgetVsyncObserver> observer =
     744           0 :     new CompositorWidgetVsyncObserver(mVsyncBridge, aRootLayerTreeId);
     745             : 
     746           0 :   CompositorWidgetChild* widget = new CompositorWidgetChild(dispatcher, observer);
     747           0 :   if (!child->SendPCompositorWidgetConstructor(widget, initData)) {
     748           0 :     return nullptr;
     749             :   }
     750           0 :   if (!child->SendInitialize(aRootLayerTreeId)) {
     751           0 :     return nullptr;
     752             :   }
     753             : 
     754           0 :   RefPtr<APZCTreeManagerChild> apz = nullptr;
     755           0 :   if (aOptions.UseAPZ()) {
     756           0 :     PAPZCTreeManagerChild* papz = child->SendPAPZCTreeManagerConstructor(0);
     757           0 :     if (!papz) {
     758           0 :       return nullptr;
     759             :     }
     760           0 :     apz = static_cast<APZCTreeManagerChild*>(papz);
     761             :   }
     762             : 
     763             :   RefPtr<RemoteCompositorSession> session =
     764           0 :     new RemoteCompositorSession(aWidget, child, widget, apz, aRootLayerTreeId);
     765           0 :   return session.forget();
     766             : #else
     767             :   gfxCriticalNote << "Platform does not support out-of-process compositing";
     768             :   return nullptr;
     769             : #endif
     770             : }
     771             : 
     772             : bool
     773           2 : GPUProcessManager::CreateContentBridges(base::ProcessId aOtherProcess,
     774             :                                         ipc::Endpoint<PCompositorManagerChild>* aOutCompositor,
     775             :                                         ipc::Endpoint<PImageBridgeChild>* aOutImageBridge,
     776             :                                         ipc::Endpoint<PVRManagerChild>* aOutVRBridge,
     777             :                                         ipc::Endpoint<dom::PVideoDecoderManagerChild>* aOutVideoManager,
     778             :                                         nsTArray<uint32_t>* aNamespaces)
     779             : {
     780           6 :   if (!CreateContentCompositorManager(aOtherProcess, aOutCompositor) ||
     781           4 :       !CreateContentImageBridge(aOtherProcess, aOutImageBridge) ||
     782           2 :       !CreateContentVRManager(aOtherProcess, aOutVRBridge))
     783             :   {
     784           0 :     return false;
     785             :   }
     786             :   // VideoDeocderManager is only supported in the GPU process, so we allow this to be
     787             :   // fallible.
     788           2 :   CreateContentVideoDecoderManager(aOtherProcess, aOutVideoManager);
     789             :   // Allocates 3 namespaces(for CompositorManagerChild, CompositorBridgeChild and ImageBridgeChild)
     790           2 :   aNamespaces->AppendElement(AllocateNamespace());
     791           2 :   aNamespaces->AppendElement(AllocateNamespace());
     792           2 :   aNamespaces->AppendElement(AllocateNamespace());
     793           2 :   return true;
     794             : }
     795             : 
     796             : bool
     797           2 : GPUProcessManager::CreateContentCompositorManager(base::ProcessId aOtherProcess,
     798             :                                                   ipc::Endpoint<PCompositorManagerChild>* aOutEndpoint)
     799             : {
     800           4 :   ipc::Endpoint<PCompositorManagerParent> parentPipe;
     801           4 :   ipc::Endpoint<PCompositorManagerChild> childPipe;
     802             : 
     803           2 :   base::ProcessId parentPid = EnsureGPUReady()
     804           2 :                               ? mGPUChild->OtherPid()
     805           2 :                               : base::GetCurrentProcId();
     806             : 
     807             :   nsresult rv = PCompositorManager::CreateEndpoints(
     808             :     parentPid,
     809             :     aOtherProcess,
     810             :     &parentPipe,
     811           2 :     &childPipe);
     812           2 :   if (NS_FAILED(rv)) {
     813           0 :     gfxCriticalNote << "Could not create content compositor manager: " << hexa(int(rv));
     814           0 :     return false;
     815             :   }
     816             : 
     817           2 :   if (mGPUChild) {
     818           0 :     mGPUChild->SendNewContentCompositorManager(Move(parentPipe));
     819             :   } else {
     820           2 :     CompositorManagerParent::Create(Move(parentPipe));
     821             :   }
     822             : 
     823           2 :   *aOutEndpoint = Move(childPipe);
     824           2 :   return true;
     825             : }
     826             : 
     827             : bool
     828           2 : GPUProcessManager::CreateContentImageBridge(base::ProcessId aOtherProcess,
     829             :                                             ipc::Endpoint<PImageBridgeChild>* aOutEndpoint)
     830             : {
     831           2 :   EnsureImageBridgeChild();
     832             : 
     833           2 :   base::ProcessId parentPid = EnsureGPUReady()
     834           2 :                               ? mGPUChild->OtherPid()
     835           2 :                               : base::GetCurrentProcId();
     836             : 
     837           4 :   ipc::Endpoint<PImageBridgeParent> parentPipe;
     838           4 :   ipc::Endpoint<PImageBridgeChild> childPipe;
     839             :   nsresult rv = PImageBridge::CreateEndpoints(
     840             :     parentPid,
     841             :     aOtherProcess,
     842             :     &parentPipe,
     843           2 :     &childPipe);
     844           2 :   if (NS_FAILED(rv)) {
     845           0 :     gfxCriticalNote << "Could not create content compositor bridge: " << hexa(int(rv));
     846           0 :     return false;
     847             :   }
     848             : 
     849           2 :   if (mGPUChild) {
     850           0 :     mGPUChild->SendNewContentImageBridge(Move(parentPipe));
     851             :   } else {
     852           2 :     if (!ImageBridgeParent::CreateForContent(Move(parentPipe))) {
     853           0 :       return false;
     854             :     }
     855             :   }
     856             : 
     857           2 :   *aOutEndpoint = Move(childPipe);
     858           2 :   return true;
     859             : }
     860             : 
     861             : base::ProcessId
     862           0 : GPUProcessManager::GPUProcessPid()
     863             : {
     864           0 :   base::ProcessId gpuPid = mGPUChild
     865           0 :                            ? mGPUChild->OtherPid()
     866           0 :                            : -1;
     867           0 :   return gpuPid;
     868             : }
     869             : 
     870             : bool
     871           2 : GPUProcessManager::CreateContentVRManager(base::ProcessId aOtherProcess,
     872             :                                           ipc::Endpoint<PVRManagerChild>* aOutEndpoint)
     873             : {
     874           2 :   EnsureVRManager();
     875             : 
     876           2 :   base::ProcessId parentPid = EnsureGPUReady()
     877           2 :                               ? mGPUChild->OtherPid()
     878           2 :                               : base::GetCurrentProcId();
     879             : 
     880           4 :   ipc::Endpoint<PVRManagerParent> parentPipe;
     881           4 :   ipc::Endpoint<PVRManagerChild> childPipe;
     882             :   nsresult rv = PVRManager::CreateEndpoints(
     883             :     parentPid,
     884             :     aOtherProcess,
     885             :     &parentPipe,
     886           2 :     &childPipe);
     887           2 :   if (NS_FAILED(rv)) {
     888           0 :     gfxCriticalNote << "Could not create content compositor bridge: " << hexa(int(rv));
     889           0 :     return false;
     890             :   }
     891             : 
     892           2 :   if (mGPUChild) {
     893           0 :     mGPUChild->SendNewContentVRManager(Move(parentPipe));
     894             :   } else {
     895           2 :     if (!VRManagerParent::CreateForContent(Move(parentPipe))) {
     896           0 :       return false;
     897             :     }
     898             :   }
     899             : 
     900           2 :   *aOutEndpoint = Move(childPipe);
     901           2 :   return true;
     902             : }
     903             : 
     904             : void
     905           2 : GPUProcessManager::CreateContentVideoDecoderManager(base::ProcessId aOtherProcess,
     906             :                                                     ipc::Endpoint<dom::PVideoDecoderManagerChild>* aOutEndpoint)
     907             : {
     908           4 :   if (!EnsureGPUReady() ||
     909           2 :       !MediaPrefs::PDMUseGPUDecoder() ||
     910           0 :       !mDecodeVideoOnGpuProcess) {
     911           2 :     return;
     912             :   }
     913             : 
     914           0 :   ipc::Endpoint<dom::PVideoDecoderManagerParent> parentPipe;
     915           0 :   ipc::Endpoint<dom::PVideoDecoderManagerChild> childPipe;
     916             : 
     917           0 :   nsresult rv = dom::PVideoDecoderManager::CreateEndpoints(
     918           0 :     mGPUChild->OtherPid(),
     919             :     aOtherProcess,
     920             :     &parentPipe,
     921           0 :     &childPipe);
     922           0 :   if (NS_FAILED(rv)) {
     923           0 :     gfxCriticalNote << "Could not create content video decoder: " << hexa(int(rv));
     924           0 :     return;
     925             :   }
     926             : 
     927           0 :   mGPUChild->SendNewContentVideoDecoderManager(Move(parentPipe));
     928             : 
     929           0 :   *aOutEndpoint = Move(childPipe);
     930           0 :   return;
     931             : }
     932             : 
     933             : already_AddRefed<IAPZCTreeManager>
     934           0 : GPUProcessManager::GetAPZCTreeManagerForLayers(uint64_t aLayersId)
     935             : {
     936           0 :   return CompositorBridgeParent::GetAPZCTreeManager(aLayersId);
     937             : }
     938             : 
     939             : void
     940           1 : GPUProcessManager::MapLayerTreeId(uint64_t aLayersId, base::ProcessId aOwningId)
     941             : {
     942           1 :   LayerTreeOwnerTracker::Get()->Map(aLayersId, aOwningId);
     943             : 
     944           1 :   if (EnsureGPUReady()) {
     945           0 :     mGPUChild->SendAddLayerTreeIdMapping(LayerTreeIdMapping(aLayersId, aOwningId));
     946             :   }
     947           1 : }
     948             : 
     949             : void
     950           0 : GPUProcessManager::UnmapLayerTreeId(uint64_t aLayersId, base::ProcessId aOwningId)
     951             : {
     952           0 :   LayerTreeOwnerTracker::Get()->Unmap(aLayersId, aOwningId);
     953             : 
     954           0 :   if (EnsureGPUReady()) {
     955           0 :     mGPUChild->SendRemoveLayerTreeIdMapping(LayerTreeIdMapping(aLayersId, aOwningId));
     956           0 :     return;
     957             :   }
     958           0 :   CompositorBridgeParent::DeallocateLayerTreeId(aLayersId);
     959             : }
     960             : 
     961             : bool
     962           0 : GPUProcessManager::IsLayerTreeIdMapped(uint64_t aLayersId, base::ProcessId aRequestingId)
     963             : {
     964           0 :   return LayerTreeOwnerTracker::Get()->IsMapped(aLayersId, aRequestingId);
     965             : }
     966             : 
     967             : uint64_t
     968           2 : GPUProcessManager::AllocateLayerTreeId()
     969             : {
     970             :   // Allocate tree id by using id namespace.
     971             :   // By it, tree id does not conflict with external image id and
     972             :   // async image pipeline id.
     973           2 :   MOZ_ASSERT(NS_IsMainThread());
     974           2 :   ++mResourceId;
     975           2 :   if (mResourceId == UINT32_MAX) {
     976             :     // Move to next id namespace.
     977           0 :     mIdNamespace = AllocateNamespace();
     978           0 :     mResourceId = 1;
     979             :   }
     980             : 
     981           2 :   uint64_t layerTreeId = mIdNamespace;
     982           2 :   layerTreeId = (layerTreeId << 32) | mResourceId;
     983           2 :   return layerTreeId;
     984             : }
     985             : 
     986             : uint32_t
     987          10 : GPUProcessManager::AllocateNamespace()
     988             : {
     989          10 :   MOZ_ASSERT(NS_IsMainThread());
     990          10 :   return ++mNextNamespace;
     991             : }
     992             : 
     993             : bool
     994           1 : GPUProcessManager::AllocateAndConnectLayerTreeId(PCompositorBridgeChild* aCompositorBridge,
     995             :                                                  base::ProcessId aOtherPid,
     996             :                                                  uint64_t* aOutLayersId,
     997             :                                                  CompositorOptions* aOutCompositorOptions)
     998             : {
     999           1 :   uint64_t layersId = AllocateLayerTreeId();
    1000           1 :   *aOutLayersId = layersId;
    1001             : 
    1002           1 :   if (!mGPUChild || !aCompositorBridge) {
    1003             :     // If we're not remoting to another process, or there is no compositor,
    1004             :     // then we'll send at most one message. In this case we can just keep
    1005             :     // the old behavior of making sure the mapping occurs, and maybe sending
    1006             :     // a creation notification.
    1007           1 :     MapLayerTreeId(layersId, aOtherPid);
    1008           1 :     if (!aCompositorBridge) {
    1009           0 :       return false;
    1010             :     }
    1011           1 :     return aCompositorBridge->SendNotifyChildCreated(layersId, aOutCompositorOptions);
    1012             :   }
    1013             : 
    1014             :   // Use the combined message path.
    1015           0 :   LayerTreeOwnerTracker::Get()->Map(layersId, aOtherPid);
    1016           0 :   return aCompositorBridge->SendMapAndNotifyChildCreated(layersId, aOtherPid, aOutCompositorOptions);
    1017             : }
    1018             : 
    1019             : void
    1020           0 : GPUProcessManager::EnsureVsyncIOThread()
    1021             : {
    1022           0 :   if (mVsyncIOThread) {
    1023           0 :     return;
    1024             :   }
    1025             : 
    1026           0 :   mVsyncIOThread = new VsyncIOThreadHolder();
    1027           0 :   MOZ_RELEASE_ASSERT(mVsyncIOThread->Start());
    1028             : }
    1029             : 
    1030             : void
    1031           0 : GPUProcessManager::ShutdownVsyncIOThread()
    1032             : {
    1033           0 :   mVsyncIOThread = nullptr;
    1034           0 : }
    1035             : 
    1036             : void
    1037           0 : GPUProcessManager::RegisterRemoteProcessSession(RemoteCompositorSession* aSession)
    1038             : {
    1039           0 :   mRemoteSessions.AppendElement(aSession);
    1040           0 : }
    1041             : 
    1042             : void
    1043           0 : GPUProcessManager::UnregisterRemoteProcessSession(RemoteCompositorSession* aSession)
    1044             : {
    1045           0 :   mRemoteSessions.RemoveElement(aSession);
    1046           0 : }
    1047             : 
    1048             : void
    1049           1 : GPUProcessManager::RegisterInProcessSession(InProcessCompositorSession* aSession)
    1050             : {
    1051           1 :   mInProcessSessions.AppendElement(aSession);
    1052           1 : }
    1053             : 
    1054             : void
    1055           0 : GPUProcessManager::UnregisterInProcessSession(InProcessCompositorSession* aSession)
    1056             : {
    1057           0 :   mInProcessSessions.RemoveElement(aSession);
    1058           0 : }
    1059             : 
    1060             : void
    1061           2 : GPUProcessManager::AddListener(GPUProcessListener* aListener)
    1062             : {
    1063           2 :   mListeners.AppendElement(aListener);
    1064           2 : }
    1065             : 
    1066             : void
    1067           0 : GPUProcessManager::RemoveListener(GPUProcessListener* aListener)
    1068             : {
    1069           0 :   mListeners.RemoveElement(aListener);
    1070           0 : }
    1071             : 
    1072             : bool
    1073           0 : GPUProcessManager::NotifyGpuObservers(const char* aTopic)
    1074             : {
    1075           0 :   if (!EnsureGPUReady()) {
    1076           0 :     return false;
    1077             :   }
    1078           0 :   nsCString topic(aTopic);
    1079           0 :   mGPUChild->SendNotifyGpuObservers(topic);
    1080           0 :   return true;
    1081             : }
    1082             : 
    1083           0 : class GPUMemoryReporter : public MemoryReportingProcess
    1084             : {
    1085             : public:
    1086           0 :   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(GPUMemoryReporter, override)
    1087             : 
    1088           0 :   bool IsAlive() const override {
    1089           0 :     if (GPUProcessManager* gpm = GPUProcessManager::Get()) {
    1090           0 :       return !!gpm->GetGPUChild();
    1091             :     }
    1092           0 :     return false;
    1093             :   }
    1094             : 
    1095           0 :   bool SendRequestMemoryReport(const uint32_t& aGeneration,
    1096             :                                const bool& aAnonymize,
    1097             :                                const bool& aMinimizeMemoryUsage,
    1098             :                                const dom::MaybeFileDesc& aDMDFile) override
    1099             :   {
    1100           0 :     GPUChild* child = GetChild();
    1101           0 :     if (!child) {
    1102           0 :       return false;
    1103             :     }
    1104             : 
    1105             :     return child->SendRequestMemoryReport(
    1106           0 :       aGeneration, aAnonymize, aMinimizeMemoryUsage, aDMDFile);
    1107             :   }
    1108             : 
    1109           0 :   int32_t Pid() const override {
    1110           0 :     if (GPUChild* child = GetChild()) {
    1111           0 :       return (int32_t)child->OtherPid();
    1112             :     }
    1113           0 :     return 0;
    1114             :   }
    1115             : 
    1116             : private:
    1117           0 :   GPUChild* GetChild() const {
    1118           0 :     if (GPUProcessManager* gpm = GPUProcessManager::Get()) {
    1119           0 :       if (GPUChild* child = gpm->GetGPUChild()) {
    1120           0 :         return child;
    1121             :       }
    1122             :     }
    1123           0 :     return nullptr;
    1124             :   }
    1125             : 
    1126             : protected:
    1127           0 :   ~GPUMemoryReporter() = default;
    1128             : };
    1129             : 
    1130             : RefPtr<MemoryReportingProcess>
    1131           0 : GPUProcessManager::GetProcessMemoryReporter()
    1132             : {
    1133           0 :   if (!EnsureGPUReady()) {
    1134           0 :     return nullptr;
    1135             :   }
    1136           0 :   return new GPUMemoryReporter();
    1137             : }
    1138             : 
    1139             : } // namespace gfx
    1140             : } // namespace mozilla

Generated by: LCOV version 1.13