Bug 897452 - Part 1 - Implement the PTexture protocol - r=mattwoodrow
☠☠ backed out by ff1bf2049ecf ☠ ☠
authorNicolas Silva <nical@mozilla.com>
Wed, 11 Dec 2013 13:05:09 -0500
changeset 175973 eb1fe464fdafca11118d775096a3eb293e562020
parent 175972 07deaa53b6fd2b66e4cf300dfcd8df9bbe80030e
child 175974 7aec6387f3e96adf7207e48e6ff41d6e5cc8302d
push id3343
push userffxbld
push dateMon, 17 Mar 2014 21:55:32 +0000
treeherdermozilla-beta@2f7d3415f79f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmattwoodrow
bugs897452
milestone29.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
Bug 897452 - Part 1 - Implement the PTexture protocol - r=mattwoodrow
gfx/layers/client/ClientLayerManager.cpp
gfx/layers/client/CompositableClient.cpp
gfx/layers/client/CompositableClient.h
gfx/layers/client/TextureClient.cpp
gfx/layers/client/TextureClient.h
gfx/layers/composite/CompositableHost.cpp
gfx/layers/composite/TextureHost.cpp
gfx/layers/composite/TextureHost.h
gfx/layers/ipc/CompositableForwarder.h
gfx/layers/ipc/CompositableTransactionParent.cpp
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/PImageBridge.ipdl
gfx/layers/ipc/PLayerTransaction.ipdl
gfx/layers/ipc/PTexture.ipdl
gfx/layers/ipc/ShadowLayerUtilsGralloc.cpp
gfx/layers/ipc/ShadowLayerUtilsGralloc.h
gfx/layers/ipc/ShadowLayers.cpp
gfx/layers/ipc/ShadowLayers.h
gfx/layers/moz.build
--- a/gfx/layers/client/ClientLayerManager.cpp
+++ b/gfx/layers/client/ClientLayerManager.cpp
@@ -364,24 +364,18 @@ ClientLayerManager::ForwardTransaction()
           static_cast<CompositableChild*>(ots.compositableChild());
         MOZ_ASSERT(compositableChild);
 
         compositableChild->GetCompositableClient()
           ->SetDescriptorFromReply(ots.textureId(), ots.image());
         break;
       }
       case EditReply::TReplyTextureRemoved: {
-        // XXX - to manage reuse of gralloc buffers, we'll need to add some
-        // glue code here to find the TextureClient and invoke a callback to
-        // let the camera know that the gralloc buffer is not used anymore on
-        // the compositor side and that it can reuse it.
-        const ReplyTextureRemoved& rep = reply.get_ReplyTextureRemoved();
-        CompositableClient* compositable
-          = static_cast<CompositableChild*>(rep.compositableChild())->GetCompositableClient();
-        compositable->OnReplyTextureRemoved(rep.textureId());
+        // XXX - The logic to remove textures is implemented in the next patch
+        // of the same bug (897452). They will land together.
         break;
       }
 
       default:
         NS_RUNTIMEABORT("not reached");
       }
     }
 
--- a/gfx/layers/client/CompositableClient.cpp
+++ b/gfx/layers/client/CompositableClient.cpp
@@ -31,33 +31,16 @@ CompositableClient::CompositableClient(C
   MOZ_COUNT_CTOR(CompositableClient);
 }
 
 
 CompositableClient::~CompositableClient()
 {
   MOZ_COUNT_DTOR(CompositableClient);
   Destroy();
-
-  FlushTexturesToRemoveCallbacks();
-  MOZ_ASSERT(mTexturesToRemove.Length() == 0, "would leak textures pending for deletion");
-}
-
-void
-CompositableClient::FlushTexturesToRemoveCallbacks()
-{
-  std::map<uint64_t,TextureClientData*>::iterator it
-    = mTexturesToRemoveCallbacks.begin();
-  std::map<uint64_t,TextureClientData*>::iterator stop
-    = mTexturesToRemoveCallbacks.end();
-  for (; it != stop; ++it) {
-    it->second->DeallocateSharedData(GetForwarder());
-    delete it->second;
-  }
-  mTexturesToRemoveCallbacks.clear();
 }
 
 LayersBackend
 CompositableClient::GetCompositorBackendType() const
 {
   return mForwarder->GetCompositorBackendType();
 }
 
@@ -262,55 +245,30 @@ CompositableClient::NextTextureID()
 
   return mNextTextureID;
 }
 
 bool
 CompositableClient::AddTextureClient(TextureClient* aClient)
 {
   aClient->SetID(NextTextureID());
-  return mForwarder->AddTexture(this, aClient);
+  return aClient->InitIPDLActor(mForwarder);
 }
 
 void
 CompositableClient::RemoveTextureClient(TextureClient* aClient)
 {
   MOZ_ASSERT(aClient);
-  mTexturesToRemove.AppendElement(TextureIDAndFlags(aClient->GetID(),
-                                                    aClient->GetFlags()));
-  if (aClient->GetFlags() & TEXTURE_DEALLOCATE_CLIENT) {
-    TextureClientData* data = aClient->DropTextureData();
-    if (data) {
-      mTexturesToRemoveCallbacks[aClient->GetID()] = data;
-    }
-  }
-  aClient->ClearID();
+  mForwarder->RemoveTexture(aClient);
   aClient->MarkInvalid();
 }
 
 void
