gfx/layers/ipc/ImageBridgeChild.cpp

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

     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/. */
     6 #include "ImageBridgeChild.h"
     7 #include <vector>                       // for vector
     8 #include "CompositorParent.h"           // for CompositorParent
     9 #include "ImageBridgeParent.h"          // for ImageBridgeParent
    10 #include "ImageContainer.h"             // for ImageContainer
    11 #include "Layers.h"                     // for Layer, etc
    12 #include "ShadowLayers.h"               // for ShadowLayerForwarder
    13 #include "base/message_loop.h"          // for MessageLoop
    14 #include "base/platform_thread.h"       // for PlatformThread
    15 #include "base/process.h"               // for ProcessHandle
    16 #include "base/process_util.h"          // for OpenProcessHandle
    17 #include "base/task.h"                  // for NewRunnableFunction, etc
    18 #include "base/thread.h"                // for Thread
    19 #include "base/tracked.h"               // for FROM_HERE
    20 #include "mozilla/Assertions.h"         // for MOZ_ASSERT, etc
    21 #include "mozilla/Monitor.h"            // for Monitor, MonitorAutoLock
    22 #include "mozilla/ReentrantMonitor.h"   // for ReentrantMonitor, etc
    23 #include "mozilla/ipc/MessageChannel.h" // for MessageChannel, etc
    24 #include "mozilla/ipc/Transport.h"      // for Transport
    25 #include "mozilla/gfx/Point.h"          // for IntSize
    26 #include "mozilla/layers/CompositableClient.h"  // for CompositableChild, etc
    27 #include "mozilla/layers/ISurfaceAllocator.h"  // for ISurfaceAllocator
    28 #include "mozilla/layers/ImageClient.h"  // for ImageClient
    29 #include "mozilla/layers/LayersMessages.h"  // for CompositableOperation
    30 #include "mozilla/layers/PCompositableChild.h"  // for PCompositableChild
    31 #include "mozilla/layers/TextureClient.h"  // for TextureClient
    32 #include "mozilla/mozalloc.h"           // for operator new, etc
    33 #include "nsAutoPtr.h"                  // for nsRefPtr
    34 #include "nsISupportsImpl.h"            // for ImageContainer::AddRef, etc
    35 #include "nsTArray.h"                   // for nsAutoTArray, nsTArray, etc
    36 #include "nsTArrayForwardDeclare.h"     // for AutoInfallibleTArray
    37 #include "nsThreadUtils.h"              // for NS_IsMainThread
    38 #include "nsXULAppAPI.h"                // for XRE_GetIOMessageLoop
    39 #include "mozilla/StaticPtr.h"          // for StaticRefPtr
    40 #include "mozilla/layers/TextureClient.h"
    42 struct nsIntRect;
    44 using namespace base;
    45 using namespace mozilla::ipc;
    46 using namespace mozilla::gfx;
    48 namespace mozilla {
    49 namespace ipc {
    50 class Shmem;
    51 }
    53 namespace layers {
    55 class PGrallocBufferChild;
    56 typedef std::vector<CompositableOperation> OpVector;
    58 struct CompositableTransaction
    59 {
    60   CompositableTransaction()
    61   : mSwapRequired(false)
    62   , mFinished(true)
    63   {}
    64   ~CompositableTransaction()
    65   {
    66     End();
    67   }
    68   bool Finished() const
    69   {
    70     return mFinished;
    71   }
    72   void Begin()
    73   {
    74     MOZ_ASSERT(mFinished);
    75     mFinished = false;
    76   }
    77   void End()
    78   {
    79     mFinished = true;
    80     mSwapRequired = false;
    81     mOperations.clear();
    82   }
    83   bool IsEmpty() const
    84   {
    85     return mOperations.empty();
    86   }
    87   void AddNoSwapEdit(const CompositableOperation& op)
    88   {
    89     NS_ABORT_IF_FALSE(!Finished(), "forgot BeginTransaction?");
    90     mOperations.push_back(op);
    91   }
    92   void AddEdit(const CompositableOperation& op)
    93   {
    94     AddNoSwapEdit(op);
    95     mSwapRequired = true;
    96   }
    98   OpVector mOperations;
    99   bool mSwapRequired;
   100   bool mFinished;
   101 };
   103 struct AutoEndTransaction {
   104   AutoEndTransaction(CompositableTransaction* aTxn) : mTxn(aTxn) {}
   105   ~AutoEndTransaction() { mTxn->End(); }
   106   CompositableTransaction* mTxn;
   107 };
   109 void
   110 ImageBridgeChild::UseTexture(CompositableClient* aCompositable,
   111                              TextureClient* aTexture)
   112 {
   113   MOZ_ASSERT(aCompositable);
   114   MOZ_ASSERT(aTexture);
   115   MOZ_ASSERT(aCompositable->GetIPDLActor());
   116   MOZ_ASSERT(aTexture->GetIPDLActor());
   117   mTxn->AddNoSwapEdit(OpUseTexture(nullptr, aCompositable->GetIPDLActor(),
   118                                    nullptr, aTexture->GetIPDLActor()));
   119 }
   121 void
   122 ImageBridgeChild::UseComponentAlphaTextures(CompositableClient* aCompositable,
   123                                             TextureClient* aTextureOnBlack,
   124                                             TextureClient* aTextureOnWhite)
   125 {
   126   MOZ_ASSERT(aCompositable);
   127   MOZ_ASSERT(aTextureOnWhite);
   128   MOZ_ASSERT(aTextureOnBlack);
   129   MOZ_ASSERT(aCompositable->GetIPDLActor());
   130   MOZ_ASSERT(aTextureOnWhite->GetIPDLActor());
   131   MOZ_ASSERT(aTextureOnBlack->GetIPDLActor());
   132   MOZ_ASSERT(aTextureOnBlack->GetSize() == aTextureOnWhite->GetSize());
   133   mTxn->AddNoSwapEdit(OpUseComponentAlphaTextures(nullptr, aCompositable->GetIPDLActor(),
   134                                                   nullptr, aTextureOnBlack->GetIPDLActor(),
   135                                                   nullptr, aTextureOnWhite->GetIPDLActor()));
   136 }
   138 void
   139 ImageBridgeChild::UpdatedTexture(CompositableClient* aCompositable,
   140                                  TextureClient* aTexture,
   141                                  nsIntRegion* aRegion)
   142 {
   143   MOZ_ASSERT(aCompositable);
   144   MOZ_ASSERT(aTexture);
   145   MOZ_ASSERT(aCompositable->GetIPDLActor());
   146   MOZ_ASSERT(aTexture->GetIPDLActor());
   147   MaybeRegion region = aRegion ? MaybeRegion(*aRegion)
   148                                : MaybeRegion(null_t());
   149   mTxn->AddNoSwapEdit(OpUpdateTexture(nullptr, aCompositable->GetIPDLActor(),
   150                                       nullptr, aTexture->GetIPDLActor(),
   151                                       region));
   152 }
   154 void
   155 ImageBridgeChild::UpdatePictureRect(CompositableClient* aCompositable,
   156                                     const nsIntRect& aRect)
   157 {
   158   MOZ_ASSERT(aCompositable);
   159   MOZ_ASSERT(aCompositable->GetIPDLActor());
   160   mTxn->AddNoSwapEdit(OpUpdatePictureRect(nullptr, aCompositable->GetIPDLActor(), aRect));
   161 }
   163 // Singleton
   164 static StaticRefPtr<ImageBridgeChild> sImageBridgeChildSingleton;
   165 static StaticRefPtr<ImageBridgeParent> sImageBridgeParentSingleton;
   166 static Thread *sImageBridgeChildThread = nullptr;
   168 void ReleaseImageBridgeParentSingleton() {
   169   sImageBridgeParentSingleton = nullptr;
   170 }
   172 // dispatched function
   173 static void ImageBridgeShutdownStep1(ReentrantMonitor *aBarrier, bool *aDone)
   174 {
   175   ReentrantMonitorAutoEnter autoMon(*aBarrier);
   177   NS_ABORT_IF_FALSE(InImageBridgeChildThread(),
   178                     "Should be in ImageBridgeChild thread.");
   179   if (sImageBridgeChildSingleton) {
   180     // Force all managed protocols to shut themselves down cleanly
   181     InfallibleTArray<PCompositableChild*> compositables;
   182     sImageBridgeChildSingleton->ManagedPCompositableChild(compositables);
   183     for (int i = compositables.Length() - 1; i >= 0; --i) {
   184       CompositableClient::FromIPDLActor(compositables[i])->Destroy();
   185     }
   186     InfallibleTArray<PTextureChild*> textures;
   187     sImageBridgeChildSingleton->ManagedPTextureChild(textures);
   188     for (int i = textures.Length() - 1; i >= 0; --i) {
   189       TextureClient::AsTextureClient(textures[i])->ForceRemove();
   190     }
   191     sImageBridgeChildSingleton->SendWillStop();
   192     sImageBridgeChildSingleton->MarkShutDown();
   193     // From now on, no message can be sent through the image bridge from the
   194     // client side except the final Stop message.
   195   }
   196   *aDone = true;
   197   aBarrier->NotifyAll();
   198 }
   200 // dispatched function
   201 static void ImageBridgeShutdownStep2(ReentrantMonitor *aBarrier, bool *aDone)
   202 {
   203   ReentrantMonitorAutoEnter autoMon(*aBarrier);
   205   NS_ABORT_IF_FALSE(InImageBridgeChildThread(),
   206                     "Should be in ImageBridgeChild thread.");
   208   sImageBridgeChildSingleton->SendStop();
   210   sImageBridgeChildSingleton = nullptr;
   212   *aDone = true;
   213   aBarrier->NotifyAll();
   214 }
   216 // dispatched function
   217 static void CreateImageClientSync(RefPtr<ImageClient>* result,
   218                                   ReentrantMonitor* barrier,
   219                                   CompositableType aType,
   220                                   bool *aDone)
   221 {
   222   ReentrantMonitorAutoEnter autoMon(*barrier);
   223   *result = sImageBridgeChildSingleton->CreateImageClientNow(aType);
   224   *aDone = true;
   225   barrier->NotifyAll();
   226 }
   229 struct GrallocParam {
   230   IntSize size;
   231   uint32_t format;
   232   uint32_t usage;
   233   MaybeMagicGrallocBufferHandle* handle;
   234   PGrallocBufferChild** child;
   236   GrallocParam(const IntSize& aSize,
   237                const uint32_t& aFormat,
   238                const uint32_t& aUsage,
   239                MaybeMagicGrallocBufferHandle* aHandle,
   240                PGrallocBufferChild** aChild)
   241     : size(aSize)
   242     , format(aFormat)
   243     , usage(aUsage)
   244     , handle(aHandle)
   245     , child(aChild)
   246   {}
   247 };
   249 // dispatched function
   250 static void AllocGrallocBufferSync(const GrallocParam& aParam,
   251                                    Monitor* aBarrier,
   252                                    bool* aDone)
   253 {
   254   MonitorAutoLock autoMon(*aBarrier);
   256   sImageBridgeChildSingleton->AllocGrallocBufferNow(aParam.size,
   257                                                     aParam.format,
   258                                                     aParam.usage,
   259                                                     aParam.handle,
   260                                                     aParam.child);
   261   *aDone = true;
   262   aBarrier->NotifyAll();
   263 }
   265 // dispatched function
   266 static void ConnectImageBridge(ImageBridgeChild * child, ImageBridgeParent * parent)
   267 {
   268   MessageLoop *parentMsgLoop = parent->GetMessageLoop();
   269   ipc::MessageChannel *parentChannel = parent->GetIPCChannel();
   270   child->Open(parentChannel, parentMsgLoop, mozilla::ipc::ChildSide);
   271 }
   273 ImageBridgeChild::ImageBridgeChild()
   274   : mShuttingDown(false)
   275 {
   276   mTxn = new CompositableTransaction();
   277 }
   278 ImageBridgeChild::~ImageBridgeChild()
   279 {
   280   delete mTxn;
   281 }
   283 void
   284 ImageBridgeChild::MarkShutDown()
   285 {
   286   MOZ_ASSERT(!mShuttingDown);
   287   mShuttingDown = true;
   288 }
   290 void
   291 ImageBridgeChild::Connect(CompositableClient* aCompositable)
   292 {
   293   MOZ_ASSERT(aCompositable);
   294   MOZ_ASSERT(!mShuttingDown);
   295   uint64_t id = 0;
   296   PCompositableChild* child =
   297     SendPCompositableConstructor(aCompositable->GetTextureInfo(), &id);
   298   MOZ_ASSERT(child);
   299   aCompositable->InitIPDLActor(child, id);
   300 }
   302 PCompositableChild*
   303 ImageBridgeChild::AllocPCompositableChild(const TextureInfo& aInfo, uint64_t* aID)
   304 {
   305   MOZ_ASSERT(!mShuttingDown);
   306   return CompositableClient::CreateIPDLActor();
   307 }
   309 bool
   310 ImageBridgeChild::DeallocPCompositableChild(PCompositableChild* aActor)
   311 {
   312   return CompositableClient::DestroyIPDLActor(aActor);
   313 }
   316 Thread* ImageBridgeChild::GetThread() const
   317 {
   318   return sImageBridgeChildThread;
   319 }
   321 ImageBridgeChild* ImageBridgeChild::GetSingleton()
   322 {
   323   return sImageBridgeChildSingleton;
   324 }
   326 bool ImageBridgeChild::IsCreated()
   327 {
   328   return GetSingleton() != nullptr;
   329 }
   331 void ImageBridgeChild::StartUp()
   332 {
   333   NS_ASSERTION(NS_IsMainThread(), "Should be on the main Thread!");
   334   ImageBridgeChild::StartUpOnThread(new Thread("ImageBridgeChild"));
   335 }
   337 #ifdef MOZ_NUWA_PROCESS
   338 #include "ipc/Nuwa.h"
   339 #endif
   341 static void
   342 ConnectImageBridgeInChildProcess(Transport* aTransport,
   343                                  ProcessHandle aOtherProcess)
   344 {
   345   // Bind the IPC channel to the image bridge thread.
   346   sImageBridgeChildSingleton->Open(aTransport, aOtherProcess,
   347                                    XRE_GetIOMessageLoop(),
   348                                    ipc::ChildSide);
   349 #ifdef MOZ_NUWA_PROCESS
   350   if (IsNuwaProcess()) {
   351     sImageBridgeChildThread
   352       ->message_loop()->PostTask(FROM_HERE,
   353                                  NewRunnableFunction(NuwaMarkCurrentThread,
   354                                                      (void (*)(void *))nullptr,
   355                                                      (void *)nullptr));
   356   }
   357 #endif
   358 }
   360 static void ReleaseImageClientNow(ImageClient* aClient)
   361 {
   362   MOZ_ASSERT(InImageBridgeChildThread());
   363   aClient->Release();
   364 }
   366 // static
   367 void ImageBridgeChild::DispatchReleaseImageClient(ImageClient* aClient)
   368 {
   369   if (!IsCreated()) {
   370     // CompositableClient::Release should normally happen in the ImageBridgeChild
   371     // thread because it usually generate some IPDL messages.
   372     // However, if we take this branch it means that the ImageBridgeChild
   373     // has already shut down, along with the CompositableChild, which means no
   374     // message will be sent and it is safe to run this code from any thread.
   375     MOZ_ASSERT(aClient->GetIPDLActor() == nullptr);
   376     aClient->Release();
   377     return;
   378   }
   380   sImageBridgeChildSingleton->GetMessageLoop()->PostTask(
   381     FROM_HERE,
   382     NewRunnableFunction(&ReleaseImageClientNow, aClient));
   383 }
   385 static void ReleaseTextureClientNow(TextureClient* aClient)
   386 {
   387   MOZ_ASSERT(InImageBridgeChildThread());
   388   aClient->Release();
   389 }
   391 // static
   392 void ImageBridgeChild::DispatchReleaseTextureClient(TextureClient* aClient)
   393 {
   394   if (!IsCreated()) {
   395     // TextureClient::Release should normally happen in the ImageBridgeChild
   396     // thread because it usually generate some IPDL messages.
   397     // However, if we take this branch it means that the ImageBridgeChild
   398     // has already shut down, along with the TextureChild, which means no
   399     // message will be sent and it is safe to run this code from any thread.
   400     MOZ_ASSERT(aClient->GetIPDLActor() == nullptr);
   401     aClient->Release();
   402     return;
   403   }
   405   sImageBridgeChildSingleton->GetMessageLoop()->PostTask(
   406     FROM_HERE,
   407     NewRunnableFunction(&ReleaseTextureClientNow, aClient));
   408 }
   410 static void UpdateImageClientNow(ImageClient* aClient, ImageContainer* aContainer)
   411 {
   412   MOZ_ASSERT(aClient);
   413   MOZ_ASSERT(aContainer);
   414   sImageBridgeChildSingleton->BeginTransaction();
   415   aClient->UpdateImage(aContainer, Layer::CONTENT_OPAQUE);
   416   aClient->OnTransaction();
   417   sImageBridgeChildSingleton->EndTransaction();
   418 }
   420 //static
   421 void ImageBridgeChild::DispatchImageClientUpdate(ImageClient* aClient,
   422                                                  ImageContainer* aContainer)
   423 {
   424   if (!IsCreated()) {
   425     return;
   426   }
   428   if (InImageBridgeChildThread()) {
   429     UpdateImageClientNow(aClient, aContainer);
   430     return;
   431   }
   432   sImageBridgeChildSingleton->GetMessageLoop()->PostTask(
   433     FROM_HERE,
   434     NewRunnableFunction<
   435       void (*)(ImageClient*, ImageContainer*),
   436       ImageClient*,
   437       nsRefPtr<ImageContainer> >(&UpdateImageClientNow, aClient, aContainer));
   438 }
   440 static void FlushAllImagesSync(ImageClient* aClient, ImageContainer* aContainer, bool aExceptFront, ReentrantMonitor* aBarrier, bool* aDone)
   441 {
   442   ImageBridgeChild::FlushAllImagesNow(aClient, aContainer, aExceptFront);
   444   ReentrantMonitorAutoEnter autoMon(*aBarrier);
   445   *aDone = true;
   446   aBarrier->NotifyAll();
   447 }
   449 //static
   450 void ImageBridgeChild::FlushAllImages(ImageClient* aClient, ImageContainer* aContainer, bool aExceptFront)
   451 {
   452  if (!IsCreated()) {
   453     return;
   454   }
   456   MOZ_ASSERT(!sImageBridgeChildSingleton->mShuttingDown);
   458   if (InImageBridgeChildThread()) {
   459     FlushAllImagesNow(aClient, aContainer, aExceptFront);
   460     return;
   461   }
   463   ReentrantMonitor barrier("CreateImageClient Lock");
   464   ReentrantMonitorAutoEnter autoMon(barrier);
   465   bool done = false;
   467   sImageBridgeChildSingleton->GetMessageLoop()->PostTask(
   468     FROM_HERE,
   469     NewRunnableFunction(&FlushAllImagesSync, aClient, aContainer, aExceptFront, &barrier, &done));
   471   // should stop the thread until the ImageClient has been created on
   472   // the other thread
   473   while (!done) {
   474     barrier.Wait();
   475   }
   476 }
   478 //static
   479 void ImageBridgeChild::FlushAllImagesNow(ImageClient* aClient, ImageContainer* aContainer, bool aExceptFront)
   480 {
   481   MOZ_ASSERT(aClient);
   482   sImageBridgeChildSingleton->BeginTransaction();
   483   if (aContainer && !aExceptFront) {
   484     aContainer->ClearCurrentImage();
   485   }
   486   aClient->FlushAllImages(aExceptFront);
   487   aClient->OnTransaction();
   488   sImageBridgeChildSingleton->EndTransaction();
   489 }
   491 void
   492 ImageBridgeChild::BeginTransaction()
   493 {
   494   MOZ_ASSERT(!mShuttingDown);
   495   MOZ_ASSERT(mTxn->Finished(), "uncommitted txn?");
   496   mTxn->Begin();
   497 }
   499 class MOZ_STACK_CLASS AutoRemoveTextures
   500 {
   501 public:
   502   AutoRemoveTextures(ImageBridgeChild* aImageBridge)
   503     : mImageBridge(aImageBridge) {}
   505   ~AutoRemoveTextures()
   506   {
   507     mImageBridge->RemoveTexturesIfNecessary();
   508   }
   509 private:
   510   ImageBridgeChild* mImageBridge;
   511 };
   513 void
   514 ImageBridgeChild::EndTransaction()
   515 {
   516   MOZ_ASSERT(!mShuttingDown);
   517   MOZ_ASSERT(!mTxn->Finished(), "forgot BeginTransaction?");
   519   AutoEndTransaction _(mTxn);
   520   AutoRemoveTextures autoRemoveTextures(this);
   522   if (mTxn->IsEmpty()) {
   523     return;
   524   }
   526   AutoInfallibleTArray<CompositableOperation, 10> cset;
   527   cset.SetCapacity(mTxn->mOperations.size());
   528   if (!mTxn->mOperations.empty()) {
   529     cset.AppendElements(&mTxn->mOperations.front(), mTxn->mOperations.size());
   530   }
   531   ShadowLayerForwarder::PlatformSyncBeforeUpdate();
   533   AutoInfallibleTArray<EditReply, 10> replies;
   535   if (mTxn->mSwapRequired) {
   536     if (!SendUpdate(cset, &replies)) {
   537       NS_WARNING("could not send async texture transaction");
   538       return;
   539     }
   540   } else {
   541     // If we don't require a swap we can call SendUpdateNoSwap which
   542     // assumes that aReplies is empty (DEBUG assertion)
   543     if (!SendUpdateNoSwap(cset)) {
   544       NS_WARNING("could not send async texture transaction (no swap)");
   545       return;
   546     }
   547   }
   548   for (nsTArray<EditReply>::size_type i = 0; i < replies.Length(); ++i) {
   549     const EditReply& reply = replies[i];
   550     switch (reply.type()) {
   551     case EditReply::TOpTextureSwap: {
   552       const OpTextureSwap& ots = reply.get_OpTextureSwap();
   554       CompositableClient* compositable =
   555         CompositableClient::FromIPDLActor(ots.compositableChild());
   557       MOZ_ASSERT(compositable);
   559       compositable->SetDescriptorFromReply(ots.textureId(), ots.image());
   560       break;
   561     }
   562     case EditReply::TReturnReleaseFence: {
   563       const ReturnReleaseFence& rep = reply.get_ReturnReleaseFence();
   564       FenceHandle fence = rep.fence();
   565       PTextureChild* child = rep.textureChild();
   567       if (!fence.IsValid() || !child) {
   568         break;
   569       }
   570       RefPtr<TextureClient> texture = TextureClient::AsTextureClient(child);
   571       if (texture) {
   572         texture->SetReleaseFenceHandle(fence);
   573       }
   574       break;
   575     }
   576     default:
   577       NS_RUNTIMEABORT("not reached");
   578     }
   579   }
   580 }
   583 PImageBridgeChild*
   584 ImageBridgeChild::StartUpInChildProcess(Transport* aTransport,
   585                                         ProcessId aOtherProcess)
   586 {
   587   NS_ASSERTION(NS_IsMainThread(), "Should be on the main Thread!");
   589   ProcessHandle processHandle;
   590   if (!base::OpenProcessHandle(aOtherProcess, &processHandle)) {
   591     return nullptr;
   592   }
   594   sImageBridgeChildThread = new Thread("ImageBridgeChild");
   595   if (!sImageBridgeChildThread->Start()) {
   596     return nullptr;
   597   }
   599   sImageBridgeChildSingleton = new ImageBridgeChild();
   600   sImageBridgeChildSingleton->GetMessageLoop()->PostTask(
   601     FROM_HERE,
   602     NewRunnableFunction(ConnectImageBridgeInChildProcess,
   603                         aTransport, processHandle));
   605   return sImageBridgeChildSingleton;
   606 }
   608 void ImageBridgeChild::ShutDown()
   609 {
   610   MOZ_ASSERT(NS_IsMainThread(), "Should be on the main Thread!");
   611   if (ImageBridgeChild::IsCreated()) {
   612     MOZ_ASSERT(!sImageBridgeChildSingleton->mShuttingDown);
   614     {
   615       ReentrantMonitor barrier("ImageBridge ShutdownStep1 lock");
   616       ReentrantMonitorAutoEnter autoMon(barrier);
   618       bool done = false;
   619       sImageBridgeChildSingleton->GetMessageLoop()->PostTask(FROM_HERE,
   620                       NewRunnableFunction(&ImageBridgeShutdownStep1, &barrier, &done));
   621       while (!done) {
   622         barrier.Wait();
   623       }
   624     }
   626     {
   627       ReentrantMonitor barrier("ImageBridge ShutdownStep2 lock");
   628       ReentrantMonitorAutoEnter autoMon(barrier);
   630       bool done = false;
   631       sImageBridgeChildSingleton->GetMessageLoop()->PostTask(FROM_HERE,
   632                       NewRunnableFunction(&ImageBridgeShutdownStep2, &barrier, &done));
   633       while (!done) {
   634         barrier.Wait();
   635       }
   636     }
   638     delete sImageBridgeChildThread;
   639     sImageBridgeChildThread = nullptr;
   640   }
   641 }
   643 bool ImageBridgeChild::StartUpOnThread(Thread* aThread)
   644 {
   645   NS_ABORT_IF_FALSE(aThread, "ImageBridge needs a thread.");
   646   if (sImageBridgeChildSingleton == nullptr) {
   647     sImageBridgeChildThread = aThread;
   648     if (!aThread->IsRunning()) {
   649       aThread->Start();
   650     }
   651     sImageBridgeChildSingleton = new ImageBridgeChild();
   652     sImageBridgeParentSingleton = new ImageBridgeParent(
   653       CompositorParent::CompositorLoop(), nullptr);
   654     sImageBridgeChildSingleton->ConnectAsync(sImageBridgeParentSingleton);
   655     return true;
   656   } else {
   657     return false;
   658   }
   659 }
   661 bool InImageBridgeChildThread()
   662 {
   663   return sImageBridgeChildThread->thread_id() == PlatformThread::CurrentId();
   664 }
   666 MessageLoop * ImageBridgeChild::GetMessageLoop() const
   667 {
   668   return sImageBridgeChildThread->message_loop();
   669 }
   671 void ImageBridgeChild::ConnectAsync(ImageBridgeParent* aParent)
   672 {
   673   GetMessageLoop()->PostTask(FROM_HERE, NewRunnableFunction(&ConnectImageBridge,
   674                                                             this, aParent));
   675 }
   677 void
   678 ImageBridgeChild::IdentifyCompositorTextureHost(const TextureFactoryIdentifier& aIdentifier)
   679 {
   680   if (sImageBridgeChildSingleton) {
   681     sImageBridgeChildSingleton->IdentifyTextureHost(aIdentifier);
   682   }
   683 }
   685 TemporaryRef<ImageClient>
   686 ImageBridgeChild::CreateImageClient(CompositableType aType)
   687 {
   688   if (InImageBridgeChildThread()) {
   689     return CreateImageClientNow(aType);
   690   }
   691   ReentrantMonitor barrier("CreateImageClient Lock");
   692   ReentrantMonitorAutoEnter autoMon(barrier);
   693   bool done = false;
   695   RefPtr<ImageClient> result = nullptr;
   696   GetMessageLoop()->PostTask(FROM_HERE, NewRunnableFunction(&CreateImageClientSync,
   697                                                             &result, &barrier, aType, &done));
   698   // should stop the thread until the ImageClient has been created on
   699   // the other thread
   700   while (!done) {
   701     barrier.Wait();
   702   }
   703   return result.forget();
   704 }
   706 TemporaryRef<ImageClient>
   707 ImageBridgeChild::CreateImageClientNow(CompositableType aType)
   708 {
   709   MOZ_ASSERT(!sImageBridgeChildSingleton->mShuttingDown);
   710   RefPtr<ImageClient> client
   711     = ImageClient::CreateImageClient(aType, this, 0);
   712   MOZ_ASSERT(client, "failed to create ImageClient");
   713   if (client) {
   714     client->Connect();
   715   }
   716   return client.forget();
   717 }
   719 PGrallocBufferChild*
   720 ImageBridgeChild::AllocPGrallocBufferChild(const IntSize&, const uint32_t&, const uint32_t&,
   721                                            MaybeMagicGrallocBufferHandle*)
   722 {
   723 #ifdef MOZ_HAVE_SURFACEDESCRIPTORGRALLOC
   724   return GrallocBufferActor::Create();
   725 #else
   726   NS_RUNTIMEABORT("No gralloc buffers for you");
   727   return nullptr;
   728 #endif
   729 }
   731 bool
   732 ImageBridgeChild::DeallocPGrallocBufferChild(PGrallocBufferChild* actor)
   733 {
   734 #ifdef MOZ_HAVE_SURFACEDESCRIPTORGRALLOC
   735   delete actor;
   736   return true;
   737 #else
   738   NS_RUNTIMEABORT("Um, how did we get here?");
   739   return false;
   740 #endif
   741 }
   743 bool
   744 ImageBridgeChild::AllocUnsafeShmem(size_t aSize,
   745                                    ipc::SharedMemory::SharedMemoryType aType,
   746                                    ipc::Shmem* aShmem)
   747 {
   748   MOZ_ASSERT(!mShuttingDown);
   749   if (InImageBridgeChildThread()) {
   750     return PImageBridgeChild::AllocUnsafeShmem(aSize, aType, aShmem);
   751   } else {
   752     return DispatchAllocShmemInternal(aSize, aType, aShmem, true); // true: unsafe
   753   }
   754 }
   756 bool
   757 ImageBridgeChild::AllocShmem(size_t aSize,
   758                              ipc::SharedMemory::SharedMemoryType aType,
   759                              ipc::Shmem* aShmem)
   760 {
   761   if (InImageBridgeChildThread()) {
   762     return PImageBridgeChild::AllocShmem(aSize, aType, aShmem);
   763   } else {
   764     return DispatchAllocShmemInternal(aSize, aType, aShmem, false); // false: unsafe
   765   }
   766 }
   768 // NewRunnableFunction accepts a limited number of parameters so we need a
   769 // struct here
   770 struct AllocShmemParams {
   771   RefPtr<ISurfaceAllocator> mAllocator;
   772   size_t mSize;
   773   ipc::SharedMemory::SharedMemoryType mType;
   774   ipc::Shmem* mShmem;
   775   bool mUnsafe;
   776   bool mSuccess;
   777 };
   779 static void ProxyAllocShmemNow(AllocShmemParams* aParams,
   780                                ReentrantMonitor* aBarrier,
   781                                bool* aDone)
   782 {
   783   MOZ_ASSERT(aParams);
   784   MOZ_ASSERT(aDone);
   785   MOZ_ASSERT(aBarrier);
   787   if (aParams->mUnsafe) {
   788     aParams->mSuccess = aParams->mAllocator->AllocUnsafeShmem(aParams->mSize,
   789                                                               aParams->mType,
   790                                                               aParams->mShmem);
   791   } else {
   792     aParams->mSuccess = aParams->mAllocator->AllocShmem(aParams->mSize,
   793                                                         aParams->mType,
   794                                                         aParams->mShmem);
   795   }
   797   ReentrantMonitorAutoEnter autoMon(*aBarrier);
   798   *aDone = true;
   799   aBarrier->NotifyAll();
   800 }
   802 bool
   803 ImageBridgeChild::DispatchAllocShmemInternal(size_t aSize,
   804                                              SharedMemory::SharedMemoryType aType,
   805                                              ipc::Shmem* aShmem,
   806                                              bool aUnsafe)
   807 {
   808   ReentrantMonitor barrier("AllocatorProxy alloc");
   809   ReentrantMonitorAutoEnter autoMon(barrier);
   811   AllocShmemParams params = {
   812     this, aSize, aType, aShmem, aUnsafe, true
   813   };
   814   bool done = false;
   816   GetMessageLoop()->PostTask(FROM_HERE,
   817                              NewRunnableFunction(&ProxyAllocShmemNow,
   818                                                  &params,
   819                                                  &barrier,
   820                                                  &done));
   821   while (!done) {
   822     barrier.Wait();
   823   }
   824   return params.mSuccess;
   825 }
   827 static void ProxyDeallocShmemNow(ISurfaceAllocator* aAllocator,
   828                                  ipc::Shmem* aShmem,
   829                                  ReentrantMonitor* aBarrier,
   830                                  bool* aDone)
   831 {
   832   MOZ_ASSERT(aShmem);
   833   MOZ_ASSERT(aDone);
   834   MOZ_ASSERT(aBarrier);
   836   aAllocator->DeallocShmem(*aShmem);
   838   ReentrantMonitorAutoEnter autoMon(*aBarrier);
   839   *aDone = true;
   840   aBarrier->NotifyAll();
   841 }
   843 void
   844 ImageBridgeChild::DeallocShmem(ipc::Shmem& aShmem)
   845 {
   846   if (InImageBridgeChildThread()) {
   847     PImageBridgeChild::DeallocShmem(aShmem);
   848   } else {
   849     ReentrantMonitor barrier("AllocatorProxy Dealloc");
   850     ReentrantMonitorAutoEnter autoMon(barrier);
   852     bool done = false;
   853     GetMessageLoop()->PostTask(FROM_HERE,
   854                                NewRunnableFunction(&ProxyDeallocShmemNow,
   855                                                    this,
   856                                                    &aShmem,
   857                                                    &barrier,
   858                                                    &done));
   859     while (!done) {
   860       barrier.Wait();
   861     }
   862   }
   863 }
   865 PGrallocBufferChild*
   866 ImageBridgeChild::AllocGrallocBuffer(const IntSize& aSize,
   867                                      uint32_t aFormat,
   868                                      uint32_t aUsage,
   869                                      MaybeMagicGrallocBufferHandle* aHandle)
   870 {
   871   if (InImageBridgeChildThread()) {
   872     PGrallocBufferChild* child = nullptr;
   873     ImageBridgeChild::AllocGrallocBufferNow(aSize, aFormat, aUsage, aHandle, &child);
   874     return child;
   875   }
   877   Monitor barrier("AllocGrallocBuffer Lock");
   878   MonitorAutoLock autoMon(barrier);
   879   bool done = false;
   880   PGrallocBufferChild* child = nullptr;
   882   GetMessageLoop()->PostTask(
   883     FROM_HERE,
   884     NewRunnableFunction(&AllocGrallocBufferSync,
   885                         GrallocParam(aSize, aFormat, aUsage, aHandle, &child), &barrier, &done));
   887   while (!done) {
   888     barrier.Wait();
   889   }
   891   return child;
   892 }
   894 void
   895 ImageBridgeChild::AllocGrallocBufferNow(const gfx::IntSize& aSize,
   896                                         uint32_t aFormat, uint32_t aUsage,
   897                                         MaybeMagicGrallocBufferHandle* aHandle,
   898                                         PGrallocBufferChild** aChild)
   899 {
   900 #ifdef MOZ_WIDGET_GONK
   901   *aChild = SendPGrallocBufferConstructor(aSize,
   902                                           aFormat,
   903                                           aUsage,
   904                                           aHandle);
   905 #else
   906   NS_RUNTIMEABORT("not implemented");
   907   aChild = nullptr;
   908 #endif
   909 }
   911 static void ProxyDeallocGrallocBufferNow(ISurfaceAllocator* aAllocator,
   912                                          PGrallocBufferChild* aChild,
   913                                          ReentrantMonitor* aBarrier,
   914                                          bool* aDone)
   915 {
   916   MOZ_ASSERT(aChild);
   917   MOZ_ASSERT(aDone);
   918   MOZ_ASSERT(aBarrier);
   920 #ifdef MOZ_WIDGET_GONK
   921   PGrallocBufferChild::Send__delete__(aChild);
   922 #else
   923   NS_RUNTIMEABORT("not implemented");
   924 #endif
   926   ReentrantMonitorAutoEnter autoMon(*aBarrier);
   927   *aDone = true;
   928   aBarrier->NotifyAll();
   929 }
   931 void
   932 ImageBridgeChild::DeallocGrallocBuffer(PGrallocBufferChild* aChild)
   933 {
   934   MOZ_ASSERT(aChild);
   935   if (InImageBridgeChildThread()) {
   936 #ifdef MOZ_WIDGET_GONK
   937     PGrallocBufferChild::Send__delete__(aChild);
   938 #else
   939     NS_RUNTIMEABORT("not implemented");
   940 #endif
   941   } else {
   942     ReentrantMonitor barrier("AllocatorProxy Dealloc");
   943     ReentrantMonitorAutoEnter autoMon(barrier);
   945     bool done = false;
   946     GetMessageLoop()->PostTask(FROM_HERE,
   947                                NewRunnableFunction(&ProxyDeallocGrallocBufferNow,
   948                                                    this,
   949                                                    aChild,
   950                                                    &barrier,
   951                                                    &done));
   952     while (!done) {
   953       barrier.Wait();
   954     }
   955   }
   956 }
   958 PTextureChild*
   959 ImageBridgeChild::AllocPTextureChild(const SurfaceDescriptor&,
   960                                      const TextureFlags&)
   961 {
   962   MOZ_ASSERT(!mShuttingDown);
   963   return TextureClient::CreateIPDLActor();
   964 }
   966 bool
   967 ImageBridgeChild::DeallocPTextureChild(PTextureChild* actor)
   968 {
   969   return TextureClient::DestroyIPDLActor(actor);
   970 }
   972 PTextureChild*
   973 ImageBridgeChild::CreateTexture(const SurfaceDescriptor& aSharedData,
   974                                 TextureFlags aFlags)
   975 {
   976   MOZ_ASSERT(!mShuttingDown);
   977   return SendPTextureConstructor(aSharedData, aFlags);
   978 }
   980 void
   981 ImageBridgeChild::RemoveTextureFromCompositable(CompositableClient* aCompositable,
   982                                                 TextureClient* aTexture)
   983 {
   984   MOZ_ASSERT(!mShuttingDown);
   985   if (aTexture->GetFlags() & TEXTURE_DEALLOCATE_CLIENT) {
   986     mTxn->AddEdit(OpRemoveTexture(nullptr, aCompositable->GetIPDLActor(),
   987                                   nullptr, aTexture->GetIPDLActor()));
   988   } else {
   989     mTxn->AddNoSwapEdit(OpRemoveTexture(nullptr, aCompositable->GetIPDLActor(),
   990                                         nullptr, aTexture->GetIPDLActor()));
   991   }
   992   // Hold texture until transaction complete.
   993   HoldUntilTransaction(aTexture);
   994 }
   996 static void RemoveTextureSync(TextureClient* aTexture, ReentrantMonitor* aBarrier, bool* aDone)
   997 {
   998   aTexture->ForceRemove();
  1000   ReentrantMonitorAutoEnter autoMon(*aBarrier);
  1001   *aDone = true;
  1002   aBarrier->NotifyAll();
  1005 void ImageBridgeChild::RemoveTexture(TextureClient* aTexture)
  1007   if (InImageBridgeChildThread()) {
  1008     MOZ_ASSERT(!mShuttingDown);
  1009     aTexture->ForceRemove();
  1010     return;
  1013   ReentrantMonitor barrier("RemoveTexture Lock");
  1014   ReentrantMonitorAutoEnter autoMon(barrier);
  1015   bool done = false;
  1017   sImageBridgeChildSingleton->GetMessageLoop()->PostTask(
  1018     FROM_HERE,
  1019     NewRunnableFunction(&RemoveTextureSync, aTexture, &barrier, &done));
  1021   // should stop the thread until the ImageClient has been created on
  1022   // the other thread
  1023   while (!done) {
  1024     barrier.Wait();
  1028 bool ImageBridgeChild::IsSameProcess() const
  1030   return OtherProcess() == ipc::kInvalidProcessHandle;
  1033 } // layers
  1034 } // mozilla

mercurial