Bug 858914 - New texture classes + OGL backend (preffed off). r=bas, nrc
authorNicolas Silva <nical@mozilla.com>
Tue, 30 Jul 2013 11:59:51 +0200
changeset 140511 313445f455f38bd21ad7a31cd4e301dac8e61c3e
parent 140510 91837985ae91d394ea96289bb43878161067bd69
child 140512 cb3f726cf350722514d5d035938f2e424ad64836
push id1970
push userryanvm@gmail.com
push dateTue, 30 Jul 2013 17:12:32 +0000
treeherderfx-team@72240998c094 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbas, nrc
bugs858914
milestone25.0a1
Bug 858914 - New texture classes + OGL backend (preffed off). r=bas, nrc
content/media/plugins/MediaPluginReader.cpp
gfx/gl/GLTextureImage.cpp
gfx/gl/GLTextureImage.h
gfx/layers/Compositor.h
gfx/layers/CompositorTypes.h
gfx/layers/Effects.h
gfx/layers/ImageContainer.cpp
gfx/layers/ImageContainer.h
gfx/layers/ImageDataSerializer.cpp
gfx/layers/ImageDataSerializer.h
gfx/layers/LayersLogging.cpp
gfx/layers/YCbCrImageDataSerializer.cpp
gfx/layers/YCbCrImageDataSerializer.h
gfx/layers/basic/BasicCompositor.h
gfx/layers/client/ClientCanvasLayer.cpp
gfx/layers/client/ClientCanvasLayer.h
gfx/layers/client/ClientImageLayer.cpp
gfx/layers/client/ClientLayerManager.cpp
gfx/layers/client/ClientThebesLayer.h
gfx/layers/client/CompositableClient.cpp
gfx/layers/client/CompositableClient.h
gfx/layers/client/ContentClient.cpp
gfx/layers/client/ContentClient.h
gfx/layers/client/ImageClient.cpp
gfx/layers/client/ImageClient.h
gfx/layers/client/TextureClient.cpp
gfx/layers/client/TextureClient.h
gfx/layers/composite/CanvasLayerComposite.cpp
gfx/layers/composite/CanvasLayerComposite.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/ImageLayerComposite.h
gfx/layers/composite/TextureHost.cpp
gfx/layers/composite/TextureHost.h
gfx/layers/composite/TiledContentHost.h
gfx/layers/d3d11/CompositorD3D11.h
gfx/layers/d3d11/TextureD3D11.h
gfx/layers/ipc/CompositableForwarder.h
gfx/layers/ipc/CompositableTransactionParent.cpp
gfx/layers/ipc/CompositableTransactionParent.h
gfx/layers/ipc/CompositorParent.cpp
gfx/layers/ipc/CompositorParent.h
gfx/layers/ipc/ISurfaceAllocator.cpp
gfx/layers/ipc/ImageBridgeChild.cpp
gfx/layers/ipc/ImageBridgeChild.h
gfx/layers/ipc/LayerTransaction.ipdlh
gfx/layers/ipc/LayerTransactionParent.cpp
gfx/layers/ipc/LayersSurfaces.ipdlh
gfx/layers/ipc/ShadowLayers.cpp
gfx/layers/ipc/ShadowLayers.h
gfx/layers/ipc/SharedPlanarYCbCrImage.cpp
gfx/layers/ipc/SharedPlanarYCbCrImage.h
gfx/layers/ipc/SharedRGBImage.cpp
gfx/layers/ipc/SharedRGBImage.h
gfx/layers/moz.build
gfx/layers/opengl/CompositingRenderTargetOGL.h
gfx/layers/opengl/CompositorOGL.cpp
gfx/layers/opengl/CompositorOGL.h
gfx/layers/opengl/TextureClientOGL.cpp
gfx/layers/opengl/TextureClientOGL.h
gfx/layers/opengl/TextureHostOGL.cpp
gfx/layers/opengl/TextureHostOGL.h
gfx/thebes/gfx2DGlue.h
gfx/thebes/gfxPlatform.cpp
gfx/thebes/gfxPlatform.h
ipc/glue/IPCMessageUtils.h
modules/libpref/src/init/all.js
--- a/content/media/plugins/MediaPluginReader.cpp
+++ b/content/media/plugins/MediaPluginReader.cpp
@@ -355,24 +355,24 @@ void *
 MediaPluginReader::ImageBufferCallback::operator()(size_t aWidth, size_t aHeight,
                                                      MPAPI::ColorFormat aColorFormat)
 {
   if (!mImageContainer) {
     NS_WARNING("No image container to construct an image");
     return nullptr;
   }
 
-  nsRefPtr<mozilla::layers::DeprecatedSharedRGBImage> rgbImage;
+  nsRefPtr<Image> rgbImage;
   switch(aColorFormat) {
     case MPAPI::RGB565:
-      rgbImage = mozilla::layers::DeprecatedSharedRGBImage::Create(mImageContainer,
-                                                         nsIntSize(aWidth, aHeight),
-                                                         gfxASurface::ImageFormatRGB16_565);
+      rgbImage = mozilla::layers::CreateSharedRGBImage(mImageContainer,
+                                                       nsIntSize(aWidth, aHeight),
+                                                       gfxASurface::ImageFormatRGB16_565);
       mImage = rgbImage;
-      return rgbImage->GetBuffer();
+      return rgbImage->AsSharedImage()->GetBuffer();
     case MPAPI::YCbCr:
     default:
       NS_NOTREACHED("Color format not supported");
       return nullptr;
   }
 }
 
 already_AddRefed<Image>
--- a/gfx/gl/GLTextureImage.cpp
+++ b/gfx/gl/GLTextureImage.cpp
@@ -3,30 +3,50 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "GLTextureImage.h"
 #include "GLContext.h"
 #include "gfxContext.h"
 #include "gfxPlatform.h"
 #include "gfxUtils.h"