-CompositableClient::OnReplyTextureRemoved(uint64_t aTextureID)
-{
-  std::map<uint64_t,TextureClientData*>::iterator it
-    = mTexturesToRemoveCallbacks.find(aTextureID);
-  if (it != mTexturesToRemoveCallbacks.end()) {
-    it->second->DeallocateSharedData(GetForwarder());
-    delete it->second;
-    mTexturesToRemoveCallbacks.erase(it);
-  }
-}
-
-void
 CompositableClient::OnTransaction()
 {
-  for (unsigned i = 0; i < mTexturesToRemove.Length(); ++i) {
-    const TextureIDAndFlags& texture = mTexturesToRemove[i];
-    mForwarder->RemoveTexture(this, texture.mID, texture.mFlags);
-  }
-  mTexturesToRemove.Clear();
 }
 
 
 void
 CompositableChild::ActorDestroy(ActorDestroyReason why)
 {
   if (mCompositableClient && why == AbnormalShutdown) {
     mCompositableClient->OnActorDestroy();
--- a/gfx/layers/client/CompositableClient.h
+++ b/gfx/layers/client/CompositableClient.h
@@ -144,53 +144,24 @@ public:
   virtual void OnTransaction();
 
   /**
    * A hook for the when the Compositable is detached from it's layer.
    */
   virtual void OnDetach() {}
 
   /**
-   * When texture deallocation must happen on the client side, we need to first
-   * ensure that the compositor has already let go of the data in order
-   * to safely deallocate it.
-   *
-   * This is implemented by registering a callback to postpone deallocation or
-   * recycling of the shared data.
-   *
-   * This hook is called when the compositor notifies the client that it is not
-   * holding any more references to the shared data so that this compositable
-   * can run the corresponding callback.
-   */
-  void OnReplyTextureRemoved(uint64_t aTextureID);
-
-  /**
-   * Run all he registered callbacks (see the comment for OnReplyTextureRemoved).
-   * Only call this if you know what you are doing.
-   */
-  void FlushTexturesToRemoveCallbacks();
-
-  /**
    * Our IPDL actor is being destroyed, get rid of any shmem resources now.
    */
   virtual void OnActorDestroy() = 0;
 
 protected:
   // return the next texture ID
   uint64_t NextTextureID();
 
-  struct TextureIDAndFlags {
-    TextureIDAndFlags(uint64_t aID, TextureFlags aFlags)
-    : mID(aID), mFlags(aFlags) {}
-    uint64_t mID;
-    TextureFlags mFlags;
-  };
-  // The textures to destroy in the next transaction;
-  nsTArray<TextureIDAndFlags> mTexturesToRemove;
-  std::map<uint64_t, TextureClientData*> mTexturesToRemoveCallbacks;
   uint64_t mNextTextureID;
   CompositableChild* mCompositableChild;
   CompositableForwarder* mForwarder;
 };
 
 /**
  * IPDL actor used by CompositableClient to match with its corresponding
  * CompositableHost on the compositor side.
--- a/gfx/layers/client/TextureClient.cpp
+++ b/gfx/layers/client/TextureClient.cpp
@@ -14,16 +14,17 @@
 #include "mozilla/ipc/SharedMemory.h"   // for SharedMemory, etc
 #include "mozilla/layers/CompositableClient.h"  // for CompositableClient
 #include "mozilla/layers/CompositableForwarder.h"
 #include "mozilla/layers/ISurfaceAllocator.h"
 #include "mozilla/layers/ImageDataSerializer.h"
 #include "mozilla/layers/ShadowLayers.h"  // for ShadowLayerForwarder
 #include "mozilla/layers/SharedPlanarYCbCrImage.h"
 #include "mozilla/layers/YCbCrImageDataSerializer.h"
+#include "mozilla/layers/PTextureChild.h"
 #include "nsDebug.h"                    // for NS_ASSERTION, NS_WARNING, etc
 #include "nsTraceRefcnt.h"              // for MOZ_COUNT_CTOR, etc
 #include "ImageContainer.h"             // for PlanarYCbCrImage, etc
 #include "mozilla/gfx/2D.h"
 
 #ifdef MOZ_ANDROID_OMTC
 #  include "gfxReusableImageSurfaceWrapper.h"
 #  include "gfxImageSurface.h"
@@ -33,16 +34,57 @@
 #endif
 
 using namespace mozilla::gl;
 using namespace mozilla::gfx;
 
 namespace mozilla {
 namespace layers {
 
+class TextureChild : public PTextureChild
+{
+public:
+
+};
+
+// static
+PTextureChild*
+TextureClient::CreateIPDLActor()
+{
+  return new TextureChild();
+}
+
+// static
+bool
+TextureClient::DestroyIPDLActor(PTextureChild* actor)
+{
+  delete actor;
+  return true;
+}
+
+bool
+TextureClient::InitIPDLActor(CompositableForwarder* aForwarder)
+{
+  MOZ_ASSERT(!mActor);
+  SurfaceDescriptor desc;
+  if (!ToSurfaceDescriptor(desc)) {
+    return false;
+  }
+
+  mActor = static_cast<TextureChild*>(aForwarder->CreateEmptyTextureChild());
+  mShared = true;
+  return mActor->SendInit(desc, GetFlags());
+}
+
+PTextureChild*
+TextureClient::GetIPDLActor()
+{
+  return mActor;
+}
+
 class ShmemTextureClientData : public TextureClientData
 {
 public:
   ShmemTextureClientData(ipc::Shmem& aShmem)
   : mShmem(aShmem)
   {
     MOZ_COUNT_CTOR(ShmemTextureClientData);
   }
@@ -107,16 +149,17 @@ ShmemTextureClient::DropTextureData()
   TextureClientData* result = new ShmemTextureClientData(mShmem);
   MarkInvalid();
   mShmem = ipc::Shmem();
   return result;
 }
 
 TextureClient::TextureClient(TextureFlags aFlags)
   : mRefCount(0)
+  , mActor(nullptr)
   , mID(0)
   , mFlags(aFlags)
   , mShared(false)
   , mValid(true)
 {}
 
 TextureClient::~TextureClient()
 {}
--- a/gfx/layers/client/TextureClient.h
+++ b/gfx/layers/client/TextureClient.h
@@ -34,16 +34,18 @@ namespace layers {
 
 class ContentClient;
 class CompositableForwarder;
 class ISurfaceAllocator;
 class CompositableClient;
 class PlanarYCbCrImage;
 class PlanarYCbCrData;
 class Image;
+class PTextureChild;
+class TextureChild;
 
 /**
  * TextureClient is the abstraction that allows us to share data between the
  * content and the compositor side.
  * TextureClient can also provide with some more "producer" facing APIs
  * such as TextureClientSurface and TextureClientYCbCr, that can be queried
  * using AsTextureCLientSurface(), etc.
  */
@@ -188,16 +190,27 @@ public:
   /**
    * Returns true if this texture has a lock/unlock mechanism.
    * Textures that do not implement locking should be immutable or should
    * use immediate uploads (see TextureFlags in CompositorTypes.h)
    */
   virtual bool ImplementsLocking() const { return false; }
 
   /**
+   * Allocate and deallocate a TextureChild actor.
+   *
+   * TextureChild is an implementation detail of TextureHost that is not
+   * exposed to the rest of the code base. CreateIPDLActor and DestroyIPDLActor
+   * are for use with the maging IPDL protocols only (so that they can
+   * implement AllocPextureChild and DeallocPTextureChild).
+   */
+  static PTextureChild* CreateIPDLActor();
+  static bool DestroyIPDLActor(PTextureChild* actor);
+
+  /**
    * Sets this texture's ID.
    *
    * This ID is used to match a texture client with his corresponding TextureHost.
    * Only the CompositableClient should be allowed to set or clear the ID.
    * Zero is always an invalid ID.
    * For a given compositableClient, there can never be more than one texture
    * client with the same non-zero ID.
    * Texture clients from different compositables may have the same ID.
@@ -264,16 +277,31 @@ public:
    * anymore. This usually means it will soon be destroyed.
    */
   void MarkInvalid() { mValid = false; }
 
   // If a texture client holds a reference to shmem, it should override this
   // method to forget about the shmem _without_ releasing it.
   virtual void OnActorDestroy() {}
 
+  /**
+   * Create and init the TextureChild/Parent IPDL actor pair.
+   *
+   * Should be called only once per TextureClient.
+   */
+  bool InitIPDLActor(CompositableForwarder* aForwarder);
+
+  /**
+   * Return a pointer to the IPDLActor.
+   *
+   * This is to be used with IPDL messages only. Do not store the returned
+   * pointer.
+   */
+  PTextureChild* GetIPDLActor();
+
 private:
   Atomic<int> mRefCount;
 
   /**
    * Called once, just before the destructor.
    *
    * Here goes the shut-down code that uses virtual methods.
    * Must only be called by Release().
@@ -285,16 +313,17 @@ private:
 
 protected:
   void AddFlags(TextureFlags  aFlags)
   {
     MOZ_ASSERT(!IsSharedWithCompositor());
     mFlags |= aFlags;
   }
 
+  TextureChild* mActor;
   uint64_t mID;
   TextureFlags mFlags;
   bool mShared;
   bool mValid;
 };
 
 /**
  * TextureClient that wraps a random access buffer such as a Shmem or raw memory.
--- a/gfx/layers/composite/CompositableHost.cpp
+++ b/gfx/layers/composite/CompositableHost.cpp
@@ -47,16 +47,17 @@ CompositableHost::~CompositableHost()
 }
 
 void
 CompositableHost::UseTextureHost(TextureHost* aTexture)
 {
   if (!aTexture) {
     return;
   }
+  aTexture->SetCompositableBackendSpecificData(GetCompositableBackendSpecificData());
   aTexture->SetCompositor(GetCompositor());
 }
 
 
 void
 CompositableHost::AddTextureHost(TextureHost* aTexture)
 {
   MOZ_ASSERT(aTexture);
--- a/gfx/layers/composite/TextureHost.cpp
+++ b/gfx/layers/composite/TextureHost.cpp
@@ -13,22 +13,72 @@
 #include "mozilla/layers/Compositor.h"  // for Compositor
 #include "mozilla/layers/ISurfaceAllocator.h"  // for ISurfaceAllocator
 #include "mozilla/layers/ImageDataSerializer.h"
 #include "mozilla/layers/LayersSurfaces.h"  // for SurfaceDescriptor, etc
 #include "mozilla/layers/YCbCrImageDataSerializer.h"
 #include "nsAString.h"
 #include "nsAutoPtr.h"                  // for nsRefPtr
 #include "nsPrintfCString.h"            // for nsPrintfCString
+#include "mozilla/layers/PTextureParent.h"
 
 struct nsIntPoint;
 
 namespace mozilla {
 namespace layers {
 
+/**
+ * TextureParent is the host-side IPDL glue between TextureClient and TextureHost.
+ * It is an IPDL actor just like LayerParent, CompositableParent, etc.
+ */
+class TextureParent : public PTextureParent
+{
+public:
+  TextureParent(ISurfaceAllocator* aAllocator);
+
+  ~TextureParent();
+
+  bool RecvInit(const SurfaceDescriptor& aSharedData,
+                const TextureFlags& aFlags) MOZ_OVERRIDE;
+
+  TextureHost* GetTextureHost() { return mTextureHost; }
+
+  ISurfaceAllocator* mAllocator;
+  RefPtr<TextureHost> mTextureHost;
+};
+
+// static
+PTextureParent*
+TextureHost::CreateIPDLActor(ISurfaceAllocator* aAllocator)
+{
+  return new TextureParent(aAllocator);
+}
+
+// static
+bool
+TextureHost::DestroyIPDLActor(PTextureParent* actor)
+{
+  delete actor;
+  return true;
+}
+
+// static
+bool
+TextureHost::SendDeleteIPDLActor(PTextureParent* actor)
+{
+  return PTextureParent::Send__delete__(actor);
+}
+
+// static
+TextureHost*
+TextureHost::AsTextureHost(PTextureParent* actor)
+{
+  return actor? static_cast<TextureParent*>(actor)->mTextureHost : nullptr;
+}
+
 // implemented in TextureOGL.cpp
 TemporaryRef<DeprecatedTextureHost> CreateDeprecatedTextureHostOGL(SurfaceDescriptorType aDescriptorType,
                                                            uint32_t aDeprecatedTextureHostFlags,
                                                            uint32_t aTextureFlags);
 // implemented in BasicCompositor.cpp
 TemporaryRef<DeprecatedTextureHost> CreateBasicDeprecatedTextureHost(SurfaceDescriptorType aDescriptorType,
                                                              uint32_t aDeprecatedTextureHostFlags,
                                                              uint32_t aTextureFlags);
@@ -571,10 +621,33 @@ MemoryTextureHost::DeallocateSharedData(
   mBuffer = nullptr;
 }
 
 uint8_t* MemoryTextureHost::GetBuffer()
 {
   return mBuffer;
 }
 
+TextureParent::TextureParent(ISurfaceAllocator* aAllocator)
+: mAllocator(aAllocator)
+{
+  MOZ_COUNT_CTOR(TextureParent);
+}
+
+TextureParent::~TextureParent()
+{
+  MOZ_COUNT_DTOR(TextureParent);
+  mTextureHost = nullptr;
+}
+
+bool
+TextureParent::RecvInit(const SurfaceDescriptor& aSharedData,
+                        const TextureFlags& aFlags)
+{
+  mTextureHost = TextureHost::Create(0, // XXX legacy texture id, see subsequent patch
+                                     aSharedData,
+                                     mAllocator,
+                                     aFlags);
+  return !!mTextureHost;
+}
+
 } // namespace
 } // namespace
