Bug 893301. Rollup patch - new textures content. r=nical,nrc
authorNicholas Cameron <ncameron@mozilla.com>
Fri, 06 Dec 2013 07:39:22 +1300
changeset 159039 0e796e3648153bde5b56d2c745c45fbfc94617e6
parent 159038 c14453ff87648f20be5b3805695d16257fd08212
child 159040 10932f3a0ba0933ffc45cd9c86fa6aa3eb1a8835
push id25771
push usercbook@mozilla.com
push dateFri, 06 Dec 2013 12:30:11 +0000
treeherdermozilla-central@9a92e42151dc [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnical, nrc
bugs893301
milestone28.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 893301. Rollup patch - new textures content. r=nical,nrc
gfx/layers/CompositorTypes.h
gfx/layers/RotatedBuffer.cpp
gfx/layers/RotatedBuffer.h
gfx/layers/client/ClientThebesLayer.cpp
gfx/layers/client/CompositableClient.cpp
gfx/layers/client/CompositableClient.h
gfx/layers/client/ContentClient.cpp
gfx/layers/client/ContentClient.h
gfx/layers/client/TextureClient.cpp
gfx/layers/client/TextureClient.h
gfx/layers/composite/CompositableHost.cpp
gfx/layers/composite/CompositableHost.h
gfx/layers/composite/ContentHost.cpp
gfx/layers/composite/ContentHost.h
gfx/layers/composite/ImageHost.cpp
gfx/layers/composite/ImageHost.h
gfx/layers/composite/ImageLayerComposite.cpp
gfx/layers/composite/TextureHost.cpp
gfx/layers/composite/TextureHost.h
gfx/layers/ipc/CompositableTransactionParent.cpp
gfx/layers/opengl/GrallocTextureClient.cpp
gfx/layers/opengl/GrallocTextureClient.h
--- a/gfx/layers/CompositorTypes.h
+++ b/gfx/layers/CompositorTypes.h
@@ -59,28 +59,37 @@ const TextureFlags TEXTURE_TILE         
 // from the previous texture.
 const TextureFlags TEXTURE_COPY_PREVIOUS      = 1 << 24;
 // Who is responsible for deallocating the shared data.
 // if TEXTURE_DEALLOCATE_CLIENT is set, the shared data is deallocated on the
 // client side and requires some extra synchronizaion to ensure race-free
 // deallocation.
 // The default behaviour is to deallocate on the host side.
 const TextureFlags TEXTURE_DEALLOCATE_CLIENT  = 1 << 25;
+// The host side is responsible for deallocation, but that may not happen
+// immediately after the client side requests it. Exactly when the texture is
+// deallocated is up to the compositable. The texture must be deallocated by
+// the time the compositable or texture host is destroyed. A texture may not
+// have both TEXTURE_DEALLOCATE_CLIENT and TEXTURE_DEALLOCATE_DEFERRED flags.
+const TextureFlags TEXTURE_DEALLOCATE_DEFERRED  = 1 << 26;
 // After being shared ith the compositor side, an immutable texture is never
 // modified, it can only be read. It is safe to not Lock/Unlock immutable
 // textures.
 const TextureFlags TEXTURE_IMMUTABLE          = 1 << 27;
 // The contents of the texture must be uploaded or copied immediately
 // during the transaction, because the producer may want to write
 // to it again.
 const TextureFlags TEXTURE_IMMEDIATE_UPLOAD   = 1 << 28;
 // The texture is going to be used as part of a double
 // buffered pair, and so we can guarantee that the producer/consumer
 // won't be racing to access its contents.
 const TextureFlags TEXTURE_DOUBLE_BUFFERED    = 1 << 29;
+// We've previously tried a texture and it didn't work for some reason. If there
+// is a fallback available, try that.
+const TextureFlags TEXTURE_ALLOC_FALLBACK     = 1 << 31;
 
 // the default flags
 const TextureFlags TEXTURE_FLAGS_DEFAULT = TEXTURE_FRONT;
 
 static inline bool
 TextureRequiresLocking(TextureFlags aFlags)
 {
   // If we're not double buffered, or uploading
@@ -162,16 +171,18 @@ enum CompositableType
   BUFFER_BRIDGE,          // image bridge protocol
   BUFFER_CONTENT,         // thebes layer interface, single buffering
   BUFFER_CONTENT_DIRECT,  // thebes layer interface, double buffering
   BUFFER_CONTENT_INC,     // thebes layer interface, only sends incremental
                           // updates to a texture on the compositor side.
   BUFFER_TILED,           // tiled thebes layer
   // the new compositable types
   COMPOSITABLE_IMAGE,     // image with single buffering
+  COMPOSITABLE_CONTENT_SINGLE,  // thebes layer interface, single buffering
+  COMPOSITABLE_CONTENT_DOUBLE,  // thebes layer interface, double buffering
   BUFFER_COUNT
 };
 
 /**
  * How the texture host is used for composition,
  */
 enum DeprecatedTextureHostFlags
 {
--- a/gfx/layers/RotatedBuffer.cpp
+++ b/gfx/layers/RotatedBuffer.cpp
@@ -276,73 +276,82 @@ RotatedContentBuffer::GetContextForQuadr
   }
 
   return ctx.forget();
 }
 
 gfxContentType
 RotatedContentBuffer::BufferContentType()
 {
-  if (mBufferProvider) {
-    return mBufferProvider->GetContentType();
+  if (mDeprecatedBufferProvider) {
+    return mDeprecatedBufferProvider->GetContentType();
   }
-  if (mDTBuffer) {
-    switch (mDTBuffer->GetFormat()) {
-    case FORMAT_A8:
-      return GFX_CONTENT_ALPHA;
-    case FORMAT_B8G8R8A8:
-    case FORMAT_R8G8B8A8:
-      return GFX_CONTENT_COLOR_ALPHA;
-    default:
-      return GFX_CONTENT_COLOR;
+  if (mBufferProvider || mDTBuffer) {
+    SurfaceFormat format;
+
+    if (mBufferProvider) {
+      format = mBufferProvider->AsTextureClientDrawTarget()->GetFormat();
+    } else if (mDTBuffer) {
+      format = mDTBuffer->GetFormat();
     }
+
+    return ContentForFormat(format);
   }
   return GFX_CONTENT_SENTINEL;
 }
 
 bool
 RotatedContentBuffer::BufferSizeOkFor(const nsIntSize& aSize)
 {
   return (aSize == mBufferRect.Size() ||
           (SizedToVisibleBounds != mBufferSizePolicy &&
            aSize < mBufferRect.Size()));
 }
 
 bool
 RotatedContentBuffer::EnsureBuffer()
 {
-  if (!mDTBuffer && mBufferProvider) {
-    mDTBuffer = mBufferProvider->LockDrawTarget();
+  if (!mDTBuffer) {
+    if (mDeprecatedBufferProvider) {
+      mDTBuffer = mDeprecatedBufferProvider->LockDrawTarget();
+    } else if (mBufferProvider) {
+      mDTBuffer = mBufferProvider->AsTextureClientDrawTarget()->GetAsDrawTarget();
+    }
   }
 
   NS_WARN_IF_FALSE(mDTBuffer, "no buffer");
   return !!mDTBuffer;
 }
 
 bool
 RotatedContentBuffer::EnsureBufferOnWhite()
 {
-  if (!mDTBufferOnWhite && mBufferProviderOnWhite) {
-    mDTBufferOnWhite = mBufferProviderOnWhite->LockDrawTarget();
+  if (!mDTBufferOnWhite) {
+    if (mDeprecatedBufferProviderOnWhite) {
+      mDTBufferOnWhite = mDeprecatedBufferProviderOnWhite->LockDrawTarget();
+    } else if (mBufferProviderOnWhite) {
+      mDTBufferOnWhite =
+        mBufferProviderOnWhite->AsTextureClientDrawTarget()->GetAsDrawTarget();
+    }
   }
 
   NS_WARN_IF_FALSE(mDTBufferOnWhite, "no buffer");
   return mDTBufferOnWhite;
 }
 
 bool
 RotatedContentBuffer::HaveBuffer() const
 {
-  return mDTBuffer || mBufferProvider;
+  return mDTBuffer || mDeprecatedBufferProvider || mBufferProvider;
 }
 
 bool
 RotatedContentBuffer::HaveBufferOnWhite() const
 {
-  return mDTBufferOnWhite || mBufferProviderOnWhite;
+  return mDTBufferOnWhite || mDeprecatedBufferProviderOnWhite || mBufferProviderOnWhite;
 }
 
 static void
 WrapRotationAxis(int32_t* aRotationPoint, int32_t aSize)
 {
   if (*aRotationPoint < 0) {
     *aRotationPoint += aSize;
   } else if (*aRotationPoint >= aSize) {
--- a/gfx/layers/RotatedBuffer.h
+++ b/gfx/layers/RotatedBuffer.h
@@ -28,16 +28,17 @@ struct nsIntSize;
 namespace mozilla {
 namespace gfx {
 class Matrix;
 }
 
 namespace layers {
 
 class DeprecatedTextureClient;
+class TextureClient;
 class ThebesLayer;
 
 /**
  * This is a cairo/Thebes surface, but with a literal twist. Scrolling
  * causes the layer's visible region to move. We want to keep
  * reusing the same surface if the region size hasn't changed, but we don't
  * want to keep moving the contents of the surface around in memory. So
  * we use a trick.
@@ -152,17 +153,19 @@ public:
    *   fit visible bounds.  May be larger.
    */
   enum BufferSizePolicy {
     SizedToVisibleBounds,
     ContainsVisibleBounds
   };
 
   RotatedContentBuffer(BufferSizePolicy aBufferSizePolicy)
-    : mBufferProvider(nullptr)
+    : mDeprecatedBufferProvider(nullptr)
+    , mDeprecatedBufferProviderOnWhite(nullptr)
+    , mBufferProvider(nullptr)
     , mBufferProviderOnWhite(nullptr)
     , mBufferSizePolicy(aBufferSizePolicy)
   {
     MOZ_COUNT_CTOR(RotatedContentBuffer);
   }
   virtual ~RotatedContentBuffer()
   {
     MOZ_COUNT_DTOR(RotatedContentBuffer);
@@ -171,16 +174,18 @@ public:
   /**
    * Wipe out all retained contents. Call this when the entire
    * buffer becomes invalid.
    */
   void Clear()
   {
     mDTBuffer = nullptr;
     mDTBufferOnWhite = nullptr;
+    mDeprecatedBufferProvider = nullptr;
+    mDeprecatedBufferProviderOnWhite = nullptr;
     mBufferProvider = nullptr;
     mBufferProviderOnWhite = nullptr;
     mBufferRect.SetEmpty();
   }
 
   /**
    * This is returned by BeginPaint. The caller should draw into mContext.
    * mRegionToDraw must be drawn. mRegionToInvalidate has been invalidated
@@ -285,33 +290,58 @@ protected:
    * demand in this code.
    *
    * It's the caller's responsibility to ensure |aClient| is valid
    * for the duration of operations it requests of this
    * RotatedContentBuffer.  It's also the caller's responsibility to
    * unset the provider when inactive, by calling
    * SetBufferProvider(nullptr).
    */
-  void SetBufferProvider(DeprecatedTextureClient* aClient)
+  void SetDeprecatedBufferProvider(DeprecatedTextureClient* aClient)
   {
     // Only this buffer provider can give us a buffer.  If we
     // already have one, something has gone wrong.
-    MOZ_ASSERT(!aClient || !mDTBuffer);
+    MOZ_ASSERT((!aClient || !mDTBuffer) && !mBufferProvider);
+
+    mDeprecatedBufferProvider = aClient;
+    if (!mDeprecatedBufferProvider) {
+      mDTBuffer = nullptr;
+    } 
+  }
+  
+  void SetDeprecatedBufferProviderOnWhite(DeprecatedTextureClient* aClient)
+  {
+    // Only this buffer provider can give us a buffer.  If we
+    // already have one, something has gone wrong.
+    MOZ_ASSERT((!aClient || !mDTBufferOnWhite) && !mBufferProviderOnWhite);
+
+    mDeprecatedBufferProviderOnWhite = aClient;
+    if (!mDeprecatedBufferProviderOnWhite) {
+      mDTBufferOnWhite = nullptr;
+    }
+  }
+
+  // new texture client versions
+  void SetBufferProvider(TextureClient* aClient)
+  {
+    // Only this buffer provider can give us a buffer.  If we
+    // already have one, something has gone wrong.
+    MOZ_ASSERT((!aClient || !mDTBuffer) && !mDeprecatedBufferProvider);
 
     mBufferProvider = aClient;
     if (!mBufferProvider) {
       mDTBuffer = nullptr;
-    } 
+    }
   }
-  
-  void SetBufferProviderOnWhite(DeprecatedTextureClient* aClient)
+
+  void SetBufferProviderOnWhite(TextureClient* aClient)
   {
     // Only this buffer provider can give us a buffer.  If we
     // already have one, something has gone wrong.
-    MOZ_ASSERT(!aClient || !mDTBufferOnWhite);
+    MOZ_ASSERT((!aClient || !mDTBufferOnWhite) && !mDeprecatedBufferProviderOnWhite);
 
     mBufferProviderOnWhite = aClient;
     if (!mBufferProviderOnWhite) {
       mDTBufferOnWhite = nullptr;
     } 
   }
 
   /**
@@ -344,18 +374,20 @@ protected:
   virtual bool HaveBuffer() const;
   virtual bool HaveBufferOnWhite() const;
 
   /**
    * These members are only set transiently.  They're used to map mDTBuffer
    * when we're using surfaces that require explicit map/unmap. Only one
    * may be used at a time.
    */
-  DeprecatedTextureClient* mBufferProvider;
-  DeprecatedTextureClient* mBufferProviderOnWhite;
+  DeprecatedTextureClient* mDeprecatedBufferProvider;
+  DeprecatedTextureClient* mDeprecatedBufferProviderOnWhite;
+  TextureClient* mBufferProvider;
+  TextureClient* mBufferProviderOnWhite;
 
   BufferSizePolicy      mBufferSizePolicy;
 };
 
 }
 }
 
 #endif /* ROTATEDBUFFER_H_ */
--- a/gfx/layers/client/ClientThebesLayer.cpp
+++ b/gfx/layers/client/ClientThebesLayer.cpp
@@ -101,16 +101,28 @@ ClientThebesLayer::RenderLayer()
     mContentClient->Connect();
     ClientManager()->AsShadowForwarder()->Attach(mContentClient, this);
     MOZ_ASSERT(mContentClient->GetForwarder());
   }
 
   mContentClient->BeginPaint();
   PaintThebes();
   mContentClient->EndPaint();
+  // It is very important that this is called after EndPaint, because destroying
+  // textures is a three stage process:
+  // 1. We are done with the buffer and move it to ContentClient::mOldTextures,
+  // that happens in DestroyBuffers which is may be called indirectly from
+  // PaintThebes.
+  // 2. The content client calls RemoveTextureClient on the texture clients in
+  // mOldTextures and forgets them. They then become invalid. The compositable
+  // client keeps a record of IDs. This happens in EndPaint.
+  // 3. An IPC message is sent to destroy the corresponding texture host. That
+  // happens from OnTransaction.
+  // It is important that these steps happen in order.
+  mContentClient->OnTransaction();
 }
 
 void
 ClientThebesLayer::PaintBuffer(gfxContext* aContext,
                                const nsIntRegion& aRegionToDraw,
                                const nsIntRegion& aExtendedRegionToDraw,
                                const nsIntRegion& aRegionToInvalidate,
                                bool aDidSelfCopy, DrawRegionClip aClip)
--- a/gfx/layers/client/CompositableClient.cpp
+++ b/gfx/layers/client/CompositableClient.cpp
@@ -10,18 +10,21 @@
 #include "mozilla/layers/TextureClient.h"  // for DeprecatedTextureClient, etc
 #include "mozilla/layers/TextureClientOGL.h"
 #include "mozilla/mozalloc.h"           // for operator delete, etc
 #include "gfxASurface.h"                // for gfxContentType
 #ifdef XP_WIN
 #include "mozilla/layers/TextureD3D9.h"
 #include "mozilla/layers/TextureD3D11.h"
 #include "gfxWindowsPlatform.h"
+#include "gfx2DGlue.h"
 #endif
 
+using namespace mozilla::gfx;
+
 namespace mozilla {
 namespace layers {
 
 CompositableClient::CompositableClient(CompositableForwarder* aForwarder)
 : mNextTextureID(1)
 , mCompositableChild(nullptr)
 , mForwarder(aForwarder)
 {
@@ -188,18 +191,18 @@ CompositableClient::CreateDeprecatedText
   MOZ_ASSERT(result->SupportsType(aDeprecatedTextureClientType),
              "Created the wrong texture client?");
   result->SetFlags(GetTextureInfo().mTextureFlags);
 
   return result.forget();
 }
 
 TemporaryRef<BufferTextureClient>
-CompositableClient::CreateBufferTextureClient(gfx::SurfaceFormat aFormat,
-                                              uint32_t aTextureFlags)
+CompositableClient::CreateBufferTextureClient(SurfaceFormat aFormat,
+                                              TextureFlags aTextureFlags)
 {
 // XXX - Once bug 908196 is fixed, we can use gralloc textures here which will
 // improve performances of videos using SharedPlanarYCbCrImage on b2g.
 //#ifdef MOZ_WIDGET_GONK
 //  {
 //    RefPtr<BufferTextureClient> result = new GrallocTextureClientOGL(this,
 //                                                                     aFormat,
 //                                                                     aTextureFlags);
@@ -209,25 +212,66 @@ CompositableClient::CreateBufferTextureC
   if (gfxPlatform::GetPlatform()->PreferMemoryOverShmem()) {
     RefPtr<BufferTextureClient> result = new MemoryTextureClient(this, aFormat, aTextureFlags);
     return result.forget();
   }
   RefPtr<BufferTextureClient> result = new ShmemTextureClient(this, aFormat, aTextureFlags);
   return result.forget();
 }
 
-bool
-CompositableClient::AddTextureClient(TextureClient* aClient)
+TemporaryRef<TextureClient>
+CompositableClient::CreateTextureClientForDrawing(SurfaceFormat aFormat,
+                                                  TextureFlags aTextureFlags)
+{
+  RefPtr<TextureClient> result;
+
+#ifdef XP_WIN
+  LayersBackend parentBackend = GetForwarder()->GetCompositorBackendType();
+  // XXX[nrc] uncomment once we have new texture clients for windows
+  if (parentBackend == LAYERS_D3D11 && gfxWindowsPlatform::GetPlatform()->GetD2DDevice() &&
+      !(aTextureFlags & TEXTURE_ALLOC_FALLBACK)) {
+    //result = new TextureClientD3D11(GetForwarder(), GetTextureInfo());
+  }
+  if (parentBackend == LAYERS_D3D9 &&
+      !GetForwarder()->ForwardsToDifferentProcess() &&
+      !(aTextureFlags & TEXTURE_ALLOC_FALLBACK)) {
+    // non-DIB textures don't work with alpha, see notes in TextureD3D9.
+    if (ContentForFormat(aFormat) == GFX_CONTENT_COLOR_ALPHA) {
+      //result = new TextureClientDIB(GetForwarder(), GetTextureInfo());
+    } else {
+      //result = new TextureClientD3D9(GetForwarder(), GetTextureInfo());
+    }
+  }
+#endif
+  // Can't do any better than a buffer texture client.
+  if (!result) {
+    result = CreateBufferTextureClient(aFormat, aTextureFlags);
+  }
+
+  MOZ_ASSERT(!result || result->AsTextureClientDrawTarget(),
+             "Not a TextureClientDrawTarget?");
+  return result;
+}
+
+uint64_t
+CompositableClient::NextTextureID()
 {
   ++mNextTextureID;
   // 0 is always an invalid ID
   if (mNextTextureID == 0) {
     ++mNextTextureID;
   }
-  aClient->SetID(mNextTextureID);
+
+  return mNextTextureID;
+}
+
+bool
+CompositableClient::AddTextureClient(TextureClient* aClient)
+{
+  aClient->SetID(NextTextureID());
   return mForwarder->AddTexture(this, aClient);
 }
 
 void
 CompositableClient::RemoveTextureClient(TextureClient* aClient)
 {
   MOZ_ASSERT(aClient);
   mTexturesToRemove.AppendElement(TextureIDAndFlags(aClient->GetID(),
--- a/gfx/layers/client/CompositableClient.h
+++ b/gfx/layers/client/CompositableClient.h
@@ -83,16 +83,22 @@ public:
   TemporaryRef<DeprecatedTextureClient>
   CreateDeprecatedTextureClient(DeprecatedTextureClientType aDeprecatedTextureClientType,
                                 gfxContentType aContentType = GFX_CONTENT_SENTINEL);
 
   virtual TemporaryRef<BufferTextureClient>
   CreateBufferTextureClient(gfx::SurfaceFormat aFormat,
                             TextureFlags aFlags = TEXTURE_FLAGS_DEFAULT);
 
+  // If we return a non-null TextureClient, then AsTextureClientDrawTarget will
+  // always be non-null.
+  TemporaryRef<TextureClient>
+  CreateTextureClientForDrawing(gfx::SurfaceFormat aFormat,
+                                TextureFlags aTextureFlags);
+
   virtual void SetDescriptorFromReply(TextureIdentifier aTextureId,
                                       const SurfaceDescriptor& aDescriptor)
   {
     MOZ_CRASH("If you want to call this, you should have implemented it");
   }
 
   /**
    * Establishes the connection with compositor side through IPDL
@@ -163,16 +169,19 @@ public:
   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;
--- a/gfx/layers/client/ContentClient.cpp
+++ b/gfx/layers/client/ContentClient.cpp
@@ -57,25 +57,32 @@ ContentClient::CreateContentClient(Compo
   } else
 #endif
   {
     useDoubleBuffering = LayerManagerComposite::SupportsDirectTexturing() ||
                          backend == LAYERS_BASIC;
   }
 
   if (useDoubleBuffering || PR_GetEnv("MOZ_FORCE_DOUBLE_BUFFERING")) {
-    return new ContentClientDoubleBuffered(aForwarder);
+    if (gfxPlatform::GetPlatform()->UseDeprecatedTextures()) {
+      return new DeprecatedContentClientDoubleBuffered(aForwarder);
+    } else {
+      return new ContentClientDoubleBuffered(aForwarder);
+    }
   }
 #ifdef XP_MACOSX
   if (backend == LAYERS_OPENGL) {
     return new ContentClientIncremental(aForwarder);
   }
 #endif
-  return new ContentClientSingleBuffered(aForwarder);
-
+  if (gfxPlatform::GetPlatform()->UseDeprecatedTextures()) {
+    return new DeprecatedContentClientSingleBuffered(aForwarder);
+  } else {
+    return new ContentClientSingleBuffered(aForwarder);
+  }
 }
 
 // We pass a null pointer for the ContentClient Forwarder argument, which means
 // this client will not have a ContentHost on the other side.
 ContentClientBasic::ContentClientBasic()
   : ContentClient(nullptr)
   , RotatedContentBuffer(ContainsVisibleBounds)
 {}
@@ -95,61 +102,261 @@ ContentClientBasic::CreateBuffer(Content
   *aBlackDT = gfxPlatform::GetPlatform()->CreateOffscreenContentDrawTarget(
     IntSize(aRect.width, aRect.height),
     ImageFormatToSurfaceFormat(format));
 }
 
 void
 ContentClientRemoteBuffer::DestroyBuffers()
 {
-  if (!mDeprecatedTextureClient) {
+  if (!mTextureClient) {
     return;
   }
 
-  MOZ_ASSERT(mDeprecatedTextureClient->GetAccessMode() == DeprecatedTextureClient::ACCESS_READ_WRITE);
-  mDeprecatedTextureClient = nullptr;
-  mDeprecatedTextureClientOnWhite = nullptr;
+  mOldTextures.AppendElement(mTextureClient);
+  mTextureClient = nullptr;
+  if (mTextureClientOnWhite) {
+    mOldTextures.AppendElement(mTextureClientOnWhite);
+    mTextureClientOnWhite = nullptr;
+  }
 
   DestroyFrontBuffer();
-
-  mForwarder->DestroyThebesBuffer(this);
 }
 
 void
 ContentClientRemoteBuffer::BeginPaint()
 {
   // XXX: So we might not have a DeprecatedTextureClient yet.. because it will
   // only be created by CreateBuffer.. which will deliver a locked surface!.
-  if (mDeprecatedTextureClient) {
-    SetBufferProvider(mDeprecatedTextureClient);
+  if (mTextureClient) {
+    SetBufferProvider(mTextureClient);
   }
-  if (mDeprecatedTextureClientOnWhite) {
-    SetBufferProviderOnWhite(mDeprecatedTextureClientOnWhite);
+  if (mTextureClientOnWhite) {
+    SetBufferProviderOnWhite(mTextureClientOnWhite);
   }
 }
 
 void
 ContentClientRemoteBuffer::EndPaint()
 {
   // XXX: We might still not have a texture client if PaintThebes
   // decided we didn't need one yet because the region to draw was empty.
   SetBufferProvider(nullptr);
   SetBufferProviderOnWhite(nullptr);
+  for (size_t i = 0; i < mOldTextures.Length(); ++i) {
+    RemoveTextureClient(mOldTextures[i]);
+  }
+  mOldTextures.Clear();
+
+  if (mTextureClient) {
+    mTextureClient->Unlock();
+  }
+  if (mTextureClientOnWhite) {
+    mTextureClientOnWhite->Unlock();
+  }
+}
+
+bool
+ContentClientRemoteBuffer::CreateAndAllocateTextureClient(RefPtr<TextureClient>& aClient,
+                                                          TextureFlags aFlags)
+{
+  aClient = CreateTextureClientForDrawing(mSurfaceFormat,
+                                          mTextureInfo.mTextureFlags | aFlags);
+  if (!aClient) {
+    return false;
+  }
+
+  if (!aClient->AsTextureClientDrawTarget()->AllocateForSurface(mSize, ALLOC_CLEAR_BUFFER)) {
+    aClient = CreateTextureClientForDrawing(mSurfaceFormat,
+                mTextureInfo.mTextureFlags | TEXTURE_ALLOC_FALLBACK | aFlags);
+    if (!aClient) {
+      return false;
+    }
+    if (!aClient->AsTextureClientDrawTarget()->AllocateForSurface(mSize, ALLOC_CLEAR_BUFFER)) {
+      NS_WARNING("Could not allocate texture client");
+      aClient = nullptr;
+      return false;
+    }
+  }
+
+  NS_WARN_IF_FALSE(aClient->IsValid(), "Created an invalid texture client");
+  return true;
+}
+
+void
+ContentClientRemoteBuffer::BuildTextureClients(SurfaceFormat aFormat,
+                                               const nsIntRect& aRect,
+                                               uint32_t aFlags)
+{
+  // If we hit this assertion, then it might be due to an empty transaction
+  // followed by a real transaction. Our buffers should be created (but not
+  // painted in the empty transaction) and then painted (but not created) in the
+  // real transaction. That is kind of fragile, and this assert will catch
+  // circumstances where we screw that up, e.g., by unnecessarily recreating our
+  // buffers.
+  NS_ABORT_IF_FALSE(!mIsNewBuffer,
+                    "Bad! Did we create a buffer twice without painting?");
+
+  mIsNewBuffer = true;
+
+  DestroyBuffers();
+
+  mSurfaceFormat = aFormat;
+  mSize = gfx::IntSize(aRect.width, aRect.height);
+  mTextureInfo.mTextureFlags = (aFlags & ~TEXTURE_DEALLOCATE_CLIENT) |
+                               TEXTURE_DEALLOCATE_DEFERRED;
+
+  if (!CreateAndAllocateTextureClient(mTextureClient, TEXTURE_ON_BLACK) ||
+      !AddTextureClient(mTextureClient)) {
+    AbortTextureClientCreation();
+    return;
+  }
+
+  if (aFlags & BUFFER_COMPONENT_ALPHA) {
+    if (!CreateAndAllocateTextureClient(mTextureClientOnWhite, TEXTURE_ON_WHITE) ||
+        !AddTextureClient(mTextureClientOnWhite)) {
+      AbortTextureClientCreation();
+      return;
+    }
+    mTextureInfo.mTextureFlags |= TEXTURE_COMPONENT_ALPHA;
+  }
+
+  CreateFrontBuffer(aRect);
+}
+
+void
+ContentClientRemoteBuffer::CreateBuffer(ContentType aType,
+                                        const nsIntRect& aRect,
+                                        uint32_t aFlags,
+                                        RefPtr<gfx::DrawTarget>* aBlackDT,
+                                        RefPtr<gfx::DrawTarget>* aWhiteDT)
+{
+  BuildTextureClients(gfxPlatform::GetPlatform()->Optimal2DFormatForContent(aType), aRect, aFlags);
+  if (!mTextureClient) {
+    return;
+  }
+
+  *aBlackDT = mTextureClient->AsTextureClientDrawTarget()->GetAsDrawTarget();
+  if (aFlags & BUFFER_COMPONENT_ALPHA) {
+    *aWhiteDT = mTextureClientOnWhite->AsTextureClientDrawTarget()->GetAsDrawTarget();
+  }
+}
+
+nsIntRegion
+ContentClientRemoteBuffer::GetUpdatedRegion(const nsIntRegion& aRegionToDraw,
+                                            const nsIntRegion& aVisibleRegion,
+                                            bool aDidSelfCopy)
+{
+  nsIntRegion updatedRegion;
+  if (mIsNewBuffer || aDidSelfCopy) {
+    // A buffer reallocation clears both buffers. The front buffer has all the
+    // content by now, but the back buffer is still clear. Here, in effect, we
+    // are saying to copy all of the pixels of the front buffer to the back.
+    // Also when we self-copied in the buffer, the buffer space
+    // changes and some changed buffer content isn't reflected in the
+    // draw or invalidate region (on purpose!).  When this happens, we
+    // need to read back the entire buffer too.
+    updatedRegion = aVisibleRegion;
+    mIsNewBuffer = false;
+  } else {
+    updatedRegion = aRegionToDraw;
+  }
+
+  NS_ASSERTION(BufferRect().Contains(aRegionToDraw.GetBounds()),
+               "Update outside of buffer rect!");
+  NS_ABORT_IF_FALSE(mTextureClient, "should have a back buffer by now");
+
+  return updatedRegion;
+}
+
+void
+ContentClientRemoteBuffer::Updated(const nsIntRegion& aRegionToDraw,
+                                   const nsIntRegion& aVisibleRegion,
+                                   bool aDidSelfCopy)
+{
+  nsIntRegion updatedRegion = GetUpdatedRegion(aRegionToDraw,
+                                               aVisibleRegion,
+                                               aDidSelfCopy);
+
+  MOZ_ASSERT(mTextureClient);
+  mForwarder->UseTexture(this, mTextureClient);
+  mForwarder->UpdateTextureRegion(this,
+                                  ThebesBufferData(BufferRect(),
+                                                   BufferRotation()),
+                                  updatedRegion);
+}
+
+void
+ContentClientRemoteBuffer::SwapBuffers(const nsIntRegion& aFrontUpdatedRegion)
+{
+  MOZ_ASSERT(mTextureClient);
+  mFrontAndBackBufferDiffer = true;
+}
+
+void
+ContentClientRemoteBuffer::OnActorDestroy()
+{
+  if (mTextureClient) {
+    mTextureClient->OnActorDestroy();
+  }
+  if (mTextureClientOnWhite) {
+    mTextureClientOnWhite->OnActorDestroy();
+  }
+  for (size_t i = 0; i < mOldTextures.Length(); ++i) {
+    mOldTextures[i]->OnActorDestroy();
+  }
+}
+
+void
+DeprecatedContentClientRemoteBuffer::DestroyBuffers()
+{
+  if (!mDeprecatedTextureClient) {
+    return;
+  }
+
+  mDeprecatedTextureClient = nullptr;
+  mDeprecatedTextureClientOnWhite = nullptr;
+
+  DestroyFrontBuffer();
+
+  mForwarder->DestroyThebesBuffer(this);
+}
+
+void
+DeprecatedContentClientRemoteBuffer::BeginPaint()
+{
+  // XXX: So we might not have a DeprecatedTextureClient yet.. because it will
+  // only be created by CreateBuffer.. which will deliver a locked surface!.
+  if (mDeprecatedTextureClient) {
+    SetDeprecatedBufferProvider(mDeprecatedTextureClient);
+  }
+  if (mDeprecatedTextureClientOnWhite) {
+    SetDeprecatedBufferProviderOnWhite(mDeprecatedTextureClientOnWhite);
+  }
+}
+
+void
+DeprecatedContentClientRemoteBuffer::EndPaint()
+{
+  // XXX: We might still not have a texture client if PaintThebes
+  // decided we didn't need one yet because the region to draw was empty.
+  SetDeprecatedBufferProvider(nullptr);
+  SetDeprecatedBufferProviderOnWhite(nullptr);
   mOldTextures.Clear();
 
   if (mDeprecatedTextureClient) {
     mDeprecatedTextureClient->Unlock();
   }
   if (mDeprecatedTextureClientOnWhite) {
     mDeprecatedTextureClientOnWhite->Unlock();
   }
 }
 
 bool
-ContentClientRemoteBuffer::CreateAndAllocateDeprecatedTextureClient(RefPtr<DeprecatedTextureClient>& aClient)
+DeprecatedContentClientRemoteBuffer::CreateAndAllocateDeprecatedTextureClient(RefPtr<DeprecatedTextureClient>& aClient)
 {
   aClient = CreateDeprecatedTextureClient(TEXTURE_CONTENT, mContentType);
   MOZ_ASSERT(aClient, "Failed to create texture client");
 
   if (!aClient->EnsureAllocated(mSize, mContentType)) {
     aClient = CreateDeprecatedTextureClient(TEXTURE_FALLBACK, mContentType);
     MOZ_ASSERT(aClient, "Failed to create texture client");
     if (!aClient->EnsureAllocated(mSize, mContentType)) {
@@ -160,17 +367,17 @@ ContentClientRemoteBuffer::CreateAndAllo
     }
   }
 
   MOZ_ASSERT(IsSurfaceDescriptorValid(*aClient->GetDescriptor()));
   return true;
 }
 
 void
-ContentClientRemoteBuffer::BuildDeprecatedTextureClients(ContentType aType,
+DeprecatedContentClientRemoteBuffer::BuildDeprecatedTextureClients(ContentType aType,
                                                const nsIntRect& aRect,
                                                uint32_t aFlags)
 {
   NS_ABORT_IF_FALSE(!mIsNewBuffer,
                     "Bad! Did we create a buffer twice without painting?");
 
   if (mDeprecatedTextureClient) {
     mOldTextures.AppendElement(mDeprecatedTextureClient);
@@ -197,17 +404,17 @@ ContentClientRemoteBuffer::BuildDeprecat
     mTextureInfo.mTextureFlags |= TEXTURE_COMPONENT_ALPHA;
   }
 
   CreateFrontBufferAndNotify(aRect);
   mIsNewBuffer = true;
 }
 
 void
-ContentClientRemoteBuffer::CreateBuffer(ContentType aType,
+DeprecatedContentClientRemoteBuffer::CreateBuffer(ContentType aType,
                                         const nsIntRect& aRect,
                                         uint32_t aFlags,
                                         RefPtr<gfx::DrawTarget>* aBlackDT,
                                         RefPtr<gfx::DrawTarget>* aWhiteDT)
 {
   BuildDeprecatedTextureClients(aType, aRect, aFlags);
   if (!mDeprecatedTextureClient) {
     return;
@@ -217,17 +424,17 @@ ContentClientRemoteBuffer::CreateBuffer(
         mDeprecatedTextureClient->BackendType()));
   *aBlackDT = mDeprecatedTextureClient->LockDrawTarget();
   if (aFlags & BUFFER_COMPONENT_ALPHA) {
     *aWhiteDT = mDeprecatedTextureClientOnWhite->LockDrawTarget();
   }
 }
 
 nsIntRegion
-ContentClientRemoteBuffer::GetUpdatedRegion(const nsIntRegion& aRegionToDraw,
+DeprecatedContentClientRemoteBuffer::GetUpdatedRegion(const nsIntRegion& aRegionToDraw,
                                             const nsIntRegion& aVisibleRegion,
                                             bool aDidSelfCopy)
 {
   nsIntRegion updatedRegion;
   if (mIsNewBuffer || aDidSelfCopy) {
     // A buffer reallocation clears both buffers. The front buffer has all the
     // content by now, but the back buffer is still clear. Here, in effect, we
     // are saying to copy all of the pixels of the front buffer to the back.
@@ -244,17 +451,17 @@ ContentClientRemoteBuffer::GetUpdatedReg
   NS_ASSERTION(BufferRect().Contains(aRegionToDraw.GetBounds()),
                "Update outside of buffer rect!");
   NS_ABORT_IF_FALSE(mDeprecatedTextureClient, "should have a back buffer by now");
 
   return updatedRegion;
 }
 
 void
-ContentClientRemoteBuffer::Updated(const nsIntRegion& aRegionToDraw,
+DeprecatedContentClientRemoteBuffer::Updated(const nsIntRegion& aRegionToDraw,
                                    const nsIntRegion& aVisibleRegion,
                                    bool aDidSelfCopy)
 {
   nsIntRegion updatedRegion = GetUpdatedRegion(aRegionToDraw,
                                                aVisibleRegion,
                                                aDidSelfCopy);
 
   MOZ_ASSERT(mDeprecatedTextureClient);
@@ -265,60 +472,234 @@ ContentClientRemoteBuffer::Updated(const
   LockFrontBuffer();
   mForwarder->UpdateTextureRegion(this,
                                   ThebesBufferData(BufferRect(),
                                                    BufferRotation()),
                                   updatedRegion);
 }
 
 void
-ContentClientRemoteBuffer::SwapBuffers(const nsIntRegion& aFrontUpdatedRegion)
+DeprecatedContentClientRemoteBuffer::SwapBuffers(const nsIntRegion& aFrontUpdatedRegion)
 {
   MOZ_ASSERT(mDeprecatedTextureClient->GetAccessMode() == DeprecatedTextureClient::ACCESS_NONE);
   MOZ_ASSERT(!mDeprecatedTextureClientOnWhite || mDeprecatedTextureClientOnWhite->GetAccessMode() == DeprecatedTextureClient::ACCESS_NONE);
   MOZ_ASSERT(mDeprecatedTextureClient);
 
   mFrontAndBackBufferDiffer = true;
   mDeprecatedTextureClient->SetAccessMode(DeprecatedTextureClient::ACCESS_READ_WRITE);
   if (mDeprecatedTextureClientOnWhite) {
     mDeprecatedTextureClientOnWhite->SetAccessMode(DeprecatedTextureClient::ACCESS_READ_WRITE);
   }
 }
 
 
 void
-ContentClientRemoteBuffer::OnActorDestroy()
+DeprecatedContentClientRemoteBuffer::OnActorDestroy()
 {
   if (mDeprecatedTextureClient) {
     mDeprecatedTextureClient->OnActorDestroy();
   }
   if (mDeprecatedTextureClientOnWhite) {
     mDeprecatedTextureClientOnWhite->OnActorDestroy();
   }
   for (size_t i = 0; i < mOldTextures.Length(); ++i) {
     mOldTextures[i]->OnActorDestroy();
   }
 }
+ 
+void
+ContentClientDoubleBuffered::CreateFrontBuffer(const nsIntRect& aBufferRect)
+{
+  if (!CreateAndAllocateTextureClient(mFrontClient, TEXTURE_ON_BLACK) ||
+      !AddTextureClient(mFrontClient)) {
+    AbortTextureClientCreation();
+    return;
+  }
+  if (mTextureInfo.mTextureFlags & TEXTURE_COMPONENT_ALPHA) {
+    if (!CreateAndAllocateTextureClient(mFrontClientOnWhite, TEXTURE_ON_WHITE) ||
+        !AddTextureClient(mFrontClientOnWhite)) {
+      AbortTextureClientCreation();
+      return;
+    }
+  }
 
-ContentClientDoubleBuffered::~ContentClientDoubleBuffered()
+  mFrontBufferRect = aBufferRect;
+  mFrontBufferRotation = nsIntPoint();
+}
+
+void
+ContentClientDoubleBuffered::DestroyFrontBuffer()
+{
+  MOZ_ASSERT(mFrontClient);
+
+  mOldTextures.AppendElement(mFrontClient);
+  mFrontClient = nullptr;
+  if (mFrontClientOnWhite) {
+    mOldTextures.AppendElement(mFrontClientOnWhite);
+    mFrontClientOnWhite = nullptr;
+  }
+}
+
+void
+ContentClientDoubleBuffered::SwapBuffers(const nsIntRegion& aFrontUpdatedRegion)
+{
+  mFrontUpdatedRegion = aFrontUpdatedRegion;
+
+  RefPtr<TextureClient> oldBack = mTextureClient;
+  mTextureClient = mFrontClient;
+  mFrontClient = oldBack;
+
+  oldBack = mTextureClientOnWhite;
+  mTextureClientOnWhite = mFrontClientOnWhite;
+  mFrontClientOnWhite = oldBack;
+
+  nsIntRect oldBufferRect = mBufferRect;
+  mBufferRect = mFrontBufferRect;
+  mFrontBufferRect = oldBufferRect;
+
+  nsIntPoint oldBufferRotation = mBufferRotation;
+  mBufferRotation = mFrontBufferRotation;
+  mFrontBufferRotation = oldBufferRotation;
+
+  MOZ_ASSERT(mFrontClient);
+
+  ContentClientRemoteBuffer::SwapBuffers(aFrontUpdatedRegion);
+}
+
+void
+ContentClientDoubleBuffered::SyncFrontBufferToBackBuffer()
+{
+  if (!mFrontAndBackBufferDiffer) {
+    return;
+  }
+  MOZ_ASSERT(mFrontClient);
+
+  MOZ_LAYERS_LOG(("BasicShadowableThebes(%p): reading back <x=%d,y=%d,w=%d,h=%d>",
+                  this,
+                  mFrontUpdatedRegion.GetBounds().x,
+                  mFrontUpdatedRegion.GetBounds().y,
+                  mFrontUpdatedRegion.GetBounds().width,
+                  mFrontUpdatedRegion.GetBounds().height));
+
+  nsIntRegion updateRegion = mFrontUpdatedRegion;
+
+  // This is a tricky trade off, we're going to get stuff out of our
+  // frontbuffer now, but the next PaintThebes might throw it all (or mostly)
+  // away if the visible region has changed. This is why in reality we want
+  // this code integrated with PaintThebes to always do the optimal thing.
+
+  if (mDidSelfCopy) {
+    mDidSelfCopy = false;
+    // We can't easily draw our front buffer into us, since we're going to be
+    // copying stuff around anyway it's easiest if we just move our situation
+    // to non-rotated while we're at it. If this situation occurs we'll have
+    // hit a self-copy path in PaintThebes before as well anyway.
+    mBufferRect.MoveTo(mFrontBufferRect.TopLeft());
+    mBufferRotation = nsIntPoint();
+    updateRegion = mBufferRect;
+  } else {
+    mBufferRect = mFrontBufferRect;
+    mBufferRotation = mFrontBufferRotation;
+  }
+
+  mIsNewBuffer = false;
+  mFrontAndBackBufferDiffer = false;
+
+  // We need to ensure that we lock these two buffers in the same
+  // order as the compositor to prevent deadlocks.
+  if (!mFrontClient->Lock(OPEN_READ_ONLY)) {
+    return;
+  }
+  if (mFrontClientOnWhite &&
+      !mFrontClientOnWhite->Lock(OPEN_READ_ONLY)) {
+    mFrontClient->Unlock();
+    return;
+  }
+  RefPtr<DrawTarget> dt =
+    mFrontClient->AsTextureClientDrawTarget()->GetAsDrawTarget();
+  RefPtr<DrawTarget> dtOnWhite = mFrontClientOnWhite
+    ? mFrontClientOnWhite->AsTextureClientDrawTarget()->GetAsDrawTarget()
+    : nullptr;
+  RotatedBuffer frontBuffer(dt,
+                            dtOnWhite,
+                            mFrontBufferRect,
+                            mFrontBufferRotation);
+  UpdateDestinationFrom(frontBuffer, updateRegion);
+  mFrontClient->Unlock();
+  if (mFrontClientOnWhite) {
+    mFrontClientOnWhite->Unlock();
+  }
+}
+
+void
+ContentClientDoubleBuffered::UpdateDestinationFrom(const RotatedBuffer& aSource,
+                                                   const nsIntRegion& aUpdateRegion)
+{
+  nsRefPtr<gfxContext> destCtx =
+    GetContextForQuadrantUpdate(aUpdateRegion.GetBounds(), BUFFER_BLACK);
+  destCtx->SetOperator(gfxContext::OPERATOR_SOURCE);
+
+  bool isClippingCheap = IsClippingCheap(destCtx, aUpdateRegion);
+  if (isClippingCheap) {
+    gfxUtils::ClipToRegion(destCtx, aUpdateRegion);
+  }
+
+  aSource.DrawBufferWithRotation(destCtx->GetDrawTarget(), BUFFER_BLACK, 1.0, OP_SOURCE);
+
+  if (aSource.HaveBufferOnWhite()) {
+    MOZ_ASSERT(HaveBufferOnWhite());
+    nsRefPtr<gfxContext> destCtx =
+      GetContextForQuadrantUpdate(aUpdateRegion.GetBounds(), BUFFER_WHITE);
+    destCtx->SetOperator(gfxContext::OPERATOR_SOURCE);
+
+    bool isClippingCheap = IsClippingCheap(destCtx, aUpdateRegion);
+    if (isClippingCheap) {
+      gfxUtils::ClipToRegion(destCtx, aUpdateRegion);
+    }
+
+    aSource.DrawBufferWithRotation(destCtx->GetDrawTarget(), BUFFER_WHITE, 1.0, OP_SOURCE);
+  }
+}
+
+void
+ContentClientDoubleBuffered::OnActorDestroy()
+{
+  if (mTextureClient) {
+    mTextureClient->OnActorDestroy();
+  }
+  if (mTextureClientOnWhite) {
+    mTextureClientOnWhite->OnActorDestroy();
+  }
+  for (size_t i = 0; i < mOldTextures.Length(); ++i) {
+    mOldTextures[i]->OnActorDestroy();
+  }
+  if (mFrontClient) {
+    mFrontClient->OnActorDestroy();
+  }
+  if (mFrontClientOnWhite) {
+    mFrontClientOnWhite->OnActorDestroy();
+  }
+}
+
+DeprecatedContentClientDoubleBuffered::~DeprecatedContentClientDoubleBuffered()
 {
   if (mDeprecatedTextureClient) {
     MOZ_ASSERT(mFrontClient);
     mDeprecatedTextureClient->SetDescriptor(SurfaceDescriptor());
     mFrontClient->SetDescriptor(SurfaceDescriptor());
   }
   if (mDeprecatedTextureClientOnWhite) {
     MOZ_ASSERT(mFrontClientOnWhite);
     mDeprecatedTextureClientOnWhite->SetDescriptor(SurfaceDescriptor());
     mFrontClientOnWhite->SetDescriptor(SurfaceDescriptor());
   }
 }
 
 void
-ContentClientDoubleBuffered::CreateFrontBufferAndNotify(const nsIntRect& aBufferRect)
+DeprecatedContentClientDoubleBuffered::CreateFrontBufferAndNotify(const nsIntRect& aBufferRect)
 {
   if (!CreateAndAllocateDeprecatedTextureClient(mFrontClient)) {
     mDeprecatedTextureClient->SetFlags(0);
     mDeprecatedTextureClient = nullptr;
     if (mDeprecatedTextureClientOnWhite) {
       mDeprecatedTextureClientOnWhite->SetFlags(0);
       mDeprecatedTextureClientOnWhite = nullptr;
     }
@@ -344,37 +725,37 @@ ContentClientDoubleBuffered::CreateFront
                                   *mFrontClient->LockSurfaceDescriptor(),
                                   *mDeprecatedTextureClient->LockSurfaceDescriptor(),
                                   mTextureInfo,
                                   mFrontClientOnWhite ? mFrontClientOnWhite->LockSurfaceDescriptor() : nullptr,
                                   mDeprecatedTextureClientOnWhite ? mDeprecatedTextureClientOnWhite->LockSurfaceDescriptor() : nullptr);
 }
 
 void
-ContentClientDoubleBuffered::DestroyFrontBuffer()
+DeprecatedContentClientDoubleBuffered::DestroyFrontBuffer()
 {
   MOZ_ASSERT(mFrontClient);
   MOZ_ASSERT(mFrontClient->GetAccessMode() != DeprecatedTextureClient::ACCESS_NONE);
 
   mFrontClient = nullptr;
   mFrontClientOnWhite = nullptr;
 }
 
 void
-ContentClientDoubleBuffered::LockFrontBuffer()
+DeprecatedContentClientDoubleBuffered::LockFrontBuffer()
 {
   MOZ_ASSERT(mFrontClient);
   mFrontClient->SetAccessMode(DeprecatedTextureClient::ACCESS_NONE);
   if (mFrontClientOnWhite) {
     mFrontClientOnWhite->SetAccessMode(DeprecatedTextureClient::ACCESS_NONE);
   }
 }
 
 void
-ContentClientDoubleBuffered::SwapBuffers(const nsIntRegion& aFrontUpdatedRegion)
+DeprecatedContentClientDoubleBuffered::SwapBuffers(const nsIntRegion& aFrontUpdatedRegion)
 {
   mFrontUpdatedRegion = aFrontUpdatedRegion;
 
   RefPtr<DeprecatedTextureClient> oldBack = mDeprecatedTextureClient;
   mDeprecatedTextureClient = mFrontClient;
   mFrontClient = oldBack;
 
   oldBack = mDeprecatedTextureClientOnWhite;
@@ -390,21 +771,21 @@ ContentClientDoubleBuffered::SwapBuffers
   mFrontBufferRotation = oldBufferRotation;
 
   MOZ_ASSERT(mFrontClient);
   mFrontClient->SetAccessMode(DeprecatedTextureClient::ACCESS_READ_ONLY);
   if (mFrontClientOnWhite) {
     mFrontClientOnWhite->SetAccessMode(DeprecatedTextureClient::ACCESS_READ_ONLY);
   }
 
-  ContentClientRemoteBuffer::SwapBuffers(aFrontUpdatedRegion);
+  DeprecatedContentClientRemoteBuffer::SwapBuffers(aFrontUpdatedRegion);
 }
 
 void
-ContentClientDoubleBuffered::OnActorDestroy()
+DeprecatedContentClientDoubleBuffered::OnActorDestroy()
 {
   if (mDeprecatedTextureClient) {
     mDeprecatedTextureClient->OnActorDestroy();
   }
   if (mDeprecatedTextureClientOnWhite) {
     mDeprecatedTextureClientOnWhite->OnActorDestroy();
   }
   for (size_t i = 0; i < mOldTextures.Length(); ++i) {
@@ -437,17 +818,17 @@ struct AutoDeprecatedTextureClient {
     }
     return nullptr;
   }
 private:
   DeprecatedTextureClient* mTexture;
 };
 
 void
-ContentClientDoubleBuffered::SyncFrontBufferToBackBuffer()
+DeprecatedContentClientDoubleBuffered::SyncFrontBufferToBackBuffer()
 {
   mIsNewBuffer = false;
 
   if (!mFrontAndBackBufferDiffer) {
     return;
   }
   MOZ_ASSERT(mFrontClient);
   MOZ_ASSERT(mFrontClient->GetAccessMode() == DeprecatedTextureClient::ACCESS_READ_ONLY);
@@ -493,17 +874,17 @@ ContentClientDoubleBuffered::SyncFrontBu
                             mFrontBufferRect,
                             mFrontBufferRotation);
   UpdateDestinationFrom(frontBuffer, updateRegion);
 
   mFrontAndBackBufferDiffer = false;
 }
 
 void
-ContentClientDoubleBuffered::UpdateDestinationFrom(const RotatedBuffer& aSource,
+DeprecatedContentClientDoubleBuffered::UpdateDestinationFrom(const RotatedBuffer& aSource,
                                                    const nsIntRegion& aUpdateRegion)
 {
   nsRefPtr<gfxContext> destCtx =
     GetContextForQuadrantUpdate(aUpdateRegion.GetBounds(), BUFFER_BLACK);
   if (!destCtx) {
     return;
   }
   destCtx->SetOperator(gfxContext::OPERATOR_SOURCE);
@@ -525,37 +906,65 @@ ContentClientDoubleBuffered::UpdateDesti
     if (isClippingCheap) {
       gfxUtils::ClipToRegion(destCtx, aUpdateRegion);
     }
 
     aSource.DrawBufferWithRotation(destCtx->GetDrawTarget(), BUFFER_WHITE, 1.0, OP_SOURCE);
   }
 }
 
-ContentClientSingleBuffered::~ContentClientSingleBuffered()
+void
+ContentClientSingleBuffered::SyncFrontBufferToBackBuffer()
+{
+  if (!mFrontAndBackBufferDiffer) {
+    return;
+  }
+
+  RefPtr<DrawTarget> backBuffer = GetDTBuffer();
+  if (!backBuffer && mTextureClient) {
+    backBuffer = mTextureClient->AsTextureClientDrawTarget()->GetAsDrawTarget();
+  }
+
+  RefPtr<DrawTarget> oldBuffer;
+  oldBuffer = SetDTBuffer(backBuffer,
+                          mBufferRect,
+                          mBufferRotation);
+
+  backBuffer = GetDTBufferOnWhite();
+  if (!backBuffer && mTextureClientOnWhite) {
+    backBuffer = mTextureClientOnWhite->AsTextureClientDrawTarget()->GetAsDrawTarget();
+  }
+
+  oldBuffer = SetDTBufferOnWhite(backBuffer);
+
+  mIsNewBuffer = false;
+  mFrontAndBackBufferDiffer = false;
+}
+
+DeprecatedContentClientSingleBuffered::~DeprecatedContentClientSingleBuffered()
 {
   if (mDeprecatedTextureClient) {
     mDeprecatedTextureClient->SetDescriptor(SurfaceDescriptor());
   }
   if (mDeprecatedTextureClientOnWhite) {
     mDeprecatedTextureClientOnWhite->SetDescriptor(SurfaceDescriptor());
   }
 }
 
 void
-ContentClientSingleBuffered::CreateFrontBufferAndNotify(const nsIntRect& aBufferRect)
+DeprecatedContentClientSingleBuffered::CreateFrontBufferAndNotify(const nsIntRect& aBufferRect)
 {
   mForwarder->CreatedSingleBuffer(this,
                                   *mDeprecatedTextureClient->LockSurfaceDescriptor(),
                                   mTextureInfo,
                                   mDeprecatedTextureClientOnWhite ? mDeprecatedTextureClientOnWhite->LockSurfaceDescriptor() : nullptr);
 }
 
 void
-ContentClientSingleBuffered::SyncFrontBufferToBackBuffer()
+DeprecatedContentClientSingleBuffered::SyncFrontBufferToBackBuffer()
 {
   mIsNewBuffer = false;
   if (!mFrontAndBackBufferDiffer) {
     return;
   }
   mFrontAndBackBufferDiffer = false;
 
   DrawTarget* backBuffer = GetDTBuffer();
--- a/gfx/layers/client/ContentClient.h
+++ b/gfx/layers/client/ContentClient.h
@@ -173,25 +173,127 @@ public:
  * compositing side with the create message (send from CreateBuffer) which
  * tells the compositor that TextureClients have been created and that the
  * compositor should assign the corresponding TextureHosts to our corresponding
  * ContentHost.
  *
  * If the size or type of our buffer(s) change(s), then we simply destroy and
  * create them.
  */
+// Version using new texture clients
 class ContentClientRemoteBuffer : public ContentClientRemote
                                 , protected RotatedContentBuffer
 {
   using RotatedContentBuffer::BufferRect;
   using RotatedContentBuffer::BufferRotation;
 public:
   ContentClientRemoteBuffer(CompositableForwarder* aForwarder)
     : ContentClientRemote(aForwarder)
     , RotatedContentBuffer(ContainsVisibleBounds)
+    , mIsNewBuffer(false)
+    , mFrontAndBackBufferDiffer(false)
+    , mSurfaceFormat(gfx::FORMAT_B8G8R8A8)
+  {}
+
+  typedef RotatedContentBuffer::PaintState PaintState;
+  typedef RotatedContentBuffer::ContentType ContentType;
+
+  virtual void Clear() { RotatedContentBuffer::Clear(); }
+  PaintState BeginPaintBuffer(ThebesLayer* aLayer, ContentType aContentType,
+                              uint32_t aFlags)
+  {
+    return RotatedContentBuffer::BeginPaint(aLayer, aContentType, aFlags);
+  }
+
+  /**
+   * Begin/End Paint map a gfxASurface from the texture client
+   * into the buffer of RotatedBuffer. The surface is only
+   * valid when the texture client is locked, so is mapped out
+   * of RotatedContentBuffer when we are done painting.
+   * None of the underlying buffer attributes (rect, rotation)
+   * are affected by mapping/unmapping.
+   */
+  virtual void BeginPaint() MOZ_OVERRIDE;
+  virtual void EndPaint() MOZ_OVERRIDE;
+
+  virtual void Updated(const nsIntRegion& aRegionToDraw,
+                       const nsIntRegion& aVisibleRegion,
+                       bool aDidSelfCopy);
+
+  virtual void SwapBuffers(const nsIntRegion& aFrontUpdatedRegion) MOZ_OVERRIDE;
+
+  // Expose these protected methods from the superclass.
+  virtual const nsIntRect& BufferRect() const
+  {
+    return RotatedContentBuffer::BufferRect();
+  }
+  virtual const nsIntPoint& BufferRotation() const
+  {
+    return RotatedContentBuffer::BufferRotation();
+  }
+
+  virtual void CreateBuffer(ContentType aType, const nsIntRect& aRect, uint32_t aFlags,
+                            RefPtr<gfx::DrawTarget>* aBlackDT, RefPtr<gfx::DrawTarget>* aWhiteDT) MOZ_OVERRIDE;
+
+  virtual TextureInfo GetTextureInfo() const MOZ_OVERRIDE
+  {
+    return mTextureInfo;
+  }
+
+  virtual void OnActorDestroy() MOZ_OVERRIDE;
+
+protected:
+  void DestroyBuffers();
+
+  virtual nsIntRegion GetUpdatedRegion(const nsIntRegion& aRegionToDraw,
+                                       const nsIntRegion& aVisibleRegion,
+                                       bool aDidSelfCopy);
+
+  void BuildTextureClients(gfx::SurfaceFormat aFormat,
+                           const nsIntRect& aRect,
+                           uint32_t aFlags);
+
+  // Create the front buffer for the ContentClient/Host pair if necessary
+  // and notify the compositor that we have created the buffer(s).
+  virtual void CreateFrontBuffer(const nsIntRect& aBufferRect) = 0;
+  virtual void DestroyFrontBuffer() {}
+
+  bool CreateAndAllocateTextureClient(RefPtr<TextureClient>& aClient,
+                                      TextureFlags aFlags = 0);
+
+  virtual void AbortTextureClientCreation()
+  {
+    mTextureClient = nullptr;
+    mTextureClientOnWhite = nullptr;
+    mIsNewBuffer = false;
+  }
+
+  RefPtr<TextureClient> mTextureClient;
+  RefPtr<TextureClient> mTextureClientOnWhite;
+  // keep a record of texture clients we have created and need to keep around
+  // (for RotatedBuffer to access), then unlock and remove them when we are done
+  // painting.
+  nsTArray<RefPtr<TextureClient> > mOldTextures;
+
+  TextureInfo mTextureInfo;
+  bool mIsNewBuffer;
+  bool mFrontAndBackBufferDiffer;
+  gfx::IntSize mSize;
+  gfx::SurfaceFormat mSurfaceFormat;
+};
+
+class DeprecatedContentClientRemoteBuffer : public ContentClientRemote
+                                          , protected RotatedContentBuffer
+{
+  using RotatedContentBuffer::BufferRect;
+  using RotatedContentBuffer::BufferRotation;
+public:
+  DeprecatedContentClientRemoteBuffer(CompositableForwarder* aForwarder)
+    : ContentClientRemote(aForwarder)
+    , RotatedContentBuffer(ContainsVisibleBounds)
     , mDeprecatedTextureClient(nullptr)
     , mIsNewBuffer(false)
     , mFrontAndBackBufferDiffer(false)
     , mContentType(GFX_CONTENT_COLOR_ALPHA)
   {}
 
   typedef RotatedContentBuffer::PaintState PaintState;
   typedef RotatedContentBuffer::ContentType ContentType;
@@ -228,26 +330,26 @@ public:
   virtual const nsIntPoint& BufferRotation() const
   {
     return RotatedContentBuffer::BufferRotation();
   }
 
   virtual void CreateBuffer(ContentType aType, const nsIntRect& aRect, uint32_t aFlags,
                             RefPtr<gfx::DrawTarget>* aBlackDT, RefPtr<gfx::DrawTarget>* aWhiteDT) MOZ_OVERRIDE;
 
-  void DestroyBuffers();
-
   virtual TextureInfo GetTextureInfo() const MOZ_OVERRIDE
   {
     return mTextureInfo;
   }
 
   virtual void OnActorDestroy() MOZ_OVERRIDE;
 
 protected:
+  void DestroyBuffers();
+
   virtual nsIntRegion GetUpdatedRegion(const nsIntRegion& aRegionToDraw,
                                        const nsIntRegion& aVisibleRegion,
                                        bool aDidSelfCopy);
 
   // create and configure mDeprecatedTextureClient
   void BuildDeprecatedTextureClients(ContentType aType,
                                      const nsIntRect& aRect,
                                      uint32_t aFlags);
@@ -287,31 +389,70 @@ protected:
  * (in SwapBuffers).
  */
 class ContentClientDoubleBuffered : public ContentClientRemoteBuffer
 {
 public:
   ContentClientDoubleBuffered(CompositableForwarder* aFwd)
     : ContentClientRemoteBuffer(aFwd)
   {
-    mTextureInfo.mCompositableType = BUFFER_CONTENT_DIRECT;
+    mTextureInfo.mCompositableType = COMPOSITABLE_CONTENT_DOUBLE;
   }
-  ~ContentClientDoubleBuffered();
+  virtual ~ContentClientDoubleBuffered() {}
 
   virtual void SwapBuffers(const nsIntRegion& aFrontUpdatedRegion) MOZ_OVERRIDE;
 
   virtual void SyncFrontBufferToBackBuffer() MOZ_OVERRIDE;
 
+  virtual void OnActorDestroy() MOZ_OVERRIDE;
+
+protected:
+  virtual void CreateFrontBuffer(const nsIntRect& aBufferRect) MOZ_OVERRIDE;
+  virtual void DestroyFrontBuffer() MOZ_OVERRIDE;
+
+private:
+  void UpdateDestinationFrom(const RotatedBuffer& aSource,
+                             const nsIntRegion& aUpdateRegion);
+
+  virtual void AbortTextureClientCreation() MOZ_OVERRIDE
+  {
+    mTextureClient = nullptr;
+    mTextureClientOnWhite = nullptr;
+    mFrontClient = nullptr;
+    mFrontClientOnWhite = nullptr;
+  }
+
+  RefPtr<TextureClient> mFrontClient;
+  RefPtr<TextureClient> mFrontClientOnWhite;
+  nsIntRegion mFrontUpdatedRegion;
+  nsIntRect mFrontBufferRect;
+  nsIntPoint mFrontBufferRotation;
+};
+
+class DeprecatedContentClientDoubleBuffered : public DeprecatedContentClientRemoteBuffer
+{
+public:
+  DeprecatedContentClientDoubleBuffered(CompositableForwarder* aFwd)
+    : DeprecatedContentClientRemoteBuffer(aFwd)
+  {
+    mTextureInfo.mCompositableType = BUFFER_CONTENT_DIRECT;
+  }
+  ~DeprecatedContentClientDoubleBuffered();
+
+  virtual void SwapBuffers(const nsIntRegion& aFrontUpdatedRegion) MOZ_OVERRIDE;
+
+  virtual void SyncFrontBufferToBackBuffer() MOZ_OVERRIDE;
+
+  virtual void OnActorDestroy() MOZ_OVERRIDE;
+
 protected:
   virtual void CreateFrontBufferAndNotify(const nsIntRect& aBufferRect) MOZ_OVERRIDE;
   virtual void DestroyFrontBuffer() MOZ_OVERRIDE;
   virtual void LockFrontBuffer() MOZ_OVERRIDE;
 
-  virtual void OnActorDestroy() MOZ_OVERRIDE;
-
 private:
   void UpdateDestinationFrom(const RotatedBuffer& aSource,
                              const nsIntRegion& aUpdateRegion);
 
   RefPtr<DeprecatedTextureClient> mFrontClient;
   RefPtr<DeprecatedTextureClient> mFrontClientOnWhite;
   nsIntRegion mFrontUpdatedRegion;
   nsIntRect mFrontBufferRect;
@@ -327,19 +468,35 @@ private:
  * the compositor.
  */
 class ContentClientSingleBuffered : public ContentClientRemoteBuffer
 {
 public:
   ContentClientSingleBuffered(CompositableForwarder* aFwd)
     : ContentClientRemoteBuffer(aFwd)
   {
+    mTextureInfo.mCompositableType = COMPOSITABLE_CONTENT_SINGLE;
+  }
+  virtual ~ContentClientSingleBuffered() {}
+
+  virtual void SyncFrontBufferToBackBuffer() MOZ_OVERRIDE;
+
+protected:
+  virtual void CreateFrontBuffer(const nsIntRect& aBufferRect) MOZ_OVERRIDE {}
+};
+
+class DeprecatedContentClientSingleBuffered : public DeprecatedContentClientRemoteBuffer
+{
+public:
+  DeprecatedContentClientSingleBuffered(CompositableForwarder* aFwd)
+    : DeprecatedContentClientRemoteBuffer(aFwd)
+  {
     mTextureInfo.mCompositableType = BUFFER_CONTENT;    
   }
-  ~ContentClientSingleBuffered();
+  ~DeprecatedContentClientSingleBuffered();
 
   virtual void SyncFrontBufferToBackBuffer() MOZ_OVERRIDE;
 
 protected:
   virtual void CreateFrontBufferAndNotify(const nsIntRect& aBufferRect) MOZ_OVERRIDE;
 };
 
 /**
--- a/gfx/layers/client/TextureClient.cpp
+++ b/gfx/layers/client/TextureClient.cpp
@@ -300,32 +300,50 @@ BufferTextureClient::GetAsSurface()
   }
 
   RefPtr<gfxImageSurface> surf = serializer.GetAsThebesSurface();
   nsRefPtr<gfxASurface> result = surf.get();
   return result.forget();
 }
 
 bool
-BufferTextureClient::AllocateForSurface(gfx::IntSize aSize)
+BufferTextureClient::AllocateForSurface(gfx::IntSize aSize, TextureAllocationFlags aFlags)
 {
   MOZ_ASSERT(IsValid());
   MOZ_ASSERT(mFormat != gfx::FORMAT_YUV, "This textureClient cannot use YCbCr data");
 
   int bufSize
     = ImageDataSerializer::ComputeMinBufferSize(aSize, mFormat);
   if (!Allocate(bufSize)) {
     return false;
   }
+
+  if (aFlags & ALLOC_CLEAR_BUFFER) {
+    memset(GetBuffer(), 0, bufSize);
+  }
+
   ImageDataSerializer serializer(GetBuffer());
   serializer.InitializeBufferInfo(aSize, mFormat);
   mSize = aSize;
   return true;
 }
 
+TemporaryRef<gfx::DrawTarget>
+BufferTextureClient::GetAsDrawTarget()
+{
+  MOZ_ASSERT(IsValid());
+
+  ImageDataSerializer serializer(GetBuffer());
+  if (!serializer.IsValid()) {
+    return nullptr;
+  }
+
+  return serializer.GetAsDrawTarget();
+}
+
 bool
 BufferTextureClient::UpdateYCbCr(const PlanarYCbCrData& aData)
 {
   MOZ_ASSERT(mFormat == gfx::FORMAT_YUV, "This textureClient can only use YCbCr data");
   MOZ_ASSERT(!IsImmutable());
   MOZ_ASSERT(IsValid());
   MOZ_ASSERT(aData.mCbSkip == aData.mCrSkip);
 
--- a/gfx/layers/client/TextureClient.h
+++ b/gfx/layers/client/TextureClient.h
@@ -43,25 +43,57 @@ class Image;
 /**
  * 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.
  */
 
+enum TextureAllocationFlags {
+  ALLOC_DEFAULT = 0,
+  ALLOC_CLEAR_BUFFER = 1
+};
+
 /**
  * Interface for TextureClients that can be updated using a gfxASurface.
  */
 class TextureClientSurface
 {
 public:
   virtual bool UpdateSurface(gfxASurface* aSurface) = 0;
   virtual already_AddRefed<gfxASurface> GetAsSurface() = 0;
-  virtual bool AllocateForSurface(gfx::IntSize aSize) = 0;
+  /**
+   * Allocates for a given surface size, taking into account the pixel format
+   * which is part of the state of the TextureClient.
+   *
+   * Does not clear the surface by default, clearing the surface can be done
+   * by passing the CLEAR_BUFFER flag.
+   */
+  virtual bool AllocateForSurface(gfx::IntSize aSize,
+                                  TextureAllocationFlags flags = ALLOC_DEFAULT) = 0;
+};
+
+/**
+ * Interface for TextureClients that can be updated using a DrawTarget.
+ */
+class TextureClientDrawTarget
+{
+public:
+  virtual TemporaryRef<gfx::DrawTarget> GetAsDrawTarget() = 0;
+  virtual gfx::SurfaceFormat GetFormat() const = 0;
+  /**
+   * Allocates for a given surface size, taking into account the pixel format
+   * which is part of the state of the TextureClient.
+   *
+   * Does not clear the surface by default, clearing the surface can be done
+   * by passing the CLEAR_BUFFER flag.
+   */
+  virtual bool AllocateForSurface(gfx::IntSize aSize,
+                                  TextureAllocationFlags flags = ALLOC_DEFAULT) = 0;
 };
 
 /**
  * Interface for TextureClients that can be updated using YCbCr data.
  */
 class TextureClientYCbCr
 {
 public:
@@ -119,16 +151,17 @@ public:
  */
 class TextureClient : public AtomicRefCounted<TextureClient>
 {
 public:
   TextureClient(TextureFlags aFlags = TEXTURE_FLAGS_DEFAULT);
   virtual ~TextureClient();
 
   virtual TextureClientSurface* AsTextureClientSurface() { return nullptr; }
+  virtual TextureClientDrawTarget* AsTextureClientDrawTarget() { return nullptr; }
   virtual TextureClientYCbCr* AsTextureClientYCbCr() { return nullptr; }
 
   /**
    * Locks the shared data, allowing the caller to get access to it.
    *
    * Please always lock/unlock when accessing the shared data.
    * If Lock() returns false, you should not attempt to access the shared data.
    */
@@ -235,17 +268,18 @@ protected:
 
 /**
  * TextureClient that wraps a random access buffer such as a Shmem or raw memory.
  * This class must be inherited to implement the memory allocation and access bits.
  * (see ShmemTextureClient and MemoryTextureClient)
  */
 class BufferTextureClient : public TextureClient
                           , public TextureClientSurface
-                          , TextureClientYCbCr
+                          , public TextureClientYCbCr
+                          , public TextureClientDrawTarget
 {
 public:
   BufferTextureClient(CompositableClient* aCompositable, gfx::SurfaceFormat aFormat,
                       TextureFlags aFlags);
 
   virtual ~BufferTextureClient();
 
   virtual bool IsAllocated() const = 0;
@@ -259,29 +293,36 @@ public:
   // TextureClientSurface
 
   virtual TextureClientSurface* AsTextureClientSurface() MOZ_OVERRIDE { return this; }
 
   virtual bool UpdateSurface(gfxASurface* aSurface) MOZ_OVERRIDE;
 
   virtual already_AddRefed<gfxASurface> GetAsSurface() MOZ_OVERRIDE;
 
-  virtual bool AllocateForSurface(gfx::IntSize aSize) MOZ_OVERRIDE;
+  virtual bool AllocateForSurface(gfx::IntSize aSize,
+                                  TextureAllocationFlags aFlags = ALLOC_DEFAULT) MOZ_OVERRIDE;
+
+  // TextureClientDrawTarget
+
+  virtual TextureClientDrawTarget* AsTextureClientDrawTarget() MOZ_OVERRIDE { return this; }
+
+  virtual TemporaryRef<gfx::DrawTarget> GetAsDrawTarget() MOZ_OVERRIDE;
 
   // TextureClientYCbCr
 
   virtual TextureClientYCbCr* AsTextureClientYCbCr() MOZ_OVERRIDE { return this; }
 
   virtual bool UpdateYCbCr(const PlanarYCbCrData& aData) MOZ_OVERRIDE;
 
   virtual bool AllocateForYCbCr(gfx::IntSize aYSize,
                                 gfx::IntSize aCbCrSize,
                                 StereoMode aStereoMode) MOZ_OVERRIDE;
 
-  gfx::SurfaceFormat GetFormat() const { return mFormat; }
+  virtual gfx::SurfaceFormat GetFormat() const MOZ_OVERRIDE { return mFormat; }
 
   // XXX - Bug 908196 - Make Allocate(uint32_t) and GetBufferSize() protected.
   // these two methods should only be called by methods of BufferTextureClient
   // that are overridden in GrallocTextureClient (which does not implement the
   // two methods below)
   virtual bool Allocate(uint32_t aSize) = 0;
 
   virtual size_t GetBufferSize() const = 0;
--- a/gfx/layers/composite/CompositableHost.cpp
+++ b/gfx/layers/composite/CompositableHost.cpp
@@ -54,30 +54,29 @@ CompositableHost::AddTextureHost(Texture
              "A texture is already present with this ID");
   RefPtr<TextureHost> second = mFirstTexture;
   mFirstTexture = aTexture;
   aTexture->SetNextSibling(second);
   aTexture->SetCompositableBackendSpecificData(GetCompositableBackendSpecificData());
 }
 
 void
-CompositableHost::RemoveTextureHost(uint64_t aTextureID)
+CompositableHost::RemoveTextureHost(TextureHost* aTexture)
 {
-  if (mFirstTexture && mFirstTexture->GetID() == aTextureID) {
-    RefPtr<TextureHost> toRemove = mFirstTexture;
+  uint64_t textureID = aTexture->GetID();
+  if (mFirstTexture && mFirstTexture->GetID() == textureID) {
     mFirstTexture = mFirstTexture->GetNextSibling();
-    toRemove->SetNextSibling(nullptr);
+    aTexture->SetNextSibling(nullptr);
   }
   RefPtr<TextureHost> it = mFirstTexture;
   while (it) {
     if (it->GetNextSibling() &&
-        it->GetNextSibling()->GetID() == aTextureID) {
-      RefPtr<TextureHost> toRemove = it->GetNextSibling();
+        it->GetNextSibling()->GetID() == textureID) {
       it->SetNextSibling(it->GetNextSibling()->GetNextSibling());
-      toRemove->SetNextSibling(nullptr);
+      aTexture->SetNextSibling(nullptr);
     }
     it = it->GetNextSibling();
   }
   if (!mFirstTexture && mBackendData) {
     mBackendData->ClearData();
   }
 }
 
@@ -89,16 +88,25 @@ CompositableHost::GetTextureHost(uint64_
     if (it->GetID() == aTextureID) {
       return it;
     }
     it = it->GetNextSibling();
   }
   return nullptr;
 }
 
+void
+CompositableHost::OnActorDestroy()
+{
+  TextureHost* it = mFirstTexture;
+  while (it) {
+    it->OnActorDestroy();
+    it = it->GetNextSibling();
+  }
+}
 
 void
 CompositableHost::SetCompositor(Compositor* aCompositor)
 {
   mCompositor = aCompositor;
   RefPtr<TextureHost> it = mFirstTexture;
   while (!!it) {
     it->SetCompositor(aCompositor);
@@ -127,17 +135,17 @@ CompositableHost::AddMaskEffect(EffectCh
                                 bool aIs3D)
 {
   RefPtr<TextureSource> source;
   RefPtr<DeprecatedTextureHost> oldHost = GetDeprecatedTextureHost();
   if (oldHost) {
     oldHost->Lock();
     source = oldHost;
   } else {
-    RefPtr<TextureHost> host = GetTextureHost();
+    RefPtr<TextureHost> host = GetAsTextureHost();
     if (host) {
       host->Lock();
       source = host->GetTextureSources();
     }
   }
 
   if (!source) {
     NS_WARNING("Using compositable with no texture host as mask layer");
@@ -154,52 +162,61 @@ CompositableHost::AddMaskEffect(EffectCh
 
 void
 CompositableHost::RemoveMaskEffect()
 {
   RefPtr<DeprecatedTextureHost> oldHost = GetDeprecatedTextureHost();
   if (oldHost) {
     oldHost->Unlock();
   } else {
-    RefPtr<TextureHost> host = GetTextureHost();
+    RefPtr<TextureHost> host = GetAsTextureHost();
     if (host) {
       host->Unlock();
     }
   }
 }
 
 // implemented in TextureHostOGL.cpp
 TemporaryRef<CompositableBackendSpecificData> CreateCompositableBackendSpecificDataOGL();
 
 /* static */ TemporaryRef<CompositableHost>
 CompositableHost::Create(const TextureInfo& aTextureInfo)
 {
   RefPtr<CompositableHost> result;
   switch (aTextureInfo.mCompositableType) {
-  case COMPOSITABLE_IMAGE:
-    result = new ImageHost(aTextureInfo);
+  case BUFFER_IMAGE_SINGLE:
+    result = new DeprecatedImageHostSingle(aTextureInfo);
     break;
   case BUFFER_IMAGE_BUFFERED:
     result = new DeprecatedImageHostBuffered(aTextureInfo);
     break;
-  case BUFFER_IMAGE_SINGLE:
-    result = new DeprecatedImageHostSingle(aTextureInfo);
+  case BUFFER_BRIDGE:
+    MOZ_CRASH("Cannot create an image bridge compositable this way");
+    break;
+  case BUFFER_CONTENT:
+    result = new DeprecatedContentHostSingleBuffered(aTextureInfo);
+    break;
+  case BUFFER_CONTENT_DIRECT:
+    result = new DeprecatedContentHostDoubleBuffered(aTextureInfo);
+    break;
+  case BUFFER_CONTENT_INC:
+    result = new ContentHostIncremental(aTextureInfo);
     break;
   case BUFFER_TILED:
     result = new TiledContentHost(aTextureInfo);
     break;
-  case BUFFER_CONTENT:
+  case COMPOSITABLE_IMAGE:
+    result = new ImageHost(aTextureInfo);
+    break;
+  case COMPOSITABLE_CONTENT_SINGLE:
     result = new ContentHostSingleBuffered(aTextureInfo);
     break;
-  case BUFFER_CONTENT_DIRECT:
+  case COMPOSITABLE_CONTENT_DOUBLE:
     result = new ContentHostDoubleBuffered(aTextureInfo);
     break;
-  case BUFFER_CONTENT_INC:
-    result = new ContentHostIncremental(aTextureInfo);
-    break;
   default:
     MOZ_CRASH("Unknown CompositableType");
   }
   if (result) {
     RefPtr<CompositableBackendSpecificData> data = CreateCompositableBackendSpecificDataOGL();
     result->SetCompositableBackendSpecificData(data);
   }
   return result;
--- a/gfx/layers/composite/CompositableHost.h
+++ b/gfx/layers/composite/CompositableHost.h
@@ -107,17 +107,17 @@ public:
   {
     mBackendData = aBackendData;
   }
 
   /**
    * Our IPDL actor is being destroyed, get rid of any shmem resources now and
    * don't worry about compositing anymore.
    */
-  virtual void OnActorDestroy() = 0;
+  virtual void OnActorDestroy();
 
   // If base class overrides, it should still call the parent implementation
   virtual void SetCompositor(Compositor* aCompositor);
 
   // composite the contents of this buffer host to the compositor's surface
   virtual void Composite(EffectChain& aEffectChain,
                          float aOpacity,
                          const gfx::Matrix4x4& aTransform,
@@ -206,17 +206,17 @@ public:
     MOZ_ASSERT(false, "should be implemented or not used");
   }
 
   virtual DeprecatedTextureHost* GetDeprecatedTextureHost() { return nullptr; }
 
   /**
    * Returns the front buffer.
    */
-  virtual TextureHost* GetTextureHost() { return nullptr; }
+  virtual TextureHost* GetAsTextureHost() { return nullptr; }
 
   virtual LayerRenderState GetRenderState() = 0;
 
   virtual void SetPictureRect(const nsIntRect& aPictureRect)
   {
     MOZ_ASSERT(false, "Should have been overridden");
   }
 
@@ -291,17 +291,23 @@ public:
 
   virtual TemporaryRef<gfx::DataSourceSurface> GetAsSurface() { return nullptr; }
 #endif
 
   virtual void PrintInfo(nsACString& aTo, const char* aPrefix) { }
 
   void AddTextureHost(TextureHost* aTexture);
   virtual void UseTextureHost(TextureHost* aTexture) {}
-  virtual void RemoveTextureHost(uint64_t aTextureID);
+  // If a texture host is flagged for deferred removal, the compositable will
+  // get an option to run any cleanup code early, that is when it would have
+  // been run if the texture host was not marked deferred.
+  // If the compositable does not cleanup the texture host now, it is the
+  // compositable's responsibility to cleanup the texture host before the
+  // texture host dies.
+  virtual void RemoveTextureHost(TextureHost* aTexture);
   TextureHost* GetTextureHost(uint64_t aTextureID);
 
 protected:
   TextureInfo mTextureInfo;
   Compositor* mCompositor;
   Layer* mLayer;
   RefPtr<CompositableBackendSpecificData> mBackendData;
   RefPtr<TextureHost> mFirstTexture;
--- a/gfx/layers/composite/ContentHost.cpp
+++ b/gfx/layers/composite/ContentHost.cpp
@@ -26,54 +26,377 @@ namespace layers {
 
 ContentHostBase::ContentHostBase(const TextureInfo& aTextureInfo)
   : ContentHost(aTextureInfo)
   , mPaintWillResample(false)
   , mInitialised(false)
 {}
 
 ContentHostBase::~ContentHostBase()
+{
+  DestroyTextureHost();
+  DestroyTextureHostOnWhite();
+}
+
+TextureHost*
+ContentHostBase::GetAsTextureHost()
+{
+  return mTextureHost;
+}
+
+void
+ContentHostBase::DestroyTextureHost()
+{
+  // The third clause in the if statement checks that we are in fact done with
+  // this texture. We don't want to prematurely deallocate a texture we might
+  // use again or double deallocate. Deallocation will happen in
+  // RemoveTextureHost.
+  // Note that GetTextureHost is linear in the number of texture hosts, but as
+  // long as that number is small (I expect a maximum of 6 for now) then it
+  // should be ok.
+  if (mTextureHost &&
+      mTextureHost->GetFlags() & TEXTURE_DEALLOCATE_DEFERRED &&
+      !GetTextureHost(mTextureHost->GetID())) {
+    MOZ_ASSERT(!(mTextureHost->GetFlags() & TEXTURE_DEALLOCATE_CLIENT));
+    mTextureHost->DeallocateSharedData();
+  }
+  mTextureHost = nullptr;
+}
+
+void
+ContentHostBase::DestroyTextureHostOnWhite()
+{
+  if (mTextureHostOnWhite &&
+      mTextureHostOnWhite->GetFlags() & TEXTURE_DEALLOCATE_DEFERRED &&
+      !GetTextureHost(mTextureHostOnWhite->GetID())) {
+    MOZ_ASSERT(!(mTextureHostOnWhite->GetFlags() & TEXTURE_DEALLOCATE_CLIENT));
+    mTextureHostOnWhite->DeallocateSharedData();
+  }
+  mTextureHostOnWhite = nullptr;
+}
+
+void
+ContentHostBase::RemoveTextureHost(TextureHost* aTexture)
+{
+  if ((aTexture->GetFlags() & TEXTURE_DEALLOCATE_DEFERRED) &&
+      !(mTextureHost && mTextureHost == aTexture) &&
+      !(mTextureHostOnWhite && mTextureHostOnWhite == aTexture)) {
+    MOZ_ASSERT(!(aTexture->GetFlags() & TEXTURE_DEALLOCATE_CLIENT));
+    aTexture->DeallocateSharedData();
+  }
+
+  CompositableHost::RemoveTextureHost(aTexture);
+}
+
+class MOZ_STACK_CLASS AutoLockTextureHost
+{
+public:
+  AutoLockTextureHost(TextureHost* aHost)
+    : mHost(aHost)
+  {
+    mLockSuccess = mHost ? mHost->Lock() : true;
+  }
+
+  ~AutoLockTextureHost()
+  {
+    if (mHost) {
+      mHost->Unlock();
+    }
+  }
+
+  bool IsValid()
+  {
+    return mLockSuccess;
+  }
+
+private:
+  TextureHost* mHost;
+  bool mLockSuccess;
+};
+
+void
+ContentHostBase::Composite(EffectChain& aEffectChain,
+                           float aOpacity,
+                           const gfx::Matrix4x4& aTransform,
+                           const Filter& aFilter,
+                           const Rect& aClipRect,
+                           const nsIntRegion* aVisibleRegion,
+                           TiledLayerProperties* aLayerProperties)
+{
+  NS_ASSERTION(aVisibleRegion, "Requires a visible region");
+
+  AutoLockTextureHost lock(mTextureHost);
+  AutoLockTextureHost lockOnWhite(mTextureHostOnWhite);
+
+  if (!mTextureHost ||
+      !lock.IsValid() ||
+      !lockOnWhite.IsValid()) {
+    return;
+  }
+
+  RefPtr<NewTextureSource> source = mTextureHost->GetTextureSources();
+  RefPtr<NewTextureSource> sourceOnWhite = mTextureHostOnWhite
+                                             ? mTextureHostOnWhite->GetTextureSources()
+                                             : nullptr;
+  if (!source) {
+    return;
+  }
+  RefPtr<TexturedEffect> effect =
+    CreateTexturedEffect(source, sourceOnWhite, aFilter);
+
+  aEffectChain.mPrimaryEffect = effect;
+
+  nsIntRegion tmpRegion;
+  const nsIntRegion* renderRegion;
+  if (PaintWillResample()) {
+    // If we're resampling, then the texture image will contain exactly the
+    // entire visible region's bounds, and we should draw it all in one quad
+    // to avoid unexpected aliasing.
+    tmpRegion = aVisibleRegion->GetBounds();
+    renderRegion = &tmpRegion;
+  } else {
+    renderRegion = aVisibleRegion;
+  }
+
+  nsIntRegion region(*renderRegion);
+  nsIntPoint origin = GetOriginOffset();
+  // translate into TexImage space, buffer origin might not be at texture (0,0)
+  region.MoveBy(-origin);
+
+  // Figure out the intersecting draw region
+  gfx::IntSize texSize = source->GetSize();
+  nsIntRect textureRect = nsIntRect(0, 0, texSize.width, texSize.height);
+  textureRect.MoveBy(region.GetBounds().TopLeft());
+  nsIntRegion subregion;
+  subregion.And(region, textureRect);
+  if (subregion.IsEmpty()) {
+    // Region is empty, nothing to draw
+    return;
+  }
+
+  nsIntRegion screenRects;
+  nsIntRegion regionRects;
+
+  // Collect texture/screen coordinates for drawing
+  nsIntRegionRectIterator iter(subregion);
+  while (const nsIntRect* iterRect = iter.Next()) {
+    nsIntRect regionRect = *iterRect;
+    nsIntRect screenRect = regionRect;
+    screenRect.MoveBy(origin);
+
+    screenRects.Or(screenRects, screenRect);
+    regionRects.Or(regionRects, regionRect);
+  }
+
+  TileIterator* tileIter = source->AsTileIterator();
+  TileIterator* iterOnWhite = nullptr;
+  if (tileIter) {
+    tileIter->BeginTileIteration();
+  }
+
+  if (mTextureHostOnWhite) {
+    iterOnWhite = sourceOnWhite->AsTileIterator();
+    MOZ_ASSERT(!tileIter || tileIter->GetTileCount() == iterOnWhite->GetTileCount(),
+               "Tile count mismatch on component alpha texture");
+    if (iterOnWhite) {
+      iterOnWhite->BeginTileIteration();
+    }
+  }
+
+  bool usingTiles = (tileIter && tileIter->GetTileCount() > 1);
+  do {
+    if (iterOnWhite) {
+      MOZ_ASSERT(iterOnWhite->GetTileRect() == tileIter->GetTileRect(),
+                 "component alpha textures should be the same size.");
+    }
+
+    nsIntRect texRect = tileIter ? tileIter->GetTileRect()
+                                 : nsIntRect(0, 0,
+                                             texSize.width,
+                                             texSize.height);
+
+    // Draw texture. If we're using tiles, we do repeating manually, as texture
+    // repeat would cause each individual tile to repeat instead of the
+    // compound texture as a whole. This involves drawing at most 4 sections,
+    // 2 for each axis that has texture repeat.
+    for (int y = 0; y < (usingTiles ? 2 : 1); y++) {
+      for (int x = 0; x < (usingTiles ? 2 : 1); x++) {
+        nsIntRect currentTileRect(texRect);
+        currentTileRect.MoveBy(x * texSize.width, y * texSize.height);
+
+        nsIntRegionRectIterator screenIter(screenRects);
+        nsIntRegionRectIterator regionIter(regionRects);
+
+        const nsIntRect* screenRect;
+        const nsIntRect* regionRect;
+        while ((screenRect = screenIter.Next()) &&
+               (regionRect = regionIter.Next())) {
+          nsIntRect tileScreenRect(*screenRect);
+          nsIntRect tileRegionRect(*regionRect);
+
+          // When we're using tiles, find the intersection between the tile
+          // rect and this region rect. Tiling is then handled by the
+          // outer for-loops and modifying the tile rect.
+          if (usingTiles) {
+            tileScreenRect.MoveBy(-origin);
+            tileScreenRect = tileScreenRect.Intersect(currentTileRect);
+            tileScreenRect.MoveBy(origin);
+
+            if (tileScreenRect.IsEmpty())
+              continue;
+
+            tileRegionRect = regionRect->Intersect(currentTileRect);
+            tileRegionRect.MoveBy(-currentTileRect.TopLeft());
+          }
+          gfx::Rect rect(tileScreenRect.x, tileScreenRect.y,
+                         tileScreenRect.width, tileScreenRect.height);
+
+          effect->mTextureCoords = Rect(Float(tileRegionRect.x) / texRect.width,
+                                        Float(tileRegionRect.y) / texRect.height,
+                                        Float(tileRegionRect.width) / texRect.width,
+                                        Float(tileRegionRect.height) / texRect.height);
+          GetCompositor()->DrawQuad(rect, aClipRect, aEffectChain, aOpacity, aTransform);
+          if (usingTiles) {
+            DiagnosticTypes diagnostics = DIAGNOSTIC_CONTENT | DIAGNOSTIC_BIGIMAGE;
+            diagnostics |= iterOnWhite ? DIAGNOSTIC_COMPONENT_ALPHA : 0;
+            GetCompositor()->DrawDiagnostics(diagnostics, rect, aClipRect,
+                                             aTransform);
+          }
+        }
+      }
+    }
+
+    if (iterOnWhite) {
+      iterOnWhite->NextTile();
+    }
+  } while (usingTiles && tileIter->NextTile());
+
+  if (tileIter) {
+    tileIter->EndTileIteration();
+  }
+  if (iterOnWhite) {
+    iterOnWhite->EndTileIteration();
+  }
+
+  DiagnosticTypes diagnostics = DIAGNOSTIC_CONTENT;
+  diagnostics |= iterOnWhite ? DIAGNOSTIC_COMPONENT_ALPHA : 0;
+  GetCompositor()->DrawDiagnostics(diagnostics, *aVisibleRegion, aClipRect, aTransform);
+}
+
+
+void
+ContentHostBase::UseTextureHost(TextureHost* aTexture)
+{
+  if (aTexture->GetFlags() & TEXTURE_ON_WHITE) {
+    DestroyTextureHost();
+    mTextureHostOnWhite = aTexture;
+  } else {
+    DestroyTextureHostOnWhite();
+    mTextureHost = aTexture;
+  }
+}
+
+void
+ContentHostBase::SetCompositor(Compositor* aCompositor)
+{
+  CompositableHost::SetCompositor(aCompositor);
+  if (mTextureHost) {
+    mTextureHost->SetCompositor(aCompositor);
+  }
+  if (mTextureHostOnWhite) {
+    mTextureHostOnWhite->SetCompositor(aCompositor);
+  }
+}
+
+#ifdef MOZ_DUMP_PAINTING
+void
+ContentHostBase::Dump(FILE* aFile,
+                      const char* aPrefix,
+                      bool aDumpHtml)
+{
+  if (!aDumpHtml) {
+    return;
+  }
+  if (!aFile) {
+    aFile = stderr;
+  }
+  fprintf(aFile, "<ul>");
+  if (mTextureHost) {
+    fprintf(aFile, "%s", aPrefix);
+    fprintf(aFile, "<li> <a href=");
+    DumpTextureHost(aFile, mTextureHost);
+    fprintf(aFile, "> Front buffer </a></li> ");
+  }
+  if (mTextureHostOnWhite) {
+    fprintf(aFile, "%s", aPrefix);
+    fprintf(aFile, "<li> <a href=");
+    DumpTextureHost(aFile, mTextureHostOnWhite);
+    fprintf(aFile, "> Front buffer on white </a> </li> ");
+  }
+  fprintf(aFile, "</ul>");
+}
+#endif
+
+void
+ContentHostBase::OnActorDestroy()
+{
+  if (mTextureHost) {
+    mTextureHost->OnActorDestroy();
+  }
+  if (mTextureHostOnWhite) {
+    mTextureHostOnWhite->OnActorDestroy();
+  }
+  CompositableHost::OnActorDestroy();
+}
+
+DeprecatedContentHostBase::DeprecatedContentHostBase(const TextureInfo& aTextureInfo)
+  : ContentHost(aTextureInfo)
+  , mPaintWillResample(false)
+  , mInitialised(false)
+{}
+
+DeprecatedContentHostBase::~DeprecatedContentHostBase()
 {}
 
 DeprecatedTextureHost*
-ContentHostBase::GetDeprecatedTextureHost()
+DeprecatedContentHostBase::GetDeprecatedTextureHost()
 {
   return mDeprecatedTextureHost;
 }
 
 void
-ContentHostBase::DestroyFrontHost()
+DeprecatedContentHostBase::DestroyFrontHost()
 {
   MOZ_ASSERT(!mDeprecatedTextureHost || mDeprecatedTextureHost->GetDeAllocator(),
              "We won't be able to destroy our SurfaceDescriptor");
   MOZ_ASSERT(!mDeprecatedTextureHostOnWhite || mDeprecatedTextureHostOnWhite->GetDeAllocator(),
              "We won't be able to destroy our SurfaceDescriptor");
   mDeprecatedTextureHost = nullptr;
   mDeprecatedTextureHostOnWhite = nullptr;
 }
 
 void
-ContentHostBase::OnActorDestroy()
+DeprecatedContentHostBase::OnActorDestroy()
 {
   if (mDeprecatedTextureHost) {
     mDeprecatedTextureHost->OnActorDestroy();
   }
   if (mDeprecatedTextureHostOnWhite) {
     mDeprecatedTextureHostOnWhite->OnActorDestroy();
   }
   if (mNewFrontHost) {
     mNewFrontHost->OnActorDestroy();
   }
   if (mNewFrontHostOnWhite) {
     mNewFrontHostOnWhite->OnActorDestroy();
   }
 }
 
 void
-ContentHostBase::Composite(EffectChain& aEffectChain,
+DeprecatedContentHostBase::Composite(EffectChain& aEffectChain,
                            float aOpacity,
                            const gfx::Matrix4x4& aTransform,
                            const Filter& aFilter,
                            const Rect& aClipRect,
                            const nsIntRegion* aVisibleRegion,
                            TiledLayerProperties* aLayerProperties)
 {
   NS_ASSERTION(aVisibleRegion, "Requires a visible region");
@@ -229,31 +552,31 @@ ContentHostBase::Composite(EffectChain& 
   }
 
   DiagnosticTypes diagnostics = DIAGNOSTIC_CONTENT;
   diagnostics |= iterOnWhite ? DIAGNOSTIC_COMPONENT_ALPHA : 0;
   GetCompositor()->DrawDiagnostics(diagnostics, *aVisibleRegion, aClipRect, aTransform);
 }
 
 void
-ContentHostBase::SetCompositor(Compositor* aCompositor)
+DeprecatedContentHostBase::SetCompositor(Compositor* aCompositor)
 {
   CompositableHost::SetCompositor(aCompositor);
   if (mDeprecatedTextureHost) {
     mDeprecatedTextureHost->SetCompositor(aCompositor);
   }
   if (mDeprecatedTextureHostOnWhite) {
     mDeprecatedTextureHostOnWhite->SetCompositor(aCompositor);
   }
 }
 
 #ifdef MOZ_DUMP_PAINTING
 
 void
-ContentHostBase::Dump(FILE* aFile,
+DeprecatedContentHostBase::Dump(FILE* aFile,
                       const char* aPrefix,
                       bool aDumpHtml)
 {
   if (!aDumpHtml) {
     return;
   }
   if (!aFile) {
     aFile = stderr;
@@ -271,24 +594,66 @@ ContentHostBase::Dump(FILE* aFile,
     DumpDeprecatedTextureHost(aFile, mDeprecatedTextureHostOnWhite);
     fprintf_stderr(aFile, "> Front buffer on white </a> </li> ");
   }
   fprintf_stderr(aFile, "</ul>");
 }
 
 #endif
 
-ContentHostSingleBuffered::~ContentHostSingleBuffered()
+void
+ContentHostSingleBuffered::UpdateThebes(const ThebesBufferData& aData,
+                                        const nsIntRegion& aUpdated,
+                                        const nsIntRegion& aOldValidRegionBack,
+                                        nsIntRegion* aUpdatedRegionBack)
+{
+  aUpdatedRegionBack->SetEmpty();
+
+  if (!mTextureHost) {
+    mInitialised = false;
+    return;
+  }
+
+  // updated is in screen coordinates. Convert it to buffer coordinates.
+  nsIntRegion destRegion(aUpdated);
+  destRegion.MoveBy(-aData.rect().TopLeft());
+
+  // Correct for rotation
+  destRegion.MoveBy(aData.rotation());
+
+  gfxIntSize size = aData.rect().Size();
+  nsIntRect destBounds = destRegion.GetBounds();
+  destRegion.MoveBy((destBounds.x >= size.width) ? -size.width : 0,
+                    (destBounds.y >= size.height) ? -size.height : 0);
+
+  // There's code to make sure that updated regions don't cross rotation
+  // boundaries, so assert here that this is the case
+  MOZ_ASSERT((destBounds.x % size.width) + destBounds.width <= size.width,
+               "updated region lies across rotation boundaries!");
+  MOZ_ASSERT((destBounds.y % size.height) + destBounds.height <= size.height,
+               "updated region lies across rotation boundaries!");
+
+  mTextureHost->Updated(&destRegion);
+  if (mTextureHostOnWhite) {
+    mTextureHostOnWhite->Updated(&destRegion);
+  }
+  mInitialised = true;
+
+  mBufferRect = aData.rect();
+  mBufferRotation = aData.rotation();
+}
+
+DeprecatedContentHostSingleBuffered::~DeprecatedContentHostSingleBuffered()
 {
   DestroyTextures();
   DestroyFrontHost();
 }
 
 void
-ContentHostSingleBuffered::EnsureDeprecatedTextureHost(TextureIdentifier aTextureId,
+DeprecatedContentHostSingleBuffered::EnsureDeprecatedTextureHost(TextureIdentifier aTextureId,
                                              const SurfaceDescriptor& aSurface,
                                              ISurfaceAllocator* aAllocator,
                                              const TextureInfo& aTextureInfo)
 {
   MOZ_ASSERT(aTextureId == TextureFront ||
              aTextureId == TextureOnWhiteFront);
   RefPtr<DeprecatedTextureHost> *newHost =
     (aTextureId == TextureFront) ? &mNewFrontHost : &mNewFrontHostOnWhite;
@@ -301,30 +666,30 @@ ContentHostSingleBuffered::EnsureDepreca
   (*newHost)->SetBuffer(new SurfaceDescriptor(aSurface), aAllocator);
   Compositor* compositor = GetCompositor();
   if (compositor) {
     (*newHost)->SetCompositor(compositor);
   }
 }
 
 void
-ContentHostSingleBuffered::DestroyTextures()
+DeprecatedContentHostSingleBuffered::DestroyTextures()
 {
   MOZ_ASSERT(!mNewFrontHost || mNewFrontHost->GetDeAllocator(),
              "We won't be able to destroy our SurfaceDescriptor");
   MOZ_ASSERT(!mNewFrontHostOnWhite || mNewFrontHostOnWhite->GetDeAllocator(),
              "We won't be able to destroy our SurfaceDescriptor");
   mNewFrontHost = nullptr;
   mNewFrontHostOnWhite = nullptr;
 
   // don't touch mDeprecatedTextureHost, we might need it for compositing
 }
 
 void
-ContentHostSingleBuffered::UpdateThebes(const ThebesBufferData& aData,
+DeprecatedContentHostSingleBuffered::UpdateThebes(const ThebesBufferData& aData,
                                         const nsIntRegion& aUpdated,
                                         const nsIntRegion& aOldValidRegionBack,
                                         nsIntRegion* aUpdatedRegionBack)
 {
   aUpdatedRegionBack->SetEmpty();
 
   if (!mDeprecatedTextureHost && !mNewFrontHost) {
     mInitialised = false;
@@ -368,24 +733,61 @@ ContentHostSingleBuffered::UpdateThebes(
     mDeprecatedTextureHostOnWhite->Update(*mDeprecatedTextureHostOnWhite->LockSurfaceDescriptor(), &destRegion);
   }
   mInitialised = true;
 
   mBufferRect = aData.rect();
   mBufferRotation = aData.rotation();
 }
 
-ContentHostDoubleBuffered::~ContentHostDoubleBuffered()
+void
+ContentHostDoubleBuffered::UpdateThebes(const ThebesBufferData& aData,
+                                        const nsIntRegion& aUpdated,
+                                        const nsIntRegion& aOldValidRegionBack,
+                                        nsIntRegion* aUpdatedRegionBack)
+{
+  if (!mTextureHost) {
+    mInitialised = false;
+
+    *aUpdatedRegionBack = aUpdated;
+    return;
+  }
+
+  // We don't need to calculate an update region because we assume that if we
+  // are using double buffering then we have render-to-texture and thus no
+  // upload to do.
+  mTextureHost->Updated();
+  if (mTextureHostOnWhite) {
+    mTextureHostOnWhite->Updated();
+  }
+  mInitialised = true;
+
+  mBufferRect = aData.rect();
+  mBufferRotation = aData.rotation();
+
+  *aUpdatedRegionBack = aUpdated;
+
+  // Save the current valid region of our front buffer, because if
+  // we're double buffering, it's going to be the valid region for the
+  // next back buffer sent back to the renderer.
+  //
+  // NB: we rely here on the fact that mValidRegion is initialized to
+  // empty, and that the first time Swap() is called we don't have a
+  // valid front buffer that we're going to return to content.
+  mValidRegionForNextBackBuffer = aOldValidRegionBack;
+}
+
+DeprecatedContentHostDoubleBuffered::~DeprecatedContentHostDoubleBuffered()
 {
   DestroyTextures();
   DestroyFrontHost();
 }
 
 void
-ContentHostDoubleBuffered::EnsureDeprecatedTextureHost(TextureIdentifier aTextureId,
+DeprecatedContentHostDoubleBuffered::EnsureDeprecatedTextureHost(TextureIdentifier aTextureId,
                                              const SurfaceDescriptor& aSurface,
                                              ISurfaceAllocator* aAllocator,
                                              const TextureInfo& aTextureInfo)
 {
   RefPtr<DeprecatedTextureHost> newHost = DeprecatedTextureHost::CreateDeprecatedTextureHost(aSurface.type(),
                                                                aTextureInfo.mDeprecatedTextureHostFlags,
                                                                aTextureInfo.mTextureFlags,
                                                                this);
@@ -415,17 +817,17 @@ ContentHostDoubleBuffered::EnsureDepreca
     mBackHostOnWhite = newHost;
     return;
   }
 
   NS_ERROR("Bad texture identifier");
 }
 
 void
-ContentHostDoubleBuffered::DestroyTextures()
+DeprecatedContentHostDoubleBuffered::DestroyTextures()
 {
   if (mNewFrontHost) {
     MOZ_ASSERT(mNewFrontHost->GetDeAllocator(),
                "We won't be able to destroy our SurfaceDescriptor");
     mNewFrontHost = nullptr;
   }
   if (mNewFrontHostOnWhite) {
     MOZ_ASSERT(mNewFrontHostOnWhite->GetDeAllocator(),
@@ -442,17 +844,17 @@ ContentHostDoubleBuffered::DestroyTextur
                "We won't be able to destroy our SurfaceDescriptor");
     mBackHostOnWhite = nullptr;
   }
 
   // don't touch mDeprecatedTextureHost, we might need it for compositing
 }
 
 void
-ContentHostDoubleBuffered::OnActorDestroy()
+DeprecatedContentHostDoubleBuffered::OnActorDestroy()
 {
   if (mDeprecatedTextureHost) {
     mDeprecatedTextureHost->OnActorDestroy();
   }
   if (mDeprecatedTextureHostOnWhite) {
     mDeprecatedTextureHostOnWhite->OnActorDestroy();
   }
   if (mNewFrontHost) {
@@ -465,17 +867,17 @@ ContentHostDoubleBuffered::OnActorDestro
     mBackHost->OnActorDestroy();
   }
   if (mBackHostOnWhite) {
     mBackHostOnWhite->OnActorDestroy();
   }
 }
 
 void
-ContentHostDoubleBuffered::UpdateThebes(const ThebesBufferData& aData,
+DeprecatedContentHostDoubleBuffered::UpdateThebes(const ThebesBufferData& aData,
                                         const nsIntRegion& aUpdated,
                                         const nsIntRegion& aOldValidRegionBack,
                                         nsIntRegion* aUpdatedRegionBack)
 {
   if (!mDeprecatedTextureHost && !mNewFrontHost) {
     mInitialised = false;
 
     *aUpdatedRegionBack = aUpdated;
@@ -750,20 +1152,41 @@ ContentHostIncremental::TextureUpdateReq
   if (mTextureId == TextureFront) {
     aHost->mDeprecatedTextureHost->Update(mDescriptor, &mUpdated, &offset);
   } else {
     aHost->mDeprecatedTextureHostOnWhite->Update(mDescriptor, &mUpdated, &offset);
   }
 }
 
 void
-ContentHostSingleBuffered::PrintInfo(nsACString& aTo, const char* aPrefix)
+ContentHostBase::PrintInfo(nsACString& aTo, const char* aPrefix)
 {
   aTo += aPrefix;
-  aTo += nsPrintfCString("ContentHostSingleBuffered (0x%p)", this);
+  aTo += nsPrintfCString("ContentHost (0x%p)", this);
+
+  AppendToString(aTo, mBufferRect, " [buffer-rect=", "]");
+  AppendToString(aTo, mBufferRotation, " [buffer-rotation=", "]");
+  if (PaintWillResample()) {
+    aTo += " [paint-will-resample]";
+  }
+
+  nsAutoCString pfx(aPrefix);
+  pfx += "  ";
+
+  if (mTextureHost) {
+    aTo += "\n";
+    mTextureHost->PrintInfo(aTo, pfx.get());
+  }
+}
+
+void
+DeprecatedContentHostSingleBuffered::PrintInfo(nsACString& aTo, const char* aPrefix)
+{
+  aTo += aPrefix;
+  aTo += nsPrintfCString("DeprecatedContentHostSingleBuffered (0x%p)", this);
 
   AppendToString(aTo, mBufferRect, " [buffer-rect=", "]");
   AppendToString(aTo, mBufferRotation, " [buffer-rotation=", "]");
   if (PaintWillResample()) {
     aTo += " [paint-will-resample]";
   }
 
   nsAutoCString pfx(aPrefix);
@@ -771,20 +1194,20 @@ ContentHostSingleBuffered::PrintInfo(nsA
 
   if (mDeprecatedTextureHost) {
     aTo += "\n";
     mDeprecatedTextureHost->PrintInfo(aTo, pfx.get());
   }
 }
 
 void
-ContentHostDoubleBuffered::PrintInfo(nsACString& aTo, const char* aPrefix)
+DeprecatedContentHostDoubleBuffered::PrintInfo(nsACString& aTo, const char* aPrefix)
 {
   aTo += aPrefix;
-  aTo += nsPrintfCString("ContentHostDoubleBuffered (0x%p)", this);
+  aTo += nsPrintfCString("DeprecatedContentHostDoubleBuffered (0x%p)", this);
 
   AppendToString(aTo, mBufferRect, " [buffer-rect=", "]");
   AppendToString(aTo, mBufferRotation, " [buffer-rotation=", "]");
   if (PaintWillResample()) {
     aTo += " [paint-will-resample]";
   }
 
   nsAutoCString prefix(aPrefix);
@@ -798,21 +1221,21 @@ ContentHostDoubleBuffered::PrintInfo(nsA
   if (mBackHost) {
     aTo += "\n";
     mBackHost->PrintInfo(aTo, prefix.get());
   }
 }
 
 #ifdef MOZ_DUMP_PAINTING
 void
-ContentHostDoubleBuffered::Dump(FILE* aFile,
+DeprecatedContentHostDoubleBuffered::Dump(FILE* aFile,
                                 const char* aPrefix,
                                 bool aDumpHtml)
 {
-  ContentHostBase::Dump(aFile, aPrefix, aDumpHtml);
+  DeprecatedContentHostBase::Dump(aFile, aPrefix, aDumpHtml);
   if (!aDumpHtml) {
     return;
   }
   if (!aFile) {
     aFile = stderr;
   }
   fprintf_stderr(aFile, "<ul>");
   if (mBackHost) {
@@ -829,28 +1252,54 @@ ContentHostDoubleBuffered::Dump(FILE* aF
   }
   fprintf_stderr(aFile, "</ul>");
 }
 #endif
 
 LayerRenderState
 ContentHostBase::GetRenderState()
 {
+  if (!mTextureHost) {
+    return LayerRenderState();
+  }
+
+  LayerRenderState result = mTextureHost->GetRenderState();
+
+  if (mBufferRotation != nsIntPoint()) {
+    result.mFlags |= LAYER_RENDER_STATE_BUFFER_ROTATION;
+  }
+  result.SetOffset(GetOriginOffset());
+  return result;
+}
+
+LayerRenderState
+DeprecatedContentHostBase::GetRenderState()
+{
   LayerRenderState result = mDeprecatedTextureHost->GetRenderState();
 
   if (mBufferRotation != nsIntPoint()) {
     result.mFlags |= LAYER_RENDER_STATE_BUFFER_ROTATION;
   }
   result.SetOffset(GetOriginOffset());
   return result;
 }
 
 #ifdef MOZ_DUMP_PAINTING
 TemporaryRef<gfx::DataSourceSurface>
 ContentHostBase::GetAsSurface()
 {
+  if (!mTextureHost) {
+    return nullptr;
+  }
+
+  return mTextureHost->GetAsSurface();
+}
+
+TemporaryRef<gfx::DataSourceSurface>
+DeprecatedContentHostBase::GetAsSurface()
+{
   return mDeprecatedTextureHost->GetAsSurface();
 }
 #endif
 
 
 } // namespace
 } // namespace
--- a/gfx/layers/composite/ContentHost.h
+++ b/gfx/layers/composite/ContentHost.h
@@ -84,17 +84,77 @@ protected:
  */
 class ContentHostBase : public ContentHost
 {
 public:
   typedef RotatedContentBuffer::ContentType ContentType;
   typedef RotatedContentBuffer::PaintState PaintState;
 
   ContentHostBase(const TextureInfo& aTextureInfo);
-  ~ContentHostBase();
+  virtual ~ContentHostBase();
+
+  virtual void Composite(EffectChain& aEffectChain,
+                         float aOpacity,
+                         const gfx::Matrix4x4& aTransform,
+                         const gfx::Filter& aFilter,
+                         const gfx::Rect& aClipRect,
+                         const nsIntRegion* aVisibleRegion = nullptr,
+                         TiledLayerProperties* aLayerProperties = nullptr);
+
+  virtual LayerRenderState GetRenderState() MOZ_OVERRIDE;
+
+  virtual void SetCompositor(Compositor* aCompositor) MOZ_OVERRIDE;
+
+#ifdef MOZ_DUMP_PAINTING
+  virtual TemporaryRef<gfx::DataSourceSurface> GetAsSurface() MOZ_OVERRIDE;
+
+  virtual void Dump(FILE* aFile=nullptr,
+                    const char* aPrefix="",
+                    bool aDumpHtml=false) MOZ_OVERRIDE;
+#endif
+
+  virtual void PrintInfo(nsACString& aTo, const char* aPrefix) MOZ_OVERRIDE;
+
+  virtual TextureHost* GetAsTextureHost() MOZ_OVERRIDE;
+
+  virtual void UseTextureHost(TextureHost* aTexture) MOZ_OVERRIDE;
+
+  virtual void RemoveTextureHost(TextureHost* aTexture) MOZ_OVERRIDE;
+
+  virtual void SetPaintWillResample(bool aResample) { mPaintWillResample = aResample; }
+
+  virtual void OnActorDestroy() MOZ_OVERRIDE;
+
+protected:
+  virtual nsIntPoint GetOriginOffset()
+  {
+    return mBufferRect.TopLeft() - mBufferRotation;
+  }
+
+  bool PaintWillResample() { return mPaintWillResample; }
+
+  // These must be called before forgetting mTextureHost or mTextureHostOnWhite
+  void DestroyTextureHost();
+  void DestroyTextureHostOnWhite();
+
+  nsIntRect mBufferRect;
+  nsIntPoint mBufferRotation;
+  RefPtr<TextureHost> mTextureHost;
+  RefPtr<TextureHost> mTextureHostOnWhite;
+  bool mPaintWillResample;
+  bool mInitialised;
+};
+class DeprecatedContentHostBase : public ContentHost
+{
+public:
+  typedef RotatedContentBuffer::ContentType ContentType;
+  typedef RotatedContentBuffer::PaintState PaintState;
+
+  DeprecatedContentHostBase(const TextureInfo& aTextureInfo);
+  ~DeprecatedContentHostBase();
 
   virtual void Composite(EffectChain& aEffectChain,
                          float aOpacity,
                          const gfx::Matrix4x4& aTransform,
                          const gfx::Filter& aFilter,
                          const gfx::Rect& aClipRect,
                          const nsIntRegion* aVisibleRegion = nullptr,
                          TiledLayerProperties* aLayerProperties = nullptr);
@@ -148,26 +208,48 @@ protected:
   // here and move it to mDeprecatedTextureHost once we do the first buffer swap.
   RefPtr<DeprecatedTextureHost> mNewFrontHost;
   RefPtr<DeprecatedTextureHost> mNewFrontHostOnWhite;
   bool mPaintWillResample;
   bool mInitialised;
 };
 
 /**
- * Double buffering is implemented by swapping the front and back DeprecatedTextureHosts.
+ * Double buffering is implemented by swapping the front and back TextureHosts.
+ * We assume that whenever we use double buffering, then we have
+ * render-to-texture and thus no texture upload to do.
  */
 class ContentHostDoubleBuffered : public ContentHostBase
 {
 public:
   ContentHostDoubleBuffered(const TextureInfo& aTextureInfo)
     : ContentHostBase(aTextureInfo)
   {}
 
-  ~ContentHostDoubleBuffered();
+  virtual ~ContentHostDoubleBuffered() {}
+
+  virtual CompositableType GetType() { return COMPOSITABLE_CONTENT_DOUBLE; }
+
+  virtual void UpdateThebes(const ThebesBufferData& aData,
+                            const nsIntRegion& aUpdated,
+                            const nsIntRegion& aOldValidRegionBack,
+                            nsIntRegion* aUpdatedRegionBack);
+
+protected:
+  nsIntRegion mValidRegionForNextBackBuffer;
+};
+
+class DeprecatedContentHostDoubleBuffered : public DeprecatedContentHostBase
+{
+public:
+  DeprecatedContentHostDoubleBuffered(const TextureInfo& aTextureInfo)
+    : DeprecatedContentHostBase(aTextureInfo)
+  {}
+
+  ~DeprecatedContentHostDoubleBuffered();
 
   virtual CompositableType GetType() { return BUFFER_CONTENT_DIRECT; }
 
   virtual void UpdateThebes(const ThebesBufferData& aData,
                             const nsIntRegion& aUpdated,
                             const nsIntRegion& aOldValidRegionBack,
                             nsIntRegion* aUpdatedRegionBack);
 
@@ -200,17 +282,33 @@ protected:
  * DeprecatedTextureHost in the layers transaction (i.e., in UpdateThebes).
  */
 class ContentHostSingleBuffered : public ContentHostBase
 {
 public:
   ContentHostSingleBuffered(const TextureInfo& aTextureInfo)
     : ContentHostBase(aTextureInfo)
   {}
-  virtual ~ContentHostSingleBuffered();
+  virtual ~ContentHostSingleBuffered() {}
+
+  virtual CompositableType GetType() { return COMPOSITABLE_CONTENT_SINGLE; }
+
+  virtual void UpdateThebes(const ThebesBufferData& aData,
+                            const nsIntRegion& aUpdated,
+                            const nsIntRegion& aOldValidRegionBack,
+                            nsIntRegion* aUpdatedRegionBack);
+};
+
+class DeprecatedContentHostSingleBuffered : public DeprecatedContentHostBase
+{
+public:
+  DeprecatedContentHostSingleBuffered(const TextureInfo& aTextureInfo)
+    : DeprecatedContentHostBase(aTextureInfo)
+  {}
+  virtual ~DeprecatedContentHostSingleBuffered();
 
   virtual CompositableType GetType() { return BUFFER_CONTENT; }
 
   virtual void UpdateThebes(const ThebesBufferData& aData,
                             const nsIntRegion& aUpdated,
                             const nsIntRegion& aOldValidRegionBack,
                             nsIntRegion* aUpdatedRegionBack);
 
@@ -228,21 +326,21 @@ public:
  * surfaces that only cover the changed pixels during an update.
  *
  * Takes ownership of the passed in update surfaces, and must
  * free them once texture upload is complete.
  *
  * Delays texture uploads until the next composite to
  * avoid blocking the main thread.
  */
-class ContentHostIncremental : public ContentHostBase
+class ContentHostIncremental : public DeprecatedContentHostBase
 {
 public:
   ContentHostIncremental(const TextureInfo& aTextureInfo)
-    : ContentHostBase(aTextureInfo)
+    : DeprecatedContentHostBase(aTextureInfo)
     , mDeAllocator(nullptr)
   {}
 
   virtual CompositableType GetType() { return BUFFER_CONTENT; }
 
   virtual void EnsureDeprecatedTextureHostIncremental(ISurfaceAllocator* aAllocator,
                                             const TextureInfo& aTextureInfo,
                                             const nsIntRect& aBufferRect) MOZ_OVERRIDE;
@@ -274,17 +372,17 @@ public:
                          const gfx::Matrix4x4& aTransform,
                          const gfx::Filter& aFilter,
                          const gfx::Rect& aClipRect,
                          const nsIntRegion* aVisibleRegion = nullptr,
                          TiledLayerProperties* aLayerProperties = nullptr)
   {
     ProcessTextureUpdates();
 
-    ContentHostBase::Composite(aEffectChain, aOpacity,
+    DeprecatedContentHostBase::Composite(aEffectChain, aOpacity,
                                aTransform, aFilter,
                                aClipRect, aVisibleRegion,
                                aLayerProperties);
   }
 
   virtual void DestroyTextures()
   {
     mDeprecatedTextureHost = nullptr;
--- a/gfx/layers/composite/ImageHost.cpp
+++ b/gfx/layers/composite/ImageHost.cpp
@@ -37,26 +37,26 @@ ImageHost::~ImageHost() {}
 
 void
 ImageHost::UseTextureHost(TextureHost* aTexture)
 {
   mFrontBuffer = aTexture;
 }
 
 void
-ImageHost::RemoveTextureHost(uint64_t aTextureID)
+ImageHost::RemoveTextureHost(TextureHost* aTexture)
 {
-  CompositableHost::RemoveTextureHost(aTextureID);
-  if (mFrontBuffer && mFrontBuffer->GetID() == aTextureID) {
+  CompositableHost::RemoveTextureHost(aTexture);
+  if (mFrontBuffer && mFrontBuffer->GetID() == aTexture->GetID()) {
     mFrontBuffer = nullptr;
   }
 }
 
 TextureHost*
-ImageHost::GetTextureHost()
+ImageHost::GetAsTextureHost()
 {
   return mFrontBuffer;
 }
 
 void
 ImageHost::Composite(EffectChain& aEffectChain,
                      float aOpacity,
                      const gfx::Matrix4x4& aTransform,
--- a/gfx/layers/composite/ImageHost.h
+++ b/gfx/layers/composite/ImageHost.h
@@ -50,19 +50,19 @@ public:
                          const gfx::Matrix4x4& aTransform,
                          const gfx::Filter& aFilter,
                          const gfx::Rect& aClipRect,
                          const nsIntRegion* aVisibleRegion = nullptr,
                          TiledLayerProperties* aLayerProperties = nullptr) MOZ_OVERRIDE;
 
   virtual void UseTextureHost(TextureHost* aTexture) MOZ_OVERRIDE;
 
-  virtual void RemoveTextureHost(uint64_t aTextureID) MOZ_OVERRIDE;
+  virtual void RemoveTextureHost(TextureHost* aTexture) MOZ_OVERRIDE;
 
-  virtual TextureHost* GetTextureHost() MOZ_OVERRIDE;
+  virtual TextureHost* GetAsTextureHost() MOZ_OVERRIDE;
 
   virtual void SetPictureRect(const nsIntRect& aPictureRect) MOZ_OVERRIDE
   {
     mPictureRect = aPictureRect;
     mHasPictureRect = true;
   }
 
   virtual LayerRenderState GetRenderState() MOZ_OVERRIDE;
--- a/gfx/layers/composite/ImageLayerComposite.cpp
+++ b/gfx/layers/composite/ImageLayerComposite.cpp
@@ -116,20 +116,20 @@ void
 ImageLayerComposite::ComputeEffectiveTransforms(const gfx3DMatrix& aTransformToSurface)
 {
   gfx3DMatrix local = GetLocalTransform();
 
   // Snap image edges to pixel boundaries
   gfxRect sourceRect(0, 0, 0, 0);
   if (mImageHost &&
       mImageHost->IsAttached() &&
-      (mImageHost->GetDeprecatedTextureHost() || mImageHost->GetTextureHost())) {
+      (mImageHost->GetDeprecatedTextureHost() || mImageHost->GetAsTextureHost())) {
     IntSize size =
-      mImageHost->GetTextureHost() ? mImageHost->GetTextureHost()->GetSize()
-                                   : mImageHost->GetDeprecatedTextureHost()->GetSize();
+      mImageHost->GetAsTextureHost() ? mImageHost->GetAsTextureHost()->GetSize()
+                                     : mImageHost->GetDeprecatedTextureHost()->GetSize();
     sourceRect.SizeTo(size.width, size.height);
     if (mScaleMode != SCALE_NONE &&
         sourceRect.width != 0.0 && sourceRect.height != 0.0) {
       NS_ASSERTION(mScaleMode == SCALE_STRETCH,
                    "No other scalemodes than stretch and none supported yet.");
       local.Scale(mScaleToSize.width / sourceRect.width,
                   mScaleToSize.height / sourceRect.height, 1.0);
     }
--- a/gfx/layers/composite/TextureHost.cpp
+++ b/gfx/layers/composite/TextureHost.cpp
@@ -508,16 +508,17 @@ ShmemTextureHost::~ShmemTextureHost()
 
 void
 ShmemTextureHost::DeallocateSharedData()
 {
   if (mShmem) {
     MOZ_ASSERT(mDeallocator,
                "Shared memory would leak without a ISurfaceAllocator");
     mDeallocator->DeallocShmem(*mShmem);
+    mShmem = nullptr;
   }
 }
 
 void
 ShmemTextureHost::OnActorDestroy()
 {
   delete mShmem;
   mShmem = nullptr;
@@ -546,16 +547,17 @@ MemoryTextureHost::~MemoryTextureHost()
 
 void
 MemoryTextureHost::DeallocateSharedData()
 {
   if (mBuffer) {
     GfxMemoryImageReporter::WillFree(mBuffer);
   }
   delete[] mBuffer;
+  mBuffer = nullptr;
 }
 
 uint8_t* MemoryTextureHost::GetBuffer()
 {
   return mBuffer;
 }
 
 } // namespace
--- a/gfx/layers/composite/TextureHost.h
+++ b/gfx/layers/composite/TextureHost.h
@@ -303,17 +303,17 @@ public:
    * Is called before compositing if the shared data has changed since last
    * composition.
    * This method should be overload in cases like when we need to do a texture
    * upload for example.
    *
    * @param aRegion The region that has been changed, if nil, it means that the
    * entire surface should be updated.
    */
-  virtual void Updated(const nsIntRegion* aRegion) {}
+  virtual void Updated(const nsIntRegion* aRegion = nullptr) {}
 
   /**
    * Sets this TextureHost's compositor.
    * A TextureHost can change compositor on certain occasions, in particular if
    * it belongs to an async Compositable.
    * aCompositor can be null, in which case the TextureHost must cleanup  all
    * of it's device textures.
    */
@@ -417,17 +417,17 @@ public:
   BufferTextureHost(uint64_t aID,
                     gfx::SurfaceFormat aFormat,
                     TextureFlags aFlags);
 
   ~BufferTextureHost();
 
   virtual uint8_t* GetBuffer() = 0;
 
-  virtual void Updated(const nsIntRegion* aRegion) MOZ_OVERRIDE;
+  virtual void Updated(const nsIntRegion* aRegion = nullptr) MOZ_OVERRIDE;
 
   virtual bool Lock() MOZ_OVERRIDE;
 
   virtual void Unlock() MOZ_OVERRIDE;
 
   virtual NewTextureSource* GetTextureSources() MOZ_OVERRIDE;
 
   virtual void DeallocateDeviceData() MOZ_OVERRIDE;
--- a/gfx/layers/ipc/CompositableTransactionParent.cpp
+++ b/gfx/layers/ipc/CompositableTransactionParent.cpp
@@ -93,17 +93,17 @@ CompositableParentManager::ReceiveCompos
                                                  op.textureInfo(),
                                                  op.bufferRect());
       break;
     }
     case CompositableOperation::TOpDestroyThebesBuffer: {
       MOZ_LAYERS_LOG(("[ParentSide] Created double buffer"));
       const OpDestroyThebesBuffer& op = aEdit.get_OpDestroyThebesBuffer();
       CompositableParent* compositableParent = static_cast<CompositableParent*>(op.compositableParent());
-      ContentHostBase* content = static_cast<ContentHostBase*>(compositableParent->GetCompositableHost());
+      DeprecatedContentHostBase* content = static_cast<DeprecatedContentHostBase*>(compositableParent->GetCompositableHost());
       content->DestroyTextures();
 
       break;
     }
     case CompositableOperation::TOpPaintTexture: {
       MOZ_LAYERS_LOG(("[ParentSide] Paint Texture X"));
       const OpPaintTexture& op = aEdit.get_OpPaintTexture();
 
@@ -266,21 +266,22 @@ CompositableParentManager::ReceiveCompos
       }
       CompositableHost* compositable = AsCompositable(op);
 
       RefPtr<TextureHost> texture = compositable->GetTextureHost(op.textureID());
       MOZ_ASSERT(texture);
 
       TextureFlags flags = texture->GetFlags();
 
-      if (!(flags & TEXTURE_DEALLOCATE_CLIENT)) {
+      if (!(flags & TEXTURE_DEALLOCATE_CLIENT) &&
+          !(flags & TEXTURE_DEALLOCATE_DEFERRED)) {
         texture->DeallocateSharedData();
       }
 
-      compositable->RemoveTextureHost(op.textureID());
+      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()));
       }
--- a/gfx/layers/opengl/GrallocTextureClient.cpp
+++ b/gfx/layers/opengl/GrallocTextureClient.cpp
@@ -181,17 +181,18 @@ uint8_t*
 GrallocTextureClientOGL::GetBuffer() const
 {
   MOZ_ASSERT(IsValid());
   NS_WARN_IF_FALSE(mMappedBuffer, "Trying to get a gralloc buffer without getting the lock?");
   return mMappedBuffer;
 }
 
 bool
-GrallocTextureClientOGL::AllocateForSurface(gfx::IntSize aSize)
+GrallocTextureClientOGL::AllocateForSurface(gfx::IntSize aSize,
+                                            TextureAllocationFlags)
 {
   MOZ_ASSERT(IsValid());
   MOZ_ASSERT(mCompositable);
   ISurfaceAllocator* allocator = mCompositable->GetForwarder();
 
   uint32_t format;
   uint32_t usage = android::GraphicBuffer::USAGE_SW_READ_OFTEN;
   bool swapRB = GetFlags() & TEXTURE_RB_SWAPPED;
--- a/gfx/layers/opengl/GrallocTextureClient.h
+++ b/gfx/layers/opengl/GrallocTextureClient.h
@@ -75,17 +75,18 @@ public:
    */
   void SetGrallocOpenFlags(uint32_t aFlags)
   {
     mGrallocFlags = aFlags;
   }
 
   virtual uint8_t* GetBuffer() const MOZ_OVERRIDE;
 
-  virtual bool AllocateForSurface(gfx::IntSize aSize) MOZ_OVERRIDE;
+  virtual bool AllocateForSurface(gfx::IntSize aSize,
+                                  TextureAllocationFlags aFlags = ALLOC_DEFAULT) MOZ_OVERRIDE;
 
   virtual bool AllocateForYCbCr(gfx::IntSize aYSize,
                                 gfx::IntSize aCbCrSize,
                                 StereoMode aStereoMode) MOZ_OVERRIDE;
 
   bool AllocateGralloc(gfx::IntSize aYSize, uint32_t aAndroidFormat, uint32_t aUsage);
 
   virtual bool Allocate(uint32_t aSize) MOZ_OVERRIDE;