LCOV - code coverage report
Current view: top level - gfx/layers/ipc - CompositorManagerParent.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 48 76 63.2 %
Date: 2017-07-14 16:53:18 Functions: 6 11 54.5 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* vim: set ts=2 sw=2 et tw=80: */
       2             : /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
       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 "mozilla/layers/CompositorManagerParent.h"
       8             : #include "mozilla/gfx/GPUParent.h"
       9             : #include "mozilla/layers/CompositorBridgeParent.h"
      10             : #include "mozilla/layers/CrossProcessCompositorBridgeParent.h"
      11             : #include "mozilla/layers/CompositorThread.h"
      12             : #include "VsyncSource.h"
      13             : 
      14             : namespace mozilla {
      15             : namespace layers {
      16             : 
      17           3 : StaticRefPtr<CompositorManagerParent> CompositorManagerParent::sInstance;
      18           3 : StaticMutex CompositorManagerParent::sMutex;
      19             : 
      20             : /* static */ already_AddRefed<CompositorManagerParent>
      21           1 : CompositorManagerParent::CreateSameProcess()
      22             : {
      23           1 :   MOZ_ASSERT(XRE_IsParentProcess());
      24           1 :   MOZ_ASSERT(NS_IsMainThread());
      25           2 :   StaticMutexAutoLock lock(sMutex);
      26             : 
      27             :   // We are creating a manager for the UI process, inside the combined GPU/UI
      28             :   // process. It is created more-or-less the same but we retain a reference to
      29             :   // the parent to access state.
      30           1 :   if (NS_WARN_IF(sInstance)) {
      31           0 :     MOZ_ASSERT_UNREACHABLE("Already initialized");
      32             :     return nullptr;
      33             :   }
      34             : 
      35             :   // The child is responsible for setting up the IPC channel in the same
      36             :   // process case because if we open from the child perspective, we can do it
      37             :   // on the main thread and complete before we return the manager handles.
      38           2 :   RefPtr<CompositorManagerParent> parent = new CompositorManagerParent();
      39           1 :   parent->SetOtherProcessId(base::GetCurrentProcId());
      40             : 
      41             :   // CompositorManagerParent::Bind would normally add a reference for IPDL but
      42             :   // we don't use that in the same process case.
      43           1 :   parent.get()->AddRef();
      44           1 :   sInstance = parent;
      45           1 :   return parent.forget();
      46             : }
      47             : 
      48             : /* static */ void
      49           2 : CompositorManagerParent::Create(Endpoint<PCompositorManagerParent>&& aEndpoint)
      50             : {
      51           2 :   MOZ_ASSERT(NS_IsMainThread());
      52             : 
      53             :   // We are creating a manager for the another process, inside the GPU process
      54             :   // (or UI process if it subsumbed the GPU process).
      55           2 :   MOZ_ASSERT(aEndpoint.OtherPid() != base::GetCurrentProcId());
      56             : 
      57           4 :   RefPtr<CompositorManagerParent> bridge = new CompositorManagerParent();
      58             : 
      59           4 :   RefPtr<Runnable> runnable = NewRunnableMethod<Endpoint<PCompositorManagerParent>&&>(
      60             :     "CompositorManagerParent::Bind",
      61             :     bridge,
      62             :     &CompositorManagerParent::Bind,
      63           6 :     Move(aEndpoint));
      64           2 :   CompositorThreadHolder::Loop()->PostTask(runnable.forget());
      65           2 : }
      66             : 
      67             : /* static */ already_AddRefed<CompositorBridgeParent>
      68           1 : CompositorManagerParent::CreateSameProcessWidgetCompositorBridge(CSSToLayoutDeviceScale aScale,
      69             :                                                                  const CompositorOptions& aOptions,
      70             :                                                                  bool aUseExternalSurfaceSize,
      71             :                                                                  const gfx::IntSize& aSurfaceSize)
      72             : {
      73           1 :   MOZ_ASSERT(XRE_IsParentProcess());
      74           1 :   MOZ_ASSERT(NS_IsMainThread());
      75             : 
      76             :   // When we are in a combined UI / GPU process, InProcessCompositorSession
      77             :   // requires both the parent and child PCompositorBridge actors for its own
      78             :   // construction, which is done on the main thread. Normally
      79             :   // CompositorBridgeParent is created on the compositor thread via the IPDL
      80             :   // plumbing (CompositorManagerParent::AllocPCompositorBridgeParent). Thus to
      81             :   // actually get a reference to the parent, we would need to block on the
      82             :   // compositor thread until it handles our constructor message. Because only
      83             :   // one one IPDL constructor is permitted per parent and child protocol, we
      84             :   // cannot make the normal case async and this case sync. Instead what we do
      85             :   // is leave the constructor async (a boon to the content process setup) and
      86             :   // create the parent ahead of time. It will pull the preinitialized parent
      87             :   // from the queue when it receives the message and give that to IPDL.
      88             : 
      89             :   // Note that the static mutex not only is used to protect sInstance, but also
      90             :   // mPendingCompositorBridges.
      91           2 :   StaticMutexAutoLock lock(sMutex);
      92           1 :   if (NS_WARN_IF(!sInstance)) {
      93           0 :     return nullptr;
      94             :   }
      95             : 
      96             :   TimeDuration vsyncRate =
      97           1 :     gfxPlatform::GetPlatform()->GetHardwareVsync()->GetGlobalDisplay().GetVsyncRate();
      98             : 
      99             :   RefPtr<CompositorBridgeParent> bridge =
     100             :     new CompositorBridgeParent(sInstance, aScale, vsyncRate, aOptions,
     101           3 :                                aUseExternalSurfaceSize, aSurfaceSize);
     102             : 
     103           1 :   sInstance->mPendingCompositorBridges.AppendElement(bridge);
     104           1 :   return bridge.forget();
     105             : }
     106             : 
     107           3 : CompositorManagerParent::CompositorManagerParent()
     108           3 :   : mCompositorThreadHolder(CompositorThreadHolder::GetSingleton())
     109             : {
     110           3 : }
     111             : 
     112           0 : CompositorManagerParent::~CompositorManagerParent()
     113             : {
     114           0 : }
     115             : 
     116             : void
     117           2 : CompositorManagerParent::Bind(Endpoint<PCompositorManagerParent>&& aEndpoint)
     118             : {
     119           2 :   MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
     120           2 :   if (NS_WARN_IF(!aEndpoint.Bind(this))) {
     121           0 :     return;
     122             :   }
     123             : 
     124             :   // Add the IPDL reference to ourself, so we can't get freed until IPDL is
     125             :   // done with us.
     126           2 :   AddRef();
     127             : }
     128             : 
     129             : void
     130           0 : CompositorManagerParent::ActorDestroy(ActorDestroyReason aReason)
     131             : {
     132           0 :   StaticMutexAutoLock lock(sMutex);
     133           0 :   if (sInstance == this) {
     134           0 :     sInstance = nullptr;
     135             :   }
     136           0 : }
     137             : 
     138             : void
     139           0 : CompositorManagerParent::DeallocPCompositorManagerParent()
     140             : {
     141           0 :   Release();
     142           0 : }
     143             : 
     144             : PCompositorBridgeParent*
     145           2 : CompositorManagerParent::AllocPCompositorBridgeParent(const CompositorBridgeOptions& aOpt)
     146             : {
     147           2 :   switch (aOpt.type()) {
     148             :     case CompositorBridgeOptions::TContentCompositorOptions: {
     149             :       CrossProcessCompositorBridgeParent* bridge =
     150           1 :         new CrossProcessCompositorBridgeParent(this);
     151           1 :       bridge->AddRef();
     152           1 :       return bridge;
     153             :     }
     154             :     case CompositorBridgeOptions::TWidgetCompositorOptions: {
     155             :       // Only the UI process is allowed to create widget compositors in the
     156             :       // compositor process.
     157           0 :       gfx::GPUParent* gpu = gfx::GPUParent::GetSingleton();
     158           0 :       if (NS_WARN_IF(!gpu || OtherPid() != gpu->OtherPid())) {
     159           0 :         MOZ_ASSERT_UNREACHABLE("Child cannot create widget compositor!");
     160             :         break;
     161             :       }
     162             : 
     163           0 :       const WidgetCompositorOptions& opt = aOpt.get_WidgetCompositorOptions();
     164             :       CompositorBridgeParent* bridge =
     165           0 :         new CompositorBridgeParent(this, opt.scale(), opt.vsyncRate(),
     166           0 :                                    opt.options(), opt.useExternalSurfaceSize(),
     167           0 :                                    opt.surfaceSize());
     168           0 :       bridge->AddRef();
     169           0 :       return bridge;
     170             :     }
     171             :     case CompositorBridgeOptions::TSameProcessWidgetCompositorOptions: {
     172             :       // If the GPU and UI process are combined, we actually already created the
     173             :       // CompositorBridgeParent, so we need to reuse that to inject it into the
     174             :       // IPDL framework.
     175           1 :       if (NS_WARN_IF(OtherPid() != base::GetCurrentProcId())) {
     176           0 :         MOZ_ASSERT_UNREACHABLE("Child cannot create same process compositor!");
     177             :         break;
     178             :       }
     179             : 
     180             :       // Note that the static mutex not only is used to protect sInstance, but
     181             :       // also mPendingCompositorBridges.
     182           2 :       StaticMutexAutoLock lock(sMutex);
     183           1 :       MOZ_ASSERT(!mPendingCompositorBridges.IsEmpty());
     184             : 
     185           1 :       CompositorBridgeParent* bridge = mPendingCompositorBridges[0];
     186           1 :       bridge->AddRef();
     187           1 :       mPendingCompositorBridges.RemoveElementAt(0);
     188           1 :       return bridge;
     189             :     }
     190             :     default:
     191           0 :       break;
     192             :   }
     193             : 
     194           0 :   return nullptr;
     195             : }
     196             : 
     197             : bool
     198           0 : CompositorManagerParent::DeallocPCompositorBridgeParent(PCompositorBridgeParent* aActor)
     199             : {
     200           0 :   static_cast<CompositorBridgeParentBase*>(aActor)->Release();
     201           0 :   return true;
     202             : }
     203             : 
     204             : } // namespace layers
     205             : } // namespace mozilla

Generated by: LCOV version 1.13