--- a/gfx/layers/composite/TextureHost.h
+++ b/gfx/layers/composite/TextureHost.h
@@ -41,18 +41,19 @@ class Compositor;
 class CompositableHost;
 class CompositableBackendSpecificData;
 class SurfaceDescriptor;
 class ISurfaceAllocator;
 class TextureSourceOGL;
 class TextureSourceD3D9;
 class TextureSourceD3D11;
 class TextureSourceBasic;
+class DataTextureSource;
+class PTextureParent;
 class TextureParent;
-class DataTextureSource;
 
 /**
  * A view on a TextureHost where the texture is internally represented as tiles
  * (contrast with a tiled buffer, where each texture is a tile). For iteration by
  * the texture's buffer host.
  * This is only useful when the underlying surface is too big to fit in one
  * device texture, which forces us to split it in smaller parts.
  * Tiled Compositable is a different thing.
@@ -367,16 +368,37 @@ public:
   /**
    * XXX - Flags should only be set at creation time, this will be removed.
    */
   void AddFlag(TextureFlags aFlag) { mFlags |= aFlag; }
 
   TextureFlags GetFlags() { return mFlags; }
 
   /**
+   * Allocate and deallocate a TextureParent actor.
+   *
+   * TextureParent< is an implementation detail of TextureHost that is not
+   * exposed to the rest of the code base. CreateIPDLActor and DestroyIPDLActor
+   * are for use with the managing IPDL protocols only (so that they can
+   * implement AllocPTextureParent and DeallocPTextureParent).
+   */
+  static PTextureParent* CreateIPDLActor(ISurfaceAllocator* aAllocator);
+  static bool DestroyIPDLActor(PTextureParent* actor);
+
+  /**
+   * Destroy the TextureChild/Parent pair.
+   */
+  static bool SendDeleteIPDLActor(PTextureParent* actor);
+
+  /**
+   * Get the TextureHost corresponding to the actor passed in parameter.
+   */
+  static TextureHost* AsTextureHost(PTextureParent* actor);
+
+  /**
    * Specific to B2G's Composer2D
    * XXX - more doc here
    */
   virtual LayerRenderState GetRenderState()
   {
     // By default we return an empty render state, this should be overridden
     // by the TextureHost implementations that are used on B2G with Composer2D
     return LayerRenderState();
--- a/gfx/layers/ipc/CompositableForwarder.h
+++ b/gfx/layers/ipc/CompositableForwarder.h
@@ -24,16 +24,18 @@ namespace layers {
 class CompositableClient;
 class TextureFactoryIdentifier;
 class SurfaceDescriptor;
 class SurfaceDescriptorTiles;
 class ThebesBufferData;
 class DeprecatedTextureClient;
 class TextureClient;
 class BasicTiledLayerBuffer;
+class PTextureChild;
+class TextureClientData;
 
 /**
  * A transaction is a set of changes that happenned on the content side, that
  * should be sent to the compositor side.
  * CompositableForwarder is an interface to manage a transaction of
  * compositable objetcs.
  *
  * ShadowLayerForwarder is an example of a CompositableForwarder (that can
@@ -89,16 +91,24 @@ public:
    * that is TextureClient/Hosts.
    */
   virtual void DestroyThebesBuffer(CompositableClient* aCompositable) = 0;
 
   virtual void PaintedTiledLayerBuffer(CompositableClient* aCompositable,
                                        const SurfaceDescriptorTiles& aTiledDescriptor) = 0;
 
   /**
+   * Create an unitialized TextureChild.
+   *
+   * This does not trigger the the creation of a TextureHost on the compositor
+   * side (see PTexture::Init).
+   */
+  virtual PTextureChild* CreateEmptyTextureChild() = 0;
+
+  /**
    * Communicate to the compositor that the texture identified by aCompositable
    * and aTextureId has been updated to aImage.
    */
   virtual void UpdateTexture(CompositableClient* aCompositable,
                              TextureIdentifier aTextureId,
                              SurfaceDescriptor* aDescriptor) = 0;
 
   /**
@@ -145,35 +155,24 @@ public:
    * posted to the parent.  During the parent-side transaction, the
    * shadow is told to destroy its front buffer.  This can happen when
    * a new front/back buffer pair have been created because of a layer
    * resize, e.g.
    */
   virtual void DestroyedThebesBuffer(const SurfaceDescriptor& aBackBufferToDestroy) = 0;
 
   /**
-   * Tell the compositor side to create a TextureHost that corresponds to
-   * aClient.
+   * Tell the compositor side to delete the TextureHost corresponding to the
+   * TextureClient passed in parameter.
    */
-  virtual bool AddTexture(CompositableClient* aCompositable,
-                          TextureClient* aClient) = 0;
-
-  /**
-   * Tell the compositor side to delete the TextureHost corresponding to
-   * aTextureID.
-   * By default the shared Data is deallocated along with the TextureHost, but
-   * this behaviour can be overriden by the TextureFlags passed here.
-   * XXX - This is kind of bad, but for now we have to do this, because of some
-   * edge cases caused by the lifetime of the TextureHost being limited by the
-   * lifetime of the CompositableHost. We should be able to remove this flags
-   * parameter when we remove the lifetime constraint.
-   */
-  virtual void RemoveTexture(CompositableClient* aCompositable,
-                             uint64_t aTextureID,
-                             TextureFlags aFlags) = 0;
+  virtual void RemoveTexture(TextureClient* aTexture)
+  {
+    // XXX - this part is incomplete. The removing textures is implemented
+    // in a subsequent patch of the same bug (897452).
+  }
 
   /**
    * Tell the CompositableHost on the compositor side what texture to use for
    * the next composition.
    */
   virtual void UseTexture(CompositableClient* aCompositable,
                           TextureClient* aClient) = 0;
 
--- a/gfx/layers/ipc/CompositableTransactionParent.cpp
+++ b/gfx/layers/ipc/CompositableTransactionParent.cpp
@@ -217,91 +217,56 @@ CompositableParentManager::ReceiveCompos
       NS_ASSERTION(tileComposer, "compositable is not a tile composer");
 
       const SurfaceDescriptorTiles& tileDesc = op.tileLayerDescriptor();
       tileComposer->PaintedTiledLayerBuffer(this, tileDesc);
       break;
     }
     case CompositableOperation::TOpUseTexture: {
       const OpUseTexture& op = aEdit.get_OpUseTexture();
-      if (op.textureID() == 0) {
-        NS_WARNING("Invalid texture ID");
-        break;
-      }
       CompositableHost* compositable = AsCompositable(op);
-      RefPtr<TextureHost> tex = compositable->GetTextureHost(op.textureID());
+      RefPtr<TextureHost> tex = TextureHost::AsTextureHost(op.textureParent());
 
       MOZ_ASSERT(tex.get());
       compositable->UseTextureHost(tex);
 
       if (IsAsync()) {
         ScheduleComposition(op);
       }
       break;
     }
-    case CompositableOperation::TOpAddTexture: {
-      const OpAddTexture& op = aEdit.get_OpAddTexture();
-      if (op.textureID() == 0) {
-        NS_WARNING("Invalid texture ID");
-        break;
-      }
-      CompositableHost* compositable = AsCompositable(op);
-      RefPtr<TextureHost> tex = TextureHost::Create(op.textureID(),
-                                                    op.data(),
-                                                    this,
-                                                    op.textureFlags());
-      MOZ_ASSERT(tex.get());
-      tex->SetCompositor(compositable->GetCompositor());
-      // set CompositableBackendSpecificData
-      // on gonk, create EGLImage if possible.
-      // create EGLImage during buffer swap could reduce the graphic driver's task
-      // during rendering.
-      compositable->AddTextureHost(tex);
-      MOZ_ASSERT(compositable->GetTextureHost(op.textureID()) == tex.get());
-      break;
-    }
     case CompositableOperation::TOpRemoveTexture: {
       const OpRemoveTexture& op = aEdit.get_OpRemoveTexture();
-      if (op.textureID() == 0) {
-        NS_WARNING("Invalid texture ID");
-        break;
-      }
-      CompositableHost* compositable = AsCompositable(op);
 
-      RefPtr<TextureHost> texture = compositable->GetTextureHost(op.textureID());
+      RefPtr<TextureHost> texture = TextureHost::AsTextureHost(op.textureParent());
       MOZ_ASSERT(texture);
 
       TextureFlags flags = texture->GetFlags();
 
       if (!(flags & TEXTURE_DEALLOCATE_CLIENT) &&
           !(flags & TEXTURE_DEALLOCATE_DEFERRED)) {
         texture->DeallocateSharedData();
       }
 
-      compositable->RemoveTextureHost(texture);
-
       // if it is not the host that deallocates the shared data, then we need
       // to notfy the client side to tell when it is safe to deallocate or
       // reuse it.
       if (flags & TEXTURE_DEALLOCATE_CLIENT) {
-        replyv.push_back(ReplyTextureRemoved(op.compositableParent(), nullptr,
-                                             op.textureID()));
+        replyv.push_back(ReplyTextureRemoved(op.callbackID()));
       }
 
+      TextureHost::SendDeleteIPDLActor(op.textureParent());
+
       break;
     }
     case CompositableOperation::TOpUpdateTexture: {
       const OpUpdateTexture& op = aEdit.get_OpUpdateTexture();
-      if (op.textureID() == 0) {
-        NS_WARNING("Invalid texture ID");
-        break;
-      }
       CompositableHost* compositable = AsCompositable(op);
       MOZ_ASSERT(compositable);
-      RefPtr<TextureHost> texture = compositable->GetTextureHost(op.textureID());
+      RefPtr<TextureHost> texture = TextureHost::AsTextureHost(op.textureParent());
       MOZ_ASSERT(texture);
 
       texture->Updated(op.region().type() == MaybeRegion::TnsIntRegion
                        ? &op.region().get_nsIntRegion()
                        : nullptr); // no region means invalidate the entire surface
 
 
       compositable->UseTextureHost(texture);
--- a/gfx/layers/ipc/ImageBridgeChild.cpp
+++ b/gfx/layers/ipc/ImageBridgeChild.cpp
@@ -31,16 +31,17 @@
 #include "mozilla/mozalloc.h"           // for operator new, etc
 #include "nsAutoPtr.h"                  // for nsRefPtr
 #include "nsISupportsImpl.h"            // for ImageContainer::AddRef, etc
 #include "nsTArray.h"                   // for nsAutoTArray, nsTArray, etc
 #include "nsTArrayForwardDeclare.h"     // for AutoInfallibleTArray
 #include "nsThreadUtils.h"              // for NS_IsMainThread
 #include "nsXULAppAPI.h"                // for XRE_GetIOMessageLoop
 #include "mozilla/StaticPtr.h"          // for StaticRefPtr
+#include "mozilla/layers/TextureClient.h"
 
 struct nsIntRect;
  
 using namespace base;
 using namespace mozilla::ipc;
 
 namespace mozilla {
 namespace ipc {
@@ -98,67 +99,33 @@ struct CompositableTransaction
 };
 
 struct AutoEndTransaction {
   AutoEndTransaction(CompositableTransaction* aTxn) : mTxn(aTxn) {}
   ~AutoEndTransaction() { mTxn->End(); }
   CompositableTransaction* mTxn;
 };
 
-bool
-ImageBridgeChild::AddTexture(CompositableClient* aCompositable,
-                             TextureClient* aTexture)
-{
-  SurfaceDescriptor descriptor;
-  if (!aTexture->ToSurfaceDescriptor(descriptor)) {
-    NS_WARNING("ImageBridge: Failed to serialize a TextureClient");
-    return false;
-  }
-  mTxn->AddEdit(OpAddTexture(nullptr, aCompositable->GetIPDLActor(),
-                             aTexture->GetID(),
-                             descriptor,
-                             aTexture->GetFlags()));
-  return true;
-}
-
-void
-ImageBridgeChild::RemoveTexture(CompositableClient* aCompositable,
-                                uint64_t aTexture,
-                                TextureFlags aFlags)
-{
-  if (aFlags & TEXTURE_DEALLOCATE_CLIENT) {
-    // if deallocation happens on the host side, we need the transaction
-    // to be synchronous.
-    mTxn->AddEdit(OpRemoveTexture(nullptr, aCompositable->GetIPDLActor(),
-                                  aTexture,
-                                  aFlags));
-  } else {
-    mTxn->AddNoSwapEdit(OpRemoveTexture(nullptr, aCompositable->GetIPDLActor(),
-                                        aTexture,
-                                        aFlags));
-  }
-}
-
 void
 ImageBridgeChild::UseTexture(CompositableClient* aCompositable,
                              TextureClient* aTexture)
 {
   mTxn->AddNoSwapEdit(OpUseTexture(nullptr, aCompositable->GetIPDLActor(),
-                                   aTexture->GetID()));
+                                   nullptr, aTexture->GetIPDLActor()));
 }
 
 void
 ImageBridgeChild::UpdatedTexture(CompositableClient* aCompositable,
                                  TextureClient* aTexture,
                                  nsIntRegion* aRegion)
 {
   MaybeRegion region = aRegion ? MaybeRegion(*aRegion)
                                : MaybeRegion(null_t());
   mTxn->AddNoSwapEdit(OpUpdateTexture(nullptr, aCompositable->GetIPDLActor(),
-                                      aTexture->GetID(),
+                                      nullptr, aTexture->GetIPDLActor(),
                                       region));
 }
 
 void
 ImageBridgeChild::UpdateTexture(CompositableClient* aCompositable,
                                 TextureIdentifier aTextureId,
                                 SurfaceDescriptor* aDescriptor)
 {
@@ -460,17 +427,16 @@ void ImageBridgeChild::FlushAllImagesNow
   MOZ_ASSERT(aClient);
   sImageBridgeChildSingleton->BeginTransaction();
   if (aContainer && !aExceptFront) {
     aContainer->ClearCurrentImage();
   }
   aClient->FlushAllImages(aExceptFront);
   aClient->OnTransaction();
   sImageBridgeChildSingleton->EndTransaction();
-  aClient->FlushTexturesToRemoveCallbacks();
 }
 
 void
 ImageBridgeChild::BeginTransaction()
 {
   MOZ_ASSERT(mTxn->Finished(), "uncommitted txn?");
   mTxn->Begin();
 }
@@ -519,25 +485,17 @@ ImageBridgeChild::EndTransaction()
 
       MOZ_ASSERT(compositableChild);
 
       compositableChild->GetCompositableClient()
         ->SetDescriptorFromReply(ots.textureId(), ots.image());
       break;
     }
     case EditReply::TReplyTextureRemoved: {
-      // We receive this reply when a Texture is removed and when it is not
-      // the responsibility of the compositor side to deallocate memory.
-      // This would be, for instance, the place to implement a mechanism to
-      // notify the B2G camera that the gralloc buffer is not used by the
-      // compositor anymore and that it can be recycled.
-      const ReplyTextureRemoved& rep = reply.get_ReplyTextureRemoved();
-      CompositableClient* compositable
-        = static_cast<CompositableChild*>(rep.compositableChild())->GetCompositableClient();
-      compositable->OnReplyTextureRemoved(rep.textureId());
+      // XXX - implemented in another patch of the same bug (897452).
       break;
     }
     default:
       NS_RUNTIMEABORT("not reached");
     }
   }
 }
 
