Link Compositables via IDs instead of actors. (bug 1323957 part 4, r=mattwoodrow)
authorDavid Anderson <dvander@alliedmods.net>
Tue, 17 Jan 2017 18:47:06 -0800
changeset 374772 58db09989d0509a721ad4ae60c24753fba767716
parent 374771 d531b1b53676413afd775208c3cb67c062838a8d
child 374773 4704ac96489ac410b8be58336ebb6225d1f19afb
push id6996
push userjlorenzo@mozilla.com
push dateMon, 06 Mar 2017 20:48:21 +0000
treeherdermozilla-beta@d89512dab048 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmattwoodrow
bugs1323957
milestone53.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Link Compositables via IDs instead of actors. (bug 1323957 part 4, r=mattwoodrow)
gfx/layers/client/ClientPaintedLayer.cpp
gfx/layers/client/CompositableChild.cpp
gfx/layers/client/CompositableClient.cpp
gfx/layers/client/CompositableClient.h
gfx/layers/composite/CompositableHost.cpp
gfx/layers/composite/CompositableHost.h
gfx/layers/ipc/CompositableForwarder.cpp
gfx/layers/ipc/CompositableForwarder.h
gfx/layers/ipc/CompositableTransactionParent.cpp
gfx/layers/ipc/CompositableTransactionParent.h
gfx/layers/ipc/ImageBridgeChild.cpp
gfx/layers/ipc/ImageBridgeChild.h
gfx/layers/ipc/ImageBridgeParent.cpp
gfx/layers/ipc/ImageBridgeParent.h
gfx/layers/ipc/LayerTransactionChild.cpp
gfx/layers/ipc/LayerTransactionChild.h
gfx/layers/ipc/LayerTransactionParent.cpp
gfx/layers/ipc/LayerTransactionParent.h
gfx/layers/ipc/LayersMessages.ipdlh
gfx/layers/ipc/PCompositable.ipdl
gfx/layers/ipc/PImageBridge.ipdl
gfx/layers/ipc/PLayerTransaction.ipdl
gfx/layers/ipc/ShadowLayers.cpp
gfx/layers/ipc/ShadowLayers.h
--- a/gfx/layers/client/ClientPaintedLayer.cpp
+++ b/gfx/layers/client/ClientPaintedLayer.cpp
@@ -94,17 +94,17 @@ ClientPaintedLayer::PaintThebes()
   }
 
   if (didUpdate) {
     Mutated();
 
     mValidRegion.Or(mValidRegion, state.mRegionToDraw);
 
     ContentClientRemote* contentClientRemote = static_cast<ContentClientRemote*>(mContentClient.get());
-    MOZ_ASSERT(contentClientRemote->GetIPDLActor());
+    MOZ_ASSERT(contentClientRemote->GetIPCHandle());
 
     // Hold(this) ensures this layer is kept alive through the current transaction
     // The ContentClient assumes this layer is kept alive (e.g., in CreateBuffer),
     // so deleting this Hold for whatever reason will break things.
     ClientManager()->Hold(this);
     contentClientRemote->Updated(state.mRegionToDraw,
                                  mVisibleRegion.ToUnknownRegion(),
                                  state.mDidSelfCopy);
--- a/gfx/layers/client/CompositableChild.cpp
+++ b/gfx/layers/client/CompositableChild.cpp
@@ -60,17 +60,16 @@ CompositableChild::GetCompositableClient
 void
 CompositableChild::ActorDestroy(ActorDestroyReason)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   mCanSend = false;
 
   if (mCompositableClient) {
-    mCompositableClient->mCompositableChild = nullptr;
     mCompositableClient = nullptr;
   }
 }
 
 /* static */ PCompositableChild*
 AsyncCompositableChild::CreateActor(uint64_t aAsyncID)
 {
   AsyncCompositableChild* child = new AsyncCompositableChild(aAsyncID);
--- a/gfx/layers/client/CompositableClient.cpp
+++ b/gfx/layers/client/CompositableClient.cpp
@@ -23,25 +23,24 @@
 #include "IPDLActor.h"
 
 namespace mozilla {
 namespace layers {
 
 using namespace mozilla::gfx;
 
 void
-CompositableClient::InitIPDLActor(PCompositableChild* aActor, const CompositableHandle& aAsyncHandle)
+CompositableClient::InitIPDL(const CompositableHandle& aHandle)
 {
-  MOZ_ASSERT(aActor);
+  MOZ_ASSERT(aHandle);
 
   mForwarder->AssertInForwarderThread();
 
-  mAsyncHandle = aAsyncHandle;
-  mCompositableChild = static_cast<CompositableChild*>(aActor);
-  mCompositableChild->Init(this);
+  mHandle = aHandle;
+  mIsAsync = !NS_IsMainThread();
 }
 
 /* static */ RefPtr<CompositableClient>
 CompositableClient::FromIPDLActor(PCompositableChild* aActor)
 {
   MOZ_ASSERT(aActor);
 
   RefPtr<CompositableClient> client = static_cast<CompositableChild*>(aActor)->GetCompositableClient();
@@ -52,81 +51,70 @@ CompositableClient::FromIPDLActor(PCompo
   client->mForwarder->AssertInForwarderThread();
   return client;
 }
 
 CompositableClient::CompositableClient(CompositableForwarder* aForwarder,
                                        TextureFlags aTextureFlags)
 : mForwarder(aForwarder)
 , mTextureFlags(aTextureFlags)
+, mIsAsync(false)
 {
 }
 
 CompositableClient::~CompositableClient()
 {
   Destroy();
 }
 
 LayersBackend
 CompositableClient::GetCompositorBackendType() const
 {
   return mForwarder->GetCompositorBackendType();
 }
 
-PCompositableChild*
-CompositableClient::GetIPDLActor() const
-{
-  return mCompositableChild;
-}
-
 bool
 CompositableClient::Connect(ImageContainer* aImageContainer)
 {
-  MOZ_ASSERT(!mCompositableChild);
-  if (!GetForwarder() || GetIPDLActor()) {
+  MOZ_ASSERT(!mHandle);
+  if (!GetForwarder() || mHandle) {
     return false;
   }
 
   GetForwarder()->AssertInForwarderThread();
   GetForwarder()->Connect(this, aImageContainer);
   return true;
 }
 
 bool
 CompositableClient::IsConnected() const
 {
   // CanSend() is only reliable in the same thread as the IPDL channel.
   mForwarder->AssertInForwarderThread();
-  return mCompositableChild && mCompositableChild->IsConnected();
+  return !!mHandle;
 }
 
 void
 CompositableClient::Destroy()
 {
-  if (!mCompositableChild) {
-    return;
-  }
-
   if (mTextureClientRecycler) {
     mTextureClientRecycler->Destroy();
   }
 
-  // Take away our IPDL's actor reference back to us.
-  mCompositableChild->RevokeCompositableClient();
-
-  // Schedule the IPDL actor to be destroyed on the forwarder's thread.
-  mForwarder->Destroy(mCompositableChild);
-  mCompositableChild = nullptr;
+  if (mHandle) {
+    mForwarder->ReleaseCompositable(mHandle);
+    mHandle = CompositableHandle();
+  }
 }
 
 CompositableHandle
 CompositableClient::GetAsyncHandle() const
 {
-  if (mCompositableChild) {
-    return mAsyncHandle;
+  if (mIsAsync) {
+    return mHandle;
   }
   return CompositableHandle();
 }
 
 already_AddRefed<TextureClient>
 CompositableClient::CreateBufferTextureClient(gfx::SurfaceFormat aFormat,
                                               gfx::IntSize aSize,
                                               gfx::BackendType aMoz2DBackend,
--- a/gfx/layers/client/CompositableClient.h
+++ b/gfx/layers/client/CompositableClient.h
@@ -109,34 +109,39 @@ public:
    * Establishes the connection with compositor side through IPDL
    */
   virtual bool Connect(ImageContainer* aImageContainer = nullptr);
 
   void Destroy();
 
   bool IsConnected() const;
 
-  PCompositableChild* GetIPDLActor() const;
-
   CompositableForwarder* GetForwarder() const
   {
     return mForwarder;
   }
 
   /**
    * This identifier is what lets us attach async compositables with a shadow
    * layer. It is not used if the compositable is used with the regular shadow
    * layer forwarder.
    *
    * If this returns empty, it means the compositable is not async (it is used
    * on the main thread).
    */
   CompositableHandle GetAsyncHandle() const;
 
   /**
+   * Handle for IPDL communication.
+   */
+  CompositableHandle GetIPCHandle() const {
+    return mHandle;
+  }
+
+  /**
    * Tells the Compositor to create a TextureHost for this TextureClient.
    */
   virtual bool AddTextureClient(TextureClient* aClient);
 
   /**
    * A hook for the when the Compositable is detached from it's layer.
    */
   virtual void OnDetach() {}
@@ -160,37 +165,36 @@ public:
    * See AutoRemoveTexture to automatically invoke this at the end of a scope.
    */
   virtual void RemoveTexture(TextureClient* aTexture);
 
   virtual ContentClientRemote* AsContentClientRemote() { return nullptr; }
 
   static RefPtr<CompositableClient> FromIPDLActor(PCompositableChild* aActor);
 
-  void InitIPDLActor(PCompositableChild* aActor, const CompositableHandle& aHandle);
+  void InitIPDL(const CompositableHandle& aHandle);
 
   TextureFlags GetTextureFlags() const { return mTextureFlags; }
 
   TextureClientRecycleAllocator* GetTextureClientRecycler();
 
   bool HasTextureClientRecycler() { return !!mTextureClientRecycler; }
 
   static void DumpTextureClient(std::stringstream& aStream,
                                 TextureClient* aTexture,
                                 TextureDumpMode aCompress);
 protected:
-  RefPtr<CompositableChild> mCompositableChild;
   RefPtr<CompositableForwarder> mForwarder;
   // Some layers may want to enforce some flags to all their textures
   // (like disallowing tiling)
   TextureFlags mTextureFlags;
   RefPtr<TextureClientRecycleAllocator> mTextureClientRecycler;
 
-  // Handle for IPDL operations.
-  CompositableHandle mAsyncHandle;
+  CompositableHandle mHandle;
+  bool mIsAsync;
 
   friend class CompositableChild;
 };
 
 /**
  * Helper to call RemoveTexture at the end of a scope.
  */
 struct AutoRemoveTexture
--- a/gfx/layers/composite/CompositableHost.cpp
+++ b/gfx/layers/composite/CompositableHost.cpp
@@ -23,48 +23,16 @@
 namespace mozilla {
 
 using namespace gfx;
 
 namespace layers {
 
 class Compositor;
 
-/**
- * IPDL actor used by CompositableHost to match with its corresponding
- * CompositableClient on the content side.
- *
- * CompositableParent is owned by the IPDL system. It's deletion is triggered
- * by either the CompositableChild's deletion, or by the IPDL communication
- * going down.
- */
-class CompositableParent : public ParentActor<PCompositableParent>
-{
-public:
-  CompositableParent(CompositableParentManager* aMgr, const TextureInfo& aTextureInfo)
-  {
-    MOZ_COUNT_CTOR(CompositableParent);
-    mHost = CompositableHost::Create(aTextureInfo);
-  }
-
-  ~CompositableParent()
-  {
-    MOZ_COUNT_DTOR(CompositableParent);
-  }
-
-  virtual void Destroy() override
-  {
-    if (mHost) {
-      mHost->Detach(nullptr, CompositableHost::FORCE_DETACH);
-    }
-  }
-
-  RefPtr<CompositableHost> mHost;
-};
-
 CompositableHost::CompositableHost(const TextureInfo& aTextureInfo)
   : mTextureInfo(aTextureInfo)
   , mCompositorID(0)
   , mCompositor(nullptr)
   , mLayer(nullptr)
   , mFlashCounter(0)
   , mAttached(false)
   , mKeepAttached(false)
@@ -72,37 +40,23 @@ CompositableHost::CompositableHost(const
   MOZ_COUNT_CTOR(CompositableHost);
 }
 
 CompositableHost::~CompositableHost()
 {
   MOZ_COUNT_DTOR(CompositableHost);
 }
 
-PCompositableParent*
-CompositableHost::CreateIPDLActor(CompositableParentManager* aMgr,
-                                  const TextureInfo& aTextureInfo)
-{
-  return new CompositableParent(aMgr, aTextureInfo);
-}
-
 bool
 CompositableHost::DestroyIPDLActor(PCompositableParent* aActor)
 {
   delete aActor;
   return true;
 }
 
-CompositableHost*
-CompositableHost::FromIPDLActor(PCompositableParent* aActor)
-{
-  MOZ_ASSERT(aActor);
-  return static_cast<CompositableParent*>(aActor)->mHost;
-}
-
 void
 CompositableHost::UseTextureHost(const nsTArray<TimedTexture>& aTextures)
 {
   if (GetCompositor()) {
     for (auto& texture : aTextures) {
       texture.mTexture->SetCompositor(GetCompositor());
     }
   }
@@ -204,16 +158,10 @@ CompositableHost::DumpTextureHost(std::s
   }
   RefPtr<gfx::DataSourceSurface> dSurf = aTexture->GetAsSurface();
   if (!dSurf) {
     return;
   }
   aStream << gfxUtils::GetAsDataURI(dSurf).get();
 }
 
-void
-CompositableHost::ReceivedDestroy(PCompositableParent* aActor)
-{
-  static_cast<CompositableParent*>(aActor)->RecvDestroy();
-}
-
 } // namespace layers
 } // namespace mozilla
--- a/gfx/layers/composite/CompositableHost.h
+++ b/gfx/layers/composite/CompositableHost.h
@@ -182,19 +182,16 @@ public:
         aFlags & FORCE_DETACH) {
       SetLayer(nullptr);
       mAttached = false;
       mKeepAttached = false;
     }
   }
   bool IsAttached() { return mAttached; }
 
-  static void
-  ReceivedDestroy(PCompositableParent* aActor);
-
   virtual void Dump(std::stringstream& aStream,
                     const char* aPrefix="",
                     bool aDumpHtml=false) { }
   static void DumpTextureHost(std::stringstream& aStream, TextureHost* aTexture);
 
   virtual already_AddRefed<gfx::DataSourceSurface> GetAsSurface() { return nullptr; }
 
   virtual void PrintInfo(std::stringstream& aStream, const char* aPrefix) = 0;
@@ -215,24 +212,18 @@ public:
   virtual void RemoveTextureHost(TextureHost* aTexture);
 
   // Called every time this is composited
   void BumpFlashCounter() {
     mFlashCounter = mFlashCounter >= DIAGNOSTIC_FLASH_COUNTER_MAX
                   ? DIAGNOSTIC_FLASH_COUNTER_MAX : mFlashCounter + 1;
   }
 
-  static PCompositableParent*
-  CreateIPDLActor(CompositableParentManager* mgr,
-                  const TextureInfo& textureInfo);
-
   static bool DestroyIPDLActor(PCompositableParent* actor);
 
-  static CompositableHost* FromIPDLActor(PCompositableParent* actor);
-
   uint64_t GetCompositorID() const { return mCompositorID; }
 
   const AsyncCompositableRef& GetAsyncRef() const { return mAsyncRef; }
   void SetAsyncRef(const AsyncCompositableRef& aRef) { mAsyncRef = aRef; }
 
   void SetCompositorID(uint64_t aID) { mCompositorID = aID; }
 
   virtual bool Lock() { return false; }
--- a/gfx/layers/ipc/CompositableForwarder.cpp
+++ b/gfx/layers/ipc/CompositableForwarder.cpp
@@ -5,24 +5,10 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "CompositableForwarder.h"
 #include "mozilla/layers/CompositableChild.h"
 
 namespace mozilla {
 namespace layers {
 
-void
-CompositableForwarder::Destroy(CompositableChild* aCompositable)
-{
-  AssertInForwarderThread();
-
-  if (!aCompositable->CanSend()) {
-    return;
-  }
-
-  if (!DestroyInTransaction(aCompositable, false)) {
-    aCompositable->SendDestroy();
-  }
-}
-
 } // namespace layers
 } // namespace mozilla
--- a/gfx/layers/ipc/CompositableForwarder.h
+++ b/gfx/layers/ipc/CompositableForwarder.h
@@ -66,20 +66,18 @@ public:
   /**
    * Communicate to the compositor that aRegion in the texture identified by
    * aCompositable and aIdentifier has been updated to aThebesBuffer.
    */
   virtual void UpdateTextureRegion(CompositableClient* aCompositable,
                                    const ThebesBufferData& aThebesBufferData,
                                    const nsIntRegion& aUpdatedRegion) = 0;
 
-  virtual void Destroy(CompositableChild* aCompositable);
-
+  virtual void ReleaseCompositable(const CompositableHandle& aHandle) = 0;
   virtual bool DestroyInTransaction(PTextureChild* aTexture, bool synchronously) = 0;
-  virtual bool DestroyInTransaction(PCompositableChild* aCompositable, bool synchronously) = 0;
 
   /**
    * Tell the CompositableHost on the compositor side to remove the texture
    * from the CompositableHost.
    * This function does not delete the TextureHost corresponding to the
    * TextureClient passed in parameter.
    * When the TextureClient has TEXTURE_DEALLOCATE_CLIENT flag,
    * the transaction becomes synchronous.
--- a/gfx/layers/ipc/CompositableTransactionParent.cpp
+++ b/gfx/layers/ipc/CompositableTransactionParent.cpp
@@ -61,17 +61,20 @@ ScheduleComposition(CompositableHost* aC
 }
 
 bool
 CompositableParentManager::ReceiveCompositableUpdate(const CompositableOperation& aEdit,
                                                      EditReplyVector& replyv)
 {
   // Ignore all operations on compositables created on stale compositors. We
   // return true because the child is unable to handle errors.
-  CompositableHost* compositable = CompositableHost::FromIPDLActor(aEdit.compositableParent());
+  RefPtr<CompositableHost> compositable = FindCompositable(aEdit.compositable());
+  if (!compositable) {
+    return false;
+  }
   if (compositable->GetCompositor() && !compositable->GetCompositor()->IsValid()) {
     return true;
   }
 
   switch (aEdit.detail().type()) {
     case CompositableOperationDetail::TOpPaintTextureRegion: {
       MOZ_LAYERS_LOG(("[ParentSide] Paint PaintedLayer"));
 
@@ -90,17 +93,17 @@ CompositableParentManager::ReceiveCompos
       if (!compositable->UpdateThebes(bufferData,
                                       op.updatedRegion(),
                                       thebes->GetValidRegion(),
                                       &frontUpdatedRegion))
       {
         return false;
       }
       replyv.push_back(
-        OpContentBufferSwap(aEdit.compositableParent(), nullptr, frontUpdatedRegion));
+        OpContentBufferSwap(aEdit.compositable(), frontUpdatedRegion));
 
       RenderTraceInvalidateEnd(thebes, "FF00FF");
       break;
     }
     case CompositableOperationDetail::TOpUseTiledLayerBuffer: {
       MOZ_LAYERS_LOG(("[ParentSide] Paint TiledLayerBuffer"));
       const OpUseTiledLayerBuffer& op = aEdit.detail().get_OpUseTiledLayerBuffer();
       TiledContentHost* tiledHost = compositable->AsTiledContentHost();
@@ -224,22 +227,67 @@ void
 CompositableParentManager::DestroyActor(const OpDestroy& aOp)
 {
   switch (aOp.type()) {
     case OpDestroy::TPTextureParent: {
       auto actor = aOp.get_PTextureParent();
       TextureHost::ReceivedDestroy(actor);
       break;
     }
-    case OpDestroy::TPCompositableParent: {
-      auto actor = aOp.get_PCompositableParent();
-      CompositableHost::ReceivedDestroy(actor);
+    case OpDestroy::TCompositableHandle: {
+      ReleaseCompositable(aOp.get_CompositableHandle());
       break;
     }
     default: {
       MOZ_ASSERT(false, "unsupported type");
     }
   }
 }
 
+RefPtr<CompositableHost>
+CompositableParentManager::AddCompositable(const CompositableHandle& aHandle,
+				           const TextureInfo& aInfo)
+{
+  if (mCompositables.find(aHandle.Value()) != mCompositables.end()) {
+    NS_ERROR("Client should not allocate duplicate handles");
+    return nullptr;
+  }
+  if (!aHandle) {
+    NS_ERROR("Client should not allocate 0 as a handle");
+    return nullptr;
+  }
+
+  RefPtr<CompositableHost> host = CompositableHost::Create(aInfo);
+  if (!host) {
+    return nullptr;
+  }
+
+  mCompositables[aHandle.Value()] = host;
+  return host;
+}
+
+RefPtr<CompositableHost>
+CompositableParentManager::FindCompositable(const CompositableHandle& aHandle)
+{
+  auto iter = mCompositables.find(aHandle.Value());
+  if (iter == mCompositables.end()) {
+    return nullptr;
+  }
+  return iter->second;
+}
+
+void
+CompositableParentManager::ReleaseCompositable(const CompositableHandle& aHandle)
+{
+  auto iter = mCompositables.find(aHandle.Value());
+  if (iter == mCompositables.end()) {
+    return;
+  }
+
+  RefPtr<CompositableHost> host = iter->second;
+  mCompositables.erase(iter);
+
+  host->Detach(nullptr, CompositableHost::FORCE_DETACH);
+}
+
 } // namespace layers
 } // namespace mozilla
 
--- a/gfx/layers/ipc/CompositableTransactionParent.h
+++ b/gfx/layers/ipc/CompositableTransactionParent.h
@@ -7,22 +7,21 @@
 
 #ifndef MOZILLA_LAYERS_COMPOSITABLETRANSACTIONPARENT_H
 #define MOZILLA_LAYERS_COMPOSITABLETRANSACTIONPARENT_H
 
 #include <vector>                       // for vector
 #include "mozilla/Attributes.h"         // for override
 #include "mozilla/layers/ISurfaceAllocator.h"  // for ISurfaceAllocator
 #include "mozilla/layers/LayersMessages.h"  // for EditReply, etc
+#include "CompositableHost.h"
 
 namespace mozilla {
 namespace layers {
 
-class CompositableHost;
-
 typedef std::vector<mozilla::layers::EditReply> EditReplyVector;
 
 // Since PCompositble has two potential manager protocols, we can't just call
 // the Manager() method usually generated when there's one manager protocol,
 // so both manager protocols implement this and we keep a reference to them
 // through this interface.
 class CompositableParentManager : public HostIPCAllocator
 {
@@ -34,22 +33,34 @@ public:
   void UpdateFwdTransactionId(uint64_t aTransactionId)
   {
     MOZ_ASSERT(mFwdTransactionId < aTransactionId);
     mFwdTransactionId = aTransactionId;
   }
 
   uint64_t GetFwdTransactionId() { return mFwdTransactionId; }
 
+  RefPtr<CompositableHost> AddCompositable(
+    const CompositableHandle& aHandle,
+    const TextureInfo& aInfo);
+  RefPtr<CompositableHost> FindCompositable(const CompositableHandle& aHandle);
+
 protected:
   /**
    * Handle the IPDL messages that affect PCompositable actors.
    */
   bool ReceiveCompositableUpdate(const CompositableOperation& aEdit,
                                  EditReplyVector& replyv);
 
+  void ReleaseCompositable(const CompositableHandle& aHandle);
+
   uint64_t mFwdTransactionId = 0;
+
+  /**
+   * Mapping form IDs to CompositableHosts.
+   */
+  std::map<uint64_t, RefPtr<CompositableHost>> mCompositables;
 };
 
 } // namespace layers
 } // namespace mozilla
 
 #endif
--- a/gfx/layers/ipc/ImageBridgeChild.cpp
+++ b/gfx/layers/ipc/ImageBridgeChild.cpp
@@ -150,17 +150,17 @@ struct AutoEndTransaction {
   CompositableTransaction* mTxn;
 };
 
 void
 ImageBridgeChild::UseTextures(CompositableClient* aCompositable,
                               const nsTArray<TimedTextureClient>& aTextures)
 {
   MOZ_ASSERT(aCompositable);
-  MOZ_ASSERT(aCompositable->GetIPDLActor());
+  MOZ_ASSERT(aCompositable->GetIPCHandle());
   MOZ_ASSERT(aCompositable->IsConnected());
 
   AutoTArray<TimedTexture,4> textures;
 
   for (auto& t : aTextures) {
     MOZ_ASSERT(t.mTextureClient);
     MOZ_ASSERT(t.mTextureClient->GetIPDLActor());
 
@@ -174,17 +174,17 @@ ImageBridgeChild::UseTextures(Compositab
     textures.AppendElement(TimedTexture(nullptr, t.mTextureClient->GetIPDLActor(),
                                         readLock,
                                         t.mTimeStamp, t.mPictureRect,
                                         t.mFrameID, t.mProducerID));
 
     // Wait end of usage on host side if TextureFlags::RECYCLE is set
     HoldUntilCompositableRefReleasedIfNecessary(t.mTextureClient);
   }
-  mTxn->AddNoSwapEdit(CompositableOperation(nullptr, aCompositable->GetIPDLActor(),
+  mTxn->AddNoSwapEdit(CompositableOperation(aCompositable->GetIPCHandle(),
                                             OpUseTexture(textures)));
 }
 
 void
 ImageBridgeChild::UseComponentAlphaTextures(CompositableClient* aCompositable,
                                             TextureClient* aTextureOnBlack,
                                             TextureClient* aTextureOnWhite)
 {
@@ -201,18 +201,17 @@ ImageBridgeChild::UseComponentAlphaTextu
   aTextureOnBlack->SerializeReadLock(readLockB);
   aTextureOnWhite->SerializeReadLock(readLockW);
 
   HoldUntilCompositableRefReleasedIfNecessary(aTextureOnBlack);
   HoldUntilCompositableRefReleasedIfNecessary(aTextureOnWhite);
 
   mTxn->AddNoSwapEdit(
     CompositableOperation(
-      nullptr,
-      aCompositable->GetIPDLActor(),
+      aCompositable->GetIPCHandle(),
       OpUseComponentAlphaTextures(
         nullptr, aTextureOnBlack->GetIPDLActor(),
         nullptr, aTextureOnWhite->GetIPDLActor(),
         readLockB, readLockW
       )
     )
   );
 }
@@ -267,24 +266,16 @@ ImageBridgeChild::ShutdownStep1(Synchron
   AutoCompleteTask complete(aTask);
 
   MOZ_ASSERT(InImageBridgeChildThread(),
              "Should be in ImageBridgeChild thread.");
 
   MediaSystemResourceManager::Shutdown();
 
   // Force all managed protocols to shut themselves down cleanly
-  InfallibleTArray<PCompositableChild*> compositables;
-  ManagedPCompositableChild(compositables);
-  for (int i = compositables.Length() - 1; i >= 0; --i) {
-    auto compositable = CompositableClient::FromIPDLActor(compositables[i]);
-    if (compositable) {
-      compositable->Destroy();
-    }
-  }
   InfallibleTArray<PTextureChild*> textures;
   ManagedPTextureChild(textures);
   for (int i = textures.Length() - 1; i >= 0; --i) {
     RefPtr<TextureClient> client = TextureClient::AsTextureClient(textures[i]);
     if (client) {
       client->Destroy();
     }
   }
@@ -386,53 +377,28 @@ ImageBridgeChild::Connect(CompositableCl
   uint64_t id = sNextID++;
 
   {
     MutexAutoLock lock(mContainerMapLock);
     MOZ_ASSERT(!mImageContainers.Contains(id));
     mImageContainers.Put(id, aImageContainer);
   }
 
-  PCompositableChild* child =
-    SendPCompositableConstructor(aCompositable->GetTextureInfo(), id);
-  if (!child) {
-    return;
-  }
-  aCompositable->InitIPDLActor(child, CompositableHandle(id));
+  CompositableHandle handle(id);
+  aCompositable->InitIPDL(handle);
+  SendNewCompositable(handle, aCompositable->GetTextureInfo());
 }
 
 void
 ImageBridgeChild::ForgetImageContainer(const CompositableHandle& aHandle)
 {
   MutexAutoLock lock(mContainerMapLock);
   mImageContainers.Remove(aHandle.Value());
 }
 
-PCompositableChild*
-ImageBridgeChild::AllocPCompositableChild(const TextureInfo& aInfo, const uint64_t& aID)
-{
-  MOZ_ASSERT(CanSend());
-  return AsyncCompositableChild::CreateActor(aID);
-}
-
-bool
-ImageBridgeChild::DeallocPCompositableChild(PCompositableChild* aActor)
-{
-  AsyncCompositableChild* actor = static_cast<AsyncCompositableChild*>(aActor);
-  MOZ_ASSERT(actor->GetAsyncID());
-
-  {
-    MutexAutoLock lock(mContainerMapLock);
-    mImageContainers.Remove(actor->GetAsyncID());
-  }
-
-  AsyncCompositableChild::DestroyActor(aActor);
-  return true;
-}
-
 Thread* ImageBridgeChild::GetThread() const
 {
   return sImageBridgeChildThread;
 }
 
 /* static */ RefPtr<ImageBridgeChild>
 ImageBridgeChild::GetSingleton()
 {
@@ -456,17 +422,16 @@ ImageBridgeChild::DispatchReleaseTexture
 
   RefPtr<ImageBridgeChild> imageBridge = ImageBridgeChild::GetSingleton();
   if (!imageBridge) {
     // TextureClient::Release should normally happen in the ImageBridgeChild
     // thread because it usually generate some IPDL messages.
     // However, if we take this branch it means that the ImageBridgeChild
     // has already shut down, along with the TextureChild, which means no
     // message will be sent and it is safe to run this code from any thread.
-    MOZ_ASSERT(aClient->GetIPDLActor() == nullptr);
     RELEASE_MANUALLY(aClient);
     return;
   }
 
   RefPtr<Runnable> runnable = WrapRunnable(
     imageBridge,
     &ImageBridgeChild::ReleaseTextureClientNow,
     aClient);
@@ -1149,62 +1114,73 @@ IBCAddOpDestroy(CompositableTransaction*
 
 bool
 ImageBridgeChild::DestroyInTransaction(PTextureChild* aTexture, bool synchronously)
 {
   return IBCAddOpDestroy(mTxn, OpDestroy(aTexture), synchronously);
 }
 
 bool
-ImageBridgeChild::DestroyInTransaction(PCompositableChild* aCompositable, bool synchronously)
+ImageBridgeChild::DestroyInTransaction(const CompositableHandle& aHandle)
 {
-  return IBCAddOpDestroy(mTxn, OpDestroy(aCompositable), synchronously);
+  return IBCAddOpDestroy(mTxn, OpDestroy(aHandle), false);
 }
 
-
 void
 ImageBridgeChild::RemoveTextureFromCompositable(CompositableClient* aCompositable,
                                                 TextureClient* aTexture)
 {
   MOZ_ASSERT(CanSend());
   MOZ_ASSERT(aTexture);
   MOZ_ASSERT(aTexture->IsSharedWithCompositor());
   MOZ_ASSERT(aCompositable->IsConnected());
   if (!aTexture || !aTexture->IsSharedWithCompositor() || !aCompositable->IsConnected()) {
     return;
   }
 
   CompositableOperation op(
-    nullptr, aCompositable->GetIPDLActor(),
+    aCompositable->GetIPCHandle(),
     OpRemoveTexture(nullptr, aTexture->GetIPDLActor()));
 
   if (aTexture->GetFlags() & TextureFlags::DEALLOCATE_CLIENT) {
     mTxn->AddEdit(op);
   } else {
     mTxn->AddNoSwapEdit(op);
   }
 }
 
 bool ImageBridgeChild::IsSameProcess() const
 {
   return OtherPid() == base::GetCurrentProcId();
 }
 
 void
-ImageBridgeChild::Destroy(CompositableChild* aCompositable)
+ImageBridgeChild::ReleaseCompositable(const CompositableHandle& aHandle)
 {
   if (!InImageBridgeChildThread()) {
     RefPtr<Runnable> runnable = WrapRunnable(
       RefPtr<ImageBridgeChild>(this),
-      &ImageBridgeChild::Destroy,
-      RefPtr<CompositableChild>(aCompositable));
+      &ImageBridgeChild::ReleaseCompositable,
+      aHandle);
     GetMessageLoop()->PostTask(runnable.forget());
     return;
   }
-  CompositableForwarder::Destroy(aCompositable);
+
+  if (!CanSend()) {
+    return;
+  }
+
+  if (!DestroyInTransaction(aHandle)) {
+    SendReleaseCompositable(aHandle);
+  }
+
+  {
+    MutexAutoLock lock(mContainerMapLock);
+    mImageContainers.Remove(aHandle.Value());
+  }
 }
 
 bool
 ImageBridgeChild::CanSend() const
 {
   MOZ_ASSERT(InImageBridgeChildThread());
   return mCanSend;
 }
--- a/gfx/layers/ipc/ImageBridgeChild.h
+++ b/gfx/layers/ipc/ImageBridgeChild.h
@@ -163,20 +163,16 @@ public:
    * Returns the ImageBridgeChild's message loop.
    *
    * Can be called from any thread.
    */
   virtual MessageLoop * GetMessageLoop() const override;
 
   virtual base::ProcessId GetParentPid() const override { return OtherPid(); }
 
-  PCompositableChild* AllocPCompositableChild(const TextureInfo& aInfo,
-                                              const uint64_t& aID) override;
-  bool DeallocPCompositableChild(PCompositableChild* aActor) override;
-
   virtual PTextureChild*
   AllocPTextureChild(const SurfaceDescriptor& aSharedData, const LayersBackend& aLayersBackend, const TextureFlags& aFlags, const uint64_t& aSerial) override;
 
   virtual bool
   DeallocPTextureChild(PTextureChild* actor) override;
 
   PMediaSystemResourceManagerChild*
   AllocPMediaSystemResourceManagerChild() override;
@@ -263,17 +259,17 @@ public:
    * See CompositableForwarder::UseTextures
    */
   virtual void UseTextures(CompositableClient* aCompositable,
                            const nsTArray<TimedTextureClient>& aTextures) override;
   virtual void UseComponentAlphaTextures(CompositableClient* aCompositable,
                                          TextureClient* aClientOnBlack,
                                          TextureClient* aClientOnWhite) override;
 
-  void Destroy(CompositableChild* aCompositable) override;
+  void ReleaseCompositable(const CompositableHandle& aHandle) override;
 
   void ForgetImageContainer(const CompositableHandle& aHandle);
 
   /**
    * Hold TextureClient ref until end of usage on host side if TextureFlags::RECYCLE is set.
    * Host side's usage is checked via CompositableRef.
    */
   void HoldUntilCompositableRefReleasedIfNecessary(TextureClient* aClient);
@@ -282,17 +278,17 @@ public:
    * Notify id of Texture When host side end its use. Transaction id is used to
    * make sure if there is no newer usage.
    */
   void NotifyNotUsed(uint64_t aTextureId, uint64_t aFwdTransactionId);
 
   virtual void CancelWaitForRecycle(uint64_t aTextureId) override;
 
   virtual bool DestroyInTransaction(PTextureChild* aTexture, bool synchronously) override;
-  virtual bool DestroyInTransaction(PCompositableChild* aCompositable, bool synchronously) override;
+  bool DestroyInTransaction(const CompositableHandle& aHandle);
 
   virtual void RemoveTextureFromCompositable(CompositableClient* aCompositable,
                                              TextureClient* aTexture) override;
 
   virtual void UseTiledLayerBuffer(CompositableClient* aCompositable,
                                    const SurfaceDescriptorTiles& aTileLayerDescriptor) override
   {
     MOZ_CRASH("should not be called");
--- a/gfx/layers/ipc/ImageBridgeParent.cpp
+++ b/gfx/layers/ipc/ImageBridgeParent.cpp
@@ -227,44 +227,33 @@ mozilla::ipc::IPCResult ImageBridgeParen
   ManagedPTextureParent(textures);
   for (unsigned int i = 0; i < textures.Length(); ++i) {
     RefPtr<TextureHost> tex = TextureHost::AsTextureHost(textures[i]);
     tex->DeallocateDeviceData();
   }
   return IPC_OK();
 }
 
-PCompositableParent*
-ImageBridgeParent::AllocPCompositableParent(const TextureInfo& aInfo, const uint64_t& aID)
+mozilla::ipc::IPCResult
+ImageBridgeParent::RecvNewCompositable(const CompositableHandle& aHandle, const TextureInfo& aInfo)
 {
-  PCompositableParent* actor = CompositableHost::CreateIPDLActor(this, aInfo);
-  if (mCompositables.find(aID) != mCompositables.end()) {
-    NS_ERROR("Async compositable ID already exists");
-    return actor;
-  }
-  if (!aID) {
-    NS_ERROR("Expected non-zero async compositable ID");
-    return actor;
+  RefPtr<CompositableHost> host = AddCompositable(aHandle, aInfo);
+  if (!host) {
+    return IPC_FAIL_NO_REASON(this);
   }
 
-  CompositableHost* host = CompositableHost::FromIPDLActor(actor);
-
-  host->SetAsyncRef(AsyncCompositableRef(OtherPid(), CompositableHandle(aID)));
-  mCompositables[aID] = host;
-
-  return actor;
+  host->SetAsyncRef(AsyncCompositableRef(OtherPid(), aHandle));
+  return IPC_OK();
 }
 
-bool ImageBridgeParent::DeallocPCompositableParent(PCompositableParent* aActor)
+mozilla::ipc::IPCResult
+ImageBridgeParent::RecvReleaseCompositable(const CompositableHandle& aHandle)
 {
-  if (CompositableHost* host = CompositableHost::FromIPDLActor(aActor)) {
-    const AsyncCompositableRef& ref = host->GetAsyncRef();
-    mCompositables.erase(ref.mHandle.Value());
-  }
-  return CompositableHost::DestroyIPDLActor(aActor);
+  ReleaseCompositable(aHandle);
+  return IPC_OK();
 }
 
 PTextureParent*
 ImageBridgeParent::AllocPTextureParent(const SurfaceDescriptor& aSharedData,
                                        const LayersBackend& aLayersBackend,
                                        const TextureFlags& aFlags,
                                        const uint64_t& aSerial)
 {
@@ -433,20 +422,10 @@ ImageBridgeParent::NotifyNotUsed(PTextur
   mPendingAsyncMessage.push_back(
     OpNotifyNotUsed(textureId, aTransactionId));
 
   if (!IsAboutToSendAsyncMessages()) {
     SendPendingAsyncMessages();
   }
 }
 
-CompositableHost*
-ImageBridgeParent::FindCompositable(const CompositableHandle& aHandle)
-{
-  auto iter = mCompositables.find(aHandle.Value());
-  if (iter == mCompositables.end()) {
-    return nullptr;
-  }
-  return iter->second;
-}
-
 } // namespace layers
 } // namespace mozilla
--- a/gfx/layers/ipc/ImageBridgeParent.h
+++ b/gfx/layers/ipc/ImageBridgeParent.h
@@ -72,26 +72,26 @@ public:
   // PImageBridge
   virtual mozilla::ipc::IPCResult RecvImageBridgeThreadId(const PlatformThreadId& aThreadId) override;
   virtual mozilla::ipc::IPCResult RecvUpdate(EditArray&& aEdits, OpDestroyArray&& aToDestroy,
                                           const uint64_t& aFwdTransactionId,
                                           EditReplyArray* aReply) override;
   virtual mozilla::ipc::IPCResult RecvUpdateNoSwap(EditArray&& aEdits, OpDestroyArray&& aToDestroy,
                                                 const uint64_t& aFwdTransactionId) override;
 
-  PCompositableParent* AllocPCompositableParent(const TextureInfo& aInfo,
-                                                const uint64_t& aID) override;
-  bool DeallocPCompositableParent(PCompositableParent* aActor) override;
-
   virtual PTextureParent* AllocPTextureParent(const SurfaceDescriptor& aSharedData,
                                               const LayersBackend& aLayersBackend,
                                               const TextureFlags& aFlags,
                                               const uint64_t& aSerial) override;
   virtual bool DeallocPTextureParent(PTextureParent* actor) override;
 
+  virtual mozilla::ipc::IPCResult RecvNewCompositable(const CompositableHandle& aHandle,
+                                                      const TextureInfo& aInfo) override;
+  virtual mozilla::ipc::IPCResult RecvReleaseCompositable(const CompositableHandle& aHandle) override;
+
   PMediaSystemResourceManagerParent* AllocPMediaSystemResourceManagerParent() override;
   bool DeallocPMediaSystemResourceManagerParent(PMediaSystemResourceManagerParent* aActor) override;
 
   // Shutdown step 1
   virtual mozilla::ipc::IPCResult RecvWillClose() override;
 
   MessageLoop* GetMessageLoop() const { return mMessageLoop; }
 
@@ -118,18 +118,16 @@ public:
   static ImageBridgeParent* GetInstance(ProcessId aId);
 
   static bool NotifyImageComposites(nsTArray<ImageCompositeNotificationInfo>& aNotifications);
 
   virtual bool UsesImageBridge() const override { return true; }
 
   virtual bool IPCOpen() const override { return !mClosed; }
 
-  CompositableHost* FindCompositable(const CompositableHandle& aHandle);
-
 protected:
   void OnChannelConnected(int32_t pid) override;
 
   void Bind(Endpoint<PImageBridgeParent>&& aEndpoint);
 
 private:
   void DeferredDestroy();
   MessageLoop* mMessageLoop;
@@ -143,41 +141,14 @@ private:
   /**
    * Map of all living ImageBridgeParent instances
    */
   static std::map<base::ProcessId, ImageBridgeParent*> sImageBridges;
 
   static MessageLoop* sMainLoop;
 
   RefPtr<CompositorThreadHolder> mCompositorThreadHolder;
-
-  /**
-   * PCompositable and PLayer can, in the case of async textures, be managed by
-   * different top level protocols. In this case they don't share the same
-   * communication channel and we can't send an OpAttachCompositable (PCompositable,
-   * PLayer) message.
-   *
-   * In order to attach a layer and the right compositable if the the compositable
-   * is async, we store references to the async compositables in a CompositableMap
-   * that is accessed only on the compositor thread. During a layer transaction we
-   * send the message OpAttachAsyncCompositable(ID, PLayer), and on the compositor
-   * side we lookup the ID in the map and attach the corresponding compositable to
-   * the layer.
-   *
-   * CompositableMap must be global because the image bridge doesn't have any
-   * reference to whatever we have created with PLayerTransaction. So, the only way to
-   * actually connect these two worlds is to have something global that they can
-   * both query (in the same  thread). The map is not allocated the map on the
-   * stack to avoid the badness of static initialization.
-   *
-   * Also, we have a compositor/PLayerTransaction protocol/etc. per layer manager, and the
-   * ImageBridge is used by all the existing compositors that have a video, so
-   * there isn't an instance or "something" that lives outside the boudaries of a
-   * given layer manager on the compositor thread except the image bridge and the
-   * thread itself.
-   */
-  std::map<uint64_t, CompositableHost*> mCompositables;
 };
 
 } // namespace layers
 } // namespace mozilla
 
 #endif // gfx_layers_ipc_ImageBridgeParent_h_
--- a/gfx/layers/ipc/LayerTransactionChild.cpp
+++ b/gfx/layers/ipc/LayerTransactionChild.cpp
@@ -31,31 +31,16 @@ LayerTransactionChild::Destroy()
   // ShadowLayerForwarder's destructor.
   // When it happens, IPCOpen() is still true.
   // See bug 1004191.
   mDestroyed = true;
 
   SendShutdown();
 }
 
-
-PCompositableChild*
-LayerTransactionChild::AllocPCompositableChild(const TextureInfo& aInfo)
-{
-  MOZ_ASSERT(!mDestroyed);
-  return CompositableChild::CreateActor();
-}
-
-bool
-LayerTransactionChild::DeallocPCompositableChild(PCompositableChild* actor)
-{
-  CompositableChild::DestroyActor(actor);
-  return true;
-}
-
 void
 LayerTransactionChild::ActorDestroy(ActorDestroyReason why)
 {
   mDestroyed = true;
 }
 
 } // namespace layers
 } // namespace mozilla
