LCOV - code coverage report
Current view: top level - gfx/layers/ipc - ImageBridgeChild.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 64 515 12.4 %
Date: 2017-07-14 16:53:18 Functions: 10 79 12.7 %
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 "ImageBridgeChild.h"
       7             : #include <vector>                       // for vector
       8             : #include "ImageBridgeParent.h"          // for ImageBridgeParent
       9             : #include "ImageContainer.h"             // for ImageContainer
      10             : #include "Layers.h"                     // for Layer, etc
      11             : #include "ShadowLayers.h"               // for ShadowLayerForwarder
      12             : #include "base/message_loop.h"          // for MessageLoop
      13             : #include "base/platform_thread.h"       // for PlatformThread
      14             : #include "base/process.h"               // for ProcessId
      15             : #include "base/task.h"                  // for NewRunnableFunction, etc
      16             : #include "base/thread.h"                // for Thread
      17             : #include "mozilla/Assertions.h"         // for MOZ_ASSERT, etc
      18             : #include "mozilla/Monitor.h"            // for Monitor, MonitorAutoLock
      19             : #include "mozilla/ReentrantMonitor.h"   // for ReentrantMonitor, etc
      20             : #include "mozilla/ipc/MessageChannel.h" // for MessageChannel, etc
      21             : #include "mozilla/ipc/Transport.h"      // for Transport
      22             : #include "mozilla/gfx/Point.h"          // for IntSize
      23             : #include "mozilla/layers/AsyncCanvasRenderer.h"
      24             : #include "mozilla/media/MediaSystemResourceManager.h" // for MediaSystemResourceManager
      25             : #include "mozilla/media/MediaSystemResourceManagerChild.h" // for MediaSystemResourceManagerChild
      26             : #include "mozilla/layers/CompositableClient.h"  // for CompositableChild, etc
      27             : #include "mozilla/layers/CompositorThread.h"
      28             : #include "mozilla/layers/ISurfaceAllocator.h"  // for ISurfaceAllocator
      29             : #include "mozilla/layers/ImageClient.h"  // for ImageClient
      30             : #include "mozilla/layers/LayersMessages.h"  // for CompositableOperation
      31             : #include "mozilla/layers/TextureClient.h"  // for TextureClient
      32             : #include "mozilla/dom/ContentChild.h"
      33             : #include "mozilla/mozalloc.h"           // for operator new, etc
      34             : #include "mtransport/runnable_utils.h"
      35             : #include "nsContentUtils.h"
      36             : #include "nsISupportsImpl.h"            // for ImageContainer::AddRef, etc
      37             : #include "nsTArray.h"                   // for AutoTArray, nsTArray, etc
      38             : #include "nsTArrayForwardDeclare.h"     // for AutoTArray
      39             : #include "nsThreadUtils.h"              // for NS_IsMainThread
      40             : #include "nsXULAppAPI.h"                // for XRE_GetIOMessageLoop
      41             : #include "mozilla/StaticMutex.h"
      42             : #include "mozilla/StaticPtr.h"          // for StaticRefPtr
      43             : #include "mozilla/layers/TextureClient.h"
      44             : #include "SynchronousTask.h"
      45             : 
      46             : namespace mozilla {
      47             : namespace ipc {
      48             : class Shmem;
      49             : } // namespace ipc
      50             : 
      51             : namespace layers {
      52             : 
      53             : using base::Thread;
      54             : using base::ProcessId;
      55             : using namespace mozilla::ipc;
      56             : using namespace mozilla::gfx;
      57             : using namespace mozilla::media;
      58             : 
      59             : typedef std::vector<CompositableOperation> OpVector;
      60             : typedef nsTArray<OpDestroy> OpDestroyVector;
      61             : typedef nsTArray<ReadLockInit> ReadLockVector;
      62             : 
      63             : struct CompositableTransaction
      64             : {
      65           3 :   CompositableTransaction()
      66           3 :   : mReadLockSequenceNumber(0)
      67           3 :   , mFinished(true)
      68           3 :   {}
      69           0 :   ~CompositableTransaction()
      70           0 :   {
      71           0 :     End();
      72           0 :   }
      73           0 :   bool Finished() const
      74             :   {
      75           0 :     return mFinished;
      76             :   }
      77           0 :   void Begin()
      78             :   {
      79           0 :     MOZ_ASSERT(mFinished);
      80           0 :     mFinished = false;
      81           0 :     mReadLockSequenceNumber = 0;
      82           0 :     mReadLocks.AppendElement();
      83           0 :   }
      84           0 :   void End()
      85             :   {
      86           0 :     mFinished = true;
      87           0 :     mOperations.clear();
      88           0 :     mDestroyedActors.Clear();
      89           0 :     mReadLocks.Clear();
      90           0 :   }
      91           0 :   bool IsEmpty() const
      92             :   {
      93           0 :     return mOperations.empty() && mDestroyedActors.IsEmpty();
      94             :   }
      95           0 :   void AddNoSwapEdit(const CompositableOperation& op)
      96             :   {
      97           0 :     MOZ_ASSERT(!Finished(), "forgot BeginTransaction?");
      98           0 :     mOperations.push_back(op);
      99           0 :   }
     100             : 
     101           0 :   ReadLockHandle AddReadLock(const ReadLockDescriptor& aReadLock)
     102             :   {
     103           0 :     ReadLockHandle handle(++mReadLockSequenceNumber);
     104           0 :     if (mReadLocks.LastElement().Length() >= CompositableForwarder::GetMaxFileDescriptorsPerMessage()) {
     105           0 :       mReadLocks.AppendElement();
     106             :     }
     107           0 :     mReadLocks.LastElement().AppendElement(ReadLockInit(aReadLock, handle));
     108           0 :     return handle;
     109             :   }
     110             : 
     111             :   OpVector mOperations;
     112             :   OpDestroyVector mDestroyedActors;
     113             :   nsTArray<ReadLockVector> mReadLocks;
     114             :   uint64_t mReadLockSequenceNumber;
     115             : 
     116             :   bool mFinished;
     117             : };
     118             : 
     119             : struct AutoEndTransaction {
     120           0 :   explicit AutoEndTransaction(CompositableTransaction* aTxn) : mTxn(aTxn) {}
     121           0 :   ~AutoEndTransaction() { mTxn->End(); }
     122             :   CompositableTransaction* mTxn;
     123             : };
     124             : 
     125             : void
     126           0 : ImageBridgeChild::UseTextures(CompositableClient* aCompositable,
     127             :                               const nsTArray<TimedTextureClient>& aTextures)
     128             : {
     129           0 :   MOZ_ASSERT(aCompositable);
     130           0 :   MOZ_ASSERT(aCompositable->GetIPCHandle());
     131           0 :   MOZ_ASSERT(aCompositable->IsConnected());
     132             : 
     133           0 :   AutoTArray<TimedTexture,4> textures;
     134             : 
     135           0 :   for (auto& t : aTextures) {
     136           0 :     MOZ_ASSERT(t.mTextureClient);
     137           0 :     MOZ_ASSERT(t.mTextureClient->GetIPDLActor());
     138             : 
     139           0 :     if (!t.mTextureClient->IsSharedWithCompositor()) {
     140           0 :       return;
     141             :     }
     142             : 
     143           0 :     ReadLockDescriptor readLock;
     144           0 :     ReadLockHandle readLockHandle;
     145           0 :     if (t.mTextureClient->SerializeReadLock(readLock)) {
     146           0 :       readLockHandle = mTxn->AddReadLock(readLock);
     147             :     }
     148             : 
     149           0 :     textures.AppendElement(TimedTexture(nullptr, t.mTextureClient->GetIPDLActor(),
     150             :                                         readLockHandle,
     151             :                                         t.mTimeStamp, t.mPictureRect,
     152           0 :                                         t.mFrameID, t.mProducerID));
     153             : 
     154             :     // Wait end of usage on host side if TextureFlags::RECYCLE is set
     155           0 :     HoldUntilCompositableRefReleasedIfNecessary(t.mTextureClient);
     156             :   }
     157           0 :   mTxn->AddNoSwapEdit(CompositableOperation(aCompositable->GetIPCHandle(),
     158           0 :                                             OpUseTexture(textures)));
     159             : }
     160             : 
     161             : void
     162           0 : ImageBridgeChild::UseComponentAlphaTextures(CompositableClient* aCompositable,
     163             :                                             TextureClient* aTextureOnBlack,
     164             :                                             TextureClient* aTextureOnWhite)
     165             : {
     166           0 :   MOZ_CRASH("should not be called");
     167             : }
     168             : 
     169             : void
     170           0 : ImageBridgeChild::HoldUntilCompositableRefReleasedIfNecessary(TextureClient* aClient)
     171             : {
     172             :   // Wait ReleaseCompositableRef only when TextureFlags::RECYCLE is set on ImageBridge.
     173           0 :   if (!aClient ||
     174           0 :       !(aClient->GetFlags() & TextureFlags::RECYCLE)) {
     175           0 :     return;
     176             :   }
     177           0 :   aClient->SetLastFwdTransactionId(GetFwdTransactionId());
     178           0 :   mTexturesWaitingRecycled.Put(aClient->GetSerial(), aClient);
     179             : }
     180             : 
     181             : void
     182           0 : ImageBridgeChild::NotifyNotUsed(uint64_t aTextureId, uint64_t aFwdTransactionId)
     183             : {
     184           0 :   if (auto entry = mTexturesWaitingRecycled.Lookup(aTextureId)) {
     185           0 :     if (aFwdTransactionId < entry.Data()->GetLastFwdTransactionId()) {
     186             :       // Released on host side, but client already requested newer use texture.
     187           0 :       return;
     188             :     }
     189           0 :     entry.Remove();
     190             :   }
     191             : }
     192             : 
     193             : void
     194           0 : ImageBridgeChild::CancelWaitForRecycle(uint64_t aTextureId)
     195             : {
     196           0 :   MOZ_ASSERT(InImageBridgeChildThread());
     197           0 :   mTexturesWaitingRecycled.Remove(aTextureId);
     198           0 : }
     199             : 
     200             : // Singleton
     201           3 : static StaticMutex sImageBridgeSingletonLock;
     202           3 : static StaticRefPtr<ImageBridgeChild> sImageBridgeChildSingleton;
     203             : static Thread *sImageBridgeChildThread = nullptr;
     204             : 
     205             : // dispatched function
     206             : void
     207           0 : ImageBridgeChild::ShutdownStep1(SynchronousTask* aTask)
     208             : {
     209           0 :   AutoCompleteTask complete(aTask);
     210             : 
     211           0 :   MOZ_ASSERT(InImageBridgeChildThread(),
     212             :              "Should be in ImageBridgeChild thread.");
     213             : 
     214           0 :   MediaSystemResourceManager::Shutdown();
     215             : 
     216             :   // Force all managed protocols to shut themselves down cleanly
     217           0 :   InfallibleTArray<PTextureChild*> textures;
     218           0 :   ManagedPTextureChild(textures);
     219           0 :   for (int i = textures.Length() - 1; i >= 0; --i) {
     220           0 :     RefPtr<TextureClient> client = TextureClient::AsTextureClient(textures[i]);
     221           0 :     if (client) {
     222           0 :       client->Destroy();
     223             :     }
     224             :   }
     225             : 
     226           0 :   if (mCanSend) {
     227           0 :     SendWillClose();
     228             :   }
     229           0 :   MarkShutDown();
     230             : 
     231             :   // From now on, no message can be sent through the image bridge from the
     232             :   // client side except the final Stop message.
     233           0 : }
     234             : 
     235             : // dispatched function
     236             : void
     237           0 : ImageBridgeChild::ShutdownStep2(SynchronousTask* aTask)
     238             : {
     239           0 :   AutoCompleteTask complete(aTask);
     240             : 
     241           0 :   MOZ_ASSERT(InImageBridgeChildThread(),
     242             :              "Should be in ImageBridgeChild thread.");
     243           0 :   Close();
     244           0 : }
     245             : 
     246             : void
     247           0 : ImageBridgeChild::ActorDestroy(ActorDestroyReason aWhy)
     248             : {
     249           0 :   mCanSend = false;
     250             :   {
     251           0 :     MutexAutoLock lock(mContainerMapLock);
     252           0 :     mImageContainers.Clear();
     253             :   }
     254           0 : }
     255             : 
     256             : void
     257           0 : ImageBridgeChild::DeallocPImageBridgeChild()
     258             : {
     259           0 :   this->Release();
     260           0 : }
     261             : 
     262             : void
     263           0 : ImageBridgeChild::CreateImageClientSync(SynchronousTask* aTask,
     264             :                                         RefPtr<ImageClient>* result,
     265             :                                         CompositableType aType,
     266             :                                         ImageContainer* aImageContainer)
     267             : {
     268           0 :   AutoCompleteTask complete(aTask);
     269           0 :   *result = CreateImageClientNow(aType, aImageContainer);
     270           0 : }
     271             : 
     272             : // dispatched function
     273             : void
     274           0 : ImageBridgeChild::CreateCanvasClientSync(SynchronousTask* aTask,
     275             :                                          CanvasClient::CanvasClientType aType,
     276             :                                          TextureFlags aFlags,
     277             :                                          RefPtr<CanvasClient>* const outResult)
     278             : {
     279           0 :   AutoCompleteTask complete(aTask);
     280           0 :   *outResult = CreateCanvasClientNow(aType, aFlags);
     281           0 : }
     282             : 
     283           3 : ImageBridgeChild::ImageBridgeChild(uint32_t aNamespace)
     284             :   : mNamespace(aNamespace)
     285             :   , mCanSend(false)
     286             :   , mDestroyed(false)
     287             :   , mFwdTransactionId(0)
     288           3 :   , mContainerMapLock("ImageBridgeChild.mContainerMapLock")
     289             : {
     290           3 :   MOZ_ASSERT(mNamespace);
     291           3 :   MOZ_ASSERT(NS_IsMainThread());
     292             : 
     293           3 :   mTxn = new CompositableTransaction();
     294           3 : }
     295             : 
     296           0 : ImageBridgeChild::~ImageBridgeChild()
     297             : {
     298           0 :   delete mTxn;
     299           0 : }
     300             : 
     301             : void
     302           0 : ImageBridgeChild::MarkShutDown()
     303             : {
     304           0 :   mTexturesWaitingRecycled.Clear();
     305             : 
     306           0 :   mCanSend = false;
     307           0 : }
     308             : 
     309             : void
     310           0 : ImageBridgeChild::Connect(CompositableClient* aCompositable,
     311             :                           ImageContainer* aImageContainer)
     312             : {
     313           0 :   MOZ_ASSERT(aCompositable);
     314           0 :   MOZ_ASSERT(InImageBridgeChildThread());
     315           0 :   MOZ_ASSERT(CanSend());
     316             : 
     317             :   // Note: this is static, rather than per-IBC, so IDs are not re-used across
     318             :   // ImageBridgeChild instances. This is relevant for the GPU process, where
     319             :   // we don't want old IDs to potentially leak into a recreated ImageBridge.
     320             :   static uint64_t sNextID = 1;
     321           0 :   uint64_t id = sNextID++;
     322             : 
     323             :   {
     324           0 :     MutexAutoLock lock(mContainerMapLock);
     325           0 :     MOZ_ASSERT(!mImageContainers.Contains(id));
     326           0 :     mImageContainers.Put(id, aImageContainer);
     327             :   }
     328             : 
     329           0 :   CompositableHandle handle(id);
     330           0 :   aCompositable->InitIPDL(handle);
     331           0 :   SendNewCompositable(handle, aCompositable->GetTextureInfo());
     332           0 : }
     333             : 
     334             : void
     335           0 : ImageBridgeChild::ForgetImageContainer(const CompositableHandle& aHandle)
     336             : {
     337           0 :   MutexAutoLock lock(mContainerMapLock);
     338           0 :   mImageContainers.Remove(aHandle.Value());
     339           0 : }
     340             : 
     341           0 : Thread* ImageBridgeChild::GetThread() const
     342             : {
     343           0 :   return sImageBridgeChildThread;
     344             : }
     345             : 
     346             : /* static */ RefPtr<ImageBridgeChild>
     347           5 : ImageBridgeChild::GetSingleton()
     348             : {
     349          10 :   StaticMutexAutoLock lock(sImageBridgeSingletonLock);
     350          10 :   return sImageBridgeChildSingleton;
     351             : }
     352             : 
     353             : void
     354           0 : ImageBridgeChild::ReleaseTextureClientNow(TextureClient* aClient)
     355             : {
     356           0 :   MOZ_ASSERT(InImageBridgeChildThread());
     357           0 :   RELEASE_MANUALLY(aClient);
     358           0 : }
     359             : 
     360             : /* static */ void
     361           0 : ImageBridgeChild::DispatchReleaseTextureClient(TextureClient* aClient)
     362             : {
     363           0 :   if (!aClient) {
     364           0 :     return;
     365             :   }
     366             : 
     367           0 :   RefPtr<ImageBridgeChild> imageBridge = ImageBridgeChild::GetSingleton();
     368           0 :   if (!imageBridge) {
     369             :     // TextureClient::Release should normally happen in the ImageBridgeChild
     370             :     // thread because it usually generate some IPDL messages.
     371             :     // However, if we take this branch it means that the ImageBridgeChild
     372             :     // has already shut down, along with the TextureChild, which means no
     373             :     // message will be sent and it is safe to run this code from any thread.
     374           0 :     RELEASE_MANUALLY(aClient);
     375           0 :     return;
     376             :   }
     377             : 
     378           0 :   RefPtr<Runnable> runnable = WrapRunnable(
     379             :     imageBridge,
     380             :     &ImageBridgeChild::ReleaseTextureClientNow,
     381           0 :     aClient);
     382           0 :   imageBridge->GetMessageLoop()->PostTask(runnable.forget());
     383             : }
     384             : 
     385             : void
     386           0 : ImageBridgeChild::UpdateImageClient(RefPtr<ImageClient> aClient, RefPtr<ImageContainer> aContainer)
     387             : {
     388           0 :   if (!aClient || !aContainer) {
     389           0 :     return;
     390             :   }
     391             : 
     392           0 :   if (!InImageBridgeChildThread()) {
     393           0 :     RefPtr<Runnable> runnable = WrapRunnable(
     394           0 :       RefPtr<ImageBridgeChild>(this),
     395             :       &ImageBridgeChild::UpdateImageClient,
     396             :       aClient,
     397           0 :       aContainer);
     398           0 :     GetMessageLoop()->PostTask(runnable.forget());
     399           0 :     return;
     400             :   }
     401             : 
     402           0 :   if (!CanSend()) {
     403           0 :     return;
     404             :   }
     405             : 
     406             :   // If the client has become disconnected before this event was dispatched,
     407             :   // early return now.
     408           0 :   if (!aClient->IsConnected()) {
     409           0 :     return;
     410             :   }
     411             : 
     412           0 :   BeginTransaction();
     413           0 :   aClient->UpdateImage(aContainer, Layer::CONTENT_OPAQUE);
     414           0 :   EndTransaction();
     415             : }
     416             : 
     417             : void
     418           0 : ImageBridgeChild::UpdateAsyncCanvasRendererSync(SynchronousTask* aTask, AsyncCanvasRenderer* aWrapper)
     419             : {
     420           0 :   AutoCompleteTask complete(aTask);
     421             : 
     422           0 :   UpdateAsyncCanvasRendererNow(aWrapper);
     423           0 : }
     424             : 
     425             : void
     426           0 : ImageBridgeChild::UpdateAsyncCanvasRenderer(AsyncCanvasRenderer* aWrapper)
     427             : {
     428           0 :   aWrapper->GetCanvasClient()->UpdateAsync(aWrapper);
     429             : 
     430           0 :   if (InImageBridgeChildThread()) {
     431           0 :     UpdateAsyncCanvasRendererNow(aWrapper);
     432           0 :     return;
     433             :   }
     434             : 
     435           0 :   SynchronousTask task("UpdateAsyncCanvasRenderer Lock");
     436             : 
     437           0 :   RefPtr<Runnable> runnable = WrapRunnable(
     438           0 :     RefPtr<ImageBridgeChild>(this),
     439             :     &ImageBridgeChild::UpdateAsyncCanvasRendererSync,
     440             :     &task,
     441           0 :     aWrapper);
     442           0 :   GetMessageLoop()->PostTask(runnable.forget());
     443             : 
     444           0 :   task.Wait();
     445             : }
     446             : 
     447             : void
     448           0 : ImageBridgeChild::UpdateAsyncCanvasRendererNow(AsyncCanvasRenderer* aWrapper)
     449             : {
     450           0 :   MOZ_ASSERT(aWrapper);
     451             : 
     452           0 :   if (!CanSend()) {
     453           0 :     return;
     454             :   }
     455             : 
     456           0 :   BeginTransaction();
     457           0 :   aWrapper->GetCanvasClient()->Updated();
     458           0 :   EndTransaction();
     459             : }
     460             : 
     461             : void
     462           0 : ImageBridgeChild::FlushAllImagesSync(SynchronousTask* aTask,
     463             :                                      ImageClient* aClient,
     464             :                                      ImageContainer* aContainer)
     465             : {
     466           0 :   AutoCompleteTask complete(aTask);
     467             : 
     468           0 :   if (!CanSend()) {
     469           0 :     return;
     470             :   }
     471             : 
     472           0 :   MOZ_ASSERT(aClient);
     473           0 :   BeginTransaction();
     474           0 :   if (aContainer) {
     475           0 :     aContainer->ClearImagesFromImageBridge();
     476             :   }
     477           0 :   aClient->FlushAllImages();
     478           0 :   EndTransaction();
     479             : }
     480             : 
     481             : void
     482           0 : ImageBridgeChild::FlushAllImages(ImageClient* aClient, ImageContainer* aContainer)
     483             : {
     484           0 :   MOZ_ASSERT(aClient);
     485           0 :   MOZ_ASSERT(!InImageBridgeChildThread());
     486             : 
     487           0 :   if (InImageBridgeChildThread()) {
     488           0 :     NS_ERROR("ImageBridgeChild::FlushAllImages() is called on ImageBridge thread.");
     489           0 :     return;
     490             :   }
     491             : 
     492           0 :   SynchronousTask task("FlushAllImages Lock");
     493             : 
     494             :   // RefPtrs on arguments are not needed since this dispatches synchronously.
     495           0 :   RefPtr<Runnable> runnable = WrapRunnable(
     496           0 :     RefPtr<ImageBridgeChild>(this),
     497             :     &ImageBridgeChild::FlushAllImagesSync,
     498             :     &task,
     499             :     aClient,
     500           0 :     aContainer);
     501           0 :   GetMessageLoop()->PostTask(runnable.forget());
     502             : 
     503           0 :   task.Wait();
     504             : }
     505             : 
     506             : void
     507           0 : ImageBridgeChild::BeginTransaction()
     508             : {
     509           0 :   MOZ_ASSERT(CanSend());
     510           0 :   MOZ_ASSERT(mTxn->Finished(), "uncommitted txn?");
     511           0 :   UpdateFwdTransactionId();
     512           0 :   mTxn->Begin();
     513           0 : }
     514             : 
     515             : void
     516           0 : ImageBridgeChild::EndTransaction()
     517             : {
     518           0 :   MOZ_ASSERT(CanSend());
     519           0 :   MOZ_ASSERT(!mTxn->Finished(), "forgot BeginTransaction?");
     520             : 
     521           0 :   AutoEndTransaction _(mTxn);
     522             : 
     523           0 :   if (mTxn->IsEmpty()) {
     524           0 :     return;
     525             :   }
     526             : 
     527           0 :   AutoTArray<CompositableOperation, 10> cset;
     528           0 :   cset.SetCapacity(mTxn->mOperations.size());
     529           0 :   if (!mTxn->mOperations.empty()) {
     530           0 :     cset.AppendElements(&mTxn->mOperations.front(), mTxn->mOperations.size());
     531             :   }
     532             : 
     533           0 :   if (!IsSameProcess()) {
     534           0 :     ShadowLayerForwarder::PlatformSyncBeforeUpdate();
     535             :   }
     536             : 
     537           0 :   for (ReadLockVector& locks : mTxn->mReadLocks) {
     538           0 :     if (locks.Length()) {
     539           0 :       if (!SendInitReadLocks(locks)) {
     540           0 :         NS_WARNING("[LayersForwarder] WARNING: sending read locks failed!");
     541           0 :         return;
     542             :       }
     543             :     }
     544             :   }
     545             : 
     546           0 :   if (!SendUpdate(cset, mTxn->mDestroyedActors, GetFwdTransactionId())) {
     547           0 :     NS_WARNING("could not send async texture transaction");
     548           0 :     return;
     549             :   }
     550             : }
     551             : 
     552             : void
     553           3 : ImageBridgeChild::SendImageBridgeThreadId()
     554             : {
     555           3 : }
     556             : 
     557             : bool
     558           2 : ImageBridgeChild::InitForContent(Endpoint<PImageBridgeChild>&& aEndpoint, uint32_t aNamespace)
     559             : {
     560           2 :   MOZ_ASSERT(NS_IsMainThread());
     561             : 
     562           2 :   gfxPlatform::GetPlatform();
     563             : 
     564           2 :   if (!sImageBridgeChildThread) {
     565           2 :     sImageBridgeChildThread = new Thread("ImageBridgeChild");
     566           2 :     if (!sImageBridgeChildThread->Start()) {
     567           0 :       return false;
     568             :     }
     569             :   }
     570             : 
     571           4 :   RefPtr<ImageBridgeChild> child = new ImageBridgeChild(aNamespace);
     572             : 
     573           4 :   RefPtr<Runnable> runnable = NewRunnableMethod<Endpoint<PImageBridgeChild>&&>(
     574             :     "layers::ImageBridgeChild::Bind",
     575             :     child,
     576             :     &ImageBridgeChild::Bind,
     577           6 :     Move(aEndpoint));
     578           2 :   child->GetMessageLoop()->PostTask(runnable.forget());
     579             : 
     580             :   // Assign this after so other threads can't post messages before we connect to IPDL.
     581             :   {
     582           4 :     StaticMutexAutoLock lock(sImageBridgeSingletonLock);
     583           2 :     sImageBridgeChildSingleton = child;
     584             :   }
     585             : 
     586           2 :   return true;
     587             : }
     588             : 
     589             : bool
     590           0 : ImageBridgeChild::ReinitForContent(Endpoint<PImageBridgeChild>&& aEndpoint, uint32_t aNamespace)
     591             : {
     592           0 :   MOZ_ASSERT(NS_IsMainThread());
     593             : 
     594             :   // Note that at this point, ActorDestroy may not have been called yet,
     595             :   // meaning mCanSend is still true. In this case we will try to send a
     596             :   // synchronous WillClose message to the parent, and will certainly get a
     597             :   // false result and a MsgDropped processing error. This is okay.
     598           0 :   ShutdownSingleton();
     599             : 
     600           0 :   return InitForContent(Move(aEndpoint), aNamespace);
     601             : }
     602             : 
     603             : void
     604           2 : ImageBridgeChild::Bind(Endpoint<PImageBridgeChild>&& aEndpoint)
     605             : {
     606           2 :   if (!aEndpoint.Bind(this)) {
     607           0 :     return;
     608             :   }
     609             : 
     610             :   // This reference is dropped in DeallocPImageBridgeChild.
     611           2 :   this->AddRef();
     612             : 
     613           2 :   mCanSend = true;
     614           2 :   SendImageBridgeThreadId();
     615             : }
     616             : 
     617             : void
     618           1 : ImageBridgeChild::BindSameProcess(RefPtr<ImageBridgeParent> aParent)
     619             : {
     620           1 :   MessageLoop *parentMsgLoop = aParent->GetMessageLoop();
     621           1 :   ipc::MessageChannel *parentChannel = aParent->GetIPCChannel();
     622           1 :   Open(parentChannel, parentMsgLoop, mozilla::ipc::ChildSide);
     623             : 
     624             :   // This reference is dropped in DeallocPImageBridgeChild.
     625           1 :   this->AddRef();
     626             : 
     627           1 :   mCanSend = true;
     628           1 :   SendImageBridgeThreadId();
     629           1 : }
     630             : 
     631             : /* static */ void
     632           0 : ImageBridgeChild::ShutDown()
     633             : {
     634           0 :   MOZ_ASSERT(NS_IsMainThread());
     635             : 
     636           0 :   ShutdownSingleton();
     637             : 
     638           0 :   delete sImageBridgeChildThread;
     639           0 :   sImageBridgeChildThread = nullptr;
     640           0 : }
     641             : 
     642             : /* static */ void
     643           0 : ImageBridgeChild::ShutdownSingleton()
     644             : {
     645           0 :   MOZ_ASSERT(NS_IsMainThread());
     646             : 
     647           0 :   if (RefPtr<ImageBridgeChild> child = GetSingleton()) {
     648           0 :     child->WillShutdown();
     649             : 
     650           0 :     StaticMutexAutoLock lock(sImageBridgeSingletonLock);
     651           0 :     sImageBridgeChildSingleton = nullptr;
     652             :   }
     653           0 : }
     654             : 
     655             : void
     656           0 : ImageBridgeChild::WillShutdown()
     657             : {
     658             :   {
     659           0 :     SynchronousTask task("ImageBridge ShutdownStep1 lock");
     660             : 
     661           0 :     RefPtr<Runnable> runnable = WrapRunnable(
     662           0 :       RefPtr<ImageBridgeChild>(this),
     663             :       &ImageBridgeChild::ShutdownStep1,
     664           0 :       &task);
     665           0 :     GetMessageLoop()->PostTask(runnable.forget());
     666             : 
     667           0 :     task.Wait();
     668             :   }
     669             : 
     670             :   {
     671           0 :     SynchronousTask task("ImageBridge ShutdownStep2 lock");
     672             : 
     673           0 :     RefPtr<Runnable> runnable = WrapRunnable(
     674           0 :       RefPtr<ImageBridgeChild>(this),
     675             :       &ImageBridgeChild::ShutdownStep2,
     676           0 :       &task);
     677           0 :     GetMessageLoop()->PostTask(runnable.forget());
     678             : 
     679           0 :     task.Wait();
     680             :   }
     681             : 
     682           0 :   mDestroyed = true;
     683           0 : }
     684             : 
     685             : void
     686           1 : ImageBridgeChild::InitSameProcess(uint32_t aNamespace)
     687             : {
     688           1 :   NS_ASSERTION(NS_IsMainThread(), "Should be on the main Thread!");
     689             : 
     690           1 :   MOZ_ASSERT(!sImageBridgeChildSingleton);
     691           1 :   MOZ_ASSERT(!sImageBridgeChildThread);
     692             : 
     693           1 :   sImageBridgeChildThread = new Thread("ImageBridgeChild");
     694           1 :   if (!sImageBridgeChildThread->IsRunning()) {
     695           1 :     sImageBridgeChildThread->Start();
     696             :   }
     697             : 
     698           2 :   RefPtr<ImageBridgeChild> child = new ImageBridgeChild(aNamespace);
     699           2 :   RefPtr<ImageBridgeParent> parent = ImageBridgeParent::CreateSameProcess();
     700             : 
     701           4 :   RefPtr<Runnable> runnable = WrapRunnable(
     702             :     child,
     703             :     &ImageBridgeChild::BindSameProcess,
     704           4 :     parent);
     705           1 :   child->GetMessageLoop()->PostTask(runnable.forget());
     706             : 
     707             :   // Assign this after so other threads can't post messages before we connect to IPDL.
     708             :   {
     709           2 :     StaticMutexAutoLock lock(sImageBridgeSingletonLock);
     710           1 :     sImageBridgeChildSingleton = child;
     711             :   }
     712           1 : }
     713             : 
     714             : /* static */ void
     715           0 : ImageBridgeChild::InitWithGPUProcess(Endpoint<PImageBridgeChild>&& aEndpoint, uint32_t aNamespace)
     716             : {
     717           0 :   MOZ_ASSERT(NS_IsMainThread());
     718           0 :   MOZ_ASSERT(!sImageBridgeChildSingleton);
     719           0 :   MOZ_ASSERT(!sImageBridgeChildThread);
     720             : 
     721           0 :   sImageBridgeChildThread = new Thread("ImageBridgeChild");
     722           0 :   if (!sImageBridgeChildThread->IsRunning()) {
     723           0 :     sImageBridgeChildThread->Start();
     724             :   }
     725             : 
     726           0 :   RefPtr<ImageBridgeChild> child = new ImageBridgeChild(aNamespace);
     727             : 
     728           0 :   MessageLoop* loop = child->GetMessageLoop();
     729           0 :   loop->PostTask(NewRunnableMethod<Endpoint<PImageBridgeChild>&&>(
     730             :     "layers::ImageBridgeChild::Bind",
     731             :     child,
     732             :     &ImageBridgeChild::Bind,
     733           0 :     Move(aEndpoint)));
     734             : 
     735             :   // Assign this after so other threads can't post messages before we connect to IPDL.
     736             :   {
     737           0 :     StaticMutexAutoLock lock(sImageBridgeSingletonLock);
     738           0 :     sImageBridgeChildSingleton = child;
     739             :   }
     740           0 : }
     741             : 
     742           0 : bool InImageBridgeChildThread()
     743             : {
     744           0 :   return sImageBridgeChildThread &&
     745           0 :     sImageBridgeChildThread->thread_id() == PlatformThread::CurrentId();
     746             : }
     747             : 
     748           3 : MessageLoop * ImageBridgeChild::GetMessageLoop() const
     749             : {
     750           3 :   return sImageBridgeChildThread ? sImageBridgeChildThread->message_loop() : nullptr;
     751             : }
     752             : 
     753             : /* static */ void
     754           2 : ImageBridgeChild::IdentifyCompositorTextureHost(const TextureFactoryIdentifier& aIdentifier)
     755             : {
     756           4 :   if (RefPtr<ImageBridgeChild> child = GetSingleton()) {
     757           2 :     child->IdentifyTextureHost(aIdentifier);
     758             :   }
     759           2 : }
     760             : 
     761             : RefPtr<ImageClient>
     762           0 : ImageBridgeChild::CreateImageClient(CompositableType aType,
     763             :                                     ImageContainer* aImageContainer)
     764             : {
     765           0 :   if (InImageBridgeChildThread()) {
     766           0 :     return CreateImageClientNow(aType, aImageContainer);
     767             :   }
     768             : 
     769           0 :   SynchronousTask task("CreateImageClient Lock");
     770             : 
     771           0 :   RefPtr<ImageClient> result = nullptr;
     772             : 
     773           0 :   RefPtr<Runnable> runnable = WrapRunnable(
     774           0 :     RefPtr<ImageBridgeChild>(this),
     775             :     &ImageBridgeChild::CreateImageClientSync,
     776             :     &task,
     777             :     &result,
     778             :     aType,
     779           0 :     aImageContainer);
     780           0 :   GetMessageLoop()->PostTask(runnable.forget());
     781             : 
     782           0 :   task.Wait();
     783             : 
     784           0 :   return result;
     785             : }
     786             : 
     787             : RefPtr<ImageClient>
     788           0 : ImageBridgeChild::CreateImageClientNow(CompositableType aType,
     789             :                                        ImageContainer* aImageContainer)
     790             : {
     791           0 :   MOZ_ASSERT(InImageBridgeChildThread());
     792           0 :   if (!CanSend()) {
     793           0 :     return nullptr;
     794             :   }
     795             : 
     796           0 :   RefPtr<ImageClient> client = ImageClient::CreateImageClient(aType, this, TextureFlags::NO_FLAGS);
     797           0 :   MOZ_ASSERT(client, "failed to create ImageClient");
     798           0 :   if (client) {
     799           0 :     client->Connect(aImageContainer);
     800             :   }
     801           0 :   return client;
     802             : }
     803             : 
     804             : already_AddRefed<CanvasClient>
     805           0 : ImageBridgeChild::CreateCanvasClient(CanvasClient::CanvasClientType aType,
     806             :                                      TextureFlags aFlag)
     807             : {
     808           0 :   if (InImageBridgeChildThread()) {
     809           0 :     return CreateCanvasClientNow(aType, aFlag);
     810             :   }
     811             : 
     812           0 :   SynchronousTask task("CreateCanvasClient Lock");
     813             : 
     814             :   // RefPtrs on arguments are not needed since this dispatches synchronously.
     815           0 :   RefPtr<CanvasClient> result = nullptr;
     816           0 :   RefPtr<Runnable> runnable = WrapRunnable(
     817           0 :     RefPtr<ImageBridgeChild>(this),
     818             :     &ImageBridgeChild::CreateCanvasClientSync,
     819             :     &task,
     820             :     aType,
     821             :     aFlag,
     822           0 :     &result);
     823           0 :   GetMessageLoop()->PostTask(runnable.forget());
     824             : 
     825           0 :   task.Wait();
     826             : 
     827           0 :   return result.forget();
     828             : }
     829             : 
     830             : already_AddRefed<CanvasClient>
     831           0 : ImageBridgeChild::CreateCanvasClientNow(CanvasClient::CanvasClientType aType,
     832             :                                         TextureFlags aFlag)
     833             : {
     834             :   RefPtr<CanvasClient> client
     835           0 :     = CanvasClient::CreateCanvasClient(aType, this, aFlag);
     836           0 :   MOZ_ASSERT(client, "failed to create CanvasClient");
     837           0 :   if (client) {
     838           0 :     client->Connect();
     839             :   }
     840           0 :   return client.forget();
     841             : }
     842             : 
     843             : bool
     844           0 : ImageBridgeChild::AllocUnsafeShmem(size_t aSize,
     845             :                                    ipc::SharedMemory::SharedMemoryType aType,
     846             :                                    ipc::Shmem* aShmem)
     847             : {
     848           0 :   if (!InImageBridgeChildThread()) {
     849           0 :     return DispatchAllocShmemInternal(aSize, aType, aShmem, true); // true: unsafe
     850             :   }
     851             : 
     852           0 :   if (!CanSend()) {
     853           0 :     return false;
     854             :   }
     855           0 :   return PImageBridgeChild::AllocUnsafeShmem(aSize, aType, aShmem);
     856             : }
     857             : 
     858             : bool
     859           0 : ImageBridgeChild::AllocShmem(size_t aSize,
     860             :                              ipc::SharedMemory::SharedMemoryType aType,
     861             :                              ipc::Shmem* aShmem)
     862             : {
     863           0 :   if (!InImageBridgeChildThread()) {
     864           0 :     return DispatchAllocShmemInternal(aSize, aType, aShmem, false); // false: unsafe
     865             :   }
     866             : 
     867           0 :   if (!CanSend()) {
     868           0 :     return false;
     869             :   }
     870           0 :   return PImageBridgeChild::AllocShmem(aSize, aType, aShmem);
     871             : }
     872             : 
     873             : // NewRunnableFunction accepts a limited number of parameters so we need a
     874             : // struct here
     875             : struct AllocShmemParams {
     876             :   size_t mSize;
     877             :   ipc::SharedMemory::SharedMemoryType mType;
     878             :   ipc::Shmem* mShmem;
     879             :   bool mUnsafe;
     880             :   bool mSuccess;
     881             : };
     882             : 
     883             : void
     884           0 : ImageBridgeChild::ProxyAllocShmemNow(SynchronousTask* aTask, AllocShmemParams* aParams)
     885             : {
     886           0 :   AutoCompleteTask complete(aTask);
     887             : 
     888           0 :   if (!CanSend()) {
     889           0 :     return;
     890             :   }
     891             : 
     892           0 :   bool ok = false;
     893           0 :   if (aParams->mUnsafe) {
     894           0 :     ok = AllocUnsafeShmem(aParams->mSize, aParams->mType, aParams->mShmem);
     895             :   } else {
     896           0 :     ok = AllocShmem(aParams->mSize, aParams->mType, aParams->mShmem);
     897             :   }
     898           0 :   aParams->mSuccess = ok;
     899             : }
     900             : 
     901             : bool
     902           0 : ImageBridgeChild::DispatchAllocShmemInternal(size_t aSize,
     903             :                                              SharedMemory::SharedMemoryType aType,
     904             :                                              ipc::Shmem* aShmem,
     905             :                                              bool aUnsafe)
     906             : {
     907           0 :   SynchronousTask task("AllocatorProxy alloc");
     908             : 
     909             :   AllocShmemParams params = {
     910             :     aSize, aType, aShmem, aUnsafe, false
     911           0 :   };
     912             : 
     913           0 :   RefPtr<Runnable> runnable = WrapRunnable(
     914           0 :     RefPtr<ImageBridgeChild>(this),
     915             :     &ImageBridgeChild::ProxyAllocShmemNow,
     916             :     &task,
     917           0 :     &params);
     918           0 :   GetMessageLoop()->PostTask(runnable.forget());
     919             : 
     920           0 :   task.Wait();
     921             : 
     922           0 :   return params.mSuccess;
     923             : }
     924             : 
     925             : void
     926           0 : ImageBridgeChild::ProxyDeallocShmemNow(SynchronousTask* aTask,
     927             :                                        ipc::Shmem* aShmem,
     928             :                                        bool* aResult)
     929             : {
     930           0 :   AutoCompleteTask complete(aTask);
     931             : 
     932           0 :   if (!CanSend()) {
     933           0 :     return;
     934             :   }
     935           0 :   *aResult = DeallocShmem(*aShmem);
     936             : }
     937             : 
     938             : bool
     939           0 : ImageBridgeChild::DeallocShmem(ipc::Shmem& aShmem)
     940             : {
     941           0 :   if (InImageBridgeChildThread()) {
     942           0 :     if (!CanSend()) {
     943           0 :       return false;
     944             :     }
     945           0 :     return PImageBridgeChild::DeallocShmem(aShmem);
     946             :   }
     947             : 
     948             :   // If we can't post a task, then we definitely cannot send, so there's
     949             :   // no reason to queue up this send.
     950           0 :   if (!CanPostTask()) {
     951           0 :     return false;
     952             :   }
     953             : 
     954           0 :   SynchronousTask task("AllocatorProxy Dealloc");
     955           0 :   bool result = false;
     956             : 
     957           0 :   RefPtr<Runnable> runnable = WrapRunnable(
     958           0 :     RefPtr<ImageBridgeChild>(this),
     959             :     &ImageBridgeChild::ProxyDeallocShmemNow,
     960             :     &task,
     961             :     &aShmem,
     962           0 :     &result);
     963           0 :   GetMessageLoop()->PostTask(runnable.forget());
     964             : 
     965           0 :   task.Wait();
     966           0 :   return result;
     967             : }
     968             : 
     969             : PTextureChild*
     970           0 : ImageBridgeChild::AllocPTextureChild(const SurfaceDescriptor&,
     971             :                                      const LayersBackend&,
     972             :                                      const TextureFlags&,
     973             :                                      const uint64_t& aSerial,
     974             :                                      const wr::MaybeExternalImageId& aExternalImageId)
     975             : {
     976           0 :   MOZ_ASSERT(CanSend());
     977           0 :   return TextureClient::CreateIPDLActor();
     978             : }
     979             : 
     980             : bool
     981           0 : ImageBridgeChild::DeallocPTextureChild(PTextureChild* actor)
     982             : {
     983           0 :   return TextureClient::DestroyIPDLActor(actor);
     984             : }
     985             : 
     986             : PMediaSystemResourceManagerChild*
     987           0 : ImageBridgeChild::AllocPMediaSystemResourceManagerChild()
     988             : {
     989           0 :   MOZ_ASSERT(CanSend());
     990           0 :   return new mozilla::media::MediaSystemResourceManagerChild();
     991             : }
     992             : 
     993             : bool
     994           0 : ImageBridgeChild::DeallocPMediaSystemResourceManagerChild(PMediaSystemResourceManagerChild* aActor)
     995             : {
     996           0 :   MOZ_ASSERT(aActor);
     997           0 :   delete static_cast<mozilla::media::MediaSystemResourceManagerChild*>(aActor);
     998           0 :   return true;
     999             : }
    1000             : 
    1001             : mozilla::ipc::IPCResult
    1002           0 : ImageBridgeChild::RecvParentAsyncMessages(InfallibleTArray<AsyncParentMessageData>&& aMessages)
    1003             : {
    1004           0 :   for (AsyncParentMessageArray::index_type i = 0; i < aMessages.Length(); ++i) {
    1005           0 :     const AsyncParentMessageData& message = aMessages[i];
    1006             : 
    1007           0 :     switch (message.type()) {
    1008             :       case AsyncParentMessageData::TOpNotifyNotUsed: {
    1009           0 :         const OpNotifyNotUsed& op = message.get_OpNotifyNotUsed();
    1010           0 :         NotifyNotUsed(op.TextureId(), op.fwdTransactionId());
    1011           0 :         break;
    1012             :       }
    1013             :       default:
    1014           0 :         NS_ERROR("unknown AsyncParentMessageData type");
    1015           0 :         return IPC_FAIL_NO_REASON(this);
    1016             :     }
    1017             :   }
    1018           0 :   return IPC_OK();
    1019             : }
    1020             : 
    1021             : mozilla::ipc::IPCResult
    1022           0 : ImageBridgeChild::RecvDidComposite(InfallibleTArray<ImageCompositeNotification>&& aNotifications)
    1023             : {
    1024           0 :   for (auto& n : aNotifications) {
    1025           0 :     RefPtr<ImageContainerListener> listener;
    1026             :     {
    1027           0 :       MutexAutoLock lock(mContainerMapLock);
    1028             :       ImageContainer* imageContainer;
    1029           0 :       imageContainer = mImageContainers.Get(n.compositable().Value());
    1030           0 :       if (imageContainer) {
    1031           0 :         listener = imageContainer->GetImageContainerListener();
    1032             :       }
    1033             :     }
    1034           0 :     if (listener) {
    1035           0 :       listener->NotifyComposite(n);
    1036             :     }
    1037             :   }
    1038           0 :   return IPC_OK();
    1039             : }
    1040             : 
    1041             : PTextureChild*
    1042           0 : ImageBridgeChild::CreateTexture(const SurfaceDescriptor& aSharedData,
    1043             :                                 LayersBackend aLayersBackend,
    1044             :                                 TextureFlags aFlags,
    1045             :                                 uint64_t aSerial,
    1046             :                                 wr::MaybeExternalImageId& aExternalImageId,
    1047             :                                 nsIEventTarget* aTarget)
    1048             : {
    1049           0 :   MOZ_ASSERT(CanSend());
    1050           0 :   return SendPTextureConstructor(aSharedData, aLayersBackend, aFlags, aSerial, aExternalImageId);
    1051             : }
    1052             : 
    1053             : static bool
    1054           0 : IBCAddOpDestroy(CompositableTransaction* aTxn, const OpDestroy& op)
    1055             : {
    1056           0 :   if (aTxn->Finished()) {
    1057           0 :     return false;
    1058             :   }
    1059             : 
    1060           0 :   aTxn->mDestroyedActors.AppendElement(op);
    1061           0 :   return true;
    1062             : }
    1063             : 
    1064             : bool
    1065           0 : ImageBridgeChild::DestroyInTransaction(PTextureChild* aTexture)
    1066             : {
    1067           0 :   return IBCAddOpDestroy(mTxn, OpDestroy(aTexture));
    1068             : }
    1069             : 
    1070             : bool
    1071           0 : ImageBridgeChild::DestroyInTransaction(const CompositableHandle& aHandle)
    1072             : {
    1073           0 :   return IBCAddOpDestroy(mTxn, OpDestroy(aHandle));
    1074             : }
    1075             : 
    1076             : void
    1077           0 : ImageBridgeChild::RemoveTextureFromCompositable(CompositableClient* aCompositable,
    1078             :                                                 TextureClient* aTexture)
    1079             : {
    1080           0 :   MOZ_ASSERT(CanSend());
    1081           0 :   MOZ_ASSERT(aTexture);
    1082           0 :   MOZ_ASSERT(aTexture->IsSharedWithCompositor());
    1083           0 :   MOZ_ASSERT(aCompositable->IsConnected());
    1084           0 :   if (!aTexture || !aTexture->IsSharedWithCompositor() || !aCompositable->IsConnected()) {
    1085           0 :     return;
    1086             :   }
    1087             : 
    1088           0 :   mTxn->AddNoSwapEdit(CompositableOperation(
    1089           0 :     aCompositable->GetIPCHandle(),
    1090           0 :     OpRemoveTexture(nullptr, aTexture->GetIPDLActor())));
    1091             : }
    1092             : 
    1093           0 : bool ImageBridgeChild::IsSameProcess() const
    1094             : {
    1095           0 :   return OtherPid() == base::GetCurrentProcId();
    1096             : }
    1097             : 
    1098             : bool
    1099           0 : ImageBridgeChild::CanPostTask() const
    1100             : {
    1101             :   // During shutdown, the cycle collector may free objects that are holding a
    1102             :   // reference to ImageBridgeChild. Since this happens on the main thread,
    1103             :   // ImageBridgeChild will attempt to post a task to the ImageBridge thread.
    1104             :   // However the thread manager has already been shut down, so the task cannot
    1105             :   // post.
    1106             :   //
    1107             :   // It's okay if this races. We only care about the shutdown case where
    1108             :   // everything's happening on the main thread. Even if it races outside of
    1109             :   // shutdown, it's still harmless to post the task, since the task must
    1110             :   // check CanSend().
    1111           0 :   return !mDestroyed;
    1112             : }
    1113             : 
    1114             : void
    1115           0 : ImageBridgeChild::ReleaseCompositable(const CompositableHandle& aHandle)
    1116             : {
    1117           0 :   if (!InImageBridgeChildThread()) {
    1118             :     // If we can't post a task, then we definitely cannot send, so there's
    1119             :     // no reason to queue up this send.
    1120           0 :     if (!CanPostTask()) {
    1121           0 :       return;
    1122             :     }
    1123             : 
    1124           0 :     RefPtr<Runnable> runnable = WrapRunnable(
    1125           0 :       RefPtr<ImageBridgeChild>(this),
    1126             :       &ImageBridgeChild::ReleaseCompositable,
    1127           0 :       aHandle);
    1128           0 :     GetMessageLoop()->PostTask(runnable.forget());
    1129           0 :     return;
    1130             :   }
    1131             : 
    1132           0 :   if (!CanSend()) {
    1133           0 :     return;
    1134             :   }
    1135             : 
    1136           0 :   if (!DestroyInTransaction(aHandle)) {
    1137           0 :     SendReleaseCompositable(aHandle);
    1138             :   }
    1139             : 
    1140             :   {
    1141           0 :     MutexAutoLock lock(mContainerMapLock);
    1142           0 :     mImageContainers.Remove(aHandle.Value());
    1143             :   }
    1144             : }
    1145             : 
    1146             : bool
    1147           0 : ImageBridgeChild::CanSend() const
    1148             : {
    1149           0 :   MOZ_ASSERT(InImageBridgeChildThread());
    1150           0 :   return mCanSend;
    1151             : }
    1152             : 
    1153             : void
    1154           0 : ImageBridgeChild::HandleFatalError(const char* aName, const char* aMsg) const
    1155             : {
    1156           0 :   dom::ContentChild::FatalErrorIfNotUsingGPUProcess(aName, aMsg, OtherPid());
    1157           0 : }
    1158             : 
    1159             : wr::MaybeExternalImageId
    1160           0 : ImageBridgeChild::GetNextExternalImageId()
    1161             : {
    1162             :   static uint32_t sNextID = 1;
    1163           0 :   ++sNextID;
    1164           0 :   MOZ_RELEASE_ASSERT(sNextID != UINT32_MAX);
    1165             : 
    1166           0 :   uint64_t imageId = mNamespace;
    1167           0 :   imageId = imageId << 32 | sNextID;
    1168           0 :   return Some(wr::ToExternalImageId(imageId));
    1169             : }
    1170             : 
    1171             : } // namespace layers
    1172             : } // namespace mozilla

Generated by: LCOV version 1.13