@@ -935,10 +893,28 @@ ImageBridgeChild::AllocGrallocBuffer(con
                                        aUsage,
                                        aHandle);
 #else
   NS_RUNTIMEABORT("not implemented");
   return nullptr;
 #endif
 }
 
+PTextureChild*
+ImageBridgeChild::AllocPTextureChild()
+{
+  return TextureClient::CreateIPDLActor();
+}
+
+bool
+ImageBridgeChild::DeallocPTextureChild(PTextureChild* actor)
+{
+  return TextureClient::DestroyIPDLActor(actor);
+}
+
+PTextureChild*
+ImageBridgeChild::CreateEmptyTextureChild()
+{
+  return SendPTextureConstructor();
+}
+
 } // layers
 } // mozilla
--- a/gfx/layers/ipc/ImageBridgeChild.h
+++ b/gfx/layers/ipc/ImageBridgeChild.h
@@ -190,16 +190,22 @@ public:
 
   virtual PGrallocBufferChild*
   AllocPGrallocBufferChild(const gfxIntSize&, const uint32_t&, const uint32_t&,
                            MaybeMagicGrallocBufferHandle*) MOZ_OVERRIDE;
 
   virtual bool
   DeallocPGrallocBufferChild(PGrallocBufferChild* actor) MOZ_OVERRIDE;
 