--- a/gfx/layers/ipc/LayerTransactionChild.h
+++ b/gfx/layers/ipc/LayerTransactionChild.h
@@ -52,19 +52,16 @@ protected:
   explicit LayerTransactionChild(const uint64_t& aId)
     : mForwarder(nullptr)
     , mIPCOpen(false)
     , mDestroyed(false)
     , mId(aId)
   {}
   ~LayerTransactionChild() { }
 
-  virtual PCompositableChild* AllocPCompositableChild(const TextureInfo& aInfo) override;
-  virtual bool DeallocPCompositableChild(PCompositableChild* actor) override;
-
   virtual void ActorDestroy(ActorDestroyReason why) override;
 
   void AddIPDLReference() {
     MOZ_ASSERT(mIPCOpen == false);
     mIPCOpen = true;
     AddRef();
   }
   void ReleaseIPDLReference() {
--- a/gfx/layers/ipc/LayerTransactionParent.cpp
+++ b/gfx/layers/ipc/LayerTransactionParent.cpp
@@ -569,17 +569,17 @@ LayerTransactionParent::RecvUpdate(const
       if (!ReceiveCompositableUpdate(edit.get_CompositableOperation(),
                                 replyv)) {
         return IPC_FAIL_NO_REASON(this);
       }
       break;
     }
     case Edit::TOpAttachCompositable: {
       const OpAttachCompositable& op = edit.get_OpAttachCompositable();
-      CompositableHost* host = CompositableHost::FromIPDLActor(op.compositableParent());
+      RefPtr<CompositableHost> host = FindCompositable(op.compositable());
       if (mPendingCompositorUpdates) {
         // Do not attach compositables from old layer trees. Return true since
         // content cannot handle errors.
         return IPC_OK();
       }
       if (!Attach(AsLayer(op.layer()), host, false)) {
         return IPC_FAIL_NO_REASON(this);
       }
@@ -594,17 +594,17 @@ LayerTransactionParent::RecvUpdate(const
         // Do not attach compositables from old layer trees. Return true since
         // content cannot handle errors.
         return IPC_OK();
       }
       ImageBridgeParent* imageBridge = ImageBridgeParent::GetInstance(OtherPid());
       if (!imageBridge) {
         return IPC_FAIL_NO_REASON(this);
       }
-      CompositableHost* host = imageBridge->FindCompositable(op.compositable());
+      RefPtr<CompositableHost> host = imageBridge->FindCompositable(op.compositable());
       if (!host) {
         NS_ERROR("CompositableHost not found in the map");
         return IPC_FAIL_NO_REASON(this);
       }
       if (!Attach(AsLayer(op.layer()), host, true)) {
         return IPC_FAIL_NO_REASON(this);
       }
       if (mLayerManager->GetCompositor()) {
@@ -937,28 +937,16 @@ LayerTransactionParent::RecvClearCachedR
 
 mozilla::ipc::IPCResult
 LayerTransactionParent::RecvForceComposite()
 {
   mCompositorBridge->ForceComposite(this);
   return IPC_OK();
 }
 
-PCompositableParent*
-LayerTransactionParent::AllocPCompositableParent(const TextureInfo& aInfo)
-{
-  return CompositableHost::CreateIPDLActor(this, aInfo);
-}
-
-bool
-LayerTransactionParent::DeallocPCompositableParent(PCompositableParent* aActor)
-{
-  return CompositableHost::DestroyIPDLActor(aActor);
-}
-
 void
 LayerTransactionParent::ActorDestroy(ActorDestroyReason why)
 {
 }
 
 bool
 LayerTransactionParent::AllocShmem(size_t aSize,
                                    ipc::SharedMemory::SharedMemoryType aType,
@@ -1036,24 +1024,40 @@ LayerTransactionParent::AsLayer(const La
 {
   if (!aHandle) {
     return nullptr;
   }
   return mLayerMap.Get(aHandle.Value()).get();
 }
 
 mozilla::ipc::IPCResult
+LayerTransactionParent::RecvNewCompositable(const CompositableHandle& aHandle, const TextureInfo& aInfo)
+{
+  if (!AddCompositable(aHandle, aInfo)) {
+    return IPC_FAIL_NO_REASON(this);
+  }
+  return IPC_OK();
+}
+
+mozilla::ipc::IPCResult
 LayerTransactionParent::RecvReleaseLayer(const LayerHandle& aHandle)
 {
   if (!aHandle || !mLayerMap.Contains(aHandle.Value())) {
     return IPC_FAIL_NO_REASON(this);
   }
 
   Maybe<RefPtr<Layer>> maybeLayer = mLayerMap.GetAndRemove(aHandle.Value());
   if (maybeLayer) {
     (*maybeLayer)->Disconnect();
   }
 
   return IPC_OK();
 }
 
+mozilla::ipc::IPCResult
+LayerTransactionParent::RecvReleaseCompositable(const CompositableHandle& aHandle)
+{
+  ReleaseCompositable(aHandle);
+  return IPC_OK();
+}
+
 } // namespace layers
 } // namespace mozilla
--- a/gfx/layers/ipc/LayerTransactionParent.h
+++ b/gfx/layers/ipc/LayerTransactionParent.h
@@ -117,17 +117,20 @@ protected:
                                                 const TimeDuration& aPaintTime) override;
 
   virtual mozilla::ipc::IPCResult RecvUpdate(const TransactionInfo& aInfo,
                                              EditReplyArray* reply) override;
 
   virtual mozilla::ipc::IPCResult RecvUpdateNoSwap(const TransactionInfo& aInfo) override;
 
   virtual mozilla::ipc::IPCResult RecvSetLayerObserverEpoch(const uint64_t& aLayerObserverEpoch) override;
+  virtual mozilla::ipc::IPCResult RecvNewCompositable(const CompositableHandle& aHandle,
+                                                      const TextureInfo& aInfo) override;
   virtual mozilla::ipc::IPCResult RecvReleaseLayer(const LayerHandle& aHandle) override;
+  virtual mozilla::ipc::IPCResult RecvReleaseCompositable(const CompositableHandle& aHandle) override;
 
   virtual mozilla::ipc::IPCResult RecvClearCachedResources() override;
   virtual mozilla::ipc::IPCResult RecvForceComposite() override;
   virtual mozilla::ipc::IPCResult RecvSetTestSampleTime(const TimeStamp& aTime) override;
   virtual mozilla::ipc::IPCResult RecvLeaveTestMode() override;
   virtual mozilla::ipc::IPCResult RecvGetAnimationOpacity(const LayerHandle& aLayerHandle,
                                                           float* aOpacity,
                                                           bool* aHasAnimationOpacity) override;
@@ -139,19 +142,16 @@ protected:
   virtual mozilla::ipc::IPCResult RecvSetAsyncZoom(const FrameMetrics::ViewID& aId,
                                                    const float& aValue) override;
   virtual mozilla::ipc::IPCResult RecvFlushApzRepaints() override;
   virtual mozilla::ipc::IPCResult RecvGetAPZTestData(APZTestData* aOutData) override;
   virtual mozilla::ipc::IPCResult RecvRequestProperty(const nsString& aProperty, float* aValue) override;
   virtual mozilla::ipc::IPCResult RecvSetConfirmedTargetAPZC(const uint64_t& aBlockId,
                                                              nsTArray<ScrollableLayerGuid>&& aTargets) override;
 
-  virtual PCompositableParent* AllocPCompositableParent(const TextureInfo& aInfo) override;
-  virtual bool DeallocPCompositableParent(PCompositableParent* actor) override;
-
   virtual void ActorDestroy(ActorDestroyReason why) override;
 
   template <typename T>
   bool BindLayer(const RefPtr<Layer>& aLayer, const T& aCreateOp) {
     return BindLayerToHandle(aLayer, aCreateOp.layer());
   }
 
   bool BindLayerToHandle(RefPtr<Layer> aLayer, const LayerHandle& aHandle);
--- a/gfx/layers/ipc/LayersMessages.ipdlh
+++ b/gfx/layers/ipc/LayersMessages.ipdlh
@@ -69,17 +69,17 @@ struct OpCreateImageLayer      { LayerHa
 struct OpCreateColorLayer      { LayerHandle layer; };
 struct OpCreateTextLayer       { LayerHandle layer; };
 struct OpCreateBorderLayer       { LayerHandle layer; };
 struct OpCreateCanvasLayer     { LayerHandle layer; };
 struct OpCreateRefLayer        { LayerHandle layer; };
 
 struct OpAttachCompositable {
   LayerHandle layer;
-  PCompositable compositable;
+  CompositableHandle compositable;
 };
 
 struct OpAttachAsyncCompositable {
   LayerHandle layer;
   CompositableHandle compositable;
 };
 
 struct ThebesBufferData {
@@ -465,17 +465,17 @@ union CompositableOperationDetail {
   OpRemoveTexture;
 
   OpUseTexture;
   OpUseComponentAlphaTextures;
   OpUseOverlaySource;
 };
 
 struct CompositableOperation {
-  PCompositable compositable;
+  CompositableHandle compositable;
   CompositableOperationDetail detail;
 };
 
 // A unit of a changeset; a set of these comprise a changeset
 // If adding a new edit type that requires the hit testing tree to be updated,
 // set the updateHitTestingTree flag to true in RecvUpdate()
 union Edit {
   OpCreatePaintedLayer;
@@ -503,23 +503,23 @@ union Edit {
 
   CompositableOperation;
 };
 
 // Operations related to destroying resources, always handled after the other
 // operations for safety.
 union OpDestroy {
   PTexture;
-  PCompositable;
+  CompositableHandle;
 };
 
 // Replies to operations
 
 struct OpContentBufferSwap {
-  PCompositable compositable;
+  CompositableHandle compositable;
   nsIntRegion frontUpdatedRegion;
 };
 
 /**
  * An ImageCompositeNotification is sent the first time a particular
  * image is composited by an ImageHost.
  */
 struct ImageCompositeNotification {
--- a/gfx/layers/ipc/PCompositable.ipdl
+++ b/gfx/layers/ipc/PCompositable.ipdl
@@ -9,17 +9,16 @@ include protocol PLayerTransaction;
 include protocol PImageBridge;
 include protocol PCompositorBridge;
 
 namespace mozilla {
 namespace layers {
 
 async protocol PCompositable
 {
-    manager PImageBridge or PLayerTransaction;
 child:
     async __delete__();
 parent:
     /**
      * Asynchronously tell the compositor side to remove the texture.
      */
     async Destroy();
 };
--- a/gfx/layers/ipc/PImageBridge.ipdl
+++ b/gfx/layers/ipc/PImageBridge.ipdl
@@ -1,38 +1,37 @@
 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 include LayersSurfaces;
 include LayersMessages;
-include protocol PCompositable;
 include protocol PTexture;
 include ProtocolTypes;
 include protocol PMediaSystemResourceManager;
 
 include "mozilla/GfxMessageUtils.h";
 
 using struct mozilla::layers::TextureInfo from "mozilla/layers/CompositorTypes.h";
 using mozilla::layers::TextureFlags from "mozilla/layers/CompositorTypes.h";
+using mozilla::layers::CompositableHandle from "mozilla/layers/LayersTypes.h";
 
 using PlatformThreadId from "base/platform_thread.h";
 
 namespace mozilla {
 namespace layers {
 
 /**
  * The PImageBridge protocol is used to allow isolated threads or processes to push
  * frames directly to the compositor thread/process without relying on the main thread
  * which might be too busy dealing with content script.
  */
 sync protocol PImageBridge
 {
-  manages PCompositable;
   manages PTexture;
   manages PMediaSystemResourceManager;
 
 child:
   async ParentAsyncMessages(AsyncParentMessageData[] aMessages);
 
   async DidComposite(ImageCompositeNotification[] aNotifications);
 
@@ -48,18 +47,19 @@ parent:
   // in a state in which it can't send asynchronous messages
   // so as to not race with the channel getting closed.
   // In the child side, the Closing the channel does not happen right after WillClose,
   // it is scheduled in the ImageBridgeChild's message queue in order to ensure
   // that all of the messages from the parent side have been received and processed
   // before sending closing the channel.
   sync WillClose();
 
-  async PCompositable(TextureInfo aInfo, uint64_t aId);
   async PTexture(SurfaceDescriptor aSharedData, LayersBackend aBackend, TextureFlags aTextureFlags, uint64_t aSerial);
   async PMediaSystemResourceManager();
 
+  sync NewCompositable(CompositableHandle aHandle, TextureInfo aInfo);
+  async ReleaseCompositable(CompositableHandle aHandle);
 };
 
 
 } // namespace
 } // namespace
 
--- a/gfx/layers/ipc/PLayerTransaction.ipdl
+++ b/gfx/layers/ipc/PLayerTransaction.ipdl
@@ -2,30 +2,30 @@
  * vim: sw=2 ts=8 et :
  */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 include LayersSurfaces;
 include LayersMessages;
-include protocol PCompositable;
 include protocol PCompositorBridge;
 include protocol PRenderFrame;
 include protocol PTexture;
 
 include "mozilla/GfxMessageUtils.h";
 
 using struct mozilla::layers::TextureInfo from "mozilla/layers/CompositorTypes.h";
 using struct mozilla::void_t from "ipc/IPCMessageUtils.h";
 using class mozilla::layers::APZTestData from "mozilla/layers/APZTestData.h";
 using mozilla::layers::FrameMetrics::ViewID from "FrameMetrics.h";
 using struct mozilla::layers::ScrollableLayerGuid from "FrameMetrics.h";
 using mozilla::layers::LayersBackend from "mozilla/layers/LayersTypes.h";
 using mozilla::layers::LayerHandle from "mozilla/layers/LayersTypes.h";
+using mozilla::layers::CompositableHandle from "mozilla/layers/LayersTypes.h";
 
 /**
  * The layers protocol is spoken between thread contexts that manage
  * layer (sub)trees.  The protocol comprises atomically publishing
  * layer subtrees to a "shadow" thread context (which grafts the
  * subtree into its own tree), and atomically updating a published
  * subtree.  ("Atomic" in this sense is wrt painting.)
  */
@@ -43,35 +43,36 @@ union MaybeTransform {
  * The "browser" can be a top-level browser window, in which case the PLayer-
  * TransactionChild exists in the UI process. The "browser" can also be a content
  * tab, in which case the PLayerTransactionChild exists in the content process.
  * In either case, the PLayerTransactionParent exists in the GPU process (if
  * there is one) or the UI process otherwise.
  */
 sync protocol PLayerTransaction {
   manager PCompositorBridge;
-  manages PCompositable;
 
 parent:
-  async PCompositable(TextureInfo aTextureInfo);
-
   // The isFirstPaint flag can be used to indicate that this is the first update
   // for a particular document.
   sync Update(TransactionInfo txn) returns (EditReply[] reply);
 
   async PaintTime(uint64_t id, TimeDuration paintTime);
 
   // We don't need to send a sync transaction if
   // no transaction operate require a swap.
   async UpdateNoSwap(TransactionInfo txn);
 
   async SetLayerObserverEpoch(uint64_t layerObserverEpoch);
 
-  // Release a layer that is no longer in use.
+  // Create a new Compositable.
+  async NewCompositable(CompositableHandle handle, TextureInfo info);
+
+  // Release an object that is no longer in use.
   async ReleaseLayer(LayerHandle layer);
+  async ReleaseCompositable(CompositableHandle compositable);
 
   // Testing APIs
 
   // Enter test mode, set the sample time to sampleTime, and resample
   // animations. sampleTime must not be null.
   sync SetTestSampleTime(TimeStamp sampleTime);
   // Leave test mode and resume normal compositing
   sync LeaveTestMode();
--- a/gfx/layers/ipc/ShadowLayers.cpp
+++ b/gfx/layers/ipc/ShadowLayers.cpp
@@ -378,34 +378,34 @@ ShadowLayerForwarder::UseTiledLayerBuffe
                                           const SurfaceDescriptorTiles& aTileLayerDescriptor)
 {
   MOZ_ASSERT(aCompositable);
 
   if (!aCompositable->IsConnected()) {
     return;
   }
 
-  mTxn->AddNoSwapPaint(CompositableOperation(nullptr, aCompositable->GetIPDLActor(),
+  mTxn->AddNoSwapPaint(CompositableOperation(aCompositable->GetIPCHandle(),
                                              OpUseTiledLayerBuffer(aTileLayerDescriptor)));
 }
 
 void
 ShadowLayerForwarder::UpdateTextureRegion(CompositableClient* aCompositable,
                                           const ThebesBufferData& aThebesBufferData,
                                           const nsIntRegion& aUpdatedRegion)
 {
   MOZ_ASSERT(aCompositable);
 
   if (!aCompositable->IsConnected()) {
     return;
   }
 
   mTxn->AddPaint(
     CompositableOperation(
-      nullptr, aCompositable->GetIPDLActor(),
+      aCompositable->GetIPCHandle(),
       OpPaintTextureRegion(aThebesBufferData, aUpdatedRegion)));
 }
 
 void
 ShadowLayerForwarder::UseTextures(CompositableClient* aCompositable,
                                   const nsTArray<TimedTextureClient>& aTextures)
 {
   MOZ_ASSERT(aCompositable);
@@ -431,51 +431,51 @@ ShadowLayerForwarder::UseTextures(Compos
 
       // We use IMMEDIATE_UPLOAD when we want to be sure that the upload cannot
       // race with updates on the main thread. In this case we want the transaction
       // to be synchronous.
       mTxn->MarkSyncTransaction();
     }
     mClientLayerManager->GetCompositorBridgeChild()->HoldUntilCompositableRefReleasedIfNecessary(t.mTextureClient);
   }
-  mTxn->AddEdit(CompositableOperation(nullptr, aCompositable->GetIPDLActor(),
+  mTxn->AddEdit(CompositableOperation(aCompositable->GetIPCHandle(),
                                       OpUseTexture(textures)));
 }
 
 void
 ShadowLayerForwarder::UseComponentAlphaTextures(CompositableClient* aCompositable,
                                                 TextureClient* aTextureOnBlack,
                                                 TextureClient* aTextureOnWhite)
 {
   MOZ_ASSERT(aCompositable);
 
   if (!aCompositable->IsConnected()) {
     return;
   }
 
   MOZ_ASSERT(aTextureOnWhite);
   MOZ_ASSERT(aTextureOnBlack);
-  MOZ_ASSERT(aCompositable->GetIPDLActor());
+  MOZ_ASSERT(aCompositable->GetIPCHandle());
   MOZ_ASSERT(aTextureOnBlack->GetIPDLActor());
   MOZ_ASSERT(aTextureOnWhite->GetIPDLActor());
   MOZ_ASSERT(aTextureOnBlack->GetSize() == aTextureOnWhite->GetSize());
   MOZ_RELEASE_ASSERT(aTextureOnWhite->GetIPDLActor()->GetIPCChannel() == mShadowManager->GetIPCChannel());
   MOZ_RELEASE_ASSERT(aTextureOnBlack->GetIPDLActor()->GetIPCChannel() == mShadowManager->GetIPCChannel());
 
   ReadLockDescriptor readLockW;
   ReadLockDescriptor readLockB;
   aTextureOnBlack->SerializeReadLock(readLockB);
   aTextureOnWhite->SerializeReadLock(readLockW);
 
   mClientLayerManager->GetCompositorBridgeChild()->HoldUntilCompositableRefReleasedIfNecessary(aTextureOnBlack);
   mClientLayerManager->GetCompositorBridgeChild()->HoldUntilCompositableRefReleasedIfNecessary(aTextureOnWhite);
 
   mTxn->AddEdit(
     CompositableOperation(
-      nullptr, aCompositable->GetIPDLActor(),
+      aCompositable->GetIPCHandle(),
       OpUseComponentAlphaTextures(
         nullptr, aTextureOnBlack->GetIPDLActor(),
         nullptr, aTextureOnWhite->GetIPDLActor(),
         readLockB, readLockW)
       )
     );
 }
 
@@ -496,19 +496,19 @@ AddOpDestroy(Transaction* aTxn, const Op
 
 bool
 ShadowLayerForwarder::DestroyInTransaction(PTextureChild* aTexture, bool synchronously)
 {
   return AddOpDestroy(mTxn, OpDestroy(aTexture), synchronously);
 }
 
 bool
-ShadowLayerForwarder::DestroyInTransaction(PCompositableChild* aCompositable, bool synchronously)
+ShadowLayerForwarder::DestroyInTransaction(const CompositableHandle& aHandle)
 {
-  return AddOpDestroy(mTxn, OpDestroy(aCompositable), synchronously);
+  return AddOpDestroy(mTxn, OpDestroy(aHandle), false);
 }
 
 void
 ShadowLayerForwarder::RemoveTextureFromCompositable(CompositableClient* aCompositable,
                                                     TextureClient* aTexture)
 {
   MOZ_ASSERT(aCompositable);
   MOZ_ASSERT(aTexture);
@@ -516,17 +516,17 @@ ShadowLayerForwarder::RemoveTextureFromC
   MOZ_RELEASE_ASSERT(aTexture->GetIPDLActor()->GetIPCChannel() == mShadowManager->GetIPCChannel());
   if (!aCompositable->IsConnected() || !aTexture->GetIPDLActor()) {
     // We don't have an actor anymore, don't try to use it!
     return;
   }
 
   mTxn->AddEdit(
     CompositableOperation(
-      nullptr, aCompositable->GetIPDLActor(),
+      aCompositable->GetIPCHandle(),
       OpRemoveTexture(nullptr, aTexture->GetIPDLActor())));
   if (aTexture->GetFlags() & TextureFlags::DEALLOCATE_CLIENT) {
     mTxn->MarkSyncTransaction();
   }
 }
 
 bool
 ShadowLayerForwarder::InWorkerThread()
@@ -766,30 +766,39 @@ ShadowLayerForwarder::ProcessReplies(con
 {
   for (const auto& reply : aReplies) {
     switch (reply.type()) {
     case EditReply::TOpContentBufferSwap: {
       MOZ_LAYERS_LOG(("[LayersForwarder] DoubleBufferSwap"));
 
       const OpContentBufferSwap& obs = reply.get_OpContentBufferSwap();
 
-      RefPtr<CompositableClient> compositable =
-        CompositableClient::FromIPDLActor(obs.compositableChild());
+      RefPtr<CompositableClient> compositable = FindCompositable(obs.compositable());
       ContentClientRemote* contentClient = compositable->AsContentClientRemote();
       MOZ_ASSERT(contentClient);
 
       contentClient->SwapBuffers(obs.frontUpdatedRegion());
       break;
     }
     default:
       MOZ_CRASH("not reached");
     }
   }
 }
 
+RefPtr<CompositableClient>
+ShadowLayerForwarder::FindCompositable(const CompositableHandle& aHandle)
+{
+  CompositableClient* client = nullptr;
+  if (!mCompositables.Get(aHandle.Value(), &client)) {
+    return nullptr;
+  }
+  return client;
+}
+
 void
 ShadowLayerForwarder::SetLayerObserverEpoch(uint64_t aLayerObserverEpoch)
 {
   if (!IPCOpen()) {
     return;
   }
   Unused << mShadowManager->SendSetLayerObserverEpoch(aLayerObserverEpoch);
 }
@@ -836,30 +845,33 @@ ShadowLayerForwarder::Connect(Compositab
 #ifdef GFX_COMPOSITOR_LOGGING
   printf("ShadowLayerForwarder::Connect(Compositable)\n");
 #endif
   MOZ_ASSERT(aCompositable);
   MOZ_ASSERT(mShadowManager);
   if (!IPCOpen()) {
     return;
   }
-  PCompositableChild* actor =
-    mShadowManager->SendPCompositableConstructor(aCompositable->GetTextureInfo());
-  if (!actor) {
-    return;
-  }
-  aCompositable->InitIPDLActor(actor, CompositableHandle());
+
+  static uint64_t sNextID = 1;
+  uint64_t id = sNextID++;
+
+  mCompositables.Put(id, aCompositable);
+
+  CompositableHandle handle(id);
+  aCompositable->InitIPDL(handle);
+  mShadowManager->SendNewCompositable(handle, aCompositable->GetTextureInfo());
 }
 
 void ShadowLayerForwarder::Attach(CompositableClient* aCompositable,
                                   ShadowableLayer* aLayer)
 {
   MOZ_ASSERT(aLayer);
   MOZ_ASSERT(aCompositable);
-  mTxn->AddEdit(OpAttachCompositable(Shadow(aLayer), nullptr, aCompositable->GetIPDLActor()));
+  mTxn->AddEdit(OpAttachCompositable(Shadow(aLayer), aCompositable->GetIPCHandle()));
 }
 
 void ShadowLayerForwarder::AttachAsyncCompositable(const CompositableHandle& aHandle,
                                                    ShadowableLayer* aLayer)
 {
   MOZ_ASSERT(aLayer);
   MOZ_ASSERT(aHandle);
   mTxn->AddEdit(OpAttachAsyncCompositable(Shadow(aLayer), aHandle));
@@ -1071,16 +1083,26 @@ void
 ShadowLayerForwarder::SyncWithCompositor()
 {
   auto compositorBridge = GetCompositorBridgeChild();
   if (compositorBridge && compositorBridge->IPCOpen()) {
     compositorBridge->SendSyncWithCompositor();
   }
 }
 
+void
+ShadowLayerForwarder::ReleaseCompositable(const CompositableHandle& aHandle)
+{
+  AssertInForwarderThread();
+  if (!DestroyInTransaction(aHandle)) {
+    mShadowManager->SendReleaseCompositable(aHandle);
+  }
+  mCompositables.Remove(aHandle.Value());
+}
+
 ShadowableLayer::~ShadowableLayer()
 {
   if (mShadow) {
     mForwarder->ReleaseLayer(GetShadow());
   }
 }
 
 } // namespace layers
--- a/gfx/layers/ipc/ShadowLayers.h
+++ b/gfx/layers/ipc/ShadowLayers.h
@@ -246,18 +246,19 @@ public:
                ShadowableLayer* aMaskLayer);
 
   /**
    * See CompositableForwarder::UseTiledLayerBuffer
    */
   void UseTiledLayerBuffer(CompositableClient* aCompositable,
                                    const SurfaceDescriptorTiles& aTileLayerDescriptor) override;
 
+  void ReleaseCompositable(const CompositableHandle& aHandle) override;
   bool DestroyInTransaction(PTextureChild* aTexture, bool synchronously) override;
-  bool DestroyInTransaction(PCompositableChild* aCompositable, bool synchronously) override;
+  bool DestroyInTransaction(const CompositableHandle& aHandle);
 
   virtual void RemoveTextureFromCompositable(CompositableClient* aCompositable,
                                              TextureClient* aTexture) override;
 
   /**
    * Communicate to the compositor that aRegion in the texture identified by aLayer
    * and aIdentifier has been updated to aThebesBuffer.
    */
@@ -416,16 +417,18 @@ protected:
 #ifdef DEBUG
   void CheckSurfaceDescriptor(const SurfaceDescriptor* aDescriptor) const;
 #else
   void CheckSurfaceDescriptor(const SurfaceDescriptor* aDescriptor) const {}
 #endif
 
   void ProcessReplies(const nsTArray<EditReply>& aReplies);
 
+  RefPtr<CompositableClient> FindCompositable(const CompositableHandle& aHandle);
+
   bool InWorkerThread();
 
   CompositorBridgeChild* GetCompositorBridgeChild();
 
   RefPtr<LayerTransactionChild> mShadowManager;
   RefPtr<CompositorBridgeChild> mCompositorBridgeChild;
 
 private:
@@ -435,16 +438,17 @@ private:
   MessageLoop* mMessageLoop;
   DiagnosticTypes mDiagnosticTypes;
   bool mIsFirstPaint;
   bool mWindowOverlayChanged;
   int32_t mPaintSyncId;
   InfallibleTArray<PluginWindowData> mPluginWindowData;
   UniquePtr<ActiveResourceTracker> mActiveResourceTracker;
   uint64_t mNextLayerHandle;
+  nsDataHashtable<nsUint64HashKey, CompositableClient*> mCompositables;
 };
 
 class CompositableClient;
 
 /**
  * A ShadowableLayer is a Layer can be shared with a parent context
  * through a ShadowLayerForwarder.  A ShadowableLayer maps to a
  * Shadow*Layer in a parent context.