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 152780 313445f455f38bd21ad7a31cd4e301dac8e61c3e
parent 152779 91837985ae91d394ea96289bb43878161067bd69
child 152781 cb3f726cf350722514d5d035938f2e424ad64836
push id2859
push userakeybl@mozilla.com
push dateMon, 16 Sep 2013 19:14:59 +0000
treeherdermozilla-beta@87d3c51cd2bf [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbas, nrc
bugs858914
milestone25.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 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