merge
authorJohn Daggett <jdaggett@mozilla.com>
Thu, 12 Dec 2013 10:50:57 +0900
changeset 177038 46586f01b86da44c671331527fe7d4fb1314d2e0
parent 177037 ec5e10f507405ffbe0db32765d5c3a76dbb2f2ed (current diff)
parent 177036 c1b544bfad40a132b03b34c5961eac9e290a2c38 (diff)
child 177039 67ae84fa6807a57be78e6a237d146297861f2da1
push id462
push userraliiev@mozilla.com
push dateTue, 22 Apr 2014 00:22:30 +0000
treeherdermozilla-release@ac5db8c74ac0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone29.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
merge
--- a/gfx/gl/GLBlitTextureImageHelper.cpp
+++ b/gfx/gl/GLBlitTextureImageHelper.cpp
@@ -3,16 +3,17 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "GLBlitTextureImageHelper.h"
 #include "GLUploadHelpers.h"
 #include "DecomposeIntoNoRepeatTriangles.h"
 #include "GLContext.h"
+#include "ScopedGLHelpers.h"
 #include "nsRect.h"
 #include "gfx2DGlue.h"
 #include "gfxUtils.h"
 
 namespace mozilla {
 namespace gl {
 
 GLBlitTextureImageHelper::GLBlitTextureImageHelper(GLContext* gl)
@@ -138,17 +139,18 @@ GLBlitTextureImageHelper::BlitTextureIma
                 RectTriangles::vert_coord* v = (RectTriangles::vert_coord*)rects.vertexPointer();
 
                 for (unsigned int i = 0; i < rects.elements(); ++i) {
                     v[i].x = (v[i].x * (dx1 - dx0)) + dx0;
                     v[i].y = (v[i].y * (dy1 - dy0)) + dy0;
                 }
             }
 
-            TextureImage::ScopedBindTexture texBind(aSrc, LOCAL_GL_TEXTURE0);
+            ScopedBindTextureUnit autoTexUnit(mGL, LOCAL_GL_TEXTURE0);
+            ScopedBindTexture autoTex(mGL, aSrc->GetTextureID());
 
             mGL->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, 0);
 
             mGL->fVertexAttribPointer(0, 2, LOCAL_GL_FLOAT, LOCAL_GL_FALSE, 0, rects.vertexPointer());
             mGL->fVertexAttribPointer(1, 2, LOCAL_GL_FLOAT, LOCAL_GL_FALSE, 0, rects.texCoordPointer());
 
             mGL->fEnableVertexAttribArray(0);
             mGL->fEnableVertexAttribArray(1);
--- a/gfx/gl/GLContext.cpp
+++ b/gfx/gl/GLContext.cpp
@@ -1184,34 +1184,16 @@ GLContext::ListHasExtension(const GLubyt
                 return true;
             }
         }
         start = terminator;
     }
     return false;
 }
 