+  virtual PTextureChild*
+  AllocPTextureChild() MOZ_OVERRIDE;
+
+  virtual bool
+  DeallocPTextureChild(PTextureChild* actor) MOZ_OVERRIDE;
+
   /**
    * Allocate a gralloc SurfaceDescriptor remotely.
    */
   bool
   AllocSurfaceDescriptorGralloc(const gfxIntSize& aSize,
                                 const uint32_t& aFormat,
                                 const uint32_t& aUsage,
                                 SurfaceDescriptor* aBuffer);
@@ -250,29 +256,16 @@ public:
    */
   static void FlushAllImagesNow(ImageClient* aClient, ImageContainer* aContainer, bool aExceptFront);
 
   // CompositableForwarder
 
   virtual void Connect(CompositableClient* aCompositable) MOZ_OVERRIDE;
 
   /**
-   * See CompositableForwarder::AddTexture
-   */
-  virtual bool AddTexture(CompositableClient* aCompositable,
-                          TextureClient* aClient) MOZ_OVERRIDE;
-
-  /**
-   * See CompositableForwarder::RemoveTexture
-   */
-  virtual void RemoveTexture(CompositableClient* aCompositable,
-                             uint64_t aTextureID,
-                             TextureFlags aFlags) MOZ_OVERRIDE;
-
-  /**
    * See CompositableForwarder::UpdatedTexture
    */
   virtual void UpdatedTexture(CompositableClient* aCompositable,
                               TextureClient* aTexture,
                               nsIntRegion* aRegion) MOZ_OVERRIDE;
 
   /**
    * See CompositableForwarder::UseTexture
@@ -373,16 +366,18 @@ public:
   /**
    * See ISurfaceAllocator.h
    * Can be used from any thread.
    * If used outside the ImageBridgeChild thread, it will proxy a synchronous
    * call on the ImageBridgeChild thread.
    */
   virtual void DeallocShmem(mozilla::ipc::Shmem& aShmem);
 
+  virtual PTextureChild* CreateEmptyTextureChild() MOZ_OVERRIDE;
+
 protected:
   ImageBridgeChild();
   bool DispatchAllocShmemInternal(size_t aSize,
                                   SharedMemory::SharedMemoryType aType,
                                   Shmem* aShmem,
                                   bool aUnsafe);
 
   CompositableTransaction* mTxn;
--- a/gfx/layers/ipc/ImageBridgeParent.cpp
+++ b/gfx/layers/ipc/ImageBridgeParent.cpp
@@ -25,16 +25,17 @@
 #include "mozilla/layers/Compositor.h"
 #include "mozilla/mozalloc.h"           // for operator new, etc
 #include "nsAutoPtr.h"                  // for nsRefPtr
 #include "nsDebug.h"                    // for NS_RUNTIMEABORT, etc
 #include "nsISupportsImpl.h"            // for ImageBridgeParent::Release, etc
 #include "nsTArray.h"                   // for nsTArray, nsTArray_Impl
 #include "nsTArrayForwardDeclare.h"     // for InfallibleTArray
 #include "nsXULAppAPI.h"                // for XRE_GetIOMessageLoop