+#include "gfx2DGlue.h"
 
 namespace mozilla {
 namespace gl {
 
 already_AddRefed<TextureImage>
 TextureImage::Create(GLContext* gl,
                      const nsIntSize& size,
                      TextureImage::ContentType contentType,
                      GLenum wrapMode,
                      TextureImage::Flags flags)
 {
     return gl->CreateTextureImage(size, contentType, wrapMode, flags);
 }
 
+bool
+TextureImage::UpdateFromDataSource(gfx::DataSourceSurface *aSurface,
+                                   const nsIntRegion* aDestRegion,
+                                   const gfx::IntPoint* aSrcPoint)
+{
+    nsIntRegion destRegion = aDestRegion ? *aDestRegion
+                                         : nsIntRect(0, 0,
+                                                     aSurface->GetSize().width,
+                                                     aSurface->GetSize().height);
+    nsIntPoint thebesSrcPoint = aSrcPoint ? nsIntPoint(aSrcPoint->x, aSrcPoint->y)
+                                          : nsIntPoint(0, 0);
+    RefPtr<gfxASurface> thebesSurf
+        = new gfxImageSurface(aSurface->GetData(),
+                              ThebesIntSize(aSurface->GetSize()),
+                              aSurface->Stride(),
+                              SurfaceFormatToImageFormat(aSurface->GetFormat()));
+    return DirectUpdate(thebesSurf, destRegion, thebesSrcPoint);
+}
+
 BasicTextureImage::~BasicTextureImage()
 {
     GLContext *ctx = mGLContext;
     if (ctx->IsDestroyed() || !ctx->IsOwningThreadCurrent()) {
         ctx = ctx->GetSharedContext();
     }
 
     // If we have a context, then we need to delete the texture;
--- a/gfx/gl/GLTextureImage.h
+++ b/gfx/gl/GLTextureImage.h
@@ -7,16 +7,23 @@
 #define GLTEXTUREIMAGE_H_
 
 #include "nsAutoPtr.h"
 #include "nsRegion.h"
 #include "nsTArray.h"
 #include "gfxASurface.h"
 #include "GLContextTypes.h"
 #include "gfxPattern.h"
+#include "mozilla/gfx/Rect.h"
+
+namespace mozilla {
+namespace gfx {
+class DataSourceSurface;
+}
+}
 
 namespace mozilla {
 namespace gl {
 class GLContext;
 
 /**
  * A TextureImage encapsulates a surface that can be drawn to by a
  * Thebes gfxContext and (hopefully efficiently!) synchronized to a
@@ -159,16 +166,20 @@ public:
     virtual void MarkValid() {}
 
     /**
      * aSurf - the source surface to update from
      * aRegion - the region in this image to update
      * aFrom - offset in the source to update from
      */
     virtual bool DirectUpdate(gfxASurface *aSurf, const nsIntRegion& aRegion, const nsIntPoint& aFrom = nsIntPoint(0,0)) = 0;
+    // Moz2D equivalent
+    bool UpdateFromDataSource(gfx::DataSourceSurface *aSurf,
+                              const nsIntRegion* aDstRegion = nullptr,
+                              const gfx::IntPoint* aSrcOffset = nullptr);
 
     virtual void BindTexture(GLenum aTextureUnit) = 0;
     virtual void ReleaseTexture() {}
 
     void BindTextureAndApplyFilter(GLenum aTextureUnit) {
         BindTexture(aTextureUnit);
         ApplyFilter();
     }
--- a/gfx/layers/Compositor.h
+++ b/gfx/layers/Compositor.h
@@ -5,19 +5,18 @@
 
 #ifndef MOZILLA_GFX_COMPOSITOR_H
 #define MOZILLA_GFX_COMPOSITOR_H
 
 #include "mozilla/gfx/Rect.h"
 #include "mozilla/gfx/Matrix.h"
 #include "gfxMatrix.h"
 #include "Layers.h"
-#include "mozilla/layers/TextureHost.h"
 #include "mozilla/RefPtr.h"
-
+#include "mozilla/layers/CompositorTypes.h"
 
 /**
  * Different elements of a web pages are rendered into separate "layers" before
  * they are flattened into the final image that is brought to the screen.
  * See Layers.h for more informations about layers and why we use retained
  * structures.
  * Most of the documentation for layers is directly in the source code in the
  * form of doc comments. An overview can also be found in the the wiki:
@@ -108,16 +107,19 @@ class DrawTarget;
 }
 
 namespace layers {
 
 struct Effect;
 struct EffectChain;
 class Image;
 class ISurfaceAllocator;
+class NewTextureSource;
+class DataTextureSource;
+class CompositingRenderTarget;
 
 enum SurfaceInitMode
 {
   INIT_MODE_NONE,
   INIT_MODE_CLEAR,
   INIT_MODE_COPY
 };
 
@@ -174,20 +176,30 @@ public:
   {
     MOZ_COUNT_CTOR(Compositor);
   }
   virtual ~Compositor()
   {
     MOZ_COUNT_DTOR(Compositor);
   }
 
+  virtual TemporaryRef<DataTextureSource> CreateDataTextureSource(TextureFlags aFlags = 0) = 0;
   virtual bool Initialize() = 0;
   virtual void Destroy() = 0;
 
   /**
+   * Return true if the effect type is supported.
+   *
+   * By default Compositor implementations should support all effects but in
+   * some rare cases it is not possible to support an effect efficiently.
+   * This is the case for BasicCompositor with EffectYCbCr.
+   */
+  virtual bool SupportsEffect(EffectTypes aEffect) { return true; }
+
+  /**
    * Request a texture host identifier that may be used for creating textures
    * across process or thread boundaries that are compatible with this
    * compositor.
    */
   virtual TextureFactoryIdentifier GetTextureFactoryIdentifier() = 0;
 
   /**
    * Properties of the compositor.
--- a/gfx/layers/CompositorTypes.h
+++ b/gfx/layers/CompositorTypes.h
@@ -14,68 +14,121 @@ namespace layers {
 typedef int32_t SurfaceDescriptorType;
 const SurfaceDescriptorType SURFACEDESCRIPTOR_UNKNOWN = 0;
 
 /**
  * Flags used by texture clients and texture hosts. These are passed from client
  * side to host side when textures and compositables are created. Usually set
  * by the compositableCient, they may be modified by either the compositable or
  * texture clients.
+ *
+ * XXX - switch to all caps constant names which seems to be the standard in gecko
  */
 typedef uint32_t TextureFlags;
 // Use nearest-neighbour texture filtering (as opposed to linear filtering).
-const TextureFlags UseNearestFilter   = 0x1;
+const TextureFlags UseNearestFilter           = 1 << 0;
 // The texture should be flipped around the y-axis when composited.
-const TextureFlags NeedsYFlip         = 0x2;
+const TextureFlags NeedsYFlip                 = 1 << 1;
 // Force the texture to be represented using a single tile (note that this means
 // tiled textures, not tiled layers).
-const TextureFlags ForceSingleTile    = 0x4;
+const TextureFlags ForceSingleTile            = 1 << 2;
 // Allow using 'repeat' mode for wrapping.
-const TextureFlags AllowRepeat        = 0x8;
+const TextureFlags AllowRepeat                = 1 << 3;
 // The texture represents a tile which is newly created.
-const TextureFlags NewTile            = 0x10;
-// The host is responsible for tidying up any shared resources.
-const TextureFlags HostRelease        = 0x20;
+const TextureFlags NewTile                    = 1 << 4;
 // The texture is part of a component-alpha pair
-const TextureFlags ComponentAlpha     = 0x40;
-// The shared resources are owned by client
-const TextureFlags OwnByClient        = 0x80;
+const TextureFlags ComponentAlpha             = 1 << 5;
+// The buffer will be treated as if the RB bytes are swapped.
+// This is useful for rendering using Cairo/Thebes, because there is no
+// BGRX Android pixel format, and so we have to do byte swapping.
+//
+// For example, if the GraphicBuffer has an Android pixel format of
+// PIXEL_FORMAT_RGBA_8888 and isRBSwapped is true, when it is sampled
+// (for example, with GL), a BGRA shader should be used.
+const TextureFlags TEXTURE_RB_SWAPPED         = 1 << 6;
 
+// A texture host that supports tiling
+const TextureFlags TEXTURE_FRONT              = 1 << 12;
+// A texture host on white for component alpha
+const TextureFlags TEXTURE_ON_WHITE           = 1 << 13;
+ // A texture host on black for component alpha
+const TextureFlags TEXTURE_ON_BLACK           = 1 << 14;
+// A texture host that supports tiling
+const TextureFlags TEXTURE_TILE               = 1 << 15;
+// Texture contents should be initialized
+// from the previous texture.
+const TextureFlags TEXTURE_COPY_PREVIOUS      = 1 << 24;
+// Who is responsible for deallocating the shared data.
+// if none of the following two flags is set, the shared data will not be
+// deallocated by the layers system. It is not necessarily a leak, it could
+// be a choice from another part of gecko that wants to keep the data alive
+// for some reason. The default behaviour is to deallocate on the host side.
+const TextureFlags TEXTURE_DEALLOCATE_CLIENT  = 1 << 25;
+const TextureFlags TEXTURE_DEALLOCATE_HOST    = 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 default flags
+const TextureFlags TEXTURE_FLAGS_DEFAULT = TEXTURE_DEALLOCATE_HOST
+                                         | TEXTURE_FRONT;
+
+/**
+ * See gfx/layers/Effects.h
+ */
+enum EffectTypes
+{
+  EFFECT_MASK,
+  EFFECT_MAX_SECONDARY, // sentinel for the count of secondary effect types
+  EFFECT_BGRX,
+  EFFECT_RGBX,
+  EFFECT_BGRA,
+  EFFECT_RGBA,
+  EFFECT_YCBCR,
+  EFFECT_COMPONENT_ALPHA,
+  EFFECT_SOLID_COLOR,
+  EFFECT_RENDER_TARGET,
+  EFFECT_MAX  //sentinel for the count of all effect types
+};
 
 /**
  * The kind of memory held by the texture client/host pair. This will
  * determine how the texture client is drawn into and how the memory
  * is shared between client and host.
  */
 enum DeprecatedTextureClientType
 {
   TEXTURE_CONTENT,            // dynamically drawn content
   TEXTURE_SHMEM,              // shared memory
-  TEXTURE_YCBCR,              // YCbCr in a shmem
+  TEXTURE_YCBCR,              // Deprecated YCbCr texture
   TEXTURE_SHARED_GL,          // GLContext::SharedTextureHandle
   TEXTURE_SHARED_GL_EXTERNAL, // GLContext::SharedTextureHandle, the ownership of
                               // the SurfaceDescriptor passed to the texture
                               // remains with whoever passed it.
   TEXTURE_STREAM_GL           // WebGL streaming buffer
 };
 
 /**
  * How the Compositable should manage textures.
  */
 enum CompositableType
 {
   BUFFER_UNKNOWN,
+  // the deprecated compositable types
   BUFFER_IMAGE_SINGLE,    // image/canvas with a single texture, single buffered
-  BUFFER_IMAGE_BUFFERED,  // image/canvas, double buffered
+  BUFFER_IMAGE_BUFFERED,  // canvas, double buffered
   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
   BUFFER_COUNT
 };
 
 /**
  * How the texture host is used for composition,
  */
 enum DeprecatedTextureHostFlags
 {
@@ -107,26 +160,31 @@ struct TextureFactoryIdentifier
     , mSupportsTextureBlitting(aSupportsTextureBlitting)
     , mSupportsPartialUploads(aSupportsPartialUploads)
   {}
 };
 
 /**
  * Identify a texture to a compositable. Many textures can have the same id, but
  * the id is unique for any texture owned by a particular compositable.
+ * XXX - This is now redundant with TextureFlags. it ill be removed along with
+ * deprecated texture classes.
  */
 typedef uint32_t TextureIdentifier;
 const TextureIdentifier TextureFront = 1;
 const TextureIdentifier TextureBack = 2;
 const TextureIdentifier TextureOnWhiteFront = 3;
 const TextureIdentifier TextureOnWhiteBack = 4;
 
 /**
  * Information required by the compositor from the content-side for creating or
  * using compositables and textures.
+ * XXX - TextureInfo is a bad name: this information is useful for the compositable,
+ * not the Texture. And ith new Textures, only the compositable type is really
+ * useful. This may (should) be removed in the near future.
  */
 struct TextureInfo
 {
   CompositableType mCompositableType;
   uint32_t mDeprecatedTextureHostFlags;
   uint32_t mTextureFlags;
 
   TextureInfo()
@@ -150,18 +208,18 @@ struct TextureInfo
 };
 
 /**
  * How a SurfaceDescriptor will be opened.
  *
  * See ShadowLayerForwarder::OpenDescriptor for example.
  */
 enum OpenMode {
-  OPEN_READ_ONLY,
-  OPEN_READ_WRITE
+  OPEN_READ_ONLY  = 0x1,
+  OPEN_READ_WRITE = 0x2
 };
 
 // The kinds of mask texture a shader can support
 // We rely on the items in this enum being sequential
 enum MaskType {
   MaskNone = 0,   // no mask layer
   Mask2d,         // mask layer for layers with 2D transforms
   Mask3d,         // mask layer for layers with 3D transforms
--- a/gfx/layers/Effects.h
+++ b/gfx/layers/Effects.h
@@ -3,16 +3,17 @@
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef MOZILLA_LAYERS_EFFECTS_H
 #define MOZILLA_LAYERS_EFFECTS_H
 
 #include "mozilla/gfx/Matrix.h"
 #include "mozilla/layers/Compositor.h"
+#include "mozilla/layers/TextureHost.h"
 #include "LayersLogging.h"
 #include "mozilla/RefPtr.h"
 
 namespace mozilla {
 namespace layers {
 
 /**
  * Effects and effect chains are used by the compositor API (see Compositor.h).
@@ -25,32 +26,16 @@ namespace layers {
  * - any way in which rendering can be changed, e.g., applying a mask layer.
  *
  * During the rendering process, an effect chain is created by the layer being
  * rendered and the primary effect is added by the compositable host. Secondary
  * effects may be added by the layer or compositable. The effect chain is passed
  * to the compositor by the compositable host as a parameter to DrawQuad.
  */
 
-
-enum EffectTypes
-{
-  EFFECT_MASK,
-  EFFECT_MAX_SECONDARY, // sentinel for the count of secondary effect types
-  EFFECT_BGRX,
-  EFFECT_RGBX,
-  EFFECT_BGRA,
-  EFFECT_RGBA,
-  EFFECT_YCBCR,
-  EFFECT_COMPONENT_ALPHA,
-  EFFECT_SOLID_COLOR,
-  EFFECT_RENDER_TARGET,
-  EFFECT_MAX  //sentinel for the count of all effect types
-};
-
 struct Effect : public RefCounted<Effect>
 {
   Effect(EffectTypes aType) : mType(aType) {}
 
   EffectTypes mType;
 
   virtual ~Effect() {}
 #ifdef MOZ_LAYERS_HAVE_LOG
--- a/gfx/layers/ImageContainer.cpp
+++ b/gfx/layers/ImageContainer.cpp
@@ -118,17 +118,17 @@ ImageContainer::ImageContainer(int flag)
   mRemoteData(nullptr),
   mRemoteDataMutex(nullptr),
   mCompositionNotifySink(nullptr),
   mImageClient(nullptr)
 {
   if (flag == ENABLE_ASYNC && ImageBridgeChild::IsCreated()) {
     // the refcount of this ImageClient is 1. we don't use a RefPtr here because the refcount
     // of this class must be done on the ImageBridge thread.
-    mImageClient = ImageBridgeChild::GetSingleton()->CreateImageClient(BUFFER_IMAGE_BUFFERED).drop();
+    mImageClient = ImageBridgeChild::GetSingleton()->CreateImageClient(BUFFER_IMAGE_SINGLE).drop();
     MOZ_ASSERT(mImageClient);
   }
 }
 
 ImageContainer::~ImageContainer()
 {
   if (IsAsync()) {
     ImageBridgeChild::DispatchReleaseImageClient(mImageClient);
--- a/gfx/layers/ImageContainer.h
+++ b/gfx/layers/ImageContainer.h
@@ -30,25 +30,39 @@ namespace ipc {
 class Shmem;
 }
 
 namespace layers {
 
 class ImageClient;
 class SharedPlanarYCbCrImage;
 class DeprecatedSharedPlanarYCbCrImage;
+class TextureClient;
+class SurfaceDescriptor;
 
 struct ImageBackendData
 {
   virtual ~ImageBackendData() {}
 
 protected:
   ImageBackendData() {}
 };
 
+// sadly we'll need this until we get rid of Deprected image classes
+class ISharedImage {
+public:
+    virtual uint8_t* GetBuffer() = 0;
+
+    /**
+     * For use with the CompositableClient only (so that the later can
+     * synchronize the TextureClient with the TextureHost).
+     */
+    virtual TextureClient* GetTextureClient() = 0;
+};
+
 /**
  * A class representing a buffer of pixel data. The data can be in one
  * of various formats including YCbCr.
  * 
  * Create an image using an ImageContainer. Fill the image with data, and
  * then call ImageContainer::SetImage to display it. An image must not be
  * modified after calling SetImage. Image implementations do not need to
  * perform locking; when filling an Image, the Image client is responsible
@@ -59,22 +73,27 @@ protected:
  * sampled. For example, cairo images should be sampled in EXTEND_PAD mode.
  */
 class Image {
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(Image)
 
 public:
   virtual ~Image() {}
 
+  virtual ISharedImage* AsSharedImage() { return nullptr; }
 
   ImageFormat GetFormat() { return mFormat; }
   void* GetImplData() { return mImplData; }
 
   virtual already_AddRefed<gfxASurface> GetAsSurface() = 0;
   virtual gfxIntSize GetSize() = 0;
+  virtual nsIntRect GetPictureRect()
+  {
+    return nsIntRect(0, 0, GetSize().width, GetSize().height);
+  }
 
   ImageBackendData* GetBackendData(LayersBackend aBackend)
   { return mBackendData[aBackend]; }
   void SetBackendData(LayersBackend aBackend, ImageBackendData* aData)
   { mBackendData[aBackend] = aData; }
 
   int32_t GetSerial() { return mSerial; }
 
new file mode 100644
--- /dev/null
+++ b/gfx/layers/ImageDataSerializer.cpp
@@ -0,0 +1,129 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "mozilla/layers/ImageDataSerializer.h"
+#include "gfxImageSurface.h"
+#include "mozilla/gfx/2D.h"
+#include "gfx2DGlue.h"
+#include "mozilla/gfx/Tools.h"
+
+namespace mozilla {
+namespace layers {
+
+// The Data is layed out as follows:
+//
+//  +-------------------+   -++ --+   <-- ImageDataSerializerBase::mData pointer
+//  | SurfaceBufferInfo |     |   |
+//  +-------------------+   --+   | offset
+//  |        ...        |         |
+//  +-------------------+   ------+
+//  |                   |
+//  |       data        |
+//  |                   |
+//  +-------------------+
+
+// Structure written at the beginning of the data blob containing the image
+// (as shown in the figure above). It contains the necessary informations to
+// read the image in the blob.
+namespace {
+struct SurfaceBufferInfo
+{
+  uint32_t width;
+  uint32_t height;
+  gfx::SurfaceFormat format;
+
+  static uint32_t GetOffset()
+  {
+    return gfx::GetAlignedStride<16>(sizeof(SurfaceBufferInfo));
+  }
+};
+} // anonymous namespace
+
+static SurfaceBufferInfo* GetBufferInfo(uint8_t* aBuffer)
+{
+  return reinterpret_cast<SurfaceBufferInfo*>(aBuffer);
+}
+
+
+void
+ImageDataSerializer::InitializeBufferInfo(gfx::IntSize aSize,
+                                          gfx::SurfaceFormat aFormat)
+{
+  SurfaceBufferInfo* info = GetBufferInfo(mData);
+  info->width = aSize.width;
+  info->height = aSize.height;
+  info->format = aFormat;
+}
+
+uint32_t
+ImageDataSerializer::ComputeMinBufferSize(gfx::IntSize aSize,
+                                          gfx::SurfaceFormat aFormat)
+{
+  // Note that at the moment we pack the image data with the minimum possible
+  // stride, we may decide to change that if we want aligned stride.
+  gfxIntSize gfxSize = gfxIntSize(aSize.width, aSize.height);
+  uint32_t bufsize = aSize.height * gfx::BytesPerPixel(aFormat) * aSize.width;
+  return SurfaceBufferInfo::GetOffset()
+       + gfx::GetAlignedStride<16>(bufsize);
+}
+
+bool
+ImageDataSerializerBase::IsValid() const
+{
+  // XXX - We could use some sanity checks here.
+  return !!mData;
+}
+
+uint8_t*
+ImageDataSerializerBase::GetData()
+{
+  MOZ_ASSERT(IsValid());
+  return mData + SurfaceBufferInfo::GetOffset();
+}
+
+gfx::IntSize
+ImageDataSerializerBase::GetSize() const
+{
+  MOZ_ASSERT(IsValid());
+  SurfaceBufferInfo* info = GetBufferInfo(mData);
+  return gfx::IntSize(info->width, info->height);
+}
+
+gfx::SurfaceFormat
+ImageDataSerializerBase::GetFormat() const
+{
+  MOZ_ASSERT(IsValid());
+  return GetBufferInfo(mData)->format;
+}
+
+TemporaryRef<gfxImageSurface>
+ImageDataSerializerBase::GetAsThebesSurface()
+{
+  MOZ_ASSERT(IsValid());
+  SurfaceBufferInfo* info = GetBufferInfo(mData);
+  uint32_t stride = gfxASurface::BytesPerPixel(
+    gfx::SurfaceFormatToImageFormat(GetFormat())) * info->width;
+  gfxIntSize size(info->width, info->height);
+  RefPtr<gfxImageSurface> surf =
+    new gfxImageSurface(GetData(), size, stride,
+                        gfx::SurfaceFormatToImageFormat(GetFormat()));
+  return surf.forget();
+}
+
+TemporaryRef<gfx::DataSourceSurface>
+ImageDataSerializerBase::GetAsSurface()
+{
+  MOZ_ASSERT(IsValid());
+  SurfaceBufferInfo* info = GetBufferInfo(mData);
+  gfx::IntSize size(info->width, info->height);
+  uint32_t stride = gfxASurface::BytesPerPixel(
+    gfx::SurfaceFormatToImageFormat(GetFormat())) * info->width;
+  RefPtr<gfx::DataSourceSurface> surf =
+    gfx::Factory::CreateWrappingDataSourceSurface(GetData(), stride, size, GetFormat());
+  return surf.forget();
+}
+
+} // namespace layers
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/gfx/layers/ImageDataSerializer.h
@@ -0,0 +1,73 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * vim: sw=2 ts=8 et :
+ */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef GFX_LAYERS_BLOBSURFACE_H
+#define GFX_LAYERS_BLOBSURFACE_H
+
+#include "mozilla/StandardInteger.h"
+#include "mozilla/gfx/Point.h"
+#include "mozilla/RefPtr.h"
+
+class gfxImageSurface;
+
+namespace mozilla {
+namespace gfx {
+class DataSourceSurface;
+} // namespace gfx
+} // namespace mozilla
+
+namespace mozilla {
+namespace layers {
+
+class ImageDataSerializerBase
+{
+public:
+  bool IsValid() const;
+
+  uint8_t* GetData();
+  gfx::IntSize GetSize() const;
+  gfx::SurfaceFormat GetFormat() const;
+  TemporaryRef<gfx::DataSourceSurface> GetAsSurface();
+  TemporaryRef<gfxImageSurface> GetAsThebesSurface();
+
+protected:
+  ImageDataSerializerBase(uint8_t* aData)
+  : mData(aData) {}
+  uint8_t* mData;
+};
+
+/**
+ * A facility to serialize an image into a buffer of memory.
+ * This is intended for use with the IPC code, in order to copy image data
+ * into shared memory.
+ * Note that there is a separate serializer class for YCbCr images
+ * (see YCbCrImageDataSerializer.h).
+ */
+class MOZ_STACK_CLASS ImageDataSerializer : public ImageDataSerializerBase
+{
+public:
+  ImageDataSerializer(uint8_t* aData) : ImageDataSerializerBase(aData) {}
+  void InitializeBufferInfo(gfx::IntSize aSize,
+                            gfx::SurfaceFormat aFormat);
+  static uint32_t ComputeMinBufferSize(gfx::IntSize aSize,
+                                       gfx::SurfaceFormat aFormat);
+};
+
+/**
+ * A facility to deserialize image data that has been serialized by an
+ * ImageDataSerializer.
+ */
+class MOZ_STACK_CLASS ImageDataDeserializer : public ImageDataSerializerBase
+{
+public:
+  ImageDataDeserializer(uint8_t* aData) : ImageDataSerializerBase(aData) {}
+};
+
+} // namespace layers
+} // namespace mozilla
+
+#endif
--- a/gfx/layers/LayersLogging.cpp
+++ b/gfx/layers/LayersLogging.cpp
@@ -210,17 +210,17 @@ AppendToString(nsACString& s, TextureFla
   } \
 }
     bool previous = false;
     AppendFlag(UseNearestFilter);
     AppendFlag(NeedsYFlip);
     AppendFlag(ForceSingleTile);
     AppendFlag(AllowRepeat);
     AppendFlag(NewTile);
-    AppendFlag(HostRelease);
+    AppendFlag(TEXTURE_DEALLOCATE_HOST);
 
 #undef AppendFlag
   }
   return s += sfx;
 }
 
 nsACString&
 AppendToString(nsACString& s, mozilla::gfx::SurfaceFormat format,
--- a/gfx/layers/YCbCrImageDataSerializer.cpp
+++ b/gfx/layers/YCbCrImageDataSerializer.cpp
@@ -1,17 +1,19 @@
 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/layers/YCbCrImageDataSerializer.h"
+#include "yuv_convert.h"
+#include "mozilla/gfx/2D.h"
+#include "gfx2DGlue.h"
 
 #define MOZ_ALIGN_WORD(x) (((x) + 3) & ~3)
-
 using namespace mozilla::ipc;
 
 namespace mozilla {
 namespace layers {
 
 // The Data is layed out as follows:
 //
 //  +-----------------+   -++ --+ --+ <-- Beginning of the buffer
@@ -213,11 +215,28 @@ YCbCrImageDataSerializer::CopyData(const
       CopyLineWithSkip(aCrData + i * aCbCrStride,
                        GetCrData() + i * GetCbCrStride(),
                        aCbCrSize.width, aCbCrSkip);
     }
   }
   return true;
 }
 
+TemporaryRef<gfx::DataSourceSurface>
+YCbCrImageDataDeserializer::ToDataSourceSurface()
+{
+  RefPtr<gfx::DataSourceSurface> result =
+    gfx::Factory::CreateDataSourceSurface(ToIntSize(GetYSize()), gfx::FORMAT_R8G8B8X8);
+
+  gfx::ConvertYCbCrToRGB32(GetYData(), GetCbData(), GetCrData(),
+                           result->GetData(),
+                           0, 0, //pic x and y
+                           GetYSize().width, GetYSize().height,
+                           GetYStride(), GetCbCrStride(),
+                           result->Stride(),
+                           gfx::YV12);
+  result->MarkDirty();
+  return result.forget();
+}
+
 
 } // namespace
 } // namespace
--- a/gfx/layers/YCbCrImageDataSerializer.h
+++ b/gfx/layers/YCbCrImageDataSerializer.h
@@ -11,16 +11,20 @@
 #include "base/basictypes.h"
 #include "Shmem.h"
 #include "gfxPoint.h"
 
 namespace mozilla {
 namespace ipc {
   class Shmem;
 }
+namespace gfx {
+  class DataSourceSurface;
+}
+
 namespace layers {
 
 class Image;
 
 /**
  * Convenience class to share code between YCbCrImageDataSerializer
  * and YCbCrImageDataDeserializer.
  * Do not use it.
@@ -129,14 +133,21 @@ public:
  *   // handle error
  * }
  * size = deserializer.GetYSize(); // work with the data, etc...
  */
 class MOZ_STACK_CLASS YCbCrImageDataDeserializer : public YCbCrImageDataDeserializerBase
 {
 public:
   YCbCrImageDataDeserializer(uint8_t* aData) : YCbCrImageDataDeserializerBase(aData) {}
+
+  /**
+   * Convert the YCbCr data into RGB and return a DataSourceSurface.
+   * This is a costly operation, so use it only when YCbCr compositing is
+   * not supported.
+   */
+  TemporaryRef<gfx::DataSourceSurface> ToDataSourceSurface();
 };
 
 } // namespace
 } // namespace
 
 #endif
--- a/gfx/layers/basic/BasicCompositor.h
+++ b/gfx/layers/basic/BasicCompositor.h
@@ -1,17 +1,18 @@
 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef MOZILLA_GFX_BASICCOMPOSITOR_H
 #define MOZILLA_GFX_BASICCOMPOSITOR_H
 
-#include "Compositor.h"
+#include "mozilla/layers/Compositor.h"
+#include "mozilla/layers/TextureHost.h"
 
 namespace mozilla {
 namespace layers {
 
 class BasicCompositingRenderTarget : public CompositingRenderTarget
 {
 public:
   BasicCompositingRenderTarget(gfx::DrawTarget* aDrawTarget, const gfx::IntSize& aSize)
@@ -27,20 +28,24 @@ public:
 
 class BasicCompositor : public Compositor
 {
 public:
   BasicCompositor(nsIWidget *aWidget);
 
   virtual ~BasicCompositor();
 
+
   virtual bool Initialize() MOZ_OVERRIDE { return true; };
 
   virtual void Destroy() MOZ_OVERRIDE;
 
+  virtual TemporaryRef<DataTextureSource>
+  CreateDataTextureSource(TextureFlags aFlags = 0) MOZ_OVERRIDE { return nullptr; }
+
   virtual TextureFactoryIdentifier GetTextureFactoryIdentifier() MOZ_OVERRIDE
   {
     return TextureFactoryIdentifier(LAYERS_BASIC, GetMaxTextureSize());
   }
 
   virtual TemporaryRef<CompositingRenderTarget>
   CreateRenderTarget(const gfx::IntRect &aRect, SurfaceInitMode aInit) MOZ_OVERRIDE;
 
--- a/gfx/layers/client/ClientCanvasLayer.cpp
+++ b/gfx/layers/client/ClientCanvasLayer.cpp
@@ -82,21 +82,21 @@ ClientCanvasLayer::RenderLayer()
   
   if (!mCanvasClient) {
     TextureFlags flags = 0;
     if (mNeedsYFlip) {
       flags |= NeedsYFlip;
     }
 
     bool isCrossProcess = !(XRE_GetProcessType() == GeckoProcessType_Default);
-    //Append OwnByClient flag for streaming buffer under OOPC case
+    //Append TEXTURE_DEALLOCATE_CLIENT flag for streaming buffer under OOPC case
     if (isCrossProcess && mGLContext) {
       GLScreenBuffer* screen = mGLContext->Screen();
       if (screen && screen->Stream()) {
-        flags |= OwnByClient;
+        flags |= TEXTURE_DEALLOCATE_CLIENT;
       }
     }
     mCanvasClient = CanvasClient::CreateCanvasClient(GetCompositableClientType(),
                                                      ClientManager(), flags);
     if (!mCanvasClient) {
       return;
     }
     if (HasShadow()) {
--- a/gfx/layers/client/ClientCanvasLayer.h
+++ b/gfx/layers/client/ClientCanvasLayer.h
@@ -29,16 +29,20 @@ public:
   ClientCanvasLayer(ClientLayerManager* aLayerManager) :
     CopyableCanvasLayer(aLayerManager, static_cast<ClientLayer*>(this))
   {
     MOZ_COUNT_CTOR(ClientCanvasLayer);
   }
   virtual ~ClientCanvasLayer()
   {
     MOZ_COUNT_DTOR(ClientCanvasLayer);
+    if (mCanvasClient) {
+      mCanvasClient->Detach();
+      mCanvasClient = nullptr;
+    }
   }
 
   virtual void SetVisibleRegion(const nsIntRegion& aRegion)
   {
     NS_ASSERTION(ClientManager()->InConstruction(),
                  "Can only set properties in construction phase");
     CanvasLayer::SetVisibleRegion(aRegion);
   }
--- a/gfx/layers/client/ClientImageLayer.cpp
+++ b/gfx/layers/client/ClientImageLayer.cpp
@@ -59,17 +59,20 @@ public:
   virtual void Disconnect()
   {
     DestroyBackBuffer();
     ClientLayer::Disconnect();
   }
 
   void DestroyBackBuffer()
   {
-    mImageClient = nullptr;
+    if (mImageClient) {
+      mImageClient->Detach();
+      mImageClient = nullptr;
+    }
   }
 
   virtual CompositableClient* GetCompositableClient() MOZ_OVERRIDE
   {
     return mImageClient;
   }
 
 protected:
@@ -107,16 +110,20 @@ ClientImageLayer::RenderLayer()
   if (GetMaskLayer()) {
     ToClientLayer(GetMaskLayer())->RenderLayer();
   }
 
   if (!mContainer) {
      return;
   }
 
+  if (mImageClient) {
+    mImageClient->OnTransaction();
+  }
+
   if (!mImageClient ||
       !mImageClient->UpdateImage(mContainer, GetContentFlags())) {
     CompositableType type = GetImageClientType();
     if (type == BUFFER_UNKNOWN) {
       return;
     }
     mImageClient = ImageClient::CreateImageClient(type,
                                                   ClientManager(),
--- a/gfx/layers/client/ClientLayerManager.cpp
+++ b/gfx/layers/client/ClientLayerManager.cpp
@@ -318,16 +318,23 @@ ClientLayerManager::ForwardTransaction()
         CompositableChild* compositableChild =
           static_cast<CompositableChild*>(ots.compositableChild());
         MOZ_ASSERT(compositableChild);
 
         compositableChild->GetCompositableClient()
           ->SetDescriptorFromReply(ots.textureId(), ots.image());
         break;
       }
+      case EditReply::TReplyTextureRemoved: {
+        // XXX - to manage reuse of gralloc buffers, we'll need to add some
+        // glue code here to find the TextureClient and invoke a callback to
+        // let the camera know that the gralloc buffer is not used anymore on
+        // the compositor side and that it can reuse it.
+        break;
+      }
 
       default:
         NS_RUNTIMEABORT("not reached");
       }
     }
   } else if (HasShadowManager()) {
     NS_WARNING("failed to forward Layers transaction");
   }
--- a/gfx/layers/client/ClientThebesLayer.h
+++ b/gfx/layers/client/ClientThebesLayer.h
@@ -22,16 +22,20 @@ public:
   ClientThebesLayer(ClientLayerManager* aLayerManager) :
     ThebesLayer(aLayerManager, static_cast<ClientLayer*>(this)),
     mContentClient(nullptr)
   {
     MOZ_COUNT_CTOR(ClientThebesLayer);
   }
   virtual ~ClientThebesLayer()
   {
+    if (mContentClient) {
+      mContentClient->Detach();
+      mContentClient = nullptr;
+    }
     MOZ_COUNT_DTOR(ClientThebesLayer);
   }
 
   virtual void SetVisibleRegion(const nsIntRegion& aRegion)
   {
     NS_ASSERTION(ClientManager()->InConstruction(),
                  "Can only set properties in construction phase");
     ThebesLayer::SetVisibleRegion(aRegion);
--- a/gfx/layers/client/CompositableClient.cpp
+++ b/gfx/layers/client/CompositableClient.cpp
@@ -3,28 +3,39 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/layers/CompositableClient.h"
 #include "mozilla/layers/TextureClient.h"
 #include "mozilla/layers/TextureClientOGL.h"
 #include "mozilla/layers/LayerTransactionChild.h"
 #include "mozilla/layers/CompositableForwarder.h"
+#include "gfxPlatform.h"
 #ifdef XP_WIN
 #include "mozilla/layers/TextureD3D11.h"
 #include "gfxWindowsPlatform.h"
 #endif
 
 namespace mozilla {
 namespace layers {
 
+CompositableClient::CompositableClient(CompositableForwarder* aForwarder)
+: mNextTextureID(1)
+, mCompositableChild(nullptr)
+, mForwarder(aForwarder)
+{
+  MOZ_COUNT_CTOR(CompositableClient);
+}
+
+
 CompositableClient::~CompositableClient()
 {
   MOZ_COUNT_DTOR(CompositableClient);
   Destroy();
+  MOZ_ASSERT(mTexturesToRemove.size() == 0, "would leak textures pending fore deletion");
 }
 
 LayersBackend
 CompositableClient::GetCompositorBackendType() const
 {
   return mForwarder->GetCompositorBackendType();
 }
 
@@ -130,10 +141,51 @@ 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)
+{
+  if (gfxPlatform::GetPlatform()->PreferMemoryOverShmem()) {
+    RefPtr<BufferTextureClient> result = new MemoryTextureClient(this, aFormat);
+    return result.forget();
+  }
+  RefPtr<BufferTextureClient> result = new ShmemTextureClient(this, aFormat);
+  return result.forget();
+}
+
+
+void
+CompositableClient::AddTextureClient(TextureClient* aClient)
+{
+  ++mNextTextureID;
+  // 0 is always an invalid ID
+  if (mNextTextureID == 0) {
+    ++mNextTextureID;
+  }
+  aClient->SetID(mNextTextureID);
+  mForwarder->AddTexture(this, aClient);
+}
+
+void
+CompositableClient::RemoveTextureClient(TextureClient* aClient)
+{
+  MOZ_ASSERT(aClient);
+  mTexturesToRemove.push_back(aClient->GetID());
+  aClient->SetID(0);
+}
+
+void
+CompositableClient::OnTransaction()
+{
+  for (unsigned i = 0; i < mTexturesToRemove.size(); ++i) {
+    mForwarder->RemoveTexture(this, mTexturesToRemove[i]);
+  }
+  mTexturesToRemove.clear();
+}
+
 } // namespace layers
 } // namespace mozilla
--- a/gfx/layers/client/CompositableClient.h
+++ b/gfx/layers/client/CompositableClient.h
@@ -11,16 +11,18 @@
 #include "mozilla/RefPtr.h"
 
 namespace mozilla {
 namespace layers {
 
 class CompositableChild;
 class CompositableClient;
 class DeprecatedTextureClient;
+class TextureClient;
+class BufferTextureClient;
 class ImageBridgeChild;
 class ShadowableLayer;
 class CompositableForwarder;
 class CompositableChild;
 class SurfaceDescriptor;
 
 /**
  * CompositableClient manages the texture-specific logic for composite layers,
@@ -58,34 +60,30 @@ class SurfaceDescriptor;
  * Subclasses: Thebes layers use ContentClients, ImageLayers use ImageClients,
  * Canvas layers use CanvasClients (but ImageHosts). We have a different subclass
  * where we have a different way of interfacing with the textures - in terms of
  * drawing into the compositable and/or passing its contents to the compostior.
  */
 class CompositableClient : public RefCounted<CompositableClient>
 {
 public:
-  CompositableClient(CompositableForwarder* aForwarder)
-  : mCompositableChild(nullptr), mForwarder(aForwarder)
-  {
-    MOZ_COUNT_CTOR(CompositableClient);
-  }
+  CompositableClient(CompositableForwarder* aForwarder);
 
   virtual ~CompositableClient();
 
-  virtual TextureInfo GetTextureInfo() const
-  {
-    MOZ_CRASH("This method should be overridden");
-  }
+  virtual TextureInfo GetTextureInfo() const = 0;
 
   LayersBackend GetCompositorBackendType() const;
 
   TemporaryRef<DeprecatedTextureClient>
   CreateDeprecatedTextureClient(DeprecatedTextureClientType aDeprecatedTextureClientType);
 
+  TemporaryRef<BufferTextureClient>
+  CreateBufferTextureClient(gfx::SurfaceFormat aFormat);
+
   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
@@ -106,17 +104,41 @@ public:
 
   /**
    * This identifier is what lets us attach async compositables with a shadow
    * layer. It is not used if the compositable is used with the regulat shadow
    * layer forwarder.
    */
   uint64_t GetAsyncID() const;
 
+  /**
+   * Tells the Compositor to create a TextureHost for this TextureClient.
+   */
+  virtual void AddTextureClient(TextureClient* aClient);
+
+  /**
+   * Tells the Compositor to delete the TextureHost corresponding to this
+   * TextureClient.
+   */
+  virtual void RemoveTextureClient(TextureClient* aClient);
+
+  /**
+   * A hook for the Compositable to execute whatever it held off for next trasanction.
+   */
+  virtual void OnTransaction();
+
+  /**
+   * A hook for the when the Compositable is detached from it's layer.
+   */
+  virtual void Detach() {}
+
 protected:
+  // The textures to destroy in the next transaction;
+  std::vector<uint64_t> mTexturesToRemove;
+  uint64_t mNextTextureID;
   CompositableChild* mCompositableChild;
   CompositableForwarder* mForwarder;
 };
 
 /**
  * IPDL actor used by CompositableClient to match with its corresponding
  * CompositableHost on the compositor side.
  *
--- a/gfx/layers/client/ContentClient.cpp
+++ b/gfx/layers/client/ContentClient.cpp
@@ -150,17 +150,17 @@ ContentClientRemoteBuffer::BuildDeprecat
 
   if (mDeprecatedTextureClient) {
     mOldTextures.AppendElement(mDeprecatedTextureClient);
     if (mDeprecatedTextureClientOnWhite) {
       mOldTextures.AppendElement(mDeprecatedTextureClientOnWhite);
     }
     DestroyBuffers();
   }
-  mTextureInfo.mTextureFlags = aFlags | HostRelease;
+  mTextureInfo.mTextureFlags = aFlags | TEXTURE_DEALLOCATE_HOST;
   mDeprecatedTextureClient = CreateDeprecatedTextureClient(TEXTURE_CONTENT);
   MOZ_ASSERT(mDeprecatedTextureClient, "Failed to create texture client");
   if (aFlags & BUFFER_COMPONENT_ALPHA) {
     mDeprecatedTextureClientOnWhite = CreateDeprecatedTextureClient(TEXTURE_CONTENT);
     MOZ_ASSERT(mDeprecatedTextureClientOnWhite, "Failed to create texture client");
     mTextureInfo.mTextureFlags |= ComponentAlpha;
   }
 
--- a/gfx/layers/client/ContentClient.h
+++ b/gfx/layers/client/ContentClient.h
@@ -385,17 +385,17 @@ private:
 
   enum BufferType{
     BUFFER_BLACK,
     BUFFER_WHITE
   };
 
   void NotifyBufferCreated(ContentType aType, uint32_t aFlags)
   {
-    mTextureInfo.mTextureFlags = aFlags | HostRelease;
+    mTextureInfo.mTextureFlags = aFlags | TEXTURE_DEALLOCATE_HOST;
     mContentType = aType;
 
     mForwarder->CreatedIncrementalBuffer(this,
                                          mTextureInfo,
                                          mBufferRect);
 
   }
 
--- a/gfx/layers/client/ImageClient.cpp
+++ b/gfx/layers/client/ImageClient.cpp
@@ -6,52 +6,216 @@
 #include "mozilla/layers/TextureClient.h"
 #include "mozilla/layers/ImageClient.h"
 #include "BasicLayers.h"
 #include "mozilla/layers/ShadowLayers.h"
 #include "SharedTextureImage.h"
 #include "ImageContainer.h" // For PlanarYCbCrImage
 #include "mozilla/layers/SharedRGBImage.h"
 #include "mozilla/layers/SharedPlanarYCbCrImage.h"
+#include "gfxPlatform.h"
 
 #ifdef MOZ_WIDGET_GONK
 #include "GrallocImages.h"
 #endif
 
 namespace mozilla {
 namespace layers {
 
 /* static */ TemporaryRef<ImageClient>
 ImageClient::CreateImageClient(CompositableType aCompositableHostType,
                                CompositableForwarder* aForwarder,
                                TextureFlags aFlags)
 {
   RefPtr<ImageClient> result = nullptr;
   switch (aCompositableHostType) {
+  case COMPOSITABLE_IMAGE:
   case BUFFER_IMAGE_SINGLE:
-    result = new DeprecatedImageClientSingle(aForwarder, aFlags, BUFFER_IMAGE_SINGLE);
+    if (gfxPlatform::GetPlatform()->UseDeprecatedTextures()) {
+      result = new DeprecatedImageClientSingle(aForwarder, aFlags, BUFFER_IMAGE_SINGLE);
+    } else {
+      result = new ImageClientSingle(aForwarder, aFlags, COMPOSITABLE_IMAGE);
+    }
     break;
   case BUFFER_IMAGE_BUFFERED:
-    result = new DeprecatedImageClientSingle(aForwarder, aFlags, BUFFER_IMAGE_BUFFERED);
+    if (gfxPlatform::GetPlatform()->UseDeprecatedTextures()) {
+      result = new DeprecatedImageClientSingle(aForwarder, aFlags, BUFFER_IMAGE_BUFFERED);
+    } else {
+      // ImageClientBuffered was a hack for async-video only, and the new textures
+      // make it so that we don't need to do this hack anymore.
+      result = new ImageClientSingle(aForwarder, aFlags, COMPOSITABLE_IMAGE);
+    }
     break;
   case BUFFER_BRIDGE:
     result = new ImageClientBridge(aForwarder, aFlags);
     break;
   case BUFFER_UNKNOWN:
     result = nullptr;
     break;
   default:
     MOZ_CRASH("unhandled program type");
   }
 
   NS_ASSERTION(result, "Failed to create ImageClient");
 
   return result.forget();
 }
 
+ImageClientSingle::ImageClientSingle(CompositableForwarder* aFwd,
+                                     TextureFlags aFlags,
+                                     CompositableType aType)
+  : ImageClient(aFwd, aType)
+  , mTextureFlags(aFlags)
+{
+}
+
+ImageClientBuffered::ImageClientBuffered(CompositableForwarder* aFwd,
+                                         TextureFlags aFlags,
+                                         CompositableType aType)
+  : ImageClientSingle(aFwd, aFlags, aType)
+{
+}
+
+TextureInfo ImageClientSingle::GetTextureInfo() const
+{
+  return TextureInfo(COMPOSITABLE_IMAGE);
+}
+
+bool
+ImageClientSingle::UpdateImage(ImageContainer* aContainer,
+                               uint32_t aContentFlags)
+{
+  AutoLockImage autoLock(aContainer);
+
+  Image *image = autoLock.GetImage();
+  if (!image) {
+    return false;
+  }
+
+  if (mLastPaintedImageSerial == image->GetSerial()) {
+    return true;
+  }
+
+  if (image->AsSharedImage() && image->AsSharedImage()->GetTextureClient()) {
+    // fast path: no need to allocate and/or copy image data
+    RefPtr<TextureClient> tex = image->AsSharedImage()->GetTextureClient();
+
+    if (mFrontBuffer) {
+      RemoveTextureClient(mFrontBuffer);
+    }
+    mFrontBuffer = tex;
+    AddTextureClient(tex);
+    GetForwarder()->UpdatedTexture(this, tex, nullptr);
+    GetForwarder()->UseTexture(this, tex);
+  } else if (image->GetFormat() == PLANAR_YCBCR) {
+    PlanarYCbCrImage* ycbcr = static_cast<PlanarYCbCrImage*>(image);
+    const PlanarYCbCrImage::Data* data = ycbcr->GetData();
+    if (!data) {
+      return false;
+    }
+
+    if (mFrontBuffer && mFrontBuffer->IsImmutable()) {
+      RemoveTextureClient(mFrontBuffer);
+      mFrontBuffer = nullptr;
+    }
+
+    if (!mFrontBuffer) {
+      mFrontBuffer = CreateBufferTextureClient(gfx::FORMAT_YUV);
+      gfx::IntSize ySize(data->mYSize.width, data->mYSize.height);
+      gfx::IntSize cbCrSize(data->mCbCrSize.width, data->mCbCrSize.height);
+      if (!mFrontBuffer->AsTextureClientYCbCr()->AllocateForYCbCr(ySize, cbCrSize)) {
+        mFrontBuffer = nullptr;
+        return false;
+      }
+      AddTextureClient(mFrontBuffer);
+    }
+
+    if (!mFrontBuffer->Lock(OPEN_READ_WRITE)) {
+      return false;
+    }
+    bool status = mFrontBuffer->AsTextureClientYCbCr()->UpdateYCbCr(*data);
+    mFrontBuffer->Unlock();
+
+    if (status) {
+      GetForwarder()->UpdatedTexture(this, mFrontBuffer, nullptr);
+      GetForwarder()->UseTexture(this, mFrontBuffer);
+    } else {
+      MOZ_ASSERT(false);
+      return false;
+    }
+
+  } else {
+    nsRefPtr<gfxASurface> surface = image->GetAsSurface();
+    MOZ_ASSERT(surface);
+
+    if (mFrontBuffer && mFrontBuffer->IsImmutable()) {
+      RemoveTextureClient(mFrontBuffer);
+      mFrontBuffer = nullptr;
+    }
+
+    if (!mFrontBuffer) {
+      gfxASurface::gfxImageFormat format
+        = gfxPlatform::GetPlatform()->OptimalFormatForContent(surface->GetContentType());
+      mFrontBuffer = CreateBufferTextureClient(gfx::ImageFormatToSurfaceFormat(format));
+      gfx::IntSize size = gfx::IntSize(image->GetSize().width, image->GetSize().height);
+      MOZ_ASSERT(mFrontBuffer->AsTextureClientSurface());
+      mFrontBuffer->AsTextureClientSurface()->AllocateForSurface(size);
+
+      AddTextureClient(mFrontBuffer);
+    }
+
+    if (!mFrontBuffer->Lock(OPEN_READ_WRITE)) {
+      return false;
+    }
+    bool status = mFrontBuffer->AsTextureClientSurface()->UpdateSurface(surface);
+    mFrontBuffer->Unlock();
+    if (status) {
+      GetForwarder()->UpdatedTexture(this, mFrontBuffer, nullptr);
+      GetForwarder()->UseTexture(this, mFrontBuffer);
+    } else {
+      return false;
+    }
+  }
+
+  UpdatePictureRect(image->GetPictureRect());
+
+  mLastPaintedImageSerial = image->GetSerial();
+  aContainer->NotifyPaintedImage(image);
+  return true;
+}
+
+bool
+ImageClientBuffered::UpdateImage(ImageContainer* aContainer,
+                                 uint32_t aContentFlags)
+{
+  RefPtr<TextureClient> temp = mFrontBuffer;
+  mFrontBuffer = mBackBuffer;
+  mBackBuffer = temp;
+  return ImageClientSingle::UpdateImage(aContainer, aContentFlags);
+}
+
+void
+ImageClientSingle::AddTextureClient(TextureClient* aTexture)
+{
+  aTexture->AddFlags(mTextureFlags);
+  CompositableClient::AddTextureClient(aTexture);
+}
+
+void
+ImageClientSingle::Detach()
+{
+  mFrontBuffer = nullptr;
+}
+
+void
+ImageClientBuffered::Detach()
+{
+  mFrontBuffer = nullptr;
+  mBackBuffer = nullptr;
+}
 
 ImageClient::ImageClient(CompositableForwarder* aFwd, CompositableType aType)
 : CompositableClient(aFwd)
 , mType(aType)
 , mLastPaintedImageSerial(0)
 {}
 
 void
@@ -227,20 +391,28 @@ ImageClientBridge::UpdateImage(ImageCont
 already_AddRefed<Image>
 ImageClient::CreateImage(const uint32_t *aFormats,
                          uint32_t aNumFormats)
 {
   nsRefPtr<Image> img;
   for (uint32_t i = 0; i < aNumFormats; i++) {
     switch (aFormats[i]) {
       case PLANAR_YCBCR:
-        img = new DeprecatedSharedPlanarYCbCrImage(GetForwarder());
+        if (gfxPlatform::GetPlatform()->UseDeprecatedTextures()) {
+            img = new DeprecatedSharedPlanarYCbCrImage(GetForwarder());
+        } else {
+            img = new SharedPlanarYCbCrImage(this);
+        }
         return img.forget();
       case SHARED_RGB:
-        img = new DeprecatedSharedRGBImage(GetForwarder());
+        if (gfxPlatform::GetPlatform()->UseDeprecatedTextures()) {
+            img = new DeprecatedSharedRGBImage(GetForwarder());
+        } else {
+            img = new SharedRGBImage(this);
+        }
         return img.forget();
 #ifdef MOZ_WIDGET_GONK
       case GRALLOC_PLANAR_YCBCR:
         img = new GrallocImage();
         return img.forget();
 #endif
     }
   }
--- a/gfx/layers/client/ImageClient.h
+++ b/gfx/layers/client/ImageClient.h
@@ -40,21 +40,16 @@ public:
   /**
    * Update this ImageClient from aContainer in aLayer
    * returns false if this is the wrong kind of ImageClient for aContainer.
    * Note that returning true does not necessarily imply success
    */
   virtual bool UpdateImage(ImageContainer* aContainer, uint32_t aContentFlags) = 0;
 
   /**
-   * Notify the compositor that this image client has been updated
-   */
-  virtual void Updated() = 0;
-
-  /**
    * The picture rect is the area of the texture which makes up the image. That
    * is, the area that should be composited. In texture space.
    */
   virtual void UpdatePictureRect(nsIntRect aPictureRect);
 
   virtual already_AddRefed<Image> CreateImage(const uint32_t *aFormats,
                                               uint32_t aNumFormats);
 
@@ -62,20 +57,64 @@ protected:
   ImageClient(CompositableForwarder* aFwd, CompositableType aType);
 
   CompositableType mType;
   int32_t mLastPaintedImageSerial;
   nsIntRect mPictureRect;
 };
 
 /**
+ * An image client which uses a single texture client.
+ */
+class ImageClientSingle : public ImageClient
+{
+public:
+  ImageClientSingle(CompositableForwarder* aFwd,
+                    TextureFlags aFlags,
+                    CompositableType aType);
+
+  virtual bool UpdateImage(ImageContainer* aContainer, uint32_t aContentFlags);
+
+  virtual void Detach() MOZ_OVERRIDE;
+
+  virtual void AddTextureClient(TextureClient* aTexture) MOZ_OVERRIDE;
+
+  virtual TextureInfo GetTextureInfo() const MOZ_OVERRIDE;
+protected:
+  RefPtr<TextureClient> mFrontBuffer;
+  // Some layers may want to enforce some flags to all their textures
+  // (like disallowing tiling)
+  TextureFlags mTextureFlags;
+};
+
+/**
+ * An image client which uses a two texture clients.
+ */
+class ImageClientBuffered : public ImageClientSingle
+{
+public:
+  ImageClientBuffered(CompositableForwarder* aFwd,
+                      TextureFlags aFlags,
+                      CompositableType aType);
+
+  virtual bool UpdateImage(ImageContainer* aContainer, uint32_t aContentFlags);
+
+  virtual void Detach() MOZ_OVERRIDE;
+
+protected:
+  RefPtr<TextureClient> mBackBuffer;
+};
+
+/**
  * An image client which uses a single texture client, may be single or double
  * buffered. (As opposed to using two texture clients for buffering, as in
  * ContentClientDoubleBuffered, or using multiple clients for YCbCr or tiled
  * images).
+ *
+ * XXX - this is deprecated, use ImageClientSingle
  */
 class DeprecatedImageClientSingle : public ImageClient
 {
 public:
   DeprecatedImageClientSingle(CompositableForwarder* aFwd,
                               TextureFlags aFlags,
                               CompositableType aType);
 
--- a/gfx/layers/client/TextureClient.cpp
+++ b/gfx/layers/client/TextureClient.cpp
@@ -12,22 +12,229 @@
 #include "mozilla/layers/ShadowLayers.h"
 #include "mozilla/layers/SharedPlanarYCbCrImage.h"
 #include "GLContext.h"
 #include "BasicLayers.h" // for PaintContext
 #include "mozilla/layers/YCbCrImageDataSerializer.h"
 #include "gfxReusableSurfaceWrapper.h"
 #include "gfxPlatform.h"
 #include "mozilla/StandardInteger.h"
+#include "mozilla/layers/ImageDataSerializer.h"
+#include "gfx2DGlue.h"
 
 using namespace mozilla::gl;
 
 namespace mozilla {
 namespace layers {
 
+
+
+
+
+TextureClient::TextureClient(TextureFlags aFlags)
+  : mID(0)
+  , mFlags(aFlags)
+{}
+
+TextureClient::~TextureClient()
+{}
+
+bool
+TextureClient::ShouldDeallocateInDestructor() const
+{
+  return IsAllocated() &&
+         !IsSharedWithCompositor() &&
+         !(GetFlags() & (TEXTURE_DEALLOCATE_HOST|TEXTURE_DEALLOCATE_CLIENT));
+}
+
+bool
+ShmemTextureClient::ToSurfaceDescriptor(SurfaceDescriptor& aDescriptor)
+{
+  if (!IsAllocated() || GetFormat() == gfx::FORMAT_UNKNOWN) {
+    return false;
+  }
+
+  aDescriptor = SurfaceDescriptorShmem(mShmem, GetFormat());
+
+  return true;
+}
+
+ISurfaceAllocator*
+ShmemTextureClient::GetAllocator() const
+{
+  return mCompositable->GetForwarder();
+}
+
+bool
+ShmemTextureClient::Allocate(uint32_t aSize)
+{
+  ipc::SharedMemory::SharedMemoryType memType = OptimalShmemType();
+  mAllocated = GetAllocator()->AllocUnsafeShmem(aSize, memType, &mShmem);
+  return mAllocated;
+}
+
+uint8_t*
+ShmemTextureClient::GetBuffer() const
+{
+  if (mAllocated) {
+    return mShmem.get<uint8_t>();
+  }
+  return nullptr;
+}
+
+size_t
+ShmemTextureClient::GetBufferSize() const
+{
+  return mShmem.Size<uint8_t>();
+}
+
+ShmemTextureClient::ShmemTextureClient(CompositableClient* aCompositable,
+                                       gfx::SurfaceFormat aFormat)
+  : BufferTextureClient(aCompositable, aFormat)
+  , mAllocated(false)
+{
+  MOZ_COUNT_CTOR(ShmemTextureClient);
+}
+
+ShmemTextureClient::~ShmemTextureClient()
+{
+  MOZ_COUNT_DTOR(ShmemTextureClient);
+  if (ShouldDeallocateInDestructor()) {
+    // if the buffer has never been shared we must deallocate it or ir would
+    // leak.
+    mCompositable->GetForwarder()->DeallocShmem(mShmem);
+  }
+}
+
+bool
+MemoryTextureClient::ToSurfaceDescriptor(SurfaceDescriptor& aDescriptor)
+{
+  if (!IsAllocated() || GetFormat() == gfx::FORMAT_UNKNOWN) {
+    return false;
+  }
+  aDescriptor = SurfaceDescriptorMemory(reinterpret_cast<uintptr_t>(mBuffer),
+                                        GetFormat());
+  return true;
+}
+
+bool
+MemoryTextureClient::Allocate(uint32_t aSize)
+{
+  MOZ_ASSERT(!mBuffer);
+  mBuffer = new uint8_t[aSize];
+  mBufSize = aSize;
+  return true;
+}
+
+MemoryTextureClient::MemoryTextureClient(CompositableClient* aCompositable, gfx::SurfaceFormat aFormat)
+  : BufferTextureClient(aCompositable, aFormat)
+  , mBuffer(nullptr)
+  , mBufSize(0)
+{
+  MOZ_COUNT_CTOR(MemoryTextureClient);
+}
+
+MemoryTextureClient::~MemoryTextureClient()
+{
+  MOZ_COUNT_DTOR(MemoryTextureClient);
+  if (ShouldDeallocateInDestructor()) {
+    // if the buffer has never been shared we must deallocate it or ir would
+    // leak.
+    delete mBuffer;
+  }
+}
+
+BufferTextureClient::BufferTextureClient(CompositableClient* aCompositable,
+                                         gfx::SurfaceFormat aFormat)
+  : TextureClient()
+  , mCompositable(aCompositable)
+  , mFormat(aFormat)
+{}
+
+BufferTextureClient::~BufferTextureClient()
+{}
+
+bool
+BufferTextureClient::UpdateSurface(gfxASurface* aSurface)
+{
+  MOZ_ASSERT(aSurface);
+
+  ImageDataSerializer serializer(GetBuffer());
+  if (!serializer.IsValid()) {
+    return false;
+  }
+
+  RefPtr<gfxImageSurface> surf = serializer.GetAsThebesSurface();
+  if (!surf) {
+    return false;
+  }
+
+  nsRefPtr<gfxContext> tmpCtx = new gfxContext(surf.get());
+  tmpCtx->SetOperator(gfxContext::OPERATOR_SOURCE);
+  tmpCtx->DrawSurface(aSurface, gfxSize(serializer.GetSize().width,
+                                        serializer.GetSize().height));
+  return true;
+}
+
+bool
+BufferTextureClient::AllocateForSurface(gfx::IntSize aSize)
+{
+  MOZ_ASSERT(mFormat != gfx::FORMAT_YUV, "This textureClient cannot use YCbCr data");
+
+  int bufSize
+    = ImageDataSerializer::ComputeMinBufferSize(aSize, mFormat);
+  if (!Allocate(bufSize)) {
+    return false;
+  }
+  ImageDataSerializer serializer(GetBuffer());
+  serializer.InitializeBufferInfo(aSize, mFormat);
+  return true;
+}
+
+bool
+BufferTextureClient::UpdateYCbCr(const PlanarYCbCrImage::Data& aData)
+{
+  MOZ_ASSERT(mFormat == gfx::FORMAT_YUV, "This textureClient can only use YCbCr data");
+  MOZ_ASSERT(!IsImmutable());
+  MOZ_ASSERT(aData.mCbSkip == aData.mCrSkip);
+
+  YCbCrImageDataSerializer serializer(GetBuffer());
+  MOZ_ASSERT(serializer.IsValid());
+  if (!serializer.CopyData(aData.mYChannel, aData.mCbChannel, aData.mCrChannel,
+                           aData.mYSize, aData.mYStride,
+                           aData.mCbCrSize, aData.mCbCrStride,
+                           aData.mYSkip, aData.mCbSkip)) {
+    NS_WARNING("Failed to copy image data!");
+    return false;
+  }
+  return true;
+}
+
+bool
+BufferTextureClient::AllocateForYCbCr(gfx::IntSize aYSize, gfx::IntSize aCbCrSize)
+{
+  size_t bufSize = YCbCrImageDataSerializer::ComputeMinBufferSize(aYSize,
+                                                                  aCbCrSize);
+  if (!Allocate(bufSize)) {
+    return false;
+  }
+  YCbCrImageDataSerializer serializer(GetBuffer());
+  serializer.InitializeBufferInfo(aYSize,
+                                  aCbCrSize);
+  return true;
+}
+
+
+
+
+
+
+
+
+
 DeprecatedTextureClient::DeprecatedTextureClient(CompositableForwarder* aForwarder,
                              const TextureInfo& aTextureInfo)
   : mForwarder(aForwarder)
   , mTextureInfo(aTextureInfo)
   , mAccessMode(ACCESS_READ_WRITE)
 {
   MOZ_COUNT_CTOR(DeprecatedTextureClient);
 }
@@ -49,17 +256,17 @@ DeprecatedTextureClientShmem::Deprecated
 void
 DeprecatedTextureClientShmem::ReleaseResources()
 {
   if (mSurface) {
     mSurface = nullptr;
     ShadowLayerForwarder::CloseDescriptor(mDescriptor);
   }
 
-  if (mTextureInfo.mTextureFlags & HostRelease) {
+  if (mTextureInfo.mTextureFlags & TEXTURE_DEALLOCATE_HOST) {
     mDescriptor = SurfaceDescriptor();
     return;
   }
 
   if (IsSurfaceDescriptorValid(mDescriptor)) {
     mForwarder->DestroySharedSurface(&mDescriptor);
     mDescriptor = SurfaceDescriptor();
   }
@@ -149,16 +356,24 @@ DeprecatedTextureClientShmem::LockImageS
 {
   if (!mSurfaceAsImage) {
     mSurfaceAsImage = GetSurface()->GetAsImageSurface();
   }
 
   return mSurfaceAsImage.get();
 }
 
+DeprecatedTextureClientTile::DeprecatedTextureClientTile(const DeprecatedTextureClientTile& aOther)
+  : DeprecatedTextureClient(aOther.mForwarder, aOther.mTextureInfo)
+  , mSurface(aOther.mSurface)
+{}
+
+DeprecatedTextureClientTile::~DeprecatedTextureClientTile()
+{}
+
 void
 DeprecatedTextureClientShmemYCbCr::ReleaseResources()
 {
   GetForwarder()->DestroySharedSurface(&mDescriptor);
 }
 
 void
 DeprecatedTextureClientShmemYCbCr::SetDescriptor(const SurfaceDescriptor& aDescriptor)
@@ -188,24 +403,16 @@ DeprecatedTextureClientShmemYCbCr::SetDe
 void
 DeprecatedTextureClientShmemYCbCr::EnsureAllocated(gfx::IntSize aSize,
                                          gfxASurface::gfxContentType aType)
 {
   NS_RUNTIMEABORT("not enough arguments to do this (need both Y and CbCr sizes)");
 }
 
 
-DeprecatedTextureClientTile::DeprecatedTextureClientTile(const DeprecatedTextureClientTile& aOther)
-  : DeprecatedTextureClient(aOther.mForwarder, aOther.mTextureInfo)
-  , mSurface(aOther.mSurface)
-{}
-
-DeprecatedTextureClientTile::~DeprecatedTextureClientTile()
-{}
-
 DeprecatedTextureClientTile::DeprecatedTextureClientTile(CompositableForwarder* aForwarder,
                                      const TextureInfo& aTextureInfo)
   : DeprecatedTextureClient(aForwarder, aTextureInfo)
   , mSurface(nullptr)
 {
   mTextureInfo.mDeprecatedTextureHostFlags = TEXTURE_HOST_TILED;
 }
 
@@ -228,16 +435,20 @@ DeprecatedTextureClientTile::LockImageSu
   // Use the gfxReusableSurfaceWrapper, which will reuse the surface
   // if the compositor no longer has a read lock, otherwise the surface
   // will be copied into a new writable surface.
   gfxImageSurface* writableSurface = nullptr;
   mSurface = mSurface->GetWritable(&writableSurface);
   return writableSurface;
 }
 
+// XXX - All the code below can be removed as soon as we remove
+// DeprecatedImageClientSingle (which has already been ported to the new
+// textures).
+
 bool AutoLockShmemClient::Update(Image* aImage,
                                  uint32_t aContentFlags,
                                  gfxASurface *aSurface)
 {
   if (!aImage) {
     return false;
   }
 
@@ -339,10 +550,11 @@ bool AutoLockYCbCrClient::EnsureDeprecat
   serializer.InitializeBufferInfo(data->mYSize,
                                   data->mCbCrSize);
 
   *mDescriptor = YCbCrImage(shmem, 0);
 
   return true;
 }
 
+
 }
 }
--- a/gfx/layers/client/TextureClient.h
+++ b/gfx/layers/client/TextureClient.h
@@ -5,31 +5,293 @@
 
 #ifndef MOZILLA_GFX_TEXTURECLIENT_H
 #define MOZILLA_GFX_TEXTURECLIENT_H
 
 #include "mozilla/layers/LayersSurfaces.h"
 #include "gfxASurface.h"
 #include "mozilla/layers/CompositorTypes.h" // for TextureInfo
 #include "mozilla/RefPtr.h"
+#include "ImageContainer.h" // for PlanarYCbCrImage::Data
 
 class gfxReusableSurfaceWrapper;
 
 namespace mozilla {
 
 namespace gl {
 class GLContext;
 }
 
 namespace layers {
 
 class ContentClient;
 class PlanarYCbCrImage;
 class Image;
 class CompositableForwarder;
+class ISurfaceAllocator;
+class CompositableClient;
+
+/**
+ * TextureClient is the abstraction that allows us to share data between the
+ * content and the compositor side.
+ * TextureClient can also provide with some more more "producer" facing APIs
+ * such as TextureClientSurface and TextureClientYCbCr, that can be queried
+ * using AsTextureCLientSurface(), etc.
+ */
+
+/**
+ * Interface for TextureClients that can be updated using a gfxASurface.
+ */
+class TextureClientSurface
+{
+public:
+  virtual bool UpdateSurface(gfxASurface* aSurface) = 0;
+  virtual bool AllocateForSurface(gfx::IntSize aSize) = 0;
+};
+
+/**
+ * Interface for TextureClients that can be updated using YCbCr data.
+ */
+class TextureClientYCbCr
+{
+public:
+  virtual bool UpdateYCbCr(const PlanarYCbCrImage::Data& aData) = 0;
+  virtual bool AllocateForYCbCr(gfx::IntSize aYSize, gfx::IntSize aCbCrSize) = 0;
+};
+
+
+/**
+ * TextureClient is a thin abstraction over texture data that need to be shared
+ * between the content process and the compositor process. It is the
+ * content-side half of a TextureClient/TextureHost pair. A corresponding
+ * TextureHost lives on the compositor-side.
+ *
+ * TextureClient's primary purpose is to present texture data in a way that is
+ * understood by the IPC system. There are two ways to use it:
+ * - Use it to serialize image data that is not IPC-friendly (most likely
+ * involving a copy into shared memory)
+ * - preallocate it and paint directly into it, which avoids copy but requires
+ * the painting code to be aware of TextureClient (or at least the underlying 
+ * shared memory)
+ *
+ * There is always one and only one TextureClient per TextureHost, and the
+ * TextureClient/Host pair only owns one buffer of image data through its
+ * lifetime. This means that to the lifetime of the underlying shared data
+ * matches the lifetime of the TextureClient/Host pair. It also means
+ * TextureClient/Host do not implement double buffering, which is the
+ * responsibility of the compositable (which would use two Texture pairs).
+ * In order to send several different buffers to the compositor side, use
+ * several TextureClients.
+ */
+class TextureClient : public RefCounted<TextureClient>
+{
+public:
+  TextureClient(TextureFlags aFlags = TEXTURE_FLAGS_DEFAULT);
+  virtual ~TextureClient();
+
+  virtual TextureClientSurface* AsTextureClientSurface() { return nullptr; }
+  virtual TextureClientYCbCr* AsTextureClientYCbCr() { return nullptr; }
+
+  virtual void MarkUnused() {}
+
+  virtual bool Lock(OpenMode aMode)
+  {
+    return true;
+  }
+
+  virtual void Unlock() {}
+
+  void SetID(uint64_t aID)
+  {
+    MOZ_ASSERT(mID == 0 || aID == 0);
+    mID = aID;
+  }
+
+  uint64_t GetID() const
+  {
+    return mID;
+  }
+
+  void SetNextSibling(TextureClient* aNext)
+  {
+    mNextSibling = aNext;
+  }
+
+  TextureClient* GetNextSibling()
+  {
+    return mNextSibling;
+  }
+
+  virtual bool IsAllocated() const = 0;
+
+  virtual bool ToSurfaceDescriptor(SurfaceDescriptor& aDescriptor) = 0;
+
+  void SetFlags(TextureFlags aFlags)
+  {
+    MOZ_ASSERT(!IsSharedWithCompositor());
+    mFlags = aFlags;
+  }
+
+  void AddFlags(TextureFlags  aFlags)
+  {
+    MOZ_ASSERT(!IsSharedWithCompositor());
+    // make sure we don't deallocate on both client and host;
+    MOZ_ASSERT(!(aFlags & TEXTURE_DEALLOCATE_CLIENT && aFlags & TEXTURE_DEALLOCATE_HOST));
+    if (aFlags & TEXTURE_DEALLOCATE_CLIENT) {
+      mFlags &= ~TEXTURE_DEALLOCATE_HOST;
+    } else if (aFlags & TEXTURE_DEALLOCATE_HOST) {
+      mFlags &= ~TEXTURE_DEALLOCATE_CLIENT;
+    }
+    mFlags |= aFlags;
+  }
+
+  void RemoveFlags(TextureFlags  aFlags)
+  {
+    MOZ_ASSERT(!IsSharedWithCompositor());
+    mFlags &= (~aFlags);
+  }
+
+  TextureFlags GetFlags() const { return mFlags; }
+
+  /**
+   * 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.
+   */
+  bool IsImmutable() const { return mFlags & TEXTURE_IMMUTABLE; }
+
+  void MarkImmutable() { AddFlags(TEXTURE_IMMUTABLE); }
+
+  bool IsSharedWithCompositor() const { return GetID() != 0; }
+
+  bool ShouldDeallocateInDestructor() const;
+protected:
+  uint64_t mID;
+  RefPtr<TextureClient> mNextSibling;
+  TextureFlags mFlags;
+};
+
+/**
+ * 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:
+  BufferTextureClient(CompositableClient* aCompositable, gfx::SurfaceFormat aFormat);
+
+  virtual ~BufferTextureClient();
+
+  virtual bool IsAllocated() const = 0;
+
+  virtual bool ToSurfaceDescriptor(SurfaceDescriptor& aDescriptor) = 0;
+
+  virtual bool Allocate(uint32_t aSize) = 0;
+
+  virtual uint8_t* GetBuffer() const = 0;
+
+  virtual size_t GetBufferSize() const = 0;
+
+  // TextureClientSurface
+
+  virtual TextureClientSurface* AsTextureClientSurface() MOZ_OVERRIDE { return this; }
+
+  virtual bool UpdateSurface(gfxASurface* aSurface) MOZ_OVERRIDE;
+
+  virtual bool AllocateForSurface(gfx::IntSize aSize) MOZ_OVERRIDE;
+
+  // TextureClientYCbCr
+
+  virtual TextureClientYCbCr* AsTextureClientYCbCr() MOZ_OVERRIDE { return this; }
+
+  virtual bool UpdateYCbCr(const PlanarYCbCrImage::Data& aData) MOZ_OVERRIDE;
+
+  virtual bool AllocateForYCbCr(gfx::IntSize aYSize, gfx::IntSize aCbCrSize) MOZ_OVERRIDE;
+
+  gfx::SurfaceFormat GetFormat() const { return mFormat; }
+
+protected:
+  CompositableClient* mCompositable;
+  gfx::SurfaceFormat mFormat;
+};
+
+/**
+ * TextureClient that wraps shared memory.
+ * the corresponding texture on the host side is ShmemTextureHost.
+ */
+class ShmemTextureClient : public BufferTextureClient
+{
+public:
+  ShmemTextureClient(CompositableClient* aCompositable, gfx::SurfaceFormat aFormat);
+
+  ~ShmemTextureClient();
+
+  virtual bool ToSurfaceDescriptor(SurfaceDescriptor& aDescriptor) MOZ_OVERRIDE;
+
+  virtual bool Allocate(uint32_t aSize) MOZ_OVERRIDE;
+
+  virtual uint8_t* GetBuffer() const MOZ_OVERRIDE;
+
+  virtual size_t GetBufferSize() const MOZ_OVERRIDE;
+
+  virtual bool IsAllocated() const MOZ_OVERRIDE { return mAllocated; }
+
+  ISurfaceAllocator* GetAllocator() const;
+
+  ipc::Shmem& GetShmem() { return mShmem; }
+
+protected:
+  ipc::Shmem mShmem;
+  ISurfaceAllocator* mAllocator;
+  bool mAllocated;
+};
+
+/**
+ * TextureClient that wraps raw memory.
+ * The corresponding texture on the host side is MemoryTextureHost.
+ * Can obviously not be used in a cross process setup.
+ */
+class MemoryTextureClient : public BufferTextureClient
+{
+public:
+  MemoryTextureClient(CompositableClient* aCompositable, gfx::SurfaceFormat aFormat);
+
+  ~MemoryTextureClient();
+
+  virtual bool ToSurfaceDescriptor(SurfaceDescriptor& aDescriptor) MOZ_OVERRIDE;
+
+  virtual bool Allocate(uint32_t aSize) MOZ_OVERRIDE;
+
+  virtual uint8_t* GetBuffer() const MOZ_OVERRIDE { return mBuffer; }
+
+  virtual size_t GetBufferSize() const MOZ_OVERRIDE { return mBufSize; }
+
+  virtual bool IsAllocated() const MOZ_OVERRIDE { return mBuffer != nullptr; }
+
+protected:
+  uint8_t* mBuffer;
+  size_t mBufSize;
+};
+
+
+struct TextureClientAutoUnlock
+{
+  TextureClient* mTexture;
+
+  TextureClientAutoUnlock(TextureClient* aTexture)
+  : mTexture(aTexture) {}
+
+  ~TextureClientAutoUnlock()
+  {
+    mTexture->Unlock();
+  }
+};
 
 /**
  * XXX - This class is deprecated, will be removed soon.
  *
  * This class allows texture clients to draw into textures through Azure or
  * thebes and applies locking semantics to allow GPU or CPU level
  * synchronization.
  * DeprecatedTextureClient's purpose is for the texture data to be
@@ -180,16 +442,17 @@ private:
   RefPtr<gfx::DrawTarget> mDrawTarget;
 
   gfxASurface::gfxContentType mContentType;
   gfx::IntSize mSize;
 
   friend class CompositingFactory;
 };
 
+// XXX - this class can be removed as soon as we remove DeprecatedImageClientSingle
 class DeprecatedTextureClientShmemYCbCr : public DeprecatedTextureClient
 {
 public:
   DeprecatedTextureClientShmemYCbCr(CompositableForwarder* aForwarder, const TextureInfo& aTextureInfo)
     : DeprecatedTextureClient(aForwarder, aTextureInfo)
   { }
   ~DeprecatedTextureClientShmemYCbCr() { ReleaseResources(); }
 
@@ -232,16 +495,17 @@ private:
   nsRefPtr<gfxReusableSurfaceWrapper> mSurface;
 
   friend class CompositingFactory;
 };
 
 /**
  * Base class for AutoLock*Client.
  * handles lock/unlock
+ * XXX - this can be removed as soon as we remove DeprecatedImageClientSingle
  */
 class AutoLockDeprecatedTextureClient
 {
 public:
   AutoLockDeprecatedTextureClient(DeprecatedTextureClient* aTexture)
   {
     mDeprecatedTextureClient = aTexture;
     mDescriptor = aTexture->LockSurfaceDescriptor();
@@ -258,28 +522,30 @@ public:
   }
 protected:
   DeprecatedTextureClient* mDeprecatedTextureClient;
   SurfaceDescriptor* mDescriptor;
 };
 
 /**
  * Writes the content of a PlanarYCbCrImage into a SurfaceDescriptor.
+ * XXX - this can be removed as soon as we remove DeprecatedImageClientSingle
  */
 class AutoLockYCbCrClient : public AutoLockDeprecatedTextureClient
 {
 public:
   AutoLockYCbCrClient(DeprecatedTextureClient* aTexture) : AutoLockDeprecatedTextureClient(aTexture) {}
   bool Update(PlanarYCbCrImage* aImage);
 protected:
   bool EnsureDeprecatedTextureClient(PlanarYCbCrImage* aImage);
 };
 
 /**
  * Writes the content of a gfxASurface into a SurfaceDescriptor.
+ * XXX - this can be removed as soon as we remove DeprecatedImageClientSingle
  */
 class AutoLockShmemClient : public AutoLockDeprecatedTextureClient
 {
 public:
   AutoLockShmemClient(DeprecatedTextureClient* aTexture) : AutoLockDeprecatedTextureClient(aTexture) {}
   bool Update(Image* aImage, uint32_t aContentFlags, gfxASurface *aSurface);
 };
 
--- a/gfx/layers/composite/CanvasLayerComposite.cpp
+++ b/gfx/layers/composite/CanvasLayerComposite.cpp
@@ -29,17 +29,17 @@ CanvasLayerComposite::CanvasLayerComposi
 CanvasLayerComposite::~CanvasLayerComposite()
 {
   MOZ_COUNT_DTOR(CanvasLayerComposite);
 
   CleanupResources();
 }
 
 void CanvasLayerComposite::SetCompositableHost(CompositableHost* aHost) {
-  mImageHost = static_cast<ImageHost*>(aHost);
+  mImageHost = aHost;
 }
 
 Layer*
 CanvasLayerComposite::GetLayer()
 {
   return this;
 }
 
--- a/gfx/layers/composite/CanvasLayerComposite.h
+++ b/gfx/layers/composite/CanvasLayerComposite.h
@@ -58,14 +58,14 @@ public:
 #ifdef MOZ_LAYERS_HAVE_LOG
   virtual const char* Name() const MOZ_OVERRIDE { return "CanvasLayerComposite"; }
 
 protected:
   virtual nsACString& PrintInfo(nsACString& aTo, const char* aPrefix) MOZ_OVERRIDE;
 #endif
 
 private:
-  RefPtr<ImageHost> mImageHost;
+  RefPtr<CompositableHost> mImageHost;
 };
 
 } /* layers */
 } /* mozilla */
 #endif /* GFX_CanvasLayerComposite_H */
--- a/gfx/layers/composite/CompositableHost.cpp
+++ b/gfx/layers/composite/CompositableHost.cpp
@@ -4,20 +4,91 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "CompositableHost.h"
 #include "ImageHost.h"
 #include "ContentHost.h"
 #include "TiledContentHost.h"
 #include "Effects.h"
 #include "mozilla/layers/CompositableTransactionParent.h"
+#include "mozilla/layers/TextureHost.h"
 
 namespace mozilla {
 namespace layers {
 
+CompositableHost::CompositableHost(const TextureInfo& aTextureInfo)
+  : mTextureInfo(aTextureInfo)
+  , mCompositor(nullptr)
+  , mLayer(nullptr)
+{
+  MOZ_COUNT_CTOR(CompositableHost);
+}
+
+CompositableHost::~CompositableHost()
+{
+  MOZ_COUNT_DTOR(CompositableHost);
+
+  RefPtr<TextureHost> it = mFirstTexture;
+  while (it) {
+    if (it->GetFlags() & TEXTURE_DEALLOCATE_HOST) {
+      it->DeallocateSharedData();
+    }
+    it = it->GetNextSibling();
+  }
+}
+
+void
+CompositableHost::AddTextureHost(TextureHost* aTexture)
+{
+  MOZ_ASSERT(aTexture);
+  MOZ_ASSERT(GetTextureHost(aTexture->GetID()) == nullptr,
+             "A texture is already present with this ID");
+  RefPtr<TextureHost> second = mFirstTexture;
+  mFirstTexture = aTexture;
+  aTexture->SetNextSibling(second);
+}
+
+void
+CompositableHost::RemoveTextureHost(uint64_t aTextureID)
+{
+  RefPtr<TextureHost> it = mFirstTexture;
+  while (it) {
+    if (it->GetNextSibling() &&
+        it->GetNextSibling()->GetID() == aTextureID) {
+      it->SetNextSibling(it->GetNextSibling()->GetNextSibling());
+    }
+    it = it->GetNextSibling();
+  }
+}
+
+TextureHost*
+CompositableHost::GetTextureHost(uint64_t aTextureID)
+{
+  RefPtr<TextureHost> it = mFirstTexture;
+  while (it) {
+    if (it->GetID() == aTextureID) {
+      return it;
+    }
+    it = it->GetNextSibling();
+  }
+  return nullptr;
+}
+
+
+void
+CompositableHost::SetCompositor(Compositor* aCompositor)
+{
+  mCompositor = aCompositor;
+  RefPtr<TextureHost> it = mFirstTexture;
+  while (!!it) {
+    it->SetCompositor(aCompositor);
+    it = it->GetNextSibling();
+  }
+}
+
 bool
 CompositableHost::Update(const SurfaceDescriptor& aImage,
                          SurfaceDescriptor* aResult)
 {
   if (!GetDeprecatedTextureHost()) {
     *aResult = aImage;
     return false;
   }
@@ -48,16 +119,19 @@ CompositableHost::AddMaskEffect(EffectCh
   return true;
 }
 
 /* static */ TemporaryRef<CompositableHost>
 CompositableHost::Create(const TextureInfo& aTextureInfo)
 {
   RefPtr<CompositableHost> result;
   switch (aTextureInfo.mCompositableType) {
+  case COMPOSITABLE_IMAGE:
+    result = new ImageHost(aTextureInfo);
+    return result;
   case BUFFER_IMAGE_BUFFERED:
     result = new DeprecatedImageHostBuffered(aTextureInfo);
     return result;
   case BUFFER_IMAGE_SINGLE:
     result = new DeprecatedImageHostSingle(aTextureInfo);
     return result;
   case BUFFER_TILED:
     result = new TiledContentHost(aTextureInfo);
@@ -85,16 +159,29 @@ CompositableHost::DumpDeprecatedTextureH
   nsRefPtr<gfxImageSurface> surf = aTexture->GetAsSurface();
   if (!surf) {
     return;
   }
   surf->DumpAsDataURL(aFile ? aFile : stderr);
 }
 
 void
+CompositableHost::DumpTextureHost(FILE* aFile, TextureHost* aTexture)
+{
+  if (!aTexture) {
+    return;
+  }
+  nsRefPtr<gfxImageSurface> surf = aTexture->GetAsSurface();
+  if (!surf) {
+    return;
+  }
+  surf->DumpAsDataURL(aFile ? aFile : stderr);
+}
+
+void
 CompositableParent::ActorDestroy(ActorDestroyReason why)
 {
   if (mHost) {
     mHost->Detach();
   }
 }
 
 CompositableParent::CompositableParent(CompositableParentManager* aMgr,
--- a/gfx/layers/composite/CompositableHost.h
+++ b/gfx/layers/composite/CompositableHost.h
@@ -24,16 +24,17 @@ struct TiledLayerProperties
   gfxRect mDisplayPort;
   gfxSize mEffectiveResolution;
   gfxRect mCompositionBounds;
   bool mRetainTiles;
 };
 
 class Layer;
 class DeprecatedTextureHost;
+class TextureHost;
 class SurfaceDescriptor;
 
 /**
  * The compositor-side counterpart to CompositableClient. Responsible for
  * updating textures and data about textures from IPC and how textures are
  * composited (tiling, double buffering, etc.).
  *
  * Update (for images/canvases) and UpdateThebes (for Thebes) are called during
@@ -43,37 +44,26 @@ class SurfaceDescriptor;
  *
  * Composite is called by the owning layer when it is composited. CompositableHost
  * will use its TextureHost(s) and call Compositor::DrawQuad to do the actual
  * rendering.
  */
 class CompositableHost : public RefCounted<CompositableHost>
 {
 public:
-  CompositableHost(const TextureInfo& aTextureInfo)
-    : mTextureInfo(aTextureInfo)
-    , mCompositor(nullptr)
-    , mLayer(nullptr)
-  {
-    MOZ_COUNT_CTOR(CompositableHost);
-  }
+  CompositableHost(const TextureInfo& aTextureInfo);
 
-  virtual ~CompositableHost()
-  {
-    MOZ_COUNT_DTOR(CompositableHost);
-  }
+  virtual ~CompositableHost();
 
   static TemporaryRef<CompositableHost> Create(const TextureInfo& aTextureInfo);
 
   virtual CompositableType GetType() = 0;
 
-  virtual void SetCompositor(Compositor* aCompositor)
-  {
-    mCompositor = aCompositor;
-  }
+  // 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,
                          const gfx::Point& aOffset,
                          const gfx::Filter& aFilter,
                          const gfx::Rect& aClipRect,
@@ -134,17 +124,20 @@ public:
    * descriptor. Whether it is necessary or not depends on the protocol between
    * the compositable client and host.
    * aAllocator - the allocator used to allocate and de-allocate resources.
    * aTextureInfo - contains flags for the texture.
    */
   virtual void EnsureDeprecatedTextureHost(TextureIdentifier aTextureId,
                                  const SurfaceDescriptor& aSurface,
                                  ISurfaceAllocator* aAllocator,
-                                 const TextureInfo& aTextureInfo) = 0;
+                                 const TextureInfo& aTextureInfo)
+  {
+    MOZ_ASSERT(false, "should be implemented or not used");
+  }
 
   /**
    * Ensure that a suitable texture host exists in this compsitable.
    *
    * Only used with ContentHostIncremental.
    *
    * No SurfaceDescriptor or TextureIdentifier is provider as we
    * don't have a single surface for the texture contents, and we
@@ -154,16 +147,21 @@ public:
                                             const TextureInfo& aTextureInfo,
                                             const nsIntRect& aBufferRect)
   {
     MOZ_ASSERT(false, "should be implemented or not used");
   }
 
   virtual DeprecatedTextureHost* GetDeprecatedTextureHost() { return nullptr; }
 
+  /**
+   * Returns the front buffer.
+   */
+  virtual TextureHost* GetTextureHost() { return nullptr; }
+
   virtual LayerRenderState GetRenderState() = 0;
 
   virtual void SetPictureRect(const nsIntRect& aPictureRect)
   {
     MOZ_ASSERT(false, "Should have been overridden");
   }
 
   /**
@@ -194,29 +192,36 @@ public:
     SetLayer(nullptr);
     SetCompositor(nullptr);
   }
 
   virtual void Dump(FILE* aFile=nullptr,
                     const char* aPrefix="",
                     bool aDumpHtml=false) { }
   static void DumpDeprecatedTextureHost(FILE* aFile, DeprecatedTextureHost* aTexture);
+  static void DumpTextureHost(FILE* aFile, TextureHost* aTexture);
 
 #ifdef MOZ_DUMP_PAINTING
   virtual already_AddRefed<gfxImageSurface> GetAsSurface() { return nullptr; }
 #endif
 
 #ifdef MOZ_LAYERS_HAVE_LOG
   virtual void PrintInfo(nsACString& aTo, const char* aPrefix) { }
 #endif
 
+  void AddTextureHost(TextureHost* aTexture);
+  virtual void UseTextureHost(TextureHost* aTexture) {}
+  void RemoveTextureHost(uint64_t aTextureID);
+  TextureHost* GetTextureHost(uint64_t aTextureID);
+
 protected:
   TextureInfo mTextureInfo;
   Compositor* mCompositor;
   Layer* mLayer;
+  RefPtr<TextureHost> mFirstTexture;
 };
 
 class CompositableParentManager;
 
 class CompositableParent : public PCompositableParent
 {
 public:
   CompositableParent(CompositableParentManager* aMgr,
--- a/gfx/layers/composite/ContentHost.cpp
+++ b/gfx/layers/composite/ContentHost.cpp
@@ -753,10 +753,31 @@ ContentHostDoubleBuffered::Dump(FILE* aF
     fprintf(aFile, aDumpHtml ? " >Back buffer on white</a> </li>" : " ");
   }
   if (aDumpHtml) {
     fprintf(aFile, "</ul>");
   }
 
 }
 
+LayerRenderState
+ContentHostBase::GetRenderState()
+{
+  LayerRenderState result = mDeprecatedTextureHost->GetRenderState();
+
+  if (mBufferRotation != nsIntPoint()) {
+    result.mFlags |= LAYER_RENDER_STATE_BUFFER_ROTATION;
+  }
+  result.SetOffset(GetOriginOffset());
+  return result;
+}
+
+#ifdef MOZ_DUMP_PAINTING
+already_AddRefed<gfxImageSurface>
+ContentHostBase::GetAsSurface()
+{
+  return mDeprecatedTextureHost->GetAsSurface();
+}
+#endif
+
+
 } // namespace
 } // namespace
--- a/gfx/layers/composite/ContentHost.h
+++ b/gfx/layers/composite/ContentHost.h
@@ -72,34 +72,22 @@ public:
                          TiledLayerProperties* aLayerProperties = nullptr);
 
   virtual PaintState BeginPaint(ContentType, uint32_t)
   {
     NS_RUNTIMEABORT("shouldn't BeginPaint for a shadow layer");
     return PaintState();
   }
 
-  virtual LayerRenderState GetRenderState() MOZ_OVERRIDE
-  {
-    LayerRenderState result = mDeprecatedTextureHost->GetRenderState();
-
-    if (mBufferRotation != nsIntPoint()) {
-      result.mFlags |= LAYER_RENDER_STATE_BUFFER_ROTATION;
-    }
-    result.SetOffset(GetOriginOffset());
-    return result;
-  }
+  virtual LayerRenderState GetRenderState() MOZ_OVERRIDE;
 
   virtual void SetCompositor(Compositor* aCompositor) MOZ_OVERRIDE;
 
 #ifdef MOZ_DUMP_PAINTING
-  virtual already_AddRefed<gfxImageSurface> GetAsSurface()
-  {
-    return mDeprecatedTextureHost->GetAsSurface();
-  }
+  virtual already_AddRefed<gfxImageSurface> GetAsSurface();
 #endif
 
   virtual void Dump(FILE* aFile=nullptr,
                     const char* aPrefix="",
                     bool aDumpHtml=false) MOZ_OVERRIDE;
 
   virtual DeprecatedTextureHost* GetDeprecatedTextureHost() MOZ_OVERRIDE;
 
--- a/gfx/layers/composite/ImageHost.cpp
+++ b/gfx/layers/composite/ImageHost.cpp
@@ -11,16 +11,159 @@
 #include "nsPrintfCString.h"
 
 namespace mozilla {
 
 using namespace gfx;
 
 namespace layers {
 
+ImageHost::ImageHost(const TextureInfo& aTextureInfo)
+  : CompositableHost(aTextureInfo)
+  , mFrontBuffer(nullptr)
+  , mHasPictureRect(false)
+{}
+
+ImageHost::~ImageHost() {}
+
+void
+ImageHost::UseTextureHost(TextureHost* aTexture)
+{
+  mFrontBuffer = aTexture;
+}
+
+TextureHost*
+ImageHost::GetTextureHost()
+{
+  return mFrontBuffer;
+}
+
+void
+ImageHost::Composite(EffectChain& aEffectChain,
+                     float aOpacity,
+                     const gfx::Matrix4x4& aTransform,
+                     const gfx::Point& aOffset,
+                     const gfx::Filter& aFilter,
+                     const gfx::Rect& aClipRect,
+                     const nsIntRegion* aVisibleRegion,
+                     TiledLayerProperties* aLayerProperties)
+{
+  if (!GetCompositor()) {
+    // should only happen when a tab is dragged to another window and
+    // async-video is still sending frames but we haven't attached the
+    // set the new compositor yet.
+    return;
+  }
+  if (!mFrontBuffer) {
+    return;
+  }
+  if (!mFrontBuffer->Lock()) {
+    NS_WARNING("failed to lock front buffer");
+    return;
+  }
+  RefPtr<NewTextureSource> source = mFrontBuffer->GetTextureSources();
+  if (!source) {
+    return;
+  }
+  RefPtr<TexturedEffect> effect = CreateTexturedEffect(mFrontBuffer->GetFormat(),
+                                                       source,
+                                                       aFilter);
+  aEffectChain.mPrimaryEffect = effect;
+  TileIterator* it = source->AsTileIterator();
+  if (it) {
+    it->BeginTileIteration();
+    do {
+      nsIntRect tileRect = it->GetTileRect();
+      gfx::Rect rect(tileRect.x, tileRect.y, tileRect.width, tileRect.height);
+      GetCompositor()->DrawQuad(rect, aClipRect, aEffectChain,
+                                aOpacity, aTransform, aOffset);
+      GetCompositor()->DrawDiagnostics(gfx::Color(0.5,0.0,0.0,1.0),
+                                       rect, aClipRect, aTransform, aOffset);
+    } while (it->NextTile());
+    it->EndTileIteration();
+  } else {
+    IntSize textureSize = source->GetSize();
+    gfx::Rect rect(0, 0,
+                   mPictureRect.width,
+                   mPictureRect.height);
+    if (mHasPictureRect) {
+      effect->mTextureCoords = Rect(Float(mPictureRect.x) / textureSize.width,
+                                    Float(mPictureRect.y) / textureSize.height,
+                                    Float(mPictureRect.width) / textureSize.width,
+                                    Float(mPictureRect.height) / textureSize.height);
+    } else {
+      effect->mTextureCoords = Rect(0, 0, 1, 1);
+      rect = gfx::Rect(0, 0, textureSize.width, textureSize.height);
+    }
+
+    if (mFrontBuffer->GetFlags() & NeedsYFlip) {
+      effect->mTextureCoords.y = effect->mTextureCoords.YMost();
+      effect->mTextureCoords.height = -effect->mTextureCoords.height;
+    }
+
+    GetCompositor()->DrawQuad(rect, aClipRect, aEffectChain,
+                              aOpacity, aTransform, aOffset);
+    GetCompositor()->DrawDiagnostics(gfx::Color(1.0,0.1,0.1,1.0),
+                                     rect, aClipRect, aTransform, aOffset);
+  }
+  mFrontBuffer->Unlock();
+}
+
+#ifdef MOZ_LAYERS_HAVE_LOG
+void
+ImageHost::PrintInfo(nsACString& aTo, const char* aPrefix)
+{
+  aTo += aPrefix;
+  aTo += nsPrintfCString("ImageHost (0x%p)", this);
+
+  AppendToString(aTo, mPictureRect, " [picture-rect=", "]");
+
+  if (mFrontBuffer) {
+    nsAutoCString pfx(aPrefix);
+    pfx += "  ";
+    aTo += "\n";
+    mFrontBuffer->PrintInfo(aTo, pfx.get());
+  }
+}
+#endif
+
+void
+ImageHost::Dump(FILE* aFile,
+                const char* aPrefix,
+                bool aDumpHtml)
+{
+  if (!aFile) {
+    aFile = stderr;
+  }
+  if (mFrontBuffer) {
+    fprintf(aFile, "%s", aPrefix);
+    fprintf(aFile, aDumpHtml ? "<ul><li>TextureHost: "
+                             : "TextureHost: ");
+    DumpTextureHost(aFile, mFrontBuffer);
+    fprintf(aFile, aDumpHtml ? " </li></ul> " : " ");
+  }
+}
+
+LayerRenderState
+ImageHost::GetRenderState()
+{
+  if (mFrontBuffer) {
+    return mFrontBuffer->GetRenderState();
+  }
+  return LayerRenderState();
+}
+
+#ifdef MOZ_DUMP_PAINTING
+already_AddRefed<gfxImageSurface>
+ImageHost::GetAsSurface()
+{
+  return mFrontBuffer->GetAsSurface();
+}
+#endif
+
 void
 DeprecatedImageHostSingle::SetCompositor(Compositor* aCompositor) {
   CompositableHost::SetCompositor(aCompositor);
   if (mDeprecatedTextureHost) {
     mDeprecatedTextureHost->SetCompositor(aCompositor);
   }
 }
 
@@ -55,16 +198,25 @@ DeprecatedImageHostSingle::MakeDeprecate
   NS_ASSERTION(mDeprecatedTextureHost, "Failed to create texture host");
 
   Compositor* compositor = GetCompositor();
   if (compositor && mDeprecatedTextureHost) {
     mDeprecatedTextureHost->SetCompositor(compositor);
   }
 }
 
+LayerRenderState
+DeprecatedImageHostSingle::GetRenderState()
+{
+  if (mDeprecatedTextureHost) {
+    return mDeprecatedTextureHost->GetRenderState();
+  }
+  return LayerRenderState();
+}
+
 void
 DeprecatedImageHostSingle::Composite(EffectChain& aEffectChain,
                                      float aOpacity,
                                      const gfx::Matrix4x4& aTransform,
                                      const gfx::Point& aOffset,
                                      const gfx::Filter& aFilter,
                                      const gfx::Rect& aClipRect,
                                      const nsIntRegion* aVisibleRegion,
@@ -192,10 +344,19 @@ DeprecatedImageHostSingle::Dump(FILE* aF
     fprintf(aFile, "%s", aPrefix);
     fprintf(aFile, aDumpHtml ? "<ul><li>DeprecatedTextureHost: "
                              : "DeprecatedTextureHost: ");
     DumpDeprecatedTextureHost(aFile, mDeprecatedTextureHost);
     fprintf(aFile, aDumpHtml ? " </li></ul> " : " ");
   }
 }
 
+#ifdef MOZ_DUMP_PAINTING
+already_AddRefed<gfxImageSurface>
+DeprecatedImageHostSingle::GetAsSurface()
+{
+  return mDeprecatedTextureHost->GetAsSurface();
+}
+#endif
+
+
 }
 }
--- a/gfx/layers/composite/ImageHost.h
+++ b/gfx/layers/composite/ImageHost.h
@@ -7,46 +7,75 @@
 #define MOZILLA_GFX_IMAGEHOST_H
 
 #include "CompositableHost.h"
 #include "mozilla/layers/LayerManagerComposite.h"
 
 namespace mozilla {
 namespace layers {
 
+class TextureHost;
+
 /**
- * Used for compositing Image and Canvas layers, matched on the content-side
- * by an ImageClient or CanvasClient.
- *
- * ImageHosts support Update., not UpdateThebes().
+ * ImageHost. Works with ImageClientSingle and ImageClientBuffered
  */
 class ImageHost : public CompositableHost
 {
 public:
-  DeprecatedTextureHost* GetDeprecatedTextureHost() MOZ_OVERRIDE { return nullptr; }
+  ImageHost(const TextureInfo& aTextureInfo);
+  ~ImageHost();
+
+  virtual CompositableType GetType() { return mTextureInfo.mCompositableType; }
+
+  virtual void Composite(EffectChain& aEffectChain,
+                         float aOpacity,
+                         const gfx::Matrix4x4& aTransform,
+                         const gfx::Point& aOffset,
+                         const gfx::Filter& aFilter,
+                         const gfx::Rect& aClipRect,
+                         const nsIntRegion* aVisibleRegion = nullptr,
+                         TiledLayerProperties* aLayerProperties = nullptr);
+
+  virtual void UseTextureHost(TextureHost* aTexture) MOZ_OVERRIDE;
+
+  virtual TextureHost* GetTextureHost() MOZ_OVERRIDE;
+
+  virtual void SetPictureRect(const nsIntRect& aPictureRect) MOZ_OVERRIDE
+  {
+    mPictureRect = aPictureRect;
+    mHasPictureRect = true;
+  }
+
+  virtual LayerRenderState GetRenderState() MOZ_OVERRIDE;
+
+  virtual void Dump(FILE* aFile=NULL,
+                    const char* aPrefix="",
+                    bool aDumpHtml=false) MOZ_OVERRIDE;
+
+#ifdef MOZ_LAYERS_HAVE_LOG
+  virtual void PrintInfo(nsACString& aTo, const char* aPrefix);
+#endif
+
+#ifdef MOZ_DUMP_PAINTING
+  virtual already_AddRefed<gfxImageSurface> GetAsSurface() MOZ_OVERRIDE;
+#endif
 
 protected:
-  ImageHost(const TextureInfo& aTextureInfo)
-  : CompositableHost(aTextureInfo)
-  {
-    MOZ_COUNT_CTOR(ImageHost);
-  }
 
-  ~ImageHost()
-  {
-    MOZ_COUNT_DTOR(ImageHost);
-  }
+  RefPtr<TextureHost> mFrontBuffer;
+  nsIntRect mPictureRect;
+  bool mHasPictureRect;
 };
 
 // ImageHost with a single DeprecatedTextureHost
-class DeprecatedImageHostSingle : public ImageHost
+class DeprecatedImageHostSingle : public CompositableHost
 {
 public:
   DeprecatedImageHostSingle(const TextureInfo& aTextureInfo)
-    : ImageHost(aTextureInfo)
+    : CompositableHost(aTextureInfo)
     , mDeprecatedTextureHost(nullptr)
     , mHasPictureRect(false)
   {}
 
   virtual CompositableType GetType() { return mTextureInfo.mCompositableType; }
 
   virtual void EnsureDeprecatedTextureHost(TextureIdentifier aTextureId,
                                  const SurfaceDescriptor& aSurface,
@@ -62,48 +91,39 @@ public:
                          const gfx::Filter& aFilter,
                          const gfx::Rect& aClipRect,
                          const nsIntRegion* aVisibleRegion = nullptr,
                          TiledLayerProperties* aLayerProperties = nullptr);
 
   virtual bool Update(const SurfaceDescriptor& aImage,
                       SurfaceDescriptor* aResult = nullptr) MOZ_OVERRIDE
   {
-    return ImageHost::Update(aImage, aResult);
+    return CompositableHost::Update(aImage, aResult);
   }
 
   virtual void SetPictureRect(const nsIntRect& aPictureRect) MOZ_OVERRIDE
   {
     mPictureRect = aPictureRect;
     mHasPictureRect = true;
   }
 
-  virtual LayerRenderState GetRenderState() MOZ_OVERRIDE
-  {
-    if (mDeprecatedTextureHost) {
-      return mDeprecatedTextureHost->GetRenderState();
-    }
-    return LayerRenderState();
-  }
+  virtual LayerRenderState GetRenderState() MOZ_OVERRIDE;
 
   virtual void SetCompositor(Compositor* aCompositor) MOZ_OVERRIDE;
 
   virtual void Dump(FILE* aFile=nullptr,
                     const char* aPrefix="",
                     bool aDumpHtml=false) MOZ_OVERRIDE;
 
 #ifdef MOZ_LAYERS_HAVE_LOG
   virtual void PrintInfo(nsACString& aTo, const char* aPrefix);
 #endif
 
 #ifdef MOZ_DUMP_PAINTING
-  virtual already_AddRefed<gfxImageSurface> GetAsSurface() MOZ_OVERRIDE
-  {
-    return mDeprecatedTextureHost->GetAsSurface();
-  }
+  virtual already_AddRefed<gfxImageSurface> GetAsSurface() MOZ_OVERRIDE;
 #endif
 
 protected:
   virtual void MakeDeprecatedTextureHost(TextureIdentifier aTextureId,
                                const SurfaceDescriptor& aSurface,
                                ISurfaceAllocator* aAllocator,
                                const TextureInfo& aTextureInfo);
 
--- a/gfx/layers/composite/ImageLayerComposite.cpp
+++ b/gfx/layers/composite/ImageLayerComposite.cpp
@@ -37,17 +37,17 @@ ImageLayerComposite::~ImageLayerComposit
   MOZ_ASSERT(mDestroyed);
 
   CleanupResources();
 }
 
 void
 ImageLayerComposite::SetCompositableHost(CompositableHost* aHost)
 {
-  mImageHost = static_cast<ImageHost*>(aHost);
+  mImageHost = aHost;
 }
 
 void
 ImageLayerComposite::Disconnect()
 {
   Destroy();
 }
 
@@ -100,18 +100,21 @@ ImageLayerComposite::RenderLayer(const n
 
 void 
 ImageLayerComposite::ComputeEffectiveTransforms(const gfx3DMatrix& aTransformToSurface)
 {
   gfx3DMatrix local = GetLocalTransform();
 
   // Snap image edges to pixel boundaries
   gfxRect sourceRect(0, 0, 0, 0);
-  if (mImageHost && mImageHost->GetDeprecatedTextureHost()) {
-    IntSize size = mImageHost->GetDeprecatedTextureHost()->GetSize();
+  if (mImageHost &&
+    (mImageHost->GetDeprecatedTextureHost() || mImageHost->GetTextureHost())) {
+    IntSize size =
+      mImageHost->GetTextureHost() ? mImageHost->GetTextureHost()->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/ImageLayerComposite.h
+++ b/gfx/layers/composite/ImageLayerComposite.h
@@ -50,15 +50,15 @@ public:
 #ifdef MOZ_LAYERS_HAVE_LOG
   virtual const char* Name() const { return "ImageLayerComposite"; }
 
 protected:
   virtual nsACString& PrintInfo(nsACString& aTo, const char* aPrefix) MOZ_OVERRIDE;
 #endif
 
 private:
-  RefPtr<ImageHost> mImageHost;
+  RefPtr<CompositableHost> mImageHost;
 };
 
 } /* layers */
 } /* mozilla */
 
 #endif /* GFX_ImageLayerComposite_H */
--- a/gfx/layers/composite/TextureHost.cpp
+++ b/gfx/layers/composite/TextureHost.cpp
@@ -2,16 +2,23 @@
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/layers/TextureHost.h"
 #include "mozilla/layers/LayersSurfaces.h"
 #include "LayersLogging.h"
 #include "nsPrintfCString.h"
+#include "mozilla/ipc/Shmem.h"
+#include "ipc/AutoOpenSurface.h"
+#include "mozilla/layers/ImageDataSerializer.h"
+#include "mozilla/layers/YCbCrImageDataSerializer.h"
+#include "gfx2DGlue.h"
+#include "mozilla/gfx/2D.h"
+
 
 namespace mozilla {
 namespace layers {
 
 // implemented in TextureOGL.cpp
 TemporaryRef<DeprecatedTextureHost> CreateDeprecatedTextureHostOGL(SurfaceDescriptorType aDescriptorType,
                                                            uint32_t aDeprecatedTextureHostFlags,
                                                            uint32_t aTextureFlags);
@@ -58,30 +65,93 @@ DeprecatedTextureHost::CreateDeprecatedT
       return CreateBasicDeprecatedTextureHost(aDescriptorType,
                                           aDeprecatedTextureHostFlags,
                                           aTextureFlags);
     default:
       MOZ_CRASH("Couldn't create texture host");
   }
 }
 
+// implemented in TextureOGL.cpp
+TemporaryRef<TextureHost> CreateTextureHostOGL(uint64_t aID,
+                                               const SurfaceDescriptor& aDesc,
+                                               ISurfaceAllocator* aDeallocator,
+                                               TextureFlags aFlags);
+
+// static
+TemporaryRef<TextureHost>
+TextureHost::Create(uint64_t aID,
+                    const SurfaceDescriptor& aDesc,
+                    ISurfaceAllocator* aDeallocator,
+                    TextureFlags aFlags)
+{
+  switch (Compositor::GetBackend()) {
+    case LAYERS_OPENGL:
+      return CreateTextureHostOGL(aID, aDesc, aDeallocator, aFlags);
+    case LAYERS_BASIC:
+      return CreateBackendIndependentTextureHost(aID,
+                                                 aDesc,
+                                                 aDeallocator,
+                                                 aFlags);
+#ifdef XP_WIN
+    case LAYERS_D3D11:
+    case LAYERS_D3D9:
+      // XXX - not implemented yet
+#endif
+    default:
+      MOZ_CRASH("Couldn't create texture host");
+      return nullptr;
+  }
+}
+
+TemporaryRef<TextureHost>
+CreateBackendIndependentTextureHost(uint64_t aID,
+                                    const SurfaceDescriptor& aDesc,
+                                    ISurfaceAllocator* aDeallocator,
+                                    TextureFlags aFlags)
+{
+  RefPtr<TextureHost> result;
+  switch (aDesc.type()) {
+    case SurfaceDescriptor::TSurfaceDescriptorShmem: {
+      const SurfaceDescriptorShmem& descriptor = aDesc.get_SurfaceDescriptorShmem();
+      result = new ShmemTextureHost(aID,
+                                    descriptor.data(),
+                                    descriptor.format(),
+                                    aDeallocator,
+                                    aFlags);
+      break;
+    }
+    case SurfaceDescriptor::TSurfaceDescriptorMemory: {
+      const SurfaceDescriptorMemory& descriptor = aDesc.get_SurfaceDescriptorMemory();
+      result = new MemoryTextureHost(aID,
+                                     reinterpret_cast<uint8_t*>(descriptor.data()),
+                                     descriptor.format(),
+                                     aFlags);
+      break;
+    }
+    default: {
+      NS_WARNING("No backend independent TextureHost for this descriptor type");
+    }
+  }
+  return result;
+}
 
 DeprecatedTextureHost::DeprecatedTextureHost()
   : mFlags(0)
   , mBuffer(nullptr)
+  , mDeAllocator(nullptr)
   , mFormat(gfx::FORMAT_UNKNOWN)
-  , mDeAllocator(nullptr)
 {
   MOZ_COUNT_CTOR(DeprecatedTextureHost);
 }
 
 DeprecatedTextureHost::~DeprecatedTextureHost()
 {
   if (mBuffer) {
-    if (!(mFlags & OwnByClient)) {
+    if (!(mFlags & TEXTURE_DEALLOCATE_CLIENT)) {
       if (mDeAllocator) {
         mDeAllocator->DestroySharedSurface(mBuffer);
       } else {
         MOZ_ASSERT(mBuffer->type() == SurfaceDescriptor::Tnull_t);
       }
     }
     delete mBuffer;
   }
@@ -125,10 +195,277 @@ DeprecatedTextureHost::PrintInfo(nsACStr
   aTo += nsPrintfCString("%s (0x%p)", Name(), this);
   AppendToString(aTo, GetSize(), " [size=", "]");
   AppendToString(aTo, GetFormat(), " [format=", "]");
   AppendToString(aTo, mFlags, " [flags=", "]");
 }
 #endif // MOZ_LAYERS_HAVE_LOG
 
 
+
+
+
+
+
+BufferTextureHost::BufferTextureHost(uint64_t aID,
+                                     gfx::SurfaceFormat aFormat,
+                                     TextureFlags aFlags)
+: TextureHost(aID, aFlags)
+, mCompositor(nullptr)
+, mFormat(aFormat)
+, mUpdateSerial(1)
+, mLocked(false)
+, mPartialUpdate(false)
+{}
+
+BufferTextureHost::~BufferTextureHost()
+{}
+
+void
+BufferTextureHost::Updated(const nsIntRegion* aRegion)
+{
+  ++mUpdateSerial;
+  if (aRegion) {
+    mPartialUpdate = true;
+    mMaybeUpdatedRegion = *aRegion;
+  } else {
+    mPartialUpdate = false;
+  }
+}
+
+void
+BufferTextureHost::SetCompositor(Compositor* aCompositor)
+{
+  if (mCompositor == aCompositor) {
+    return;
+  }
+  DeallocateDeviceData();
+  mCompositor = aCompositor;
+}
+
+void
+BufferTextureHost::DeallocateDeviceData()
+{
+  RefPtr<NewTextureSource> it = mFirstSource;
+  while (it) {
+    it->DeallocateDeviceData();
+    it = it->GetNextSibling();
+  }
+}
+
+bool
+BufferTextureHost::Lock()
+{
+  mLocked = true;
+  return true;
+}
+
+void
+BufferTextureHost::Unlock()
+{
+  mLocked = false;
+}
+
+NewTextureSource*
+BufferTextureHost::GetTextureSources()
+{
+  MOZ_ASSERT(mLocked, "should never be called while not locked");
+  if (!mFirstSource || mUpdateSerial != mFirstSource->GetUpdateSerial()) {
+    if (!Upload(mPartialUpdate ? &mMaybeUpdatedRegion : nullptr)) {
+      return nullptr;
+    }
+    mFirstSource->SetUpdateSerial(mUpdateSerial);
+  }
+  return mFirstSource;
+}
+
+gfx::SurfaceFormat
+BufferTextureHost::GetFormat() const
+{
+  // mFormat is the format of the data that we share with the content process.
+  // GetFormat, on the other hand, expects the format that we present to the
+  // Compositor (it is used to choose the effect type).
+  // if the compositor does not support YCbCr effects, we give it a RGBX texture
+  // instead (see BufferTextureHost::Upload)
+  if (mFormat == gfx::FORMAT_YUV &&
+    mCompositor &&
+    !mCompositor->SupportsEffect(EFFECT_YCBCR)) {
+    return gfx::FORMAT_R8G8B8X8;
+  }
+  return mFormat;
+}
+
+bool
+BufferTextureHost::Upload(nsIntRegion *aRegion)
+{
+  if (mFormat == gfx::FORMAT_UNKNOWN) {
+    NS_WARNING("BufferTextureHost: unsupported format!");
+    return false;
+  } else if (mFormat == gfx::FORMAT_YUV) {
+    YCbCrImageDataDeserializer yuvDeserializer(GetBuffer());
+    MOZ_ASSERT(yuvDeserializer.IsValid());
+
+    if (!mCompositor->SupportsEffect(EFFECT_YCBCR)) {
+      RefPtr<gfx::DataSourceSurface> surf = yuvDeserializer.ToDataSourceSurface();
+      if (!mFirstSource) {
+        mFirstSource = mCompositor->CreateDataTextureSource(mFlags);
+      }
+      mFirstSource->Update(surf, mFlags, aRegion);
+      return true;
+    }
+
+    RefPtr<DataTextureSource> srcY;
+    RefPtr<DataTextureSource> srcU;
+    RefPtr<DataTextureSource> srcV;
+    if (!mFirstSource) {
+      srcY = mCompositor->CreateDataTextureSource(mFlags);
+      srcU = mCompositor->CreateDataTextureSource(mFlags);
+      srcV = mCompositor->CreateDataTextureSource(mFlags);
+      mFirstSource = srcY;
+      srcY->SetNextSibling(srcU);
+      srcU->SetNextSibling(srcV);
+    } else {
+      // mFormat never changes so if this was created as a YCbCr host and already
+      // contains a source it should already have 3 sources.
+      // BufferTextureHost only uses DataTextureSources so it is safe to assume
+      // all 3 sources are DataTextureSource.
+      MOZ_ASSERT(mFirstSource->GetNextSibling());
+      MOZ_ASSERT(mFirstSource->GetNextSibling()->GetNextSibling());
+      srcY = mFirstSource;
+      srcU = mFirstSource->GetNextSibling()->AsDataTextureSource();
+      srcV = mFirstSource->GetNextSibling()->GetNextSibling()->AsDataTextureSource();
+    }
+
+
+    RefPtr<gfx::DataSourceSurface> tempY =
+      gfx::Factory::CreateWrappingDataSourceSurface(yuvDeserializer.GetYData(),
+                                                    yuvDeserializer.GetYStride(),
+                                                    gfx::ToIntSize(yuvDeserializer.GetYSize()),
+                                                    gfx::FORMAT_A8);
+    RefPtr<gfx::DataSourceSurface> tempCb =
+      gfx::Factory::CreateWrappingDataSourceSurface(yuvDeserializer.GetCbData(),
+                                                    yuvDeserializer.GetCbCrStride(),
+                                                    gfx::ToIntSize(yuvDeserializer.GetCbCrSize()),
+                                                    gfx::FORMAT_A8);
+    RefPtr<gfx::DataSourceSurface> tempCr =
+      gfx::Factory::CreateWrappingDataSourceSurface(yuvDeserializer.GetCrData(),
+                                                    yuvDeserializer.GetCbCrStride(),
+                                                    gfx::ToIntSize(yuvDeserializer.GetCbCrSize()),
+                                                    gfx::FORMAT_A8);
+    // We don't support partial updates for Y U V textures
+    NS_ASSERTION(!aRegion, "Unsupported partial updates for YCbCr textures");
+    if (!srcY->Update(tempY, mFlags) ||
+        !srcU->Update(tempCb, mFlags) ||
+        !srcV->Update(tempCr, mFlags)) {
+      NS_WARNING("failed to update the DataTextureSource");
+      return false;
+    }
+  } else {
+    // non-YCbCr case
+    if (!mFirstSource) {
+      mFirstSource = mCompositor->CreateDataTextureSource();
+    }
+    ImageDataDeserializer deserializer(GetBuffer());
+    if (!deserializer.IsValid()) {
+      NS_WARNING("failed to open shmem surface");
+      return false;
+    }
+
+    RefPtr<gfx::DataSourceSurface> surf = deserializer.GetAsSurface();
+
+    if (!mFirstSource->Update(surf.get(), mFlags, aRegion)) {
+      NS_WARNING("failed to update the DataTextureSource");
+      return false;
+    }
+  }
+  return true;
+}
+
+already_AddRefed<gfxImageSurface>
+BufferTextureHost::GetAsSurface()
+{
+  nsRefPtr<gfxImageSurface> result; 
+  if (mFormat == gfx::FORMAT_UNKNOWN) {
+    NS_WARNING("BufferTextureHost: unsupported format!");
+    return nullptr;
+  } else if (mFormat == gfx::FORMAT_YUV) {
+    YCbCrImageDataDeserializer yuvDeserializer(GetBuffer());
+    if (!yuvDeserializer.IsValid()) {
+      return nullptr;
+    }
+    result = new gfxImageSurface(yuvDeserializer.GetYData(),
+                                 yuvDeserializer.GetYSize(),
+                                 yuvDeserializer.GetYStride(),
+                                 gfxASurface::ImageFormatA8);
+  } else {
+    ImageDataDeserializer deserializer(GetBuffer());
+    if (!deserializer.IsValid()) {
+      return nullptr;
+    }
+    RefPtr<gfxImageSurface> surf = deserializer.GetAsThebesSurface();
+    result = surf.get();
+  }
+  return result.forget();
+}
+
+ShmemTextureHost::ShmemTextureHost(uint64_t aID,
+                                   const ipc::Shmem& aShmem,
+                                   gfx::SurfaceFormat aFormat,
+                                   ISurfaceAllocator* aDeallocator,
+                                   TextureFlags aFlags)
+: BufferTextureHost(aID, aFormat, aFlags)
+, mShmem(new ipc::Shmem(aShmem))
+, mDeallocator(aDeallocator)
+{
+  MOZ_COUNT_CTOR(ShmemTextureHost);
+}
+
+ShmemTextureHost::~ShmemTextureHost()
+{
+  DeallocateDeviceData();
+  delete mShmem;
+  MOZ_COUNT_DTOR(ShmemTextureHost);
+}
+
+void
+ShmemTextureHost::DeallocateSharedData()
+{
+  if (mShmem) {
+    MOZ_ASSERT(mDeallocator,
+               "Shared memory would leak without a ISurfaceAllocator");
+    mDeallocator->DeallocShmem(*mShmem);
+  }
+}
+
+uint8_t* ShmemTextureHost::GetBuffer()
+{
+  return mShmem ? mShmem->get<uint8_t>() : nullptr;
+}
+
+MemoryTextureHost::MemoryTextureHost(uint64_t aID,
+                                     uint8_t* aBuffer,
+                                     gfx::SurfaceFormat aFormat,
+                                     TextureFlags aFlags)
+: BufferTextureHost(aID, aFormat, aFlags)
+, mBuffer(aBuffer)
+{
+  MOZ_COUNT_CTOR(MemoryTextureHost);
+}
+
+MemoryTextureHost::~MemoryTextureHost()
+{
+  DeallocateDeviceData();
+  MOZ_COUNT_DTOR(ShmemTextureHost);
+}
+
+void
+MemoryTextureHost::DeallocateSharedData()
+{
+  delete[] mBuffer;
+}
+
+uint8_t* MemoryTextureHost::GetBuffer()
+{
+  return mBuffer;
+}
+
 } // namespace
 } // namespace
--- a/gfx/layers/composite/TextureHost.h
+++ b/gfx/layers/composite/TextureHost.h
@@ -14,28 +14,35 @@
 #include "nsAutoPtr.h"
 #include "mozilla/RefPtr.h"
 #include "mozilla/layers/ISurfaceAllocator.h"
 
 class gfxReusableSurfaceWrapper;
 class gfxImageSurface;
 
 namespace mozilla {
+namespace gfx {
+class DataSourceSurface;
+}
+}
+
+namespace mozilla {
 namespace layers {
 
 class Compositor;
 class SurfaceDescriptor;
 class ISurfaceAllocator;
 class TextureSourceOGL;
 class TextureSourceD3D11;
 class TextureSourceBasic;
 class TextureParent;
+class DataTextureSource;
 
 /**
- * A view on a DeprecatedTextureHost where the texture is internally represented as tiles
+ * A view on a TextureHost where the texture is internally represented as tiles
  * (contrast with a tiled buffer, where each texture is a tile). For iteration by
  * the texture's buffer host.
  * This is only useful when the underlying surface is too big to fit in one
  * device texture, which forces us to split it in smaller parts.
  * Tiled Compositable is a different thing.
  */
 class TileIterator
 {
@@ -64,52 +71,451 @@ public:
     MOZ_COUNT_CTOR(TextureSource);
   }
   virtual ~TextureSource()
   {
     MOZ_COUNT_DTOR(TextureSource);
   }
 
   /**
-   * Returns the size of the texture in texels.
-   * If the underlying texture host is a tile iterator, GetSize must return the
-   * size of the current tile.
+   * Return the size of the texture in texels.
+   * If this is a tile iterator, GetSize must return the size of the current tile.
    */
   virtual gfx::IntSize GetSize() const = 0;
 
+  /**
+   * Return the pixel format of this texture
+   */
   virtual gfx::SurfaceFormat GetFormat() const { return gfx::FORMAT_UNKNOWN; }
 
   /**
-   * Cast to an TextureSource for the OpenGL backend.
+   * Cast to a TextureSource for the OpenGL backend.
    */
   virtual TextureSourceOGL* AsSourceOGL() { return nullptr; }
 
   /**
-   * Cast to an TextureSource for the D3D11 backend.
+   * Cast to a TextureSource for the D3D11 backend.
    */
   virtual TextureSourceD3D11* AsSourceD3D11() { return nullptr; }
 
+  /**
+   * Cast to a TextureSource for the software backend.
+   */
   virtual TextureSourceBasic* AsSourceBasic() { return nullptr; }
 
   /**
+   * Cast to a DataTextureSurce.
+   */
+  virtual DataTextureSource* AsDataTextureSource() { return nullptr; }
+
+  /**
    * In some rare cases we currently need to consider a group of textures as one
    * TextureSource, that can be split in sub-TextureSources.
    */
   virtual TextureSource* GetSubSource(int index) { return nullptr; }
+
   /**
    * Overload this if the TextureSource supports big textures that don't fit in
    * one device texture and must be tiled internally.
    */
   virtual TileIterator* AsTileIterator() { return nullptr; }
 
 #ifdef MOZ_LAYERS_HAVE_LOG
   virtual void PrintInfo(nsACString& aTo, const char* aPrefix);
 #endif
 };
 
+
+/**
+ * XXX - merge this class with TextureSource when deprecated texture classes
+ * are completely removed.
+ */
+class NewTextureSource : public TextureSource
+{
+public:
+  NewTextureSource()
+  {
+    MOZ_COUNT_CTOR(NewTextureSource);
+  }
+  virtual ~NewTextureSource()
+  {
+    MOZ_COUNT_DTOR(NewTextureSource);
+  }
+
+  /**
+   * Should be overriden in order to deallocate the data that is associated
+   * with the rendering backend, such as GL textures.
+   */
+  virtual void DeallocateDeviceData() = 0;
+
+  void SetNextSibling(NewTextureSource* aTexture)
+  {
+    mNextSibling = aTexture;
+  }
+
+  NewTextureSource* GetNextSibling() const
+  {
+    return mNextSibling;
+  }
+
+  // temporary adapter to use the same SubSource API as the old TextureSource
+  virtual TextureSource* GetSubSource(int index) MOZ_OVERRIDE
+  {
+    switch (index) {
+      case 0: return this;
+      case 1: return GetNextSibling();
+      case 2: return GetNextSibling() ? GetNextSibling()->GetNextSibling() : nullptr;
+    }
+    return nullptr;
+  }
+
+protected:
+  RefPtr<NewTextureSource> mNextSibling;
+};
+
+/**
+ * Interface for TextureSources that can be updated from a DataSourceSurface.
+ *
+ * All backend should implement at least one DataTextureSource.
+ */
+class DataTextureSource : public NewTextureSource
+{
+public:
+  DataTextureSource()
+    : mUpdateSerial(0)
+  {}
+
+  virtual DataTextureSource* AsDataTextureSource() MOZ_OVERRIDE { return this; }
+
+  /**
+   * Upload a (portion of) surface to the TextureSource.
+   *
+   * The DataTextureSource doesn't own aSurface, although it owns and manage
+   * the device texture it uploads to internally.
+   */
+  virtual bool Update(gfx::DataSourceSurface* aSurface,
+                      TextureFlags aFlags,
+                      nsIntRegion* aDestRegion = nullptr,
+                      gfx::IntPoint* aSrcOffset = nullptr) = 0;
+
+  /**
+   * A facility to avoid reuploading when it is not necessary.
+   * The caller of Update can use GetUpdateSerial to see if the number has changed
+   * since last update, and call SetUpdateSerial after each successful update.
+   * The caller is responsible for managing the update serial except when the
+   * texture data is deallocated in which case the TextureSource should always
+   * reset the update serial to zero.
+   */
+  uint32_t GetUpdateSerial() const { return mUpdateSerial; }
+  void SetUpdateSerial(uint32_t aValue) { mUpdateSerial = aValue; }
+
+  // By default at least set the update serial to zero.
+  // overloaded versions should do that too.
+  virtual void DeallocateDeviceData() MOZ_OVERRIDE
+  {
+    SetUpdateSerial(0);
+  }
+
+  /**
+   * Provide read access to the data as a DataSourceSurface.
+   *
+   * This is expected to be very slow and should be used for mostly debugging.
+   * XXX - implement everywhere and make it pure virtual.
+   */
+  virtual TemporaryRef<gfx::DataSourceSurface> ReadBack() { return nullptr; };
+private:
+  uint32_t mUpdateSerial;
+};
+
+/**
+ * TextureHost is a thin abstraction over texture data that need to be shared
+ * between the content process and the compositor process. It is the
+ * compositor-side half of a TextureClient/TextureHost pair. A corresponding
+ * TextureClient lives on the content-side.
+ *
+ * TextureHost only knows how to deserialize or synchronize generic image data
+ * (SurfaceDescriptor) and provide access to one or more TextureSource objects
+ * (these provide the necessary APIs for compositor backends to composite the
+ * image).
+ *
+ * A TextureHost implementation corresponds to one SurfaceDescriptor type, as
+ * opposed to TextureSource that corresponds to device textures.
+ * This means that for YCbCr planes, even though they are represented as
+ * 3 textures internally (3 TextureSources), we use 1 TextureHost and not 3,
+ * because the 3 planes are stored in the same buffer of shared memory, before
+ * they are uploaded separately.
+ *
+ * There is always one and only one TextureHost per TextureClient, and the
+ * TextureClient/Host pair only owns one buffer of image data through its
+ * lifetime. This means that the lifetime of the underlying shared data
+ * matches the lifetime of the TextureClient/Host pair. It also means
+ * TextureClient/Host do not implement double buffering, which is the
+ * reponsibility of the compositable (which would use two Texture pairs).
+ *
+ * The Lock/Unlock mecanism here mirrors Lock/Unlock in TextureClient.
+ *
+ */
+class TextureHost : public RefCounted<TextureHost>
+{
+public:
+  TextureHost(uint64_t aID,
+              TextureFlags aFlags)
+    : mID(aID)
+    , mNextTexture(nullptr)
+    , mFlags(aFlags)
+  {}
+
+  virtual ~TextureHost() {}
+
+  /**
+   * Factory method.
+   */
+  static TemporaryRef<TextureHost> Create(uint64_t aID,
+                                          const SurfaceDescriptor& aDesc,
+                                          ISurfaceAllocator* aDeallocator,
+                                          TextureFlags aFlags);
+
+  /**
+   * Lock the texture host for compositing.
+   */
+  virtual bool Lock() { return true; }
+
+  /**
+   * Unlock the texture host after compositing.
+   */
+  virtual void Unlock() {}
+
+  /**
+   * Note that the texture host format can be different from its corresponding
+   * texture source's. For example a ShmemTextureHost can have the ycbcr
+   * format and produce 3 "alpha" textures sources.
+   */
+  virtual gfx::SurfaceFormat GetFormat() const = 0;
+
+  /**
+   * Return a list of TextureSources for use with a Compositor.
+   *
+   * This can trigger texture uploads, so do not call it inside transactions
+   * so as to not upload textures while the main thread is blocked.
+   * Must not be called while this TextureHost is not sucessfully Locked.
+   */
+  virtual NewTextureSource* GetTextureSources() = 0;
+
+  /**
+   * 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) {}
+
+  /**
+   * 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.
+   */
+  virtual void SetCompositor(Compositor* aCompositor) {}
+
+  /**
+   * Should be overriden in order to deallocate the data that is associated
+   * with the rendering backend, such as GL textures.
+   */
+  virtual void DeallocateDeviceData() {}
+
+  /**
+   * Should be overriden in order to deallocate the data that is shared with
+   * the content side, such as shared memory.
+   */
+  virtual void DeallocateSharedData() {}
+
+  /**
+   * An ID to differentiate TextureHosts of a given CompositableHost.
+   *
+   * A TextureHost and its corresponding TextureClient always have the same ID.
+   * TextureHosts of a given CompositableHost always have different IDs.
+   * TextureHosts of different CompositableHosts, may have the same ID.
+   * Zero is always an invalid ID.
+   */
+  uint64_t GetID() const { return mID; }
+
+  virtual gfx::IntSize GetSize() const = 0;
+
+  /**
+   * TextureHosts are kept as a linked list in their compositable
+   * XXX - This is just a poor man's PTexture. The purpose of this list is
+   * to keep TextureHost alive which should be independent from compositables.
+   * It will be removed when we add the PTetxure protocol (which will more
+   * gracefully handle the lifetime of textures). See bug 897452
+   */
+  TextureHost* GetNextSibling() const { return mNextTexture; }
+  void SetNextSibling(TextureHost* aNext) { mNextTexture = aNext; }
+
+  /**
+   * Debug facility.
+   * XXX - cool kids use Moz2D
+   */
+  virtual already_AddRefed<gfxImageSurface> GetAsSurface() = 0;
+
+  /**
+   * XXX - Flags should only be set at creation time, this will be removed.
+   */
+  void SetFlags(TextureFlags aFlags) { mFlags = aFlags; }
+
+  /**
+   * XXX - Flags should only be set at creation time, this will be removed.
+   */
+  void AddFlag(TextureFlags aFlag) { mFlags |= aFlag; }
+
+  TextureFlags GetFlags() { return mFlags; }
+
+  /**
+   * Specific to B2G's Composer2D
+   * XXX - more doc here
+   */
+  virtual LayerRenderState GetRenderState()
+  {
+    // By default we return an empty render state, this should be overriden
+    // by the TextureHost implementations that are used on B2G with Composer2D
+    return LayerRenderState();
+  }
+
+#ifdef MOZ_LAYERS_HAVE_LOG
+  virtual void PrintInfo(nsACString& aTo, const char* aPrefix)
+  {
+    RefPtr<TextureSource> source = GetTextureSources();
+    if (source) {
+      source->PrintInfo(aTo, aPrefix);
+    }
+  }
+#endif
+
+protected:
+  uint64_t mID;
+  RefPtr<TextureHost> mNextTexture;
+  TextureFlags mFlags;
+};
+
+/**
+ * TextureHost that wraps a random access buffer such as a Shmem or some raw
+ * memory.
+ *
+ * This TextureHost is backend-independent and the backend-specific bits are
+ * in the TextureSource.
+ * This class must be inherited to implement GetBuffer and DeallocSharedData
+ * (see ShmemTextureHost and MemoryTextureHost)
+ *
+ * Uploads happen when Lock is called.
+ *
+ * BufferTextureHost supports YCbCr and flavours of RGBA images (RGBX, A, etc.).
+ */
+class BufferTextureHost : public TextureHost
+{
+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 bool Lock() MOZ_OVERRIDE;
+
+  virtual void Unlock() MOZ_OVERRIDE;
+
+  virtual NewTextureSource* GetTextureSources() MOZ_OVERRIDE;
+
+  virtual void DeallocateDeviceData() MOZ_OVERRIDE;
+
+  virtual void SetCompositor(Compositor* aCompositor) MOZ_OVERRIDE;
+
+  /**
+   * Return the format that is exposed to the compositor when calling
+   * GetTextureSources.
+   *
+   * If the shared format is YCbCr and the compositor does not support it,
+   * GetFormat will be RGB32 (even though mFormat is FORMAT_YUV).
+   */
+  virtual gfx::SurfaceFormat GetFormat() const MOZ_OVERRIDE;
+
+  virtual already_AddRefed<gfxImageSurface> GetAsSurface() MOZ_OVERRIDE;
+
+  virtual gfx::IntSize GetSize() const MOZ_OVERRIDE { return mSize; }
+
+protected:
+  bool Upload(nsIntRegion *aRegion = nullptr);
+
+  Compositor* mCompositor;
+  RefPtr<DataTextureSource> mFirstSource;
+  nsIntRegion mMaybeUpdatedRegion;
+  gfx::IntSize mSize;
+  // format of the data that is shared with the content process.
+  gfx::SurfaceFormat mFormat;
+  uint32_t mUpdateSerial;
+  bool mLocked;
+  bool mPartialUpdate;
+};
+
+/**
+ * TextureHost that wraps shared memory.
+ * the corresponding texture on the client side is ShmemTextureClient.
+ * This TextureHost is backend-independent.
+ */
+class ShmemTextureHost : public BufferTextureHost
+{
+public:
+  ShmemTextureHost(uint64_t aID,
+                   const ipc::Shmem& aShmem,
+                   gfx::SurfaceFormat aFormat,
+                   ISurfaceAllocator* aDeallocator,
+                   TextureFlags aFlags);
+
+  ~ShmemTextureHost();
+
+  virtual void DeallocateSharedData() MOZ_OVERRIDE;
+
+  virtual uint8_t* GetBuffer() MOZ_OVERRIDE;
+
+protected:
+  ipc::Shmem* mShmem;
+  ISurfaceAllocator* mDeallocator;
+};
+
+/**
+ * TextureHost that wraps raw memory.
+ * The corresponding texture on the client side is MemoryTextureClient.
+ * Can obviously not be used in a cross process setup.
+ * This TextureHost is backend-independent.
+ */
+class MemoryTextureHost : public BufferTextureHost
+{
+public:
+  MemoryTextureHost(uint64_t aID,
+                    uint8_t* aBuffer,
+                    gfx::SurfaceFormat aFormat,
+                    TextureFlags aFlags);
+
+  ~MemoryTextureHost();
+
+  virtual void DeallocateSharedData() MOZ_OVERRIDE;
+
+  virtual uint8_t* GetBuffer() MOZ_OVERRIDE;
+
+protected:
+  uint8_t* mBuffer;
+};
+
+
 /**
  * XXX - This class is deprectaed, will be removed soon.
  *
  * DeprecatedTextureHost is a thin abstraction over texture data that need to be shared
  * or transfered from the content process to the compositor process. It is the
  * compositor-side half of a DeprecatedTextureClient/DeprecatedTextureHost pair. A corresponding
  * DeprecatedTextureClient lives on the client-side.
  *
@@ -118,17 +524,17 @@ public:
  * (these provide the necessary APIs for compositor backends to composite the
  * image).
  *
  * A DeprecatedTextureHost should mostly correspond to one or several SurfaceDescriptor
  * types. This means that for YCbCr planes, even though they are represented as
  * 3 textures internally, use 1 DeprecatedTextureHost and not 3, because the 3 planes
  * arrive in the same IPC message.
  *
- * The Lock/Unlock mecanism here mirrors Lock/Unlock in DeprecatedTextureClient. These two
+ * The Lock/Unlock mechanism here mirrors Lock/Unlock in DeprecatedTextureClient. These two
  * methods don't always have to use blocking locks, unless a resource is shared
  * between the two sides (like shared texture handles). For instance, in some
  * cases the data received in Update(...) is a copy in shared memory of the data
  * owned by the content process, in which case no blocking lock is required.
  *
  * DeprecatedTextureHosts can be changed at any time, for example if we receive a
  * SurfaceDescriptor type that was not expected. This should be an incentive
  * to keep the ownership model simple (especially on the OpenGL case, where
@@ -342,19 +748,18 @@ protected:
 
   // Texture info
   TextureFlags mFlags;
   SurfaceDescriptor* mBuffer; // FIXME [bjacob] it's terrible to have a SurfaceDescriptor here,
                               // because SurfaceDescriptor's may have raw pointers to IPDL actors,
                               // which can go away under our feet at any time. This is the cause
                               // of bug 862324 among others. Our current understanding is that
                               // this will be gone in Gecko 24. See bug 858914.
+  ISurfaceAllocator* mDeAllocator;
   gfx::SurfaceFormat mFormat;
-
-  ISurfaceAllocator* mDeAllocator;
 };
 
 class AutoLockDeprecatedTextureHost
 {
 public:
   AutoLockDeprecatedTextureHost(DeprecatedTextureHost* aHost)
     : mDeprecatedTextureHost(aHost)
     , mIsValid(true)
@@ -387,11 +792,22 @@ class CompositingRenderTarget : public T
 public:
   virtual ~CompositingRenderTarget() {}
 
 #ifdef MOZ_DUMP_PAINTING
   virtual already_AddRefed<gfxImageSurface> Dump(Compositor* aCompositor) { return nullptr; }
 #endif
 };
 
+/**
+ * Creates a TextureHost that can be used with any of the existing backends
+ * Not all SurfaceDescriptor types are supported
+ */
+TemporaryRef<TextureHost>
+CreateBackendIndependentTextureHost(uint64_t aID,
+                                    const SurfaceDescriptor& aDesc,
+                                    ISurfaceAllocator* aDeallocator,
+                                    TextureFlags aFlags);
+
 }
 }
+
 #endif
--- a/gfx/layers/composite/TiledContentHost.h
+++ b/gfx/layers/composite/TiledContentHost.h
@@ -3,16 +3,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef GFX_TILEDCONTENTHOST_H
 #define GFX_TILEDCONTENTHOST_H
 
 #include "ContentHost.h"
 #include "ClientTiledThebesLayer.h" // for BasicTiledLayerBuffer
+#include "mozilla/layers/TextureHost.h"
 
 namespace mozilla {
 namespace layers {
 
 class ThebesBuffer;
 class OptionalThebesBuffer;
 struct TexturedEffect;
 
--- a/gfx/layers/d3d11/CompositorD3D11.h
+++ b/gfx/layers/d3d11/CompositorD3D11.h
@@ -42,16 +42,19 @@ public:
   ~CompositorD3D11();
 
   virtual bool Initialize() MOZ_OVERRIDE;
   virtual void Destroy() MOZ_OVERRIDE {}
 
   virtual TextureFactoryIdentifier
     GetTextureFactoryIdentifier() MOZ_OVERRIDE;
 
+  virtual TemporaryRef<DataTextureSource>
+    CreateDataTextureSource(TextureFlags aFlags = 0) MOZ_OVERRIDE { return nullptr; }
+
   virtual bool CanUseCanvasLayerForSize(const gfxIntSize& aSize) MOZ_OVERRIDE;
   virtual int32_t GetMaxTextureSize() const MOZ_FINAL;
 
   virtual void SetTargetContext(gfxContext* aTarget)  MOZ_OVERRIDE
   {
     mTarget = aTarget;
   }
 
--- a/gfx/layers/d3d11/TextureD3D11.h
+++ b/gfx/layers/d3d11/TextureD3D11.h
@@ -3,16 +3,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef MOZILLA_GFX_TEXTURED3D11_H
 #define MOZILLA_GFX_TEXTURED3D11_H
 
 #include "mozilla/layers/Compositor.h"
 #include "mozilla/layers/TextureClient.h"
+#include "mozilla/layers/TextureHost.h"
 #include "gfxWindowsPlatform.h"
 #include <d3d11.h>
 #include <vector>
 
 class gfxD2DSurface;
 
 namespace mozilla {
 namespace layers {
--- a/gfx/layers/ipc/CompositableForwarder.h
+++ b/gfx/layers/ipc/CompositableForwarder.h
@@ -15,16 +15,17 @@
 namespace mozilla {
 namespace layers {
 
 class CompositableClient;
 class TextureFactoryIdentifier;
 class SurfaceDescriptor;
 class ThebesBufferData;
 class DeprecatedTextureClient;
+class TextureClient;
 class BasicTiledLayerBuffer;
 
 /**
  * A transaction is a set of changes that happenned on the content side, that
  * should be sent to the compositor side.
  * CompositableForwarder is an interface to manage a transaction of
  * compositable objetcs.
  *
@@ -136,16 +137,52 @@ public:
    * |aBackBufferToDestroy| is deallocated when this transaction is
    * posted to the parent.  During the parent-side transaction, the
    * shadow is told to destroy its front buffer.  This can happen when
    * a new front/back buffer pair have been created because of a layer
    * resize, e.g.
    */
   virtual void DestroyedThebesBuffer(const SurfaceDescriptor& aBackBufferToDestroy) = 0;
 
+  /**
+   * Tell the compositor side to create a TextureHost that corresponds to
+   * aClient.
+   */
+  virtual void AddTexture(CompositableClient* aCompositable,
+                          TextureClient* aClient) = 0;
+
+  /**
+   * Tell the compositor side to delete the TextureHost corresponding to
+   * aTextureID.
+   * By default the shared Data is deallocated along with the TextureHost, but
+   * this behaviour can be overriden by the TextureFlags passed here.
+   * XXX - This is kind of bad, but for now we have to do this, because of some
+   * edge cases caused by the lifetime of the TextureHost being limited by the
+   * lifetime of the CompositableHost. We should be able to remove this flags
+   * parameter when we remove the lifetime constraint.
+   */
+  virtual void RemoveTexture(CompositableClient* aCompositable,
+                             uint64_t aTextureID,
+                             TextureFlags aFlags = TEXTURE_FLAGS_DEFAULT) = 0;
+
+  /**
+   * Tell the CompositableHost on the compositor side what texture to use for
+   * the next composition.
+   */
+  virtual void UseTexture(CompositableClient* aCompositable,
+                          TextureClient* aClient) = 0;
+
+  /**
+   * Tell the compositor side that the shared data has been modified so that
+   * it can react accordingly (upload textures, etc.).
+   */
+  virtual void UpdatedTexture(CompositableClient* aCompositable,
+                              TextureClient* aTexture,
+                              nsIntRegion* aRegion) = 0;
+
   void IdentifyTextureHost(const TextureFactoryIdentifier& aIdentifier);
 
   /**
    * Returns the maximum texture size supported by the compositor.
    */
   virtual int32_t GetMaxTextureSize() const { return mTextureFactoryIdentifier.mMaxTextureSize; }
 
   bool IsOnCompositorSide() const MOZ_OVERRIDE { return false; }
--- a/gfx/layers/ipc/CompositableTransactionParent.cpp
+++ b/gfx/layers/ipc/CompositableTransactionParent.cpp
@@ -10,21 +10,44 @@
 #include "RenderTrace.h"
 #include "ShadowLayersManager.h"
 #include "CompositableHost.h"
 #include "mozilla/layers/ContentHost.h"
 #include "ShadowLayerParent.h"
 #include "TiledLayerBuffer.h"
 #include "mozilla/layers/LayerManagerComposite.h"
 #include "mozilla/layers/ThebesLayerComposite.h"
+#include "mozilla/layers/TextureHost.h"
 #include "CompositorParent.h"
 
 namespace mozilla {
 namespace layers {
 
+template<typename T>
+CompositableHost* AsCompositable(const T& op)
+{
+  return static_cast<CompositableParent*>(op.compositableParent())->GetCompositableHost();
+}
+
+template<typename T>
+bool ScheduleComposition(const T& op)
+{
+  CompositableParent* comp = static_cast<CompositableParent*>(op.compositableParent());
+  if (!comp || !comp->GetCompositorID()) {
+    return false;
+  }
+  CompositorParent* cp
+    = CompositorParent::GetCompositor(comp->GetCompositorID());
+  if (!cp) {
+    return false;
+  }
+  cp->ScheduleComposition();
+  return true;
+}
+
 bool
 CompositableParentManager::ReceiveCompositableUpdate(const CompositableOperation& aEdit,
                                                      EditReplyVector& replyv)
 {
   switch (aEdit.type()) {
     case CompositableOperation::TOpCreatedTexture: {
       MOZ_LAYERS_LOG(("[ParentSide] Created texture"));
       const OpCreatedTexture& op = aEdit.get_OpCreatedTexture();
@@ -96,22 +119,18 @@ CompositableParentManager::ReceiveCompos
 
         SurfaceDescriptor newBack;
         bool shouldRecomposite = compositable->Update(descriptor, &newBack);
         if (IsSurfaceDescriptorValid(newBack)) {
           replyv.push_back(OpTextureSwap(compositableParent, nullptr,
                                          op.textureId(), newBack));
         }
 
-        if (shouldRecomposite && compositableParent->GetCompositorID()) {
-          CompositorParent* cp
-            = CompositorParent::GetCompositor(compositableParent->GetCompositorID());
-          if (cp) {
-            cp->ScheduleComposition();
-          }
+        if (shouldRecomposite) {
+          ScheduleComposition(op);
         }
       }
 
       if (layer) {
         RenderTraceInvalidateEnd(layer, "FF00FF");
       }
 
       break;
@@ -176,16 +195,101 @@ CompositableParentManager::ReceiveCompos
 
       TiledLayerComposer* tileComposer = compositable->AsTiledLayerComposer();
       NS_ASSERTION(tileComposer, "compositable is not a tile composer");
 
       BasicTiledLayerBuffer* p = reinterpret_cast<BasicTiledLayerBuffer*>(op.tiledLayerBuffer());
       tileComposer->PaintedTiledLayerBuffer(p);
       break;
     }
+    case CompositableOperation::TOpUseTexture: {
+      const OpUseTexture& op = aEdit.get_OpUseTexture();
+      if (op.textureID() == 0) {
+        NS_WARNING("Invalid texture ID");
+        break;
+      }
+      CompositableHost* compositable = AsCompositable(op);
+      RefPtr<TextureHost> tex = compositable->GetTextureHost(op.textureID());
+
+      MOZ_ASSERT(tex.get());
+      compositable->UseTextureHost(tex);
+
+      if (!ScheduleComposition(op)) {
+        NS_WARNING("could not find a compositor to schedule composition");
+      }
+      break;
+    }
+    case CompositableOperation::TOpAddTexture: {
+      const OpAddTexture& op = aEdit.get_OpAddTexture();
+      if (op.textureID() == 0) {
+        NS_WARNING("Invalid texture ID");
+        break;
+      }
+      CompositableHost* compositable = AsCompositable(op);
+      RefPtr<TextureHost> tex = TextureHost::Create(op.textureID(),
+                                                    op.data(),
+                                                    this,
+                                                    op.textureFlags());
+      MOZ_ASSERT(tex.get());
+      tex->SetCompositor(compositable->GetCompositor());
+      compositable->AddTextureHost(tex);
+      MOZ_ASSERT(compositable->GetTextureHost(op.textureID()) == tex.get());
+      break;
+    }
+    case CompositableOperation::TOpRemoveTexture: {
+      const OpRemoveTexture& op = aEdit.get_OpRemoveTexture();
+      if (op.textureID() == 0) {
+        NS_WARNING("Invalid texture ID");
+        break;
+      }
+      CompositableHost* compositable = AsCompositable(op);
+
+      RefPtr<TextureHost> texture = compositable->GetTextureHost(op.textureID());
+      MOZ_ASSERT(texture);
+
+      TextureFlags flags = texture->GetFlags();
+
+      if (flags & TEXTURE_DEALLOCATE_HOST) {
+        texture->DeallocateSharedData();
+      }
+
+      compositable->RemoveTextureHost(op.textureID());
+
+      // 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_HOST)) {
+        replyv.push_back(ReplyTextureRemoved(op.compositableParent(), nullptr,
+                                             op.textureID()));
+      }
+
+      break;
+    }
+    case CompositableOperation::TOpUpdateTexture: {
+      const OpUpdateTexture& op = aEdit.get_OpUpdateTexture();
+      if (op.textureID() == 0) {
+        NS_WARNING("Invalid texture ID");
+        break;
+      }
+      CompositableHost* compositable = AsCompositable(op);
+      MOZ_ASSERT(compositable);
+      RefPtr<TextureHost> texture = compositable->GetTextureHost(op.textureID());
+      MOZ_ASSERT(texture);
+      if (op.region().type() == MaybeRegion::TnsIntRegion) {
+        nsIntRegion region = op.region().get_nsIntRegion();
+        texture->Updated(&region);
+      } else {
+        // no region means invalidate the entire surface
+        texture->Updated(nullptr);
+      }
+      compositable->UseTextureHost(texture);
+
+      break;
+    }
+
     default: {
       MOZ_ASSERT(false, "bad type");
     }
   }
 
   return true;
 }
 
--- a/gfx/layers/ipc/CompositableTransactionParent.h
+++ b/gfx/layers/ipc/CompositableTransactionParent.h
@@ -14,18 +14,16 @@ namespace layers {
 typedef std::vector<mozilla::layers::EditReply> EditReplyVector;
 
 // Since PCompositble has two potential manager protocols, we can't just call
 // the Manager() method usually generated when there's one manager protocol,
 // so both manager protocols implement this and we keep a reference to them
 // through this interface.
 class CompositableParentManager : public ISurfaceAllocator
 {
-public:
-
 protected:
   /**
    * Handle the IPDL messages that affect PCompositable actors.
    */
   bool ReceiveCompositableUpdate(const CompositableOperation& aEdit,
                                  EditReplyVector& replyv);
   bool IsOnCompositorSide() const MOZ_OVERRIDE { return true; }
 };
--- a/gfx/layers/ipc/CompositorParent.cpp
+++ b/gfx/layers/ipc/CompositorParent.cpp
@@ -159,16 +159,22 @@ CompositorParent::CompositorParent(nsIWi
 }
 
 PlatformThreadId
 CompositorParent::CompositorThreadID()
 {
   return sCompositorThread ? sCompositorThread->thread_id() : sCompositorThreadID;
 }
 
+bool
+CompositorParent::IsInCompositorThread()
+{
+  return CompositorThreadID() == PlatformThread::CurrentId();
+}
+
 CompositorParent::~CompositorParent()
 {
   MOZ_COUNT_DTOR(CompositorParent);
 
   ReleaseCompositorThread();
 }
 
 void
--- a/gfx/layers/ipc/CompositorParent.h
+++ b/gfx/layers/ipc/CompositorParent.h
@@ -170,16 +170,20 @@ public:
    * Tell all CompositorParents to update their last refresh to aTime and sample
    * animations at this time stamp.  If aIsTesting is true, the
    * CompositorParents will become "paused" and continue sampling animations at
    * this time stamp until this function is called again with aIsTesting set to
    * false.
    */
   static void SetTimeAndSampleAnimations(TimeStamp aTime, bool aIsTesting);
 
+  /**
+   * Returns true if the calling thrad is the compositor thread.
+   */
+  static bool IsInCompositorThread();
 protected:
   virtual PLayerTransactionParent*
     AllocPLayerTransactionParent(const LayersBackend& aBackendHint,
                                  const uint64_t& aId,
                                  TextureFactoryIdentifier* aTextureFactoryIdentifier);
   virtual bool DeallocPLayerTransactionParent(PLayerTransactionParent* aLayers);
   virtual void ScheduleTask(CancelableTask*, int);
   virtual void Composite();
@@ -188,17 +192,17 @@ protected:
   void SetEGLSurfaceSize(int width, int height);
 
 private:
   void PauseComposition();
   void ResumeComposition();
   void ResumeCompositionAndResize(int width, int height);
   void ForceComposition();
 
-  inline PlatformThreadId CompositorThreadID();
+  inline static PlatformThreadId CompositorThreadID();
 
   /**
    * Creates a global map referencing each compositor by ID.
    *
    * This map is used by the ImageBridge protocol to trigger
    * compositions without having to keep references to the
    * compositor
    */
--- a/gfx/layers/ipc/ISurfaceAllocator.cpp
+++ b/gfx/layers/ipc/ISurfaceAllocator.cpp
@@ -115,20 +115,16 @@ ISurfaceAllocator::AllocSurfaceDescripto
 
 void
 ISurfaceAllocator::DestroySharedSurface(SurfaceDescriptor* aSurface)
 {
   MOZ_ASSERT(aSurface);
   if (!aSurface) {
     return;
   }
-  if (!IsOnCompositorSide() && ReleaseOwnedSurfaceDescriptor(*aSurface)) {
-    *aSurface = SurfaceDescriptor();
-    return;
-  }
   if (PlatformDestroySharedSurface(aSurface)) {
     return;
   }
   switch (aSurface->type()) {
     case SurfaceDescriptor::TShmem:
       DeallocShmem(aSurface->get_Shmem());
       break;
     case SurfaceDescriptor::TYCbCrImage:
@@ -146,48 +142,16 @@ ISurfaceAllocator::DestroySharedSurface(
     case SurfaceDescriptor::T__None:
       break;
     default:
       NS_RUNTIMEABORT("surface type not implemented!");
   }
   *aSurface = SurfaceDescriptor();
 }
 
-bool IsSurfaceDescriptorOwned(const SurfaceDescriptor& aDescriptor)
-{
-  switch (aDescriptor.type()) {
-    case SurfaceDescriptor::TYCbCrImage: {
-      const YCbCrImage& ycbcr = aDescriptor.get_YCbCrImage();
-      return ycbcr.owner() != 0;
-    }
-    case SurfaceDescriptor::TRGBImage: {
-      const RGBImage& rgb = aDescriptor.get_RGBImage();
-      return rgb.owner() != 0;
-    }
-    default:
-      return false;
-  }
-  return false;
-}
-bool ReleaseOwnedSurfaceDescriptor(const SurfaceDescriptor& aDescriptor)
-{
-  DeprecatedSharedPlanarYCbCrImage* sharedYCbCr =
-    DeprecatedSharedPlanarYCbCrImage::FromSurfaceDescriptor(aDescriptor);
-  if (sharedYCbCr) {
-    sharedYCbCr->Release();
-    return true;
-  }
-  DeprecatedSharedRGBImage* sharedRGB = DeprecatedSharedRGBImage::FromSurfaceDescriptor(aDescriptor);
-  if (sharedRGB) {
-    sharedRGB->Release();
-    return true;
-  }
-  return false;
-}
-
 #if !defined(MOZ_HAVE_PLATFORM_SPECIFIC_LAYER_BUFFERS)
 bool
 ISurfaceAllocator::PlatformAllocSurfaceDescriptor(const gfxIntSize&,
                                                   gfxASurface::gfxContentType,
                                                   uint32_t,
                                                   SurfaceDescriptor*)
 {
   return false;
--- a/gfx/layers/ipc/ImageBridgeChild.cpp
+++ b/gfx/layers/ipc/ImageBridgeChild.cpp
@@ -74,16 +74,61 @@ struct CompositableTransaction
 
 struct AutoEndTransaction {
   AutoEndTransaction(CompositableTransaction* aTxn) : mTxn(aTxn) {}
   ~AutoEndTransaction() { mTxn->End(); }
   CompositableTransaction* mTxn;
 };
 
 void
+ImageBridgeChild::AddTexture(CompositableClient* aCompositable,
+                             TextureClient* aTexture)
+{
+  SurfaceDescriptor descriptor;
+  if (!aTexture->ToSurfaceDescriptor(descriptor)) {
+    NS_WARNING("ImageBridge: Failed to serialize a TextureClient");
+    return;
+  }
+  mTxn->AddEdit(OpAddTexture(nullptr, aCompositable->GetIPDLActor(),
+                             aTexture->GetID(),
+                             descriptor,
+                             aTexture->GetFlags()));
+}
+
+void
+ImageBridgeChild::RemoveTexture(CompositableClient* aCompositable,
+                                uint64_t aTexture,
+                                TextureFlags aFlags)
+{
+  mTxn->AddNoSwapEdit(OpRemoveTexture(nullptr, aCompositable->GetIPDLActor(),
+                      aTexture,
+                      aFlags));
+}
+
+void
+ImageBridgeChild::UseTexture(CompositableClient* aCompositable,
+                             TextureClient* aTexture)
+{
+  mTxn->AddNoSwapEdit(OpUseTexture(nullptr, aCompositable->GetIPDLActor(),
+                      aTexture->GetID()));
+}
+
+void
+ImageBridgeChild::UpdatedTexture(CompositableClient* aCompositable,
+                                 TextureClient* aTexture,
+                                 nsIntRegion* aRegion)
+{
+  MaybeRegion region = aRegion ? MaybeRegion(*aRegion)
+                               : MaybeRegion(null_t());
+  mTxn->AddNoSwapEdit(OpUpdateTexture(nullptr, aCompositable->GetIPDLActor(),
+                                      aTexture->GetID(),
+                                      region));
+}
+
+void
 ImageBridgeChild::UpdateTexture(CompositableClient* aCompositable,
                                 TextureIdentifier aTextureId,
                                 SurfaceDescriptor* aDescriptor)
 {
   if (aDescriptor->type() != SurfaceDescriptor::T__None &&
       aDescriptor->type() != SurfaceDescriptor::Tnull_t) {
     MOZ_ASSERT(aCompositable);
     MOZ_ASSERT(aCompositable->GetIPDLActor());
@@ -299,16 +344,17 @@ void ImageBridgeChild::DispatchReleaseIm
 }
 
 static void UpdateImageClientNow(ImageClient* aClient, ImageContainer* aContainer)
 {
   MOZ_ASSERT(aClient);
   MOZ_ASSERT(aContainer);
   sImageBridgeChildSingleton->BeginTransaction();
   aClient->UpdateImage(aContainer, Layer::CONTENT_OPAQUE);
+  aClient->OnTransaction();
   sImageBridgeChildSingleton->EndTransaction();
 }
 
 //static
 void ImageBridgeChild::DispatchImageClientUpdate(ImageClient* aClient,
                                                  ImageContainer* aContainer)
 {
   if (InImageBridgeChildThread()) {
@@ -332,20 +378,16 @@ ImageBridgeChild::BeginTransaction()
 
 void
 ImageBridgeChild::EndTransaction()
 {
   MOZ_ASSERT(!mTxn->Finished(), "forgot BeginTransaction?");
 
   AutoEndTransaction _(mTxn);
 
-  if (mTxn->IsEmpty()) {
-    return;
-  }
-
   AutoInfallibleTArray<CompositableOperation, 10> cset;
   cset.SetCapacity(mTxn->mOperations.size());
   if (!mTxn->mOperations.empty()) {
     cset.AppendElements(&mTxn->mOperations.front(), mTxn->mOperations.size());
   }
   ShadowLayerForwarder::PlatformSyncBeforeUpdate();
 
   AutoInfallibleTArray<EditReply, 10> replies;
--- a/gfx/layers/ipc/ImageBridgeChild.h
+++ b/gfx/layers/ipc/ImageBridgeChild.h
@@ -23,17 +23,17 @@ namespace layers {
 class ImageClient;
 class ImageContainer;
 class ImageBridgeParent;
 class SurfaceDescriptor;
 class CompositableClient;
 class CompositableTransaction;
 class ShadowableLayer;
 class Image;
-
+class TextureClient;
 
 /**
  * Returns true if the current thread is the ImageBrdigeChild's thread.
  *
  * Can be called from any thread.
  */
 bool InImageBridgeChildThread();
 
@@ -227,16 +227,42 @@ public:
   static void DispatchReleaseImageClient(ImageClient* aClient);
   static void DispatchImageClientUpdate(ImageClient* aClient, ImageContainer* aContainer);
 
 
   // CompositableForwarder
 
   virtual void Connect(CompositableClient* aCompositable) MOZ_OVERRIDE;
 
+  /**
+   * See CompositableForwarder::AddTexture
+   */
+  virtual void AddTexture(CompositableClient* aCompositable,
+                          TextureClient* aClient) MOZ_OVERRIDE;
+
+  /**
+   * See CompositableForwarder::RemoveTexture
+   */
+  virtual void RemoveTexture(CompositableClient* aCompositable,
+                             uint64_t aTextureID,
+                             TextureFlags aFlags) MOZ_OVERRIDE;
+
+  /**
+   * See CompositableForwarder::UpdatedTexture
+   */
+  virtual void UpdatedTexture(CompositableClient* aCompositable,
+                              TextureClient* aTexture,
+                              nsIntRegion* aRegion) MOZ_OVERRIDE;
+
+  /**
+   * See CompositableForwarder::UseTexture
+   */
+  virtual void UseTexture(CompositableClient* aCompositable,
+                          TextureClient* aClient) MOZ_OVERRIDE;
+
   virtual void PaintedTiledLayerBuffer(CompositableClient* aCompositable,
                                        BasicTiledLayerBuffer* aTiledLayerBuffer) MOZ_OVERRIDE
   {
     NS_RUNTIMEABORT("should not be called");
   }
 
   /**
    * Communicate to the compositor that the texture identified by aCompositable
--- a/gfx/layers/ipc/LayerTransaction.ipdlh
+++ b/gfx/layers/ipc/LayerTransaction.ipdlh
@@ -285,28 +285,74 @@ struct OpPaintTextureIncremental {
   nsIntPoint bufferRotation;
 };
 
 struct OpUpdatePictureRect {
   PCompositable compositable;
   nsIntRect picture;
 };
 
+/**
+ * Provides the compositor side with enough information to create a
+ * TextureHost.
+ */
+struct OpAddTexture {
+  PCompositable compositable;
+  uint64_t textureID;
+  SurfaceDescriptor data;
+  uint32_t textureFlags;
+};
+
+/**
+ * Tells the compositor-side to remove the corresponding TextureHost and
+ * deallocate its data.
+ */
+struct OpRemoveTexture {
+  PCompositable compositable;
+  uint64_t textureID;
+  uint32_t flags;
+};
+
+/**
+ * Tells the compositor-side which texture to use (for example, as front buffer
+ * if there is several textures for double buffering)
+ */
+struct OpUseTexture {
+  PCompositable compositable;
+  uint64_t textureID;
+};
+
+union MaybeRegion {
+  nsIntRegion;
+  null_t;
+};
+
+struct OpUpdateTexture {
+  PCompositable compositable;
+  uint64_t textureID;
+  MaybeRegion region;
+};
+
 union CompositableOperation {
   OpUpdatePictureRect;
 
   OpCreatedTexture;
   OpCreatedIncrementalTexture;
   OpDestroyThebesBuffer;
 
   OpPaintTexture;
   OpPaintTextureRegion;
   OpPaintTextureIncremental;
 
   OpPaintTiledLayerBuffer;
+
+  OpAddTexture;
+  OpRemoveTexture;
+  OpUpdateTexture;
+  OpUseTexture;
 };
 
 // A unit of a changeset; a set of these comprise a changeset
 union Edit {
   OpCreateThebesLayer;
   OpCreateContainerLayer;
   OpCreateImageLayer;
   OpCreateColorLayer;
@@ -338,17 +384,25 @@ struct OpContentBufferSwap {
 };
 
 struct OpTextureSwap {
   PCompositable compositable;
   uint32_t textureId;
   SurfaceDescriptor image;
 };
 
+struct ReplyTextureRemoved {
+  PCompositable compositable;
+  uint32_t textureId;
+};
+
 // Unit of a "changeset reply".  This is a weird abstraction, probably
 // only to be used for buffer swapping.
 union EditReply {
   OpContentBufferSwap;
   OpTextureSwap;
+
+  // new stuff
+  ReplyTextureRemoved;
 };
 
 } // namespace
 } // namespace
--- a/gfx/layers/ipc/LayerTransactionParent.cpp
+++ b/gfx/layers/ipc/LayerTransactionParent.cpp
@@ -391,16 +391,18 @@ LayerTransactionParent::RecvUpdate(const
     case Edit::TCompositableOperation: {
       ReceiveCompositableUpdate(edit.get_CompositableOperation(),
                                 replyv);
       break;
     }
     case Edit::TOpAttachCompositable: {
       const OpAttachCompositable& op = edit.get_OpAttachCompositable();
       Attach(cast(op.layerParent()), cast(op.compositableParent()));
+      cast(op.compositableParent())->SetCompositorID(
+        mLayerManager->GetCompositor()->GetCompositorID());
       break;
     }
     case Edit::TOpAttachAsyncCompositable: {
       const OpAttachAsyncCompositable& op = edit.get_OpAttachAsyncCompositable();
       CompositableParent* compositableParent = CompositableMap::Get(op.containerID());
       MOZ_ASSERT(compositableParent, "CompositableParent not found in the map");
       Attach(cast(op.layerParent()), compositableParent);
       compositableParent->SetCompositorID(mLayerManager->GetCompositor()->GetCompositorID());
--- a/gfx/layers/ipc/LayersSurfaces.ipdlh
+++ b/gfx/layers/ipc/LayersSurfaces.ipdlh
@@ -1,15 +1,16 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 include protocol PGrallocBuffer;
 
 include "gfxipc/ShadowLayerUtils.h";
+include "mozilla/gfx/Types.h";
 
 using gfx3DMatrix;
 using gfxIntSize;
 using gfxPoint;
 using gfxRGBA;
 using nsIntPoint;
 using nsIntRect;
 using nsIntRegion;
@@ -19,16 +20,18 @@ using mozilla::GraphicsFilterType;
 using mozilla::layers::FrameMetrics;
 using mozilla::layers::MagicGrallocBufferHandle;
 using mozilla::layers::SurfaceDescriptorX11;
 using mozilla::null_t;
 using mozilla::WindowsHandle;
 using mozilla::gl::SharedTextureHandle;
 using mozilla::gl::GLContext::SharedTextureShareType;
 using mozilla::gfx::SurfaceStreamHandle;
+using mozilla::gfx::SurfaceFormat;
+using mozilla::gfx::IntSize;
 
 namespace mozilla {
 namespace layers {
 
 union MaybeMagicGrallocBufferHandle {
   MagicGrallocBufferHandle;
   null_t;
 };
@@ -40,16 +43,17 @@ struct SurfaceDescriptorD3D10 {
 
 struct SharedTextureDescriptor {
   SharedTextureShareType shareType;
   SharedTextureHandle handle;
   nsIntSize size;
   bool inverted;
 };
 
+// XXX - soon to be removed
 struct SurfaceDescriptorGralloc {
   PGrallocBuffer buffer;
   /**
    * android::GraphicBuffer has a size information. But there are cases
    * that GraphicBuffer's size and actual video's size are different.
    * Extra size member is necessary. See Bug 850566.
    */
   nsIntSize size;
@@ -75,16 +79,17 @@ struct SurfaceDescriptorGralloc {
   bool isRBSwapped;
 };
 
 struct SurfaceStreamDescriptor {
   SurfaceStreamHandle handle;
   bool yflip;
 };
 
+// XXX - can be removed as soon as DeprecatedImageClientSingle is removed
 struct YCbCrImage {
   Shmem data;
   uint64_t owner;
 };
 
 // XXX remove RGBImage (see bug 847914)
 struct RGBImage {
   Shmem data;
@@ -95,23 +100,41 @@ struct RGBImage {
 
 struct MemoryImage {
   uintptr_t data;
   gfxIntSize size;
   uint32_t stride;
   uint32_t format;
 };
 
+/**
+ * Used for shmem-backed YCbCr and (flavors of) RGBA textures
+ */
+struct SurfaceDescriptorShmem {
+  Shmem data;
+  SurfaceFormat format;
+};
+
+/**
+ * Used for "raw memory"-backed YCbCr and (flavors of) RGBA textures
+ */
+ struct SurfaceDescriptorMemory {
+  uintptr_t data;
+  SurfaceFormat format;
+};
+
 union SurfaceDescriptor {
-  Shmem;
+  SurfaceDescriptorShmem;
+  SurfaceDescriptorMemory;
   SurfaceDescriptorD3D10;
-  SurfaceDescriptorGralloc;
   SurfaceDescriptorX11;
-  YCbCrImage;
-  RGBImage;
   SharedTextureDescriptor;
   SurfaceStreamDescriptor;
-  MemoryImage;
+  YCbCrImage;                 // XXX - deprecated
+  SurfaceDescriptorGralloc;   // XXX - deprecated
+  Shmem;                      // XXX - deprecated
+  RGBImage;                   // XXX - deprecated
+  MemoryImage;                // XXX - deprecated
   null_t;
 };
 
 } // namespace
 } // namespace
--- a/gfx/layers/ipc/ShadowLayers.cpp
+++ b/gfx/layers/ipc/ShadowLayers.cpp
@@ -369,16 +369,63 @@ ShadowLayerForwarder::UpdateTextureIncre
 
 void
 ShadowLayerForwarder::UpdatePictureRect(CompositableClient* aCompositable,
                                         const nsIntRect& aRect)
 {
   mTxn->AddNoSwapPaint(OpUpdatePictureRect(nullptr, aCompositable->GetIPDLActor(), aRect));
 }
 
+void
+ShadowLayerForwarder::AddTexture(CompositableClient* aCompositable,
+                                 TextureClient* aTexture)
+{
+  SurfaceDescriptor descriptor;
+  if (!aTexture->ToSurfaceDescriptor(descriptor)) {
+    NS_WARNING("Failed to serialize a TextureClient");
+    return;
+  }
+  mTxn->AddEdit(OpAddTexture(nullptr, aCompositable->GetIPDLActor(),
+                             aTexture->GetID(),
+                             descriptor,
+                             aTexture->GetFlags()));
+}
+
+void
+ShadowLayerForwarder::RemoveTexture(CompositableClient* aCompositable,
+                                    uint64_t aTexture,
+                                    TextureFlags aFlags)
+{
+  mTxn->AddEdit(OpRemoveTexture(nullptr,
+                aCompositable->GetIPDLActor(),
+                aTexture,
+                aFlags));
+}
+
+void
+ShadowLayerForwarder::UpdatedTexture(CompositableClient* aCompositable,
+                                     TextureClient* aTexture,
+                                     nsIntRegion* aRegion)
+{
+  printf("ShadowLayerForwarder::UpdatedTexture %i\n", (int)aTexture->GetID());
+  MaybeRegion region = aRegion ? MaybeRegion(*aRegion)
+                               : MaybeRegion(null_t());
+  mTxn->AddEdit(OpUpdateTexture(nullptr, aCompositable->GetIPDLActor(),
+                                aTexture->GetID(),
+                                region));
+}
+
+void
+ShadowLayerForwarder::UseTexture(CompositableClient* aCompositable,
+                                 TextureClient* aTexture)
+{
+  mTxn->AddEdit(OpUseTexture(nullptr, aCompositable->GetIPDLActor(),
+                             aTexture->GetID()));
+}
+
 bool
 ShadowLayerForwarder::EndTransaction(InfallibleTArray<EditReply>* aReplies)
 {
   PROFILER_LABEL("ShadowLayerForwarder", "EndTranscation");
   RenderTraceScope rendertrace("Foward Transaction", "000091");
   NS_ABORT_IF_FALSE(HasShadowManager(), "no manager to forward to");
   NS_ABORT_IF_FALSE(!mTxn->Finished(), "forgot BeginTransaction?");
 
--- a/gfx/layers/ipc/ShadowLayers.h
+++ b/gfx/layers/ipc/ShadowLayers.h
@@ -47,21 +47,23 @@ class CanvasLayerComposite;
 class RefLayerComposite;
 class SurfaceDescriptor;
 class ThebesBuffer;
 class TiledLayerComposer;
 class Transaction;
 class SurfaceDescriptor;
 class CanvasSurface;
 class DeprecatedTextureClientShmem;
+class ShmemTextureClient;
 class ContentClientRemote;
 class CompositableChild;
 class ImageClient;
 class CanvasClient;
 class ContentClient;
+class TextureClient;
 
 
 /**
  * We want to share layer trees across thread contexts and address
  * spaces for several reasons; chief among them
  *
  *  - a parent process can paint a child process's layer tree while
  *    the child process is blocked, say on content script.  This is
@@ -299,16 +301,42 @@ public:
 
   /**
    * Communicate the picture rect of an image to the compositor
    */
   void UpdatePictureRect(CompositableClient* aCompositable,
                          const nsIntRect& aRect);
 
   /**
+   * See CompositableForwarder::AddTexture
+   */
+  virtual void AddTexture(CompositableClient* aCompositable,
+                          TextureClient* aClient) MOZ_OVERRIDE;
+
+  /**
+   * See CompositableForwarder::RemoveTexture
+   */
+  virtual void RemoveTexture(CompositableClient* aCompositable,
+                             uint64_t aTextureID,
+                             TextureFlags aFlags) MOZ_OVERRIDE;
+
+  /**
+   * See CompositableForwarder::UpdatedTexture
+   */
+  virtual void UpdatedTexture(CompositableClient* aCompositable,
+                              TextureClient* aTexture,
+                              nsIntRegion* aRegion) MOZ_OVERRIDE;
+
+  /**
+   * See CompositableForwarder::UseTexture
+   */
+  virtual void UseTexture(CompositableClient* aCompositable,
+                          TextureClient* aClient) MOZ_OVERRIDE;
+
+  /**
    * End the current transaction and forward it to LayerManagerComposite.
    * |aReplies| are directions from the LayerManagerComposite to the
    * caller of EndTransaction().
    */
   bool EndTransaction(InfallibleTArray<EditReply>* aReplies);
 
   /**
    * Set an actor through which layer updates will be pushed.
--- a/gfx/layers/ipc/SharedPlanarYCbCrImage.cpp
+++ b/gfx/layers/ipc/SharedPlanarYCbCrImage.cpp
@@ -2,32 +2,189 @@
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "SharedPlanarYCbCrImage.h"
 #include "mozilla/layers/YCbCrImageDataSerializer.h"
 #include "ISurfaceAllocator.h"
 #include "mozilla/layers/LayersSurfaces.h"
+#include "mozilla/layers/TextureClient.h"
+#include "mozilla/layers/ImageClient.h"
 
 namespace mozilla {
 namespace layers {
 
 using namespace mozilla::ipc;
 
+SharedPlanarYCbCrImage::SharedPlanarYCbCrImage(ImageClient* aCompositable)
+: PlanarYCbCrImage(nullptr)
+{
+  mTextureClient = aCompositable->CreateBufferTextureClient(gfx::FORMAT_YUV);
+  MOZ_COUNT_CTOR(SharedPlanarYCbCrImage);
+}
+
+SharedPlanarYCbCrImage::~SharedPlanarYCbCrImage() {
+  MOZ_COUNT_DTOR(SharedPlanarYCbCrImage);
+}
+
+
 DeprecatedSharedPlanarYCbCrImage::~DeprecatedSharedPlanarYCbCrImage() {
   MOZ_COUNT_DTOR(DeprecatedSharedPlanarYCbCrImage);
 
   if (mAllocated) {
     SurfaceDescriptor desc;
     DropToSurfaceDescriptor(desc);
     mSurfaceAllocator->DestroySharedSurface(&desc);
   }
 }
 
+TextureClient*
+SharedPlanarYCbCrImage::GetTextureClient()
+{
+  return mTextureClient.get();
+}
+
+uint8_t*
+SharedPlanarYCbCrImage::GetBuffer()
+{
+  return mTextureClient->GetBuffer();
+}
+
+already_AddRefed<gfxASurface>
+SharedPlanarYCbCrImage::GetAsSurface()
+{
+  if (!mTextureClient->IsAllocated()) {
+    NS_WARNING("Can't get as surface");
+    return nullptr;
+  }
+  return PlanarYCbCrImage::GetAsSurface();
+}
+
+void
+SharedPlanarYCbCrImage::SetData(const PlanarYCbCrImage::Data& aData)
+{
+  // If mShmem has not been allocated (through Allocate(aData)), allocate it.
+  // This code path is slower than the one used when Allocate has been called
+  // since it will trigger a full copy.
+  if (!mTextureClient->IsAllocated()) {
+    Data data = aData;
+    if (!Allocate(data)) {
+      printf("SharedPlanarYCbCrImage::SetData failed to allocate :(\n");
+      return;
+    }
+  }
+
+  MOZ_ASSERT(mTextureClient->AsTextureClientYCbCr());
+
+  if (!mTextureClient->AsTextureClientYCbCr()->UpdateYCbCr(aData)) {
+    MOZ_ASSERT(false, "Failed to copy YCbCr data into the TextureClient");
+    return;
+  }
+
+  // do not set mBuffer like in PlanarYCbCrImage because the later
+  // will try to manage this memory without knowing it belongs to a
+  // shmem.
+  mBufferSize = YCbCrImageDataSerializer::ComputeMinBufferSize(mData.mYSize,
+                                                               mData.mCbCrSize);
+  mSize = mData.mPicSize;
+
+  YCbCrImageDataSerializer serializer(mTextureClient->GetBuffer());
+  mData.mYChannel = serializer.GetYData();
+  mData.mCbChannel = serializer.GetCbData();
+  mData.mCrChannel = serializer.GetCrData();
+  mTextureClient->MarkImmutable();
+}
+
+// needs to be overriden because the parent class sets mBuffer which we
+// do not want to happen.
+uint8_t*
+SharedPlanarYCbCrImage::AllocateAndGetNewBuffer(uint32_t aSize)
+{
+  NS_ABORT_IF_FALSE(!mTextureClient->IsAllocated(), "This image already has allocated data");
+  size_t size = YCbCrImageDataSerializer::ComputeMinBufferSize(aSize);
+  // update buffer size
+  mBufferSize = size;
+
+  // get new buffer _without_ setting mBuffer.
+  bool status = mTextureClient->Allocate(mBufferSize);
+  MOZ_ASSERT(status);
+  YCbCrImageDataSerializer serializer(mTextureClient->GetBuffer());
+
+  return serializer.GetData();
+}
+
+void
+SharedPlanarYCbCrImage::SetDataNoCopy(const Data &aData)
+{
+  mData = aData;
+  mSize = aData.mPicSize;
+  YCbCrImageDataSerializer serializer(mTextureClient->GetBuffer());
+  serializer.InitializeBufferInfo(aData.mYSize,
+                                  aData.mCbCrSize);
+}
+
+uint8_t*
+SharedPlanarYCbCrImage::AllocateBuffer(uint32_t aSize)
+{
+  NS_ABORT_IF_FALSE(!mTextureClient->IsAllocated(),
+                    "This image already has allocated data");
+  if (!mTextureClient->Allocate(aSize)) {
+    return nullptr;
+  }
+  return mTextureClient->GetBuffer();
+}
+
+bool
+SharedPlanarYCbCrImage::IsValid() {
+  return mTextureClient->IsAllocated();
+}
+
+bool
+SharedPlanarYCbCrImage::Allocate(PlanarYCbCrImage::Data& aData)
+{
+  NS_ABORT_IF_FALSE(!mTextureClient->IsAllocated(),
+                    "This image already has allocated data");
+
+  size_t size = YCbCrImageDataSerializer::ComputeMinBufferSize(aData.mYSize,
+                                                               aData.mCbCrSize);
+
+  if (AllocateBuffer(static_cast<uint32_t>(size)) == nullptr) {
+    return false;
+  }
+
+  YCbCrImageDataSerializer serializer(mTextureClient->GetBuffer());
+  serializer.InitializeBufferInfo(aData.mYSize,
+                                  aData.mCbCrSize);
+  MOZ_ASSERT(serializer.IsValid());
+
+  aData.mYChannel = serializer.GetYData();
+  aData.mCbChannel = serializer.GetCbData();
+  aData.mCrChannel = serializer.GetCrData();
+
+  // copy some of aData's values in mData (most of them)
+  mData.mYChannel = aData.mYChannel;
+  mData.mCbChannel = aData.mCbChannel;
+  mData.mCrChannel = aData.mCrChannel;
+  mData.mYSize = aData.mYSize;
+  mData.mCbCrSize = aData.mCbCrSize;
+  mData.mPicX = aData.mPicX;
+  mData.mPicY = aData.mPicY;
+  mData.mPicSize = aData.mPicSize;
+  mData.mStereoMode = aData.mStereoMode;
+  // those members are not always equal to aData's, due to potentially different
+  // packing.
+  mData.mYSkip = 0;
+  mData.mCbSkip = 0;
+  mData.mCrSkip = 0;
+  mData.mYStride = mData.mYSize.width;
+  mData.mCbCrStride = mData.mCbCrSize.width;
+
+  return true;
+}
 
 void
 DeprecatedSharedPlanarYCbCrImage::SetData(const PlanarYCbCrImage::Data& aData)
 {
   // If mShmem has not been allocated (through Allocate(aData)), allocate it.
   // This code path is slower than the one used when Allocate has been called
   // since it will trigger a full copy.
   if (!mAllocated) {
--- a/gfx/layers/ipc/SharedPlanarYCbCrImage.h
+++ b/gfx/layers/ipc/SharedPlanarYCbCrImage.h
@@ -10,17 +10,20 @@
 
 #ifndef MOZILLA_LAYERS_DeprecatedSharedPlanarYCbCrImage_H
 #define MOZILLA_LAYERS_DeprecatedSharedPlanarYCbCrImage_H
 
 namespace mozilla {
 namespace layers {
 
 class ImageClient;
+class TextureClient;
+class BufferTextureClient;
 
+// XXX - This class will be removed along with DeprecatedImageClient
 class DeprecatedSharedPlanarYCbCrImage : public PlanarYCbCrImage
 {
 public:
   DeprecatedSharedPlanarYCbCrImage(ISurfaceAllocator* aAllocator)
   : PlanarYCbCrImage(nullptr)
   , mSurfaceAllocator(aAllocator), mAllocated(false)
   {
     MOZ_COUNT_CTOR(DeprecatedSharedPlanarYCbCrImage);
@@ -77,12 +80,40 @@ public:
   static DeprecatedSharedPlanarYCbCrImage* FromSurfaceDescriptor(const SurfaceDescriptor& aDesc);
 
 private:
   ipc::Shmem mShmem;
   ISurfaceAllocator* mSurfaceAllocator;
   bool mAllocated;
 };
 
+
+class SharedPlanarYCbCrImage : public PlanarYCbCrImage
+                             , public ISharedImage
+{
+public:
+  SharedPlanarYCbCrImage(ImageClient* aCompositable);
+  ~SharedPlanarYCbCrImage();
+
+  virtual ISharedImage* AsSharedImage() MOZ_OVERRIDE { return this; }
+  virtual TextureClient* GetTextureClient() MOZ_OVERRIDE;
+  virtual uint8_t* GetBuffer() MOZ_OVERRIDE;
+
+  virtual already_AddRefed<gfxASurface> GetAsSurface() MOZ_OVERRIDE;
+  virtual void SetData(const PlanarYCbCrImage::Data& aData) MOZ_OVERRIDE;
+  virtual void SetDataNoCopy(const Data &aData) MOZ_OVERRIDE;
+
+  virtual bool Allocate(PlanarYCbCrImage::Data& aData);
+  virtual uint8_t* AllocateBuffer(uint32_t aSize) MOZ_OVERRIDE;
+  // needs to be overriden because the parent class sets mBuffer which we
+  // do not want to happen.
+  virtual uint8_t* AllocateAndGetNewBuffer(uint32_t aSize) MOZ_OVERRIDE;
+
+  virtual bool IsValid() MOZ_OVERRIDE;
+
+private:
+  RefPtr<BufferTextureClient> mTextureClient;
+};
+
 } // namespace
 } // namespace
 
 #endif
--- a/gfx/layers/ipc/SharedRGBImage.cpp
+++ b/gfx/layers/ipc/SharedRGBImage.cpp
@@ -2,16 +2,19 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "ShadowLayers.h"
 #include "SharedRGBImage.h"
 #include "mozilla/layers/LayersSurfaces.h"
 #include "Shmem.h"
 #include "mozilla/layers/ISurfaceAllocator.h"
+#include "mozilla/layers/TextureClient.h"
+#include "mozilla/layers/ImageClient.h"
+#include "gfx2DGlue.h"
 
 // Just big enough for a 1080p RGBA32 frame
 #define MAX_FRAME_SIZE (16 * 1024 * 1024)
 
 namespace mozilla {
 namespace layers {
 
 DeprecatedSharedRGBImage::DeprecatedSharedRGBImage(ISurfaceAllocator *aAllocator) :
@@ -31,20 +34,20 @@ DeprecatedSharedRGBImage::~DeprecatedSha
   if (mAllocated) {
     SurfaceDescriptor desc;
     DropToSurfaceDescriptor(desc);
     mSurfaceAllocator->DestroySharedSurface(&desc);
   }
   delete mShmem;
 }
 
-already_AddRefed<DeprecatedSharedRGBImage>
-DeprecatedSharedRGBImage::Create(ImageContainer *aImageContainer,
-                       nsIntSize aSize,
-                       gfxImageFormat aImageFormat)
+already_AddRefed<Image>
+CreateSharedRGBImage(ImageContainer *aImageContainer,
+                     nsIntSize aSize,
+                     gfxImageFormat aImageFormat)
 {
   NS_ASSERTION(aImageFormat == gfxASurface::ImageFormatARGB32 ||
                aImageFormat == gfxASurface::ImageFormatRGB24 ||
                aImageFormat == gfxASurface::ImageFormatRGB16_565,
                "RGB formats supported only");
 
   if (!aImageContainer) {
     NS_WARNING("No ImageContainer to allocate DeprecatedSharedRGBImage");
@@ -54,26 +57,31 @@ DeprecatedSharedRGBImage::Create(ImageCo
   ImageFormat format = SHARED_RGB;
   nsRefPtr<Image> image = aImageContainer->CreateImage(&format, 1);
 
   if (!image) {
     NS_WARNING("Failed to create DeprecatedSharedRGBImage");
     return nullptr;
   }
 
-  nsRefPtr<DeprecatedSharedRGBImage> rgbImage = static_cast<DeprecatedSharedRGBImage*>(image.get());
-  rgbImage->mSize = gfxIntSize(aSize.width, aSize.height);
-  rgbImage->mImageFormat = aImageFormat;
+  if (gfxPlatform::GetPlatform()->UseDeprecatedTextures()) {
+      nsRefPtr<DeprecatedSharedRGBImage> rgbImageDep = static_cast<DeprecatedSharedRGBImage*>(image.get());
+      rgbImageDep->mSize = gfxIntSize(aSize.width, aSize.height);
+      rgbImageDep->mImageFormat = aImageFormat;
 
-  if (!rgbImage->AllocateBuffer(aSize, aImageFormat)) {
-    NS_WARNING("Failed to allocate shared memory for DeprecatedSharedRGBImage");
-    return nullptr;
+      if (!rgbImageDep->AllocateBuffer(aSize, aImageFormat)) {
+        NS_WARNING("Failed to allocate shared memory for DeprecatedSharedRGBImage");
+        return nullptr;
+      }
+      return rgbImageDep.forget();
   }
-
-  return rgbImage.forget();
+  nsRefPtr<SharedRGBImage> rgbImage = static_cast<SharedRGBImage*>(image.get());
+  rgbImage->Allocate(gfx::ToIntSize(aSize),
+                     gfx::ImageFormatToSurfaceFormat(aImageFormat));
+  return image.forget();
 }
 
 uint8_t *
 DeprecatedSharedRGBImage::GetBuffer()
 {
   return mShmem->get<uint8_t>();
 }
 
@@ -152,11 +160,63 @@ DeprecatedSharedRGBImage::FromSurfaceDes
   }
   const RGBImage& rgb = aDescriptor.get_RGBImage();
   if (rgb.owner() == 0) {
     return nullptr;
   }
   return reinterpret_cast<DeprecatedSharedRGBImage*>(rgb.owner());
 }
 
+SharedRGBImage::SharedRGBImage(ImageClient* aCompositable)
+: Image(nullptr, SHARED_RGB)
+, mCompositable(aCompositable)
+{
+  MOZ_COUNT_CTOR(SharedRGBImage);
+}
+
+SharedRGBImage::~SharedRGBImage()
+{
+  MOZ_COUNT_DTOR(SharedRGBImage);
+}
+
+bool
+SharedRGBImage::Allocate(gfx::IntSize aSize, gfx::SurfaceFormat aFormat)
+{
+  mSize = aSize;
+  mTextureClient = mCompositable->CreateBufferTextureClient(aFormat);
+  return mTextureClient->AllocateForSurface(aSize);
+}
+
+uint8_t*
+SharedRGBImage::GetBuffer()
+{
+  return mTextureClient ? mTextureClient->GetBuffer()
+                        : nullptr;
+}
+
+gfxIntSize
+SharedRGBImage::GetSize()
+{
+  return ThebesIntSize(mSize);
+}
+
+size_t
+SharedRGBImage::GetBufferSize()
+{
+  return mTextureClient ? mTextureClient->GetBufferSize()
+                        : 0;
+}
+
+TextureClient*
+SharedRGBImage::GetTextureClient()
+{
+  return mTextureClient.get();
+}
+
+already_AddRefed<gfxASurface>
+SharedRGBImage::GetAsSurface()
+{
+  return nullptr;
+}
+
 
 } // namespace layers
 } // namespace mozilla
--- a/gfx/layers/ipc/SharedRGBImage.h
+++ b/gfx/layers/ipc/SharedRGBImage.h
@@ -8,35 +8,43 @@
 #include "ImageContainer.h"
 #include "ISurfaceAllocator.h"
 
 namespace mozilla {
 namespace ipc {
 class Shmem;
 }
 namespace layers {
+class BufferTextureClient;
+class TextureClient;
+class ImageClient;
+
+already_AddRefed<Image> CreateSharedRGBImage(ImageContainer* aImageContainer,
+                                             nsIntSize aSize,
+                                             gfxASurface::gfxImageFormat aImageFormat);
 
 /**
  * Stores RGB data in shared memory
  * It is assumed that the image width and stride are equal
  */
-class DeprecatedSharedRGBImage : public Image
+class DeprecatedSharedRGBImage : public Image,
+                                 public ISharedImage
 {
+friend already_AddRefed<Image> CreateSharedRGBImage(ImageContainer* aImageContainer,
+                                                    nsIntSize aSize,
+                                                    gfxASurface::gfxImageFormat aImageFormat);
+public:
   typedef gfxASurface::gfxImageFormat gfxImageFormat;
-public:
   struct Header {
     gfxImageFormat mImageFormat;
   };
 
   DeprecatedSharedRGBImage(ISurfaceAllocator *aAllocator);
   ~DeprecatedSharedRGBImage();
 
-  static already_AddRefed<DeprecatedSharedRGBImage> Create(ImageContainer* aImageContainer,
-                                                 nsIntSize aSize,
-                                                 gfxImageFormat aImageFormat);
   uint8_t *GetBuffer();
 
   gfxIntSize GetSize();
   size_t GetBufferSize();
 
   static uint8_t BytesPerPixel(gfxImageFormat aImageFormat);
   already_AddRefed<gfxASurface> GetAsSurface();
 
@@ -56,23 +64,54 @@ public:
   bool DropToSurfaceDescriptor(SurfaceDescriptor& aResult);
 
   /**
    * Returns a DeprecatedSharedRGBImage* iff the descriptor was initialized with
    * ToSurfaceDescriptor.
    */
   static DeprecatedSharedRGBImage* FromSurfaceDescriptor(const SurfaceDescriptor& aDescriptor);
 
-private:
   bool AllocateBuffer(nsIntSize aSize, gfxImageFormat aImageFormat);
 
+  TextureClient* GetTextureClient() MOZ_OVERRIDE { return nullptr; }
+
+protected:
   gfxIntSize mSize;
   gfxImageFormat mImageFormat;
   ISurfaceAllocator* mSurfaceAllocator;
 
   bool mAllocated;
   ipc::Shmem *mShmem;
 };
 
+/**
+ * Stores RGB data in shared memory
+ * It is assumed that the image width and stride are equal
+ */
+class SharedRGBImage : public Image
+                     , public ISharedImage
+{
+  typedef gfxASurface::gfxImageFormat gfxImageFormat;
+public:
+  SharedRGBImage(ImageClient* aCompositable);
+  ~SharedRGBImage();
+
+  virtual TextureClient* GetTextureClient() MOZ_OVERRIDE;
+
+  virtual uint8_t* GetBuffer() MOZ_OVERRIDE;
+
+  gfxIntSize GetSize();
+
+  size_t GetBufferSize();
+
+  already_AddRefed<gfxASurface> GetAsSurface();
+
+  bool Allocate(gfx::IntSize aSize, gfx::SurfaceFormat aFormat);
+private:
+  gfx::IntSize mSize;
+  RefPtr<ImageClient> mCompositable;
+  RefPtr<BufferTextureClient> mTextureClient;
+};
+
 } // namespace layers
 } // namespace mozilla
 
 #endif
--- a/gfx/layers/moz.build
+++ b/gfx/layers/moz.build
@@ -89,16 +89,17 @@ EXPORTS.gfxipc += [
     'ipc/ShadowLayerUtils.h',
 ]
 
 EXPORTS.mozilla.layers += [
     'Compositor.h',
     'CompositorTypes.h',
     'D3D9SurfaceImage.h',
     'Effects.h',
+    'ImageDataSerializer.h',
     'LayersTypes.h',
     'RenderTrace.h',
     'YCbCrImageDataSerializer.h',
     'basic/BasicCompositor.h',
     'client/CanvasClient.h',
     'client/CompositableClient.h',
     'client/ContentClient.h',
     'client/ImageClient.h',
@@ -208,16 +209,17 @@ CPP_SOURCES += [
     'CopyableCanvasLayer.cpp',
     'Effects.cpp',
     'GestureEventListener.cpp',
     'ISurfaceAllocator.cpp',
     'ImageBridgeChild.cpp',
     'ImageBridgeParent.cpp',
     'ImageClient.cpp',
     'ImageContainer.cpp',
+    'ImageDataSerializer.cpp',
     'ImageHost.cpp',
     'ImageLayerComposite.cpp',
     'ImageLayerOGL.cpp',
     'ImageLayers.cpp',
     'LayerManagerComposite.cpp',
     'LayerManagerOGL.cpp',
     'LayerManagerOGLProgram.cpp',
     'LayerSorter.cpp',
--- a/gfx/layers/opengl/CompositingRenderTargetOGL.h
+++ b/gfx/layers/opengl/CompositingRenderTargetOGL.h
@@ -18,17 +18,16 @@ namespace mozilla {
 namespace gl {
   class TextureImage;
   class BindableTexture;
 }
 namespace layers {
 
 class CompositingRenderTargetOGL : public CompositingRenderTarget
 {
-  typedef gfxASurface::gfxContentType ContentType;
   typedef mozilla::gl::GLContext GLContext;
 
   // For lazy initialisation of the GL stuff
   struct InitParams
   {
     InitParams() : mStatus(NO_PARAMS) {}
     InitParams(const gfx::IntSize& aSize,
                GLenum aFBOTextureTarget,
@@ -146,16 +145,23 @@ public:
     return nullptr;
   }
   gfx::IntSize GetSize() const MOZ_OVERRIDE
   {
     MOZ_ASSERT(false, "CompositingRenderTargetOGL should not be used as a TextureSource");
     return gfx::IntSize(0, 0);
   }
 
+  gfx::SurfaceFormat GetFormat() const MOZ_OVERRIDE
+  {
+    // XXX - Should it be implemented ? is the above assert true ?
+    MOZ_ASSERT(false, "Not implemented");
+    return gfx::FORMAT_UNKNOWN;
+  }
+
   const gfxMatrix& GetTransform() {
     return mTransform;
   }
 
 #ifdef MOZ_DUMP_PAINTING
   virtual already_AddRefed<gfxImageSurface> Dump(Compositor* aCompositor)
   {
     MOZ_ASSERT(mInitParams.mStatus == InitParams::INITIALIZED);
--- a/gfx/layers/opengl/CompositorOGL.cpp
+++ b/gfx/layers/opengl/CompositorOGL.cpp
@@ -940,17 +940,17 @@ CompositorOGL::GetProgramTypeForEffect(E
   case EFFECT_BGRA:
   case EFFECT_BGRX:
   {
     TexturedEffect* texturedEffect =
         static_cast<TexturedEffect*>(aEffect);
     TextureSourceOGL* source = texturedEffect->mTexture->AsSourceOGL();
 
     return ShaderProgramFromTargetAndFormat(source->GetTextureTarget(),
-                                            source->GetTextureFormat());
+                                            source->GetFormat());
   }
   case EFFECT_YCBCR:
     return YCbCrLayerProgramType;
   case EFFECT_RENDER_TARGET:
     return GetFBOLayerProgramType();
   default:
     return RGBALayerProgramType;
   }
@@ -1406,11 +1406,18 @@ bool
 CompositorOGL::Resume()
 {
 #ifdef MOZ_WIDGET_ANDROID
   return gl()->RenewSurface();
 #endif
   return true;
 }
 
+TemporaryRef<DataTextureSource>
+CompositorOGL::CreateDataTextureSource(TextureFlags aFlags)
+{
+  RefPtr<DataTextureSource> result =
+    new TextureImageTextureSourceOGL(mGLContext, !(aFlags & ForceSingleTile));
+  return result;
+}
 
 } /* layers */
 } /* mozilla */
--- a/gfx/layers/opengl/CompositorOGL.h
+++ b/gfx/layers/opengl/CompositorOGL.h
@@ -29,16 +29,19 @@ class CompositorOGL : public Compositor
   friend class GLManagerCompositor;
 
 public:
   CompositorOGL(nsIWidget *aWidget, int aSurfaceWidth = -1, int aSurfaceHeight = -1,
                 bool aUseExternalSurfaceSize = false);
 
   virtual ~CompositorOGL();
 
+  virtual TemporaryRef<DataTextureSource>
+  CreateDataTextureSource(TextureFlags aFlags = 0) MOZ_OVERRIDE;
+
   virtual bool Initialize() MOZ_OVERRIDE;
 
   virtual void Destroy() MOZ_OVERRIDE;
 
   virtual TextureFactoryIdentifier GetTextureFactoryIdentifier() MOZ_OVERRIDE
   {
     return TextureFactoryIdentifier(LAYERS_OPENGL,
                                     GetMaxTextureSize(),
--- a/gfx/layers/opengl/TextureClientOGL.cpp
+++ b/gfx/layers/opengl/TextureClientOGL.cpp
@@ -1,21 +1,69 @@
 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/layers/TextureClientOGL.h"
+#include "mozilla/layers/CompositableClient.h"
+#include "mozilla/layers/CompositableForwarder.h"
 #include "GLContext.h"
+#include "gfxipc/ShadowLayerUtils.h"
 
 using namespace mozilla::gl;
 
 namespace mozilla {
 namespace layers {
 
+SharedTextureClientOGL::SharedTextureClientOGL()
+: mHandle(0), mIsCrossProcess(false), mInverted(false)
+{
+}
+
+SharedTextureClientOGL::~SharedTextureClientOGL()
+{
+  // the data is released by the host
+}
+
+
+bool
+SharedTextureClientOGL::ToSurfaceDescriptor(SurfaceDescriptor& aOutDescriptor)
+{
+  if (!IsAllocated()) {
+    return false;
+  }
+  nsIntSize nsSize(mSize.width, mSize.height);
+  aOutDescriptor = SharedTextureDescriptor(mIsCrossProcess ? gl::GLContext::CrossProcess
+                                                           : gl::GLContext::SameProcess,
+                                           mHandle, nsSize, mInverted);
+  return true;
+}
+
+void
+SharedTextureClientOGL::InitWith(gl::SharedTextureHandle aHandle,
+                                 gfx::IntSize aSize,
+                                 bool aIsCrossProcess,
+                                 bool aInverted)
+{
+  MOZ_ASSERT(!IsAllocated());
+  mHandle = aHandle;
+  mSize = aSize;
+  mIsCrossProcess = aIsCrossProcess;
+  mInverted = aInverted;
+}
+
+bool
+SharedTextureClientOGL::IsAllocated() const
+{
+  return mHandle != 0;
+}
+
+
+
 DeprecatedTextureClientSharedOGL::DeprecatedTextureClientSharedOGL(CompositableForwarder* aForwarder,
                                                const TextureInfo& aTextureInfo)
   : DeprecatedTextureClient(aForwarder, aTextureInfo)
   , mGL(nullptr)
 {
 }
 
 void
--- a/gfx/layers/opengl/TextureClientOGL.h
+++ b/gfx/layers/opengl/TextureClientOGL.h
@@ -3,20 +3,57 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef MOZILLA_GFX_TEXTURECLIENTOGL_H
 #define MOZILLA_GFX_TEXTURECLIENTOGL_H
 
 #include "mozilla/layers/TextureClient.h"
 #include "ISurfaceAllocator.h" // For IsSurfaceDescriptorValid
+#include "GLContext.h" // For SharedTextureHandle
+
+#ifdef MOZ_WIDGET_GONK
+#include <ui/GraphicBuffer.h>
+#endif
 
 namespace mozilla {
 namespace layers {
 
+
+
+/**
+ * A TextureClient implementation to share TextureMemory that is already
+ * on the GPU, for the OpenGL backend.
+ */
+class SharedTextureClientOGL : public TextureClient
+{
+public:
+  SharedTextureClientOGL();
+
+  ~SharedTextureClientOGL();
+
+  virtual bool IsAllocated() const MOZ_OVERRIDE;
+
+  virtual bool ToSurfaceDescriptor(SurfaceDescriptor& aOutDescriptor) MOZ_OVERRIDE;
+
+  void InitWith(gl::SharedTextureHandle aHandle,
+                gfx::IntSize aSize,
+                bool aIsCrossProcess = false,
+                bool aInverted = false);
+
+  gfx::IntSize GetSize() const { return mSize; }
+
+protected:
+  gfx::IntSize mSize;
+  gl::SharedTextureHandle mHandle;
+  bool mIsCrossProcess;
+  bool mInverted;
+};
+
+
 class DeprecatedTextureClientSharedOGL : public DeprecatedTextureClient
 {
 public:
   DeprecatedTextureClientSharedOGL(CompositableForwarder* aForwarder, const TextureInfo& aTextureInfo);
   ~DeprecatedTextureClientSharedOGL() { ReleaseResources(); }
 
   virtual bool SupportsType(DeprecatedTextureClientType aType) MOZ_OVERRIDE { return aType == TEXTURE_SHARED_GL; }
   virtual void EnsureAllocated(gfx::IntSize aSize, gfxASurface::gfxContentType aType);
--- a/gfx/layers/opengl/TextureHostOGL.cpp
+++ b/gfx/layers/opengl/TextureHostOGL.cpp
@@ -48,16 +48,45 @@ CreateDeprecatedTextureHostOGL(SurfaceDe
   }
 
   NS_ASSERTION(result, "Result should have been created.");
 
   result->SetFlags(aTextureFlags);
   return result.forget();
 }
 
+
+TemporaryRef<TextureHost>
+CreateTextureHostOGL(uint64_t aID,
+                     const SurfaceDescriptor& aDesc,
+                     ISurfaceAllocator* aDeallocator,
+                     TextureFlags aFlags)
+{
+  RefPtr<TextureHost> result;
+  switch (aDesc.type()) {
+    case SurfaceDescriptor::TSurfaceDescriptorShmem:
+    case SurfaceDescriptor::TSurfaceDescriptorMemory: {
+      result = CreateBackendIndependentTextureHost(aID, aDesc,
+                                                   aDeallocator, aFlags);
+      break;
+    }
+    case SurfaceDescriptor::TSharedTextureDescriptor: {
+      const SharedTextureDescriptor& desc = aDesc.get_SharedTextureDescriptor();
+      result = new SharedTextureHostOGL(aID, aFlags,
+                                        desc.shareType(),
+                                        desc.handle(),
+                                        gfx::ToIntSize(desc.size()),
+                                        desc.inverted());
+      break;
+    }
+    default: return nullptr;
+  }
+  return result.forget();
+}
+
 static void
 MakeTextureIfNeeded(gl::GLContext* gl, GLenum aTarget, GLuint& aTexture)
 {
   if (aTexture != 0)
     return;
 
   GLenum target = aTarget;
   // GL_TEXTURE_EXTERNAL requires us to initialize the texture
@@ -97,16 +126,230 @@ WrapMode(gl::GLContext *aGl, bool aAllow
   if (aAllowRepeat &&
       (aGl->IsExtensionSupported(GLContext::ARB_texture_non_power_of_two) ||
        aGl->IsExtensionSupported(GLContext::OES_texture_npot))) {
     return LOCAL_GL_REPEAT;
   }
   return LOCAL_GL_CLAMP_TO_EDGE;
 }
 
+bool
+TextureImageTextureSourceOGL::Update(gfx::DataSourceSurface* aSurface,
+                                     TextureFlags aFlags,
+                                     nsIntRegion* aDestRegion,
+                                     gfx::IntPoint* aSrcOffset)
+{
+  MOZ_ASSERT(mGL);
+  if (!mGL) {
+    NS_WARNING("trying to update TextureImageTextureSourceOGL without a GLContext");
+    return false;
+  }
+  MOZ_ASSERT(aSurface);
+
+  nsIntSize size = ThebesIntSize(aSurface->GetSize());
+  if (!mTexImage ||
+      mTexImage->GetSize() != size ||
+      mTexImage->GetContentType() != gfx::ContentForFormat(aSurface->GetFormat())) {
+    if (mAllowTiling) {
+      // XXX - clarify the which size we want to use. Some use cases may
+      // require the size of the destnation surface to be different from
+      // the size of aSurface.
+      mTexImage = mGL->CreateTextureImage(size,
+                                          gfx::ContentForFormat(aSurface->GetFormat()),
+                                          WrapMode(mGL, aFlags & AllowRepeat),
+                                          FlagsToGLFlags(aFlags));
+    } else {
+      mTexImage = CreateBasicTextureImage(mGL,
+                                          size,
+                                          gfx::ContentForFormat(aSurface->GetFormat()),
+                                          WrapMode(mGL, aFlags & AllowRepeat),
+                                          FlagsToGLFlags(aFlags));
+    }
+  }
+
+  mTexImage->UpdateFromDataSource(aSurface, aDestRegion, aSrcOffset);
+
+  if (mTexImage->InUpdate()) {
+    mTexImage->EndUpdate();
+  }
+  return true;
+}
+
+gfx::IntSize
+TextureImageTextureSourceOGL::GetSize() const
+{
+  if (mTexImage) {
+    if (mIterating) {
+      nsIntRect rect = mTexImage->GetTileRect();
+      return gfx::IntSize(rect.width, rect.height);
+    }
+    return gfx::IntSize(mTexImage->GetSize().width, mTexImage->GetSize().height);
+  }
+  NS_WARNING("Trying to query the size of an empty TextureSource.");
+  return gfx::IntSize(0, 0);
+}
+
+gfx::SurfaceFormat
+TextureImageTextureSourceOGL::GetFormat() const
+{
+  MOZ_ASSERT(mTexImage);
+  return mTexImage->GetTextureFormat();
+}
+
+void
+TextureImageTextureSourceOGL::BindTexture(GLenum aTextureUnit)
+{
+  MOZ_ASSERT(mTexImage,
+    "Trying to bind a TextureSource that does not have an underlying GL texture.");
+  mTexImage->BindTexture(aTextureUnit);
+}
+
+SharedTextureSourceOGL::SharedTextureSourceOGL(CompositorOGL* aCompositor,
+                                               gl::SharedTextureHandle aHandle,
+                                               gfx::SurfaceFormat aFormat,
+                                               GLenum aTarget,
+                                               GLenum aWrapMode,
+                                               SharedTextureShareType aShareType,
+                                               gfx::IntSize aSize,
+                                               const gfx3DMatrix& aTexTransform)
+  : mTextureTransform(aTexTransform)
+  , mSize(aSize)
+  , mCompositor(aCompositor)
+  , mSharedHandle(aHandle)
+  , mFormat(aFormat)
+  , mShareType(aShareType)
+  , mTextureTarget(aTarget)
+  , mWrapMode(aWrapMode)
+{}
+
+void
+SharedTextureSourceOGL::BindTexture(GLenum aTextureUnit)
+{
+  if (!gl()) {
+    NS_WARNING("Trying to bind a texture without a GLContext");
+    return;
+  }
+  GLuint tex = mCompositor->GetTemporaryTexture(aTextureUnit);
+
+  gl()->fActiveTexture(aTextureUnit);
+  gl()->fBindTexture(mTextureTarget, tex);
+  if (!gl()->AttachSharedHandle(mShareType, mSharedHandle)) {
+    NS_ERROR("Failed to bind shared texture handle");
+    return;
+  }
+  gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
+}
+
+void
+SharedTextureSourceOGL::DetachSharedHandle()
+{
+  if (!gl()) {
+    return;
+  }
+  gl()->DetachSharedHandle(mShareType, mSharedHandle);
+}
+
+void
+SharedTextureSourceOGL::SetCompositor(CompositorOGL* aCompositor)
+{
+  mCompositor = aCompositor;
+}
+
+bool
+SharedTextureSourceOGL::IsValid() const
+{
+  return gl() != nullptr;
+}
+
+gl::GLContext*
+SharedTextureSourceOGL::gl() const
+{
+  return mCompositor ? mCompositor->gl() : nullptr;
+}
+
+SharedTextureHostOGL::SharedTextureHostOGL(uint64_t aID,
+                                           TextureFlags aFlags,
+                                           gl::GLContext::SharedTextureShareType aShareType,
+                                           gl::SharedTextureHandle aSharedHandle,
+                                           gfx::IntSize aSize,
+                                           bool inverted)
+  : TextureHost(aID, aFlags)
+  , mSize(aSize)
+  , mCompositor(nullptr)
+  , mSharedHandle(aSharedHandle)
+  , mShareType(aShareType)
+{
+}
+
+SharedTextureHostOGL::~SharedTextureHostOGL()
+{
+  // If need to deallocate textures, call DeallocateSharedData() before
+  // the destructor
+}
+
+gl::GLContext*
+SharedTextureHostOGL::gl() const
+{
+  return mCompositor ? mCompositor->gl() : nullptr;
+}
+
+bool
+SharedTextureHostOGL::Lock()
+{
+  if (!mCompositor) {
+    return false;
+  }
+
+  if (!mTextureSource) {
+    // XXX on android GetSharedHandleDetails can call into Java which we'd
+    // rather not do from the compositor
+    GLContext::SharedHandleDetails handleDetails;
+    if (!gl()->GetSharedHandleDetails(mShareType, mSharedHandle, handleDetails)) {
+      NS_WARNING("Could not get shared handle details");
+      return false;
+    }
+
+    GLenum wrapMode = LOCAL_GL_CLAMP_TO_EDGE;
+    mTextureSource = new SharedTextureSourceOGL(nullptr, // Compositor
+                                                mSharedHandle,
+                                                handleDetails.mTextureFormat,
+                                                handleDetails.mTarget,
+                                                wrapMode,
+                                                mShareType,
+                                                mSize,
+                                                handleDetails.mTextureTransform);
+  }
+  return true;
+}
+
+void
+SharedTextureHostOGL::Unlock()
+{
+  if (!mTextureSource) {
+    return;
+  }
+  mTextureSource->DetachSharedHandle();
+}
+
+void
+SharedTextureHostOGL::SetCompositor(Compositor* aCompositor)
+{
+  CompositorOGL* glCompositor = static_cast<CompositorOGL*>(aCompositor);
+  if (mTextureSource) {
+    mTextureSource->SetCompositor(glCompositor);
+  }
+}
+
+gfx::SurfaceFormat
+SharedTextureHostOGL::GetFormat() const
+{
+  MOZ_ASSERT(mTextureSource);
+  return mTextureSource->GetFormat();
+}
+
 TextureImageDeprecatedTextureHostOGL::~TextureImageDeprecatedTextureHostOGL()
 {
   MOZ_COUNT_DTOR(TextureImageDeprecatedTextureHostOGL);
   if (mTexture && mTexture->InUpdate()) {
     mTexture->EndUpdate();
   }
 }
 
@@ -546,16 +789,17 @@ YCbCrDeprecatedTextureHostOGL::UpdateImp
 }
 
 bool
 YCbCrDeprecatedTextureHostOGL::Lock()
 {
   return true;
 }
 
+
 TiledDeprecatedTextureHostOGL::~TiledDeprecatedTextureHostOGL()
 {
   DeleteTextures();
 }
 
 static void
 GetFormatAndTileForImageFormat(gfxASurface::gfxImageFormat aFormat,
                                GLenum& aOutFormat,
@@ -725,16 +969,27 @@ void GrallocDeprecatedTextureHostOGL::Se
 {
   CompositorOGL* glCompositor = static_cast<CompositorOGL*>(aCompositor);
   if (mCompositor && !glCompositor) {
     DeleteTextures();
   }
   mCompositor = glCompositor;
 }
 
+gfx::SurfaceFormat
+GrallocDeprecatedTextureHostOGL::GetFormat() const
+{
+  if (mTextureTarget == LOCAL_GL_TEXTURE_EXTERNAL) {
+    return gfx::FORMAT_R8G8B8A8;
+  }
+  MOZ_ASSERT(mTextureTarget == LOCAL_GL_TEXTURE_2D);
+  return mFormat;
+}
+
+
 void
 GrallocDeprecatedTextureHostOGL::DeleteTextures()
 {
   if (mEGLImage) {
     gl()->MakeCurrent();
     gl()->DestroyEGLImage(mEGLImage);
     mEGLImage = 0;
   }
@@ -844,22 +1099,16 @@ GrallocDeprecatedTextureHostOGL::Lock()
 }
 
 void
 GrallocDeprecatedTextureHostOGL::Unlock()
 {
   // Lock/Unlock is done internally when binding the gralloc buffer to a gl texture
 }
 
-gfx::SurfaceFormat
-GrallocDeprecatedTextureHostOGL::GetFormat() const
-{
-  return mFormat;
-}
-
 void
 GrallocDeprecatedTextureHostOGL::SetBuffer(SurfaceDescriptor* aBuffer, ISurfaceAllocator* aAllocator)
 {
   MOZ_ASSERT(!mBuffer, "Will leak the old mBuffer");
   mBuffer = aBuffer;
   mDeAllocator = aAllocator;
 
   // only done for hacky fix in gecko 23 for bug 862324.
@@ -918,37 +1167,37 @@ YCbCrDeprecatedTextureHostOGL::GetAsSurf
   return surf.forget();
 }
 
 already_AddRefed<gfxImageSurface>
 SharedDeprecatedTextureHostOGL::GetAsSurface() {
   nsRefPtr<gfxImageSurface> surf = IsValid() ?
     mGL->GetTexImage(GetTextureHandle(),
                      false,
-                     GetTextureFormat())
+                     GetFormat())
     : nullptr;
   return surf.forget();
 }
 
 already_AddRefed<gfxImageSurface>
 SurfaceStreamHostOGL::GetAsSurface() {
   nsRefPtr<gfxImageSurface> surf = IsValid() ?
     mGL->GetTexImage(mTextureHandle,
                      false,
-                     GetTextureFormat())
+                     GetFormat())
     : nullptr;
   return surf.forget();
 }
 
 already_AddRefed<gfxImageSurface>
 TiledDeprecatedTextureHostOGL::GetAsSurface() {
   nsRefPtr<gfxImageSurface> surf = IsValid() ?
     mGL->GetTexImage(mTextureHandle,
                      false,
-                     GetTextureFormat())
+                     GetFormat())
     : nullptr;
   return surf.forget();
 }
 
 #ifdef MOZ_WIDGET_GONK
 already_AddRefed<gfxImageSurface>
 GrallocDeprecatedTextureHostOGL::GetAsSurface() {
   gl()->MakeCurrent();
@@ -959,16 +1208,16 @@ GrallocDeprecatedTextureHostOGL::GetAsSu
   if (!mEGLImage) {
     mEGLImage = gl()->CreateEGLImageForNativeBuffer(mGraphicBuffer->getNativeBuffer());
   }
   gl()->fEGLImageTargetTexture2D(mTextureTarget, mEGLImage);
 
   nsRefPtr<gfxImageSurface> surf = IsValid() ?
     gl()->GetTexImage(tex,
                       false,
-                      GetTextureFormat())
+                      GetFormat())
     : nullptr;
   return surf.forget();
 }
 #endif
 
 } // namespace
 } // namespace
--- a/gfx/layers/opengl/TextureHostOGL.h
+++ b/gfx/layers/opengl/TextureHostOGL.h
@@ -33,55 +33,275 @@ class CompositorOGL;
  * released. At the moment the teardown sequence happens in the middle of
  * the nsBaseWidget's destructor, meaning that at a given moment we must be
  * able to easily find and release all the GL resources.
  * The point is: be careful about the ownership model and limit the number
  * of objects sharing references to GL resources to make the tear down
  * sequence as simple as possible.
  */
 
-/**
- * TextureSourceOGL provides the necessary API for CompositorOGL to composite
- * a TextureSource.
- */
-class TextureSourceOGL
-{
-public:
-  virtual bool IsValid() const = 0;
-  virtual void BindTexture(GLenum aTextureUnit) = 0;
-  virtual void ReleaseTexture() = 0;
-  virtual gfx::IntSize GetSize() const = 0;
-  virtual gfx::SurfaceFormat GetTextureFormat() const {
-    MOZ_CRASH("unhandled texture format");
-  }
-  // TODO: Noone's implementing this anymore, should see if we need this.
-  virtual GLenum GetTextureTarget() const { return LOCAL_GL_TEXTURE_2D; }
-  virtual GLenum GetWrapMode() const = 0;// { return LOCAL_GL_CLAMP_TO_EDGE; } // default
-  virtual gfx3DMatrix GetTextureTransform() { return gfx3DMatrix(); }
-
-  virtual TextureImageDeprecatedTextureHostOGL* AsTextureImageDeprecatedTextureHost() { return nullptr; }
-};
-
 inline ShaderProgramType
-GetProgramTypeForTexture(const DeprecatedTextureHost *aDeprecatedTextureHost)
-{
-  switch (aDeprecatedTextureHost->GetFormat()) {
+GetProgramTypeForSurfaceFormat(gfx::SurfaceFormat aFormat)
+ {
+  switch (aFormat) {
   case gfx::FORMAT_B8G8R8A8:
     return BGRALayerProgramType;;
   case gfx::FORMAT_B8G8R8X8:
     return BGRXLayerProgramType;;
   case gfx::FORMAT_R8G8B8X8:
     return RGBXLayerProgramType;;
   case gfx::FORMAT_R8G8B8A8:
     return RGBALayerProgramType;;
   default:
     MOZ_CRASH("unhandled program type");
   }
 }
 
+inline ShaderProgramType
+GetProgramTypeForTexture(const DeprecatedTextureHost *aDeprecatedTextureHost)
+{
+  return GetProgramTypeForSurfaceFormat(aDeprecatedTextureHost->GetFormat());
+}
+
+/**
+ * TextureSourceOGL provides the necessary API for CompositorOGL to composite
+ * a TextureSource.
+ */
+class TextureSourceOGL
+{
+public:
+  virtual bool IsValid() const = 0;
+
+  virtual void BindTexture(GLenum aTextureUnit) = 0;
+
+  /**
+   * Unbind this texture
+   * XXX - "Release" is confusing, should be called UnbindTexture instead.
+   */
+  virtual void ReleaseTexture() = 0;
+
+  virtual gfx::IntSize GetSize() const = 0;
+
+  virtual GLenum GetTextureTarget() const { return LOCAL_GL_TEXTURE_2D; }
+
+  virtual gfx::SurfaceFormat GetFormat() const = 0;
+
+  virtual GLenum GetWrapMode() const = 0;
+
+  virtual gfx3DMatrix GetTextureTransform() { return gfx3DMatrix(); }
+
+  virtual TextureImageDeprecatedTextureHostOGL* AsTextureImageDeprecatedTextureHost() { return nullptr; }
+};
+
+/**
+ * A TextureSource backed by a TextureImage.
+ *
+ * Depending on the underlying TextureImage, may support texture tiling, so
+ * make sure to check AsTileIterator() and use the texture accordingly.
+ *
+ * This TextureSource can be used without a TextureHost and manage it's own
+ * GL texture(s).
+ */
+class TextureImageTextureSourceOGL : public DataTextureSource
+                                   , public TextureSourceOGL
+                                   , public TileIterator
+{
+public:
+  TextureImageTextureSourceOGL(gl::GLContext* aGL, bool aAllowTiling = true)
+    : mGL(aGL)
+    , mAllowTiling(aAllowTiling)
+    , mIterating(false)
+  {}
+
+  // DataTextureSource
+
+  virtual bool Update(gfx::DataSourceSurface* aSurface,
+                      TextureFlags aFlags,
+                      nsIntRegion* aDestRegion = nullptr,
+                      gfx::IntPoint* aSrcOffset = nullptr) MOZ_OVERRIDE;
+
+  // TextureSource
+
+  virtual void DeallocateDeviceData() MOZ_OVERRIDE
+  {
+    mTexImage = nullptr;
+    SetUpdateSerial(0);
+  }
+
+  virtual TextureSourceOGL* AsSourceOGL() MOZ_OVERRIDE { return this; }
+
+  virtual void BindTexture(GLenum aTextureUnit) MOZ_OVERRIDE;
+
+  virtual gfx::IntSize GetSize() const MOZ_OVERRIDE;
+
+  virtual gfx::SurfaceFormat GetFormat() const MOZ_OVERRIDE;
+
+  virtual bool IsValid() const MOZ_OVERRIDE { return !!mTexImage; }
+
+  virtual void ReleaseTexture() MOZ_OVERRIDE
+  {
+    mTexImage->ReleaseTexture();
+  }
+
+  virtual GLenum GetWrapMode() const MOZ_OVERRIDE
+  {
+    return mTexImage->GetWrapMode();
+  }
+
+  // TileIterator
+
+  virtual TileIterator* AsTileIterator() MOZ_OVERRIDE { return this; }
+
+  virtual void BeginTileIteration() MOZ_OVERRIDE
+  {
+    mTexImage->BeginTileIteration();
+    mIterating = true;
+  }
+
+  virtual void EndTileIteration() MOZ_OVERRIDE
+  {
+    mIterating = false;
+  }
+
+  virtual nsIntRect GetTileRect() MOZ_OVERRIDE
+  {
+    return mTexImage->GetTileRect();
+  }
+
+  virtual size_t GetTileCount() MOZ_OVERRIDE
+  {
+    return mTexImage->GetTileCount();
+  }
+
+  virtual bool NextTile() MOZ_OVERRIDE
+  {
+    return mTexImage->NextTile();
+  }
+
+protected:
+  nsRefPtr<gl::TextureImage> mTexImage;
+  gl::GLContext* mGL;
+  bool mAllowTiling;
+  bool mIterating;
+};
+
+/**
+ * A texture source meant for use with SharedTextureHostOGL.
+ *
+ * It does not own any GL texture, and attaches its shared handle to one of
+ * the compositor's temporary textures when binding.
+ *
+ * The shared texture handle is owned by the TextureHost.
+ */
+class SharedTextureSourceOGL : public NewTextureSource
+                             , public TextureSourceOGL
+{
+public:
+  typedef gl::GLContext::SharedTextureShareType SharedTextureShareType;
+
+  SharedTextureSourceOGL(CompositorOGL* aCompositor,
+                         gl::SharedTextureHandle aHandle,
+                         gfx::SurfaceFormat aFormat,
+                         GLenum aTarget,
+                         GLenum aWrapMode,
+                         SharedTextureShareType aShareType,
+                         gfx::IntSize aSize,
+                         const gfx3DMatrix& aTexTransform);
+
+  virtual TextureSourceOGL* AsSourceOGL() { return this; }
+
+  virtual void BindTexture(GLenum activetex) MOZ_OVERRIDE;
+
+  virtual bool IsValid() const MOZ_OVERRIDE;
+
+  virtual gfx::IntSize GetSize() const MOZ_OVERRIDE { return mSize; }
+
+  virtual gfx::SurfaceFormat GetFormat() const MOZ_OVERRIDE { return mFormat; }
+
+  virtual gfx3DMatrix GetTextureTransform() MOZ_OVERRIDE { return mTextureTransform; }
+
+  virtual GLenum GetWrapMode() const MOZ_OVERRIDE { return mWrapMode; }
+
+  virtual void ReleaseTexture() MOZ_OVERRIDE {}
+
+  // SharedTextureSource doesn't own any gl texture
+  virtual void DeallocateDeviceData() {}
+
+  void DetachSharedHandle();
+
+  void SetCompositor(CompositorOGL* aCompositor);
+
+  gl::GLContext* gl() const;
+
+protected:
+  gfx3DMatrix mTextureTransform;
+  gfx::IntSize mSize;
+  CompositorOGL* mCompositor;
+  gl::SharedTextureHandle mSharedHandle;
+  gfx::SurfaceFormat mFormat;
+  SharedTextureShareType mShareType;
+  GLenum mTextureTarget;
+  GLenum mWrapMode;
+};
+
+/**
+ * A TextureHost for shared GL Textures
+ *
+ * Most of the logic actually happens in SharedTextureSourceOGL.
+ */
+class SharedTextureHostOGL : public TextureHost
+{
+public:
+  SharedTextureHostOGL(uint64_t aID,
+                       TextureFlags aFlags,
+                       gl::GLContext::SharedTextureShareType aShareType,
+                     gl::SharedTextureHandle aSharedhandle,
+                       gfx::IntSize aSize,
+                       bool inverted);
+
+  virtual ~SharedTextureHostOGL();
+
+  // SharedTextureHostOGL doesn't own any GL texture
+  virtual void DeallocateDeviceData() MOZ_OVERRIDE {}
+
+  virtual void SetCompositor(Compositor* aCompositor) MOZ_OVERRIDE;
+
+  virtual bool Lock() MOZ_OVERRIDE;
+
+  virtual void Unlock() MOZ_OVERRIDE;
+
+  virtual gfx::SurfaceFormat GetFormat() const MOZ_OVERRIDE;
+
+  virtual NewTextureSource* GetTextureSources() MOZ_OVERRIDE
+  {
+    return mTextureSource;
+  }
+
+  virtual already_AddRefed<gfxImageSurface> GetAsSurface() MOZ_OVERRIDE
+  {
+    return nullptr; // XXX - implement this (for MOZ_DUMP_PAINTING)
+  }
+
+  gl::GLContext* gl() const;
+
+  virtual gfx::IntSize GetSize() const MOZ_OVERRIDE { return mSize; }
+
+#ifdef MOZ_LAYERS_HAVE_LOG
+  virtual const char* Name() { return "SharedTextureHostOGL"; }
+#endif
+
+protected:
+  gfx::IntSize mSize;
+  CompositorOGL* mCompositor;
+  gl::SharedTextureHandle mSharedHandle;
+  gl::GLContext::SharedTextureShareType mShareType;
+
+  RefPtr<SharedTextureSourceOGL> mTextureSource;
+};
+
 /**
  * DeprecatedTextureHost implementation using a TextureImage as the underlying texture.
  */
 class TextureImageDeprecatedTextureHostOGL : public DeprecatedTextureHost
                                            , public TextureSourceOGL
                                            , public TileIterator
 {
 public:
@@ -143,21 +363,16 @@ public:
 
   void ReleaseTexture() MOZ_OVERRIDE
   {
     mTexture->ReleaseTexture();
   }
 
   gfx::IntSize GetSize() const MOZ_OVERRIDE;
 
-  gfx::SurfaceFormat GetTextureFormat() const MOZ_OVERRIDE
-  {
-    return GetFormat();
-  }
-
   GLenum GetWrapMode() const MOZ_OVERRIDE
   {
     return mTexture->GetWrapMode();
   }
 
   gl::TextureImage* GetTextureImage()
   {
     return mTexture;
@@ -196,27 +411,31 @@ public:
     return mTexture->GetTileCount();
   }
 
   bool NextTile() MOZ_OVERRIDE
   {
     return mTexture->NextTile();
   }
 
+  virtual gfx::SurfaceFormat GetFormat() const MOZ_OVERRIDE
+  {
+    return DeprecatedTextureHost::GetFormat();
+  }
+
 #ifdef MOZ_LAYERS_HAVE_LOG
   virtual const char* Name() { return "TextureImageDeprecatedTextureHostOGL"; }
 #endif
 
 protected:
   nsRefPtr<gl::TextureImage> mTexture;
   gl::GLContext* mGL;
   bool mIterating;
 };
 
-
 /**
  * DeprecatedTextureHost implementation for YCbCr images in the OpenGL backend.
  *
  * This DeprecatedTextureHost is a little bit particular in that it implements
  * the TextureSource interface, as it is required that a DeprecatedTextureHost
  * provides access to a TextureSource, but does not implement the
  * DeprecatedTextureHostOGL interface. Instead it contains 3 channels (one per
  * plane) that implement the TextureSourceOGL interface, and
@@ -280,16 +499,20 @@ public:
     virtual gfx::IntSize GetSize() const MOZ_OVERRIDE
     {
       return gfx::IntSize(mTexImage->GetSize().width, mTexImage->GetSize().height);
     }
     virtual GLenum GetWrapMode() const MOZ_OVERRIDE
     {
       return mTexImage->GetWrapMode();
     }
+    virtual gfx::SurfaceFormat GetFormat() const MOZ_OVERRIDE
+    {
+      return gfx::FORMAT_A8;
+    }
   };
 
   // TextureSource implementation
 
   TextureSource* GetSubSource(int index) MOZ_OVERRIDE
   {
     switch (index) {
       case 0 : return mYTexture.get();
@@ -316,16 +539,17 @@ public:
 
 private:
   RefPtr<Channel> mYTexture;
   RefPtr<Channel> mCbTexture;
   RefPtr<Channel> mCrTexture;
   gl::GLContext* mGL;
 };
 
+
 class SharedDeprecatedTextureHostOGL : public DeprecatedTextureHost
                            , public TextureSourceOGL
 {
 public:
   typedef gfxASurface::gfxContentType ContentType;
   typedef mozilla::gl::GLContext GLContext;
   typedef mozilla::gl::TextureImage TextureImage;
 
@@ -346,16 +570,21 @@ public:
     }
   }
 
   virtual GLuint GetTextureHandle()
   {
     return mTextureHandle;
   }
 
+  virtual gfx::SurfaceFormat GetFormat() const MOZ_OVERRIDE
+  {
+    return DeprecatedTextureHost::GetFormat();
+  }
+
   virtual TextureSourceOGL* AsSourceOGL() MOZ_OVERRIDE { return this; }
 
   bool IsValid() const MOZ_OVERRIDE { return !!mSharedHandle; }
 
   // override from DeprecatedTextureHost, we support both buffered
   // and unbuffered operation.
   virtual void UpdateImpl(const SurfaceDescriptor& aImage,
                           nsIntRegion* aRegion = nullptr,
@@ -363,21 +592,16 @@ public:
   virtual void SwapTexturesImpl(const SurfaceDescriptor& aImage,
                                 nsIntRegion* aRegion = nullptr) MOZ_OVERRIDE;
   virtual bool Lock() MOZ_OVERRIDE;
   virtual void Unlock() MOZ_OVERRIDE;
 
   virtual GLenum GetWrapMode() const MOZ_OVERRIDE { return mWrapMode; }
   virtual void SetWrapMode(GLenum aMode) { mWrapMode = aMode; }
 
-  gfx::SurfaceFormat GetTextureFormat() const MOZ_OVERRIDE
-  {
-    return mFormat;
-  }
-
   virtual GLenum GetTextureTarget() const MOZ_OVERRIDE
   {
     return mTextureTarget;
   }
 
   gfx::IntSize GetSize() const MOZ_OVERRIDE {
     return mSize;
   }
@@ -433,16 +657,21 @@ public:
 
   virtual void SetCompositor(Compositor* aCompositor) MOZ_OVERRIDE;
 
   virtual GLuint GetTextureHandle()
   {
     return mTextureHandle;
   }
 
+  virtual gfx::SurfaceFormat GetFormat() const MOZ_OVERRIDE
+  {
+    return DeprecatedTextureHost::GetFormat();
+  }
+
   virtual TextureSourceOGL* AsSourceOGL() MOZ_OVERRIDE { return this; }
 
   bool IsValid() const MOZ_OVERRIDE { return true; }
 
   // override from DeprecatedTextureHost
   virtual void SwapTexturesImpl(const SurfaceDescriptor& aImage,
                                 nsIntRegion* aRegion = nullptr) MOZ_OVERRIDE;
   virtual bool Lock() MOZ_OVERRIDE;
@@ -450,37 +679,33 @@ public:
 
   virtual GLenum GetWrapMode() const MOZ_OVERRIDE {
     return mWrapMode;
   }
   virtual void SetWrapMode(GLenum aMode) {
     mWrapMode = aMode;
   }
 
-  gfx::SurfaceFormat GetTextureFormat() const MOZ_OVERRIDE
-  {
-    return mFormat;
-  }
-
   gfx::IntSize GetSize() const MOZ_OVERRIDE {
     return mSize;
   }
 
   virtual GLenum GetTextureTarget() const MOZ_OVERRIDE
   {
     return mTextureTarget;
   }
 
   void BindTexture(GLenum activetex) MOZ_OVERRIDE {
     MOZ_ASSERT(mGL);
     mGL->fActiveTexture(activetex);
     mGL->fBindTexture(mTextureTarget, mTextureHandle);
   }
-  void ReleaseTexture() MOZ_OVERRIDE {
-  }
+
+  void ReleaseTexture() MOZ_OVERRIDE {}
+
   GLuint GetTextureID() { return mTextureHandle; }
   ContentType GetContentType() {
     return (mFormat == gfx::FORMAT_B8G8R8A8) ?
              gfxASurface::CONTENT_COLOR_ALPHA :
              gfxASurface::CONTENT_COLOR;
   }
 
   virtual already_AddRefed<gfxImageSurface> GetAsSurface() MOZ_OVERRIDE;
@@ -521,35 +746,35 @@ public:
 
   virtual void SetCompositor(Compositor* aCompositor);
 
   // have to pass the size in here (every time) because of DrawQuad API :-(
   virtual void Update(gfxReusableSurfaceWrapper* aReusableSurface, TextureFlags aFlags, const gfx::IntSize& aSize) MOZ_OVERRIDE;
   virtual bool Lock() MOZ_OVERRIDE;
   virtual void Unlock() MOZ_OVERRIDE {}
 
+  virtual gfx::SurfaceFormat GetFormat() const MOZ_OVERRIDE
+  {
+    return DeprecatedTextureHost::GetFormat();
+  }
+
   virtual TextureSourceOGL* AsSourceOGL() MOZ_OVERRIDE { return this; }
   virtual bool IsValid() const MOZ_OVERRIDE { return true; }
   virtual GLenum GetWrapMode() const MOZ_OVERRIDE { return LOCAL_GL_CLAMP_TO_EDGE; }
   virtual void BindTexture(GLenum aTextureUnit) MOZ_OVERRIDE
   {
     mGL->fActiveTexture(aTextureUnit);
     mGL->fBindTexture(LOCAL_GL_TEXTURE_2D, mTextureHandle);
   }
   virtual void ReleaseTexture() MOZ_OVERRIDE {}
   virtual gfx::IntSize GetSize() const MOZ_OVERRIDE
   {
     return mSize;
   }
 
-  gfx::SurfaceFormat GetTextureFormat() const MOZ_OVERRIDE
-  {
-    return GetFormat();
-  }
-
   virtual void SwapTexturesImpl(const SurfaceDescriptor& aImage,
                                 nsIntRegion* aRegion = nullptr)
   { MOZ_ASSERT(false, "Tiles should not use this path"); }
 
   virtual already_AddRefed<gfxImageSurface> GetAsSurface() MOZ_OVERRIDE;
 
 #ifdef MOZ_LAYERS_HAVE_LOG
   virtual const char* Name() { return "TiledDeprecatedTextureHostOGL"; }
@@ -600,24 +825,17 @@ public:
   virtual bool Lock() MOZ_OVERRIDE;
   virtual void Unlock() MOZ_OVERRIDE;
 
   virtual gfx::IntSize GetSize() const MOZ_OVERRIDE
   {
     return mGraphicBuffer.get() ? gfx::IntSize(mGraphicBuffer->getWidth(), mGraphicBuffer->getHeight()) : gfx::IntSize(0, 0);
   }
 
-  gfx::SurfaceFormat GetTextureFormat() const MOZ_OVERRIDE
-  {
-    if (mTextureTarget == LOCAL_GL_TEXTURE_EXTERNAL) {
-      return gfx::FORMAT_R8G8B8A8;
-    }
-    MOZ_ASSERT(mTextureTarget == LOCAL_GL_TEXTURE_2D);
-    return mFormat;
-  }
+  virtual gfx::SurfaceFormat GetFormat() const MOZ_OVERRIDE;
 
   GLenum GetWrapMode() const MOZ_OVERRIDE
   {
     return LOCAL_GL_CLAMP_TO_EDGE;
   }
 
   virtual GLenum GetTextureTarget() const MOZ_OVERRIDE
   {
@@ -630,18 +848,16 @@ public:
 
 #ifdef MOZ_LAYERS_HAVE_LOG
   virtual const char* Name() { return "GrallocDeprecatedTextureHostOGL"; }
 #endif
 
   void BindTexture(GLenum aTextureUnit) MOZ_OVERRIDE;
   void ReleaseTexture() MOZ_OVERRIDE {}
 
-  virtual gfx::SurfaceFormat GetFormat() const;
-
   virtual TextureSourceOGL* AsSourceOGL() MOZ_OVERRIDE
   {
     return this;
   }
 
   // only overridden for hacky fix in gecko 23 for bug 862324
   // see bug 865908 about fixing this.
   virtual void SetBuffer(SurfaceDescriptor* aBuffer, ISurfaceAllocator* aAllocator) MOZ_OVERRIDE;
--- a/gfx/thebes/gfx2DGlue.h
+++ b/gfx/thebes/gfx2DGlue.h
@@ -49,16 +49,21 @@ inline Point ToPoint(const gfxPoint &aPo
   return Point(Float(aPoint.x), Float(aPoint.y));
 }
 
 inline Size ToSize(const gfxSize &aSize)
 {
   return Size(Float(aSize.width), Float(aSize.height));
 }
 
+inline IntSize ToIntSize(const gfxIntSize &aSize)
+{
+  return IntSize(aSize.width, aSize.height);
+}
+
 inline Filter ToFilter(gfxPattern::GraphicsFilter aFilter)
 {
   switch (aFilter) {
   case gfxPattern::FILTER_NEAREST:
     return FILTER_POINT;
   default:
     return FILTER_LINEAR;
   }
--- a/gfx/thebes/gfxPlatform.cpp
+++ b/gfx/thebes/gfxPlatform.cpp
@@ -250,16 +250,23 @@ gfxPlatform::gfxPlatform()
     mUseHarfBuzzScripts = UNINITIALIZED_VALUE;
     mAllowDownloadableFonts = UNINITIALIZED_VALUE;
     mFallbackUsesCmaps = UNINITIALIZED_VALUE;
 
     mGraphiteShapingEnabled = UNINITIALIZED_VALUE;
     mOpenTypeSVGEnabled = UNINITIALIZED_VALUE;
     mBidiNumeralOption = UNINITIALIZED_VALUE;
 
+    mLayersPreferMemoryOverShmem =
+        XRE_GetProcessType() == GeckoProcessType_Default &&
+        Preferences::GetBool("layers.prefer-memory-over-shmem", true);
+
+    mLayersUseDeprecated =
+        Preferences::GetBool("layers.use-deprecated-textures", true);
+
     uint32_t canvasMask = (1 << BACKEND_CAIRO) | (1 << BACKEND_SKIA);
     uint32_t contentMask = 0;
     InitBackendPrefs(canvasMask, contentMask);
 }
 
 gfxPlatform*
 gfxPlatform::GetPlatform()
 {
@@ -498,16 +505,22 @@ gfxPlatform::~gfxPlatform()
     // It would be nice to do this (although it might need to be after
     // the cairo shutdown that happens in ~gfxPlatform).  It even looks
     // idempotent.  But it has fatal assertions that fire if stuff is
     // leaked, and we hit them.
     FcFini();
 #endif
 }
 
+bool
+gfxPlatform::PreferMemoryOverShmem() const {
+  MOZ_ASSERT(!CompositorParent::IsInCompositorThread());
+  return mLayersPreferMemoryOverShmem;
+}
+
 already_AddRefed<gfxASurface>
 gfxPlatform::CreateOffscreenImageSurface(const gfxIntSize& aSize,
                                          gfxASurface::gfxContentType aContentType)
 {
   nsRefPtr<gfxASurface> newSurface;
   newSurface = new gfxImageSurface(aSize, OptimalFormatForContent(aContentType));
 
   return newSurface.forget();
--- a/gfx/thebes/gfxPlatform.h
+++ b/gfx/thebes/gfxPlatform.h
@@ -551,16 +551,24 @@ public:
     virtual int GetScreenDepth() const;
 
     bool WidgetUpdateFlashing() const { return mWidgetUpdateFlashing; }
 
     uint32_t GetOrientationSyncMillis() const;
 
     static bool DrawLayerBorders();
     static bool DrawFrameCounter();
+    /**
+     * Returns true if we should use raw memory to send data to the compositor
+     * rather than using shmems.
+     *
+     * This method should not be called from the compositor thread.
+     */
+    bool PreferMemoryOverShmem() const;
+    bool UseDeprecatedTextures() const { return mLayersUseDeprecated; }
 
 protected:
     gfxPlatform();
     virtual ~gfxPlatform();
 
     void AppendCJKPrefLangs(eFontPrefLang aPrefLangs[], uint32_t &aLen, 
                             eFontPrefLang aCharLang, eFontPrefLang aPageLang);
 
@@ -654,11 +662,13 @@ private:
     uint32_t mContentBackendBitmask;
 
     mozilla::widget::GfxInfoCollector<gfxPlatform> mAzureCanvasBackendCollector;
     bool mWorkAroundDriverBugs;
 
     mozilla::RefPtr<mozilla::gfx::DrawEventRecorder> mRecorder;
     bool mWidgetUpdateFlashing;
     uint32_t mOrientationSyncMillis;
+    bool mLayersPreferMemoryOverShmem;
+    bool mLayersUseDeprecated;
 };
 
 #endif /* GFX_PLATFORM_H */
--- a/ipc/glue/IPCMessageUtils.h
+++ b/ipc/glue/IPCMessageUtils.h
@@ -11,16 +11,17 @@
 #include "chrome/common/ipc_message_utils.h"
 
 #include "mozilla/TimeStamp.h"
 #ifdef XP_WIN
 #include "mozilla/TimeStamp_windows.h"
 #endif
 #include "mozilla/Util.h"
 #include "mozilla/gfx/2D.h"
+#include "mozilla/gfx/Point.h"
 #include "mozilla/StandardInteger.h"
 
 #include "nsID.h"
 #include "nsMemory.h"
 #include "nsStringGlue.h"
 #include "nsTArray.h"
 #include "gfx3DMatrix.h"
 #include "gfxColor.h"
@@ -717,16 +718,34 @@ struct ParamTraits<nsIntPoint>
   static bool Read(const Message* msg, void** iter, paramType* result)
   {
     return (ReadParam(msg, iter, &result->x) &&
             ReadParam(msg, iter, &result->y));
   }
 };
 
 template<>
+struct ParamTraits<mozilla::gfx::IntSize>
+{
+  typedef mozilla::gfx::IntSize paramType;
+
+  static void Write(Message* msg, const paramType& param)
+  {
+    WriteParam(msg, param.width);
+    WriteParam(msg, param.height);
+  }
+
+  static bool Read(const Message* msg, void** iter, paramType* result)
+  {
+    return (ReadParam(msg, iter, &result->width) &&
+            ReadParam(msg, iter, &result->height));
+  }
+};
+
+template<>
 struct ParamTraits<nsIntRect>
 {
   typedef nsIntRect paramType;
 
   static void Write(Message* msg, const paramType& param)
   {
     WriteParam(msg, param.x);
     WriteParam(msg, param.y);
@@ -1185,11 +1204,18 @@ struct ParamTraits<mozilla::layers::Text
 
 template <>
 struct ParamTraits<mozilla::layers::CompositableType>
   : public EnumSerializer<mozilla::layers::CompositableType,
                           mozilla::layers::BUFFER_UNKNOWN,
                           mozilla::layers::BUFFER_COUNT>
 {};
 
+template <>
+struct ParamTraits<mozilla::gfx::SurfaceFormat>
+  : public EnumSerializer<mozilla::gfx::SurfaceFormat,
+                          mozilla::gfx::FORMAT_B8G8R8A8,
+                          mozilla::gfx::FORMAT_UNKNOWN>
+{};
+
 } /* namespace IPC */
 
 #endif /* __IPC_GLUE_IPCMESSAGEUTILS_H__ */
--- a/modules/libpref/src/init/all.js
+++ b/modules/libpref/src/init/all.js
@@ -4051,16 +4051,19 @@ pref("network.tcp.sendbuffer", 131072);
 
 // Asynchonous video compositing using the ImageBridge IPDL protocol.
 // requires off-main-thread compositing.
 pref("layers.async-video.enabled",false);
 
 // Whether to disable acceleration for all widgets.
 pref("layers.acceleration.disabled", false);
 
+// Whether to use the deprecated texture architecture rather than the new one.
+pref("layers.use-deprecated-textures", true);
+
 // Whether to force acceleration on, ignoring blacklists.
 #ifdef ANDROID
 // bug 838603 -- on Android, accidentally blacklisting OpenGL layers
 // means a startup crash for everyone.
 pref("layers.acceleration.force-enabled", true);
 #else
 pref("layers.acceleration.force-enabled", false);
 #endif
@@ -4075,16 +4078,18 @@ pref("layers.offmainthreadcomposition.en
 #else
 pref("layers.offmainthreadcomposition.enabled", false);
 #endif
 // same effect as layers.offmainthreadcomposition.enabled, but specifically for
 // use with tests.
 pref("layers.offmainthreadcomposition.testing.enabled", false);
 // Whether to animate simple opacity and transforms on the compositor
 pref("layers.offmainthreadcomposition.async-animations", false);
+// Whether to prefer normal memory over shared memory. Ignored with cross-process compositing
+pref("layers.prefer-memory-over-shmem", true);
 
 #ifdef MOZ_X11
 #ifdef MOZ_WIDGET_GTK2
 pref("gfx.xrender.enabled",true);
 #endif
 #endif
 
 #ifdef XP_WIN