-void GLContext::ApplyFilterToBoundTexture(GraphicsFilter aFilter)
-{
-    ApplyFilterToBoundTexture(LOCAL_GL_TEXTURE_2D, aFilter);
-}
-
-void GLContext::ApplyFilterToBoundTexture(GLuint aTarget,
-                                          GraphicsFilter aFilter)
-{
-    if (aFilter == GraphicsFilter::FILTER_NEAREST) {
-        fTexParameteri(aTarget, LOCAL_GL_TEXTURE_MIN_FILTER, LOCAL_GL_NEAREST);
-        fTexParameteri(aTarget, LOCAL_GL_TEXTURE_MAG_FILTER, LOCAL_GL_NEAREST);
-    } else {
-        fTexParameteri(aTarget, LOCAL_GL_TEXTURE_MIN_FILTER, LOCAL_GL_LINEAR);
-        fTexParameteri(aTarget, LOCAL_GL_TEXTURE_MAG_FILTER, LOCAL_GL_LINEAR);
-    }
-}
-
-
 void
 GLContext::DetermineCaps()
 {
     PixelBufferFormat format = QueryPixelFormat();
 
     SurfaceCaps caps;
     caps.color = !!format.red && !!format.green && !!format.blue;
     caps.bpp16 = caps.color && format.ColorBits() == 16;
--- a/gfx/gl/GLContext.h
+++ b/gfx/gl/GLContext.h
@@ -2477,35 +2477,16 @@ public:
      * Defines a two-dimensional texture image for context target surface
      */
     virtual bool BindTexImage() { return false; }
     /*
      * Releases a color buffer that is being used as a texture
      */
     virtual bool ReleaseTexImage() { return false; }
 
-    /**
-     * Applies aFilter to the texture currently bound to GL_TEXTURE_2D.
-     */
-    void ApplyFilterToBoundTexture(GraphicsFilter aFilter);
-
-    /**
-     * Applies aFilter to the texture currently bound to aTarget.
-     */
-    void ApplyFilterToBoundTexture(GLuint aTarget,
-                                   GraphicsFilter aFilter);
-
-    virtual bool BindExternalBuffer(GLuint texture, void* buffer) { return false; }
-    virtual bool UnbindExternalBuffer(GLuint texture) { return false; }
-
-#ifdef MOZ_WIDGET_GONK
-    virtual EGLImage CreateEGLImageForNativeBuffer(void* buffer) = 0;
-    virtual void DestroyEGLImage(EGLImage image) = 0;
-#endif
-
     // Before reads from offscreen texture
     void GuaranteeResolve();
 
     /*
      * Resize the current offscreen buffer.  Returns true on success.
      * If it returns false, the context should be treated as unusable
      * and should be recreated.  After the resize, the viewport is not
      * changed; glViewport should be called as appropriate.
--- a/gfx/gl/GLContextProviderEGL.cpp
+++ b/gfx/gl/GLContextProviderEGL.cpp
@@ -403,35 +403,16 @@ public:
                                                LOCAL_EGL_BACK_BUFFER);
         if (success == LOCAL_EGL_FALSE)
             return false;
 
         mBound = false;
         return true;
     }
 
-#ifdef MOZ_WIDGET_GONK
-    EGLImage CreateEGLImageForNativeBuffer(void* buffer) MOZ_OVERRIDE
-    {
-        EGLint attrs[] = {
-            LOCAL_EGL_IMAGE_PRESERVED, LOCAL_EGL_TRUE,
-            LOCAL_EGL_NONE, LOCAL_EGL_NONE
-        };
-        return sEGLLibrary.fCreateImage(EGL_DISPLAY(),
-                                        EGL_NO_CONTEXT,
-                                        LOCAL_EGL_NATIVE_BUFFER_ANDROID,
-                                        buffer, attrs);
-    }
-
-    void DestroyEGLImage(EGLImage image) MOZ_OVERRIDE
-    {
-        sEGLLibrary.fDestroyImage(EGL_DISPLAY(), image);
-    }
-#endif
-
     virtual void SetEGLSurfaceOverride(EGLSurface surf) MOZ_OVERRIDE {
         if (Screen()) {
             /* Blit `draw` to `read` if we need to, before we potentially juggle
              * `read` around. If we don't, we might attach a different `read`,
              * and *then* hit AssureBlitted, which will blit a dirty `draw` onto
              * the wrong `read`!
              */
             Screen()->AssureBlitted();
--- a/gfx/gl/GLContextProviderGLX.cpp
+++ b/gfx/gl/GLContextProviderGLX.cpp
@@ -53,17 +53,17 @@ LibType
 GLXLibrary::SelectLibrary(const ContextFlags& aFlags)
 {
   return (aFlags & ContextFlagsMesaLLVMPipe)
           ? GLXLibrary::MESA_LLVMPIPE_LIB
           : GLXLibrary::OPENGL_LIB;
 }
 
 // Check that we have at least version aMajor.aMinor .
-bool 
+bool
 GLXLibrary::GLXVersionCheck(int aMajor, int aMinor)
 {
     return aMajor < mGLXMajorVersion ||
            (aMajor == mGLXMajorVersion && aMinor <= mGLXMinorVersion);
 }
 
 static inline bool
 HasExtension(const char* aExtensions, const char* aRequiredExtension)
@@ -239,17 +239,17 @@ GLXLibrary::EnsureInitialized(LibType li
         sym14 = symbols14;
     }
     if (!GLLibraryLoader::LoadSymbols(mOGLLibrary, sym14)) {
         NS_WARNING("Couldn't find required entry point in OpenGL shared library");
         return false;
     }
 
     if (HasExtension(extensionsStr, "GLX_EXT_texture_from_pixmap") &&
-        GLLibraryLoader::LoadSymbols(mOGLLibrary, symbols_texturefrompixmap, 
+        GLLibraryLoader::LoadSymbols(mOGLLibrary, symbols_texturefrompixmap,
                                          (GLLibraryLoader::PlatformLookupFunction)&xGetProcAddress))
     {
 #ifdef MOZ_WIDGET_GTK
         mUseTextureFromPixmap = gfxPlatformGtk::GetPlatform()->UseXRender();
 #else
         mUseTextureFromPixmap = true;
 #endif
     } else {
@@ -273,25 +273,25 @@ GLXLibrary::EnsureInitialized(LibType li
 }
 
 bool
 GLXLibrary::SupportsTextureFromPixmap(gfxASurface* aSurface)
 {
     if (!EnsureInitialized(mLibType)) {
         return false;
     }
-    
+
     if (aSurface->GetType() != gfxSurfaceTypeXlib || !mUseTextureFromPixmap) {
         return false;
     }
 
     return true;
 }
 
-GLXPixmap 
+GLXPixmap
 GLXLibrary::CreatePixmap(gfxASurface* aSurface)
 {
     if (!SupportsTextureFromPixmap(aSurface)) {
         return None;
     }
 
     gfxXlibSurface *xs = static_cast<gfxXlibSurface*>(aSurface);
     const XRenderPictFormat *format = xs->XRenderFormat();
@@ -315,17 +315,17 @@ GLXLibrary::CreatePixmap(gfxASurface* aS
     Display *display = xs->XDisplay();
     int xscreen = DefaultScreen(display);
 
     ScopedXFree<GLXFBConfig> cfgs(xChooseFBConfig(display,
                                                   xscreen,
                                                   attribs,
                                                   &numConfigs));
 
-    // Find an fbconfig that matches the pixel format used on the Pixmap. 
+    // Find an fbconfig that matches the pixel format used on the Pixmap.
     int matchIndex = -1;
     unsigned long redMask =
         static_cast<unsigned long>(direct.redMask) << direct.red;
     unsigned long greenMask =
         static_cast<unsigned long>(direct.greenMask) << direct.green;
     unsigned long blueMask =
         static_cast<unsigned long>(direct.blueMask) << direct.blue;
     // This is true if the Pixmap has bits for alpha or unused bits.
@@ -431,17 +431,17 @@ GLXLibrary::DestroyPixmap(GLXPixmap aPix
     }
 
     Display *display = DefaultXDisplay();
     xDestroyPixmap(display, aPixmap);
 }
 
 void
 GLXLibrary::BindTexImage(GLXPixmap aPixmap)
-{    
+{
     if (!mUseTextureFromPixmap) {
         return;
     }
 
     Display *display = DefaultXDisplay();
     // Make sure all X drawing to the surface has finished before binding to a texture.
     if (mClientIsMesa) {
         // Using XSync instead of Mesa's glXWaitX, because its glxWaitX is a
@@ -503,97 +503,97 @@ GLXLibrary::AfterGLXCall()
         }
         XSetErrorHandler(sOldErrorHandler);
     }
 }
 
 #define BEFORE_GLX_CALL do {                     \
     sGLXLibrary[gCurrLib].BeforeGLXCall();       \
 } while (0)
-    
+
 #define AFTER_GLX_CALL do {                      \
     sGLXLibrary[gCurrLib].AfterGLXCall();        \
 } while (0)
 
 #else
 
 #define BEFORE_GLX_CALL do { } while(0)
 #define AFTER_GLX_CALL do { } while(0)
 
 #endif
-    
-void 
+
+void
 GLXLibrary::xDestroyContext(Display* display, GLXContext context)
 {
     BEFORE_GLX_CALL;
     xDestroyContextInternal(display, context);
     AFTER_GLX_CALL;
 }
 
-Bool 
-GLXLibrary::xMakeCurrent(Display* display, 
-                         GLXDrawable drawable, 
+Bool
+GLXLibrary::xMakeCurrent(Display* display,
+                         GLXDrawable drawable,
                          GLXContext context)
 {
     BEFORE_GLX_CALL;
     Bool result = xMakeCurrentInternal(display, drawable, context);
     AFTER_GLX_CALL;
     return result;
 }
 
-GLXContext 
+GLXContext
 GLXLibrary::xGetCurrentContext()
 {
     BEFORE_GLX_CALL;
     GLXContext result = xGetCurrentContextInternal();
     AFTER_GLX_CALL;
     return result;
 }
 
-/* static */ void* 
+/* static */ void*
 GLXLibrary::xGetProcAddress(const char *procName)
 {
     BEFORE_GLX_CALL;
     void* result = sGLXLibrary[gCurrLib].xGetProcAddressInternal(procName);
     AFTER_GLX_CALL;
     return result;
 }
 
 GLXFBConfig*
-GLXLibrary::xChooseFBConfig(Display* display, 
-                            int screen, 
-                            const int *attrib_list, 
+GLXLibrary::xChooseFBConfig(Display* display,
+                            int screen,
+                            const int *attrib_list,
                             int *nelements)
 {
     BEFORE_GLX_CALL;
     GLXFBConfig* result = xChooseFBConfigInternal(display, screen, attrib_list, nelements);
     AFTER_GLX_CALL;
     return result;
 }
 
-GLXFBConfig* 
-GLXLibrary::xGetFBConfigs(Display* display, 
-                          int screen, 
+GLXFBConfig*
+GLXLibrary::xGetFBConfigs(Display* display,
+                          int screen,
                           int *nelements)
 {
     BEFORE_GLX_CALL;
     GLXFBConfig* result = xGetFBConfigsInternal(display, screen, nelements);
     AFTER_GLX_CALL;
     return result;
 }
-    
+
 GLXContext
-GLXLibrary::xCreateNewContext(Display* display, 
-                              GLXFBConfig config, 
-                              int render_type, 
-                              GLXContext share_list, 
+GLXLibrary::xCreateNewContext(Display* display,
+                              GLXFBConfig config,
+                              int render_type,
+                              GLXContext share_list,
                               Bool direct)
 {
     BEFORE_GLX_CALL;
-    GLXContext result = xCreateNewContextInternal(display, config, 
+    GLXContext result = xCreateNewContextInternal(display, config,
                                                   render_type,
                                                   share_list, direct);
     AFTER_GLX_CALL;
     return result;
 }
 
 int
 GLXLibrary::xGetFBConfigAttrib(Display *display,
@@ -642,17 +642,17 @@ GLXLibrary::xQueryServerString(Display *
 {
     BEFORE_GLX_CALL;
     const char *result = xQueryServerStringInternal(display, screen, name);
     AFTER_GLX_CALL;
     return result;
 }
 
 GLXPixmap
-GLXLibrary::xCreatePixmap(Display *display, 
+GLXLibrary::xCreatePixmap(Display *display,
                           GLXFBConfig config,
                           Pixmap pixmap,
                           const int *attrib_list)
 {
     BEFORE_GLX_CALL;
     GLXPixmap result = xCreatePixmapInternal(display, config,
                                              pixmap, attrib_list);
     AFTER_GLX_CALL;
@@ -705,43 +705,43 @@ GLXLibrary::xReleaseTexImage(Display *di
                              GLXDrawable drawable,
                              int buffer)
 {
     BEFORE_GLX_CALL;
     xReleaseTexImageInternal(display, drawable, buffer);
     AFTER_GLX_CALL;
 }
 
-void 
+void
 GLXLibrary::xWaitGL()
 {
     BEFORE_GLX_CALL;
     xWaitGLInternal();
     AFTER_GLX_CALL;
 }
 
 void
 GLXLibrary::xWaitX()
 {
     BEFORE_GLX_CALL;
     xWaitXInternal();
     AFTER_GLX_CALL;
 }
 
 GLXContext
-GLXLibrary::xCreateContextAttribs(Display* display, 
-                                  GLXFBConfig config, 
-                                  GLXContext share_list, 
+GLXLibrary::xCreateContextAttribs(Display* display,
+                                  GLXFBConfig config,
+                                  GLXContext share_list,
                                   Bool direct,
                                   const int* attrib_list)
 {
     BEFORE_GLX_CALL;
-    GLXContext result = xCreateContextAttribsInternal(display, 
-                                                      config, 
-                                                      share_list, 
+    GLXContext result = xCreateContextAttribsInternal(display,
+                                                      config,
+                                                      share_list,
                                                       direct,
                                                       attrib_list);
     AFTER_GLX_CALL;
     return result;
 }
 
 class GLContextGLX : public GLContext
 {
@@ -900,17 +900,17 @@ TRY_AGAIN_NO_SHARING:
         return true;
     }
 
     void *GetNativeData(NativeDataType aType)
     {
         switch(aType) {
         case NativeGLContext:
             return mContext;
- 
+
         case NativeThebesSurface:
             return mPixmap;
 
         default:
             return nullptr;
         }
     }
 
@@ -1007,23 +1007,23 @@ GLContextProviderGLX::CreateForWindow(ns
 
     // Currently, we take whatever Visual the window already has, and
     // try to create an fbconfig for that visual.  This isn't
     // necessarily what we want in the long run; an fbconfig may not
     // be available for the existing visual, or if it is, the GL
     // performance might be suboptimal.  But using the existing visual
     // is a relatively safe intermediate step.
 
-    Display *display = (Display*)aWidget->GetNativeData(NS_NATIVE_DISPLAY); 
+    Display *display = (Display*)aWidget->GetNativeData(NS_NATIVE_DISPLAY);
     int xscreen = DefaultScreen(display);
     Window window = GET_NATIVE_WINDOW(aWidget);
 
     int numConfigs;
     ScopedXFree<GLXFBConfig> cfgs;
-    if (sDefGLXLib.IsATI() || 
+    if (sDefGLXLib.IsATI() ||
         !sDefGLXLib.GLXVersionCheck(1, 3)) {
         const int attribs[] = {
             LOCAL_GLX_DOUBLEBUFFER, False,
             0
         };
         cfgs = sDefGLXLib.xChooseFBConfig(display,
                                        xscreen,
                                        attribs,
--- a/gfx/gl/GLTextureImage.cpp
+++ b/gfx/gl/GLTextureImage.cpp
@@ -200,23 +200,16 @@ BasicTextureImage::EndUpdate()
 void
 BasicTextureImage::BindTexture(GLenum aTextureUnit)
 {
     mGLContext->fActiveTexture(aTextureUnit);
     mGLContext->fBindTexture(LOCAL_GL_TEXTURE_2D, mTexture);
     mGLContext->fActiveTexture(LOCAL_GL_TEXTURE0);
 }
 
-void
-BasicTextureImage::ApplyFilter()
-{
-  mGLContext->ApplyFilterToBoundTexture(mFilter);
-}
-
-
 already_AddRefed<gfxASurface>
 BasicTextureImage::GetSurfaceForUpdate(const gfxIntSize& aSize, ImageFormat aFmt)
 {
     return gfxPlatform::GetPlatform()->
         CreateOffscreenSurface(aSize, gfxASurface::ContentFromFormat(aFmt));
 }
 
 bool
@@ -632,22 +625,16 @@ void
 TiledTextureImage::BindTexture(GLenum aTextureUnit)
 {
     if (!GetTileCount()) {
         return;
     }
     mImages[mCurrentImage]->BindTexture(aTextureUnit);
 }
 
-void
-TiledTextureImage::ApplyFilter()
-{
-   mGL->ApplyFilterToBoundTexture(mFilter);
-}
-
 /*
  * Resize, trying to reuse tiles. The reuse strategy is to decide on reuse per
  * column. A tile on a column is reused if it hasn't changed size, otherwise it
  * is discarded/replaced. Extra tiles on a column are pruned after iterating
  * each column, and extra rows are pruned after iteration over the entire image
  * finishes.
  */
 void TiledTextureImage::Resize(const nsIntSize& aSize)
@@ -740,26 +727,16 @@ void TiledTextureImage::Resize(const nsI
     mCurrentImage = 0;
 }
 
 uint32_t TiledTextureImage::GetTileCount()
 {
     return mImages.Length();
 }
 
-TextureImage::ScopedBindTexture::ScopedBindTexture(TextureImage* aTexture,
-                                                   GLenum aTextureUnit)
-    : mTexture(aTexture)
-{
-    if (mTexture) {
-        MOZ_ASSERT(aTextureUnit >= LOCAL_GL_TEXTURE0);
-        mTexture->BindTexture(aTextureUnit);
-    }
-}
-
 already_AddRefed<TextureImage>
 CreateBasicTextureImage(GLContext* aGL,
                         const nsIntSize& aSize,
                         TextureImage::ContentType aContentType,
                         GLenum aWrapMode,
                         TextureImage::Flags aFlags,
                         TextureImage::ImageFormat aImageFormat)
 {
--- a/gfx/gl/GLTextureImage.h
+++ b/gfx/gl/GLTextureImage.h
@@ -180,51 +180,16 @@ public:
      */
     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();
-    }
-
-    class ScopedBindTexture
-    {
-    public:
-        ScopedBindTexture(TextureImage *aTexture, GLenum aTextureUnit);
-
-        ~ScopedBindTexture()
-        {
-            if (mTexture) {
-                mTexture->ReleaseTexture();
-            }
-        }
-
-    protected:
-        TextureImage *mTexture;
-    };
-
-    class ScopedBindTextureAndApplyFilter
-        : public ScopedBindTexture
-    {
-    public:
-        ScopedBindTextureAndApplyFilter(TextureImage *aTexture, GLenum aTextureUnit) :
-          ScopedBindTexture(aTexture, aTextureUnit)
-        {
-            if (mTexture) {
-                mTexture->ApplyFilter();
-            }
-        }
-    };
 
     /**
      * Returns the image format of the texture. Only valid after a matching
      * BeginUpdate/EndUpdate pair have been called.
      */
     virtual gfx::SurfaceFormat GetTextureFormat() {
         return mTextureFormat;
     }
@@ -242,22 +207,16 @@ public:
     gfx::IntSize GetSize() const;
     ContentType GetContentType() const { return mContentType; }
     ImageFormat GetImageFormat() const { return mImageFormat; }
     virtual bool InUpdate() const = 0;
     GLenum GetWrapMode() const { return mWrapMode; }
 
     void SetFilter(GraphicsFilter aFilter) { mFilter = aFilter; }
 
-    /**
-     * Applies this TextureImage's filter, assuming that its texture is
-     * the currently bound texture.
-     */
-    virtual void ApplyFilter() = 0;
-
 protected:
     friend class GLContext;
 
     /**
      * After the ctor, the TextureImage is invalid.  Implementations
      * must allocate resources successfully before returning the new
      * TextureImage from GLContext::CreateTextureImage().  That is,
      * clients must not be given partially-constructed TextureImages.
@@ -340,19 +299,17 @@ public:
 
     // Call after surface data has been uploaded to a texture.
     virtual void FinishedSurfaceUpload();
 
     virtual bool InUpdate() const { return !!mUpdateSurface; }
 
     virtual void Resize(const nsIntSize& aSize);
 
-    virtual void ApplyFilter();
 protected:
-
     GLuint mTexture;
     TextureState mTextureState;
     nsRefPtr<GLContext> mGLContext;
     nsRefPtr<gfxASurface> mUpdateSurface;
     nsIntRegion mUpdateRegion;
 
     // The offset into the update surface at which the update rect is located.
     nsIntPoint mUpdateOffset;
@@ -385,17 +342,16 @@ public:
                                       void* aCallbackData);
     virtual gfx::IntRect GetTileRect();
     virtual GLuint GetTextureID() {
         return mImages[mCurrentImage]->GetTextureID();
     }
     virtual bool DirectUpdate(gfxASurface* aSurf, const nsIntRegion& aRegion, const nsIntPoint& aFrom = nsIntPoint(0,0));
     virtual bool InUpdate() const { return mInUpdate; }
     virtual void BindTexture(GLenum);
-    virtual void ApplyFilter();
 
 protected:
     virtual gfx::IntRect GetSrcTileRect();
 
     unsigned int mCurrentImage;
     TileIterationCallback mIterationCallback;
     void* mIterationCallbackData;
     nsTArray< nsRefPtr<TextureImage> > mImages;
--- a/gfx/gl/TextureImageEGL.cpp
+++ b/gfx/gl/TextureImageEGL.cpp
@@ -306,22 +306,16 @@ TextureImageEGL::DestroyEGLSurface(void)
 {
     if (!mSurface)
         return;
 
     sEGLLibrary.fDestroySurface(EGL_DISPLAY(), mSurface);
     mSurface = nullptr;
 }
 
-void
-TextureImageEGL::ApplyFilter()
-{
-    mGLContext->ApplyFilterToBoundTexture(mFilter);
-}
-
 already_AddRefed<TextureImage>
 CreateTextureImageEGL(GLContext *gl,
                       const nsIntSize& aSize,
                       TextureImage::ContentType aContentType,
                       GLenum aWrapMode,
                       TextureImage::Flags aFlags,
                       TextureImage::ImageFormat aImageFormat)
 {
@@ -352,9 +346,9 @@ TileGenFuncEGL(GLContext *gl,
   gl->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MAG_FILTER, texfilter);
   gl->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_S, LOCAL_GL_CLAMP_TO_EDGE);
   gl->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_T, LOCAL_GL_CLAMP_TO_EDGE);
 
   return teximage.forget();
 }
 
 }
-}
\ No newline at end of file
+}
--- a/gfx/gl/TextureImageEGL.h
+++ b/gfx/gl/TextureImageEGL.h
@@ -70,18 +70,16 @@ protected:
     nsRefPtr<gfxASurface> mUpdateSurface;
     EGLImage mEGLImage;
     GLuint mTexture;
     EGLSurface mSurface;
     EGLConfig mConfig;
     TextureState mTextureState;
 
     bool mBound;
-
-    virtual void ApplyFilter();
 };
 
 already_AddRefed<TextureImage>
 CreateTextureImageEGL(GLContext *gl,
                       const nsIntSize& aSize,
                       TextureImage::ContentType aContentType,
                       GLenum aWrapMode,
                       TextureImage::Flags aFlags,
@@ -92,9 +90,9 @@ TileGenFuncEGL(GLContext *gl,
                const nsIntSize& aSize,
                TextureImage::ContentType aContentType,
                TextureImage::Flags aFlags,
                TextureImage::ImageFormat aImageFormat);
 
 }
 }
 
-#endif // TEXTUREIMAGEEGL_H_
\ No newline at end of file
+#endif // TEXTUREIMAGEEGL_H_
new file mode 100644
--- /dev/null
+++ b/gfx/layers/AtomicRefCountedWithFinalize.h
@@ -0,0 +1,47 @@
+/* -*- 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_ATOMICREFCOUNTEDWITHFINALIZE_H_
+#define MOZILLA_ATOMICREFCOUNTEDWITHFINALIZE_H_
+
+#include "mozilla/RefPtr.h"
+
+namespace mozilla {
+
+template<typename T>
+class AtomicRefCountedWithFinalize
+{
+  protected:
+    AtomicRefCountedWithFinalize()
+      : mRefCount(0)
+    {}
+
+    ~AtomicRefCountedWithFinalize() {}
+
+  public:
+    void AddRef() {
+      MOZ_ASSERT(mRefCount >= 0);
+      ++mRefCount;
+    }
+
+    void Release() {
+      MOZ_ASSERT(mRefCount > 0);
+      if (0 == --mRefCount) {
+#ifdef DEBUG
+        mRefCount = detail::DEAD;
+#endif
+        T* derived = static_cast<T*>(this);
+        derived->Finalize();
+        delete derived;
+      }
+    }
+
+private:
+    Atomic<int> mRefCount;
+};
+
+}
+
+#endif
--- a/gfx/layers/ImageContainer.cpp
+++ b/gfx/layers/ImageContainer.cpp
@@ -212,16 +212,17 @@ ImageContainer::SetCurrentImage(Image *a
  void
 ImageContainer::ClearAllImages()
 {
   if (IsAsync()) {
     // Let ImageClient release all TextureClients.
     ImageBridgeChild::FlushAllImages(mImageClient, this, false);
     return;
   }
+
   ReentrantMonitorAutoEnter mon(mReentrantMonitor);
   SetCurrentImageInternal(nullptr);
 }
 
 void
 ImageContainer::ClearAllImagesExceptFront()
 {
   if (IsAsync()) {
--- a/gfx/layers/basic/MacIOSurfaceTextureHostBasic.cpp
+++ b/gfx/layers/basic/MacIOSurfaceTextureHostBasic.cpp
@@ -30,21 +30,20 @@ MacIOSurfaceTextureSourceBasic::GetSize(
 
 gfx::SurfaceFormat
 MacIOSurfaceTextureSourceBasic::GetFormat() const
 {
   return mSurface->HasAlpha() ? gfx::FORMAT_R8G8B8A8 : gfx::FORMAT_B8G8R8X8;
 }
 
 MacIOSurfaceTextureHostBasic::MacIOSurfaceTextureHostBasic(
-    uint64_t aID,
     TextureFlags aFlags,
     const SurfaceDescriptorMacIOSurface& aDescriptor
 )
-  : TextureHost(aID, aFlags)
+  : TextureHost(aFlags)
 {
   mSurface = MacIOSurface::LookupSurface(aDescriptor.surface(),
                                          aDescriptor.scaleFactor(),
                                          aDescriptor.hasAlpha());
 }
 
 gfx::SourceSurface*
 MacIOSurfaceTextureSourceBasic::GetSurface()
--- a/gfx/layers/basic/MacIOSurfaceTextureHostBasic.h
+++ b/gfx/layers/basic/MacIOSurfaceTextureHostBasic.h
@@ -51,19 +51,18 @@ protected:
 /**
  * A TextureHost for shared MacIOSurface
  *
  * Most of the logic actually happens in MacIOSurfaceTextureSourceBasic.
  */
 class MacIOSurfaceTextureHostBasic : public TextureHost
 {
 public:
-  MacIOSurfaceTextureHostBasic(uint64_t aID,
-                             TextureFlags aFlags,
-                             const SurfaceDescriptorMacIOSurface& aDescriptor);
+  MacIOSurfaceTextureHostBasic(TextureFlags aFlags,
+                               const SurfaceDescriptorMacIOSurface& aDescriptor);
 
   virtual void SetCompositor(Compositor* aCompositor) MOZ_OVERRIDE;
 
   virtual bool Lock() MOZ_OVERRIDE;
 
   virtual gfx::SurfaceFormat GetFormat() const MOZ_OVERRIDE;
 
   virtual NewTextureSource* GetTextureSources() MOZ_OVERRIDE
--- a/gfx/layers/basic/TextureHostBasic.cpp
+++ b/gfx/layers/basic/TextureHostBasic.cpp
@@ -8,33 +8,32 @@
 
 using namespace mozilla::gl;
 using namespace mozilla::gfx;
 
 namespace mozilla {
 namespace layers {
 
 TemporaryRef<TextureHost>
-CreateTextureHostBasic(uint64_t aID,
-                       const SurfaceDescriptor& aDesc,
+CreateTextureHostBasic(const SurfaceDescriptor& aDesc,
                        ISurfaceAllocator* aDeallocator,
                        TextureFlags aFlags)
 {
   RefPtr<TextureHost> result;
   switch (aDesc.type()) {
 #ifdef XP_MACOSX
     case SurfaceDescriptor::TSurfaceDescriptorMacIOSurface: {
       const SurfaceDescriptorMacIOSurface& desc =
         aDesc.get_SurfaceDescriptorMacIOSurface();
-      result = new MacIOSurfaceTextureHostBasic(aID, aFlags, desc);
+      result = new MacIOSurfaceTextureHostBasic(aFlags, desc);
       break;
     }
 #endif
     default: {
-      result = CreateBackendIndependentTextureHost(aID, aDesc, aDeallocator, aFlags);
+      result = CreateBackendIndependentTextureHost(aDesc, aDeallocator, aFlags);
       break;
     }
   }
 
   return result;
 }
 
 } // namespace layers
--- a/gfx/layers/client/CanvasClient.cpp
+++ b/gfx/layers/client/CanvasClient.cpp
@@ -53,17 +53,17 @@ CanvasClient::CreateCanvasClient(CanvasC
   return new CanvasClient2D(aForwarder, aFlags);
 }
 
 void
 CanvasClient2D::Update(gfx::IntSize aSize, ClientCanvasLayer* aLayer)
 {
   if (mBuffer &&
       (mBuffer->IsImmutable() || mBuffer->GetSize() != aSize)) {
-    RemoveTextureClient(mBuffer);
+    mBuffer->ForceRemove();
     mBuffer = nullptr;
   }
 
   bool bufferCreated = false;
   if (!mBuffer) {
     bool isOpaque = (aLayer->GetContentFlags() & Layer::CONTENT_OPAQUE);
     gfxContentType contentType = isOpaque
                                                 ? GFX_CONTENT_COLOR
@@ -102,24 +102,16 @@ CanvasClient2D::Update(gfx::IntSize aSiz
 TemporaryRef<BufferTextureClient>
 CanvasClient2D::CreateBufferTextureClient(gfx::SurfaceFormat aFormat, TextureFlags aFlags)
 {
   return CompositableClient::CreateBufferTextureClient(aFormat,
                                                        mTextureInfo.mTextureFlags | aFlags);
 }
 
 void
-CanvasClient2D::OnActorDestroy()
-{
-  if (mBuffer) {
-    mBuffer->OnActorDestroy();
-  }
-}
-
-void
 DeprecatedCanvasClient2D::Updated()
 {
   mForwarder->UpdateTexture(this, 1, mDeprecatedTextureClient->LockSurfaceDescriptor());
 }
 
 
 DeprecatedCanvasClient2D::DeprecatedCanvasClient2D(CompositableForwarder* aFwd,
                                                    TextureFlags aFlags)
@@ -161,24 +153,16 @@ DeprecatedCanvasClient2D::Update(gfx::In
   }
 
   gfxASurface* surface = mDeprecatedTextureClient->LockSurface();
   aLayer->UpdateSurface(surface);
   mDeprecatedTextureClient->Unlock();
 }
 
 void
-DeprecatedCanvasClient2D::OnActorDestroy()
-{
-  if (mDeprecatedTextureClient) {
-    mDeprecatedTextureClient->OnActorDestroy();
-  }
-}
-
-void
 DeprecatedCanvasClientSurfaceStream::Updated()
 {
   mForwarder->UpdateTextureNoSwap(this, 1, mDeprecatedTextureClient->LockSurfaceDescriptor());
 }
 
 
 DeprecatedCanvasClientSurfaceStream::DeprecatedCanvasClientSurfaceStream(CompositableForwarder* aFwd,
                                                                          TextureFlags aFlags)
@@ -236,18 +220,10 @@ DeprecatedCanvasClientSurfaceStream::Upd
     // Ref this so the SurfaceStream doesn't disappear unexpectedly. The
     // Compositor will need to unref it when finished.
     aLayer->mGLContext->AddRef();
   }
 
   aLayer->Painted();
 }
 
-void
-DeprecatedCanvasClientSurfaceStream::OnActorDestroy()
-{
-  if (mDeprecatedTextureClient) {
-    mDeprecatedTextureClient->OnActorDestroy();
-  }
-}
-
 }
 }
--- a/gfx/layers/client/CanvasClient.h
+++ b/gfx/layers/client/CanvasClient.h
@@ -86,18 +86,16 @@ public:
   CreateBufferTextureClient(gfx::SurfaceFormat aFormat,
                             TextureFlags aFlags = TEXTURE_FLAGS_DEFAULT) MOZ_OVERRIDE;
 
   virtual void OnDetach() MOZ_OVERRIDE
   {
     mBuffer = nullptr;
   }
 
-  virtual void OnActorDestroy() MOZ_OVERRIDE;
-
 private:
   RefPtr<TextureClient> mBuffer;
 };
 
 class DeprecatedCanvasClient2D : public CanvasClient
 {
 public:
   DeprecatedCanvasClient2D(CompositableForwarder* aLayerForwarder,
@@ -112,18 +110,16 @@ public:
   virtual void Updated() MOZ_OVERRIDE;
 
   virtual void SetDescriptorFromReply(TextureIdentifier aTextureId,
                                       const SurfaceDescriptor& aDescriptor) MOZ_OVERRIDE
   {
     mDeprecatedTextureClient->SetDescriptorFromReply(aDescriptor);
   }
 
-  virtual void OnActorDestroy() MOZ_OVERRIDE;
-
 private:
   RefPtr<DeprecatedTextureClient> mDeprecatedTextureClient;
 };
 
 // Used for GL canvases where we don't need to do any readback, i.e., with a
 // GL backend.
 class DeprecatedCanvasClientSurfaceStream : public CanvasClient
 {
@@ -140,18 +136,16 @@ public:
   virtual void Updated() MOZ_OVERRIDE;
 
   virtual void SetDescriptorFromReply(TextureIdentifier aTextureId,
                                       const SurfaceDescriptor& aDescriptor) MOZ_OVERRIDE
   {
     mDeprecatedTextureClient->SetDescriptorFromReply(aDescriptor);
   }
 
-  virtual void OnActorDestroy() MOZ_OVERRIDE;
-
 private:
   RefPtr<DeprecatedTextureClient> mDeprecatedTextureClient;
 };
 
 }
 }
 
 #endif
--- a/gfx/layers/client/ClientLayerManager.cpp
+++ b/gfx/layers/client/ClientLayerManager.cpp
@@ -363,27 +363,16 @@ 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.
-        const ReplyTextureRemoved& rep = reply.get_ReplyTextureRemoved();
-        CompositableClient* compositable
-          = static_cast<CompositableChild*>(rep.compositableChild())->GetCompositableClient();
-        compositable->OnReplyTextureRemoved(rep.textureId());
-        break;
-      }
 
       default:
         NS_RUNTIMEABORT("not reached");
       }
     }
 
     if (sent) {
       mNeedsComposite = false;
--- a/gfx/layers/client/CompositableClient.cpp
+++ b/gfx/layers/client/CompositableClient.cpp
@@ -19,45 +19,27 @@
 #endif
 
 using namespace mozilla::gfx;
 
 namespace mozilla {
 namespace layers {
 
 CompositableClient::CompositableClient(CompositableForwarder* aForwarder)
-: mNextTextureID(1)
-, mCompositableChild(nullptr)
+: mCompositableChild(nullptr)
 , mForwarder(aForwarder)
 {
   MOZ_COUNT_CTOR(CompositableClient);
 }
 
 
 CompositableClient::~CompositableClient()
 {
   MOZ_COUNT_DTOR(CompositableClient);
   Destroy();
-
-  FlushTexturesToRemoveCallbacks();
-  MOZ_ASSERT(mTexturesToRemove.Length() == 0, "would leak textures pending for deletion");
-}
-
-void
-CompositableClient::FlushTexturesToRemoveCallbacks()
-{
-  std::map<uint64_t,TextureClientData*>::iterator it
-    = mTexturesToRemoveCallbacks.begin();
-  std::map<uint64_t,TextureClientData*>::iterator stop
-    = mTexturesToRemoveCallbacks.end();
-  for (; it != stop; ++it) {
-    it->second->DeallocateSharedData(GetForwarder());
-    delete it->second;
-  }
-  mTexturesToRemoveCallbacks.clear();
 }
 
 LayersBackend
 CompositableClient::GetCompositorBackendType() const
 {
   return mForwarder->GetCompositorBackendType();
 }
 
@@ -246,75 +228,21 @@ CompositableClient::CreateTextureClientF
     result = CreateBufferTextureClient(aFormat, aTextureFlags);
   }
 
   MOZ_ASSERT(!result || result->AsTextureClientDrawTarget(),
              "Not a TextureClientDrawTarget?");
   return result;
 }
 
-uint64_t
-CompositableClient::NextTextureID()
-{
-  ++mNextTextureID;
-  // 0 is always an invalid ID
-  if (mNextTextureID == 0) {
-    ++mNextTextureID;
-  }
-
-  return mNextTextureID;
-}
-
 bool
 CompositableClient::AddTextureClient(TextureClient* aClient)
 {
-  aClient->SetID(NextTextureID());
-  return mForwarder->AddTexture(this, aClient);
-}
-
-void
-CompositableClient::RemoveTextureClient(TextureClient* aClient)
-{
-  MOZ_ASSERT(aClient);
-  mTexturesToRemove.AppendElement(TextureIDAndFlags(aClient->GetID(),
-                                                    aClient->GetFlags()));
-  if (aClient->GetFlags() & TEXTURE_DEALLOCATE_CLIENT) {
-    TextureClientData* data = aClient->DropTextureData();
-    if (data) {
-      mTexturesToRemoveCallbacks[aClient->GetID()] = data;
-    }
-  }
-  aClient->ClearID();
-  aClient->MarkInvalid();
-}
-
-void
-CompositableClient::OnReplyTextureRemoved(uint64_t aTextureID)
-{
-  std::map<uint64_t,TextureClientData*>::iterator it
-    = mTexturesToRemoveCallbacks.find(aTextureID);
-  if (it != mTexturesToRemoveCallbacks.end()) {
-    it->second->DeallocateSharedData(GetForwarder());
-    delete it->second;
-    mTexturesToRemoveCallbacks.erase(it);
-  }
+  return aClient->InitIPDLActor(mForwarder);
 }
 
 void
 CompositableClient::OnTransaction()
 {
-  for (unsigned i = 0; i < mTexturesToRemove.Length(); ++i) {
-    const TextureIDAndFlags& texture = mTexturesToRemove[i];
-    mForwarder->RemoveTexture(this, texture.mID, texture.mFlags);
-  }
-  mTexturesToRemove.Clear();
 }
 
-
-void
-CompositableChild::ActorDestroy(ActorDestroyReason why)
-{
-  if (mCompositableClient && why == AbnormalShutdown) {
-    mCompositableClient->OnActorDestroy();
-  }
-}
 } // namespace layers
 } // namespace mozilla
--- a/gfx/layers/client/CompositableClient.h
+++ b/gfx/layers/client/CompositableClient.h
@@ -128,72 +128,30 @@ public:
   uint64_t GetAsyncID() const;
 
   /**
    * Tells the Compositor to create a TextureHost for this TextureClient.
    */
   virtual bool 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 transaction.
    */
   virtual void OnTransaction();
 
   /**
    * A hook for the when the Compositable is detached from it's layer.
    */
   virtual void OnDetach() {}
 
-  /**
-   * When texture deallocation must happen on the client side, we need to first
-   * ensure that the compositor has already let go of the data in order
-   * to safely deallocate it.
-   *
-   * This is implemented by registering a callback to postpone deallocation or
-   * recycling of the shared data.
-   *
-   * This hook is called when the compositor notifies the client that it is not
-   * holding any more references to the shared data so that this compositable
-   * can run the corresponding callback.
-   */
-  void OnReplyTextureRemoved(uint64_t aTextureID);
-
-  /**
-   * Run all he registered callbacks (see the comment for OnReplyTextureRemoved).
-   * Only call this if you know what you are doing.
-   */
-  void FlushTexturesToRemoveCallbacks();
-
-  /**
-   * Our IPDL actor is being destroyed, get rid of any shmem resources now.
-   */
-  virtual void OnActorDestroy() = 0;
-
 protected:
-  // return the next texture ID
-  uint64_t NextTextureID();
-
-  struct TextureIDAndFlags {
-    TextureIDAndFlags(uint64_t aID, TextureFlags aFlags)
-    : mID(aID), mFlags(aFlags) {}
-    uint64_t mID;
-    TextureFlags mFlags;
-  };
-  // The textures to destroy in the next transaction;
-  nsTArray<TextureIDAndFlags> mTexturesToRemove;
-  std::map<uint64_t, TextureClientData*> mTexturesToRemoveCallbacks;
-  uint64_t mNextTextureID;
   CompositableChild* mCompositableChild;
   CompositableForwarder* mForwarder;
+
+  friend class CompositableChild;
 };
 
 /**
  * IPDL actor used by CompositableClient to match with its corresponding
  * CompositableHost on the compositor side.
  *
  * CompositableChild is owned by a CompositableClient.
  */
@@ -217,17 +175,21 @@ public:
     mCompositableClient = aClient;
   }
 
   CompositableClient* GetCompositableClient() const
   {
     return mCompositableClient;
   }
 
-  virtual void ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE;
+  virtual void ActorDestroy(ActorDestroyReason) MOZ_OVERRIDE {
+    if (mCompositableClient) {
+      mCompositableClient->mCompositableChild = nullptr;
+    }
+  }
 
   void SetAsyncID(uint64_t aID) { mID = aID; }
   uint64_t GetAsyncID() const
   {
     return mID;
   }
 private:
   CompositableClient* mCompositableClient;
--- a/gfx/layers/client/ContentClient.cpp
+++ b/gfx/layers/client/ContentClient.cpp
@@ -143,19 +143,16 @@ ContentClientRemoteBuffer::BeginPaint()
 
 void
 ContentClientRemoteBuffer::EndPaint()
 {
   // XXX: We might still not have a texture client if PaintThebes
   // decided we didn't need one yet because the region to draw was empty.
   SetBufferProvider(nullptr);
   SetBufferProviderOnWhite(nullptr);
-  for (size_t i = 0; i < mOldTextures.Length(); ++i) {
-    RemoveTextureClient(mOldTextures[i]);
-  }
   mOldTextures.Clear();
 
   if (mTextureClient) {
     mTextureClient->Unlock();
   }
   if (mTextureClientOnWhite) {
     mTextureClientOnWhite->Unlock();
   }
@@ -294,30 +291,16 @@ ContentClientRemoteBuffer::Updated(const
 void
 ContentClientRemoteBuffer::SwapBuffers(const nsIntRegion& aFrontUpdatedRegion)
 {
   MOZ_ASSERT(mTextureClient);
   mFrontAndBackBufferDiffer = true;
 }
 
 void
-ContentClientRemoteBuffer::OnActorDestroy()
-{
-  if (mTextureClient) {
-    mTextureClient->OnActorDestroy();
-  }
-  if (mTextureClientOnWhite) {
-    mTextureClientOnWhite->OnActorDestroy();
-  }
-  for (size_t i = 0; i < mOldTextures.Length(); ++i) {
-    mOldTextures[i]->OnActorDestroy();
-  }
-}
-
-void
 DeprecatedContentClientRemoteBuffer::DestroyBuffers()
 {
   if (!mDeprecatedTextureClient) {
     return;
   }
 
   mDeprecatedTextureClient = nullptr;
   mDeprecatedTextureClientOnWhite = nullptr;
@@ -492,31 +475,16 @@ DeprecatedContentClientRemoteBuffer::Swa
 
   mFrontAndBackBufferDiffer = true;
   mDeprecatedTextureClient->SetAccessMode(DeprecatedTextureClient::ACCESS_READ_WRITE);
   if (mDeprecatedTextureClientOnWhite) {
     mDeprecatedTextureClientOnWhite->SetAccessMode(DeprecatedTextureClient::ACCESS_READ_WRITE);
   }
 }
 
-
-void
-DeprecatedContentClientRemoteBuffer::OnActorDestroy()
-{
-  if (mDeprecatedTextureClient) {
-    mDeprecatedTextureClient->OnActorDestroy();
-  }
-  if (mDeprecatedTextureClientOnWhite) {
-    mDeprecatedTextureClientOnWhite->OnActorDestroy();
-  }
-  for (size_t i = 0; i < mOldTextures.Length(); ++i) {
-    mOldTextures[i]->OnActorDestroy();
-  }
-}
- 
 void
 ContentClientDoubleBuffered::CreateFrontBuffer(const nsIntRect& aBufferRect)
 {
   if (!CreateAndAllocateTextureClient(mFrontClient, TEXTURE_ON_BLACK) ||
       !AddTextureClient(mFrontClient)) {
     AbortTextureClientCreation();
     return;
   }
@@ -661,36 +629,16 @@ ContentClientDoubleBuffered::UpdateDesti
     if (isClippingCheap) {
       gfxUtils::ClipToRegion(destCtx, aUpdateRegion);
     }
 
     aSource.DrawBufferWithRotation(destCtx->GetDrawTarget(), BUFFER_WHITE, 1.0, OP_SOURCE);
   }
 }
 
-void
-ContentClientDoubleBuffered::OnActorDestroy()
-{
-  if (mTextureClient) {
-    mTextureClient->OnActorDestroy();
-  }
-  if (mTextureClientOnWhite) {
-    mTextureClientOnWhite->OnActorDestroy();
-  }
-  for (size_t i = 0; i < mOldTextures.Length(); ++i) {
-    mOldTextures[i]->OnActorDestroy();
-  }
-  if (mFrontClient) {
-    mFrontClient->OnActorDestroy();
-  }
-  if (mFrontClientOnWhite) {
-    mFrontClientOnWhite->OnActorDestroy();
-  }
-}
-
 DeprecatedContentClientDoubleBuffered::~DeprecatedContentClientDoubleBuffered()
 {
   if (mDeprecatedTextureClient) {
     MOZ_ASSERT(mFrontClient);
     mDeprecatedTextureClient->SetDescriptor(SurfaceDescriptor());
     mFrontClient->SetDescriptor(SurfaceDescriptor());
   }
   if (mDeprecatedTextureClientOnWhite) {
@@ -781,36 +729,16 @@ DeprecatedContentClientDoubleBuffered::S
   mFrontClient->SetAccessMode(DeprecatedTextureClient::ACCESS_READ_ONLY);
   if (mFrontClientOnWhite) {
     mFrontClientOnWhite->SetAccessMode(DeprecatedTextureClient::ACCESS_READ_ONLY);
   }
 
   DeprecatedContentClientRemoteBuffer::SwapBuffers(aFrontUpdatedRegion);
 }
 
-void
-DeprecatedContentClientDoubleBuffered::OnActorDestroy()
-{
-  if (mDeprecatedTextureClient) {
-    mDeprecatedTextureClient->OnActorDestroy();
-  }
-  if (mDeprecatedTextureClientOnWhite) {
-    mDeprecatedTextureClientOnWhite->OnActorDestroy();
-  }
-  for (size_t i = 0; i < mOldTextures.Length(); ++i) {
-    mOldTextures[i]->OnActorDestroy();
-  }
-  if (mFrontClient) {
-    mFrontClient->OnActorDestroy();
-  }
-  if (mFrontClientOnWhite) {
-    mFrontClientOnWhite->OnActorDestroy();
-  }
-}
-
 struct AutoDeprecatedTextureClient {
   AutoDeprecatedTextureClient()
     : mTexture(nullptr)
   {}
   ~AutoDeprecatedTextureClient()
   {
     if (mTexture) {
       mTexture->Unlock();
--- a/gfx/layers/client/ContentClient.h
+++ b/gfx/layers/client/ContentClient.h
@@ -154,18 +154,16 @@ public:
 
   virtual void CreateBuffer(ContentType aType, const nsIntRect& aRect, uint32_t aFlags,
                             RefPtr<gfx::DrawTarget>* aBlackDT, RefPtr<gfx::DrawTarget>* aWhiteDT) MOZ_OVERRIDE;
 
   virtual TextureInfo GetTextureInfo() const MOZ_OVERRIDE
   {
     MOZ_CRASH("Should not be called on non-remote ContentClient");
   }
-
-  virtual void OnActorDestroy() MOZ_OVERRIDE {}
 };
 
 /**
  * A ContentClientRemote backed by a RotatedContentBuffer.
  *
  * When using a ContentClientRemote, SurfaceDescriptors are created on
  * the rendering side and destroyed on the compositing side. They are only
  * passed from one side to the other when the TextureClient/Hosts are created.
@@ -233,18 +231,16 @@ public:
   virtual void CreateBuffer(ContentType aType, const nsIntRect& aRect, uint32_t aFlags,
                             RefPtr<gfx::DrawTarget>* aBlackDT, RefPtr<gfx::DrawTarget>* aWhiteDT) MOZ_OVERRIDE;
 
   virtual TextureInfo GetTextureInfo() const MOZ_OVERRIDE
   {
     return mTextureInfo;
   }
 
-  virtual void OnActorDestroy() MOZ_OVERRIDE;
-
 protected:
   void DestroyBuffers();
 
   virtual nsIntRegion GetUpdatedRegion(const nsIntRegion& aRegionToDraw,
                                        const nsIntRegion& aVisibleRegion,
                                        bool aDidSelfCopy);
 
   void BuildTextureClients(gfx::SurfaceFormat aFormat,
@@ -335,18 +331,16 @@ public:
   virtual void CreateBuffer(ContentType aType, const nsIntRect& aRect, uint32_t aFlags,
                             RefPtr<gfx::DrawTarget>* aBlackDT, RefPtr<gfx::DrawTarget>* aWhiteDT) MOZ_OVERRIDE;
 
   virtual TextureInfo GetTextureInfo() const MOZ_OVERRIDE
   {
     return mTextureInfo;
   }
 
-  virtual void OnActorDestroy() MOZ_OVERRIDE;
-
 protected:
   void DestroyBuffers();
 
   virtual nsIntRegion GetUpdatedRegion(const nsIntRegion& aRegionToDraw,
                                        const nsIntRegion& aVisibleRegion,
                                        bool aDidSelfCopy);
 
   // create and configure mDeprecatedTextureClient
@@ -397,18 +391,16 @@ public:
     mTextureInfo.mCompositableType = COMPOSITABLE_CONTENT_DOUBLE;
   }
   virtual ~ContentClientDoubleBuffered() {}
 
   virtual void SwapBuffers(const nsIntRegion& aFrontUpdatedRegion) MOZ_OVERRIDE;
 
   virtual void SyncFrontBufferToBackBuffer() MOZ_OVERRIDE;
 
-  virtual void OnActorDestroy() MOZ_OVERRIDE;
-
 protected:
   virtual void CreateFrontBuffer(const nsIntRect& aBufferRect) MOZ_OVERRIDE;
   virtual void DestroyFrontBuffer() MOZ_OVERRIDE;
 
 private:
   void UpdateDestinationFrom(const RotatedBuffer& aSource,
                              const nsIntRegion& aUpdateRegion);
 
@@ -436,18 +428,16 @@ public:
     mTextureInfo.mCompositableType = BUFFER_CONTENT_DIRECT;
   }
   ~DeprecatedContentClientDoubleBuffered();
 
   virtual void SwapBuffers(const nsIntRegion& aFrontUpdatedRegion) MOZ_OVERRIDE;
 
   virtual void SyncFrontBufferToBackBuffer() MOZ_OVERRIDE;
 
-  virtual void OnActorDestroy() MOZ_OVERRIDE;
-
 protected:
   virtual void CreateFrontBufferAndNotify(const nsIntRect& aBufferRect) MOZ_OVERRIDE;
   virtual void DestroyFrontBuffer() MOZ_OVERRIDE;
   virtual void LockFrontBuffer() MOZ_OVERRIDE;
 
 private:
   void UpdateDestinationFrom(const RotatedBuffer& aSource,
                              const nsIntRegion& aUpdateRegion);
@@ -544,18 +534,16 @@ public:
     if (IsSurfaceDescriptorValid(mUpdateDescriptor)) {
       mForwarder->DestroySharedSurface(&mUpdateDescriptor);
     }
     if (IsSurfaceDescriptorValid(mUpdateDescriptorOnWhite)) {
       mForwarder->DestroySharedSurface(&mUpdateDescriptorOnWhite);
     }
   }
 
-  virtual void OnActorDestroy() MOZ_OVERRIDE {}
-
 private:
 
   enum BufferType{
     BUFFER_BLACK,
     BUFFER_WHITE
   };
 
   void NotifyBufferCreated(ContentType aType, uint32_t aFlags)
--- a/gfx/layers/client/ImageClient.cpp
+++ b/gfx/layers/client/ImageClient.cpp
@@ -96,30 +96,30 @@ TextureInfo ImageClientSingle::GetTextur
 {
   return TextureInfo(COMPOSITABLE_IMAGE);
 }
 
 void
 ImageClientSingle::FlushAllImages(bool aExceptFront)
 {
   if (!aExceptFront && mFrontBuffer) {
-    RemoveTextureClient(mFrontBuffer);
+    mFrontBuffer->ForceRemove();
     mFrontBuffer = nullptr;
   }
 }
 
 void
 ImageClientBuffered::FlushAllImages(bool aExceptFront)
 {
   if (!aExceptFront && mFrontBuffer) {
-    RemoveTextureClient(mFrontBuffer);
+    mFrontBuffer->ForceRemove();
     mFrontBuffer = nullptr;
   }
   if (mBackBuffer) {
-    RemoveTextureClient(mBackBuffer);
+    mBackBuffer->ForceRemove();
     mBackBuffer = nullptr;
   }
 }
 
 bool
 ImageClientSingle::UpdateImage(ImageContainer* aContainer,
                                uint32_t aContentFlags)
 {
@@ -140,34 +140,34 @@ ImageClientSingle::UpdateImage(ImageCont
 
     if (texture->IsSharedWithCompositor()) {
       // XXX - temporary fix for bug 911941
       // This will be changed with bug 912907
       return false;
     }
 
     if (mFrontBuffer) {
-      RemoveTextureClient(mFrontBuffer);
+      mFrontBuffer->ForceRemove();
     }
     mFrontBuffer = texture;
     if (!AddTextureClient(texture)) {
       mFrontBuffer = nullptr;
       return false;
     }
     GetForwarder()->UpdatedTexture(this, texture, nullptr);
     GetForwarder()->UseTexture(this, texture);
   } else if (image->GetFormat() == PLANAR_YCBCR) {
     PlanarYCbCrImage* ycbcr = static_cast<PlanarYCbCrImage*>(image);
     const PlanarYCbCrData* data = ycbcr->GetData();
     if (!data) {
       return false;
     }
 
     if (mFrontBuffer && mFrontBuffer->IsImmutable()) {
-      RemoveTextureClient(mFrontBuffer);
+      mFrontBuffer->ForceRemove();
       mFrontBuffer = nullptr;
     }
 
     bool bufferCreated = false;
     if (!mFrontBuffer) {
       mFrontBuffer = CreateBufferTextureClient(gfx::FORMAT_YUV, TEXTURE_FLAGS_DEFAULT);
       gfx::IntSize ySize(data->mYSize.width, data->mYSize.height);
       gfx::IntSize cbCrSize(data->mCbCrSize.width, data->mCbCrSize.height);
@@ -200,17 +200,17 @@ ImageClientSingle::UpdateImage(ImageCont
     }
 
   } else if (image->GetFormat() == SHARED_TEXTURE) {
     SharedTextureImage* sharedImage = static_cast<SharedTextureImage*>(image);
     const SharedTextureImage::Data *data = sharedImage->GetData();
     gfx::IntSize size = gfx::IntSize(image->GetSize().width, image->GetSize().height);
 
     if (mFrontBuffer) {
-      RemoveTextureClient(mFrontBuffer);
+      mFrontBuffer->ForceRemove();
       mFrontBuffer = nullptr;
     }
 
     RefPtr<SharedTextureClientOGL> buffer = new SharedTextureClientOGL(mTextureFlags);
     buffer->InitWith(data->mHandle, size, data->mShareType, data->mInverted);
     mFrontBuffer = buffer;
     if (!AddTextureClient(mFrontBuffer)) {
       mFrontBuffer = nullptr;
@@ -221,17 +221,17 @@ ImageClientSingle::UpdateImage(ImageCont
   } else {
     nsRefPtr<gfxASurface> surface = image->GetAsSurface();
     MOZ_ASSERT(surface);
 
     gfx::IntSize size = gfx::IntSize(image->GetSize().width, image->GetSize().height);
 
     if (mFrontBuffer &&
         (mFrontBuffer->IsImmutable() || mFrontBuffer->GetSize() != size)) {
-      RemoveTextureClient(mFrontBuffer);
+      mFrontBuffer->ForceRemove();
       mFrontBuffer = nullptr;
     }
 
     bool bufferCreated = false;
     if (!mFrontBuffer) {
       gfxImageFormat format
         = gfxPlatform::GetPlatform()->OptimalFormatForContent(surface->GetContentType());
       mFrontBuffer = CreateBufferTextureClient(gfx::ImageFormatToSurfaceFormat(format),
@@ -275,35 +275,16 @@ ImageClientBuffered::UpdateImage(ImageCo
                                  uint32_t aContentFlags)
 {
   RefPtr<TextureClient> temp = mFrontBuffer;
   mFrontBuffer = mBackBuffer;
   mBackBuffer = temp;
   return ImageClientSingle::UpdateImage(aContainer, aContentFlags);
 }
 
-void
-ImageClientSingle::OnActorDestroy()
-{
-  if (mFrontBuffer) {
-    mFrontBuffer->OnActorDestroy();
-  }
-}
-
-void
-ImageClientBuffered::OnActorDestroy()
-{
-  if (mFrontBuffer) {
-    mFrontBuffer->OnActorDestroy();
-  }
-  if (mBackBuffer) {
-    mBackBuffer->OnActorDestroy();
-  }
-}
-
 bool
 ImageClientSingle::AddTextureClient(TextureClient* aTexture)
 {
   MOZ_ASSERT((mTextureFlags & aTexture->GetFlags()) == mTextureFlags);
   return CompositableClient::AddTextureClient(aTexture);
 }
 
 TemporaryRef<BufferTextureClient>
@@ -479,24 +460,16 @@ DeprecatedImageClientSingle::Updated()
 ImageClientBridge::ImageClientBridge(CompositableForwarder* aFwd,
                                      TextureFlags aFlags)
 : ImageClient(aFwd, BUFFER_BRIDGE)
 , mAsyncContainerID(0)
 , mLayer(nullptr)
 {
 }
 
-void
-DeprecatedImageClientSingle::OnActorDestroy()
-{
-  if (mDeprecatedTextureClient) {
-    mDeprecatedTextureClient->OnActorDestroy();
-  }
-}
-
 bool
 ImageClientBridge::UpdateImage(ImageContainer* aContainer, uint32_t aContentFlags)
 {
   if (!GetForwarder() || !mLayer) {
     return false;
   }
   if (mAsyncContainerID == aContainer->GetAsyncContainerID()) {
     return true;
--- a/gfx/layers/client/ImageClient.h
+++ b/gfx/layers/client/ImageClient.h
@@ -97,18 +97,16 @@ public:
 
   virtual TextureInfo GetTextureInfo() const MOZ_OVERRIDE;
 
   virtual already_AddRefed<Image> CreateImage(const uint32_t *aFormats,
                                               uint32_t aNumFormats) MOZ_OVERRIDE;
 
   virtual void FlushAllImages(bool aExceptFront) MOZ_OVERRIDE;
 
-  virtual void OnActorDestroy() MOZ_OVERRIDE;
-
 protected:
   RefPtr<TextureClient> mFrontBuffer;
   // Some layers may want to enforce some flags to all their textures
   // (like disallowing tiling)
   TextureFlags mTextureFlags;
 };
 
 /**
@@ -122,18 +120,16 @@ public:
                       CompositableType aType);
 
   virtual bool UpdateImage(ImageContainer* aContainer, uint32_t aContentFlags);
 
   virtual void OnDetach() MOZ_OVERRIDE;
 
   virtual void FlushAllImages(bool aExceptFront) MOZ_OVERRIDE;
 
-  virtual void OnActorDestroy() 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
@@ -168,18 +164,16 @@ public:
   virtual TextureInfo GetTextureInfo() const MOZ_OVERRIDE
   {
     return mTextureInfo;
   }
 
   virtual already_AddRefed<Image> CreateImage(const uint32_t *aFormats,
                                               uint32_t aNumFormats) MOZ_OVERRIDE;
 
-  virtual void OnActorDestroy() MOZ_OVERRIDE;
-
 private:
   RefPtr<DeprecatedTextureClient> mDeprecatedTextureClient;
   TextureInfo mTextureInfo;
 };
 
 /**
  * Image class to be used for async image uploads using the image bridge
  * protocol.
@@ -211,18 +205,16 @@ public:
 
   virtual already_AddRefed<Image> CreateImage(const uint32_t *aFormats,
                                               uint32_t aNumFormats) MOZ_OVERRIDE
   {
     NS_WARNING("Should not create an image through an ImageClientBridge");
     return nullptr;
   }
 
-  virtual void OnActorDestroy() MOZ_OVERRIDE {}
-
 protected:
   uint64_t mAsyncContainerID;
   ShadowableLayer* mLayer;
 };
 
 }
 }
 
--- a/gfx/layers/client/TextureClient.cpp
+++ b/gfx/layers/client/TextureClient.cpp
@@ -14,16 +14,17 @@
 #include "mozilla/ipc/SharedMemory.h"   // for SharedMemory, etc
 #include "mozilla/layers/CompositableClient.h"  // for CompositableClient
 #include "mozilla/layers/CompositableForwarder.h"
 #include "mozilla/layers/ISurfaceAllocator.h"
 #include "mozilla/layers/ImageDataSerializer.h"
 #include "mozilla/layers/ShadowLayers.h"  // for ShadowLayerForwarder
 #include "mozilla/layers/SharedPlanarYCbCrImage.h"
 #include "mozilla/layers/YCbCrImageDataSerializer.h"
+#include "mozilla/layers/PTextureChild.h"
 #include "nsDebug.h"                    // for NS_ASSERTION, NS_WARNING, etc
 #include "nsTraceRefcnt.h"              // for MOZ_COUNT_CTOR, etc
 #include "ImageContainer.h"             // for PlanarYCbCrImage, etc
 #include "mozilla/gfx/2D.h"
 
 #ifdef MOZ_ANDROID_OMTC
 #  include "gfxReusableImageSurfaceWrapper.h"
 #  include "gfxImageSurface.h"
@@ -33,16 +34,136 @@
 #endif
 
 using namespace mozilla::gl;
 using namespace mozilla::gfx;
 
 namespace mozilla {
 namespace layers {
 
+/**
+ * TextureChild is the content-side incarnation of the PTexture IPDL actor.
+ *
+ * TextureChild is used to synchronize a texture client and its corresponding
+ * TextureHost if needed (a TextureClient that is not shared with the compositor
+ * does not have a TextureChild)
+ *
+ * During the deallocation phase, a TextureChild may hold its recently destroyed
+ * TextureClient's data until the compositor side confirmed that it is safe to
+ * deallocte or recycle the it.
+ */
+class TextureChild : public PTextureChild
+{
+public:
+  TextureChild()
+  : mForwarder(nullptr)
+  , mTextureData(nullptr)
+  , mTextureClient(nullptr)
+  {
+    MOZ_COUNT_CTOR(TextureChild);
+  }
+
+  ~TextureChild()
+  {
+    MOZ_COUNT_DTOR(TextureChild);
+  }
+
+  bool Recv__delete__() MOZ_OVERRIDE;
+
+  /**
+   * Only used during the deallocation phase iff we need synchronization between
+   * the client and host side for deallocation (that is, when the data is going
+   * to be deallocated or recycled on the client side).
+   */
+  void SetTextureData(TextureClientData* aData)
+  {
+    mTextureData = aData;
+  }
+
+  void DeleteTextureData();
+
+  CompositableForwarder* GetForwarder() { return mForwarder; }
+
+  ISurfaceAllocator* GetAllocator() { return mForwarder; }
+
+  void ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE;
+
+private:
+
+  CompositableForwarder* mForwarder;
+  TextureClientData* mTextureData;
+  TextureClient* mTextureClient;
+
+  friend class TextureClient;
+};
+
+void
+TextureChild::DeleteTextureData()
+{
+  if (mTextureData) {
+    mTextureData->DeallocateSharedData(GetAllocator());
+    delete mTextureData;
+    mTextureData = nullptr;
+  }
+}
+
+bool
+TextureChild::Recv__delete__()
+{
+  DeleteTextureData();
+  return true;
+}
+
+void
+TextureChild::ActorDestroy(ActorDestroyReason why)
+{
+  if (mTextureClient) {
+    mTextureClient->mActor = nullptr;
+  }
+}
+
+// static
+PTextureChild*
+TextureClient::CreateIPDLActor()
+{
+  return new TextureChild();
+}
+
+// static
+bool
+TextureClient::DestroyIPDLActor(PTextureChild* actor)
+{
+  delete actor;
+  return true;
+}
+
+bool
+TextureClient::InitIPDLActor(CompositableForwarder* aForwarder)
+{
+  MOZ_ASSERT(!mActor);
+  MOZ_ASSERT(aForwarder);
+
+  SurfaceDescriptor desc;
+  if (!ToSurfaceDescriptor(desc)) {
+    return false;
+  }
+
+  mActor = static_cast<TextureChild*>(aForwarder->CreateEmptyTextureChild());
+  mActor->mForwarder = aForwarder;
+  mActor->mTextureClient = this;
+  mShared = true;
+  return mActor->SendInit(desc, GetFlags());
+}
+
+PTextureChild*
+TextureClient::GetIPDLActor()
+{
+  return mActor;
+}
+
 class ShmemTextureClientData : public TextureClientData
 {
 public:
   ShmemTextureClientData(ipc::Shmem& aShmem)
   : mShmem(aShmem)
   {
     MOZ_COUNT_CTOR(ShmemTextureClientData);
   }
@@ -75,16 +196,17 @@ public:
   {
     MOZ_ASSERT(!mBuffer, "Forgot to deallocate the shared texture data?");
     MOZ_COUNT_CTOR(MemoryTextureClientData);
   }
 
   virtual void DeallocateSharedData(ISurfaceAllocator*)
   {
     delete[] mBuffer;
+    mBuffer = nullptr;
   }
 
 private:
   uint8_t* mBuffer;
 };
 
 TextureClientData*
 MemoryTextureClient::DropTextureData()
@@ -106,24 +228,53 @@ ShmemTextureClient::DropTextureData()
   }
   TextureClientData* result = new ShmemTextureClientData(mShmem);
   MarkInvalid();
   mShmem = ipc::Shmem();
   return result;
 }
 
 TextureClient::TextureClient(TextureFlags aFlags)
-  : mID(0)
+  : mActor(nullptr)
   , mFlags(aFlags)
   , mShared(false)
   , mValid(true)
 {}
 
 TextureClient::~TextureClient()
-{}
+{
+  // All the destruction code that may lead to virtual method calls must
+  // be in Finalize() which is called just before the destructor.
+}
+
+void TextureClient::ForceRemove()
+{
+  if (mValid && mActor) {
+    if (GetFlags() & TEXTURE_DEALLOCATE_CLIENT) {
+      mActor->SetTextureData(DropTextureData());
+      mActor->SendRemoveTextureSync();
+      mActor->DeleteTextureData();
+    } else {
+      mActor->SendRemoveTexture();
+    }
+  }
+  MarkInvalid();
+}
+
+void
+TextureClient::Finalize()
+{
+  if (mActor) {
+    // this will call ForceRemove in the right thread, using a sync proxy if needed
+    mActor->GetForwarder()->RemoveTexture(this);
+
+    // mActor has a raw pointer to us, mActor->mTextureClient. Null it before we die.
+    mActor->mTextureClient = nullptr;
+  }
+}
 
 bool
 TextureClient::ShouldDeallocateInDestructor() const
 {
   if (!IsAllocated()) {
     return false;
   }
 
@@ -232,18 +383,18 @@ MemoryTextureClient::MemoryTextureClient
   , mBufSize(0)
 {
   MOZ_COUNT_CTOR(MemoryTextureClient);
 }
 
 MemoryTextureClient::~MemoryTextureClient()
 {
   MOZ_COUNT_DTOR(MemoryTextureClient);
-  if (ShouldDeallocateInDestructor() && mBuffer) {
-    // if the buffer has never been shared we must deallocate it or ir would
+  if (mBuffer && ShouldDeallocateInDestructor()) {
+    // if the buffer has never been shared we must deallocate it or it would
     // leak.
     GfxMemoryImageReporter::WillFree(mBuffer);
     delete mBuffer;
   }
 }
 
 BufferTextureClient::BufferTextureClient(CompositableClient* aCompositable,
                                          gfx::SurfaceFormat aFormat,
@@ -408,25 +559,16 @@ DeprecatedTextureClient::DeprecatedTextu
 }
 
 DeprecatedTextureClient::~DeprecatedTextureClient()
 {
   MOZ_COUNT_DTOR(DeprecatedTextureClient);
   MOZ_ASSERT(mDescriptor.type() == SurfaceDescriptor::T__None, "Need to release surface!");
 }
 
-void
-DeprecatedTextureClient::OnActorDestroy()
-{
-  if (ISurfaceAllocator::IsShmem(&mDescriptor)) {
-    mDescriptor = SurfaceDescriptor();
-  }
-}
-
-
 DeprecatedTextureClientShmem::DeprecatedTextureClientShmem(CompositableForwarder* aForwarder,
                                        const TextureInfo& aTextureInfo)
   : DeprecatedTextureClient(aForwarder, aTextureInfo)
 {
 }
 
 DeprecatedTextureClientShmem::~DeprecatedTextureClientShmem()
 {
--- a/gfx/layers/client/TextureClient.h
+++ b/gfx/layers/client/TextureClient.h
@@ -19,31 +19,34 @@
 #include "mozilla/gfx/Types.h"          // for SurfaceFormat
 #include "mozilla/ipc/Shmem.h"          // for Shmem
 #include "mozilla/layers/CompositorTypes.h"  // for TextureFlags, etc
 #include "mozilla/layers/LayersSurfaces.h"  // for SurfaceDescriptor
 #include "mozilla/mozalloc.h"           // for operator delete
 #include "nsAutoPtr.h"                  // for nsRefPtr
 #include "nsCOMPtr.h"                   // for already_AddRefed
 #include "nsISupportsImpl.h"            // for TextureImage::AddRef, etc
+#include "mozilla/layers/AtomicRefCountedWithFinalize.h"
 
 class gfxReusableSurfaceWrapper;
 class gfxASurface;
 class gfxImageSurface;
 
 namespace mozilla {
 namespace layers {
 
 class ContentClient;
 class CompositableForwarder;
 class ISurfaceAllocator;
 class CompositableClient;
 class PlanarYCbCrImage;
 class PlanarYCbCrData;
 class Image;
+class PTextureChild;
+class TextureChild;
 
 /**
  * TextureClient is the abstraction that allows us to share data between the
  * content and the compositor side.
  * TextureClient can also provide with some more "producer" facing APIs
  * such as TextureClientSurface and TextureClientYCbCr, that can be queried
  * using AsTextureCLientSurface(), etc.
  */
@@ -106,24 +109,23 @@ public:
 /**
  * Holds the shared data of a TextureClient, to be destroyed later.
  *
  * TextureClient's destructor initiates the destruction sequence of the
  * texture client/host pair. If the shared data is to be deallocated on the
  * host side, there is nothing to do.
  * On the other hand, if the client data must be deallocated on the client
  * side, the CompositableClient will ask the TextureClient to drop its shared
- * data in the form of a TextureClientData object. The compositable will keep
- * this object until it has received from the host side the confirmation that
- * the compositor is not using the texture and that it is completely safe to
- * deallocate the shared data.
+ * data in the form of a TextureClientData object. This data will be kept alive
+ * until the host side confirms that it is not using the data anymore and that
+ * it is completely safe to deallocate the shared data.
  *
  * See:
- *  - CompositableClient::RemoveTextureClient
- *  - CompositableClient::OnReplyTextureRemoved
+ *  - The PTexture IPDL protocol
+ *  - CompositableChild in TextureClient.cpp
  */
 class TextureClientData {
 public:
   virtual void DeallocateSharedData(ISurfaceAllocator* allocator) = 0;
   virtual ~TextureClientData() {}
 };
 
 /**
@@ -144,17 +146,18 @@ public:
  * 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
  * 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 AtomicRefCounted<TextureClient>
+class TextureClient
+  : public AtomicRefCountedWithFinalize<TextureClient>
 {
 public:
   TextureClient(TextureFlags aFlags = TEXTURE_FLAGS_DEFAULT);
   virtual ~TextureClient();
 
   virtual TextureClientSurface* AsTextureClientSurface() { return nullptr; }
   virtual TextureClientDrawTarget* AsTextureClientDrawTarget() { return nullptr; }
   virtual TextureClientYCbCr* AsTextureClientYCbCr() { return nullptr; }
@@ -172,38 +175,25 @@ public:
   /**
    * Returns true if this texture has a lock/unlock mechanism.
    * Textures that do not implement locking should be immutable or should
    * use immediate uploads (see TextureFlags in CompositorTypes.h)
    */
   virtual bool ImplementsLocking() const { return false; }
 
   /**
-   * Sets this texture's ID.
+   * Allocate and deallocate a TextureChild actor.
    *
-   * This ID is used to match a texture client with his corresponding TextureHost.
-   * Only the CompositableClient should be allowed to set or clear the ID.
-   * Zero is always an invalid ID.
-   * For a given compositableClient, there can never be more than one texture
-   * client with the same non-zero ID.
-   * Texture clients from different compositables may have the same ID.
+   * TextureChild is an implementation detail of TextureHost that is not
+   * exposed to the rest of the code base. CreateIPDLActor and DestroyIPDLActor
+   * are for use with the maging IPDL protocols only (so that they can
+   * implement AllocPextureChild and DeallocPTextureChild).
    */
-  void SetID(uint64_t aID)
-  {
-    MOZ_ASSERT(mID == 0 && aID != 0);
-    mID = aID;
-    mShared = true;
-  }
-  void ClearID()
-  {
-    MOZ_ASSERT(mID != 0);
-    mID = 0;
-  }
-
-  uint64_t GetID() const { return mID; }
+  static PTextureChild* CreateIPDLActor();
+  static bool DestroyIPDLActor(PTextureChild* actor);
 
   virtual bool IsAllocated() const = 0;
 
   virtual bool ToSurfaceDescriptor(SurfaceDescriptor& aDescriptor) = 0;
 
   virtual gfx::IntSize GetSize() const = 0;
 
   /**
@@ -244,31 +234,60 @@ public:
   bool IsValid() const { return mValid; }
 
   /**
    * An invalid TextureClient cannot provide access to its shared data
    * anymore. This usually means it will soon be destroyed.
    */
   void MarkInvalid() { mValid = false; }
 
-  // If a texture client holds a reference to shmem, it should override this
-  // method to forget about the shmem _without_ releasing it.
-  virtual void OnActorDestroy() {}
+  /**
+   * Create and init the TextureChild/Parent IPDL actor pair.
+   *
+   * Should be called only once per TextureClient.
+   */
+  bool InitIPDLActor(CompositableForwarder* aForwarder);
+
+  /**
+   * Return a pointer to the IPDLActor.
+   *
+   * This is to be used with IPDL messages only. Do not store the returned
+   * pointer.
+   */
+  PTextureChild* GetIPDLActor();
+
+  /**
+   * TODO[nical] doc!
+   */
+  void ForceRemove();
+
+private:
+  /**
+   * Called once, just before the destructor.
+   *
+   * Here goes the shut-down code that uses virtual methods.
+   * Must only be called by Release().
+   */
+  void Finalize();
+
+  friend class AtomicRefCountedWithFinalize<TextureClient>;
 
 protected:
   void AddFlags(TextureFlags  aFlags)
   {
     MOZ_ASSERT(!IsSharedWithCompositor());
     mFlags |= aFlags;
   }
 
-  uint64_t mID;
+  TextureChild* mActor;
   TextureFlags mFlags;
   bool mShared;
   bool mValid;
+
+  friend class TextureChild;
 };
 
 /**
  * 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
@@ -356,21 +375,16 @@ public:
   virtual bool IsAllocated() const MOZ_OVERRIDE { return mAllocated; }
 
   virtual TextureClientData* DropTextureData() MOZ_OVERRIDE;
 
   ISurfaceAllocator* GetAllocator() const;
 
   ipc::Shmem& GetShmem() { return mShmem; }
 
-  virtual void OnActorDestroy() MOZ_OVERRIDE
-  {
-    mShmem = ipc::Shmem();
-  }
-
 protected:
   ipc::Shmem mShmem;
   RefPtr<ISurfaceAllocator> mAllocator;
   bool mAllocated;
 };
 
 /**
  * TextureClient that wraps raw memory.
@@ -537,18 +551,16 @@ public:
 
   AccessMode GetAccessMode() const
   {
     return mAccessMode;
   }
 
   virtual gfxContentType GetContentType() = 0;
 
-  void OnActorDestroy();
-
 protected:
   DeprecatedTextureClient(CompositableForwarder* aForwarder,
                 const TextureInfo& aTextureInfo);
 
   CompositableForwarder* mForwarder;
   // So far all DeprecatedTextureClients use a SurfaceDescriptor, so it makes sense to
   // keep the reference here.
   SurfaceDescriptor mDescriptor;
--- a/gfx/layers/client/TiledContentClient.h
+++ b/gfx/layers/client/TiledContentClient.h
@@ -247,24 +247,16 @@ public:
                          LayerManager::DrawThebesLayerCallback aCallback,
                          void* aCallbackData);
 
   SurfaceDescriptorTiles GetSurfaceDescriptorTiles();
 
   static BasicTiledLayerBuffer OpenDescriptor(ISurfaceAllocator* aAllocator,
                                               const SurfaceDescriptorTiles& aDescriptor);
 
-  void OnActorDestroy()
-  {
-    for (size_t i = 0; i < mRetainedTiles.Length(); i++) {
-      if (mRetainedTiles[i].IsPlaceholderTile()) continue;
-      mRetainedTiles[i].mDeprecatedTextureClient->OnActorDestroy();
-    }
-  }
-
 protected:
   BasicTiledLayerTile ValidateTile(BasicTiledLayerTile aTile,
                                    const nsIntPoint& aTileRect,
                                    const nsIntRegion& dirtyRect);
 
   // If this returns true, we perform the paint operation into a single large
   // buffer and copy it out to the tiles instead of calling PaintThebes() on
   // each tile individually. Somewhat surprisingly, this turns out to be faster
@@ -344,22 +336,16 @@ public:
   }
 
   enum TiledBufferType {
     TILED_BUFFER,
     LOW_PRECISION_TILED_BUFFER
   };
   void LockCopyAndWrite(TiledBufferType aType);
 
-  virtual void OnActorDestroy() MOZ_OVERRIDE
-  {
-    mTiledBuffer.OnActorDestroy();
-    mLowPrecisionTiledBuffer.OnActorDestroy();
-  }
-
 private:
   BasicTiledLayerBuffer mTiledBuffer;
   BasicTiledLayerBuffer mLowPrecisionTiledBuffer;
 };
 
 }
 }
 
--- a/gfx/layers/composite/CompositableHost.cpp
+++ b/gfx/layers/composite/CompositableHost.cpp
@@ -31,92 +31,32 @@ CompositableHost::CompositableHost(const
   , mKeepAttached(false)
 {
   MOZ_COUNT_CTOR(CompositableHost);
 }
 
 CompositableHost::~CompositableHost()
 {
   MOZ_COUNT_DTOR(CompositableHost);
-
-  RefPtr<TextureHost> it = mFirstTexture;
-  while (it) {
-    if (!(it->GetFlags() & TEXTURE_DEALLOCATE_CLIENT)) {
-      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);
-  aTexture->SetCompositableBackendSpecificData(GetCompositableBackendSpecificData());
 }
 
 void
-CompositableHost::RemoveTextureHost(TextureHost* aTexture)
+CompositableHost::UseTextureHost(TextureHost* aTexture)
 {
-  uint64_t textureID = aTexture->GetID();
-  if (mFirstTexture && mFirstTexture->GetID() == textureID) {
-    mFirstTexture = mFirstTexture->GetNextSibling();
-    aTexture->SetNextSibling(nullptr);
-  }
-  RefPtr<TextureHost> it = mFirstTexture;
-  while (it) {
-    if (it->GetNextSibling() &&
-        it->GetNextSibling()->GetID() == textureID) {
-      it->SetNextSibling(it->GetNextSibling()->GetNextSibling());
-      aTexture->SetNextSibling(nullptr);
-    }
-    it = it->GetNextSibling();
-  }
-  if (!mFirstTexture && mBackendData) {
-    mBackendData->ClearData();
+  if (!aTexture) {
+    return;
   }
-}
-
-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::OnActorDestroy()
-{
-  TextureHost* it = mFirstTexture;
-  while (it) {
-    it->OnActorDestroy();
-    it = it->GetNextSibling();
-  }
+  aTexture->SetCompositor(GetCompositor());
+  aTexture->SetCompositableBackendSpecificData(GetCompositableBackendSpecificData());
 }
 
 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;
@@ -259,23 +199,16 @@ CompositableHost::DumpTextureHost(FILE* 
   surf->DumpAsDataURL(aFile ? aFile : stderr);
 }
 #endif
 
 void
 CompositableParent::ActorDestroy(ActorDestroyReason why)
 {
   if (mHost) {
-    // XXX: sadness warning. We should be able to do this whenever we get ActorDestroy,
-    // not just for abnormal shutdowns (which is the only case we _need_ to - so that
-    // we don't double release our shmems). But, for some reason, that causes a
-    // crash, we don't know why. (Bug 925773).
-    if (why == AbnormalShutdown) {
-      mHost->OnActorDestroy();
-    }
     mHost->Detach(nullptr, CompositableHost::FORCE_DETACH);
   }
 }
 
 CompositableParent::CompositableParent(CompositableParentManager* aMgr,
                                        const TextureInfo& aTextureInfo,
                                        uint64_t aID)
 : mManager(aMgr)
--- a/gfx/layers/composite/CompositableHost.h
+++ b/gfx/layers/composite/CompositableHost.h
@@ -103,22 +103,16 @@ public:
     return mBackendData;
   }
 
   virtual void SetCompositableBackendSpecificData(CompositableBackendSpecificData* aBackendData)
   {
     mBackendData = aBackendData;
   }
 
-  /**
-   * Our IPDL actor is being destroyed, get rid of any shmem resources now and
-   * don't worry about compositing anymore.
-   */
-  virtual void OnActorDestroy();
-
   // 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::Filter& aFilter,
@@ -289,33 +283,23 @@ public:
   static void DumpDeprecatedTextureHost(FILE* aFile, DeprecatedTextureHost* aTexture);
   static void DumpTextureHost(FILE* aFile, TextureHost* aTexture);
 
   virtual TemporaryRef<gfx::DataSourceSurface> GetAsSurface() { return nullptr; }
 #endif
 
   virtual void PrintInfo(nsACString& aTo, const char* aPrefix) { }
 
-  void AddTextureHost(TextureHost* aTexture);
-  virtual void UseTextureHost(TextureHost* aTexture) {}
-  // If a texture host is flagged for deferred removal, the compositable will
-  // get an option to run any cleanup code early, that is when it would have
-  // been run if the texture host was not marked deferred.
-  // If the compositable does not cleanup the texture host now, it is the
-  // compositable's responsibility to cleanup the texture host before the
-  // texture host dies.
-  virtual void RemoveTextureHost(TextureHost* aTexture);
-  TextureHost* GetTextureHost(uint64_t aTextureID);
+  virtual void UseTextureHost(TextureHost* aTexture);
 
 protected:
   TextureInfo mTextureInfo;
   Compositor* mCompositor;
   Layer* mLayer;
   RefPtr<CompositableBackendSpecificData> mBackendData;
-  RefPtr<TextureHost> mFirstTexture;
   bool mAttached;
   bool mKeepAttached;
 };
 
 class CompositableParentManager;
 
 /**
  * IPDL actor used by CompositableHost to match with its corresponding
--- a/gfx/layers/composite/ContentHost.cpp
+++ b/gfx/layers/composite/ContentHost.cpp
@@ -27,70 +27,24 @@ namespace layers {
 ContentHostBase::ContentHostBase(const TextureInfo& aTextureInfo)
   : ContentHost(aTextureInfo)
   , mPaintWillResample(false)
   , mInitialised(false)
 {}
 
 ContentHostBase::~ContentHostBase()
 {
-  DestroyTextureHost();
-  DestroyTextureHostOnWhite();
 }
 
 TextureHost*
 ContentHostBase::GetAsTextureHost()
 {
   return mTextureHost;
 }
 
-void
-ContentHostBase::DestroyTextureHost()
-{
-  // The third clause in the if statement checks that we are in fact done with
-  // this texture. We don't want to prematurely deallocate a texture we might
-  // use again or double deallocate. Deallocation will happen in
-  // RemoveTextureHost.
-  // Note that GetTextureHost is linear in the number of texture hosts, but as
-  // long as that number is small (I expect a maximum of 6 for now) then it
-  // should be ok.
-  if (mTextureHost &&
-      mTextureHost->GetFlags() & TEXTURE_DEALLOCATE_DEFERRED &&
-      !GetTextureHost(mTextureHost->GetID())) {
-    MOZ_ASSERT(!(mTextureHost->GetFlags() & TEXTURE_DEALLOCATE_CLIENT));
-    mTextureHost->DeallocateSharedData();
-  }
-  mTextureHost = nullptr;
-}
-
-void
-ContentHostBase::DestroyTextureHostOnWhite()
-{
-  if (mTextureHostOnWhite &&
-      mTextureHostOnWhite->GetFlags() & TEXTURE_DEALLOCATE_DEFERRED &&
-      !GetTextureHost(mTextureHostOnWhite->GetID())) {
-    MOZ_ASSERT(!(mTextureHostOnWhite->GetFlags() & TEXTURE_DEALLOCATE_CLIENT));
-    mTextureHostOnWhite->DeallocateSharedData();
-  }
-  mTextureHostOnWhite = nullptr;
-}
-
-void
-ContentHostBase::RemoveTextureHost(TextureHost* aTexture)
-{
-  if ((aTexture->GetFlags() & TEXTURE_DEALLOCATE_DEFERRED) &&
-      !(mTextureHost && mTextureHost == aTexture) &&
-      !(mTextureHostOnWhite && mTextureHostOnWhite == aTexture)) {
-    MOZ_ASSERT(!(aTexture->GetFlags() & TEXTURE_DEALLOCATE_CLIENT));
-    aTexture->DeallocateSharedData();
-  }
-
-  CompositableHost::RemoveTextureHost(aTexture);
-}
-
 class MOZ_STACK_CLASS AutoLockTextureHost
 {
 public:
   AutoLockTextureHost(TextureHost* aHost)
     : mHost(aHost)
   {
     mLockSuccess = mHost ? mHost->Lock() : true;
   }
@@ -281,20 +235,20 @@ ContentHostBase::Composite(EffectChain& 
   GetCompositor()->DrawDiagnostics(diagnostics, *aVisibleRegion, aClipRect, aTransform);
 }
 
 
 void
 ContentHostBase::UseTextureHost(TextureHost* aTexture)
 {
   if (aTexture->GetFlags() & TEXTURE_ON_WHITE) {
-    DestroyTextureHost();
+    mTextureHost = nullptr;
     mTextureHostOnWhite = aTexture;
   } else {
-    DestroyTextureHostOnWhite();
+    mTextureHostOnWhite = nullptr;
     mTextureHost = aTexture;
   }
 }
 
 void
 ContentHostBase::SetCompositor(Compositor* aCompositor)
 {
   CompositableHost::SetCompositor(aCompositor);
@@ -330,28 +284,16 @@ ContentHostBase::Dump(FILE* aFile,
     fprintf(aFile, "<li> <a href=");
     DumpTextureHost(aFile, mTextureHostOnWhite);
     fprintf(aFile, "> Front buffer on white </a> </li> ");
   }
   fprintf(aFile, "</ul>");
 }
 #endif
 
-void
-ContentHostBase::OnActorDestroy()
-{
-  if (mTextureHost) {
-    mTextureHost->OnActorDestroy();
-  }
-  if (mTextureHostOnWhite) {
-    mTextureHostOnWhite->OnActorDestroy();
-  }
-  CompositableHost::OnActorDestroy();
-}
-
 DeprecatedContentHostBase::DeprecatedContentHostBase(const TextureInfo& aTextureInfo)
   : ContentHost(aTextureInfo)
   , mPaintWillResample(false)
   , mInitialised(false)
 {}
 
 DeprecatedContentHostBase::~DeprecatedContentHostBase()
 {}
@@ -369,33 +311,16 @@ DeprecatedContentHostBase::DestroyFrontH
              "We won't be able to destroy our SurfaceDescriptor");
   MOZ_ASSERT(!mDeprecatedTextureHostOnWhite || mDeprecatedTextureHostOnWhite->GetDeAllocator(),
              "We won't be able to destroy our SurfaceDescriptor");
   mDeprecatedTextureHost = nullptr;
   mDeprecatedTextureHostOnWhite = nullptr;
 }
 
 void
-DeprecatedContentHostBase::OnActorDestroy()
-{
-  if (mDeprecatedTextureHost) {
-    mDeprecatedTextureHost->OnActorDestroy();
-  }
-  if (mDeprecatedTextureHostOnWhite) {
-    mDeprecatedTextureHostOnWhite->OnActorDestroy();
-  }
-  if (mNewFrontHost) {
-    mNewFrontHost->OnActorDestroy();
-  }
-  if (mNewFrontHostOnWhite) {
-    mNewFrontHostOnWhite->OnActorDestroy();
-  }
-}
-
-void
 DeprecatedContentHostBase::Composite(EffectChain& aEffectChain,
                            float aOpacity,
                            const gfx::Matrix4x4& aTransform,
                            const Filter& aFilter,
                            const Rect& aClipRect,
                            const nsIntRegion* aVisibleRegion,
                            TiledLayerProperties* aLayerProperties)
 {
@@ -844,39 +769,16 @@ DeprecatedContentHostDoubleBuffered::Des
                "We won't be able to destroy our SurfaceDescriptor");
     mBackHostOnWhite = nullptr;
   }
 
   // don't touch mDeprecatedTextureHost, we might need it for compositing
 }
 
 void
-DeprecatedContentHostDoubleBuffered::OnActorDestroy()
-{
-  if (mDeprecatedTextureHost) {
-    mDeprecatedTextureHost->OnActorDestroy();
-  }
-  if (mDeprecatedTextureHostOnWhite) {
-    mDeprecatedTextureHostOnWhite->OnActorDestroy();
-  }
-  if (mNewFrontHost) {
-    mNewFrontHost->OnActorDestroy();
-  }
-  if (mNewFrontHostOnWhite) {
-    mNewFrontHostOnWhite->OnActorDestroy();
-  }
-  if (mBackHost) {
-    mBackHost->OnActorDestroy();
-  }
-  if (mBackHostOnWhite) {
-    mBackHostOnWhite->OnActorDestroy();
-  }
-}
-
-void
 DeprecatedContentHostDoubleBuffered::UpdateThebes(const ThebesBufferData& aData,
                                         const nsIntRegion& aUpdated,
                                         const nsIntRegion& aOldValidRegionBack,
                                         nsIntRegion* aUpdatedRegionBack)
 {
   if (!mDeprecatedTextureHost && !mNewFrontHost) {
     mInitialised = false;
 
--- a/gfx/layers/composite/ContentHost.h
+++ b/gfx/layers/composite/ContentHost.h
@@ -112,34 +112,26 @@ public:
 #endif
 
   virtual void PrintInfo(nsACString& aTo, const char* aPrefix) MOZ_OVERRIDE;
 
   virtual TextureHost* GetAsTextureHost() MOZ_OVERRIDE;
 
   virtual void UseTextureHost(TextureHost* aTexture) MOZ_OVERRIDE;
 
-  virtual void RemoveTextureHost(TextureHost* aTexture) MOZ_OVERRIDE;
-
   virtual void SetPaintWillResample(bool aResample) { mPaintWillResample = aResample; }
 
-  virtual void OnActorDestroy() MOZ_OVERRIDE;
-
 protected:
   virtual nsIntPoint GetOriginOffset()
   {
     return mBufferRect.TopLeft() - mBufferRotation;
   }
 
   bool PaintWillResample() { return mPaintWillResample; }
 
-  // These must be called before forgetting mTextureHost or mTextureHostOnWhite
-  void DestroyTextureHost();
-  void DestroyTextureHostOnWhite();
-
   nsIntRect mBufferRect;
   nsIntPoint mBufferRotation;
   RefPtr<TextureHost> mTextureHost;
   RefPtr<TextureHost> mTextureHostOnWhite;
   bool mPaintWillResample;
   bool mInitialised;
 };
 class DeprecatedContentHostBase : public ContentHost
@@ -180,18 +172,16 @@ public:
   virtual DeprecatedTextureHost* GetDeprecatedTextureHost() MOZ_OVERRIDE;
 
   virtual void SetPaintWillResample(bool aResample) { mPaintWillResample = aResample; }
   // The client has destroyed its texture clients and we should destroy our
   // texture hosts and SurfaceDescriptors. Note that we don't immediately
   // destroy our front buffer so that we can continue to composite.
   virtual void DestroyTextures() = 0;
 
-  virtual void OnActorDestroy() MOZ_OVERRIDE;
-
 protected:
   virtual nsIntPoint GetOriginOffset()
   {
     return mBufferRect.TopLeft() - mBufferRotation;
   }
 
   bool PaintWillResample() { return mPaintWillResample; }
 
@@ -254,18 +244,16 @@ public:
                             nsIntRegion* aUpdatedRegionBack);
 
   virtual void EnsureDeprecatedTextureHost(TextureIdentifier aTextureId,
                                  const SurfaceDescriptor& aSurface,
                                  ISurfaceAllocator* aAllocator,
                                  const TextureInfo& aTextureInfo) MOZ_OVERRIDE;
   virtual void DestroyTextures() MOZ_OVERRIDE;
 
-  virtual void OnActorDestroy() MOZ_OVERRIDE;
-
 #ifdef MOZ_DUMP_PAINTING
   virtual void Dump(FILE* aFile=nullptr,
                     const char* aPrefix="",
                     bool aDumpHtml=false) MOZ_OVERRIDE;
 #endif
 
   virtual void PrintInfo(nsACString& aTo, const char* aPrefix);
 protected:
--- a/gfx/layers/composite/ImageHost.cpp
+++ b/gfx/layers/composite/ImageHost.cpp
@@ -33,28 +33,26 @@ ImageHost::ImageHost(const TextureInfo& 
   , mHasPictureRect(false)
 {}
 
 ImageHost::~ImageHost() {}
 
 void
 ImageHost::UseTextureHost(TextureHost* aTexture)
 {
+  if (mFrontBuffer) {
+    // XXX - When we implement sharing textures between several compositables
+    // we will need to not remove the compositor if there is another compositable
+    // using the texture.
+    mFrontBuffer->SetCompositor(nullptr);
+  }
+  CompositableHost::UseTextureHost(aTexture);
   mFrontBuffer = aTexture;
 }
 
-void
-ImageHost::RemoveTextureHost(TextureHost* aTexture)
-{
-  CompositableHost::RemoveTextureHost(aTexture);
-  if (mFrontBuffer && mFrontBuffer->GetID() == aTexture->GetID()) {
-    mFrontBuffer = nullptr;
-  }
-}
-
 TextureHost*
 ImageHost::GetAsTextureHost()
 {
   return mFrontBuffer;
 }
 
 void
 ImageHost::Composite(EffectChain& aEffectChain,
@@ -69,16 +67,20 @@ ImageHost::Composite(EffectChain& aEffec
     // 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;
   }
+
+  // Make sure the front buffer has a compositor
+  mFrontBuffer->SetCompositor(GetCompositor());
+
   if (!mFrontBuffer->Lock()) {
     NS_WARNING("failed to lock front buffer");
     return;
   }
   RefPtr<NewTextureSource> source = mFrontBuffer->GetTextureSources();
   if (!source) {
     return;
   }
@@ -150,16 +152,25 @@ ImageHost::Composite(EffectChain& aEffec
     GetCompositor()->DrawDiagnostics(DIAGNOSTIC_IMAGE,
                                      rect, aClipRect,
                                      aTransform);
   }
   mFrontBuffer->Unlock();
 }
 
 void
+ImageHost::SetCompositor(Compositor* aCompositor)
+{
+  if (mFrontBuffer && mCompositor != aCompositor) {
+    mFrontBuffer->SetCompositor(aCompositor);
+  }
+  CompositableHost::SetCompositor(aCompositor);
+}
+
+void
 ImageHost::PrintInfo(nsACString& aTo, const char* aPrefix)
 {
   aTo += aPrefix;
   aTo += nsPrintfCString("ImageHost (0x%p)", this);
 
   AppendToString(aTo, mPictureRect, " [picture-rect=", "]");
 
   if (mFrontBuffer) {
--- a/gfx/layers/composite/ImageHost.h
+++ b/gfx/layers/composite/ImageHost.h
@@ -50,35 +50,28 @@ public:
                          const gfx::Matrix4x4& aTransform,
                          const gfx::Filter& aFilter,
                          const gfx::Rect& aClipRect,
                          const nsIntRegion* aVisibleRegion = nullptr,
                          TiledLayerProperties* aLayerProperties = nullptr) MOZ_OVERRIDE;
 
   virtual void UseTextureHost(TextureHost* aTexture) MOZ_OVERRIDE;
 
-  virtual void RemoveTextureHost(TextureHost* aTexture) MOZ_OVERRIDE;
+  virtual TextureHost* GetAsTextureHost() MOZ_OVERRIDE;
 
-  virtual TextureHost* GetAsTextureHost() MOZ_OVERRIDE;
+  virtual void SetCompositor(Compositor* aCompositor) MOZ_OVERRIDE;
 
   virtual void SetPictureRect(const nsIntRect& aPictureRect) MOZ_OVERRIDE
   {
     mPictureRect = aPictureRect;
     mHasPictureRect = true;
   }
 
   virtual LayerRenderState GetRenderState() MOZ_OVERRIDE;
 
-  virtual void OnActorDestroy() MOZ_OVERRIDE
-  {
-    if (mFrontBuffer) {
-      mFrontBuffer->OnActorDestroy();
-    }
-  }
-
   virtual void PrintInfo(nsACString& aTo, const char* aPrefix);
 
 #ifdef MOZ_DUMP_PAINTING
   virtual void Dump(FILE* aFile=NULL,
                     const char* aPrefix="",
                     bool aDumpHtml=false) MOZ_OVERRIDE;
 
   virtual TemporaryRef<gfx::DataSourceSurface> GetAsSurface() MOZ_OVERRIDE;
@@ -129,23 +122,16 @@ public:
     mPictureRect = aPictureRect;
     mHasPictureRect = true;
   }
 
   virtual LayerRenderState GetRenderState() MOZ_OVERRIDE;
 
   virtual void SetCompositor(Compositor* aCompositor) MOZ_OVERRIDE;
 
-  virtual void OnActorDestroy() MOZ_OVERRIDE
-  {
-    if (mDeprecatedTextureHost) {
-      mDeprecatedTextureHost->OnActorDestroy();
-    }
-  }
-
   virtual void PrintInfo(nsACString& aTo, const char* aPrefix);
 
 #ifdef MOZ_DUMP_PAINTING
   virtual void Dump(FILE* aFile=nullptr,
                     const char* aPrefix="",
                     bool aDumpHtml=false) MOZ_OVERRIDE;
 
   virtual TemporaryRef<gfx::DataSourceSurface> GetAsSurface() MOZ_OVERRIDE;
--- a/gfx/layers/composite/TextureHost.cpp
+++ b/gfx/layers/composite/TextureHost.cpp
@@ -13,22 +13,78 @@
 #include "mozilla/layers/Compositor.h"  // for Compositor
 #include "mozilla/layers/ISurfaceAllocator.h"  // for ISurfaceAllocator
 #include "mozilla/layers/ImageDataSerializer.h"
 #include "mozilla/layers/LayersSurfaces.h"  // for SurfaceDescriptor, etc
 #include "mozilla/layers/YCbCrImageDataSerializer.h"
 #include "nsAString.h"
 #include "nsAutoPtr.h"                  // for nsRefPtr
 #include "nsPrintfCString.h"            // for nsPrintfCString
+#include "mozilla/layers/PTextureParent.h"
 
 struct nsIntPoint;
 
 namespace mozilla {
 namespace layers {
 
+/**
+ * TextureParent is the host-side IPDL glue between TextureClient and TextureHost.
+ * It is an IPDL actor just like LayerParent, CompositableParent, etc.
+ */
+class TextureParent : public PTextureParent
+{
+public:
+  TextureParent(ISurfaceAllocator* aAllocator);
+
+  ~TextureParent();
+
+  bool RecvInit(const SurfaceDescriptor& aSharedData,
+                const TextureFlags& aFlags) MOZ_OVERRIDE;
+
+  virtual bool RecvRemoveTexture() MOZ_OVERRIDE;
+
+  virtual bool RecvRemoveTextureSync() MOZ_OVERRIDE;
+
+  TextureHost* GetTextureHost() { return mTextureHost; }
+
+  void ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE;
+
+  ISurfaceAllocator* mAllocator;
+  RefPtr<TextureHost> mTextureHost;
+};
+
+// static
+PTextureParent*
+TextureHost::CreateIPDLActor(ISurfaceAllocator* aAllocator)
+{
+  return new TextureParent(aAllocator);
+}
+
+// static
+bool
+TextureHost::DestroyIPDLActor(PTextureParent* actor)
+{
+  delete actor;
+  return true;
+}
+
+// static
+bool
+TextureHost::SendDeleteIPDLActor(PTextureParent* actor)
+{
+  return PTextureParent::Send__delete__(actor);
+}
+
+// static
+TextureHost*
+TextureHost::AsTextureHost(PTextureParent* actor)
+{
+  return actor? static_cast<TextureParent*>(actor)->mTextureHost : nullptr;
+}
+
 // implemented in TextureOGL.cpp
 TemporaryRef<DeprecatedTextureHost> CreateDeprecatedTextureHostOGL(SurfaceDescriptorType aDescriptorType,
                                                            uint32_t aDeprecatedTextureHostFlags,
                                                            uint32_t aTextureFlags);
 // implemented in BasicCompositor.cpp
 TemporaryRef<DeprecatedTextureHost> CreateBasicDeprecatedTextureHost(SurfaceDescriptorType aDescriptorType,
                                                              uint32_t aDeprecatedTextureHostFlags,
                                                              uint32_t aTextureFlags);
@@ -76,78 +132,72 @@ DeprecatedTextureHost::CreateDeprecatedT
                                           aDeprecatedTextureHostFlags,
                                           aTextureFlags);
     default:
       MOZ_CRASH("Couldn't create texture host");
   }
 }
 
 // implemented in TextureHostOGL.cpp
-TemporaryRef<TextureHost> CreateTextureHostOGL(uint64_t aID,
-                                               const SurfaceDescriptor& aDesc,
+TemporaryRef<TextureHost> CreateTextureHostOGL(const SurfaceDescriptor& aDesc,
                                                ISurfaceAllocator* aDeallocator,
                                                TextureFlags aFlags);
 
 // implemented in TextureHostBasic.cpp
-TemporaryRef<TextureHost> CreateTextureHostBasic(uint64_t aID,
-                                               const SurfaceDescriptor& aDesc,
-                                               ISurfaceAllocator* aDeallocator,
-                                               TextureFlags aFlags);
+TemporaryRef<TextureHost> CreateTextureHostBasic(const SurfaceDescriptor& aDesc,
+                                                 ISurfaceAllocator* aDeallocator,
+                                                 TextureFlags aFlags);
 
 // static
 TemporaryRef<TextureHost>
-TextureHost::Create(uint64_t aID,
-                    const SurfaceDescriptor& aDesc,
+TextureHost::Create(const SurfaceDescriptor& aDesc,
                     ISurfaceAllocator* aDeallocator,
                     TextureFlags aFlags)
 {
   switch (Compositor::GetBackend()) {
     case LAYERS_OPENGL:
-      return CreateTextureHostOGL(aID, aDesc, aDeallocator, aFlags);
+      return CreateTextureHostOGL(aDesc, aDeallocator, aFlags);
     case LAYERS_BASIC:
-      return CreateTextureHostBasic(aID, aDesc, aDeallocator, aFlags);
+      return CreateTextureHostBasic(aDesc, aDeallocator, aFlags);
 #ifdef MOZ_WIDGET_GONK
     case LAYERS_NONE:
       // Power on video reqests to allocate TextureHost,
       // when Compositor is still not present. This is a very hacky workaround.
       // See Bug 944420.
-      return CreateTextureHostOGL(aID, aDesc, aDeallocator, aFlags);
+      return CreateTextureHostOGL(aDesc, aDeallocator, aFlags);
 #endif
 #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,
+CreateBackendIndependentTextureHost(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(),
+      result = new ShmemTextureHost(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()),
+      result = new MemoryTextureHost(reinterpret_cast<uint8_t*>(descriptor.data()),
                                      descriptor.format(),
                                      aFlags);
       break;
     }
     default: {
       NS_WARNING("No backend independent TextureHost for this descriptor type");
     }
   }
@@ -156,27 +206,33 @@ CreateBackendIndependentTextureHost(uint
 
 void
 TextureHost::SetCompositableBackendSpecificData(CompositableBackendSpecificData* aBackendData)
 {
     mCompositableBackendData = aBackendData;
 }
 
 
-TextureHost::TextureHost(uint64_t aID,
-                         TextureFlags aFlags)
-    : mID(aID)
-    , mNextTexture(nullptr)
-    , mFlags(aFlags)
+TextureHost::TextureHost(TextureFlags aFlags)
+    : mFlags(aFlags)
 {}
 
 TextureHost::~TextureHost()
 {
 }
 
+void TextureHost::Finalize()
+{
+  if (GetFlags() & TEXTURE_DEALLOCATE_DEFERRED) {
+    MOZ_ASSERT(!(GetFlags() & TEXTURE_DEALLOCATE_CLIENT));
+    DeallocateSharedData();
+    DeallocateDeviceData();
+  }
+}
+
 void
 TextureHost::PrintInfo(nsACString& aTo, const char* aPrefix)
 {
   aTo += aPrefix;
   aTo += nsPrintfCString("%s (0x%p)", Name(), this);
   AppendToString(aTo, GetSize(), " [size=", "]");
   AppendToString(aTo, GetFormat(), " [format=", "]");
   AppendToString(aTo, mFlags, " [flags=", "]");
@@ -248,17 +304,17 @@ DeprecatedTextureHost::SwapTextures(cons
   // register the TextureHost with the GrallocBufferActor.
   // The reason why this SetBuffer calls is needed here is that just above we
   // overwrote *mBuffer in place, so we need to tell the new mBuffer about this
   // TextureHost.
   SetBuffer(mBuffer, mDeAllocator);
 }
 
 void
-DeprecatedTextureHost::OnActorDestroy()
+DeprecatedTextureHost::OnShutdown()
 {
   if (ISurfaceAllocator::IsShmem(mBuffer)) {
     *mBuffer = SurfaceDescriptor();
     mBuffer = nullptr;
   }
 }
 
 void
@@ -274,20 +330,19 @@ DeprecatedTextureHost::PrintInfo(nsACStr
 void
 DeprecatedTextureHost::SetBuffer(SurfaceDescriptor* aBuffer, ISurfaceAllocator* aAllocator)
 {
   MOZ_ASSERT(!mBuffer || mBuffer == aBuffer, "Will leak the old mBuffer");
   mBuffer = aBuffer;
   mDeAllocator = aAllocator;
 }
 
-BufferTextureHost::BufferTextureHost(uint64_t aID,
-                                     gfx::SurfaceFormat aFormat,
+BufferTextureHost::BufferTextureHost(gfx::SurfaceFormat aFormat,
                                      TextureFlags aFlags)
-: TextureHost(aID, aFlags)
+: TextureHost(aFlags)
 , mCompositor(nullptr)
 , mFormat(aFormat)
 , mUpdateSerial(1)
 , mLocked(false)
 , mPartialUpdate(false)
 {}
 
 BufferTextureHost::~BufferTextureHost()
@@ -379,16 +434,29 @@ BufferTextureHost::MaybeUpload(nsIntRegi
   }
   mFirstSource->SetUpdateSerial(mUpdateSerial);
   return true;
 }
 
 bool
 BufferTextureHost::Upload(nsIntRegion *aRegion)
 {
+  if (!GetBuffer()) {
+    // We don't have a buffer; a possible cause is that the IPDL actor
+    // is already dead. This inevitably happens as IPDL actors can die
+    // at any time, so we want to silently return in this case.
+    return false;
+  }
+  if (!mCompositor) {
+    NS_WARNING("Tried to upload without a compositor. Skipping texture upload...");
+    // If we are in this situation it means we should have called SetCompositor
+    // earlier. It is conceivable that on certain rare conditions with async-video
+    // we may end up here for the first frame, but this should not happen repeatedly.
+    return false;
+  }
   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)) {
@@ -489,22 +557,21 @@ BufferTextureHost::GetAsSurface()
     if (!deserializer.IsValid()) {
       return nullptr;
     }
     result = deserializer.GetAsSurface();
   }
   return result.forget();
 }
 
-ShmemTextureHost::ShmemTextureHost(uint64_t aID,
-                                   const ipc::Shmem& aShmem,
+ShmemTextureHost::ShmemTextureHost(const ipc::Shmem& aShmem,
                                    gfx::SurfaceFormat aFormat,
                                    ISurfaceAllocator* aDeallocator,
                                    TextureFlags aFlags)
-: BufferTextureHost(aID, aFormat, aFlags)
+: BufferTextureHost(aFormat, aFlags)
 , mShmem(new ipc::Shmem(aShmem))
 , mDeallocator(aDeallocator)
 {
   MOZ_COUNT_CTOR(ShmemTextureHost);
 }
 
 ShmemTextureHost::~ShmemTextureHost()
 {
@@ -515,37 +582,46 @@ ShmemTextureHost::~ShmemTextureHost()
 
 void
 ShmemTextureHost::DeallocateSharedData()
 {
   if (mShmem) {
     MOZ_ASSERT(mDeallocator,
                "Shared memory would leak without a ISurfaceAllocator");
     mDeallocator->DeallocShmem(*mShmem);
+    delete mShmem;
     mShmem = nullptr;
   }
 }
 
 void
-ShmemTextureHost::OnActorDestroy()
+ShmemTextureHost::ForgetSharedData()
+{
+  if (mShmem) {
+    delete mShmem;
+    mShmem = nullptr;
+  }
+}
+
+void
+ShmemTextureHost::OnShutdown()
 {
   delete mShmem;
   mShmem = nullptr;
 }
 
 uint8_t* ShmemTextureHost::GetBuffer()
 {
   return mShmem ? mShmem->get<uint8_t>() : nullptr;
 }
 
-MemoryTextureHost::MemoryTextureHost(uint64_t aID,
-                                     uint8_t* aBuffer,
+MemoryTextureHost::MemoryTextureHost(uint8_t* aBuffer,
                                      gfx::SurfaceFormat aFormat,
                                      TextureFlags aFlags)
-: BufferTextureHost(aID, aFormat, aFlags)
+: BufferTextureHost(aFormat, aFlags)
 , mBuffer(aBuffer)
 {
   MOZ_COUNT_CTOR(MemoryTextureHost);
 }
 
 MemoryTextureHost::~MemoryTextureHost()
 {
   DeallocateDeviceData();
@@ -559,15 +635,87 @@ MemoryTextureHost::DeallocateSharedData(
 {
   if (mBuffer) {
     GfxMemoryImageReporter::WillFree(mBuffer);
   }
   delete[] mBuffer;
   mBuffer = nullptr;
 }
 
+void
+MemoryTextureHost::ForgetSharedData()
+{
+  mBuffer = nullptr;
+}
+
 uint8_t* MemoryTextureHost::GetBuffer()
 {
   return mBuffer;
 }
 
+TextureParent::TextureParent(ISurfaceAllocator* aAllocator)
+: mAllocator(aAllocator)
+{
+  MOZ_COUNT_CTOR(TextureParent);
+}
+
+TextureParent::~TextureParent()
+{
+  MOZ_COUNT_DTOR(TextureParent);
+  mTextureHost = nullptr;
+}
+
+bool
+TextureParent::RecvInit(const SurfaceDescriptor& aSharedData,
+                        const TextureFlags& aFlags)
+{
+  mTextureHost = TextureHost::Create(aSharedData,
+                                     mAllocator,
+                                     aFlags);
+  return !!mTextureHost;
+}
+
+bool
+TextureParent::RecvRemoveTexture()
+{
+  return PTextureParent::Send__delete__(this);
+}
+
+bool
+TextureParent::RecvRemoveTextureSync()
+{
+  // we don't need to send a reply in the synchronous case since the child side
+  // has the guarantee that this message has been handled synchronously.
+  return PTextureParent::Send__delete__(this);
+}
+
+void
+TextureParent::ActorDestroy(ActorDestroyReason why)
+{
+  if (!mTextureHost) {
+    return;
+  }
+
+  switch (why) {
+  case AncestorDeletion:
+    NS_WARNING("PTexture deleted after ancestor");
+    // fall-through to deletion path
+  case Deletion:
+    if (!(mTextureHost->GetFlags() & TEXTURE_DEALLOCATE_CLIENT) &&
+        !(mTextureHost->GetFlags() & TEXTURE_DEALLOCATE_DEFERRED)) {
+      mTextureHost->DeallocateSharedData();
+    }
+    break;
+
+  case NormalShutdown:
+  case AbnormalShutdown:
+    mTextureHost->OnShutdown();
+    break;
+
+  case FailedConstructor:
+    NS_RUNTIMEABORT("FailedConstructor isn't possible in PTexture");
+  }
+  mTextureHost->ForgetSharedData();
+  mTextureHost = nullptr;
+}
+
 } // namespace
 } // namespace
--- a/gfx/layers/composite/TextureHost.h
+++ b/gfx/layers/composite/TextureHost.h
@@ -18,16 +18,17 @@
 #include "mozilla/layers/CompositorTypes.h"  // for TextureFlags, etc
 #include "mozilla/layers/LayersTypes.h"  // for LayerRenderState, etc
 #include "mozilla/mozalloc.h"           // for operator delete
 #include "nsCOMPtr.h"                   // for already_AddRefed
 #include "nsDebug.h"                    // for NS_RUNTIMEABORT
 #include "nsRegion.h"                   // for nsIntRegion
 #include "nsTraceRefcnt.h"              // for MOZ_COUNT_CTOR, etc
 #include "nscore.h"                     // for nsACString
+#include "mozilla/layers/AtomicRefCountedWithFinalize.h"
 
 class gfxImageSurface;
 class gfxReusableSurfaceWrapper;
 struct nsIntPoint;
 struct nsIntSize;
 struct nsIntRect;
 
 namespace mozilla {
@@ -41,18 +42,19 @@ class Compositor;
 class CompositableHost;
 class CompositableBackendSpecificData;
 class SurfaceDescriptor;
 class ISurfaceAllocator;
 class TextureSourceOGL;
 class TextureSourceD3D9;
 class TextureSourceD3D11;
 class TextureSourceBasic;
+class DataTextureSource;
+class PTextureParent;
 class TextureParent;
-class DataTextureSource;
 
 /**
  * A view on a TextureHost where the texture is internally represented as tiles
  * (contrast with a tiled buffer, where each texture is a tile). For iteration by
  * the texture's buffer host.
  * This is only useful when the underlying surface is too big to fit in one
  * device texture, which forces us to split it in smaller parts.
  * Tiled Compositable is a different thing.
@@ -252,29 +254,38 @@ private:
  * 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>
+class TextureHost
+  : public AtomicRefCountedWithFinalize<TextureHost>
 {
+  /**
+   * Called once, just before the destructor.
+   *
+   * Here goes the shut-down code that uses virtual methods.
+   * Must only be called by Release().
+   */
+  void Finalize();
+
+  friend class AtomicRefCountedWithFinalize<TextureHost>;
+
 public:
-  TextureHost(uint64_t aID,
-              TextureFlags aFlags);
+  TextureHost(TextureFlags aFlags);
 
   virtual ~TextureHost();
 
   /**
    * Factory method.
    */
-  static TemporaryRef<TextureHost> Create(uint64_t aID,
-                                          const SurfaceDescriptor& aDesc,
+  static TemporaryRef<TextureHost> Create(const SurfaceDescriptor& aDesc,
                                           ISurfaceAllocator* aDeallocator,
                                           TextureFlags aFlags);
 
   /**
    * Lock the texture host for compositing.
    */
   virtual bool Lock() { return true; }
 
@@ -327,38 +338,26 @@ public:
 
   /**
    * Should be overridden 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.
+   * Should be overridden in order to force the TextureHost to drop all references
+   * to it's shared data.
    *
-   * 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.
+   * This is important to ensure the correctness of the deallocation protocol.
    */
-  uint64_t GetID() const { return mID; }
+  virtual void ForgetSharedData() {}
 
   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. See bug 882113.
    */
   virtual TemporaryRef<gfx::DataSourceSurface> GetAsSurface() = 0;
 
   /**
    * XXX - Flags should only be set at creation time, this will be removed.
    */
@@ -367,38 +366,57 @@ public:
   /**
    * XXX - Flags should only be set at creation time, this will be removed.
    */
   void AddFlag(TextureFlags aFlag) { mFlags |= aFlag; }
 
   TextureFlags GetFlags() { return mFlags; }
 
   /**
+   * Allocate and deallocate a TextureParent actor.
+   *
+   * TextureParent< is an implementation detail of TextureHost that is not
+   * exposed to the rest of the code base. CreateIPDLActor and DestroyIPDLActor
+   * are for use with the managing IPDL protocols only (so that they can
+   * implement AllocPTextureParent and DeallocPTextureParent).
+   */
+  static PTextureParent* CreateIPDLActor(ISurfaceAllocator* aAllocator);
+  static bool DestroyIPDLActor(PTextureParent* actor);
+
+  /**
+   * Destroy the TextureChild/Parent pair.
+   */
+  static bool SendDeleteIPDLActor(PTextureParent* actor);
+
+  /**
+   * Get the TextureHost corresponding to the actor passed in parameter.
+   */
+  static TextureHost* AsTextureHost(PTextureParent* actor);
+
+  /**
    * Specific to B2G's Composer2D
    * XXX - more doc here
    */
   virtual LayerRenderState GetRenderState()
   {
     // By default we return an empty render state, this should be overridden
     // by the TextureHost implementations that are used on B2G with Composer2D
     return LayerRenderState();
   }
 
   virtual void SetCompositableBackendSpecificData(CompositableBackendSpecificData* aBackendData);
 
   // If a texture host holds a reference to shmem, it should override this method
   // to forget about the shmem _without_ releasing it.
-  virtual void OnActorDestroy() {}
+  virtual void OnShutdown() {}
 
   virtual const char *Name() { return "TextureHost"; }
   virtual void PrintInfo(nsACString& aTo, const char* aPrefix);
 
 protected:
-  uint64_t mID;
-  RefPtr<TextureHost> mNextTexture;
   TextureFlags mFlags;
   RefPtr<CompositableBackendSpecificData> mCompositableBackendData;
 };
 
 /**
  * TextureHost that wraps a random access buffer such as a Shmem or some raw
  * memory.
  *
@@ -409,18 +427,17 @@ protected:
  *
  * 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,
+  BufferTextureHost(gfx::SurfaceFormat aFormat,
                     TextureFlags aFlags);
 
   ~BufferTextureHost();
 
   virtual uint8_t* GetBuffer() = 0;
 
   virtual void Updated(const nsIntRegion* aRegion = nullptr) MOZ_OVERRIDE;
 
@@ -465,55 +482,57 @@ protected:
 /**
  * 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 mozilla::ipc::Shmem& aShmem,
+  ShmemTextureHost(const mozilla::ipc::Shmem& aShmem,
                    gfx::SurfaceFormat aFormat,
                    ISurfaceAllocator* aDeallocator,
                    TextureFlags aFlags);
 
   ~ShmemTextureHost();
 
   virtual void DeallocateSharedData() MOZ_OVERRIDE;
 
+  virtual void ForgetSharedData() MOZ_OVERRIDE;
+
   virtual uint8_t* GetBuffer() MOZ_OVERRIDE;
 
   virtual const char *Name() MOZ_OVERRIDE { return "ShmemTextureHost"; }
 
-  virtual void OnActorDestroy() MOZ_OVERRIDE;
+  virtual void OnShutdown() MOZ_OVERRIDE;
 
 protected:
   mozilla::ipc::Shmem* mShmem;
   RefPtr<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,
+  MemoryTextureHost(uint8_t* aBuffer,
                     gfx::SurfaceFormat aFormat,
                     TextureFlags aFlags);
 
   ~MemoryTextureHost();
 
   virtual void DeallocateSharedData() MOZ_OVERRIDE;
 
+  virtual void ForgetSharedData() MOZ_OVERRIDE;
+
   virtual uint8_t* GetBuffer() MOZ_OVERRIDE;
 
   virtual const char *Name() MOZ_OVERRIDE { return "MemoryTextureHost"; }
 
 protected:
   uint8_t* mBuffer;
 };
 
@@ -706,17 +725,17 @@ public:
   // only made virtual to allow overriding in GrallocDeprecatedTextureHostOGL, for hacky fix in gecko 23 for bug 862324.
   // see bug 865908 about fixing this.
   virtual void SetBuffer(SurfaceDescriptor* aBuffer, ISurfaceAllocator* aAllocator);
 
   // used only for hacky fix in gecko 23 for bug 862324
   // see bug 865908 about fixing this.
   virtual void ForgetBuffer() {}
 
-  void OnActorDestroy();
+  void OnShutdown();
 
 protected:
   /**
    * Should be implemented by the backend-specific DeprecatedTextureHost classes
    *
    * It should not take a reference to aImage, unless it knows the data
    * to be thread-safe.
    */
@@ -809,17 +828,16 @@ private:
   gfx::IntPoint mOrigin;
 };
 
 /**
  * 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,
+CreateBackendIndependentTextureHost(const SurfaceDescriptor& aDesc,
                                     ISurfaceAllocator* aDeallocator,
                                     TextureFlags aFlags);
 
 }
 }
 
 #endif
--- a/gfx/layers/composite/TiledContentHost.h
+++ b/gfx/layers/composite/TiledContentHost.h
@@ -114,26 +114,16 @@ public:
   // by the sum of the resolutions of all parent layers' FrameMetrics.
   const CSSToScreenScale& GetFrameResolution() { return mFrameResolution; }
 
   void SetCompositor(Compositor* aCompositor)
   {
     mCompositor = aCompositor;
   }
 
-  void OnActorDestroy()
-  {
-    Iterator end = TilesEnd();
-    for (Iterator it = TilesBegin(); it != end; ++it) {
-      if (it->mDeprecatedTextureHost) {
-        it->mDeprecatedTextureHost->OnActorDestroy();
-      }
-    }
-  }
-
 protected:
   TiledTexture ValidateTile(TiledTexture aTile,
                             const nsIntPoint& aTileRect,
                             const nsIntRegion& dirtyRect);
 
   // do nothing, the desctructor in the texture host takes care of releasing resources
   void ReleaseTile(TiledTexture aTile) {}
 
@@ -244,22 +234,16 @@ public:
     mVideoMemoryTiledBuffer.SetCompositor(aCompositor);
     mLowPrecisionVideoMemoryTiledBuffer.SetCompositor(aCompositor);
   }
 
   virtual void Attach(Layer* aLayer,
                       Compositor* aCompositor,
                       AttachFlags aFlags = NO_FLAGS) MOZ_OVERRIDE;
 
-  virtual void OnActorDestroy() MOZ_OVERRIDE
-  {
-    mVideoMemoryTiledBuffer.OnActorDestroy();
-    mLowPrecisionVideoMemoryTiledBuffer.OnActorDestroy();
-  }
-
 #ifdef MOZ_DUMP_PAINTING
   virtual void Dump(FILE* aFile=nullptr,
                     const char* aPrefix="",
                     bool aDumpHtml=false) MOZ_OVERRIDE;
 #endif
 
   virtual void PrintInfo(nsACString& aTo, const char* aPrefix);
 
--- a/gfx/layers/ipc/CompositableForwarder.h
+++ b/gfx/layers/ipc/CompositableForwarder.h
@@ -24,16 +24,18 @@ namespace layers {
 class CompositableClient;
 class TextureFactoryIdentifier;
 class SurfaceDescriptor;
 class SurfaceDescriptorTiles;
 class ThebesBufferData;
 class DeprecatedTextureClient;
 class TextureClient;
 class BasicTiledLayerBuffer;
+class PTextureChild;
+class TextureClientData;
 
 /**
  * A transaction is a set of changes that happenned on the content side, that
  * should be sent to the compositor side.
  * CompositableForwarder is an interface to manage a transaction of
  * compositable objetcs.
  *
  * ShadowLayerForwarder is an example of a CompositableForwarder (that can
@@ -89,16 +91,24 @@ public:
    * that is TextureClient/Hosts.
    */
   virtual void DestroyThebesBuffer(CompositableClient* aCompositable) = 0;
 
   virtual void PaintedTiledLayerBuffer(CompositableClient* aCompositable,
                                        const SurfaceDescriptorTiles& aTiledDescriptor) = 0;
 
   /**
+   * Create an unitialized TextureChild.
+   *
+   * This does not trigger the the creation of a TextureHost on the compositor
+   * side (see PTexture::Init).
+   */
+  virtual PTextureChild* CreateEmptyTextureChild() = 0;
+
+  /**
    * Communicate to the compositor that the texture identified by aCompositable
    * and aTextureId has been updated to aImage.
    */
   virtual void UpdateTexture(CompositableClient* aCompositable,
                              TextureIdentifier aTextureId,
                              SurfaceDescriptor* aDescriptor) = 0;
 
   /**
@@ -145,35 +155,20 @@ public:
    * posted to the parent.  During the parent-side transaction, the
    * shadow is told to destroy its front buffer.  This can happen when
    * a new front/back buffer pair have been created because of a layer
    * resize, e.g.
    */
   virtual void DestroyedThebesBuffer(const SurfaceDescriptor& aBackBufferToDestroy) = 0;
 
   /**
-   * Tell the compositor side to create a TextureHost that corresponds to
-   * aClient.
+   * Tell the compositor side to delete the TextureHost corresponding to the
+   * TextureClient passed in parameter.
    */
-  virtual bool AddTexture(CompositableClient* aCompositable,
-                          TextureClient* aClient) = 0;
-
-  /**
-   * Tell the compositor side to delete the TextureHost corresponding to
-   * aTextureID.
-   * By default the shared Data is deallocated along with the TextureHost, but
-   * this behaviour can be overriden by the TextureFlags passed here.
-   * XXX - This is kind of bad, but for now we have to do this, because of some
-   * edge cases caused by the lifetime of the TextureHost being limited by the
-   * lifetime of the CompositableHost. We should be able to remove this flags
-   * parameter when we remove the lifetime constraint.
-   */
-  virtual void RemoveTexture(CompositableClient* aCompositable,
-                             uint64_t aTextureID,
-                             TextureFlags aFlags) = 0;
+  virtual void RemoveTexture(TextureClient* aTexture) = 0;
 
   /**
    * Tell the CompositableHost on the compositor side what texture to use for
    * the next composition.
    */
   virtual void UseTexture(CompositableClient* aCompositable,
                           TextureClient* aClient) = 0;
 
--- a/gfx/layers/ipc/CompositableTransactionParent.cpp
+++ b/gfx/layers/ipc/CompositableTransactionParent.cpp
@@ -217,100 +217,38 @@ CompositableParentManager::ReceiveCompos
       NS_ASSERTION(tileComposer, "compositable is not a tile composer");
 
       const SurfaceDescriptorTiles& tileDesc = op.tileLayerDescriptor();
       tileComposer->PaintedTiledLayerBuffer(this, tileDesc);
       break;
     }
     case CompositableOperation::TOpUseTexture: {
       const OpUseTexture& op = aEdit.get_OpUseTexture();
-      if (op.textureID() == 0) {
-        NS_WARNING("Invalid texture ID");
-        break;
-      }
       CompositableHost* compositable = AsCompositable(op);
-      RefPtr<TextureHost> tex = compositable->GetTextureHost(op.textureID());
+      RefPtr<TextureHost> tex = TextureHost::AsTextureHost(op.textureParent());
 
       MOZ_ASSERT(tex.get());
       compositable->UseTextureHost(tex);
 
       if (IsAsync()) {
         ScheduleComposition(op);
       }
       break;
     }
-    case CompositableOperation::TOpAddTexture: {
-      const OpAddTexture& op = aEdit.get_OpAddTexture();
-      if (op.textureID() == 0) {
-        NS_WARNING("Invalid texture ID");
-        break;
-      }
-      CompositableHost* compositable = AsCompositable(op);
-      RefPtr<TextureHost> tex = TextureHost::Create(op.textureID(),
-                                                    op.data(),
-                                                    this,
-                                                    op.textureFlags());
-      MOZ_ASSERT(tex.get());
-      tex->SetCompositor(compositable->GetCompositor());
-      // set CompositableBackendSpecificData
-      // on gonk, create EGLImage if possible.
-      // create EGLImage during buffer swap could reduce the graphic driver's task
-      // during rendering.
-      compositable->AddTextureHost(tex);
-      MOZ_ASSERT(compositable->GetTextureHost(op.textureID()) == tex.get());
-      break;
-    }
-    case CompositableOperation::TOpRemoveTexture: {
-      const OpRemoveTexture& op = aEdit.get_OpRemoveTexture();
-      if (op.textureID() == 0) {
-        NS_WARNING("Invalid texture ID");
-        break;
-      }
-      CompositableHost* compositable = AsCompositable(op);
-
-      RefPtr<TextureHost> texture = compositable->GetTextureHost(op.textureID());
-      MOZ_ASSERT(texture);
-
-      TextureFlags flags = texture->GetFlags();
-
-      if (!(flags & TEXTURE_DEALLOCATE_CLIENT) &&
-          !(flags & TEXTURE_DEALLOCATE_DEFERRED)) {
-        texture->DeallocateSharedData();
-      }
-
-      compositable->RemoveTextureHost(texture);
-
-      // if it is not the host that deallocates the shared data, then we need
-      // to notfy the client side to tell when it is safe to deallocate or
-      // reuse it.
-      if (flags & TEXTURE_DEALLOCATE_CLIENT) {
-        replyv.push_back(ReplyTextureRemoved(op.compositableParent(), nullptr,
-                                             op.textureID()));
-      }
-
-      break;
-    }
     case CompositableOperation::TOpUpdateTexture: {
       const OpUpdateTexture& op = aEdit.get_OpUpdateTexture();
-      if (op.textureID() == 0) {
-        NS_WARNING("Invalid texture ID");
-        break;
-      }
       CompositableHost* compositable = AsCompositable(op);
       MOZ_ASSERT(compositable);
-      RefPtr<TextureHost> texture = compositable->GetTextureHost(op.textureID());
+      RefPtr<TextureHost> texture = TextureHost::AsTextureHost(op.textureParent());
       MOZ_ASSERT(texture);
 
       texture->Updated(op.region().type() == MaybeRegion::TnsIntRegion
                        ? &op.region().get_nsIntRegion()
                        : nullptr); // no region means invalidate the entire surface
 
-
-      compositable->UseTextureHost(texture);
-
       break;
     }
 
     default: {
       MOZ_ASSERT(false, "bad type");
     }
   }
 
--- a/gfx/layers/ipc/ImageBridgeChild.cpp
+++ b/gfx/layers/ipc/ImageBridgeChild.cpp
@@ -31,16 +31,17 @@
 #include "mozilla/mozalloc.h"           // for operator new, etc
 #include "nsAutoPtr.h"                  // for nsRefPtr
 #include "nsISupportsImpl.h"            // for ImageContainer::AddRef, etc
 #include "nsTArray.h"                   // for nsAutoTArray, nsTArray, etc
 #include "nsTArrayForwardDeclare.h"     // for AutoInfallibleTArray
 #include "nsThreadUtils.h"              // for NS_IsMainThread
 #include "nsXULAppAPI.h"                // for XRE_GetIOMessageLoop
 #include "mozilla/StaticPtr.h"          // for StaticRefPtr
+#include "mozilla/layers/TextureClient.h"
 
 struct nsIntRect;
  
 using namespace base;
 using namespace mozilla::ipc;
 
 namespace mozilla {
 namespace ipc {
@@ -98,67 +99,33 @@ struct CompositableTransaction
 };
 
 struct AutoEndTransaction {
   AutoEndTransaction(CompositableTransaction* aTxn) : mTxn(aTxn) {}
   ~AutoEndTransaction() { mTxn->End(); }
   CompositableTransaction* mTxn;
 };
 
-bool
-ImageBridgeChild::AddTexture(CompositableClient* aCompositable,
-                             TextureClient* aTexture)
-{
-  SurfaceDescriptor descriptor;
-  if (!aTexture->ToSurfaceDescriptor(descriptor)) {
-    NS_WARNING("ImageBridge: Failed to serialize a TextureClient");
-    return false;
-  }
-  mTxn->AddEdit(OpAddTexture(nullptr, aCompositable->GetIPDLActor(),
-                             aTexture->GetID(),
-                             descriptor,
-                             aTexture->GetFlags()));
-  return true;
-}
-
-void
-ImageBridgeChild::RemoveTexture(CompositableClient* aCompositable,
-                                uint64_t aTexture,
-                                TextureFlags aFlags)
-{
-  if (aFlags & TEXTURE_DEALLOCATE_CLIENT) {
-    // if deallocation happens on the host side, we need the transaction
-    // to be synchronous.
-    mTxn->AddEdit(OpRemoveTexture(nullptr, aCompositable->GetIPDLActor(),
-                                  aTexture,
-                                  aFlags));
-  } else {
-    mTxn->AddNoSwapEdit(OpRemoveTexture(nullptr, aCompositable->GetIPDLActor(),
-                                        aTexture,
-                                        aFlags));
-  }
-}
-
 void
 ImageBridgeChild::UseTexture(CompositableClient* aCompositable,
                              TextureClient* aTexture)
 {
   mTxn->AddNoSwapEdit(OpUseTexture(nullptr, aCompositable->GetIPDLActor(),
-                                   aTexture->GetID()));
+                                   nullptr, aTexture->GetIPDLActor()));
 }
 
 void
 ImageBridgeChild::UpdatedTexture(CompositableClient* aCompositable,
                                  TextureClient* aTexture,
                                  nsIntRegion* aRegion)
 {
   MaybeRegion region = aRegion ? MaybeRegion(*aRegion)
                                : MaybeRegion(null_t());
   mTxn->AddNoSwapEdit(OpUpdateTexture(nullptr, aCompositable->GetIPDLActor(),
-                                      aTexture->GetID(),
+                                      nullptr, aTexture->GetIPDLActor(),
                                       region));
 }
 
 void
 ImageBridgeChild::UpdateTexture(CompositableClient* aCompositable,
                                 TextureIdentifier aTextureId,
                                 SurfaceDescriptor* aDescriptor)
 {
@@ -460,17 +427,16 @@ void ImageBridgeChild::FlushAllImagesNow
   MOZ_ASSERT(aClient);
   sImageBridgeChildSingleton->BeginTransaction();
   if (aContainer && !aExceptFront) {
     aContainer->ClearCurrentImage();
   }
   aClient->FlushAllImages(aExceptFront);
   aClient->OnTransaction();
   sImageBridgeChildSingleton->EndTransaction();
-  aClient->FlushTexturesToRemoveCallbacks();
 }
 
 void
 ImageBridgeChild::BeginTransaction()
 {
   MOZ_ASSERT(mTxn->Finished(), "uncommitted txn?");
   mTxn->Begin();
 }
@@ -518,28 +484,16 @@ ImageBridgeChild::EndTransaction()
           static_cast<CompositableChild*>(ots.compositableChild());
 
       MOZ_ASSERT(compositableChild);
 
       compositableChild->GetCompositableClient()
         ->SetDescriptorFromReply(ots.textureId(), ots.image());
       break;
     }
-    case EditReply::TReplyTextureRemoved: {
-      // We receive this reply when a Texture is removed and when it is not
-      // the responsibility of the compositor side to deallocate memory.
-      // This would be, for instance, the place to implement a mechanism to
-      // notify the B2G camera that the gralloc buffer is not used by the
-      // compositor anymore and that it can be recycled.
-      const ReplyTextureRemoved& rep = reply.get_ReplyTextureRemoved();
-      CompositableClient* compositable
-        = static_cast<CompositableChild*>(rep.compositableChild())->GetCompositableClient();
-      compositable->OnReplyTextureRemoved(rep.textureId());
-      break;
-    }
     default:
       NS_RUNTIMEABORT("not reached");
     }
   }
 }
 
 
 PImageBridgeChild*
@@ -935,10 +889,59 @@ ImageBridgeChild::AllocGrallocBuffer(con
                                        aUsage,
                                        aHandle);
 #else
   NS_RUNTIMEABORT("not implemented");
   return nullptr;
 #endif
 }
 
+PTextureChild*
+ImageBridgeChild::AllocPTextureChild()
+{
+  return TextureClient::CreateIPDLActor();
+}
+
+bool
+ImageBridgeChild::DeallocPTextureChild(PTextureChild* actor)
+{
+  return TextureClient::DestroyIPDLActor(actor);
+}
+
+PTextureChild*
+ImageBridgeChild::CreateEmptyTextureChild()
+{
+  return SendPTextureConstructor();
+}
+
+static void RemoveTextureSync(TextureClient* aTexture, ReentrantMonitor* aBarrier, bool* aDone)
+{
+  aTexture->ForceRemove();
+
+  ReentrantMonitorAutoEnter autoMon(*aBarrier);
+  *aDone = true;
+  aBarrier->NotifyAll();
+}
+
+void ImageBridgeChild::RemoveTexture(TextureClient* aTexture)
+{
+  if (InImageBridgeChildThread()) {
+    aTexture->ForceRemove();
+    return;
+  }
+
+  ReentrantMonitor barrier("RemoveTexture Lock");
+  ReentrantMonitorAutoEnter autoMon(barrier);
+  bool done = false;
+
+  sImageBridgeChildSingleton->GetMessageLoop()->PostTask(
+    FROM_HERE,
+    NewRunnableFunction(&RemoveTextureSync, aTexture, &barrier, &done));
+
+  // should stop the thread until the ImageClient has been created on
+  // the other thread
+  while (!done) {
+    barrier.Wait();
+  }
+}
+
 } // layers
 } // mozilla
--- a/gfx/layers/ipc/ImageBridgeChild.h
+++ b/gfx/layers/ipc/ImageBridgeChild.h
@@ -190,16 +190,22 @@ public:
 
   virtual PGrallocBufferChild*
   AllocPGrallocBufferChild(const gfxIntSize&, const uint32_t&, const uint32_t&,
                            MaybeMagicGrallocBufferHandle*) MOZ_OVERRIDE;
 
   virtual bool
   DeallocPGrallocBufferChild(PGrallocBufferChild* actor) MOZ_OVERRIDE;
 
+  virtual PTextureChild*
+  AllocPTextureChild() MOZ_OVERRIDE;
+
+  virtual bool
+  DeallocPTextureChild(PTextureChild* actor) MOZ_OVERRIDE;
+
   /**
    * Allocate a gralloc SurfaceDescriptor remotely.
    */
   bool
   AllocSurfaceDescriptorGralloc(const gfxIntSize& aSize,
                                 const uint32_t& aFormat,
                                 const uint32_t& aUsage,
                                 SurfaceDescriptor* aBuffer);
@@ -250,41 +256,30 @@ public:
    */
   static void FlushAllImagesNow(ImageClient* aClient, ImageContainer* aContainer, bool aExceptFront);
 
   // CompositableForwarder
 
   virtual void Connect(CompositableClient* aCompositable) MOZ_OVERRIDE;
 
   /**
-   * See CompositableForwarder::AddTexture
-   */
-  virtual bool AddTexture(CompositableClient* aCompositable,
-                          TextureClient* aClient) MOZ_OVERRIDE;
-
-  /**
-   * See CompositableForwarder::RemoveTexture
-   */
-  virtual void RemoveTexture(CompositableClient* aCompositable,
-                             uint64_t aTextureID,
-                             TextureFlags aFlags) MOZ_OVERRIDE;
-
-  /**
    * See CompositableForwarder::UpdatedTexture
    */
   virtual void UpdatedTexture(CompositableClient* aCompositable,
                               TextureClient* aTexture,
                               nsIntRegion* aRegion) MOZ_OVERRIDE;
 
   /**
    * See CompositableForwarder::UseTexture
    */
   virtual void UseTexture(CompositableClient* aCompositable,
                           TextureClient* aClient) MOZ_OVERRIDE;
 
+  virtual void RemoveTexture(TextureClient* aTexture) MOZ_OVERRIDE;
+
   virtual void PaintedTiledLayerBuffer(CompositableClient* aCompositable,
                                        const SurfaceDescriptorTiles& aTileLayerDescriptor) MOZ_OVERRIDE
   {
     NS_RUNTIMEABORT("should not be called");
   }
 
   /**
    * Communicate to the compositor that the texture identified by aCompositable
@@ -373,16 +368,18 @@ public:
   /**
    * See ISurfaceAllocator.h
    * Can be used from any thread.
    * If used outside the ImageBridgeChild thread, it will proxy a synchronous
    * call on the ImageBridgeChild thread.
    */
   virtual void DeallocShmem(mozilla::ipc::Shmem& aShmem);
 
+  virtual PTextureChild* CreateEmptyTextureChild() MOZ_OVERRIDE;
+
 protected:
   ImageBridgeChild();
   bool DispatchAllocShmemInternal(size_t aSize,
                                   SharedMemory::SharedMemoryType aType,
                                   Shmem* aShmem,
                                   bool aUnsafe);
 
   CompositableTransaction* mTxn;
--- a/gfx/layers/ipc/ImageBridgeParent.cpp
+++ b/gfx/layers/ipc/ImageBridgeParent.cpp
@@ -25,16 +25,17 @@
 #include "mozilla/layers/Compositor.h"
 #include "mozilla/mozalloc.h"           // for operator new, etc
 #include "nsAutoPtr.h"                  // for nsRefPtr
 #include "nsDebug.h"                    // for NS_RUNTIMEABORT, etc
 #include "nsISupportsImpl.h"            // for ImageBridgeParent::Release, etc
 #include "nsTArray.h"                   // for nsTArray, nsTArray_Impl
 #include "nsTArrayForwardDeclare.h"     // for InfallibleTArray
 #include "nsXULAppAPI.h"                // for XRE_GetIOMessageLoop
+#include "mozilla/layers/TextureHost.h"
 
 using namespace base;
 using namespace mozilla::ipc;
 
 namespace mozilla {
 namespace layers {
 
 class PGrallocBufferParent;
@@ -122,16 +123,26 @@ ImageBridgeParent::Create(Transport* aTr
   loop->PostTask(FROM_HERE,
                  NewRunnableFunction(ConnectImageBridgeInParentProcess,
                                      bridge.get(), aTransport, processHandle));
   return bridge.get();
 }
 
 bool ImageBridgeParent::RecvStop()
 {
+  // If there is any texture still alive we have to force it to deallocate the
+  // device data (GL textures, etc.) now because shortly after SenStop() returns
+  // on the child side the widget will be destroyed along with it's associated
+  // GL context.
+  InfallibleTArray<PTextureParent*> textures;
+  ManagedPTextureParent(textures);
+  for (unsigned int i = 0; i < textures.Length(); ++i) {
+    RefPtr<TextureHost> tex = TextureHost::AsTextureHost(textures[i]);
+    tex->DeallocateDeviceData();
+  }
   return true;
 }
 
 static  uint64_t GenImageContainerID() {
   static uint64_t sNextImageID = 1;
 
   ++sNextImageID;
   return sNextImageID;
@@ -173,16 +184,28 @@ ImageBridgeParent::AllocPCompositablePar
 }
 
 bool ImageBridgeParent::DeallocPCompositableParent(PCompositableParent* aActor)
 {
   delete aActor;
   return true;
 }
 
+PTextureParent*
+ImageBridgeParent::AllocPTextureParent()
+{
+  return TextureHost::CreateIPDLActor(this);
+}
+
+bool
+ImageBridgeParent::DeallocPTextureParent(PTextureParent* actor)
+{
+  return TextureHost::DestroyIPDLActor(actor);
+}
+
 MessageLoop * ImageBridgeParent::GetMessageLoop() {
   return mMessageLoop;
 }
 
 void
 ImageBridgeParent::DeferredDestroy()
 {
   mSelfRef = nullptr;
--- a/gfx/layers/ipc/ImageBridgeParent.h
+++ b/gfx/layers/ipc/ImageBridgeParent.h
@@ -60,16 +60,19 @@ public:
   virtual bool RecvUpdateNoSwap(const EditArray& aEdits);
 
   virtual bool IsAsync() const MOZ_OVERRIDE { return true; }
 
   PCompositableParent* AllocPCompositableParent(const TextureInfo& aInfo,
                                                 uint64_t*) MOZ_OVERRIDE;
   bool DeallocPCompositableParent(PCompositableParent* aActor) MOZ_OVERRIDE;
 
+  virtual PTextureParent* AllocPTextureParent() MOZ_OVERRIDE;
+  virtual bool DeallocPTextureParent(PTextureParent* actor) MOZ_OVERRIDE;
+
   bool RecvStop() MOZ_OVERRIDE;
 
   MessageLoop * GetMessageLoop();
 
 
   // ISurfaceAllocator
 
   bool AllocShmem(size_t aSize,
--- a/gfx/layers/ipc/LayerTransactionChild.cpp
+++ b/gfx/layers/ipc/LayerTransactionChild.cpp
@@ -8,16 +8,17 @@
 #include "LayerTransactionChild.h"
 #include "mozilla/layers/CompositableClient.h"  // for CompositableChild
 #include "mozilla/layers/LayersSurfaces.h"  // for PGrallocBufferChild
 #include "mozilla/layers/PCompositableChild.h"  // for PCompositableChild
 #include "mozilla/layers/PLayerChild.h"  // for PLayerChild
 #include "mozilla/mozalloc.h"           // for operator delete, etc
 #include "nsDebug.h"                    // for NS_RUNTIMEABORT, etc
 #include "nsTArray.h"                   // for nsTArray
+#include "mozilla/layers/TextureClient.h"
 
 namespace mozilla {
 namespace layers {
 
 class PGrallocBufferChild;
 
 void
 LayerTransactionChild::Destroy()
@@ -91,10 +92,22 @@ LayerTransactionChild::ActorDestroy(Acto
   // shutdown. Its better just to crash here. On desktop though, we have a chance
   // of recovering.
   if (why == AbnormalShutdown) {
     NS_RUNTIMEABORT("ActorDestroy by IPC channel failure at LayerTransactionChild");
   }
 #endif
 }
 
+PTextureChild*
+LayerTransactionChild::AllocPTextureChild()
+{
+  return TextureClient::CreateIPDLActor();
+}
+
+bool
+LayerTransactionChild::DeallocPTextureChild(PTextureChild* actor)
+{
+  return TextureClient::DestroyIPDLActor(actor);
+}
+
 }  // namespace layers
 }  // namespace mozilla
--- a/gfx/layers/ipc/LayerTransactionChild.h
+++ b/gfx/layers/ipc/LayerTransactionChild.h
@@ -53,16 +53,20 @@ protected:
   virtual bool
   DeallocPGrallocBufferChild(PGrallocBufferChild* actor) MOZ_OVERRIDE;
 
   virtual PLayerChild* AllocPLayerChild() MOZ_OVERRIDE;
   virtual bool DeallocPLayerChild(PLayerChild* actor) MOZ_OVERRIDE;
 
   virtual PCompositableChild* AllocPCompositableChild(const TextureInfo& aInfo) MOZ_OVERRIDE;
   virtual bool DeallocPCompositableChild(PCompositableChild* actor) MOZ_OVERRIDE;
+
+  virtual PTextureChild* AllocPTextureChild() MOZ_OVERRIDE;
+  virtual bool DeallocPTextureChild(PTextureChild* actor) MOZ_OVERRIDE;
+
   virtual void ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE;
 
   void AddIPDLReference() {
     MOZ_ASSERT(mIPCOpen == false);
     mIPCOpen = true;
     AddRef();
   }
   void ReleaseIPDLReference() {
--- a/gfx/layers/ipc/LayerTransactionParent.cpp
+++ b/gfx/layers/ipc/LayerTransactionParent.cpp
@@ -34,16 +34,17 @@
 #include "nsDebug.h"                    // for NS_RUNTIMEABORT
 #include "nsISupportsImpl.h"            // for Layer::Release, etc
 #include "nsLayoutUtils.h"              // for nsLayoutUtils
 #include "nsMathUtils.h"                // for NS_round
 #include "nsPoint.h"                    // for nsPoint
 #include "nsTArray.h"                   // for nsTArray, nsTArray_Impl, etc
 #include "nsTraceRefcnt.h"              // for MOZ_COUNT_CTOR, etc
 #include "GeckoProfiler.h"
+#include "mozilla/layers/TextureHost.h"
 
 typedef std::vector<mozilla::layers::EditReply> EditReplyVector;
 
 using mozilla::layout::RenderFrameParent;
 
 namespace mozilla {
 namespace layers {
 
@@ -595,10 +596,22 @@ LayerTransactionParent::AllocPCompositab
 
 bool
 LayerTransactionParent::DeallocPCompositableParent(PCompositableParent* actor)
 {
   delete actor;
   return true;
 }
 
+PTextureParent*
+LayerTransactionParent::AllocPTextureParent()
+{
+  return TextureHost::CreateIPDLActor(this);
+}
+
+bool
+LayerTransactionParent::DeallocPTextureParent(PTextureParent* actor)
+{
+  return TextureHost::DestroyIPDLActor(actor);
+}
+
 } // namespace layers
 } // namespace mozilla
--- a/gfx/layers/ipc/LayerTransactionParent.h
+++ b/gfx/layers/ipc/LayerTransactionParent.h
@@ -101,16 +101,19 @@ protected:
   DeallocPGrallocBufferParent(PGrallocBufferParent* actor) MOZ_OVERRIDE;
 
   virtual PLayerParent* AllocPLayerParent() MOZ_OVERRIDE;
   virtual bool DeallocPLayerParent(PLayerParent* actor) MOZ_OVERRIDE;
 
   virtual PCompositableParent* AllocPCompositableParent(const TextureInfo& aInfo) MOZ_OVERRIDE;
   virtual bool DeallocPCompositableParent(PCompositableParent* actor) MOZ_OVERRIDE;
 
+  virtual PTextureParent* AllocPTextureParent() MOZ_OVERRIDE;
+  virtual bool DeallocPTextureParent(PTextureParent* actor) MOZ_OVERRIDE;
+
   void Attach(ShadowLayerParent* aLayerParent,
               CompositableParent* aCompositable,
               bool aIsAsyncVideo);
 
   void AddIPDLReference() {
     MOZ_ASSERT(mIPCOpen == false);
     mIPCOpen = true;
     AddRef();
--- a/gfx/layers/ipc/LayersMessages.ipdlh
+++ b/gfx/layers/ipc/LayersMessages.ipdlh
@@ -6,16 +6,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 include LayersSurfaces;
 include protocol PCompositable;
 include protocol PCompositor;
 include protocol PGrallocBuffer;
 include protocol PLayer;
 include protocol PRenderFrame;
+include protocol PTexture;
 
 include "gfxipc/ShadowLayerUtils.h";
 include "mozilla/GfxMessageUtils.h";
 include "ImageLayers.h";
 
 using mozilla::GraphicsFilterType from "mozilla/GfxMessageUtils.h";
 using struct gfxRGBA from "gfxColor.h";
 using struct gfxPoint3D from "gfxPoint3D.h";
@@ -296,71 +297,48 @@ struct OpPaintTextureIncremental {
 };
 
 struct OpUpdatePictureRect {
   PCompositable compositable;
   nsIntRect picture;
 };
 
 /**
- * Provides the compositor side with enough information to create a
- * TextureHost.
- */
-struct OpAddTexture {
-  PCompositable compositable;
-  uint64_t textureID;
-  SurfaceDescriptor data;
-  uint32_t textureFlags;
-};
-
-/**
- * Tells the compositor-side to remove the corresponding TextureHost and
- * deallocate its data.
- */
-struct OpRemoveTexture {
-  PCompositable compositable;
-  uint64_t textureID;
-  uint32_t flags;
-};
-
-/**
  * Tells the compositor-side which texture to use (for example, as front buffer
  * if there is several textures for double buffering)
  */
 struct OpUseTexture {
   PCompositable compositable;
-  uint64_t textureID;
+  PTexture texture;
 };
 
 union MaybeRegion {
   nsIntRegion;
   null_t;
 };
 
 struct OpUpdateTexture {
   PCompositable compositable;
-  uint64_t textureID;
+  PTexture texture;
   MaybeRegion region;
 };
 
 union CompositableOperation {
   OpUpdatePictureRect;
 
   OpCreatedTexture;
   OpCreatedIncrementalTexture;
   OpDestroyThebesBuffer;
 
   OpPaintTexture;
   OpPaintTextureRegion;
   OpPaintTextureIncremental;
 
   OpPaintTiledLayerBuffer;
 
-  OpAddTexture;
-  OpRemoveTexture;
   OpUpdateTexture;
   OpUseTexture;
 };
 
 // A unit of a changeset; a set of these comprise a changeset
 union Edit {
   OpCreateThebesLayer;
   OpCreateContainerLayer;
@@ -394,24 +372,17 @@ struct OpContentBufferSwap {
 };
 
 struct OpTextureSwap {
   PCompositable compositable;
   uint32_t textureId;
   SurfaceDescriptor image;
 };
 
-struct ReplyTextureRemoved {
-  PCompositable compositable;
-  uint64_t textureId;
-};
-
 // Unit of a "changeset reply".  This is a weird abstraction, probably
 // only to be used for buffer swapping.
 union EditReply {
   OpContentBufferSwap;
   OpTextureSwap;
-
-  ReplyTextureRemoved;
 };
 
 } // namespace
 } // namespace
--- a/gfx/layers/ipc/PImageBridge.ipdl
+++ b/gfx/layers/ipc/PImageBridge.ipdl
@@ -2,16 +2,17 @@
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 include LayersSurfaces;
 include LayersMessages;
 include protocol PGrallocBuffer;
 include protocol PCompositable;
+include protocol PTexture;
 include ProtocolTypes;
 
 include "mozilla/GfxMessageUtils.h";
 
 using struct mozilla::layers::TextureInfo from "mozilla/layers/CompositorTypes.h";
 
 namespace mozilla {
 namespace layers {
@@ -20,16 +21,17 @@ namespace layers {
  * The PImageBridge protocol is used to allow isolated threads or processes to push
  * frames directly to the compositor thread/process without relying on the main thread
  * which might be too busy dealing with content script.
  */
 intr protocol PImageBridge
 {
   manages PCompositable;
   manages PGrallocBuffer;
+  manages PTexture;
 
 parent:
 
   sync Update(CompositableOperation[] ops) returns (EditReply[] reply);
   async UpdateNoSwap(CompositableOperation[] ops);
 
   // Allocates a gralloc buffer that may not suitable to use with
   // gfxImageSurface but allows hardware decoder to write to the
@@ -44,14 +46,15 @@ parent:
   // counterpart so as to not race with the upcomming __delete__ message.
   // In the child side, the __delete__ messages are not sent right after Stop,
   // they are scheduled in the ImageBridgeChild's message queue in order to ensure
   // that all the messages from the parent side have been received and processed
   // before sending __delete__.
   sync Stop();
 
   sync PCompositable(TextureInfo aInfo) returns (uint64_t id);
+  async PTexture();
 };
 
 
 } // namespace
 } // namespace
 
--- a/gfx/layers/ipc/PLayerTransaction.ipdl
+++ b/gfx/layers/ipc/PLayerTransaction.ipdl
@@ -7,16 +7,17 @@
 
 include LayersSurfaces;
 include LayersMessages;
 include protocol PCompositable;
 include protocol PCompositor;
 include protocol PGrallocBuffer;
 include protocol PLayer;
 include protocol PRenderFrame;
+include protocol PTexture;
 
 include "mozilla/GfxMessageUtils.h";
 
 using struct mozilla::layers::TextureInfo from "mozilla/layers/CompositorTypes.h";
 
 /**
  * The layers protocol is spoken between thread contexts that manage
  * layer (sub)trees.  The protocol comprises atomically publishing
@@ -28,16 +29,17 @@ using struct mozilla::layers::TextureInf
 namespace mozilla {
 namespace layers {
 
 sync protocol PLayerTransaction {
   manager PRenderFrame or PCompositor;
   manages PLayer;
   manages PCompositable;
   manages PGrallocBuffer;
+  manages PTexture;
 
 parent:
   /**
    * Only the parent side has privileges to allocate the buffer.
    * Allocation may fail (pmem is a scarce resource), and if so null_t
    * is returned.
    *
    * |format| is an Android PixelFormat (see PixelFormat.h)
@@ -61,16 +63,17 @@ parent:
    *   USAGE_HW_RENDER | USAGE_HW_TEXTURE
    *     - used for GL rendering to a buffer which the compositor
    *       treats as a texture
    */
   sync PGrallocBuffer(gfxIntSize size, uint32_t format, uint32_t usage)
     returns (MaybeMagicGrallocBufferHandle handle);
   async PLayer();
   async PCompositable(TextureInfo aTextureInfo);
+  async PTexture();
 
   // The isFirstPaint flag can be used to indicate that this is the first update
   // for a particular document.
   sync Update(Edit[] cset, TargetConfig targetConfig, bool isFirstPaint)
     returns (EditReply[] reply);
 
   sync GetOpacity(PLayer layer) returns (float opacity);
   sync GetTransform(PLayer layer) returns (gfx3DMatrix transform);
new file mode 100644
--- /dev/null
+++ b/gfx/layers/ipc/PTexture.ipdl
@@ -0,0 +1,46 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * vim: sw=2 ts=8 et :
+ */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+include LayersSurfaces;
+include protocol PLayerTransaction;
+include protocol PImageBridge;
+include protocol PGrallocBuffer;
+include "mozilla/GfxMessageUtils.h";
+
+using struct mozilla::layers::FrameMetrics from "FrameMetrics.h";
+
+namespace mozilla {
+namespace layers {
+
+/**
+ * PTexture is the IPDL glue between a TextureClient and a TextureHost.
+ */
+sync protocol PTexture {
+    manager PImageBridge or PLayerTransaction;
+
+child:
+    async __delete__();
+
+parent:
+    /**
+     * Set the shared data and create the TextureHost on the parent side.
+     */
+    async Init(SurfaceDescriptor aSharedData, uint32_t aTextureFlags);
+
+    /**
+     * Asynchronously tell the Compositor side to remove the texture.
+     */
+    async RemoveTexture();
+
+    /**
+     * Synchronously tell the compositor side to remove the texture.
+     */
+    sync RemoveTextureSync();
+};
+
+} // layers
+} // mozilla
--- a/gfx/layers/ipc/ShadowLayerUtilsGralloc.cpp
+++ b/gfx/layers/ipc/ShadowLayerUtilsGralloc.cpp
@@ -8,16 +8,17 @@
 #include "mozilla/DebugOnly.h"
 
 #include "mozilla/layers/PGrallocBufferChild.h"
 #include "mozilla/layers/PGrallocBufferParent.h"
 #include "mozilla/layers/LayerTransactionChild.h"
 #include "mozilla/layers/ShadowLayers.h"
 #include "mozilla/layers/LayerManagerComposite.h"
 #include "mozilla/layers/CompositorTypes.h"
+#include "mozilla/layers/TextureHost.h"
 #include "mozilla/unused.h"
 #include "nsXULAppAPI.h"
 
 #include "ShadowLayerUtilsGralloc.h"
 
 #include "nsIMemoryReporter.h"
 
 #include "gfxImageSurface.h"
--- a/gfx/layers/ipc/ShadowLayerUtilsGralloc.h
+++ b/gfx/layers/ipc/ShadowLayerUtilsGralloc.h
@@ -10,30 +10,28 @@
 
 #include <unistd.h>
 #include <ui/GraphicBuffer.h>
 
 #include "ipc/IPCMessageUtils.h"
 #include "mozilla/layers/PGrallocBufferChild.h"
 #include "mozilla/layers/PGrallocBufferParent.h"
 
-// used only for hacky fix in gecko 23 for bug 862324
-// see bug 865908 about fixing this.
-#include "TextureHost.h"
-
 #define MOZ_HAVE_SURFACEDESCRIPTORGRALLOC
 #define MOZ_HAVE_PLATFORM_SPECIFIC_LAYER_BUFFERS
 
 class gfxASurface;
 
 namespace mozilla {
 namespace layers {
 
 class MaybeMagicGrallocBufferHandle;
 class SurfaceDescriptorGralloc;
+class TextureHost;
+class DeprecatedTextureHost;
 
 /**
  * This class exists to share the underlying GraphicBuffer resources
  * from one thread context to another.  This requires going through
  * slow paths in the kernel so can be somewhat expensive.
  *
  * This is not just platform-specific, but also
  * gralloc-implementation-specific.
--- a/gfx/layers/ipc/ShadowLayers.cpp
+++ b/gfx/layers/ipc/ShadowLayers.cpp
@@ -402,73 +402,46 @@ ShadowLayerForwarder::UpdateTextureIncre
 
 void
 ShadowLayerForwarder::UpdatePictureRect(CompositableClient* aCompositable,
                                         const nsIntRect& aRect)
 {
   mTxn->AddNoSwapPaint(OpUpdatePictureRect(nullptr, aCompositable->GetIPDLActor(), aRect));
 }
 
-bool
-ShadowLayerForwarder::AddTexture(CompositableClient* aCompositable,
-                                 TextureClient* aTexture)
-{
-  SurfaceDescriptor descriptor;
-  if (!aTexture->ToSurfaceDescriptor(descriptor)) {
-    NS_WARNING("Failed to serialize a TextureClient");
-    return false;
-  }
-  CheckSurfaceDescriptor(&descriptor);
-  MOZ_ASSERT(aCompositable);
-  MOZ_ASSERT(aCompositable->GetIPDLActor());
-  MOZ_ASSERT(aTexture->GetFlags() != 0);
-  mTxn->AddEdit(OpAddTexture(nullptr, aCompositable->GetIPDLActor(),
-                             aTexture->GetID(),
-                             descriptor,
-                             aTexture->GetFlags()));
-  return true;
-}
-
-void
-ShadowLayerForwarder::RemoveTexture(CompositableClient* aCompositable,
-                                    uint64_t aTexture,
-                                    TextureFlags aFlags)
-{
-  mTxn->AddEdit(OpRemoveTexture(nullptr, aCompositable->GetIPDLActor(),
-                                aTexture,
-                                aFlags));
-  if (aFlags & TEXTURE_DEALLOCATE_CLIENT) {
-    mTxn->MarkSyncTransaction();
-  }
-}
-
 void
 ShadowLayerForwarder::UpdatedTexture(CompositableClient* aCompositable,
                                      TextureClient* aTexture,
                                      nsIntRegion* aRegion)
 {
   MaybeRegion region = aRegion ? MaybeRegion(*aRegion)
                                : MaybeRegion(null_t());
   if (aTexture->GetFlags() & TEXTURE_IMMEDIATE_UPLOAD) {
     mTxn->AddPaint(OpUpdateTexture(nullptr, aCompositable->GetIPDLActor(),
-                                   aTexture->GetID(),
+                                   nullptr, aTexture->GetIPDLActor(),
                                    region));
   } else {
     mTxn->AddNoSwapPaint(OpUpdateTexture(nullptr, aCompositable->GetIPDLActor(),
-                                         aTexture->GetID(),
+                                         nullptr, aTexture->GetIPDLActor(),
                                          region));
   }
 }
 
 void
 ShadowLayerForwarder::UseTexture(CompositableClient* aCompositable,
                                  TextureClient* aTexture)
 {
   mTxn->AddEdit(OpUseTexture(nullptr, aCompositable->GetIPDLActor(),
-                             aTexture->GetID()));
+                             nullptr, aTexture->GetIPDLActor()));
+}
+
+void
+ShadowLayerForwarder::RemoveTexture(TextureClient* aTexture)
+{
+  aTexture->ForceRemove();
 }
 
 bool
 ShadowLayerForwarder::EndTransaction(InfallibleTArray<EditReply>* aReplies, bool* aSent)
 {
   *aSent = false;
 
   PROFILER_LABEL("ShadowLayerForwarder", "EndTranscation");
@@ -984,16 +957,23 @@ void ShadowLayerForwarder::AttachAsyncCo
                                                    ShadowableLayer* aLayer)
 {
   MOZ_ASSERT(aLayer);
   MOZ_ASSERT(aCompositableID != 0); // zero is always an invalid compositable id.
   mTxn->AddEdit(OpAttachAsyncCompositable(nullptr, Shadow(aLayer),
                                           aCompositableID));
 }
 
+PTextureChild*
+ShadowLayerForwarder::CreateEmptyTextureChild()
+{
+  return mShadowManager->SendPTextureConstructor();
+}
+
+
 void ShadowLayerForwarder::SetShadowManager(PLayerTransactionChild* aShadowManager)
 {
   mShadowManager = static_cast<LayerTransactionChild*>(aShadowManager);
 }
 
 
 } // namespace layers
 } // namespace mozilla
--- a/gfx/layers/ipc/ShadowLayers.h
+++ b/gfx/layers/ipc/ShadowLayers.h
@@ -144,16 +144,18 @@ public:
   virtual ~ShadowLayerForwarder();
 
   /**
    * Setup the IPDL actor for aCompositable to be part of layers
    * transactions.
    */
   void Connect(CompositableClient* aCompositable);
 
+  virtual PTextureChild* CreateEmptyTextureChild() MOZ_OVERRIDE;
+
   virtual void CreatedSingleBuffer(CompositableClient* aCompositable,
                                    const SurfaceDescriptor& aDescriptor,
                                    const TextureInfo& aTextureInfo,
                                    const SurfaceDescriptor* aDescriptorOnWhite = nullptr) MOZ_OVERRIDE;
   virtual void CreatedIncrementalBuffer(CompositableClient* aCompositable,
                                         const TextureInfo& aTextureInfo,
                                         const nsIntRect& aBufferRect) MOZ_OVERRIDE;
   virtual void CreatedDoubleBuffer(CompositableClient* aCompositable,
@@ -272,16 +274,18 @@ public:
   /**
    * Communicate to the compositor that the texture identified by aLayer
    * and aIdentifier has been updated to aImage.
    */
   virtual void UpdateTexture(CompositableClient* aCompositable,
                              TextureIdentifier aTextureId,
                              SurfaceDescriptor* aDescriptor) MOZ_OVERRIDE;
 
+  virtual void RemoveTexture(TextureClient* aTexture) MOZ_OVERRIDE;
+
   /**
    * Same as above, but performs an asynchronous layer transaction
    */
   virtual void UpdateTextureNoSwap(CompositableClient* aCompositable,
                                    TextureIdentifier aTextureId,
                                    SurfaceDescriptor* aDescriptor) MOZ_OVERRIDE;
 
   /**
@@ -301,29 +305,16 @@ public:
 
   /**
    * Communicate the picture rect of an image to the compositor
    */
   void UpdatePictureRect(CompositableClient* aCompositable,
                          const nsIntRect& aRect);
 
   /**
-   * See CompositableForwarder::AddTexture
-   */
-  virtual bool AddTexture(CompositableClient* aCompositable,
-                          TextureClient* aClient) MOZ_OVERRIDE;
-
-  /**
-   * See CompositableForwarder::RemoveTexture
-   */
-  virtual void RemoveTexture(CompositableClient* aCompositable,
-                             uint64_t aTextureID,
-                             TextureFlags aFlags) MOZ_OVERRIDE;
-
-  /**
    * See CompositableForwarder::UpdatedTexture
    */
   virtual void UpdatedTexture(CompositableClient* aCompositable,
                               TextureClient* aTexture,
                               nsIntRegion* aRegion) MOZ_OVERRIDE;
 
   /**
    * See CompositableForwarder::UseTexture
--- a/gfx/layers/moz.build
+++ b/gfx/layers/moz.build
@@ -93,16 +93,17 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'wind
             'd3d11/CompositorD3D11.cpp',
         ]
 
 EXPORTS.gfxipc += [
     'ipc/ShadowLayerUtils.h',
 ]
 
 EXPORTS.mozilla.layers += [
+    'AtomicRefCountedWithFinalize.h',
     'basic/BasicCompositor.h',
     'basic/MacIOSurfaceTextureHostBasic.h',
     'basic/TextureHostBasic.h',
     'client/CanvasClient.h',
     'client/CompositableClient.h',
     'client/ContentClient.h',
     'client/ImageClient.h',
     'client/TextureClient.h',
@@ -181,16 +182,17 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'coco
 # libraries, but only Gonk is able to use it reliably because Gecko
 # has full system permissions there.
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
     EXPORTS.mozilla.layers += [
         'ipc/ShadowLayerUtilsGralloc.h',
     ]
     UNIFIED_SOURCES += [
         'GrallocImages.cpp',
+        'opengl/EGLImageHelpers.cpp',
         'opengl/GrallocTextureClient.cpp',
         'opengl/GrallocTextureHost.cpp',
     ]
     SOURCES += [
         'ipc/ShadowLayerUtilsGralloc.cpp',
     ]
 
 UNIFIED_SOURCES += [
@@ -285,16 +287,17 @@ IPDL_SOURCES = [
     'ipc/LayersMessages.ipdlh',
     'ipc/LayersSurfaces.ipdlh',
     'ipc/PCompositable.ipdl',
     'ipc/PCompositor.ipdl',
     'ipc/PGrallocBuffer.ipdl',
     'ipc/PImageBridge.ipdl',
     'ipc/PLayer.ipdl',
     'ipc/PLayerTransaction.ipdl',
+    'ipc/PTexture.ipdl',
 ]
 
 MSVC_ENABLE_PGO = True
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'thebes'
 
--- a/gfx/layers/opengl/CompositorOGL.cpp
+++ b/gfx/layers/opengl/CompositorOGL.cpp
@@ -36,16 +36,17 @@
 #include "nsIConsoleService.h"          // for nsIConsoleService, etc
 #include "nsIWidget.h"                  // for nsIWidget
 #include "nsLiteralString.h"            // for NS_LITERAL_STRING
 #include "nsMathUtils.h"                // for NS_roundf
 #include "nsRect.h"                     // for nsIntRect
 #include "nsServiceManagerUtils.h"      // for do_GetService
 #include "nsString.h"                   // for nsString, nsAutoCString, etc
 #include "DecomposeIntoNoRepeatTriangles.h"
+#include "ScopedGLHelpers.h"
 
 #if MOZ_ANDROID_OMTC
 #include "TexturePoolOGL.h"
 #endif
 #include "GeckoProfiler.h"
 
 #ifdef MOZ_WIDGET_ANDROID
 #include "GfxInfo.h"
@@ -60,16 +61,26 @@ using namespace gfx;
 namespace layers {
 
 using namespace mozilla::gl;
 
 static inline IntSize ns2gfxSize(const nsIntSize& s) {
   return IntSize(s.width, s.height);
 }
 
+static void
+BindMaskForProgram(ShaderProgramOGL* aProgram, TextureSourceOGL* aSourceMask,
+                   GLenum aTexUnit, const gfx::Matrix4x4& aTransform)
+{
+  MOZ_ASSERT(LOCAL_GL_TEXTURE0 <= aTexUnit && aTexUnit <= LOCAL_GL_TEXTURE31);
+  aSourceMask->BindTexture(aTexUnit);
+  aProgram->SetMaskTextureUnit(aTexUnit - LOCAL_GL_TEXTURE0);
+  aProgram->SetMaskLayerTransform(aTransform);
+}
+
 // Draw the given quads with the already selected shader. Texture coordinates
 // are supplied if the shader requires them.
 static void
 DrawQuads(GLContext *aGLContext,
           VBOArena &aVBOs,
           ShaderProgramOGL *aProg,
           RectTriangles &aRects)
 {
@@ -973,38 +984,86 @@ CompositorOGL::GetProgramTypeForEffect(E
   case EFFECT_RENDER_TARGET:
     return GetFBOLayerProgramType();
   default:
     return RGBALayerProgramType;
   }
 }
 
 struct MOZ_STACK_CLASS AutoBindTexture
+  : public ScopedGLWrapper<AutoBindTexture>
 {
-  AutoBindTexture() : mTexture(nullptr) {}
-  AutoBindTexture(TextureSourceOGL* aTexture, GLenum aTextureUnit)
-   : mTexture(nullptr) { Bind(aTexture, aTextureUnit); }
-  ~AutoBindTexture()
+  friend struct ScopedGLWrapper<AutoBindTexture>;
+
+protected:
+  GLenum mTexUnit;
+  GLuint mOldTexId;
+
+public:
+  explicit AutoBindTexture(GLContext* aGL)
+    : ScopedGLWrapper<AutoBindTexture>(aGL)
+    , mTexUnit(0)
+    , mOldTexId(GLuint(-1))
+  { }
+
+  AutoBindTexture(GLContext* aGL, TextureSourceOGL* aTexture,
+                  GLenum aTexUnit = LOCAL_GL_TEXTURE0)
+    : ScopedGLWrapper<AutoBindTexture>(aGL)
+    , mTexUnit(0)
+    , mOldTexId(GLuint(-1))
   {
-    if (mTexture) {
-      mTexture->UnbindTexture();
-    }
+    MOZ_ASSERT(aTexture);
+    MOZ_ASSERT(mOldTexId == GLuint(-1));
+    mTexUnit = aTexUnit;
+
+    ScopedBindTextureUnit autoBindTexUnit(mGL, aTexUnit);
+
+    mGL->GetUIntegerv(LOCAL_GL_TEXTURE_BINDING_2D, &mOldTexId);
+    aTexture->BindTexture(mTexUnit);
   }
 
-  void Bind(TextureSourceOGL* aTexture, GLenum aTextureUnit)
+protected:
+  void UnwrapImpl()
   {
-    MOZ_ASSERT(!mTexture);
-    mTexture = aTexture;
-    mTexture->BindTexture(aTextureUnit);
+    if (mOldTexId == GLuint(-1))
+      return;
+
+    ScopedBindTextureUnit autoBindTexUnit(mGL, mTexUnit);
+    mGL->fBindTexture(LOCAL_GL_TEXTURE_2D, mOldTexId);
+  }
+};
+
+struct MOZ_STACK_CLASS AutoSaveTexture
+  : public ScopedGLWrapper<AutoSaveTexture>
+{
+  friend struct ScopedGLWrapper<AutoSaveTexture>;
+
+protected:
+  GLenum mTexUnit;
+  GLuint mOldTexId;
+
+public:
+  AutoSaveTexture(GLContext* aGL, GLenum aTexUnit = LOCAL_GL_TEXTURE0)
+    : ScopedGLWrapper<AutoSaveTexture>(aGL)
+    , mTexUnit(aTexUnit)
+    , mOldTexId(GLuint(-1))
+  {
+    ScopedBindTextureUnit savedTexUnit(mGL, mTexUnit);
+    mGL->GetUIntegerv(LOCAL_GL_TEXTURE_BINDING_2D, &mOldTexId);
   }
 
-private:
-  TextureSourceOGL* mTexture;
+protected:
+  void UnwrapImpl()
+  {
+    ScopedBindTextureUnit savedTexUnit(mGL, mTexUnit);
+    mGL->fBindTexture(LOCAL_GL_TEXTURE_2D, mOldTexId);
+  }
 };
 
+
 void
 CompositorOGL::DrawLines(const std::vector<gfx::Point>& aLines, const gfx::Rect& aClipRect,
                          const gfx::Color& aColor,
                          gfx::Float aOpacity, const gfx::Matrix4x4 &aTransform)
 {
   mGLContext->fLineWidth(2.0);
 
   EffectChain effects;
@@ -1014,16 +1073,30 @@ CompositorOGL::DrawLines(const std::vect
     const gfx::Point& p1 = aLines[i];
     const gfx::Point& p2 = aLines[i+1];
     DrawQuadInternal(Rect(p1.x, p2.y, p2.x - p1.x, p1.y - p2.y),
                      aClipRect, effects, aOpacity, aTransform,
                      LOCAL_GL_LINE_STRIP);
   }
 }
 
+/**
+ * Applies aFilter to the texture currently bound to aTarget.
+ */
+void ApplyFilterToBoundTexture(GLContext* aGL,
+                               GraphicsFilter aFilter,
+                               GLuint aTarget = LOCAL_GL_TEXTURE_2D)
+{
+  GLenum filter =
+    (aFilter == GraphicsFilter::FILTER_NEAREST ? LOCAL_GL_NEAREST : LOCAL_GL_LINEAR);
+
+    aGL->fTexParameteri(aTarget, LOCAL_GL_TEXTURE_MIN_FILTER, filter);
+    aGL->fTexParameteri(aTarget, LOCAL_GL_TEXTURE_MAG_FILTER, filter);
+}
+
 void
 CompositorOGL::DrawQuadInternal(const Rect& aRect,
                                 const Rect& aClipRect,
                                 const EffectChain &aEffectChain,
                                 Float aOpacity,
                                 const gfx::Matrix4x4 &aTransform,
                                 GLuint aDrawMode)
 {
@@ -1107,21 +1180,19 @@ CompositorOGL::DrawQuadInternal(const Re
       Float opacity = aOpacity * color.a;
       color.r *= opacity;
       color.g *= opacity;
       color.b *= opacity;
       color.a = opacity;
 
       program->SetRenderColor(color);
 
-      AutoBindTexture bindMask;
+      AutoSaveTexture bindMask(mGLContext, LOCAL_GL_TEXTURE0);
       if (maskType != MaskNone) {
-        bindMask.Bind(sourceMask, LOCAL_GL_TEXTURE0);
-        program->SetMaskTextureUnit(0);
-        program->SetMaskLayerTransform(maskQuadTransform);
+        BindMaskForProgram(program, sourceMask, LOCAL_GL_TEXTURE0, maskQuadTransform);
       }
 
       BindAndDrawQuad(program, false, aDrawMode);
     }
     break;
 
   case EFFECT_BGRA:
   case EFFECT_BGRX:
@@ -1132,17 +1203,17 @@ CompositorOGL::DrawQuadInternal(const Re
       Rect textureCoords;
       TextureSource *source = texturedEffect->mTexture;
 
       if (!texturedEffect->mPremultiplied) {
         mGLContext->fBlendFuncSeparate(LOCAL_GL_SRC_ALPHA, LOCAL_GL_ONE_MINUS_SRC_ALPHA,
                                        LOCAL_GL_ONE, LOCAL_GL_ONE);
       }
 
-      AutoBindTexture bindSource(source->AsSourceOGL(), LOCAL_GL_TEXTURE0);
+      AutoBindTexture bindSource(mGLContext, source->AsSourceOGL(), LOCAL_GL_TEXTURE0);
 
       gfx3DMatrix textureTransform = source->AsSourceOGL()->GetTextureTransform();
       program->SetTextureTransform(textureTransform);
 
       GraphicsFilter filter = ThebesFilter(texturedEffect->mFilter);
       gfxMatrix textureTransform2D;
 #ifdef MOZ_WIDGET_ANDROID
       if (filter != GraphicsFilter::FILTER_NEAREST &&
@@ -1150,28 +1221,25 @@ CompositorOGL::DrawQuadInternal(const Re
           textureTransform.Is2D(&textureTransform2D) &&
           textureTransform2D.HasOnlyIntegerTranslation()) {
         // On Android we encounter small resampling errors in what should be
         // pixel-aligned compositing operations. This works around them. This
         // code should not be needed!
         filter = GraphicsFilter::FILTER_NEAREST;
       }
 #endif
-      mGLContext->ApplyFilterToBoundTexture(source->AsSourceOGL()->GetTextureTarget(),
-                                            filter);
+      ApplyFilterToBoundTexture(mGLContext, filter,
+                                source->AsSourceOGL()->GetTextureTarget());
 
       program->SetTextureUnit(0);
       program->SetLayerOpacity(aOpacity);
 
-      AutoBindTexture bindMask;
+      AutoSaveTexture bindMask(mGLContext, LOCAL_GL_TEXTURE1);
       if (maskType != MaskNone) {
-        mGLContext->fActiveTexture(LOCAL_GL_TEXTURE1);
-        bindMask.Bind(sourceMask, LOCAL_GL_TEXTURE1);
-        program->SetMaskTextureUnit(1);
-        program->SetMaskLayerTransform(maskQuadTransform);
+        BindMaskForProgram(program, sourceMask, LOCAL_GL_TEXTURE1, maskQuadTransform);
       }
 
       BindAndDrawQuadWithTextureRect(program, texturedEffect->mTextureCoords, source);
 
       if (!texturedEffect->mPremultiplied) {
         mGLContext->fBlendFuncSeparate(LOCAL_GL_ONE, LOCAL_GL_ONE_MINUS_SRC_ALPHA,
                                        LOCAL_GL_ONE, LOCAL_GL_ONE);
       }
@@ -1188,32 +1256,30 @@ CompositorOGL::DrawQuadInternal(const Re
 
       if (!sourceY && !sourceCb && !sourceCr) {
         NS_WARNING("Invalid layer texture.");
         return;
       }
 
       GraphicsFilter filter = ThebesFilter(effectYCbCr->mFilter);
 
-      AutoBindTexture bindY(sourceY, LOCAL_GL_TEXTURE0);
-      mGLContext->ApplyFilterToBoundTexture(filter);
-      AutoBindTexture bindCb(sourceCb, LOCAL_GL_TEXTURE1);
-      mGLContext->ApplyFilterToBoundTexture(filter);
-      AutoBindTexture bindCr(sourceCr, LOCAL_GL_TEXTURE2);
-      mGLContext->ApplyFilterToBoundTexture(filter);
+      AutoBindTexture bindY(mGLContext, sourceY, LOCAL_GL_TEXTURE0);
+      ApplyFilterToBoundTexture(mGLContext, filter);
+      AutoBindTexture bindCb(mGLContext, sourceCb, LOCAL_GL_TEXTURE1);
+      ApplyFilterToBoundTexture(mGLContext, filter);
+      AutoBindTexture bindCr(mGLContext, sourceCr, LOCAL_GL_TEXTURE2);
+      ApplyFilterToBoundTexture(mGLContext, filter);
 
       program->SetYCbCrTextureUnits(Y, Cb, Cr);
       program->SetLayerOpacity(aOpacity);
       program->SetTextureTransform(gfx3DMatrix());
 
-      AutoBindTexture bindMask;
+      AutoSaveTexture bindMask(mGLContext, LOCAL_GL_TEXTURE3);
       if (maskType != MaskNone) {
-        bindMask.Bind(sourceMask, LOCAL_GL_TEXTURE3);
-        program->SetMaskTextureUnit(3);
-        program->SetMaskLayerTransform(maskQuadTransform);
+        BindMaskForProgram(program, sourceMask, LOCAL_GL_TEXTURE3, maskQuadTransform);
       }
       BindAndDrawQuadWithTextureRect(program, effectYCbCr->mTextureCoords, sourceYCbCr->GetSubSource(Y));
     }
     break;
   case EFFECT_RENDER_TARGET: {
       EffectRenderTarget* effectRenderTarget =
         static_cast<EffectRenderTarget*>(aEffectChain.mPrimaryEffect.get());
       RefPtr<CompositingRenderTargetOGL> surface
@@ -1223,19 +1289,19 @@ CompositorOGL::DrawQuadInternal(const Re
 
       surface->BindTexture(LOCAL_GL_TEXTURE0, mFBOTextureTarget);
 
       program->Activate();
       program->SetTextureUnit(0);
       program->SetLayerOpacity(aOpacity);
       program->SetTextureTransform(gfx3DMatrix());
 
-      AutoBindTexture bindMask;
+      AutoSaveTexture bindMask(mGLContext, LOCAL_GL_TEXTURE1);
       if (maskType != MaskNone) {
-        bindMask.Bind(sourceMask, LOCAL_GL_TEXTURE1);
+        sourceMask->BindTexture(LOCAL_GL_TEXTURE1);
         program->SetMaskTextureUnit(1);
         program->SetMaskLayerTransform(maskQuadTransform);
       }
 
       if (program->GetTexCoordMultiplierUniformLocation() != -1) {
         // 2DRect case, get the multiplier right for a sampler2DRect
         program->SetTexCoordMultiplier(aRect.width, aRect.height);
       }
@@ -1272,32 +1338,30 @@ CompositorOGL::DrawQuadInternal(const Re
           ShaderProgramType type = gl()->GetPreferredARGB32Format() == LOCAL_GL_BGRA ?
                                    ComponentAlphaPass2RGBProgramType :
                                    ComponentAlphaPass2ProgramType;
           program = GetProgram(type, maskType);
           gl()->fBlendFuncSeparate(LOCAL_GL_ONE, LOCAL_GL_ONE,
                                    LOCAL_GL_ONE, LOCAL_GL_ONE);
         }
 
-        AutoBindTexture bindSourceOnBlack(sourceOnBlack, LOCAL_GL_TEXTURE0);
-        AutoBindTexture bindSourceOnWhite(sourceOnWhite, LOCAL_GL_TEXTURE1);
+        AutoBindTexture bindSourceOnBlack(mGLContext, sourceOnBlack, LOCAL_GL_TEXTURE0);
+        AutoBindTexture bindSourceOnWhite(mGLContext, sourceOnWhite, LOCAL_GL_TEXTURE1);
 
         program->Activate();
         program->SetBlackTextureUnit(0);
         program->SetWhiteTextureUnit(1);
         program->SetLayerOpacity(aOpacity);
         program->SetLayerTransform(aTransform);
         program->SetTextureTransform(gfx3DMatrix());
         program->SetRenderOffset(offset.x, offset.y);
         program->SetLayerQuadRect(aRect);
-        AutoBindTexture bindMask;
+        AutoSaveTexture bindMask(mGLContext, LOCAL_GL_TEXTURE2);
         if (maskType != MaskNone) {
-          bindMask.Bind(sourceMask, LOCAL_GL_TEXTURE2);
-          program->SetMaskTextureUnit(2);
-          program->SetMaskLayerTransform(maskQuadTransform);
+          BindMaskForProgram(program, sourceMask, LOCAL_GL_TEXTURE2, maskQuadTransform);
         }
 
         BindAndDrawQuadWithTextureRect(program, effectComponentAlpha->mTextureCoords, effectComponentAlpha->mOnBlack);
 
         mGLContext->fBlendFuncSeparate(LOCAL_GL_ONE, LOCAL_GL_ONE_MINUS_SRC_ALPHA,
                                        LOCAL_GL_ONE, LOCAL_GL_ONE);
       }
     }
new file mode 100644
--- /dev/null
+++ b/gfx/layers/opengl/EGLImageHelpers.cpp
@@ -0,0 +1,50 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* vim: set ts=8 sts=4 et sw=4 tw=80: */
+/* 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 "EGLImageHelpers.h"
+#include "GLContext.h"
+#include "GLLibraryEGL.h"
+
+namespace mozilla
+{
+namespace layers {
+
+using namespace gl;
+
+EGLImage
+EGLImageCreateFromNativeBuffer(GLContext* aGL, void* aBuffer)
+{
+    EGLint attrs[] = {
+        LOCAL_EGL_IMAGE_PRESERVED, LOCAL_EGL_TRUE,
+        LOCAL_EGL_NONE, LOCAL_EGL_NONE
+    };
+
+    GLLibraryEGL* egl = aGL->GetLibraryEGL();
+    if (!egl) {
+        NS_WARNING("Failed to obtain pointer to EGL. Returning EGL_NO_IMAGE.");
+        return EGL_NO_IMAGE;
+    }
+
+    return egl->fCreateImage(egl->Display(),
+                             EGL_NO_CONTEXT,
+                             LOCAL_EGL_NATIVE_BUFFER_ANDROID,
+                             aBuffer, attrs);
+}
+
+void
+EGLImageDestroy(GLContext* aGL, EGLImage aImage)
+{
+    GLLibraryEGL* egl = aGL->GetLibraryEGL();
+    if (!egl) {
+        NS_WARNING("Failed to obtain pointer to EGL. Image not destroyed.");
+        return;
+    }
+
+    egl->fDestroyImage(egl->Display(), aImage);
+}
+
+} // namespace layers
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/gfx/layers/opengl/EGLImageHelpers.h
@@ -0,0 +1,25 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* vim: set ts=8 sts=4 et sw=4 tw=80: */
+/* 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 EGLIMAGEHELPERS_H_
+#define EGLIMAGEHELPERS_H_
+
+typedef void* EGLImage;
+
+namespace mozilla {
+namespace gl {
+    class GLContext;
+}
+
+namespace layers {
+
+EGLImage EGLImageCreateFromNativeBuffer(gl::GLContext* aGL, void* aBuffer);
+void EGLImageDestroy(gl::GLContext* aGL, EGLImage aImage);
+
+} // namespace layers
+} // namespace mozilla
+
+#endif // EGLIMAGEHELPERS_H_
--- a/gfx/layers/opengl/GrallocTextureHost.cpp
+++ b/gfx/layers/opengl/GrallocTextureHost.cpp
@@ -5,16 +5,17 @@
 
 #include "GLContext.h"
 #include "gfxImageSurface.h"
 #include "gfx2DGlue.h"
 #include <ui/GraphicBuffer.h>
 #include "GrallocImages.h"  // for GrallocImage
 #include "mozilla/layers/GrallocTextureHost.h"
 #include "mozilla/layers/CompositorOGL.h"
+#include "EGLImageHelpers.h"
 #include "GLContextUtils.h"
 
 namespace mozilla {
 namespace layers {
 
 using namespace android;
 
 static gfx::SurfaceFormat
@@ -90,16 +91,17 @@ TextureTargetForAndroidPixelFormat(andro
 
 GrallocTextureSourceOGL::GrallocTextureSourceOGL(CompositorOGL* aCompositor,
                                                  android::GraphicBuffer* aGraphicBuffer,
                                                  gfx::SurfaceFormat aFormat)
   : mCompositor(aCompositor)
   , mGraphicBuffer(aGraphicBuffer)
   , mEGLImage(0)
   , mFormat(aFormat)
+  , mNeedsReset(true)
 {
   MOZ_ASSERT(mGraphicBuffer.get());
 }
 
 GrallocTextureSourceOGL::~GrallocTextureSourceOGL()
 {
   DeallocateDeviceData();
   mCompositor = nullptr;
@@ -107,17 +109,17 @@ GrallocTextureSourceOGL::~GrallocTexture
 
 void GrallocTextureSourceOGL::BindTexture(GLenum aTextureUnit)
 {
   /*
    * The job of this function is to ensure that the texture is tied to the
    * android::GraphicBuffer, so that texturing will source the GraphicBuffer.
    *
    * To this effect we create an EGLImage wrapping this GraphicBuffer,
-   * using CreateEGLImageForNativeBuffer, and then we tie this EGLImage to our
+   * using EGLImageCreateFromNativeBuffer, and then we tie this EGLImage to our
    * texture using fEGLImageTargetTexture2D.
    */
   MOZ_ASSERT(gl());
   gl()->MakeCurrent();
 
   GLuint tex = GetGLTexture();
   GLuint textureTarget = GetTextureTarget();
 
@@ -164,34 +166,43 @@ GrallocTextureSourceOGL::GetFormat() con
     return gfx::FORMAT_R8G8B8A8;
   }
   return mFormat;
 }
 
 void
 GrallocTextureSourceOGL::SetCompositableBackendSpecificData(CompositableBackendSpecificData* aBackendData)
 {
+  if (mCompositableBackendData != aBackendData) {
+    mNeedsReset = true;
+  }
+
+  if (!mNeedsReset) {
+    return;
+  }
+
   mCompositableBackendData = aBackendData;
 
   if (!mCompositor) {
     return;
   }
 
   // delete old EGLImage
   DeallocateDeviceData();
 
   gl()->MakeCurrent();
   GLuint tex = GetGLTexture();
   GLuint textureTarget = GetTextureTarget();
 
   gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
   gl()->fBindTexture(textureTarget, tex);
   // create new EGLImage
-  mEGLImage = gl()->CreateEGLImageForNativeBuffer(mGraphicBuffer->getNativeBuffer());
+  mEGLImage = EGLImageCreateFromNativeBuffer(gl(), mGraphicBuffer->getNativeBuffer());
   gl()->fEGLImageTargetTexture2D(textureTarget, mEGLImage);
+  mNeedsReset = false;
 }
 
 gfx::IntSize
 GrallocTextureSourceOGL::GetSize() const
 {
   if (!IsValid()) {
     NS_WARNING("Trying to access the size of an invalid GrallocTextureSourceOGL");
     return gfx::IntSize(0, 0);
@@ -200,25 +211,24 @@ GrallocTextureSourceOGL::GetSize() const
 }
 
 void
 GrallocTextureSourceOGL::DeallocateDeviceData()
 {
   if (mEGLImage) {
     MOZ_ASSERT(gl());
     gl()->MakeCurrent();
-    gl()->DestroyEGLImage(mEGLImage);
-    mEGLImage = 0;
+    EGLImageDestroy(gl(), mEGLImage);
+    mEGLImage = EGL_NO_IMAGE;
   }
 }
 
-GrallocTextureHostOGL::GrallocTextureHostOGL(uint64_t aID,
-                                             TextureFlags aFlags,
+GrallocTextureHostOGL::GrallocTextureHostOGL(TextureFlags aFlags,
                                              const NewSurfaceDescriptorGralloc& aDescriptor)
-  : TextureHost(aID, aFlags)
+  : TextureHost(aFlags)
 {
   mGrallocActor =
     static_cast<GrallocBufferActor*>(aDescriptor.bufferParent());
 
   android::GraphicBuffer* graphicBuffer = mGrallocActor->GetGraphicBuffer();
 
   mSize = aDescriptor.size();
   gfx::SurfaceFormat format =
@@ -269,16 +279,24 @@ GrallocTextureHostOGL::DeallocateSharedD
 {
   if (mTextureSource) {
     mTextureSource->ForgetBuffer();
   }
   PGrallocBufferParent::Send__delete__(mGrallocActor);
 }
 
 void
+GrallocTextureHostOGL::ForgetSharedData()
+{
+  if (mTextureSource) {
+    mTextureSource->ForgetBuffer();
+  }
+}
+
+void
 GrallocTextureHostOGL::DeallocateDeviceData()
 {
   mTextureSource->DeallocateDeviceData();
 }
 
 LayerRenderState
 GrallocTextureHostOGL::GetRenderState()
 {
@@ -308,17 +326,17 @@ TemporaryRef<gfx::DataSourceSurface>
 GrallocTextureSourceOGL::GetAsSurface() {
   MOZ_ASSERT(gl());
   gl()->MakeCurrent();
 
   GLuint tex = GetGLTexture();
   gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
   gl()->fBindTexture(GetTextureTarget(), tex);
   if (!mEGLImage) {
-    mEGLImage = gl()->CreateEGLImageForNativeBuffer(mGraphicBuffer->getNativeBuffer());
+    mEGLImage = EGLImageCreateFromNativeBuffer(gl(), mGraphicBuffer->getNativeBuffer());
   }
   gl()->fEGLImageTargetTexture2D(GetTextureTarget(), mEGLImage);
 
   RefPtr<gfx::DataSourceSurface> surf =
     IsValid() ? ReadBackSurface(gl(), tex, false, GetFormat())
               : nullptr;
 
   gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
--- a/gfx/layers/opengl/GrallocTextureHost.h
+++ b/gfx/layers/opengl/GrallocTextureHost.h
@@ -27,18 +27,16 @@ public:
                           gfx::SurfaceFormat aFormat);
 
   virtual ~GrallocTextureSourceOGL();
 
   virtual bool IsValid() const MOZ_OVERRIDE;
 
   virtual void BindTexture(GLenum aTextureUnit) MOZ_OVERRIDE;
 
-  virtual void UnbindTexture() MOZ_OVERRIDE {}
-
   virtual gfx::IntSize GetSize() const MOZ_OVERRIDE;
 
   virtual TextureSourceOGL* AsSourceOGL() MOZ_OVERRIDE { return this; }
 
   virtual GLenum GetTextureTarget() const MOZ_OVERRIDE;
 
   virtual gfx::SurfaceFormat GetFormat() const MOZ_OVERRIDE;
 
@@ -64,38 +62,40 @@ public:
 
   GLuint GetGLTexture();
 
 protected:
   CompositorOGL* mCompositor;
   android::sp<android::GraphicBuffer> mGraphicBuffer;
   EGLImage mEGLImage;
   gfx::SurfaceFormat mFormat;
+  bool mNeedsReset;
 };
 
 class GrallocTextureHostOGL : public TextureHost
 {
   friend class GrallocBufferActor;
 public:
-  GrallocTextureHostOGL(uint64_t aID,
-                        TextureFlags aFlags,
+  GrallocTextureHostOGL(TextureFlags aFlags,
                         const NewSurfaceDescriptorGralloc& aDescriptor);
 
   virtual ~GrallocTextureHostOGL();
 
   virtual void Updated(const nsIntRegion* aRegion) MOZ_OVERRIDE {}
 
   virtual bool Lock() MOZ_OVERRIDE;
 
   virtual void Unlock() MOZ_OVERRIDE;
 
   virtual void SetCompositor(Compositor* aCompositor) MOZ_OVERRIDE;
 
   virtual void DeallocateSharedData() MOZ_OVERRIDE;
 
+  virtual void ForgetSharedData() MOZ_OVERRIDE;
+
   virtual void DeallocateDeviceData() MOZ_OVERRIDE;
 
   virtual gfx::SurfaceFormat GetFormat() const;
 
   virtual gfx::IntSize GetSize() const MOZ_OVERRIDE { return mSize; }
 
   virtual LayerRenderState GetRenderState() MOZ_OVERRIDE;
 
--- a/gfx/layers/opengl/MacIOSurfaceTextureHostOGL.cpp
+++ b/gfx/layers/opengl/MacIOSurfaceTextureHostOGL.cpp
@@ -29,20 +29,19 @@ MacIOSurfaceTextureSourceOGL::GetSize() 
 }
 
 gfx::SurfaceFormat
 MacIOSurfaceTextureSourceOGL::GetFormat() const
 {
   return mSurface->HasAlpha() ? gfx::FORMAT_R8G8B8A8 : gfx::FORMAT_B8G8R8X8;
 }
 
-MacIOSurfaceTextureHostOGL::MacIOSurfaceTextureHostOGL(uint64_t aID,
-                                                       TextureFlags aFlags,
+MacIOSurfaceTextureHostOGL::MacIOSurfaceTextureHostOGL(TextureFlags aFlags,
                                                        const SurfaceDescriptorMacIOSurface& aDescriptor)
-  : TextureHost(aID, aFlags)
+  : TextureHost(aFlags)
 {
   mSurface = MacIOSurface::LookupSurface(aDescriptor.surface(),
                                          aDescriptor.scaleFactor(),
                                          aDescriptor.hasAlpha());
 }
 
 bool
 MacIOSurfaceTextureHostOGL::Lock()
--- a/gfx/layers/opengl/MacIOSurfaceTextureHostOGL.h
+++ b/gfx/layers/opengl/MacIOSurfaceTextureHostOGL.h
@@ -36,18 +36,16 @@ public:
   virtual gfx::IntSize GetSize() const MOZ_OVERRIDE;
 
   virtual gfx::SurfaceFormat GetFormat() const MOZ_OVERRIDE;
 
   virtual GLenum GetTextureTarget() const { return LOCAL_GL_TEXTURE_RECTANGLE_ARB; }
 
   virtual GLenum GetWrapMode() const MOZ_OVERRIDE { return LOCAL_GL_CLAMP_TO_EDGE; }
 
-  virtual void UnbindTexture() MOZ_OVERRIDE {}
-
   // MacIOSurfaceTextureSourceOGL doesn't own any gl texture
   virtual void DeallocateDeviceData() {}
 
   void SetCompositor(CompositorOGL* aCompositor) {
     mCompositor = aCompositor;
   }
 
   gl::GLContext* gl() const;
@@ -60,18 +58,17 @@ protected:
 /**
  * A TextureHost for shared MacIOSurface
  *
  * Most of the logic actually happens in MacIOSurfaceTextureSourceOGL.
  */
 class MacIOSurfaceTextureHostOGL : public TextureHost
 {
 public:
-  MacIOSurfaceTextureHostOGL(uint64_t aID,
-                             TextureFlags aFlags,
+  MacIOSurfaceTextureHostOGL(TextureFlags aFlags,
                              const SurfaceDescriptorMacIOSurface& aDescriptor);
 
   // SharedTextureHostOGL doesn't own any GL texture
   virtual void DeallocateDeviceData() MOZ_OVERRIDE {}
 
   virtual void SetCompositor(Compositor* aCompositor) MOZ_OVERRIDE;
 
   virtual bool Lock() MOZ_OVERRIDE;
@@ -100,9 +97,9 @@ protected:
   CompositorOGL* mCompositor;
   RefPtr<MacIOSurfaceTextureSourceOGL> mTextureSource;
   RefPtr<MacIOSurface> mSurface;
 };
 
 }
 }
 
-#endif // MOZILLA_GFX_MACIOSURFACETEXTUREHOSTOGL_H
\ No newline at end of file
+#endif // MOZILLA_GFX_MACIOSURFACETEXTUREHOSTOGL_H
--- a/gfx/layers/opengl/TextureHostOGL.cpp
+++ b/gfx/layers/opengl/TextureHostOGL.cpp
@@ -19,16 +19,17 @@
 #include "gfxPoint.h"                   // for gfxIntSize
 #include "gfxReusableSurfaceWrapper.h"  // for gfxReusableSurfaceWrapper
 #include "ipc/AutoOpenSurface.h"        // for AutoOpenSurface
 #include "mozilla/gfx/2D.h"             // for DataSourceSurface
 #include "mozilla/gfx/BaseSize.h"       // for BaseSize
 #include "mozilla/layers/CompositorOGL.h"  // for CompositorOGL
 #ifdef MOZ_WIDGET_GONK
 # include "GrallocImages.h"  // for GrallocImage
+# include "EGLImageHelpers.h"
 #endif
 #include "mozilla/layers/ISurfaceAllocator.h"
 #include "mozilla/layers/YCbCrImageDataSerializer.h"
 #include "mozilla/layers/GrallocTextureHost.h"
 #include "nsPoint.h"                    // for nsIntPoint
 #include "nsRegion.h"                   // for nsIntRegion
 #include "GfxTexturesReporter.h"        // for GfxTexturesReporter
 #include "GLBlitTextureImageHelper.h"
@@ -39,17 +40,17 @@
 #include "GeckoProfiler.h"
 
 using namespace mozilla::gl;
 using namespace mozilla::gfx;
 
 namespace mozilla {
 namespace layers {
 
-class Compositor; 
+class Compositor;
 
 TemporaryRef<CompositableBackendSpecificData>
 CreateCompositableBackendSpecificDataOGL()
 {
 #ifdef MOZ_WIDGET_GONK
   return new CompositableDataGonkOGL();
 #else
   return nullptr;
@@ -82,51 +83,50 @@ 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,
+CreateTextureHostOGL(const SurfaceDescriptor& aDesc,
                      ISurfaceAllocator* aDeallocator,
                      TextureFlags aFlags)
 {
   RefPtr<TextureHost> result;
   switch (aDesc.type()) {
     case SurfaceDescriptor::TSurfaceDescriptorShmem:
     case SurfaceDescriptor::TSurfaceDescriptorMemory: {
-      result = CreateBackendIndependentTextureHost(aID, aDesc,
+      result = CreateBackendIndependentTextureHost(aDesc,
                                                    aDeallocator, aFlags);
       break;
     }
     case SurfaceDescriptor::TSharedTextureDescriptor: {
       const SharedTextureDescriptor& desc = aDesc.get_SharedTextureDescriptor();
-      result = new SharedTextureHostOGL(aID, aFlags,
+      result = new SharedTextureHostOGL(aFlags,
                                         desc.shareType(),
                                         desc.handle(),
                                         gfx::ToIntSize(desc.size()),
                                         desc.inverted());
       break;
     }
 #ifdef XP_MACOSX
     case SurfaceDescriptor::TSurfaceDescriptorMacIOSurface: {
       const SurfaceDescriptorMacIOSurface& desc =
         aDesc.get_SurfaceDescriptorMacIOSurface();
-      result = new MacIOSurfaceTextureHostOGL(aID, aFlags, desc);
+      result = new MacIOSurfaceTextureHostOGL(aFlags, desc);
       break;
     }
 #endif
 #ifdef MOZ_WIDGET_GONK
     case SurfaceDescriptor::TNewSurfaceDescriptorGralloc: {
       const NewSurfaceDescriptorGralloc& desc =
         aDesc.get_NewSurfaceDescriptorGralloc();
-      result = new GrallocTextureHostOGL(aID, aFlags, desc);
+      result = new GrallocTextureHostOGL(aFlags, desc);
       break;
     }
 #endif
     default: return nullptr;
   }
   return result.forget();
 }
 
@@ -371,23 +371,22 @@ SharedTextureSourceOGL::GetTextureTransf
   if (!GetSharedHandleDetails(gl(), mShareType, mSharedHandle, handleDetails)) {
     NS_WARNING("Could not get shared handle details");
     return gfx3DMatrix();
   }
 
   return handleDetails.mTextureTransform;
 }
 
-SharedTextureHostOGL::SharedTextureHostOGL(uint64_t aID,
-                                           TextureFlags aFlags,
+SharedTextureHostOGL::SharedTextureHostOGL(TextureFlags aFlags,
                                            gl::SharedTextureShareType aShareType,
                                            gl::SharedTextureHandle aSharedHandle,
                                            gfx::IntSize aSize,
                                            bool inverted)
-  : TextureHost(aID, aFlags)
+  : TextureHost(aFlags)
   , mSize(aSize)
   , mCompositor(nullptr)
   , mSharedHandle(aSharedHandle)
   , mShareType(aShareType)
 {
 }
 
 SharedTextureHostOGL::~SharedTextureHostOGL()
@@ -1151,19 +1150,19 @@ GrallocDeprecatedTextureHostOGL::GetForm
   }
 }
 
 void
 GrallocDeprecatedTextureHostOGL::DeleteTextures()
 {
   if (mEGLImage) {
     if (gl()->MakeCurrent()) {
-      gl()->DestroyEGLImage(mEGLImage);
+      EGLImageDestroy(gl(), mEGLImage);
     }
-    mEGLImage = 0;
+    mEGLImage = EGL_NO_IMAGE;
   }
 }
 
 // only used for hacky fix in gecko 23 for bug 862324
 static void
 AddDeprecatedTextureHostToGrallocBufferActor(DeprecatedTextureHost* aDeprecatedTextureHost, const SurfaceDescriptor* aSurfaceDescriptor)
 {
   if (aSurfaceDescriptor && IsSurfaceDescriptorValid(*aSurfaceDescriptor)) {
@@ -1209,17 +1208,17 @@ GrallocDeprecatedTextureHostOGL::SwapTex
   if (!gl()->MakeCurrent()) {
     return;
   }
   gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
   gl()->fBindTexture(mTextureTarget, tex);
   // create new EGLImage
   // create EGLImage during buffer swap could reduce the graphic driver's task
   // during rendering.
-  mEGLImage = gl()->CreateEGLImageForNativeBuffer(mGraphicBuffer->getNativeBuffer());
+  mEGLImage = EGLImageCreateFromNativeBuffer(gl(), mGraphicBuffer->getNativeBuffer());
   gl()->fEGLImageTargetTexture2D(mTextureTarget, mEGLImage);
 
 }
 
 gl::GLContext*
 GrallocDeprecatedTextureHostOGL::gl() const
 {
   return mCompositor ? mCompositor->gl() : nullptr;
@@ -1382,17 +1381,17 @@ TemporaryRef<gfx::DataSourceSurface>
 GrallocDeprecatedTextureHostOGL::GetAsSurface() {
   if (!gl()->MakeCurrent()) {
     return nullptr;
   }
   GLuint tex = GetGLTexture();
   gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
   gl()->fBindTexture(mTextureTarget, tex);
   if (!mEGLImage) {
-    mEGLImage = gl()->CreateEGLImageForNativeBuffer(mGraphicBuffer->getNativeBuffer());
+    mEGLImage = EGLImageCreateFromNativeBuffer(gl(), mGraphicBuffer->getNativeBuffer());
   }
   gl()->fEGLImageTargetTexture2D(mTextureTarget, mEGLImage);
 
   RefPtr<gfx::DataSourceSurface> surf =
     IsValid() ? ReadBackSurface(gl(), tex, false, GetFormat())
               : nullptr;
   return surf.forget();
 }
--- a/gfx/layers/opengl/TextureHostOGL.h
+++ b/gfx/layers/opengl/TextureHostOGL.h
@@ -122,18 +122,16 @@ GetProgramTypeForTexture(const Deprecate
  */
 class TextureSourceOGL
 {
 public:
   virtual bool IsValid() const = 0;
 
   virtual void BindTexture(GLenum aTextureUnit) = 0;
 
-  virtual void UnbindTexture() = 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;
 
@@ -182,21 +180,16 @@ public:
   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 UnbindTexture() MOZ_OVERRIDE
-  {
-    mTexImage->ReleaseTexture();
-  }
-
   virtual GLenum GetWrapMode() const MOZ_OVERRIDE
   {
     return mTexImage->GetWrapMode();
   }
 
   // TileIterator
 
   virtual TileIterator* AsTileIterator() MOZ_OVERRIDE { return this; }
@@ -264,18 +257,16 @@ public:
   virtual gfx::SurfaceFormat GetFormat() const MOZ_OVERRIDE { return mFormat; }
 
   virtual gfx3DMatrix GetTextureTransform() MOZ_OVERRIDE;
 
   virtual GLenum GetTextureTarget() const { return mTextureTarget; }
 
   virtual GLenum GetWrapMode() const MOZ_OVERRIDE { return mWrapMode; }
 
-  virtual void UnbindTexture() MOZ_OVERRIDE {}
-
   // SharedTextureSource doesn't own any gl texture
   virtual void DeallocateDeviceData() {}
 
   void DetachSharedHandle();
 
   void SetCompositor(CompositorOGL* aCompositor);
 
   gl::GLContext* gl() const;
@@ -293,18 +284,17 @@ protected:
 /**
  * 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,
+  SharedTextureHostOGL(TextureFlags aFlags,
                        gl::SharedTextureShareType aShareType,
                        gl::SharedTextureHandle aSharedhandle,
                        gfx::IntSize aSize,
                        bool inverted);
 
   virtual ~SharedTextureHostOGL();
 
   // SharedTextureHostOGL doesn't own any GL texture
@@ -402,21 +392,16 @@ public:
   virtual TemporaryRef<gfx::DataSourceSurface> GetAsSurface() MOZ_OVERRIDE;
 
   // textureSource
   void BindTexture(GLenum aTextureUnit) MOZ_OVERRIDE
   {
     mTexture->BindTexture(aTextureUnit);
   }
 
-  void UnbindTexture() MOZ_OVERRIDE
-  {
-    mTexture->ReleaseTexture();
-  }
-
   gfx::IntSize GetSize() const MOZ_OVERRIDE;
 
   GLenum GetWrapMode() const MOZ_OVERRIDE
   {
     return mTexture->GetWrapMode();
   }
 
   gl::TextureImage* GetTextureImage()
@@ -524,20 +509,16 @@ public:
       return this;
     }
     nsRefPtr<gl::TextureImage> mTexImage;
 
     void BindTexture(GLenum aUnit) MOZ_OVERRIDE
     {
       mTexImage->BindTexture(aUnit);
     }
-    void UnbindTexture() MOZ_OVERRIDE
-    {
-      mTexImage->ReleaseTexture();
-    }
     virtual bool IsValid() const MOZ_OVERRIDE
     {
       return !!mTexImage;
     }
     virtual gfx::IntSize GetSize() const MOZ_OVERRIDE
     {
       return gfx::IntSize(mTexImage->GetSize().width, mTexImage->GetSize().height);
     }
@@ -646,17 +627,16 @@ public:
   }
 
   void BindTexture(GLenum activetex) MOZ_OVERRIDE
   {
     MOZ_ASSERT(mGL);
     // Lock already bound us!
     MOZ_ASSERT(activetex == LOCAL_GL_TEXTURE0);
   }
-  void UnbindTexture() MOZ_OVERRIDE {}
   GLuint GetTextureID() { return mTextureHandle; }
   ContentType GetContentType()
   {
     return (mFormat == gfx::FORMAT_B8G8R8A8) ?
              GFX_CONTENT_COLOR_ALPHA :
              GFX_CONTENT_COLOR;
   }
 
@@ -727,18 +707,16 @@ public:
 
   virtual GLenum GetTextureTarget() const MOZ_OVERRIDE
   {
     return mTextureTarget;
   }
 
   void BindTexture(GLenum activetex) MOZ_OVERRIDE;
 
-  void UnbindTexture() MOZ_OVERRIDE {}
-
   GLuint GetTextureID() { return mTextureHandle; }
   ContentType GetContentType() {
     return (mFormat == gfx::FORMAT_B8G8R8A8) ?
              GFX_CONTENT_COLOR_ALPHA :
              GFX_CONTENT_COLOR;
   }
 
   virtual TemporaryRef<gfx::DataSourceSurface> GetAsSurface() MOZ_OVERRIDE;
@@ -788,17 +766,16 @@ public:
   {
     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);
-  virtual void UnbindTexture() MOZ_OVERRIDE {}
   virtual gfx::IntSize GetSize() const MOZ_OVERRIDE
   {
     return mSize;
   }
 
   virtual void SwapTexturesImpl(const SurfaceDescriptor& aImage,
                                 nsIntRegion* aRegion = nullptr)
   { MOZ_ASSERT(false, "Tiles should not use this path"); }
@@ -871,17 +848,16 @@ public:
 
   bool IsValid() const MOZ_OVERRIDE;
 
   virtual TemporaryRef<gfx::DataSourceSurface> GetAsSurface() MOZ_OVERRIDE;
 
   virtual const char* Name() { return "GrallocDeprecatedTextureHostOGL"; }
 
   void BindTexture(GLenum aTextureUnit) MOZ_OVERRIDE;
-  void UnbindTexture() MOZ_OVERRIDE {}
 
   virtual TextureSourceOGL* AsSourceOGL() MOZ_OVERRIDE
   {
     return this;
   }
 
   // only overridden for hacky fix in gecko 23 for bug 862324
   // see bug 865908 about fixing this.
--- a/gfx/tests/gtest/TestTextures.cpp
+++ b/gfx/tests/gtest/TestTextures.cpp
@@ -114,45 +114,39 @@ void TestTextureClientSurface(TextureCli
   nsRefPtr<gfxASurface> aSurface = client->GetAsSurface();
   nsRefPtr<gfxImageSurface> clientSurface = aSurface->GetAsImageSurface();
 
   ASSERT_TRUE(texture->Lock(OPEN_READ_ONLY));
   AssertSurfacesEqual(surface, clientSurface);
   texture->Unlock();
 
   // client serialization
-  texture->SetID(1);
   SurfaceDescriptor descriptor;
   ASSERT_TRUE(texture->ToSurfaceDescriptor(descriptor));
 
   ASSERT_NE(descriptor.type(), SurfaceDescriptor::Tnull_t);
 
   // host deserialization
-  RefPtr<TextureHost> host = CreateBackendIndependentTextureHost(texture->GetID(),
-                                                                 descriptor, nullptr,
+  RefPtr<TextureHost> host = CreateBackendIndependentTextureHost(descriptor, nullptr,
                                                                  texture->GetFlags());
 
   ASSERT_TRUE(host.get() != nullptr);
   ASSERT_EQ(host->GetFlags(), texture->GetFlags());
-  ASSERT_EQ(host->GetID(), texture->GetID());
 
   // host read
   ASSERT_TRUE(host->Lock());
   RefPtr<mozilla::gfx::DataSourceSurface> hostDataSurface = host->GetAsSurface();
   host->Unlock();
 
   nsRefPtr<gfxImageSurface> hostSurface =
     new gfxImageSurface(hostDataSurface->GetData(),
                         ThebesIntSize(hostDataSurface->GetSize()),
                         hostDataSurface->Stride(),
                         SurfaceFormatToImageFormat(hostDataSurface->GetFormat()));
   AssertSurfacesEqual(surface, hostSurface.get());
-
-  // host deallocation
-  host->DeallocateSharedData();
 }
 
 // Same as above, for YCbCr surfaces
 void TestTextureClientYCbCr(TextureClient* client, PlanarYCbCrData& ycbcrData) {
 
   // client allocation
   ASSERT_TRUE(client->AsTextureClientYCbCr() != nullptr);
   TextureClientYCbCr* texture = client->AsTextureClientYCbCr();
@@ -163,32 +157,29 @@ void TestTextureClientYCbCr(TextureClien
 
   // client painting
   texture->UpdateYCbCr(ycbcrData);
 
   ASSERT_TRUE(client->Lock(OPEN_READ_ONLY));
   client->Unlock();
 
   // client serialization
-  client->SetID(1);
   SurfaceDescriptor descriptor;
   ASSERT_TRUE(client->ToSurfaceDescriptor(descriptor));
 
   ASSERT_NE(descriptor.type(), SurfaceDescriptor::Tnull_t);
 
   // host deserialization
-  RefPtr<TextureHost> textureHost = CreateBackendIndependentTextureHost(client->GetID(),
-                                                                        descriptor, nullptr,
+  RefPtr<TextureHost> textureHost = CreateBackendIndependentTextureHost(descriptor, nullptr,
                                                                         client->GetFlags());
 
   RefPtr<BufferTextureHost> host = static_cast<BufferTextureHost*>(textureHost.get());
 
   ASSERT_TRUE(host.get() != nullptr);
   ASSERT_EQ(host->GetFlags(), client->GetFlags());
-  ASSERT_EQ(host->GetID(), client->GetID());
 
   // This will work iff the compositor is not BasicCompositor
   ASSERT_EQ(host->GetFormat(), mozilla::gfx::FORMAT_YUV);
 
   // host read
   ASSERT_TRUE(host->Lock());
 
   ASSERT_TRUE(host->GetFormat() == mozilla::gfx::FORMAT_YUV);
@@ -208,19 +199,16 @@ void TestTextureClientYCbCr(TextureClien
   data.mCbSkip = 0;
   data.mCrSkip = 0;
   data.mPicSize = data.mYSize;
   data.mPicX = 0;
   data.mPicY = 0;
 
   AssertYCbCrSurfacesEqual(&ycbcrData, &data);
   host->Unlock();
-
-  // host deallocation
-  host->DeallocateSharedData();
 }
 
 TEST(Layers, TextureSerialization) {
   // the test is run on all the following image formats
   gfxImageFormat formats[3] = {
     gfxImageFormatARGB32,
     gfxImageFormatRGB24,
     gfxImageFormatA8,
@@ -229,17 +217,17 @@ TEST(Layers, TextureSerialization) {
   for (int f = 0; f < 3; ++f) {
     RefPtr<gfxImageSurface> surface = new gfxImageSurface(gfxIntSize(400,300), formats[f]);
     SetupSurface(surface.get());
     AssertSurfacesEqual(surface, surface);
 
     RefPtr<TextureClient> client
       = new MemoryTextureClient(nullptr,
                                 mozilla::gfx::ImageFormatToSurfaceFormat(surface->Format()),
-                                TEXTURE_FLAGS_DEFAULT);
+                                TEXTURE_DEALLOCATE_CLIENT);
 
     TestTextureClientSurface(client, surface);
 
     // XXX - Test more texture client types.
   }
 }
 
 TEST(Layers, TextureYCbCrSerialization) {
@@ -265,14 +253,14 @@ TEST(Layers, TextureYCbCrSerialization) 
   clientData.mCrSkip = 0;
   clientData.mCrSkip = 0;
   clientData.mPicX = 0;
   clientData.mPicX = 0;
 
   RefPtr<TextureClient> client
     = new MemoryTextureClient(nullptr,
                               mozilla::gfx::FORMAT_YUV,
-                              TEXTURE_FLAGS_DEFAULT);
+                              TEXTURE_DEALLOCATE_CLIENT);
 
   TestTextureClientYCbCr(client, clientData);
 
   // XXX - Test more texture client types.
 }
--- a/layout/base/ActiveLayerTracker.cpp
+++ b/layout/base/ActiveLayerTracker.cpp
@@ -5,16 +5,18 @@
 #include "ActiveLayerTracker.h"
 
 #include "nsExpirationTracker.h"
 #include "nsIFrame.h"
 #include "nsIContent.h"
 #include "nsRefreshDriver.h"
 #include "nsPIDOMWindow.h"
 #include "nsIDocument.h"
+#include "nsAnimationManager.h"
+#include "nsTransitionManager.h"
 
 namespace mozilla {
 
 /**
  * This tracks the state of a frame that may need active layers due to
  * ongoing content changes or style changes that indicate animation.
  *
  * When no changes of *any* kind are detected after 75-100ms we remove this
@@ -210,16 +212,28 @@ ActiveLayerTracker::IsStyleAnimated(nsIF
   if (layerActivity) {
     if (layerActivity->RestyleCountForProperty(aProperty) >= 2) {
       return true;
     }
   }
   if (aProperty == eCSSProperty_transform && aFrame->Preserves3D()) {
     return IsStyleAnimated(aFrame->GetParent(), aProperty);
   }
+  nsIContent* content = aFrame->GetContent();
+  if (content) {
+    if (mozilla::HasAnimationOrTransition<ElementAnimations>(
+          content, nsGkAtoms::animationsProperty, aProperty)) {
+      return true;
+    }
+    if (mozilla::HasAnimationOrTransition<ElementTransitions>(
+          content, nsGkAtoms::transitionsProperty, aProperty)) {
+      return true;
+    }
+  }
+
   return false;
 }
 
 /* static */ bool
 ActiveLayerTracker::IsOffsetOrMarginStyleAnimated(nsIFrame* aFrame)
 {
   LayerActivity* layerActivity = GetLayerActivity(aFrame);
   if (layerActivity) {
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -225,33 +225,44 @@ nsLayoutUtils::HasAnimationsForComposito
     return false;
   return HasAnimationOrTransitionForCompositor<ElementAnimations>
             (aContent, nsGkAtoms::animationsProperty, aProperty) ||
          HasAnimationOrTransitionForCompositor<ElementTransitions>
             (aContent, nsGkAtoms::transitionsProperty, aProperty);
 }
 
 template <class AnimationsOrTransitions>
-static AnimationsOrTransitions*
-HasAnimationOrTransition(nsIContent* aContent,
+AnimationsOrTransitions*
+mozilla::HasAnimationOrTransition(nsIContent* aContent,
                          nsIAtom* aAnimationProperty,
                          nsCSSProperty aProperty)
 {
   AnimationsOrTransitions* animations =
     static_cast<AnimationsOrTransitions*>(aContent->GetProperty(aAnimationProperty));
   if (animations) {
     bool propertyMatches = animations->HasAnimationOfProperty(aProperty);
     if (propertyMatches) {
       return animations;
     }
   }
 
   return nullptr;
 }
 
+template ElementAnimations*
+mozilla::HasAnimationOrTransition<ElementAnimations>(nsIContent* aContent,
+                         nsIAtom* aAnimationProperty,
+                         nsCSSProperty aProperty);
+
+template ElementTransitions*
+mozilla::HasAnimationOrTransition<ElementTransitions>(nsIContent* aContent,
+                         nsIAtom* aAnimationProperty,
+                         nsCSSProperty aProperty);
+
+
 bool
 nsLayoutUtils::HasAnimations(nsIContent* aContent,
                              nsCSSProperty aProperty)
 {
   if (!aContent->MayHaveAnimations())
     return false;
   return HasAnimationOrTransition<ElementAnimations>
             (aContent, nsGkAtoms::animationsProperty, aProperty) ||
--- a/layout/base/nsLayoutUtils.h
+++ b/layout/base/nsLayoutUtils.h
@@ -65,16 +65,22 @@ class DOMRectList;
 class Element;
 class HTMLImageElement;
 class HTMLCanvasElement;
 class HTMLVideoElement;
 } // namespace dom
 namespace layers {
 class Layer;
 }
+
+template <class AnimationsOrTransitions>
+extern AnimationsOrTransitions* HasAnimationOrTransition(nsIContent* aContent,
+                                                         nsIAtom* aAnimationProperty,
+                                                         nsCSSProperty aProperty);
+
 } // namespace mozilla
 
 /**
  * nsLayoutUtils is a namespace class used for various helper
  * functions that are useful in multiple places in layout.  The goal
  * is not to define multiple copies of the same static helper.
  */
 class nsLayoutUtils
--- a/python/mozbuild/mozbuild/backend/base.py
+++ b/python/mozbuild/mozbuild/backend/base.py
@@ -61,46 +61,58 @@ class BackendConsumeSummary(object):
 
         # CPU time spent by during the interval captured by wall_time.
         self.cpu_time = 0.0
 
         # The total wall time spent executing moz.build files. This is just
         # the read and execute time. It does not cover consume time.
         self.mozbuild_execution_time = 0.0
 
+        # The total wall time spent emitting objects from sandboxes.
+        self.emitter_execution_time = 0.0
+
         # The total wall time spent in the backend. This counts the time the
         # backend writes out files, etc.
         self.backend_execution_time = 0.0
 
         # How much wall time the system spent doing other things. This is
-        # wall_time - mozbuild_execution_time - backend_execution_time.
+        # wall_time - mozbuild_execution_time - emitter_execution_time -
+        # backend_execution_time.
         self.other_time = 0.0
 
     @property
     def reader_summary(self):
-        return 'Finished reading {:d} moz.build files into {:d} descriptors in {:.2f}s'.format(
-            self.mozbuild_count, self.object_count,
+        return 'Finished reading {:d} moz.build files in {:.2f}s'.format(
+            self.mozbuild_count,
             self.mozbuild_execution_time)
 
     @property
+    def emitter_summary(self):
+        return 'Processed into {:d} build config descriptors in {:.2f}s'.format(
+            self.object_count, self.emitter_execution_time)
+
+    @property
     def backend_summary(self):
         return 'Backend executed in {:.2f}s'.format(self.backend_execution_time)
 
     def backend_detailed_summary(self):
         """Backend summary to be supplied by BuildBackend implementations."""
         return None
 
     @property
     def total_summary(self):
         efficiency_value = self.cpu_time / self.wall_time if self.wall_time else 100
-        return 'Total wall time: {:.2f}s; CPU time: {:.2f}s; Efficiency: {:.0%}'.format(
-            self.wall_time, self.cpu_time, efficiency_value)
+        return 'Total wall time: {:.2f}s; CPU time: {:.2f}s; Efficiency: ' \
+            '{:.0%}; Untracked: {:.2f}s'.format(
+                self.wall_time, self.cpu_time, efficiency_value,
+                self.other_time)
 
     def summaries(self):
         yield self.reader_summary
+        yield self.emitter_summary
         yield self.backend_summary
 
         detailed = self.backend_detailed_summary()
         if detailed:
             yield detailed
 
         yield self.total_summary
 
@@ -192,17 +204,18 @@ class BuildBackend(LoggingMixin):
             self.consume_object(obj)
             backend_time += time.time() - obj_start
 
             if isinstance(obj, SandboxDerived):
                 self.backend_input_files |= obj.sandbox_all_paths
 
             if isinstance(obj, ReaderSummary):
                 self.summary.mozbuild_count = obj.total_file_count
-                self.summary.mozbuild_execution_time = obj.total_execution_time
+                self.summary.mozbuild_execution_time = obj.total_sandbox_execution_time
+                self.summary.emitter_execution_time = obj.total_emitter_execution_time
 
         finished_start = time.time()
         self.consume_finished()
         backend_time += time.time() - finished_start
 
         # Purge backend files created in previous run, but not created anymore
         delete_files = self._backend_output_list - self._backend_output_files
         for path in delete_files:
@@ -227,16 +240,17 @@ class BuildBackend(LoggingMixin):
             with open(self._backend_output_list_file, 'a'):
                 os.utime(self._backend_output_list_file, None)
 
         self.summary.cpu_time = time.clock() - cpu_start
         self.summary.wall_time = time.time() - time_start
         self.summary.backend_execution_time = backend_time
         self.summary.other_time = self.summary.wall_time - \
             self.summary.mozbuild_execution_time - \
+            self.summary.emitter_execution_time - \
             self.summary.backend_execution_time
 
         return self.summary
 
     @abstractmethod
     def consume_object(self, obj):
         """Consumes an individual TreeMetadata instance.
 
--- a/python/mozbuild/mozbuild/frontend/data.py
+++ b/python/mozbuild/mozbuild/frontend/data.py
@@ -36,20 +36,22 @@ class TreeMetadata(object):
 
     def ack(self):
         self._ack = True
 
 
 class ReaderSummary(TreeMetadata):
     """A summary of what the reader did."""
 
-    def __init__(self, total_file_count, total_execution_time):
+    def __init__(self, total_file_count, total_sandbox_execution_time,
+        total_emitter_execution_time):
         TreeMetadata.__init__(self)
         self.total_file_count = total_file_count
-        self.total_execution_time = total_execution_time
+        self.total_sandbox_execution_time = total_sandbox_execution_time
+        self.total_emitter_execution_time = total_emitter_execution_time
 
 
 class SandboxDerived(TreeMetadata):
     """Build object derived from a single MozbuildSandbox instance.
 
     It holds fields common to all sandboxes. This class is likely never
     instantiated directly but is instead derived from.
     """
--- a/python/mozbuild/mozbuild/frontend/emitter.py
+++ b/python/mozbuild/mozbuild/frontend/emitter.py
@@ -4,16 +4,17 @@
 
 from __future__ import unicode_literals
 
 import json
 import logging
 import os
 import traceback
 import sys
+import time
 
 from mach.mixin.logging import LoggingMixin
 
 import mozpack.path as mozpath
 import manifestparser
 
 from .data import (
     ConfigFileSubstitution,
@@ -74,36 +75,54 @@ class TreeMetadataEmitter(LoggingMixin):
 
     def emit(self, output):
         """Convert the BuildReader output into data structures.
 
         The return value from BuildReader.read_topsrcdir() (a generator) is
         typically fed into this function.
         """
         file_count = 0
-        execution_time = 0.0
+        sandbox_execution_time = 0.0
+        emitter_time = 0.0
         sandboxes = {}
 
+        def emit_objs(objs):
+            for o in objs:
+                yield o
+                if not o._ack:
+                    raise Exception('Unhandled object of type %s' % type(o))
+
         for out in output:
             if isinstance(out, MozbuildSandbox):
                 # Keep all sandboxes around, we will need them later.
                 sandboxes[out['OBJDIR']] = out
 
-                for o in self.emit_from_sandbox(out):
-                    yield o
-                    if not o._ack:
-                        raise Exception('Unhandled object of type %s' % type(o))
+                start = time.time()
+                # We need to expand the generator for the timings to work.
+                objs = list(self.emit_from_sandbox(out))
+                emitter_time += time.time() - start
+
+                for o in emit_objs(objs): yield o
 
                 # Update the stats.
                 file_count += len(out.all_paths)
-                execution_time += out.execution_time
+                sandbox_execution_time += out.execution_time
 
             else:
                 raise Exception('Unhandled output type: %s' % out)
 
+        start = time.time()
+        objs = list(self._emit_libs_derived(sandboxes))
+        emitter_time += time.time() - start
+
+        for o in emit_objs(objs): yield o
+
+        yield ReaderSummary(file_count, sandbox_execution_time, emitter_time)
+
+    def _emit_libs_derived(self, sandboxes):
         for objdir, libname, final_lib in self._final_libs:
             if final_lib not in self._libs:
                 raise Exception('FINAL_LIBRARY in %s (%s) does not match any '
                                 'LIBRARY_NAME' % (objdir, final_lib))
             libs = self._libs[final_lib]
             if len(libs) > 1:
                 raise Exception('FINAL_LIBRARY in %s (%s) matches a '
                                 'LIBRARY_NAME defined in multiple places (%s)' %
@@ -129,18 +148,16 @@ class TreeMetadataEmitter(LoggingMixin):
                 # (recursively), that its FINAL_LIBRARY is that root library.
                 if not libdef.refcount:
                     for p in recurse_libs(path, basename):
                         passthru = VariablePassthru(sandboxes[p])
                         passthru.variables['FINAL_LIBRARY'] = basename
                         yield passthru
                 yield libdef
 
-        yield ReaderSummary(file_count, execution_time)
-
     def emit_from_sandbox(self, sandbox):
         """Convert a MozbuildSandbox to tree metadata objects.
 
         This is a generator of mozbuild.frontend.data.SandboxDerived instances.
         """
         # We always emit a directory traversal descriptor. This is needed by
         # the recursive make backend.
         for o in self._emit_directory_traversal_from_sandbox(sandbox): yield o