+#include "mozilla/layers/TextureHost.h"
 
 using namespace base;
 using namespace mozilla::ipc;
 
 namespace mozilla {
 namespace layers {
 
 class PGrallocBufferParent;
@@ -173,16 +174,28 @@ ImageBridgeParent::AllocPCompositablePar
 }
 
 bool ImageBridgeParent::DeallocPCompositableParent(PCompositableParent* aActor)
 {
   delete aActor;
   return true;
 }
 
+PTextureParent*
+ImageBridgeParent::AllocPTextureParent()
+{
+  return TextureHost::CreateIPDLActor(this);
+}
+
+bool
+ImageBridgeParent::DeallocPTextureParent(PTextureParent* actor)
+{
+  return TextureHost::DestroyIPDLActor(actor);
+}
+
 MessageLoop * ImageBridgeParent::GetMessageLoop() {
   return mMessageLoop;
 }
 
 void
 ImageBridgeParent::DeferredDestroy()
 {
   mSelfRef = nullptr;
--- a/gfx/layers/ipc/ImageBridgeParent.h
+++ b/gfx/layers/ipc/ImageBridgeParent.h
@@ -60,16 +60,19 @@ public:
   virtual bool RecvUpdateNoSwap(const EditArray& aEdits);
 
   virtual bool IsAsync() const MOZ_OVERRIDE { return true; }
 
   PCompositableParent* AllocPCompositableParent(const TextureInfo& aInfo,
                                                 uint64_t*) MOZ_OVERRIDE;
   bool DeallocPCompositableParent(PCompositableParent* aActor) MOZ_OVERRIDE;
 
+  virtual PTextureParent* AllocPTextureParent() MOZ_OVERRIDE;
+  virtual bool DeallocPTextureParent(PTextureParent* actor) MOZ_OVERRIDE;
+
   bool RecvStop() MOZ_OVERRIDE;
 
   MessageLoop * GetMessageLoop();
 
 
   // ISurfaceAllocator
 
   bool AllocShmem(size_t aSize,
--- a/gfx/layers/ipc/LayerTransactionChild.cpp
+++ b/gfx/layers/ipc/LayerTransactionChild.cpp
@@ -8,16 +8,17 @@
 #include "LayerTransactionChild.h"
 #include "mozilla/layers/CompositableClient.h"  // for CompositableChild
 #include "mozilla/layers/LayersSurfaces.h"  // for PGrallocBufferChild
 #include "mozilla/layers/PCompositableChild.h"  // for PCompositableChild
 #include "mozilla/layers/PLayerChild.h"  // for PLayerChild
 #include "mozilla/mozalloc.h"           // for operator delete, etc
 #include "nsDebug.h"                    // for NS_RUNTIMEABORT, etc
 #include "nsTArray.h"                   // for nsTArray
+#include "mozilla/layers/TextureClient.h"
 
 namespace mozilla {
 namespace layers {
 
 class PGrallocBufferChild;
 
 void
 LayerTransactionChild::Destroy()
@@ -91,10 +92,22 @@ LayerTransactionChild::ActorDestroy(Acto
   // shutdown. Its better just to crash here. On desktop though, we have a chance
   // of recovering.
   if (why == AbnormalShutdown) {
     NS_RUNTIMEABORT("ActorDestroy by IPC channel failure at LayerTransactionChild");
   }
 #endif
 }
 
+PTextureChild*
+LayerTransactionChild::AllocPTextureChild()
+{
+  return TextureClient::CreateIPDLActor();
+}
+
+bool
+LayerTransactionChild::DeallocPTextureChild(PTextureChild* actor)
+{
+  return TextureClient::DestroyIPDLActor(actor);
+}
+
 }  // namespace layers
 }  // namespace mozilla
--- a/gfx/layers/ipc/LayerTransactionChild.h
+++ b/gfx/layers/ipc/LayerTransactionChild.h
@@ -53,16 +53,20 @@ protected:
   virtual bool
   DeallocPGrallocBufferChild(PGrallocBufferChild* actor) MOZ_OVERRIDE;
 
   virtual PLayerChild* AllocPLayerChild() MOZ_OVERRIDE;
   virtual bool DeallocPLayerChild(PLayerChild* actor) MOZ_OVERRIDE;
 
   virtual PCompositableChild* AllocPCompositableChild(const TextureInfo& aInfo) MOZ_OVERRIDE;
   virtual bool DeallocPCompositableChild(PCompositableChild* actor) MOZ_OVERRIDE;
+
+  virtual PTextureChild* AllocPTextureChild() MOZ_OVERRIDE;
+  virtual bool DeallocPTextureChild(PTextureChild* actor) MOZ_OVERRIDE;
+
   virtual void ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE;
 
   void AddIPDLReference() {
     MOZ_ASSERT(mIPCOpen == false);
     mIPCOpen = true;
     AddRef();
   }
   void ReleaseIPDLReference() {
--- a/gfx/layers/ipc/LayerTransactionParent.cpp
+++ b/gfx/layers/ipc/LayerTransactionParent.cpp
@@ -34,16 +34,17 @@
 #include "nsDebug.h"                    // for NS_RUNTIMEABORT
 #include "nsISupportsImpl.h"            // for Layer::Release, etc
 #include "nsLayoutUtils.h"              // for nsLayoutUtils
 #include "nsMathUtils.h"                // for NS_round
 #include "nsPoint.h"                    // for nsPoint
 #include "nsTArray.h"                   // for nsTArray, nsTArray_Impl, etc
 #include "nsTraceRefcnt.h"              // for MOZ_COUNT_CTOR, etc
 #include "GeckoProfiler.h"
+#include "mozilla/layers/TextureHost.h"
 
 typedef std::vector<mozilla::layers::EditReply> EditReplyVector;
 
 using mozilla::layout::RenderFrameParent;
 
 namespace mozilla {
 namespace layers {
 
@@ -595,10 +596,22 @@ LayerTransactionParent::AllocPCompositab
 
 bool
 LayerTransactionParent::DeallocPCompositableParent(PCompositableParent* actor)
 {
   delete actor;
   return true;
 }
 
+PTextureParent*
+LayerTransactionParent::AllocPTextureParent()
+{
+  return TextureHost::CreateIPDLActor(this);
+}
+
+bool
+LayerTransactionParent::DeallocPTextureParent(PTextureParent* actor)
+{
+  return TextureHost::DestroyIPDLActor(actor);
+}
+
 } // namespace layers
 } // namespace mozilla
--- a/gfx/layers/ipc/LayerTransactionParent.h
+++ b/gfx/layers/ipc/LayerTransactionParent.h
@@ -101,16 +101,19 @@ protected:
   DeallocPGrallocBufferParent(PGrallocBufferParent* actor) MOZ_OVERRIDE;
 
   virtual PLayerParent* AllocPLayerParent() MOZ_OVERRIDE;
   virtual bool DeallocPLayerParent(PLayerParent* actor) MOZ_OVERRIDE;
 
   virtual PCompositableParent* AllocPCompositableParent(const TextureInfo& aInfo) MOZ_OVERRIDE;
   virtual bool DeallocPCompositableParent(PCompositableParent* actor) MOZ_OVERRIDE;
 
+  virtual PTextureParent* AllocPTextureParent() MOZ_OVERRIDE;
+  virtual bool DeallocPTextureParent(PTextureParent* actor) MOZ_OVERRIDE;
+
   void Attach(ShadowLayerParent* aLayerParent,
               CompositableParent* aCompositable,
               bool aIsAsyncVideo);
 
   void AddIPDLReference() {
     MOZ_ASSERT(mIPCOpen == false);
     mIPCOpen = true;
     AddRef();
--- a/gfx/layers/ipc/LayersMessages.ipdlh
+++ b/gfx/layers/ipc/LayersMessages.ipdlh
@@ -6,16 +6,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 include LayersSurfaces;
 include protocol PCompositable;
 include protocol PCompositor;
 include protocol PGrallocBuffer;
 include protocol PLayer;
 include protocol PRenderFrame;
+include protocol PTexture;
 
 include "gfxipc/ShadowLayerUtils.h";
 include "mozilla/GfxMessageUtils.h";
 include "ImageLayers.h";
 
 using mozilla::GraphicsFilterType from "mozilla/GfxMessageUtils.h";
 using struct gfxRGBA from "gfxColor.h";
 using struct gfxPoint3D from "gfxPoint3D.h";
@@ -296,70 +297,57 @@ struct OpPaintTextureIncremental {
 };
 
 struct OpUpdatePictureRect {
   PCompositable compositable;
   nsIntRect picture;
 };
 
 /**
- * Provides the compositor side with enough information to create a
- * TextureHost.
- */
-struct OpAddTexture {
-  PCompositable compositable;
-  uint64_t textureID;
-  SurfaceDescriptor data;
-  uint32_t textureFlags;
-};
-
-/**
  * Tells the compositor-side to remove the corresponding TextureHost and
  * deallocate its data.
  */
 struct OpRemoveTexture {
-  PCompositable compositable;
-  uint64_t textureID;
-  uint32_t flags;
+  PTexture texture;
+  uint64_t callbackID;
 };
 
 /**
  * Tells the compositor-side which texture to use (for example, as front buffer
  * if there is several textures for double buffering)
  */
 struct OpUseTexture {
   PCompositable compositable;
-  uint64_t textureID;
+  PTexture texture;
 };
 
 union MaybeRegion {
   nsIntRegion;
   null_t;
 };
 
 struct OpUpdateTexture {
   PCompositable compositable;
-  uint64_t textureID;
+  PTexture texture;
   MaybeRegion region;
 };
 
 union CompositableOperation {
   OpUpdatePictureRect;
 
   OpCreatedTexture;
   OpCreatedIncrementalTexture;
   OpDestroyThebesBuffer;
 
   OpPaintTexture;
   OpPaintTextureRegion;
   OpPaintTextureIncremental;
 
   OpPaintTiledLayerBuffer;
 
-  OpAddTexture;
   OpRemoveTexture;
   OpUpdateTexture;
   OpUseTexture;
 };
 
 // A unit of a changeset; a set of these comprise a changeset
 union Edit {
   OpCreateThebesLayer;
@@ -395,18 +383,17 @@ struct OpContentBufferSwap {
 
 struct OpTextureSwap {
   PCompositable compositable;
   uint32_t textureId;
   SurfaceDescriptor image;
 };
 
 struct ReplyTextureRemoved {
-  PCompositable compositable;
-  uint64_t textureId;
+  uint64_t callbackID;
 };
 
 // Unit of a "changeset reply".  This is a weird abstraction, probably
 // only to be used for buffer swapping.
 union EditReply {
   OpContentBufferSwap;
   OpTextureSwap;
 
--- a/gfx/layers/ipc/PImageBridge.ipdl
+++ b/gfx/layers/ipc/PImageBridge.ipdl
@@ -2,16 +2,17 @@
  * 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 PGrallocBuffer;
 include protocol PCompositable;
+include protocol PTexture;
 include ProtocolTypes;
 
 include "mozilla/GfxMessageUtils.h";
 
 using struct mozilla::layers::TextureInfo from "mozilla/layers/CompositorTypes.h";
 
 namespace mozilla {
 namespace layers {
@@ -20,16 +21,17 @@ 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.
  */
 intr protocol PImageBridge
 {
   manages PCompositable;
   manages PGrallocBuffer;
+  manages PTexture;
 
 parent:
 
   sync Update(CompositableOperation[] ops) returns (EditReply[] reply);
   async UpdateNoSwap(CompositableOperation[] ops);
 
   // Allocates a gralloc buffer that may not suitable to use with
   // gfxImageSurface but allows hardware decoder to write to the
@@ -44,14 +46,15 @@ parent:
   // counterpart so as to not race with the upcomming __delete__ message.
   // In the child side, the __delete__ messages are not sent right after Stop,
   // they are scheduled in the ImageBridgeChild's message queue in order to ensure
   // that all the messages from the parent side have been received and processed
   // before sending __delete__.
   sync Stop();
 
   sync PCompositable(TextureInfo aInfo) returns (uint64_t id);
+  async PTexture();
 };
 
 
 } // namespace
 } // namespace
 
--- a/gfx/layers/ipc/PLayerTransaction.ipdl
+++ b/gfx/layers/ipc/PLayerTransaction.ipdl
@@ -7,16 +7,17 @@
 
 include LayersSurfaces;
 include LayersMessages;
 include protocol PCompositable;
 include protocol PCompositor;
 include protocol PGrallocBuffer;
 include protocol PLayer;
 include protocol PRenderFrame;
+include protocol PTexture;
 
 include "mozilla/GfxMessageUtils.h";
 
 using struct mozilla::layers::TextureInfo from "mozilla/layers/CompositorTypes.h";
 
 /**
  * The layers protocol is spoken between thread contexts that manage
  * layer (sub)trees.  The protocol comprises atomically publishing
@@ -28,16 +29,17 @@ using struct mozilla::layers::TextureInf
 namespace mozilla {
 namespace layers {
 
 sync protocol PLayerTransaction {
   manager PRenderFrame or PCompositor;
   manages PLayer;
   manages PCompositable;
   manages PGrallocBuffer;
+  manages PTexture;
 
 parent:
   /**
    * Only the parent side has privileges to allocate the buffer.
    * Allocation may fail (pmem is a scarce resource), and if so null_t
    * is returned.
    *
    * |format| is an Android PixelFormat (see PixelFormat.h)
@@ -61,16 +63,17 @@ parent:
    *   USAGE_HW_RENDER | USAGE_HW_TEXTURE
    *     - used for GL rendering to a buffer which the compositor
    *       treats as a texture
    */
   sync PGrallocBuffer(gfxIntSize size, uint32_t format, uint32_t usage)
     returns (MaybeMagicGrallocBufferHandle handle);
   async PLayer();
   async PCompositable(TextureInfo aTextureInfo);
+  async PTexture();
 
   // The isFirstPaint flag can be used to indicate that this is the first update
   // for a particular document.
   sync Update(Edit[] cset, TargetConfig targetConfig, bool isFirstPaint)
     returns (EditReply[] reply);
 
   sync GetOpacity(PLayer layer) returns (float opacity);
   sync GetTransform(PLayer layer) returns (gfx3DMatrix transform);
new file mode 100644
--- /dev/null
+++ b/gfx/layers/ipc/PTexture.ipdl
@@ -0,0 +1,36 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * 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 protocol PLayerTransaction;
+include protocol PImageBridge;
+include protocol PGrallocBuffer;
+include "mozilla/GfxMessageUtils.h";
+
+using struct mozilla::layers::FrameMetrics from "FrameMetrics.h";
+
+namespace mozilla {
+namespace layers {
+
+/**
+ * PTexture is the IPDL glue between a TextureClient and a TextureHost.
+ */
+sync protocol PTexture {
+    manager PImageBridge or PLayerTransaction;
+
+child:
+    async __delete__();
+
+parent:
+    /**
+     * Set the shared data and create the TextureHost on the parent side.
+     */
+    async Init(SurfaceDescriptor aSharedData, uint32_t aTextureFlags);
+};
+
+} // layers
+} // mozilla
--- a/gfx/layers/ipc/ShadowLayerUtilsGralloc.cpp
+++ b/gfx/layers/ipc/ShadowLayerUtilsGralloc.cpp
@@ -8,16 +8,17 @@
 #include "mozilla/DebugOnly.h"
 
 #include "mozilla/layers/PGrallocBufferChild.h"
 #include "mozilla/layers/PGrallocBufferParent.h"
 #include "mozilla/layers/LayerTransactionChild.h"
 #include "mozilla/layers/ShadowLayers.h"
 #include "mozilla/layers/LayerManagerComposite.h"
 #include "mozilla/layers/CompositorTypes.h"
+#include "mozilla/layers/TextureHost.h"
 #include "mozilla/unused.h"
 #include "nsXULAppAPI.h"
 
 #include "ShadowLayerUtilsGralloc.h"
 
 #include "nsIMemoryReporter.h"
 
 #include "gfxImageSurface.h"
--- a/gfx/layers/ipc/ShadowLayerUtilsGralloc.h
+++ b/gfx/layers/ipc/ShadowLayerUtilsGralloc.h
@@ -10,30 +10,28 @@
 
 #include <unistd.h>
 #include <ui/GraphicBuffer.h>
 
 #include "ipc/IPCMessageUtils.h"
 #include "mozilla/layers/PGrallocBufferChild.h"
 #include "mozilla/layers/PGrallocBufferParent.h"
 
-// used only for hacky fix in gecko 23 for bug 862324
-// see bug 865908 about fixing this.
-#include "TextureHost.h"
-
 #define MOZ_HAVE_SURFACEDESCRIPTORGRALLOC
 #define MOZ_HAVE_PLATFORM_SPECIFIC_LAYER_BUFFERS
 
 class gfxASurface;
 
 namespace mozilla {
 namespace layers {
 
 class MaybeMagicGrallocBufferHandle;
 class SurfaceDescriptorGralloc;
+class TextureHost;
+class DeprecatedTextureHost;
 
 /**
  * This class exists to share the underlying GraphicBuffer resources
  * from one thread context to another.  This requires going through
  * slow paths in the kernel so can be somewhat expensive.
  *
  * This is not just platform-specific, but also
  * gralloc-implementation-specific.
--- a/gfx/layers/ipc/ShadowLayers.cpp
+++ b/gfx/layers/ipc/ShadowLayers.cpp
@@ -402,73 +402,40 @@ ShadowLayerForwarder::UpdateTextureIncre
 
 void
 ShadowLayerForwarder::UpdatePictureRect(CompositableClient* aCompositable,
                                         const nsIntRect& aRect)
 {
   mTxn->AddNoSwapPaint(OpUpdatePictureRect(nullptr, aCompositable->GetIPDLActor(), aRect));
 }
 
-bool
-ShadowLayerForwarder::AddTexture(CompositableClient* aCompositable,
-                                 TextureClient* aTexture)
-{
-  SurfaceDescriptor descriptor;
-  if (!aTexture->ToSurfaceDescriptor(descriptor)) {
-    NS_WARNING("Failed to serialize a TextureClient");
-    return false;
-  }
-  CheckSurfaceDescriptor(&descriptor);
-  MOZ_ASSERT(aCompositable);
-  MOZ_ASSERT(aCompositable->GetIPDLActor());
-  MOZ_ASSERT(aTexture->GetFlags() != 0);
-  mTxn->AddEdit(OpAddTexture(nullptr, aCompositable->GetIPDLActor(),
-                             aTexture->GetID(),
-                             descriptor,
-                             aTexture->GetFlags()));
-  return true;
-}
-
-void
-ShadowLayerForwarder::RemoveTexture(CompositableClient* aCompositable,
-                                    uint64_t aTexture,
-                                    TextureFlags aFlags)
-{
-  mTxn->AddEdit(OpRemoveTexture(nullptr, aCompositable->GetIPDLActor(),
-                                aTexture,
-                                aFlags));
-  if (aFlags & TEXTURE_DEALLOCATE_CLIENT) {
-    mTxn->MarkSyncTransaction();
-  }
-}
-
 void
 ShadowLayerForwarder::UpdatedTexture(CompositableClient* aCompositable,
                                      TextureClient* aTexture,
                                      nsIntRegion* aRegion)
 {
   MaybeRegion region = aRegion ? MaybeRegion(*aRegion)
                                : MaybeRegion(null_t());
   if (aTexture->GetFlags() & TEXTURE_IMMEDIATE_UPLOAD) {
     mTxn->AddPaint(OpUpdateTexture(nullptr, aCompositable->GetIPDLActor(),
-                                   aTexture->GetID(),
+                                   nullptr, aTexture->GetIPDLActor(),
                                    region));
   } else {
     mTxn->AddNoSwapPaint(OpUpdateTexture(nullptr, aCompositable->GetIPDLActor(),
-                                         aTexture->GetID(),
+                                         nullptr, aTexture->GetIPDLActor(),
                                          region));
   }
 }
 
 void
 ShadowLayerForwarder::UseTexture(CompositableClient* aCompositable,
                                  TextureClient* aTexture)
 {
   mTxn->AddEdit(OpUseTexture(nullptr, aCompositable->GetIPDLActor(),
-                             aTexture->GetID()));
+                             nullptr, aTexture->GetIPDLActor()));
 }
 
 bool
 ShadowLayerForwarder::EndTransaction(InfallibleTArray<EditReply>* aReplies, bool* aSent)
 {
   *aSent = false;
 
   PROFILER_LABEL("ShadowLayerForwarder", "EndTranscation");
@@ -984,16 +951,23 @@ void ShadowLayerForwarder::AttachAsyncCo
                                                    ShadowableLayer* aLayer)
 {
   MOZ_ASSERT(aLayer);
   MOZ_ASSERT(aCompositableID != 0); // zero is always an invalid compositable id.
   mTxn->AddEdit(OpAttachAsyncCompositable(nullptr, Shadow(aLayer),
                                           aCompositableID));
 }
 
+PTextureChild*
+ShadowLayerForwarder::CreateEmptyTextureChild()
+{
+  return mShadowManager->SendPTextureConstructor();
+}
+
+
 void ShadowLayerForwarder::SetShadowManager(PLayerTransactionChild* aShadowManager)
 {
   mShadowManager = static_cast<LayerTransactionChild*>(aShadowManager);
 }
 
 
 } // namespace layers
 } // namespace mozilla
--- a/gfx/layers/ipc/ShadowLayers.h
+++ b/gfx/layers/ipc/ShadowLayers.h
@@ -144,16 +144,18 @@ public:
   virtual ~ShadowLayerForwarder();
 
   /**
    * Setup the IPDL actor for aCompositable to be part of layers
    * transactions.
    */
   void Connect(CompositableClient* aCompositable);
 
+  virtual PTextureChild* CreateEmptyTextureChild() MOZ_OVERRIDE;
+
   virtual void CreatedSingleBuffer(CompositableClient* aCompositable,
                                    const SurfaceDescriptor& aDescriptor,
                                    const TextureInfo& aTextureInfo,
                                    const SurfaceDescriptor* aDescriptorOnWhite = nullptr) MOZ_OVERRIDE;
   virtual void CreatedIncrementalBuffer(CompositableClient* aCompositable,
                                         const TextureInfo& aTextureInfo,
                                         const nsIntRect& aBufferRect) MOZ_OVERRIDE;
   virtual void CreatedDoubleBuffer(CompositableClient* aCompositable,
@@ -301,29 +303,16 @@ public:
 
   /**
    * Communicate the picture rect of an image to the compositor
    */
   void UpdatePictureRect(CompositableClient* aCompositable,
                          const nsIntRect& aRect);
 
   /**
-   * See CompositableForwarder::AddTexture
-   */
-  virtual bool AddTexture(CompositableClient* aCompositable,
-                          TextureClient* aClient) MOZ_OVERRIDE;
-
-  /**
-   * See CompositableForwarder::RemoveTexture
-   */
-  virtual void RemoveTexture(CompositableClient* aCompositable,
-                             uint64_t aTextureID,
-                             TextureFlags aFlags) MOZ_OVERRIDE;
-
-  /**
    * See CompositableForwarder::UpdatedTexture
    */
   virtual void UpdatedTexture(CompositableClient* aCompositable,
                               TextureClient* aTexture,
                               nsIntRegion* aRegion) MOZ_OVERRIDE;
 
   /**
    * See CompositableForwarder::UseTexture
--- a/gfx/layers/moz.build
+++ b/gfx/layers/moz.build
@@ -285,16 +285,17 @@ IPDL_SOURCES = [
     'ipc/LayersMessages.ipdlh',
     'ipc/LayersSurfaces.ipdlh',
     'ipc/PCompositable.ipdl',
     'ipc/PCompositor.ipdl',
     'ipc/PGrallocBuffer.ipdl',
     'ipc/PImageBridge.ipdl',
     'ipc/PLayer.ipdl',
     'ipc/PLayerTransaction.ipdl',
+    'ipc/PTexture.ipdl',
 ]
 
 MSVC_ENABLE_PGO = True
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'thebes'