LCOV - code coverage report
Current view: top level - gfx/layers/ipc - ImageBridgeParent.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 35 176 19.9 %
Date: 2017-07-14 16:53:18 Functions: 8 36 22.2 %
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 "ImageBridgeParent.h"
       8             : #include <stdint.h>                     // for uint64_t, uint32_t
       9             : #include "CompositableHost.h"           // for CompositableParent, Create
      10             : #include "base/message_loop.h"          // for MessageLoop
      11             : #include "base/process.h"               // for ProcessId
      12             : #include "base/task.h"                  // for CancelableTask, DeleteTask, etc
      13             : #include "mozilla/ClearOnShutdown.h"
      14             : #include "mozilla/gfx/Point.h"                   // for IntSize
      15             : #include "mozilla/Hal.h"                // for hal::SetCurrentThreadPriority()
      16             : #include "mozilla/HalTypes.h"           // for hal::THREAD_PRIORITY_COMPOSITOR
      17             : #include "mozilla/ipc/MessageChannel.h" // for MessageChannel, etc
      18             : #include "mozilla/ipc/ProtocolUtils.h"
      19             : #include "mozilla/ipc/Transport.h"      // for Transport
      20             : #include "mozilla/media/MediaSystemResourceManagerParent.h" // for MediaSystemResourceManagerParent
      21             : #include "mozilla/layers/CompositableTransactionParent.h"
      22             : #include "mozilla/layers/LayerManagerComposite.h"
      23             : #include "mozilla/layers/LayersMessages.h"  // for EditReply
      24             : #include "mozilla/layers/PImageBridgeParent.h"
      25             : #include "mozilla/layers/TextureHostOGL.h"  // for TextureHostOGL
      26             : #include "mozilla/layers/Compositor.h"
      27             : #include "mozilla/Monitor.h"
      28             : #include "mozilla/mozalloc.h"           // for operator new, etc
      29             : #include "mozilla/Unused.h"
      30             : #include "nsDebug.h"                    // for NS_RUNTIMEABORT, etc
      31             : #include "nsISupportsImpl.h"            // for ImageBridgeParent::Release, etc
      32             : #include "nsTArray.h"                   // for nsTArray, nsTArray_Impl
      33             : #include "nsTArrayForwardDeclare.h"     // for InfallibleTArray
      34             : #include "nsXULAppAPI.h"                // for XRE_GetIOMessageLoop
      35             : #include "mozilla/layers/TextureHost.h"
      36             : #include "nsThreadUtils.h"
      37             : 
      38             : namespace mozilla {
      39             : namespace layers {
      40             : 
      41             : using namespace mozilla::ipc;
      42             : using namespace mozilla::gfx;
      43             : using namespace mozilla::media;
      44             : 
      45           3 : std::map<base::ProcessId, ImageBridgeParent*> ImageBridgeParent::sImageBridges;
      46             : 
      47           3 : StaticAutoPtr<mozilla::Monitor> sImageBridgesLock;
      48             : 
      49             : // defined in CompositorBridgeParent.cpp
      50             : CompositorThreadHolder* GetCompositorThreadHolder();
      51             : 
      52             : /* static */ void
      53           1 : ImageBridgeParent::Setup()
      54             : {
      55           1 :   MOZ_ASSERT(NS_IsMainThread());
      56           1 :   if (!sImageBridgesLock) {
      57           1 :     sImageBridgesLock = new Monitor("ImageBridges");
      58           1 :     mozilla::ClearOnShutdown(&sImageBridgesLock);
      59             :   }
      60           1 : }
      61             : 
      62           3 : ImageBridgeParent::ImageBridgeParent(MessageLoop* aLoop,
      63           3 :                                      ProcessId aChildProcessId)
      64             :   : mMessageLoop(aLoop)
      65             :   , mSetChildThreadPriority(false)
      66           3 :   , mClosed(false)
      67             : {
      68           3 :   MOZ_ASSERT(NS_IsMainThread());
      69             : 
      70             :   // creates the map only if it has not been created already, so it is safe
      71             :   // with several bridges
      72             :   {
      73           6 :     MonitorAutoLock lock(*sImageBridgesLock);
      74           3 :     sImageBridges[aChildProcessId] = this;
      75             :   }
      76           3 :   SetOtherProcessId(aChildProcessId);
      77           3 : }
      78             : 
      79           0 : ImageBridgeParent::~ImageBridgeParent()
      80             : {
      81           0 : }
      82             : 
      83           3 : static StaticRefPtr<ImageBridgeParent> sImageBridgeParentSingleton;
      84             : 
      85           0 : void ReleaseImageBridgeParentSingleton() {
      86           0 :   sImageBridgeParentSingleton = nullptr;
      87           0 : }
      88             : 
      89             : /* static */ ImageBridgeParent*
      90           1 : ImageBridgeParent::CreateSameProcess()
      91             : {
      92             :   RefPtr<ImageBridgeParent> parent =
      93           3 :     new ImageBridgeParent(CompositorThreadHolder::Loop(), base::GetCurrentProcId());
      94           1 :   parent->mSelfRef = parent;
      95             : 
      96           1 :   sImageBridgeParentSingleton = parent;
      97           2 :   return parent;
      98             : }
      99             : 
     100             : /* static */ bool
     101           0 : ImageBridgeParent::CreateForGPUProcess(Endpoint<PImageBridgeParent>&& aEndpoint)
     102             : {
     103           0 :   MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_GPU);
     104             : 
     105           0 :   MessageLoop* loop = CompositorThreadHolder::Loop();
     106           0 :   RefPtr<ImageBridgeParent> parent = new ImageBridgeParent(loop, aEndpoint.OtherPid());
     107             : 
     108           0 :   loop->PostTask(NewRunnableMethod<Endpoint<PImageBridgeParent>&&>(
     109             :     "layers::ImageBridgeParent::Bind",
     110             :     parent,
     111             :     &ImageBridgeParent::Bind,
     112           0 :     Move(aEndpoint)));
     113             : 
     114           0 :   sImageBridgeParentSingleton = parent;
     115           0 :   return true;
     116             : }
     117             : 
     118             : void
     119           0 : ImageBridgeParent::ActorDestroy(ActorDestroyReason aWhy)
     120             : {
     121             :   // Can't alloc/dealloc shmems from now on.
     122           0 :   mClosed = true;
     123           0 :   mCompositables.clear();
     124             :   {
     125           0 :     MonitorAutoLock lock(*sImageBridgesLock);
     126           0 :     sImageBridges.erase(OtherPid());
     127             :   }
     128           0 :   MessageLoop::current()->PostTask(
     129           0 :     NewRunnableMethod("layers::ImageBridgeParent::DeferredDestroy",
     130             :                       this,
     131           0 :                       &ImageBridgeParent::DeferredDestroy));
     132             : 
     133             :   // It is very important that this method gets called at shutdown (be it a clean
     134             :   // or an abnormal shutdown), because DeferredDestroy is what clears mSelfRef.
     135             :   // If mSelfRef is not null and ActorDestroy is not called, the ImageBridgeParent
     136             :   // is leaked which causes the CompositorThreadHolder to be leaked and
     137             :   // CompsoitorParent's shutdown ends up spinning the event loop forever, waiting
     138             :   // for the compositor thread to terminate.
     139           0 : }
     140             : 
     141             : mozilla::ipc::IPCResult
     142           0 : ImageBridgeParent::RecvImageBridgeThreadId(const PlatformThreadId& aThreadId)
     143             : {
     144           0 :   MOZ_ASSERT(!mSetChildThreadPriority);
     145           0 :   if (mSetChildThreadPriority) {
     146           0 :     return IPC_FAIL_NO_REASON(this);
     147             :   }
     148           0 :   mSetChildThreadPriority = true;
     149           0 :   return IPC_OK();
     150             : }
     151             : 
     152             : class MOZ_STACK_CLASS AutoImageBridgeParentAsyncMessageSender
     153             : {
     154             : public:
     155           0 :   explicit AutoImageBridgeParentAsyncMessageSender(ImageBridgeParent* aImageBridge,
     156             :                                                    InfallibleTArray<OpDestroy>* aToDestroy = nullptr)
     157           0 :     : mImageBridge(aImageBridge)
     158           0 :     , mToDestroy(aToDestroy)
     159             :   {
     160           0 :     mImageBridge->SetAboutToSendAsyncMessages();
     161           0 :   }
     162             : 
     163           0 :   ~AutoImageBridgeParentAsyncMessageSender()
     164           0 :   {
     165           0 :     mImageBridge->SendPendingAsyncMessages();
     166           0 :     if (mToDestroy) {
     167           0 :       for (const auto& op : *mToDestroy) {
     168           0 :         mImageBridge->DestroyActor(op);
     169             :       }
     170             :     }
     171           0 :   }
     172             : private:
     173             :   ImageBridgeParent* mImageBridge;
     174             :   InfallibleTArray<OpDestroy>* mToDestroy;
     175             : };
     176             : 
     177             : mozilla::ipc::IPCResult
     178           0 : ImageBridgeParent::RecvInitReadLocks(ReadLockArray&& aReadLocks)
     179             : {
     180           0 :   if (!AddReadLocks(Move(aReadLocks))) {
     181           0 :     return IPC_FAIL_NO_REASON(this);
     182             :   }
     183           0 :   return IPC_OK();
     184             : }
     185             : 
     186             : mozilla::ipc::IPCResult
     187           0 : ImageBridgeParent::RecvUpdate(EditArray&& aEdits, OpDestroyArray&& aToDestroy,
     188             :                               const uint64_t& aFwdTransactionId)
     189             : {
     190             :   // This ensures that destroy operations are always processed. It is not safe
     191             :   // to early-return from RecvUpdate without doing so.
     192           0 :   AutoImageBridgeParentAsyncMessageSender autoAsyncMessageSender(this, &aToDestroy);
     193           0 :   UpdateFwdTransactionId(aFwdTransactionId);
     194           0 :   AutoClearReadLocks clearLocks(mReadLocks);
     195             : 
     196           0 :   for (EditArray::index_type i = 0; i < aEdits.Length(); ++i) {
     197           0 :     if (!ReceiveCompositableUpdate(aEdits[i])) {
     198           0 :       return IPC_FAIL_NO_REASON(this);
     199             :     }
     200             :   }
     201             : 
     202           0 :   if (!IsSameProcess()) {
     203             :     // Ensure that any pending operations involving back and front
     204             :     // buffers have completed, so that neither process stomps on the
     205             :     // other's buffer contents.
     206           0 :     LayerManagerComposite::PlatformSyncBeforeReplyUpdate();
     207             :   }
     208             : 
     209           0 :   return IPC_OK();
     210             : }
     211             : 
     212             : /* static */ bool
     213           2 : ImageBridgeParent::CreateForContent(Endpoint<PImageBridgeParent>&& aEndpoint)
     214             : {
     215           2 :   MessageLoop* loop = CompositorThreadHolder::Loop();
     216             : 
     217           6 :   RefPtr<ImageBridgeParent> bridge = new ImageBridgeParent(loop, aEndpoint.OtherPid());
     218           4 :   loop->PostTask(NewRunnableMethod<Endpoint<PImageBridgeParent>&&>(
     219             :     "layers::ImageBridgeParent::Bind",
     220             :     bridge,
     221             :     &ImageBridgeParent::Bind,
     222           4 :     Move(aEndpoint)));
     223             : 
     224           4 :   return true;
     225             : }
     226             : 
     227             : void
     228           2 : ImageBridgeParent::Bind(Endpoint<PImageBridgeParent>&& aEndpoint)
     229             : {
     230           2 :   if (!aEndpoint.Bind(this))
     231           0 :     return;
     232           2 :   mSelfRef = this;
     233             : }
     234             : 
     235           0 : mozilla::ipc::IPCResult ImageBridgeParent::RecvWillClose()
     236             : {
     237             :   // If there is any texture still alive we have to force it to deallocate the
     238             :   // device data (GL textures, etc.) now because shortly after SenStop() returns
     239             :   // on the child side the widget will be destroyed along with it's associated
     240             :   // GL context.
     241           0 :   InfallibleTArray<PTextureParent*> textures;
     242           0 :   ManagedPTextureParent(textures);
     243           0 :   for (unsigned int i = 0; i < textures.Length(); ++i) {
     244           0 :     RefPtr<TextureHost> tex = TextureHost::AsTextureHost(textures[i]);
     245           0 :     tex->DeallocateDeviceData();
     246             :   }
     247           0 :   return IPC_OK();
     248             : }
     249             : 
     250             : mozilla::ipc::IPCResult
     251           0 : ImageBridgeParent::RecvNewCompositable(const CompositableHandle& aHandle, const TextureInfo& aInfo)
     252             : {
     253           0 :   RefPtr<CompositableHost> host = AddCompositable(aHandle, aInfo);
     254           0 :   if (!host) {
     255           0 :     return IPC_FAIL_NO_REASON(this);
     256             :   }
     257             : 
     258           0 :   host->SetAsyncRef(AsyncCompositableRef(OtherPid(), aHandle));
     259           0 :   return IPC_OK();
     260             : }
     261             : 
     262             : mozilla::ipc::IPCResult
     263           0 : ImageBridgeParent::RecvReleaseCompositable(const CompositableHandle& aHandle)
     264             : {
     265           0 :   ReleaseCompositable(aHandle);
     266           0 :   return IPC_OK();
     267             : }
     268             : 
     269             : PTextureParent*
     270           0 : ImageBridgeParent::AllocPTextureParent(const SurfaceDescriptor& aSharedData,
     271             :                                        const LayersBackend& aLayersBackend,
     272             :                                        const TextureFlags& aFlags,
     273             :                                        const uint64_t& aSerial,
     274             :                                        const wr::MaybeExternalImageId& aExternalImageId)
     275             : {
     276           0 :   return TextureHost::CreateIPDLActor(this, aSharedData, aLayersBackend, aFlags, aSerial, aExternalImageId);
     277             : }
     278             : 
     279             : bool
     280           0 : ImageBridgeParent::DeallocPTextureParent(PTextureParent* actor)
     281             : {
     282           0 :   return TextureHost::DestroyIPDLActor(actor);
     283             : }
     284             : 
     285             : PMediaSystemResourceManagerParent*
     286           0 : ImageBridgeParent::AllocPMediaSystemResourceManagerParent()
     287             : {
     288           0 :   return new mozilla::media::MediaSystemResourceManagerParent();
     289             : }
     290             : 
     291             : bool
     292           0 : ImageBridgeParent::DeallocPMediaSystemResourceManagerParent(PMediaSystemResourceManagerParent* aActor)
     293             : {
     294           0 :   MOZ_ASSERT(aActor);
     295           0 :   delete static_cast<mozilla::media::MediaSystemResourceManagerParent*>(aActor);
     296           0 :   return true;
     297             : }
     298             : 
     299             : void
     300           0 : ImageBridgeParent::SendAsyncMessage(const InfallibleTArray<AsyncParentMessageData>& aMessage)
     301             : {
     302           0 :   mozilla::Unused << SendParentAsyncMessages(aMessage);
     303           0 : }
     304             : 
     305             : class ProcessIdComparator
     306             : {
     307             : public:
     308           0 :   bool Equals(const ImageCompositeNotificationInfo& aA,
     309             :               const ImageCompositeNotificationInfo& aB) const
     310             :   {
     311           0 :     return aA.mImageBridgeProcessId == aB.mImageBridgeProcessId;
     312             :   }
     313           0 :   bool LessThan(const ImageCompositeNotificationInfo& aA,
     314             :                 const ImageCompositeNotificationInfo& aB) const
     315             :   {
     316           0 :     return aA.mImageBridgeProcessId < aB.mImageBridgeProcessId;
     317             :   }
     318             : };
     319             : 
     320             : /* static */ bool
     321           0 : ImageBridgeParent::NotifyImageComposites(nsTArray<ImageCompositeNotificationInfo>& aNotifications)
     322             : {
     323             :   // Group the notifications by destination process ID and then send the
     324             :   // notifications in one message per group.
     325           0 :   aNotifications.Sort(ProcessIdComparator());
     326           0 :   uint32_t i = 0;
     327           0 :   bool ok = true;
     328           0 :   while (i < aNotifications.Length()) {
     329           0 :     AutoTArray<ImageCompositeNotification,1> notifications;
     330           0 :     notifications.AppendElement(aNotifications[i].mNotification);
     331           0 :     uint32_t end = i + 1;
     332           0 :     MOZ_ASSERT(aNotifications[i].mNotification.compositable());
     333           0 :     ProcessId pid = aNotifications[i].mImageBridgeProcessId;
     334           0 :     while (end < aNotifications.Length() &&
     335           0 :            aNotifications[end].mImageBridgeProcessId == pid) {
     336           0 :       notifications.AppendElement(aNotifications[end].mNotification);
     337           0 :       ++end;
     338             :     }
     339           0 :     GetInstance(pid)->SendPendingAsyncMessages();
     340           0 :     if (!GetInstance(pid)->SendDidComposite(notifications)) {
     341           0 :       ok = false;
     342             :     }
     343           0 :     i = end;
     344             :   }
     345           0 :   return ok;
     346             : }
     347             : 
     348             : void
     349           0 : ImageBridgeParent::DeferredDestroy()
     350             : {
     351           0 :   mCompositorThreadHolder = nullptr;
     352           0 :   mSelfRef = nullptr; // "this" ImageBridge may get deleted here.
     353           0 : }
     354             : 
     355             : RefPtr<ImageBridgeParent>
     356           0 : ImageBridgeParent::GetInstance(ProcessId aId)
     357             : {
     358           0 :   MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
     359           0 :   MonitorAutoLock lock(*sImageBridgesLock);
     360           0 :   NS_ASSERTION(sImageBridges.count(aId) == 1, "ImageBridgeParent for the process");
     361           0 :   return sImageBridges[aId];
     362             : }
     363             : 
     364             : void
     365           1 : ImageBridgeParent::OnChannelConnected(int32_t aPid)
     366             : {
     367           1 :   mCompositorThreadHolder = GetCompositorThreadHolder();
     368           1 : }
     369             : 
     370             : 
     371             : bool
     372           0 : ImageBridgeParent::AllocShmem(size_t aSize,
     373             :                       ipc::SharedMemory::SharedMemoryType aType,
     374             :                       ipc::Shmem* aShmem)
     375             : {
     376           0 :   if (mClosed) {
     377           0 :     return false;
     378             :   }
     379           0 :   return PImageBridgeParent::AllocShmem(aSize, aType, aShmem);
     380             : }
     381             : 
     382             : bool
     383           0 : ImageBridgeParent::AllocUnsafeShmem(size_t aSize,
     384             :                       ipc::SharedMemory::SharedMemoryType aType,
     385             :                       ipc::Shmem* aShmem)
     386             : {
     387           0 :   if (mClosed) {
     388           0 :     return false;
     389             :   }
     390           0 :   return PImageBridgeParent::AllocUnsafeShmem(aSize, aType, aShmem);
     391             : }
     392             : 
     393             : void
     394           0 : ImageBridgeParent::DeallocShmem(ipc::Shmem& aShmem)
     395             : {
     396           0 :   if (mClosed) {
     397           0 :     return;
     398             :   }
     399           0 :   PImageBridgeParent::DeallocShmem(aShmem);
     400             : }
     401             : 
     402           0 : bool ImageBridgeParent::IsSameProcess() const
     403             : {
     404           0 :   return OtherPid() == base::GetCurrentProcId();
     405             : }
     406             : 
     407             : void
     408           0 : ImageBridgeParent::NotifyNotUsed(PTextureParent* aTexture, uint64_t aTransactionId)
     409             : {
     410           0 :   RefPtr<TextureHost> texture = TextureHost::AsTextureHost(aTexture);
     411           0 :   if (!texture) {
     412           0 :     return;
     413             :   }
     414             : 
     415           0 :   if (!(texture->GetFlags() & TextureFlags::RECYCLE)) {
     416           0 :     return;
     417             :   }
     418             : 
     419           0 :   uint64_t textureId = TextureHost::GetTextureSerial(aTexture);
     420           0 :   mPendingAsyncMessage.push_back(
     421           0 :     OpNotifyNotUsed(textureId, aTransactionId));
     422             : 
     423           0 :   if (!IsAboutToSendAsyncMessages()) {
     424           0 :     SendPendingAsyncMessages();
     425             :   }
     426             : }
     427             : 
     428             : } // namespace layers
     429           9 : } // namespace mozilla

Generated by: LCOV version 1.13