Bug 893301. Rollup patch - new textures content. r=nical,nrc
authorNicholas Cameron <ncameron@mozilla.com>
Fri, 06 Dec 2013 07:39:22 +1300
changeset 168210 0e796e3648153bde5b56d2c745c45fbfc94617e6
parent 168209 c14453ff87648f20be5b3805695d16257fd08212
child 168211 10932f3a0ba0933ffc45cd9c86fa6aa3eb1a8835
push idunknown
push userunknown
push dateunknown
reviewersnical, nrc
bugs893301
milestone28.0a1
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;