LCOV - code coverage report
Current view: top level - gfx/layers/ipc - CompositorManagerChild.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 67 122 54.9 %
Date: 2017-07-14 16:53:18 Functions: 10 18 55.6 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
       2             :  * This Source Code Form is subject to the terms of the Mozilla Public
       3             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       4             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       5             : 
       6             : #include "mozilla/layers/CompositorManagerChild.h"
       7             : #include "mozilla/layers/CompositorBridgeChild.h"
       8             : #include "mozilla/layers/CompositorManagerParent.h"
       9             : #include "mozilla/layers/CompositorThread.h"
      10             : #include "mozilla/gfx/GPUProcessManager.h"
      11             : #include "mozilla/dom/ContentChild.h"   // for ContentChild
      12             : #include "mozilla/dom/TabChild.h"       // for TabChild
      13             : #include "mozilla/dom/TabGroup.h"       // for TabGroup
      14             : #include "VsyncSource.h"
      15             : 
      16             : namespace mozilla {
      17             : namespace layers {
      18             : 
      19           3 : StaticRefPtr<CompositorManagerChild> CompositorManagerChild::sInstance;
      20             : 
      21             : /* static */ bool
      22           2 : CompositorManagerChild::IsInitialized(base::ProcessId aGPUPid)
      23             : {
      24           2 :   MOZ_ASSERT(NS_IsMainThread());
      25             :   // Since GPUChild and CompositorManagerChild will race on ActorDestroy, we
      26             :   // cannot know if the CompositorManagerChild is about to be released but has
      27             :   // yet to be. As such, we need to verify the GPU PID matches as well.
      28           2 :   return sInstance && sInstance->CanSend() && sInstance->OtherPid() == aGPUPid;
      29             : }
      30             : 
      31             : /* static */ bool
      32           1 : CompositorManagerChild::InitSameProcess(uint32_t aNamespace)
      33             : {
      34           1 :   MOZ_ASSERT(NS_IsMainThread());
      35           1 :   if (NS_WARN_IF(IsInitialized(base::GetCurrentProcId()))) {
      36           0 :     MOZ_ASSERT_UNREACHABLE("Already initialized same process");
      37             :     return false;
      38             :   }
      39             : 
      40             :   RefPtr<CompositorManagerParent> parent =
      41           2 :     CompositorManagerParent::CreateSameProcess();
      42           2 :   sInstance = new CompositorManagerChild(parent, aNamespace);
      43           1 :   return true;
      44             : }
      45             : 
      46             : /* static */ bool
      47           2 : CompositorManagerChild::Init(Endpoint<PCompositorManagerChild>&& aEndpoint,
      48             :                              uint32_t aNamespace)
      49             : {
      50           2 :   MOZ_ASSERT(NS_IsMainThread());
      51           2 :   if (sInstance) {
      52             :     // Since GPUChild and CompositorManagerChild will race on ActorDestroy, we
      53             :     // cannot know if the CompositorManagerChild has yet to be released or not.
      54             :     // To avoid an unnecessary reinitialization, we verify the GPU PID actually
      55             :     // changed.
      56           0 :     MOZ_ASSERT(sInstance->mNamespace != aNamespace);
      57           0 :     MOZ_RELEASE_ASSERT(sInstance->OtherPid() != aEndpoint.OtherPid());
      58             :   }
      59             : 
      60           4 :   sInstance = new CompositorManagerChild(Move(aEndpoint), aNamespace);
      61           2 :   return sInstance->CanSend();
      62             : }
      63             : 
      64             : /* static */ void
      65           0 : CompositorManagerChild::Shutdown()
      66             : {
      67           0 :   MOZ_ASSERT(NS_IsMainThread());
      68           0 :   CompositorBridgeChild::ShutDown();
      69             : 
      70           0 :   if (!sInstance) {
      71           0 :     return;
      72             :   }
      73             : 
      74           0 :   sInstance->Close();
      75           0 :   sInstance = nullptr;
      76             : }
      77             : 
      78             : /* static */ bool
      79           2 : CompositorManagerChild::CreateContentCompositorBridge(uint32_t aNamespace)
      80             : {
      81           2 :   MOZ_ASSERT(NS_IsMainThread());
      82           2 :   if (NS_WARN_IF(!sInstance)) {
      83           0 :     return false;
      84             :   }
      85             : 
      86           4 :   CompositorBridgeOptions options = ContentCompositorOptions();
      87             :   PCompositorBridgeChild* pbridge =
      88           2 :     sInstance->SendPCompositorBridgeConstructor(options);
      89           2 :   if (NS_WARN_IF(!pbridge)) {
      90           0 :     return true;
      91             :   }
      92             : 
      93           2 :   auto bridge = static_cast<CompositorBridgeChild*>(pbridge);
      94           2 :   bridge->InitForContent(aNamespace);
      95           2 :   return true;
      96             : }
      97             : 
      98             : /* static */ already_AddRefed<CompositorBridgeChild>
      99           0 : CompositorManagerChild::CreateWidgetCompositorBridge(uint64_t aProcessToken,
     100             :                                                      LayerManager* aLayerManager,
     101             :                                                      uint32_t aNamespace,
     102             :                                                      CSSToLayoutDeviceScale aScale,
     103             :                                                      const CompositorOptions& aOptions,
     104             :                                                      bool aUseExternalSurfaceSize,
     105             :                                                      const gfx::IntSize& aSurfaceSize)
     106             : {
     107           0 :   MOZ_ASSERT(XRE_IsParentProcess());
     108           0 :   MOZ_ASSERT(NS_IsMainThread());
     109           0 :   if (NS_WARN_IF(!sInstance)) {
     110           0 :     return nullptr;
     111             :   }
     112             : 
     113             :   TimeDuration vsyncRate =
     114           0 :     gfxPlatform::GetPlatform()->GetHardwareVsync()->GetGlobalDisplay().GetVsyncRate();
     115             : 
     116             :   CompositorBridgeOptions options =
     117           0 :     WidgetCompositorOptions(aScale, vsyncRate, aOptions,
     118           0 :                             aUseExternalSurfaceSize, aSurfaceSize);
     119             :   PCompositorBridgeChild* pbridge =
     120           0 :     sInstance->SendPCompositorBridgeConstructor(options);
     121           0 :   if (NS_WARN_IF(!pbridge)) {
     122           0 :     return nullptr;
     123             :   }
     124             : 
     125             :   RefPtr<CompositorBridgeChild> bridge =
     126           0 :     static_cast<CompositorBridgeChild*>(pbridge);
     127           0 :   bridge->InitForWidget(aProcessToken, aLayerManager, aNamespace);
     128           0 :   return bridge.forget();
     129             : }
     130             : 
     131             : /* static */ already_AddRefed<CompositorBridgeChild>
     132           1 : CompositorManagerChild::CreateSameProcessWidgetCompositorBridge(LayerManager* aLayerManager,
     133             :                                                                 uint32_t aNamespace)
     134             : {
     135           1 :   MOZ_ASSERT(XRE_IsParentProcess());
     136           1 :   MOZ_ASSERT(NS_IsMainThread());
     137           1 :   if (NS_WARN_IF(!sInstance)) {
     138           0 :     return nullptr;
     139             :   }
     140             : 
     141           2 :   CompositorBridgeOptions options = SameProcessWidgetCompositorOptions();
     142             :   PCompositorBridgeChild* pbridge =
     143           1 :     sInstance->SendPCompositorBridgeConstructor(options);
     144           1 :   if (NS_WARN_IF(!pbridge)) {
     145           0 :     return nullptr;
     146             :   }
     147             : 
     148             :   RefPtr<CompositorBridgeChild> bridge =
     149           2 :     static_cast<CompositorBridgeChild*>(pbridge);
     150           1 :   bridge->InitForWidget(1, aLayerManager, aNamespace);
     151           1 :   return bridge.forget();
     152             : }
     153             : 
     154           1 : CompositorManagerChild::CompositorManagerChild(CompositorManagerParent* aParent,
     155           1 :                                                uint32_t aNamespace)
     156             :   : mCanSend(false)
     157             :   , mNamespace(aNamespace)
     158           1 :   , mResourceId(0)
     159             : {
     160           1 :   MOZ_ASSERT(aParent);
     161             : 
     162           1 :   SetOtherProcessId(base::GetCurrentProcId());
     163           1 :   MessageLoop* loop = CompositorThreadHolder::Loop();
     164           1 :   ipc::MessageChannel* channel = aParent->GetIPCChannel();
     165           1 :   if (NS_WARN_IF(!Open(channel, loop, ipc::ChildSide))) {
     166           0 :     return;
     167             :   }
     168             : 
     169           1 :   mCanSend = true;
     170           1 :   AddRef();
     171           1 :   SetReplyTimeout();
     172             : }
     173             : 
     174           2 : CompositorManagerChild::CompositorManagerChild(Endpoint<PCompositorManagerChild>&& aEndpoint,
     175           2 :                                                uint32_t aNamespace)
     176             :   : mCanSend(false)
     177             :   , mNamespace(aNamespace)
     178           2 :   , mResourceId(0)
     179             : {
     180           2 :   if (NS_WARN_IF(!aEndpoint.Bind(this))) {
     181           0 :     return;
     182             :   }
     183             : 
     184           2 :   mCanSend = true;
     185           2 :   AddRef();
     186           2 :   SetReplyTimeout();
     187             : }
     188             : 
     189             : void
     190           0 : CompositorManagerChild::DeallocPCompositorManagerChild()
     191             : {
     192           0 :   MOZ_ASSERT(!mCanSend);
     193           0 :   Release();
     194           0 : }
     195             : 
     196             : void
     197           0 : CompositorManagerChild::ActorDestroy(ActorDestroyReason aReason)
     198             : {
     199           0 :   mCanSend = false;
     200           0 :   if (sInstance == this) {
     201           0 :     sInstance = nullptr;
     202             :   }
     203           0 : }
     204             : 
     205             : PCompositorBridgeChild*
     206           3 : CompositorManagerChild::AllocPCompositorBridgeChild(const CompositorBridgeOptions& aOptions)
     207             : {
     208           3 :   CompositorBridgeChild* child = new CompositorBridgeChild(this);
     209           3 :   child->AddRef();
     210           3 :   return child;
     211             : }
     212             : 
     213             : bool
     214           0 : CompositorManagerChild::DeallocPCompositorBridgeChild(PCompositorBridgeChild* aActor)
     215             : {
     216           0 :   static_cast<CompositorBridgeChild*>(aActor)->Release();
     217           0 :   return true;
     218             : }
     219             : 
     220             : void
     221           0 : CompositorManagerChild::HandleFatalError(const char* aName, const char* aMsg) const
     222             : {
     223           0 :   dom::ContentChild::FatalErrorIfNotUsingGPUProcess(aName, aMsg, OtherPid());
     224           0 : }
     225             : 
     226             : void
     227           0 : CompositorManagerChild::ProcessingError(Result aCode, const char* aReason)
     228             : {
     229           0 :   if (aCode != MsgDropped) {
     230           0 :     gfxDevCrash(gfx::LogReason::ProcessingError) << "Processing error in CompositorBridgeChild: " << int(aCode);
     231             :   }
     232           0 : }
     233             : 
     234             : already_AddRefed<nsIEventTarget>
     235          64 : CompositorManagerChild::GetSpecificMessageEventTarget(const Message& aMsg)
     236             : {
     237          64 :   if (aMsg.type() != PCompositorBridge::Msg_DidComposite__ID) {
     238           7 :     return nullptr;
     239             :   }
     240             : 
     241             :   uint64_t layersId;
     242          57 :   PickleIterator iter(aMsg);
     243          57 :   if (!IPC::ReadParam(&aMsg, &iter, &layersId)) {
     244           0 :     return nullptr;
     245             :   }
     246             : 
     247          57 :   TabChild* tabChild = TabChild::GetFrom(layersId);
     248          57 :   if (!tabChild) {
     249          29 :     return nullptr;
     250             :   }
     251             : 
     252          28 :   return do_AddRef(tabChild->TabGroup()->EventTargetFor(TaskCategory::Other));
     253             : }
     254             : 
     255             : void
     256           3 : CompositorManagerChild::SetReplyTimeout()
     257             : {
     258             : #ifndef DEBUG
     259             :   // Add a timeout for release builds to kill GPU process when it hangs.
     260             :   // Don't apply timeout when using web render as it tend to timeout frequently.
     261             :   if (XRE_IsParentProcess() && !gfxVars::UseWebRender()) {
     262             :     int32_t timeout = gfxPrefs::GPUProcessIPCReplyTimeoutMs();
     263             :     SetReplyTimeoutMs(timeout);
     264             :   }
     265             : #endif
     266           3 : }
     267             : 
     268             : bool
     269           0 : CompositorManagerChild::ShouldContinueFromReplyTimeout()
     270             : {
     271           0 :   if (XRE_IsParentProcess()) {
     272           0 :     gfxCriticalNote << "Killing GPU process due to IPC reply timeout";
     273           0 :     GPUProcessManager::Get()->KillProcess();
     274             :   }
     275           0 :   return false;
     276             : }
     277             : 
     278             : } // namespace layers
     279             : } // namespace mozilla

Generated by: LCOV version 1.13