Backed out 4 changesets (bug 991028) for nonunified bustage
authorPhil Ringnalda <philringnalda@gmail.com>
Sun, 06 Apr 2014 21:21:38 -0700
changeset 195725 2579095d0f7eedb18f807dce976d450f7d4b7fd6
parent 195724 7248b992c6b2111d7531b603bcb983424cf0d13c
child 195726 fe57c073f01974bf7ef58e2306d4bbe75a3a2f0b
push id3624
push userasasaki@mozilla.com
push dateMon, 09 Jun 2014 21:49:01 +0000
treeherdermozilla-beta@b1a5da15899a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs991028
milestone31.0a1
backs out147581a518c343e509531cb608567758868cc3bd
e5bacc566e58d5c74d0fd31e61335a13ba8676ee
6dc852777a4d92685e2d98d7a0505d36bb277700
780bec5571b950839d5f52e7a723fba48c23edc5
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
Backed out 4 changesets (bug 991028) for nonunified bustage CLOSED TREE Backed out changeset 147581a518c3 (bug 991028) Backed out changeset e5bacc566e58 (bug 991028) Backed out changeset 6dc852777a4d (bug 991028) Backed out changeset 780bec5571b9 (bug 991028)
content/media/omx/OMXCodecWrapper.cpp
content/media/webrtc/MediaEngineWebRTCVideo.cpp
gfx/layers/ImageDataSerializer.h
gfx/layers/basic/AutoMaskData.h
gfx/layers/basic/BasicCompositor.cpp
gfx/layers/basic/BasicImageLayer.cpp
gfx/layers/basic/BasicImplData.h
gfx/layers/basic/BasicLayersImpl.cpp
gfx/layers/basic/BasicLayersImpl.h
gfx/layers/client/ClientLayerManager.cpp
gfx/layers/client/ContentClient.cpp
gfx/layers/client/ContentClient.h
gfx/layers/composite/ContentHost.cpp
gfx/layers/composite/LayerManagerComposite.h
gfx/layers/composite/TextureHost.cpp
gfx/layers/d3d11/TextureD3D11.cpp
gfx/layers/d3d9/CanvasLayerD3D9.cpp
gfx/layers/d3d9/ImageLayerD3D9.cpp
gfx/layers/d3d9/TextureD3D9.cpp
gfx/layers/d3d9/ThebesLayerD3D9.cpp
gfx/layers/ipc/AutoOpenSurface.h
gfx/layers/ipc/CompositableForwarder.h
gfx/layers/ipc/CompositorParent.cpp
gfx/layers/ipc/ISurfaceAllocator.cpp
gfx/layers/ipc/ISurfaceAllocator.h
gfx/layers/ipc/ImageBridgeChild.h
gfx/layers/ipc/LayersSurfaces.ipdlh
gfx/layers/ipc/ShadowLayerUtilsD3D10.cpp
gfx/layers/ipc/ShadowLayerUtilsGralloc.cpp
gfx/layers/ipc/ShadowLayerUtilsGralloc.h
gfx/layers/ipc/ShadowLayerUtilsMac.cpp
gfx/layers/ipc/ShadowLayerUtilsX11.cpp
gfx/layers/ipc/ShadowLayers.cpp
gfx/layers/ipc/ShadowLayers.h
gfx/layers/opengl/GrallocTextureClient.cpp
gfx/layers/opengl/TextureHostOGL.cpp
media/webrtc/signaling/src/mediapipeline/MediaPipeline.cpp
--- a/content/media/omx/OMXCodecWrapper.cpp
+++ b/content/media/omx/OMXCodecWrapper.cpp
@@ -12,17 +12,16 @@
 #include <media/ICrypto.h>
 #include <media/IOMX.h>
 #include <OMX_Component.h>
 #include <stagefright/MediaDefs.h>
 #include <stagefright/MediaErrors.h>
 
 #include "AudioChannelFormat.h"
 #include <mozilla/Monitor.h>
-#include "mozilla/layers/GrallocTextureClient.h"
 
 using namespace mozilla;
 using namespace mozilla::gfx;
 using namespace mozilla::layers;
 
 #define ENCODER_CONFIG_BITRATE 2000000 // bps
 // How many seconds between I-frames.
 #define ENCODER_CONFIG_I_FRAME_INTERVAL 1
@@ -252,19 +251,19 @@ ConvertPlanarYCbCrToNV12(const PlanarYCb
 // conversion. Currently only 2 source format are supported:
 // - NV21/HAL_PIXEL_FORMAT_YCrCb_420_SP (from camera preview window).
 // - YV12/HAL_PIXEL_FORMAT_YV12 (from video decoder).
 static
 void
 ConvertGrallocImageToNV12(GrallocImage* aSource, uint8_t* aDestination)
 {
   // Get graphic buffer.
-  GrallocTextureClientOGL* client =
-    static_cast<GrallocTextureClientOGL*>(aSource->GetTextureClient(nullptr));
-  sp<GraphicBuffer> graphicBuffer = client->GetGraphicBuffer();
+  SurfaceDescriptor handle = aSource->GetSurfaceDescriptor();
+  SurfaceDescriptorGralloc gralloc = handle.get_SurfaceDescriptorGralloc();
+  sp<GraphicBuffer> graphicBuffer = GrallocBufferActor::GetFrom(gralloc);
 
   int pixelFormat = graphicBuffer->getPixelFormat();
   // Only support NV21 (from camera) or YV12 (from HW decoder output) for now.
   NS_ENSURE_TRUE_VOID(pixelFormat == HAL_PIXEL_FORMAT_YCrCb_420_SP ||
                       pixelFormat == HAL_PIXEL_FORMAT_YV12);
 
   void* imgPtr = nullptr;
   graphicBuffer->lock(GraphicBuffer::USAGE_SW_READ_MASK, &imgPtr);
--- a/content/media/webrtc/MediaEngineWebRTCVideo.cpp
+++ b/content/media/webrtc/MediaEngineWebRTCVideo.cpp
@@ -1,17 +1,16 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "MediaEngineWebRTC.h"
 #include "Layers.h"
 #include "ImageTypes.h"
 #include "ImageContainer.h"
-#include "mozilla/layers/GrallocTextureClient.h"
 #include "nsMemory.h"
 #include "mtransport/runnable_utils.h"
 
 #ifdef MOZ_B2G_CAMERA
 #include "GrallocImages.h"
 #include "libyuv.h"
 #include "mozilla/Hal.h"
 #include "ScreenOrientation.h"
@@ -649,19 +648,19 @@ MediaEngineWebRTCVideoSource::OnTakePict
                                                  static_cast<uint64_t>(aLength),
                                                  aMimeType));
   mCallbackMonitor.Notify();
 }
 
 void
 MediaEngineWebRTCVideoSource::RotateImage(layers::Image* aImage, uint32_t aWidth, uint32_t aHeight) {
   layers::GrallocImage *nativeImage = static_cast<layers::GrallocImage*>(aImage);
-  layers::GrallocTextureClientOGL* client =
-    static_cast<layers::GrallocTextureClientOGL*>(nativeImage->GetTextureClient(nullptr));
-  android::sp<android::GraphicBuffer> graphicBuffer = client->GetGraphicBuffer();
+  layers::SurfaceDescriptor handle = nativeImage->GetSurfaceDescriptor();
+  layers::SurfaceDescriptorGralloc grallocHandle = handle.get_SurfaceDescriptorGralloc();
+  android::sp<android::GraphicBuffer> graphicBuffer = layers::GrallocBufferActor::GetFrom(grallocHandle);
   void *pMem = nullptr;
   uint32_t size = aWidth * aHeight * 3 / 2;
 
   graphicBuffer->lock(android::GraphicBuffer::USAGE_SW_READ_MASK, &pMem);
 
   uint8_t* srcPtr = static_cast<uint8_t*>(pMem);
   // Create a video frame and append it to the track.
   nsRefPtr<layers::Image> image = mImageContainer->CreateImage(ImageFormat::PLANAR_YCBCR);
--- a/gfx/layers/ImageDataSerializer.h
+++ b/gfx/layers/ImageDataSerializer.h
@@ -84,15 +84,14 @@ public:
 class MOZ_STACK_CLASS ImageDataDeserializer : public ImageDataSerializerBase
 {
 public:
   ImageDataDeserializer(uint8_t* aData, size_t aDataSize)
     : ImageDataSerializerBase(aData, aDataSize)
   {
     Validate();
   }
-
 };
 
 } // namespace layers
 } // namespace mozilla
 
 #endif
--- a/gfx/layers/basic/AutoMaskData.h
+++ b/gfx/layers/basic/AutoMaskData.h
@@ -9,18 +9,22 @@
 #include "gfxASurface.h"
 #include "mozilla/layers/LayersSurfaces.h"  // for SurfaceDescriptor
 
 namespace mozilla {
 namespace layers {
 
 /**
  * Drawing with a mask requires a mask surface and a transform.
+ * Sometimes the mask surface is a direct gfxASurface, but other times
+ * it's a SurfaceDescriptor.  For SurfaceDescriptor, we need to use a
+ * scoped AutoOpenSurface to get a gfxASurface for the
+ * SurfaceDescriptor.
  *
- * This helper class manages the gfxASurface
+ * This helper class manages the gfxASurface-or-SurfaceDescriptor
  * logic.
  */
 class MOZ_STACK_CLASS AutoMaskData {
 public:
   AutoMaskData() { }
   ~AutoMaskData() { }
 
   /**
@@ -28,25 +32,29 @@ public:
    * SurfaceDescriptor.  Construct() must only be called once.
    * GetSurface() and GetTransform() must not be called until this has
    * been constructed.
    */
 
   void Construct(const gfx::Matrix& aTransform,
                  gfxASurface* aSurface);
 
+  void Construct(const gfx::Matrix& aTransform,
+                 const SurfaceDescriptor& aSurface);
+
   /** The returned surface can't escape the scope of |this|. */
   gfxASurface* GetSurface();
   const gfx::Matrix& GetTransform();
 
 private:
   bool IsConstructed();
 
   gfx::Matrix mTransform;
   nsRefPtr<gfxASurface> mSurface;
+  Maybe<AutoOpenSurface> mSurfaceOpener;
 
   AutoMaskData(const AutoMaskData&) MOZ_DELETE;
   AutoMaskData& operator=(const AutoMaskData&) MOZ_DELETE;
 };
 
 class MOZ_STACK_CLASS AutoMoz2DMaskData {
 public:
   AutoMoz2DMaskData() { }
--- a/gfx/layers/basic/BasicCompositor.cpp
+++ b/gfx/layers/basic/BasicCompositor.cpp
@@ -1,15 +1,16 @@
 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "BasicCompositor.h"
 #include "TextureHostBasic.h"
+#include "ipc/AutoOpenSurface.h"
 #include "mozilla/layers/Effects.h"
 #include "mozilla/layers/YCbCrImageDataSerializer.h"
 #include "nsIWidget.h"
 #include "gfx2DGlue.h"
 #include "mozilla/gfx/2D.h"
 #include "mozilla/gfx/Helpers.h"
 #include "gfxUtils.h"
 #include "YCbCrUtils.h"
--- a/gfx/layers/basic/BasicImageLayer.cpp
+++ b/gfx/layers/basic/BasicImageLayer.cpp
@@ -48,17 +48,18 @@ public:
   {
     NS_ASSERTION(BasicManager()->InConstruction(),
                  "Can only set properties in construction phase");
     ImageLayer::SetVisibleRegion(aRegion);
   }
 
   virtual void Paint(DrawTarget* aDT, Layer* aMaskLayer) MOZ_OVERRIDE;
 
-  virtual bool GetAsSurface(gfxASurface** aSurface);
+  virtual bool GetAsSurface(gfxASurface** aSurface,
+                            SurfaceDescriptor* aDescriptor);
   virtual TemporaryRef<SourceSurface> GetAsSourceSurface() MOZ_OVERRIDE;
 
 protected:
   BasicLayerManager* BasicManager()
   {
     return static_cast<BasicLayerManager*>(mManager);
   }
 
@@ -128,17 +129,18 @@ BasicImageLayer::GetAndPaintCurrentImage
 
     GetContainer()->NotifyPaintedImage(image);
   }
 
   mContainer->UnlockCurrentImage();
 }
 
 bool
-BasicImageLayer::GetAsSurface(gfxASurface** aSurface)
+BasicImageLayer::GetAsSurface(gfxASurface** aSurface,
+                              SurfaceDescriptor* aDescriptor)
 {
   if (!mContainer) {
     return false;
   }
 
   gfx::IntSize dontCare;
   nsRefPtr<gfxASurface> surface = mContainer->DeprecatedGetCurrentAsSurface(&dontCare);
   surface.forget(aSurface);
--- a/gfx/layers/basic/BasicImplData.h
+++ b/gfx/layers/basic/BasicImplData.h
@@ -112,17 +112,18 @@ public:
 
   /**
    * Return a surface for this layer. Will use an existing surface, if
    * possible, or may create a temporary surface.  Implement this
    * method for any layers that might be used as a mask.  Should only
    * return false if a surface cannot be created.  If true is
    * returned, only one of |aSurface| or |aDescriptor| is valid.
    */
-  virtual bool GetAsSurface(gfxASurface** aSurface)
+  virtual bool GetAsSurface(gfxASurface** aSurface,
+                            SurfaceDescriptor* aDescriptor)
   { return false; }
   virtual TemporaryRef<gfx::SourceSurface> GetAsSourceSurface() { return nullptr; }
 
   bool GetClipToVisibleRegion() { return mClipToVisibleRegion; }
   void SetClipToVisibleRegion(bool aClip) { mClipToVisibleRegion = aClip; }
 
   void SetDrawAtomically(bool aDrawAtomically) { mDrawAtomically = aDrawAtomically; }
 
--- a/gfx/layers/basic/BasicLayersImpl.cpp
+++ b/gfx/layers/basic/BasicLayersImpl.cpp
@@ -22,49 +22,66 @@ void
 AutoMaskData::Construct(const gfx::Matrix& aTransform,
                         gfxASurface* aSurface)
 {
   MOZ_ASSERT(!IsConstructed());
   mTransform = aTransform;
   mSurface = aSurface;
 }
 
+void
+AutoMaskData::Construct(const gfx::Matrix& aTransform,
+                        const SurfaceDescriptor& aSurface)
+{
+  MOZ_ASSERT(!IsConstructed());
+  mTransform = aTransform;
+  mSurfaceOpener.construct(OPEN_READ_ONLY, aSurface);
+}
+
 gfxASurface*
 AutoMaskData::GetSurface()
 {
   MOZ_ASSERT(IsConstructed());
-  return mSurface.get();
+  if (mSurface) {
+    return mSurface.get();
+  }
+  return mSurfaceOpener.ref().Get();
 }
 
 const gfx::Matrix&
 AutoMaskData::GetTransform()
 {
   MOZ_ASSERT(IsConstructed());
   return mTransform;
 }
 
 bool
 AutoMaskData::IsConstructed()
 {
-  return !!mSurface;
+  return !!mSurface || !mSurfaceOpener.empty();
 }
 
 bool
 GetMaskData(Layer* aMaskLayer, AutoMaskData* aMaskData)
 {
   if (aMaskLayer) {
     nsRefPtr<gfxASurface> surface;
+    SurfaceDescriptor descriptor;
     if (static_cast<BasicImplData*>(aMaskLayer->ImplData())
-        ->GetAsSurface(getter_AddRefs(surface)) &&
-        surface) {
+        ->GetAsSurface(getter_AddRefs(surface), &descriptor) &&
+        (surface || IsSurfaceDescriptorValid(descriptor))) {
       Matrix transform;
       Matrix4x4 effectiveTransform = aMaskLayer->GetEffectiveTransform();
       DebugOnly<bool> maskIs2D = effectiveTransform.CanDraw2D(&transform);
       NS_ASSERTION(maskIs2D, "How did we end up with a 3D transform here?!");
-      aMaskData->Construct(transform, surface);
+      if (surface) {
+        aMaskData->Construct(transform, surface);
+      } else {
+        aMaskData->Construct(transform, descriptor);
+      }
       return true;
     }
   }
   return false;
 }
 
 bool
 GetMaskData(Layer* aMaskLayer, AutoMoz2DMaskData* aMaskData)
--- a/gfx/layers/basic/BasicLayersImpl.h
+++ b/gfx/layers/basic/BasicLayersImpl.h
@@ -6,16 +6,17 @@
 #ifndef GFX_BASICLAYERSIMPL_H
 #define GFX_BASICLAYERSIMPL_H
 
 #include "BasicImplData.h"              // for BasicImplData
 #include "BasicLayers.h"                // for BasicLayerManager
 #include "ReadbackLayer.h"              // for ReadbackLayer
 #include "gfxASurface.h"                // for gfxASurface
 #include "gfxContext.h"                 // for gfxContext, etc
+#include "ipc/AutoOpenSurface.h"        // for AutoOpenSurface
 #include "mozilla/Attributes.h"         // for MOZ_DELETE, MOZ_STACK_CLASS
 #include "mozilla/Maybe.h"              // for Maybe
 #include "nsAutoPtr.h"                  // for nsRefPtr
 #include "nsDebug.h"                    // for NS_ASSERTION
 #include "nsISupportsImpl.h"            // for gfxContext::Release, etc
 #include "nsRegion.h"                   // for nsIntRegion
 
 namespace mozilla {
--- a/gfx/layers/client/ClientLayerManager.cpp
+++ b/gfx/layers/client/ClientLayerManager.cpp
@@ -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 "ClientLayerManager.h"
 #include "CompositorChild.h"            // for CompositorChild
 #include "GeckoProfiler.h"              // for PROFILER_LABEL
 #include "gfxASurface.h"                // for gfxASurface, etc
+#include "ipc/AutoOpenSurface.h"        // for AutoOpenSurface
 #include "mozilla/Assertions.h"         // for MOZ_ASSERT, etc
 #include "mozilla/Hal.h"
 #include "mozilla/dom/ScreenOrientation.h"  // for ScreenOrientation
 #include "mozilla/dom/TabChild.h"       // for TabChild
 #include "mozilla/hal_sandbox/PHal.h"   // for ScreenConfiguration
 #include "mozilla/layers/CompositableClient.h"  // for CompositableChild, etc
 #include "mozilla/layers/ContentClient.h"  // for ContentClientRemote
 #include "mozilla/layers/ISurfaceAllocator.h"
@@ -283,20 +284,20 @@ ClientLayerManager::MakeSnapshotIfRequir
       SurfaceDescriptor inSnapshot, snapshot;
       if (mForwarder->AllocSurfaceDescriptor(bounds.Size().ToIntSize(),
                                              gfxContentType::COLOR_ALPHA,
                                              &inSnapshot) &&
           // The compositor will usually reuse |snapshot| and return
           // it through |outSnapshot|, but if it doesn't, it's
           // responsible for freeing |snapshot|.
           remoteRenderer->SendMakeSnapshot(inSnapshot, &snapshot)) {
-        RefPtr<DataSourceSurface> surf = GetSurfaceForDescriptor(snapshot);
-        mShadowTarget->GetDrawTarget()->CopySurface(surf,
-                                                    IntRect(0, 0, bounds.Size().width, bounds.Size().height),
-                                                    IntPoint(0, 0));
+        AutoOpenSurface opener(OPEN_READ_ONLY, snapshot);
+        gfxASurface* source = opener.Get();
+
+        mShadowTarget->DrawSurface(source, source->GetSize());
       }
       if (IsSurfaceDescriptorValid(snapshot)) {
         mForwarder->DestroySharedSurface(&snapshot);
       }
     }
   }
   mShadowTarget = nullptr;
 }
--- a/gfx/layers/client/ContentClient.cpp
+++ b/gfx/layers/client/ContentClient.cpp
@@ -567,26 +567,24 @@ WrapRotationAxis(int32_t* aRotationPoint
   if (*aRotationPoint < 0) {
     *aRotationPoint += aSize;
   } else if (*aRotationPoint >= aSize) {
     *aRotationPoint -= aSize;
   }
 }
 
 static void
-FillSurface(DrawTarget* aDT, const nsIntRegion& aRegion,
+FillSurface(gfxASurface* aSurface, const nsIntRegion& aRegion,
             const nsIntPoint& aOffset, const gfxRGBA& aColor)
 {
-  nsIntRegionRectIterator iter(aRegion);
-  const nsIntRect* r;
-  while ((r = iter.Next()) != nullptr) {
-    aDT->FillRect(Rect(r->x - aOffset.x, r->y - aOffset.y,
-                       r->width, r->height),
-                  ColorPattern(ToColor(aColor)));
-  }
+  nsRefPtr<gfxContext> ctx = new gfxContext(aSurface);
+  ctx->Translate(-gfxPoint(aOffset.x, aOffset.y));
+  gfxUtils::ClipToRegion(ctx, aRegion);
+  ctx->SetColor(aColor);
+  ctx->Paint();
 }
 
 RotatedContentBuffer::PaintState
 ContentClientIncremental::BeginPaintBuffer(ThebesLayer* aLayer,
                                            uint32_t aFlags)
 {
   mTextureInfo.mDeprecatedTextureHostFlags = 0;
   PaintState result;
@@ -796,29 +794,32 @@ ContentClientIncremental::BorrowDrawTarg
 
   nsIntRect drawBounds = aPaintState.mRegionToDraw.GetBounds();
   MOZ_ASSERT(!mLoanedDrawTarget);
 
   // BeginUpdate is allowed to modify the given region,
   // if it wants more to be repainted than we request.
   if (aPaintState.mMode == SurfaceMode::SURFACE_COMPONENT_ALPHA) {
     nsIntRegion drawRegionCopy = aPaintState.mRegionToDraw;
-    RefPtr<DrawTarget> onBlack = GetUpdateSurface(BUFFER_BLACK, drawRegionCopy);
-    RefPtr<DrawTarget> onWhite = GetUpdateSurface(BUFFER_WHITE, aPaintState.mRegionToDraw);
+    nsRefPtr<gfxASurface> onBlack = GetUpdateSurface(BUFFER_BLACK, drawRegionCopy);
+    nsRefPtr<gfxASurface> onWhite = GetUpdateSurface(BUFFER_WHITE, aPaintState.mRegionToDraw);
     if (onBlack && onWhite) {
       NS_ASSERTION(aPaintState.mRegionToDraw == drawRegionCopy,
                    "BeginUpdate should always modify the draw region in the same way!");
       FillSurface(onBlack, aPaintState.mRegionToDraw, nsIntPoint(drawBounds.x, drawBounds.y), gfxRGBA(0.0, 0.0, 0.0, 1.0));
       FillSurface(onWhite, aPaintState.mRegionToDraw, nsIntPoint(drawBounds.x, drawBounds.y), gfxRGBA(1.0, 1.0, 1.0, 1.0));
-      mLoanedDrawTarget = Factory::CreateDualDrawTarget(onBlack, onWhite);
+      RefPtr<DrawTarget> onBlackDT = gfxPlatform::GetPlatform()->CreateDrawTargetForUpdateSurface(onBlack, onBlack->GetSize().ToIntSize());
+      RefPtr<DrawTarget> onWhiteDT = gfxPlatform::GetPlatform()->CreateDrawTargetForUpdateSurface(onWhite, onWhite->GetSize().ToIntSize());
+      mLoanedDrawTarget = Factory::CreateDualDrawTarget(onBlackDT, onWhiteDT);
     } else {
       mLoanedDrawTarget = nullptr;
     }
   } else {
-    mLoanedDrawTarget = GetUpdateSurface(BUFFER_BLACK, aPaintState.mRegionToDraw);
+    nsRefPtr<gfxASurface> surf = GetUpdateSurface(BUFFER_BLACK, aPaintState.mRegionToDraw);
+    mLoanedDrawTarget = gfxPlatform::GetPlatform()->CreateDrawTargetForUpdateSurface(surf, surf->GetSize().ToIntSize());
   }
   if (!mLoanedDrawTarget) {
     NS_WARNING("unable to get context for update");
     return nullptr;
   }
 
   result = mLoanedDrawTarget;
   mLoanedTransform = mLoanedDrawTarget->GetTransform();
@@ -836,59 +837,66 @@ ContentClientIncremental::BorrowDrawTarg
 }
 
 void
 ContentClientIncremental::Updated(const nsIntRegion& aRegionToDraw,
                                   const nsIntRegion& aVisibleRegion,
                                   bool aDidSelfCopy)
 {
   if (IsSurfaceDescriptorValid(mUpdateDescriptor)) {
+    ShadowLayerForwarder::CloseDescriptor(mUpdateDescriptor);
+
     mForwarder->UpdateTextureIncremental(this,
                                          TextureFront,
                                          mUpdateDescriptor,
                                          aRegionToDraw,
                                          mBufferRect,
                                          mBufferRotation);
     mUpdateDescriptor = SurfaceDescriptor();
   }
   if (IsSurfaceDescriptorValid(mUpdateDescriptorOnWhite)) {
+    ShadowLayerForwarder::CloseDescriptor(mUpdateDescriptorOnWhite);
+
     mForwarder->UpdateTextureIncremental(this,
                                          TextureOnWhiteFront,
                                          mUpdateDescriptorOnWhite,
                                          aRegionToDraw,
                                          mBufferRect,
                                          mBufferRotation);
     mUpdateDescriptorOnWhite = SurfaceDescriptor();
   }
 
 }
 
-TemporaryRef<DrawTarget>
+already_AddRefed<gfxASurface>
 ContentClientIncremental::GetUpdateSurface(BufferType aType,
                                            const nsIntRegion& aUpdateRegion)
 {
   nsIntRect rgnSize = aUpdateRegion.GetBounds();
   if (!mBufferRect.Contains(rgnSize)) {
     NS_ERROR("update outside of image");
     return nullptr;
   }
   SurfaceDescriptor desc;
   if (!mForwarder->AllocSurfaceDescriptor(rgnSize.Size().ToIntSize(),
                                           mContentType,
                                           &desc)) {
     NS_WARNING("creating SurfaceDescriptor failed!");
     return nullptr;
   }
 
+  nsRefPtr<gfxASurface> tmpASurface =
+    ShadowLayerForwarder::OpenDescriptor(OPEN_READ_WRITE, desc);
+
   if (aType == BUFFER_BLACK) {
     MOZ_ASSERT(!IsSurfaceDescriptorValid(mUpdateDescriptor));
     mUpdateDescriptor = desc;
   } else {
     MOZ_ASSERT(!IsSurfaceDescriptorValid(mUpdateDescriptorOnWhite));
     MOZ_ASSERT(aType == BUFFER_WHITE);
     mUpdateDescriptorOnWhite = desc;
   }
 
-  return GetDrawTargetForDescriptor(desc, gfx::BackendType::COREGRAPHICS);
+  return tmpASurface.forget();
 }
 
 }
 }
--- a/gfx/layers/client/ContentClient.h
+++ b/gfx/layers/client/ContentClient.h
@@ -454,17 +454,17 @@ private:
     mContentType = aType;
 
     mForwarder->CreatedIncrementalBuffer(this,
                                          mTextureInfo,
                                          mBufferRect);
 
   }
 
-  TemporaryRef<gfx::DrawTarget> GetUpdateSurface(BufferType aType,
+  already_AddRefed<gfxASurface> GetUpdateSurface(BufferType aType,
                                                  const nsIntRegion& aUpdateRegion);
 
   TextureInfo mTextureInfo;
   nsIntRect mBufferRect;
   nsIntPoint mBufferRotation;
 
   SurfaceDescriptor mUpdateDescriptor;
   SurfaceDescriptor mUpdateDescriptorOnWhite;
--- a/gfx/layers/composite/ContentHost.cpp
+++ b/gfx/layers/composite/ContentHost.cpp
@@ -10,16 +10,17 @@
 #include "mozilla/Assertions.h"         // for MOZ_ASSERT, etc
 #include "mozilla/gfx/BaseRect.h"       // for BaseRect
 #include "mozilla/layers/Compositor.h"  // for Compositor
 #include "mozilla/layers/Effects.h"     // for TexturedEffect, Effect, etc
 #include "mozilla/layers/LayersMessages.h"  // for ThebesBufferData
 #include "nsAString.h"
 #include "nsPrintfCString.h"            // for nsPrintfCString
 #include "nsString.h"                   // for nsAutoCString
+#include "ipc/AutoOpenSurface.h"        // for AutoOpenSurface
 #include "mozilla/layers/TextureHostOGL.h"  // for TextureHostOGL
 
 namespace mozilla {
 namespace gfx {
 class Matrix4x4;
 }
 using namespace gfx;
 
@@ -616,22 +617,29 @@ ContentHostIncremental::TextureUpdateReq
   YSide sideY = drawBounds.YMost() <= yBoundary ? BOTTOM : TOP;
   nsIntRect quadrantRect = GetQuadrantRectangle(sideX, sideY);
   NS_ASSERTION(quadrantRect.Contains(drawBounds), "Messed up quadrants");
 
   mUpdated.MoveBy(-nsIntPoint(quadrantRect.x, quadrantRect.y));
 
   IntPoint offset = ToIntPoint(-mUpdated.GetBounds().TopLeft());
 
-  RefPtr<DataSourceSurface> surf = GetSurfaceForDescriptor(mDescriptor);
+  AutoOpenSurface surf(OPEN_READ_ONLY, mDescriptor);
+
+  nsRefPtr<gfxImageSurface> thebesSurf = surf.GetAsImage();
+  RefPtr<DataSourceSurface> sourceSurf =
+    gfx::Factory::CreateWrappingDataSourceSurface(thebesSurf->Data(),
+                                                  thebesSurf->Stride(),
+                                                  ToIntSize(thebesSurf->GetSize()),
+                                                  ImageFormatToSurfaceFormat(thebesSurf->Format()));
 
   if (mTextureId == TextureFront) {
-    aHost->mSource->Update(surf, &mUpdated, &offset);
+    aHost->mSource->Update(sourceSurf, &mUpdated, &offset);
   } else {
-    aHost->mSourceOnWhite->Update(surf, &mUpdated, &offset);
+    aHost->mSourceOnWhite->Update(sourceSurf, &mUpdated, &offset);
   }
 }
 
 void
 ContentHostTexture::PrintInfo(nsACString& aTo, const char* aPrefix)
 {
   aTo += aPrefix;
   aTo += nsPrintfCString("ContentHost (0x%p)", this);
--- a/gfx/layers/composite/LayerManagerComposite.h
+++ b/gfx/layers/composite/LayerManagerComposite.h
@@ -211,16 +211,18 @@ public:
     mInvalidRegion.Or(mInvalidRegion, aRegion);
   }
 
   Compositor* GetCompositor() const
   {
     return mCompositor;
   }
 
+  bool PlatformDestroySharedSurface(SurfaceDescriptor* aSurface);
+
   /**
    * LayerManagerComposite provides sophisticated debug overlays
    * that can request a next frame.
    */
   bool DebugOverlayWantsNextFrame() { return mDebugOverlayWantsNextFrame; }
   void SetDebugOverlayWantsNextFrame(bool aVal)
   { mDebugOverlayWantsNextFrame = aVal; }
 
--- a/gfx/layers/composite/TextureHost.cpp
+++ b/gfx/layers/composite/TextureHost.cpp
@@ -141,16 +141,17 @@ TextureHost::Create(const SurfaceDescrip
                     ISurfaceAllocator* aDeallocator,
                     TextureFlags aFlags)
 {
   switch (aDesc.type()) {
     case SurfaceDescriptor::TSurfaceDescriptorShmem:
     case SurfaceDescriptor::TSurfaceDescriptorMemory:
       return CreateBackendIndependentTextureHost(aDesc, aDeallocator, aFlags);
     case SurfaceDescriptor::TSharedTextureDescriptor:
+    case SurfaceDescriptor::TSurfaceDescriptorGralloc:
     case SurfaceDescriptor::TNewSurfaceDescriptorGralloc:
     case SurfaceDescriptor::TSurfaceStreamDescriptor:
       return CreateTextureHostOGL(aDesc, aDeallocator, aFlags);
     case SurfaceDescriptor::TSurfaceDescriptorMacIOSurface:
       if (Compositor::GetBackend() == LayersBackend::LAYERS_OPENGL) {
         return CreateTextureHostOGL(aDesc, aDeallocator, aFlags);
       } else {
         return CreateTextureHostBasic(aDesc, aDeallocator, aFlags);
--- a/gfx/layers/d3d11/TextureD3D11.cpp
+++ b/gfx/layers/d3d11/TextureD3D11.cpp
@@ -3,16 +3,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "TextureD3D11.h"
 #include "CompositorD3D11.h"
 #include "gfxContext.h"
 #include "gfxImageSurface.h"
 #include "Effects.h"
+#include "ipc/AutoOpenSurface.h"
 #include "mozilla/layers/YCbCrImageDataSerializer.h"
 #include "gfxWindowsPlatform.h"
 #include "gfxD2DSurface.h"
 #include "gfx2DGlue.h"
 
 namespace mozilla {
 
 using namespace gfx;
--- a/gfx/layers/d3d9/CanvasLayerD3D9.cpp
+++ b/gfx/layers/d3d9/CanvasLayerD3D9.cpp
@@ -1,14 +1,15 @@
 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 
+#include "ipc/AutoOpenSurface.h"
 #include "mozilla/layers/PLayerTransaction.h"
 
 #include "gfxImageSurface.h"
 #include "gfxWindowsSurface.h"
 #include "gfxWindowsPlatform.h"
 #include "SurfaceStream.h"
 #include "SharedSurfaceGL.h"
 #include "GLContext.h"
--- a/gfx/layers/d3d9/ImageLayerD3D9.cpp
+++ b/gfx/layers/d3d9/ImageLayerD3D9.cpp
@@ -1,13 +1,14 @@
 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
+#include "ipc/AutoOpenSurface.h"
 #include "mozilla/gfx/2D.h"
 #include "mozilla/gfx/Point.h"
 #include "mozilla/RefPtr.h"
 #include "mozilla/layers/PLayerTransaction.h"
 #include "gfxSharedImageSurface.h"
 
 #include "ImageLayerD3D9.h"
 #include "ThebesLayerD3D9.h"
--- a/gfx/layers/d3d9/TextureD3D9.cpp
+++ b/gfx/layers/d3d9/TextureD3D9.cpp
@@ -3,16 +3,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "TextureD3D9.h"
 #include "CompositorD3D9.h"
 #include "gfxContext.h"
 #include "gfxImageSurface.h"
 #include "Effects.h"
+#include "ipc/AutoOpenSurface.h"
 #include "mozilla/layers/YCbCrImageDataSerializer.h"
 #include "gfxWindowsPlatform.h"
 #include "gfx2DGlue.h"
 #include "gfxUtils.h"
 #include "mozilla/gfx/2D.h"
 
 using namespace mozilla::gfx;
 
--- a/gfx/layers/d3d9/ThebesLayerD3D9.cpp
+++ b/gfx/layers/d3d9/ThebesLayerD3D9.cpp
@@ -4,16 +4,18 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/layers/PLayerTransaction.h"
 
 // This must occur *after* layers/PLayerTransaction.h to avoid
 // typedefs conflicts.
 #include "mozilla/ArrayUtils.h"
 
+#include "ipc/AutoOpenSurface.h"
+
 #include "ThebesLayerD3D9.h"
 #include "gfxPlatform.h"
 
 #include "gfxWindowsPlatform.h"
 #include "gfxTeeSurface.h"
 #include "gfxUtils.h"
 #include "ReadbackProcessor.h"
 #include "ReadbackLayer.h"
new file mode 100644
--- /dev/null
+++ b/gfx/layers/ipc/AutoOpenSurface.h
@@ -0,0 +1,73 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * vim: sw=2 ts=8 et :
+ */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_layers_AutoOpenSurface_h
+#define mozilla_layers_AutoOpenSurface_h 1
+
+#include "base/basictypes.h"
+
+#include "gfxASurface.h"
+#include "mozilla/layers/PLayerTransaction.h"
+#include "ShadowLayers.h"
+
+namespace mozilla {
+namespace layers {
+
+/**
+ * Some surface types can be fairly expensive to open.  This helper
+ * tries to put off opening surfaces as long as it can, until
+ * ahsolutely necessary.  And after being forced to open, it remembers
+ * the mapping so it doesn't need to be redone.
+ */
+class MOZ_STACK_CLASS AutoOpenSurface
+{
+public:
+
+  /** |aDescriptor| must be valid while AutoOpenSurface is
+   * in scope. */
+  AutoOpenSurface(OpenMode aMode, const SurfaceDescriptor& aDescriptor);
+
+  ~AutoOpenSurface();
+
+  /**
+   * These helpers do not necessarily need to open the descriptor to
+   * return an answer.
+   */
+  gfxContentType ContentType();
+  gfxImageFormat ImageFormat();
+  gfx::IntSize Size();
+
+  /** This can't escape the scope of AutoOpenSurface. */
+  gfxASurface* Get();
+
+  /**
+   * This can't escape the scope of AutoOpenSurface.
+   *
+   * This method is currently just a convenience wrapper around
+   * gfxASurface::GetAsImageSurface() --- it returns a valid surface
+   * exactly when this->Get()->GetAsImageSurface() would.  Clients
+   * that need guaranteed (fast) ImageSurfaces should allocate the
+   * underlying descriptor with capability MAP_AS_IMAGE_SURFACE, in
+   * which case this helper is guaranteed to succeed.
+   */
+  gfxImageSurface* GetAsImage();
+
+
+private:
+  SurfaceDescriptor mDescriptor;
+  nsRefPtr<gfxASurface> mSurface;
+  nsRefPtr<gfxImageSurface> mSurfaceAsImage;
+  OpenMode mMode;
+
+  AutoOpenSurface(const AutoOpenSurface&) MOZ_DELETE;
+  AutoOpenSurface& operator=(const AutoOpenSurface&) MOZ_DELETE;
+};
+
+} // namespace layers
+} // namespace mozilla
+
+#endif // ifndef mozilla_layers_AutoOpenSurface_h
--- a/gfx/layers/ipc/CompositableForwarder.h
+++ b/gfx/layers/ipc/CompositableForwarder.h
@@ -37,16 +37,17 @@ class PTextureChild;
  * compositable objetcs.
  *
  * ShadowLayerForwarder is an example of a CompositableForwarder (that can
  * additionally forward modifications of the Layer tree).
  * ImageBridgeChild is another CompositableForwarder.
  */
 class CompositableForwarder : public ISurfaceAllocator
 {
+  friend class AutoOpenSurface;
 public:
 
   CompositableForwarder()
     : mSerial(++sSerialCounter)
   {}
 
   /**
    * Setup the IPDL actor for aCompositable to be part of layers
@@ -101,16 +102,26 @@ public:
 
   /**
    * Communicate the picture rect of a YUV image in aLayer to the compositor
    */
   virtual void UpdatePictureRect(CompositableClient* aCompositable,
                                  const nsIntRect& aRect) = 0;
 
   /**
+   * The specified layer is destroying its buffers.
+   * |aBackBufferToDestroy| is deallocated when this transaction is
+   * posted to the parent.  During the parent-side transaction, the
+   * shadow is told to destroy its front buffer.  This can happen when
+   * a new front/back buffer pair have been created because of a layer
+   * resize, e.g.
+   */
+  virtual void DestroyedThebesBuffer(const SurfaceDescriptor& aBackBufferToDestroy) = 0;
+
+  /**
    * Tell the CompositableHost on the compositor side to remove the texture.
    * This function does not delete the TextureHost corresponding to the
    * TextureClient passed in parameter.
    */
   virtual void RemoveTextureFromCompositable(CompositableClient* aCompositable,
                                              TextureClient* aTexture) = 0;
 
   /**
--- a/gfx/layers/ipc/CompositorParent.cpp
+++ b/gfx/layers/ipc/CompositorParent.cpp
@@ -4,16 +4,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "CompositorParent.h"
 #include <stdio.h>                      // for fprintf, stdout
 #include <stdint.h>                     // for uint64_t
 #include <map>                          // for _Rb_tree_iterator, etc
 #include <utility>                      // for pair
+#include "AutoOpenSurface.h"            // for AutoOpenSurface
 #include "LayerTransactionParent.h"     // for LayerTransactionParent
 #include "RenderTrace.h"                // for RenderTraceLayers
 #include "base/message_loop.h"          // for MessageLoop
 #include "base/process.h"               // for ProcessHandle
 #include "base/process_util.h"          // for OpenProcessHandle
 #include "base/task.h"                  // for CancelableTask, etc
 #include "base/thread.h"                // for Thread
 #include "base/tracked.h"               // for FROM_HERE
@@ -307,17 +308,22 @@ CompositorParent::RecvResume()
   ResumeComposition();
   return true;
 }
 
 bool
 CompositorParent::RecvMakeSnapshot(const SurfaceDescriptor& aInSnapshot,
                                    SurfaceDescriptor* aOutSnapshot)
 {
-  RefPtr<DrawTarget> target = GetDrawTargetForDescriptor(aInSnapshot, gfx::BackendType::CAIRO);
+  AutoOpenSurface opener(OPEN_READ_WRITE, aInSnapshot);
+  gfx::IntSize size = opener.Size();
+  // XXX CreateDrawTargetForSurface will always give us a Cairo surface, we can
+  // do better if AutoOpenSurface uses Moz2D directly.
+  RefPtr<DrawTarget> target =
+    gfxPlatform::GetPlatform()->CreateDrawTargetForSurface(opener.Get(), size);
   ForceComposeToTarget(target);
   *aOutSnapshot = aInSnapshot;
   return true;
 }
 
 bool
 CompositorParent::RecvFlushRendering()
 {
--- a/gfx/layers/ipc/ISurfaceAllocator.cpp
+++ b/gfx/layers/ipc/ISurfaceAllocator.cpp
@@ -15,18 +15,16 @@
 #include "mozilla/Atomics.h"            // for PrimitiveIntrinsics
 #include "mozilla/ipc/SharedMemory.h"   // for SharedMemory, etc
 #include "mozilla/layers/LayersSurfaces.h"  // for SurfaceDescriptor, etc
 #include "ShadowLayerUtils.h"
 #include "mozilla/mozalloc.h"           // for operator delete[], etc
 #include "nsAutoPtr.h"                  // for nsRefPtr, getter_AddRefs, etc
 #include "nsDebug.h"                    // for NS_RUNTIMEABORT
 #include "nsXULAppAPI.h"                // for XRE_GetProcessType, etc
-#include "mozilla/ipc/Shmem.h"
-#include "mozilla/layers/ImageDataSerializer.h"
 #ifdef DEBUG
 #include "prenv.h"
 #endif
 
 using namespace mozilla::ipc;
 
 namespace mozilla {
 namespace layers {
@@ -54,132 +52,149 @@ ISurfaceAllocator::~ISurfaceAllocator()
 }
 
 void
 ISurfaceAllocator::Finalize()
 {
   ShrinkShmemSectionHeap();
 }
 
-static inline uint8_t*
-GetAddressFromDescriptor(const SurfaceDescriptor& aDescriptor, size_t& aSize)
+bool
+ISurfaceAllocator::AllocSharedImageSurface(const gfx::IntSize& aSize,
+                               gfxContentType aContent,
+                               gfxSharedImageSurface** aBuffer)
 {
-  MOZ_ASSERT(IsSurfaceDescriptorValid(aDescriptor));
-  MOZ_ASSERT(aDescriptor.type() == SurfaceDescriptor::TSurfaceDescriptorShmem ||
-             aDescriptor.type() == SurfaceDescriptor::TSurfaceDescriptorMemory);
-  if (aDescriptor.type() == SurfaceDescriptor::TSurfaceDescriptorShmem) {
-    Shmem shmem(aDescriptor.get_SurfaceDescriptorShmem().data());
-    aSize = shmem.Size<uint8_t>();
-    return shmem.get<uint8_t>();
-  } else {
-    const SurfaceDescriptorMemory& image = aDescriptor.get_SurfaceDescriptorMemory();
-    aSize = std::numeric_limits<size_t>::max();
-    return reinterpret_cast<uint8_t*>(image.data());
-  }
-}
+  mozilla::ipc::SharedMemory::SharedMemoryType shmemType = OptimalShmemType();
+  gfxImageFormat format = gfxPlatform::GetPlatform()->OptimalFormatForContent(aContent);
 
-TemporaryRef<gfx::DrawTarget>
-GetDrawTargetForDescriptor(const SurfaceDescriptor& aDescriptor, gfx::BackendType aBackend)
-{
-  size_t size;
-  uint8_t* data = GetAddressFromDescriptor(aDescriptor, size);
-  ImageDataDeserializer image(data, size);
-  return image.GetAsDrawTarget(aBackend);
-}
+  nsRefPtr<gfxSharedImageSurface> back =
+    gfxSharedImageSurface::CreateUnsafe(this,
+                                        gfx::ThebesIntSize(aSize),
+                                        format,
+                                        shmemType);
+  if (!back)
+    return false;
 
-TemporaryRef<gfx::DataSourceSurface>
-GetSurfaceForDescriptor(const SurfaceDescriptor& aDescriptor)
-{
-  size_t size;
-  uint8_t* data = GetAddressFromDescriptor(aDescriptor, size);
-  ImageDataDeserializer image(data, size);
-  return image.GetAsSurface();
+  *aBuffer = nullptr;
+  back.swap(*aBuffer);
+  return true;
 }
 
 bool
 ISurfaceAllocator::AllocSurfaceDescriptor(const gfx::IntSize& aSize,
                                           gfxContentType aContent,
                                           SurfaceDescriptor* aBuffer)
 {
   return AllocSurfaceDescriptorWithCaps(aSize, aContent, DEFAULT_BUFFER_CAPS, aBuffer);
 }
 
 bool
 ISurfaceAllocator::AllocSurfaceDescriptorWithCaps(const gfx::IntSize& aSize,
                                                   gfxContentType aContent,
                                                   uint32_t aCaps,
                                                   SurfaceDescriptor* aBuffer)
 {
-  gfx::SurfaceFormat format =
-    gfxPlatform::GetPlatform()->Optimal2DFormatForContent(aContent);
-  size_t size = ImageDataSerializer::ComputeMinBufferSize(aSize, format);
-  if (gfxPlatform::GetPlatform()->PreferMemoryOverShmem()) {
-    uint8_t *data = new (std::nothrow) uint8_t[size];
+  bool tryPlatformSurface = true;
+#ifdef DEBUG
+  tryPlatformSurface = !PR_GetEnv("MOZ_LAYERS_FORCE_SHMEM_SURFACES");
+#endif
+  if (tryPlatformSurface &&
+      PlatformAllocSurfaceDescriptor(aSize, aContent, aCaps, aBuffer)) {
+    return true;
+  }
+
+  if (XRE_GetProcessType() == GeckoProcessType_Default) {
+    gfxImageFormat format =
+      gfxPlatform::GetPlatform()->OptimalFormatForContent(aContent);
+    int32_t stride = gfxASurface::FormatStrideForWidth(format, aSize.width);
+    uint8_t *data = new (std::nothrow) uint8_t[stride * aSize.height];
     if (!data) {
       return false;
     }
     GfxMemoryImageReporter::DidAlloc(data);
 #ifdef XP_MACOSX
     // Workaround a bug in Quartz where drawing an a8 surface to another a8
     // surface with OPERATOR_SOURCE still requires the destination to be clear.
-    if (format == SurfaceFormat::A8) {
-      memset(data, 0, size);
+    if (format == gfxImageFormat::A8) {
+      memset(data, 0, stride * aSize.height);
     }
 #endif
-    *aBuffer = SurfaceDescriptorMemory((uintptr_t)data, format);
-  } else {
+    *aBuffer = MemoryImage((uintptr_t)data, aSize, stride, format);
+    return true;
+  }
 
-    mozilla::ipc::SharedMemory::SharedMemoryType shmemType = OptimalShmemType();
-    mozilla::ipc::Shmem shmem;
-    if (!AllocUnsafeShmem(size, shmemType, &shmem)) {
-      return false;
-    }
+  nsRefPtr<gfxSharedImageSurface> buffer;
+  if (!AllocSharedImageSurface(aSize, aContent,
+                               getter_AddRefs(buffer))) {
+    return false;
+  }
 
-    *aBuffer = SurfaceDescriptorShmem(shmem, format);
-  }
-  
-  uint8_t* data = GetAddressFromDescriptor(*aBuffer, size);
-  ImageDataSerializer serializer(data, size);
-  serializer.InitializeBufferInfo(aSize, format);
+  *aBuffer = buffer->GetShmem();
   return true;
 }
 
 /* static */ bool
 ISurfaceAllocator::IsShmem(SurfaceDescriptor* aSurface)
 {
-  return aSurface && (aSurface->type() == SurfaceDescriptor::TSurfaceDescriptorShmem);
+  return aSurface && (aSurface->type() == SurfaceDescriptor::TShmem ||
+                      aSurface->type() == SurfaceDescriptor::TYCbCrImage ||
+                      aSurface->type() == SurfaceDescriptor::TRGBImage);
 }
 
 void
 ISurfaceAllocator::DestroySharedSurface(SurfaceDescriptor* aSurface)
 {
   MOZ_ASSERT(aSurface);
   if (!aSurface) {
     return;
   }
   if (!IPCOpen()) {
     return;
   }
+  if (PlatformDestroySharedSurface(aSurface)) {
+    return;
+  }
   switch (aSurface->type()) {
-    case SurfaceDescriptor::TSurfaceDescriptorShmem:
-      DeallocShmem(aSurface->get_SurfaceDescriptorShmem().data());
+    case SurfaceDescriptor::TShmem:
+      DeallocShmem(aSurface->get_Shmem());
+      break;
+    case SurfaceDescriptor::TYCbCrImage:
+      DeallocShmem(aSurface->get_YCbCrImage().data());
       break;
-    case SurfaceDescriptor::TSurfaceDescriptorMemory:
-      GfxMemoryImageReporter::WillFree((uint8_t*)aSurface->get_SurfaceDescriptorMemory().data());
-      delete [] (uint8_t*)aSurface->get_SurfaceDescriptorMemory().data();
+    case SurfaceDescriptor::TRGBImage:
+      DeallocShmem(aSurface->get_RGBImage().data());
+      break;
+    case SurfaceDescriptor::TSurfaceDescriptorD3D9:
+    case SurfaceDescriptor::TSurfaceDescriptorDIB:
+    case SurfaceDescriptor::TSurfaceDescriptorD3D10:
+      break;
+    case SurfaceDescriptor::TMemoryImage:
+      GfxMemoryImageReporter::WillFree((uint8_t*)aSurface->get_MemoryImage().data());
+      delete [] (uint8_t*)aSurface->get_MemoryImage().data();
       break;
     case SurfaceDescriptor::Tnull_t:
     case SurfaceDescriptor::T__None:
       break;
     default:
       NS_RUNTIMEABORT("surface type not implemented!");
   }
   *aSurface = SurfaceDescriptor();
 }
 
+#if !defined(MOZ_HAVE_PLATFORM_SPECIFIC_LAYER_BUFFERS)
+bool
+ISurfaceAllocator::PlatformAllocSurfaceDescriptor(const gfx::IntSize&,
+                                                  gfxContentType,
+                                                  uint32_t,
+                                                  SurfaceDescriptor*)
+{
+  return false;
+}
+#endif
+
 // XXX - We should actually figure out the minimum shmem allocation size on
 // a certain platform and use that.
 const uint32_t sShmemPageSize = 4096;
 const uint32_t sSupportedBlockSize = 4;
 
 enum AllocationStatus
 {
   STATUS_ALLOCATED,
--- a/gfx/layers/ipc/ISurfaceAllocator.h
+++ b/gfx/layers/ipc/ISurfaceAllocator.h
@@ -35,19 +35,16 @@ class gfxSharedImageSurface;
 namespace base {
 class Thread;
 }
 
 namespace mozilla {
 namespace ipc {
 class Shmem;
 }
-namespace gfx {
-class DataSourceSurface;
-}
 
 namespace layers {
 
 class PGrallocBufferChild;
 class MaybeMagicGrallocBufferHandle;
 class MemoryTextureClient;
 class MemoryTextureHost;
 
@@ -66,19 +63,16 @@ enum BufferCapabilities {
 
 class SurfaceDescriptor;
 
 
 mozilla::ipc::SharedMemory::SharedMemoryType OptimalShmemType();
 bool IsSurfaceDescriptorValid(const SurfaceDescriptor& aSurface);
 bool IsSurfaceDescriptorOwned(const SurfaceDescriptor& aDescriptor);
 bool ReleaseOwnedSurfaceDescriptor(const SurfaceDescriptor& aDescriptor);
-
-TemporaryRef<gfx::DrawTarget> GetDrawTargetForDescriptor(const SurfaceDescriptor& aDescriptor, gfx::BackendType aBackend);
-TemporaryRef<gfx::DataSourceSurface> GetSurfaceForDescriptor(const SurfaceDescriptor& aDescriptor);
 /**
  * An interface used to create and destroy surfaces that are shared with the
  * Compositor process (using shmem, or gralloc, or other platform specific memory)
  *
  * Most of the methods here correspond to methods that are implemented by IPDL
  * actors without a common polymorphic interface.
  * These methods should be only called in the ipdl implementor's thread, unless
  * specified otherwise in the implementing class.
@@ -132,16 +126,19 @@ public:
   void FreeShmemSection(mozilla::layers::ShmemSection& aShmemSection);
 
   /**
    * Deallocate memory allocated by either AllocShmem or AllocUnsafeShmem.
    */
   virtual void DeallocShmem(mozilla::ipc::Shmem& aShmem) = 0;
 
   // was AllocBuffer
+  virtual bool AllocSharedImageSurface(const gfx::IntSize& aSize,
+                                       gfxContentType aContent,
+                                       gfxSharedImageSurface** aBuffer);
   virtual bool AllocSurfaceDescriptor(const gfx::IntSize& aSize,
                                       gfxContentType aContent,
                                       SurfaceDescriptor* aBuffer);
 
   // was AllocBufferWithCaps
   virtual bool AllocSurfaceDescriptorWithCaps(const gfx::IntSize& aSize,
                                               gfxContentType aContent,
                                               uint32_t aCaps,
@@ -172,16 +169,22 @@ public:
   virtual bool IsSameProcess() const = 0;
 
   // Returns true if aSurface wraps a Shmem.
   static bool IsShmem(SurfaceDescriptor* aSurface);
 
 protected:
 
   virtual bool IsOnCompositorSide() const = 0;
+  bool PlatformDestroySharedSurface(SurfaceDescriptor* aSurface);
+  virtual bool PlatformAllocSurfaceDescriptor(const gfx::IntSize& aSize,
+                                              gfxContentType aContent,
+                                              uint32_t aCaps,
+                                              SurfaceDescriptor* aBuffer);
+
 
   virtual ~ISurfaceAllocator();
 
   void ShrinkShmemSectionHeap();
 
   // This is used to implement an extremely simple & naive heap allocator.
   std::vector<mozilla::ipc::Shmem> mUsedShmems;
 
--- a/gfx/layers/ipc/ImageBridgeChild.h
+++ b/gfx/layers/ipc/ImageBridgeChild.h
@@ -271,16 +271,21 @@ public:
   {
     NS_RUNTIMEABORT("should not be called");
   }
   virtual void UpdateTextureRegion(CompositableClient* aCompositable,
                                    const ThebesBufferData& aThebesBufferData,
                                    const nsIntRegion& aUpdatedRegion) MOZ_OVERRIDE {
     NS_RUNTIMEABORT("should not be called");
   }
+  virtual void DestroyedThebesBuffer(const SurfaceDescriptor& aBackBufferToDestroy) MOZ_OVERRIDE
+  {
+    NS_RUNTIMEABORT("should not be called");
+  }
+
 
   // ISurfaceAllocator
 
   /**
    * 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.
--- a/gfx/layers/ipc/LayersSurfaces.ipdlh
+++ b/gfx/layers/ipc/LayersSurfaces.ipdlh
@@ -61,21 +61,73 @@ struct NewSurfaceDescriptorGralloc {
   /**
    * android::GraphicBuffer has a size information. But there are cases
    * that GraphicBuffer's size and actual video's size are different.
    * Extra size member is necessary. See Bug 850566.
    */
   IntSize size;
 };
 
+// XXX - soon to be removed
+struct SurfaceDescriptorGralloc {
+  PGrallocBuffer buffer;
+  /**
+   * android::GraphicBuffer has a size information. But there are cases
+   * that GraphicBuffer's size and actual video's size are different.
+   * Extra size member is necessary. See Bug 850566.
+   */
+  IntSize size;
+
+  /**
+   * We can have one source producing gralloc buffers and sharing them
+   * with another source that may also produce its own gralloc buffers.
+   * This happens for camera preview buffers sent to video code.  When
+   * that happens, the producer can mark the buffer as "external" to
+   * prevent its consumer from mistakenly freeing the buffer.
+   */
+  bool external;
+
+  /**
+   * This gralloc buffer will be treated as if the RB bytes are swapped.
+   * This is useful for rendering using Cairo/Thebes, because there is no
+   * BGRX Android pixel format, and so we have to do byte swapping.
+   *
+   * For example, if the GraphicBuffer has an Android pixel format of
+   * PIXEL_FORMAT_RGBA_8888 and isRBSwapped is true, when it is sampled
+   * (for example, with GL), a BGRA shader should be used.
+   */
+  bool isRBSwapped;
+};
+
 struct SurfaceStreamDescriptor {
   SurfaceStreamHandle handle;
   bool yflip;
 };
 
+// XXX - can be removed as soon as DeprecatedImageClientSingle is removed
+struct YCbCrImage {
+  Shmem data;
+  uint64_t owner;
+};
+
+// XXX remove RGBImage (see bug 847914)
+struct RGBImage {
+  Shmem data;
+  nsIntRect picture;
+  gfxImageFormat rgbFormat;
+  uint64_t owner;
+};
+
+struct MemoryImage {
+  uintptr_t data;
+  IntSize size;
+  uint32_t stride;
+  gfxImageFormat format;
+};
+
 /**
  * Used for shmem-backed YCbCr and (flavors of) RGBA textures
  */
 struct SurfaceDescriptorShmem {
   Shmem data;
   SurfaceFormat format;
 };
 
@@ -93,13 +145,18 @@ union SurfaceDescriptor {
   SurfaceDescriptorD3D9;
   SurfaceDescriptorDIB;
   SurfaceDescriptorD3D10;
   SurfaceDescriptorX11;
   SharedTextureDescriptor;
   SurfaceStreamDescriptor;
   SurfaceDescriptorMacIOSurface;
   NewSurfaceDescriptorGralloc;
+  YCbCrImage;                 // XXX - deprecated
+  SurfaceDescriptorGralloc;   // XXX - deprecated
+  Shmem;                      // XXX - deprecated
+  RGBImage;                   // XXX - deprecated
+  MemoryImage;                // XXX - deprecated
   null_t;
 };
 
 } // namespace
 } // namespace
--- a/gfx/layers/ipc/ShadowLayerUtilsD3D10.cpp
+++ b/gfx/layers/ipc/ShadowLayerUtilsD3D10.cpp
@@ -13,22 +13,87 @@
 #include "mozilla/layers/PLayerTransaction.h"
 #include "ShadowLayers.h"
 
 using namespace mozilla::gl;
 
 namespace mozilla {
 namespace layers {
 
+// Platform-specific shadow-layers interfaces.  See ShadowLayers.h.
+// D3D10 doesn't need all these yet.
+bool
+ISurfaceAllocator::PlatformAllocSurfaceDescriptor(const gfx::IntSize&,
+                                                  gfxContentType,
+                                                  uint32_t,
+                                                  SurfaceDescriptor*)
+{
+  return false;
+}
+
+/*static*/ already_AddRefed<gfxASurface>
+ShadowLayerForwarder::PlatformOpenDescriptor(OpenMode,
+                                             const SurfaceDescriptor&)
+{
+  return nullptr;
+}
+
+/*static*/ bool
+ShadowLayerForwarder::PlatformCloseDescriptor(const SurfaceDescriptor&)
+{
+  return false;
+}
+
+/*static*/ bool
+ShadowLayerForwarder::PlatformGetDescriptorSurfaceContentType(
+  const SurfaceDescriptor&,
+  OpenMode,
+  gfxContentType*,
+  gfxASurface**)
+{
+  return false;
+}
+
+/*static*/ bool
+ShadowLayerForwarder::PlatformGetDescriptorSurfaceSize(
+  const SurfaceDescriptor&,
+  OpenMode,
+  gfx::IntSize*,
+  gfxASurface**)
+{
+  return false;
+}
+
+/*static*/ bool
+ShadowLayerForwarder::PlatformGetDescriptorSurfaceImageFormat(
+  const SurfaceDescriptor&,
+  OpenMode,
+  gfxImageFormat*,
+  gfxASurface**)
+{
+  return false;
+}
+
+bool
+ShadowLayerForwarder::PlatformDestroySharedSurface(SurfaceDescriptor*)
+{
+  return false;
+}
 
 /*static*/ void
 ShadowLayerForwarder::PlatformSyncBeforeUpdate()
 {
 }
 
+bool
+ISurfaceAllocator::PlatformDestroySharedSurface(SurfaceDescriptor*)
+{
+  return false;
+}
+
 /*static*/ bool
 LayerManagerComposite::SupportsDirectTexturing()
 {
   return true;
 }
 
 /*static*/ void
 LayerManagerComposite::PlatformSyncBeforeReplyUpdate()
--- a/gfx/layers/ipc/ShadowLayerUtilsGralloc.cpp
+++ b/gfx/layers/ipc/ShadowLayerUtilsGralloc.cpp
@@ -337,16 +337,39 @@ LayerManagerComposite::SupportsDirectTex
 }
 
 /*static*/ void
 LayerManagerComposite::PlatformSyncBeforeReplyUpdate()
 {
   // Nothing to be done for gralloc.
 }
 
+bool
+ISurfaceAllocator::PlatformDestroySharedSurface(SurfaceDescriptor* aSurface)
+{
+  if (SurfaceDescriptor::TSurfaceDescriptorGralloc != aSurface->type()) {
+    return false;
+  }
+
+  // we should have either a bufferParent or bufferChild
+  // depending on whether we're on the parent or child side.
+  PGrallocBufferParent* gbp =
+    aSurface->get_SurfaceDescriptorGralloc().bufferParent();
+  if (gbp) {
+    unused << PGrallocBufferParent::Send__delete__(gbp);
+  } else {
+    PGrallocBufferChild* gbc =
+      aSurface->get_SurfaceDescriptorGralloc().bufferChild();
+    DeallocGrallocBuffer(gbc);
+  }
+
+  *aSurface = SurfaceDescriptor();
+  return true;
+}
+
 //-----------------------------------------------------------------------------
 // Child process
 
 /*static*/ PGrallocBufferChild*
 GrallocBufferActor::Create()
 {
   return new GrallocBufferActor();
 }
@@ -371,25 +394,216 @@ ShadowLayerForwarder::AllocGrallocBuffer
 
 void
 ShadowLayerForwarder::DeallocGrallocBuffer(PGrallocBufferChild* aChild)
 {
   MOZ_ASSERT(aChild);
   PGrallocBufferChild::Send__delete__(aChild);
 }
 
+bool
+ISurfaceAllocator::PlatformAllocSurfaceDescriptor(const gfx::IntSize& aSize,
+                                                  gfxContentType aContent,
+                                                  uint32_t aCaps,
+                                                  SurfaceDescriptor* aBuffer)
+{
+
+  if (aSize.width <= 0 || aSize.height <= 0) {
+    return false;
+  }
+#if ANDROID_VERSION <= 15
+  // Adreno 200 fails to render gralloc textures with width < 64
+  // or with height < 32.
+  if (aSize.width < 64 || aSize.height < 32) {
+    return false;
+  }
+#endif
+  PROFILER_LABEL("ShadowLayerForwarder", "PlatformAllocSurfaceDescriptor");
+  // Gralloc buffers are efficiently mappable as gfxImageSurface, so
+  // no need to check |aCaps & MAP_AS_IMAGE_SURFACE|.
+  MaybeMagicGrallocBufferHandle handle;
+  PGrallocBufferChild* gc;
+  bool defaultRBSwap;
+
+  if (PixelFormatForContentType(aContent) == android::PIXEL_FORMAT_UNKNOWN) {
+    return false;
+  }
+
+  if (aCaps & USING_GL_RENDERING_ONLY) {
+    gc = AllocGrallocBuffer(aSize,
+                            PixelFormatForContentType(aContent),
+                            GraphicBuffer::USAGE_HW_RENDER |
+                            GraphicBuffer::USAGE_HW_TEXTURE,
+                            &handle);
+    // If you're allocating for USING_GL_RENDERING_ONLY, then we don't flag
+    // this for RB swap.
+    defaultRBSwap = false;
+  } else {
+    gc = AllocGrallocBuffer(aSize,
+                            PixelFormatForContentType(aContent),
+                            GraphicBuffer::USAGE_SW_READ_OFTEN |
+                            GraphicBuffer::USAGE_SW_WRITE_OFTEN |
+                            GraphicBuffer::USAGE_HW_TEXTURE,
+                            &handle);
+    // But if you're allocating for non-GL-only rendering, we flag for
+    // RB swap to preserve old behaviour and proper interaction with
+    // cairo.
+    defaultRBSwap = true;
+  }
+
+  if (!gc) {
+    NS_ERROR("GrallocBufferConstructor failed by returned null");
+    return false;
+  } else if (handle.Tnull_t == handle.type()) {
+    NS_ERROR("GrallocBufferConstructor failed by returning handle with type Tnull_t");
+    PGrallocBufferChild::Send__delete__(gc);
+    return false;
+  }
+
+  GrallocBufferActor* gba = static_cast<GrallocBufferActor*>(gc);
+  gba->InitFromHandle(handle.get_MagicGrallocBufferHandle());
+
+  *aBuffer = SurfaceDescriptorGralloc(nullptr, gc, aSize,
+                                      /* external */ false,
+                                      defaultRBSwap);
+  return true;
+}
+
 //-----------------------------------------------------------------------------
 // Both processes
 
+/*static*/ sp<GraphicBuffer>
+GrallocBufferActor::GetFrom(const SurfaceDescriptorGralloc& aDescriptor)
+{
+  GrallocBufferActor* gba = nullptr;
+  if (PGrallocBufferChild* child = aDescriptor.bufferChild()) {
+    gba = static_cast<GrallocBufferActor*>(child);
+  } else if (PGrallocBufferParent* parent = aDescriptor.bufferParent()) {
+    gba = static_cast<GrallocBufferActor*>(parent);
+  }
+  return gba->mGraphicBuffer;
+}
+
 android::GraphicBuffer*
 GrallocBufferActor::GetGraphicBuffer()
 {
   return mGraphicBuffer.get();
 }
 
+/*static*/ already_AddRefed<gfxASurface>
+ShadowLayerForwarder::PlatformOpenDescriptor(OpenMode aMode,
+                                             const SurfaceDescriptor& aSurface)
+{
+  PROFILER_LABEL("ShadowLayerForwarder", "PlatformOpenDescriptor");
+  if (SurfaceDescriptor::TSurfaceDescriptorGralloc != aSurface.type()) {
+    return nullptr;
+  }
+
+  sp<GraphicBuffer> buffer =
+    GrallocBufferActor::GetFrom(aSurface.get_SurfaceDescriptorGralloc());
+  uint32_t usage = GRALLOC_USAGE_SW_READ_OFTEN;
+  if (OPEN_READ_WRITE == aMode) {
+    usage |= GRALLOC_USAGE_SW_WRITE_OFTEN;
+  }
+  void *vaddr;
+  DebugOnly<status_t> status = buffer->lock(usage, &vaddr);
+  // If we fail to lock, we'll just end up aborting anyway.
+  MOZ_ASSERT(status == OK);
+
+  gfx::IntSize size = aSurface.get_SurfaceDescriptorGralloc().size();
+  gfxImageFormat format = ImageFormatForPixelFormat(buffer->getPixelFormat());
+  long pixelStride = buffer->getStride();
+  long byteStride = pixelStride * gfxASurface::BytePerPixelFromFormat(format);
+
+  nsRefPtr<gfxASurface> surf =
+    new gfxImageSurface((unsigned char*)vaddr,
+                        gfx::ThebesIntSize(size),
+                        byteStride,
+                        format);
+  return surf->CairoStatus() ? nullptr : surf.forget();
+}
+
+/*static*/ bool
+ShadowLayerForwarder::PlatformGetDescriptorSurfaceContentType(
+  const SurfaceDescriptor& aDescriptor, OpenMode aMode,
+  gfxContentType* aContent,
+  gfxASurface** aSurface)
+{
+  if (SurfaceDescriptor::TSurfaceDescriptorGralloc != aDescriptor.type()) {
+    return false;
+  }
+
+  sp<GraphicBuffer> buffer =
+    GrallocBufferActor::GetFrom(aDescriptor.get_SurfaceDescriptorGralloc());
+  *aContent = ContentTypeFromPixelFormat(buffer->getPixelFormat());
+  return true;
+}
+
+/*static*/ bool
+ShadowLayerForwarder::PlatformGetDescriptorSurfaceSize(
+  const SurfaceDescriptor& aDescriptor, OpenMode aMode,
+  gfx::IntSize* aSize,
+  gfxASurface** aSurface)
+{
+  if (SurfaceDescriptor::TSurfaceDescriptorGralloc != aDescriptor.type()) {
+    return false;
+  }
+
+  sp<GraphicBuffer> buffer =
+    GrallocBufferActor::GetFrom(aDescriptor.get_SurfaceDescriptorGralloc());
+  *aSize = aDescriptor.get_SurfaceDescriptorGralloc().size();
+  return true;
+}
+
+/*static*/ bool
+ShadowLayerForwarder::PlatformGetDescriptorSurfaceImageFormat(
+  const SurfaceDescriptor& aDescriptor,
+  OpenMode aMode,
+  gfxImageFormat* aImageFormat,
+  gfxASurface** aSurface)
+{
+  if (SurfaceDescriptor::TSurfaceDescriptorGralloc != aDescriptor.type()) {
+    return false;
+  }
+
+  sp<GraphicBuffer> buffer =
+    GrallocBufferActor::GetFrom(aDescriptor.get_SurfaceDescriptorGralloc());
+  *aImageFormat = ImageFormatForPixelFormat(buffer->getPixelFormat());
+  return true;
+}
+
+/*static*/ bool
+ShadowLayerForwarder::PlatformDestroySharedSurface(SurfaceDescriptor* aSurface)
+{
+  if (SurfaceDescriptor::TSurfaceDescriptorGralloc != aSurface->type()) {
+    return false;
+  }
+
+  PGrallocBufferChild* gbp =
+    aSurface->get_SurfaceDescriptorGralloc().bufferChild();
+  PGrallocBufferChild::Send__delete__(gbp);
+  *aSurface = SurfaceDescriptor();
+  return true;
+}
+
+/*static*/ bool
+ShadowLayerForwarder::PlatformCloseDescriptor(const SurfaceDescriptor& aDescriptor)
+{
+  PROFILER_LABEL("ShadowLayerForwarder", "PlatformCloseDescriptor");
+  if (SurfaceDescriptor::TSurfaceDescriptorGralloc != aDescriptor.type()) {
+    return false;
+  }
+
+  sp<GraphicBuffer> buffer = GrallocBufferActor::GetFrom(aDescriptor);
+  DebugOnly<status_t> status = buffer->unlock();
+  // If we fail to unlock, we'll subsequently fail to lock and end up aborting anyway.
+  MOZ_ASSERT(status == OK);
+  return true;
+}
+
 /*static*/ void
 ShadowLayerForwarder::PlatformSyncBeforeUpdate()
 {
   // Nothing to be done for gralloc.
 }
 
 } // namespace layers
 } // namespace mozilla
--- a/gfx/layers/ipc/ShadowLayerUtilsGralloc.h
+++ b/gfx/layers/ipc/ShadowLayerUtilsGralloc.h
@@ -19,16 +19,17 @@
 #define MOZ_HAVE_PLATFORM_SPECIFIC_LAYER_BUFFERS
 
 class gfxASurface;
 
 namespace mozilla {
 namespace layers {
 
 class MaybeMagicGrallocBufferHandle;
+class SurfaceDescriptorGralloc;
 class TextureHost;
 
 /**
  * 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
@@ -71,16 +72,19 @@ public:
   Create(const gfx::IntSize& aSize,
          const uint32_t& aFormat,
          const uint32_t& aUsage,
          MaybeMagicGrallocBufferHandle* aOutHandle);
 
   static PGrallocBufferChild*
   Create();
 
+  static android::sp<GraphicBuffer>
+  GetFrom(const SurfaceDescriptorGralloc& aDescriptor);
+
   // used only for hacky fix in gecko 23 for bug 862324
   // see bug 865908 about fixing this.
   void ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE;
 
   void AddTextureHost(TextureHost* aTextureHost);
   void RemoveTextureHost();
 
   android::GraphicBuffer* GetGraphicBuffer();
--- a/gfx/layers/ipc/ShadowLayerUtilsMac.cpp
+++ b/gfx/layers/ipc/ShadowLayerUtilsMac.cpp
@@ -16,26 +16,103 @@
 
 #include "gfxSharedQuartzSurface.h"
 
 using namespace mozilla::gl;
 
 namespace mozilla {
 namespace layers {
 
+bool
+ISurfaceAllocator::PlatformAllocSurfaceDescriptor(const gfx::IntSize& aSize,
+                                                  gfxContentType aContent,
+                                                  uint32_t aCaps,
+                                                  SurfaceDescriptor* aBuffer)
+{
+  return false;
+}
+
+/*static*/ already_AddRefed<gfxASurface>
+ShadowLayerForwarder::PlatformOpenDescriptor(OpenMode aMode,
+                                             const SurfaceDescriptor& aSurface)
+{
+  if (aSurface.type() == SurfaceDescriptor::TShmem) {
+    return gfxSharedQuartzSurface::Open(aSurface.get_Shmem());
+  } else if (aSurface.type() == SurfaceDescriptor::TMemoryImage) {
+    const MemoryImage& image = aSurface.get_MemoryImage();
+    gfxImageFormat format
+      = static_cast<gfxImageFormat>(image.format());
+
+    nsRefPtr<gfxASurface> surf =
+      new gfxQuartzSurface((unsigned char*)image.data(),
+                           gfx::ThebesIntSize(image.size()),
+                           image.stride(),
+                           format);
+    return surf.forget();
+
+  }
+  return nullptr;
+}
+
+/*static*/ bool
+ShadowLayerForwarder::PlatformCloseDescriptor(const SurfaceDescriptor& aDescriptor)
+{
+  return false;
+}
+
+/*static*/ bool
+ShadowLayerForwarder::PlatformGetDescriptorSurfaceContentType(
+  const SurfaceDescriptor& aDescriptor, OpenMode aMode,
+  gfxContentType* aContent,
+  gfxASurface** aSurface)
+{
+  return false;
+}
+
+/*static*/ bool
+ShadowLayerForwarder::PlatformGetDescriptorSurfaceSize(
+  const SurfaceDescriptor& aDescriptor, OpenMode aMode,
+  gfx::IntSize* aSize,
+  gfxASurface** aSurface)
+{
+  return false;
+}
+
+/*static*/ bool
+ShadowLayerForwarder::PlatformGetDescriptorSurfaceImageFormat(
+  const SurfaceDescriptor&,
+  OpenMode,
+  gfxImageFormat*,
+  gfxASurface**)
+{
+  return false;
+}
+
+bool
+ShadowLayerForwarder::PlatformDestroySharedSurface(SurfaceDescriptor* aSurface)
+{
+  return false;
+}
+
 /*static*/ void
 ShadowLayerForwarder::PlatformSyncBeforeUpdate()
 {
 }
 
 /*static*/ void
 LayerManagerComposite::PlatformSyncBeforeReplyUpdate()
 {
 }
 
+bool
+ISurfaceAllocator::PlatformDestroySharedSurface(SurfaceDescriptor*)
+{
+  return false;
+}
+
 /*static*/ bool
 LayerManagerComposite::SupportsDirectTexturing()
 {
   return false;
 }
 
 
 } // namespace layers
--- a/gfx/layers/ipc/ShadowLayerUtilsX11.cpp
+++ b/gfx/layers/ipc/ShadowLayerUtilsX11.cpp
@@ -58,16 +58,27 @@ UsingXCompositing()
 static XRenderPictFormat*
 GetXRenderPictFormatFromId(Display* aDisplay, PictFormat aFormatId)
 {
   XRenderPictFormat tmplate;
   tmplate.id = aFormatId;
   return XRenderFindFormat(aDisplay, PictFormatID, &tmplate, 0);
 }
 
+static bool
+TakeAndDestroyXlibSurface(SurfaceDescriptor* aSurface)
+{
+  nsRefPtr<gfxXlibSurface> surf =
+    aSurface->get_SurfaceDescriptorX11().OpenForeign();
+  surf->TakePixmap();
+  *aSurface = SurfaceDescriptor();
+  // the Pixmap is destroyed when |surf| goes out of scope
+  return true;
+}
+
 SurfaceDescriptorX11::SurfaceDescriptorX11(gfxXlibSurface* aSurf)
   : mId(aSurf->XDrawable())
   , mSize(aSurf->GetSize().ToIntSize())
 {
   const XRenderPictFormat *pictFormat = aSurf->XRenderFormat();
   if (pictFormat) {
     mFormat = pictFormat->id;
   } else {
@@ -99,16 +110,105 @@ SurfaceDescriptorX11::OpenForeign() cons
     if (!visual)
       return nullptr;
 
     surf = new gfxXlibSurface(display, mId, visual, gfx::ThebesIntSize(mSize));
   }
   return surf->CairoStatus() ? nullptr : surf.forget();
 }
 
+bool
+ISurfaceAllocator::PlatformAllocSurfaceDescriptor(const gfx::IntSize& aSize,
+                                                  gfxContentType aContent,
+                                                  uint32_t aCaps,
+                                                  SurfaceDescriptor* aBuffer)
+{
+  if (!UsingXCompositing()) {
+    // If we're not using X compositing, we're probably compositing on
+    // the client side, in which case X surfaces would just slow
+    // things down.  Use Shmem instead.
+    return false;
+  }
+  if (MAP_AS_IMAGE_SURFACE & aCaps) {
+    // We can't efficiently map pixmaps as gfxImageSurface, in
+    // general.  Fall back on Shmem.
+    return false;
+  }
+
+  gfxPlatform* platform = gfxPlatform::GetPlatform();
+  nsRefPtr<gfxASurface> buffer =
+    platform->CreateOffscreenSurface(aSize, aContent);
+  if (!buffer ||
+      buffer->GetType() != gfxSurfaceType::Xlib) {
+    NS_ERROR("creating Xlib front/back surfaces failed!");
+    return false;
+  }
+
+  gfxXlibSurface* bufferX = static_cast<gfxXlibSurface*>(buffer.get());
+  // Release Pixmap ownership to the layers model
+  bufferX->ReleasePixmap();
+
+  *aBuffer = SurfaceDescriptorX11(bufferX);
+  return true;
+}
+
+/*static*/ already_AddRefed<gfxASurface>
+ShadowLayerForwarder::PlatformOpenDescriptor(OpenMode aMode,
+                                             const SurfaceDescriptor& aSurface)
+{
+  if (SurfaceDescriptor::TSurfaceDescriptorX11 != aSurface.type()) {
+    return nullptr;
+  }
+  return aSurface.get_SurfaceDescriptorX11().OpenForeign();
+}
+
+/*static*/ bool
+ShadowLayerForwarder::PlatformCloseDescriptor(const SurfaceDescriptor& aDescriptor)
+{
+  // XIDs don't need to be "closed".
+  return false;
+}
+
+/*static*/ bool
+ShadowLayerForwarder::PlatformGetDescriptorSurfaceContentType(
+  const SurfaceDescriptor& aDescriptor, OpenMode aMode,
+  gfxContentType* aContent,
+  gfxASurface** aSurface)
+{
+  return false;
+}
+
+/*static*/ bool
+ShadowLayerForwarder::PlatformGetDescriptorSurfaceSize(
+  const SurfaceDescriptor& aDescriptor, OpenMode aMode,
+  gfx::IntSize* aSize,
+  gfxASurface** aSurface)
+{
+  return false;
+}
+
+/*static*/ bool
+ShadowLayerForwarder::PlatformGetDescriptorSurfaceImageFormat(
+  const SurfaceDescriptor&,
+  OpenMode,
+  gfxImageFormat*,
+  gfxASurface**)
+{
+  return false;
+}
+
+bool
+ShadowLayerForwarder::PlatformDestroySharedSurface(SurfaceDescriptor* aSurface)
+{
+  if (SurfaceDescriptor::TSurfaceDescriptorX11 != aSurface->type()) {
+    return false;
+  }
+  return TakeAndDestroyXlibSurface(aSurface);
+}
+
 /*static*/ void
 ShadowLayerForwarder::PlatformSyncBeforeUpdate()
 {
   if (UsingXCompositing()) {
     // If we're using X surfaces, then we need to finish all pending
     // operations on the back buffers before handing them to the
     // parent, otherwise the surface might be used by the parent's
     // Display in between two operations queued by our Display.
@@ -130,10 +230,19 @@ LayerManagerComposite::PlatformSyncBefor
 }
 
 /*static*/ bool
 LayerManagerComposite::SupportsDirectTexturing()
 {
   return false;
 }
 
+bool
+ISurfaceAllocator::PlatformDestroySharedSurface(SurfaceDescriptor* aSurface)
+{
+  if (SurfaceDescriptor::TSurfaceDescriptorX11 != aSurface->type()) {
+    return false;
+  }
+  return TakeAndDestroyXlibSurface(aSurface);
+}
+
 } // namespace layers
 } // namespace mozilla
--- a/gfx/layers/ipc/ShadowLayers.cpp
+++ b/gfx/layers/ipc/ShadowLayers.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 "ShadowLayers.h"
 #include <set>                          // for _Rb_tree_const_iterator, etc
 #include <vector>                       // for vector
+#include "AutoOpenSurface.h"            // for AutoOpenSurface, etc
 #include "GeckoProfiler.h"              // for PROFILER_LABEL
 #include "ISurfaceAllocator.h"          // for IsSurfaceDescriptorValid
 #include "Layers.h"                     // for Layer
 #include "RenderTrace.h"                // for RenderTraceScope
 #include "ShadowLayerChild.h"           // for ShadowLayerChild
 #include "gfx2DGlue.h"                  // for Moz2D transition helpers
 #include "gfxImageSurface.h"            // for gfxImageSurface
 #include "gfxPlatform.h"                // for gfxImageFormat, gfxPlatform
@@ -114,36 +115,48 @@ public:
     NS_ABORT_IF_FALSE(!Finished(), "forgot BeginTransaction?");
     mPaints.push_back(Edit(aPaint));
   }
   void AddMutant(ShadowableLayer* aLayer)
   {
     NS_ABORT_IF_FALSE(!Finished(), "forgot BeginTransaction?");
     mMutants.insert(aLayer);
   }
+  void AddBufferToDestroy(gfxSharedImageSurface* aBuffer)
+  {
+    return AddBufferToDestroy(aBuffer->GetShmem());
+  }
+  void AddBufferToDestroy(const SurfaceDescriptor& aBuffer)
+  {
+    NS_ABORT_IF_FALSE(!Finished(), "forgot BeginTransaction?");
+    mDyingBuffers.AppendElement(aBuffer);
+  }
+
   void End()
   {
     mCset.clear();
     mPaints.clear();
+    mDyingBuffers.Clear();
     mMutants.clear();
     mOpen = false;
     mSwapRequired = false;
     mRotationChanged = false;
   }
 
   bool Empty() const {
     return mCset.empty() && mPaints.empty() && mMutants.empty();
   }
   bool RotationChanged() const {
     return mRotationChanged;
   }
   bool Finished() const { return !mOpen && Empty(); }
 
   EditVector mCset;
   EditVector mPaints;
+  BufferArray mDyingBuffers;
   ShadowableLayerSet mMutants;
   nsIntRect mTargetBounds;
   ScreenRotation mTargetRotation;
   nsIntRect mClientBounds;
   ScreenOrientation mTargetOrientation;
   bool mSwapRequired;
 
 private:
@@ -231,16 +244,22 @@ ShadowLayerForwarder::CreatedCanvasLayer
 }
 void
 ShadowLayerForwarder::CreatedRefLayer(ShadowableLayer* aRef)
 {
   CreatedLayer<OpCreateRefLayer>(mTxn, aRef);
 }
 
 void
+ShadowLayerForwarder::DestroyedThebesBuffer(const SurfaceDescriptor& aBackBufferToDestroy)
+{
+  mTxn->AddBufferToDestroy(aBackBufferToDestroy);
+}
+
+void
 ShadowLayerForwarder::Mutated(ShadowableLayer* aMutant)
 {
 mTxn->AddMutant(aMutant);
 }
 
 void
 ShadowLayerForwarder::SetRoot(ShadowableLayer* aRoot)
 {
@@ -292,21 +311,21 @@ ShadowLayerForwarder::RepositionChild(Sh
 #ifdef DEBUG
 void
 ShadowLayerForwarder::CheckSurfaceDescriptor(const SurfaceDescriptor* aDescriptor) const
 {
   if (!aDescriptor) {
     return;
   }
 
-  if (aDescriptor->type() == SurfaceDescriptor::TSurfaceDescriptorShmem) {
-    const SurfaceDescriptorShmem& shmem = aDescriptor->get_SurfaceDescriptorShmem();
-    shmem.data().AssertInvariants();
+  if (aDescriptor->type() == SurfaceDescriptor::TShmem) {
+    const mozilla::ipc::Shmem& shmem = aDescriptor->get_Shmem();
+    shmem.AssertInvariants();
     MOZ_ASSERT(mShadowManager &&
-               mShadowManager->IsTrackingSharedMemory(shmem.data().mSegment));
+               mShadowManager->IsTrackingSharedMemory(shmem.mSegment));
   }
 }
 #endif
 
 void
 ShadowLayerForwarder::UseTiledLayerBuffer(CompositableClient* aCompositable,
                                           const SurfaceDescriptorTiles& aTileLayerDescriptor)
 {
@@ -432,16 +451,20 @@ ShadowLayerForwarder::EndTransaction(Inf
 
   if (mTxn->Empty() && !mTxn->RotationChanged() && !mWindowOverlayChanged) {
     MOZ_LAYERS_LOG(("[LayersForwarder] 0-length cset (?) and no rotation event, skipping Update()"));
     return true;
   }
 
   MOZ_LAYERS_LOG(("[LayersForwarder] destroying buffers..."));
 
+  for (uint32_t i = 0; i < mTxn->mDyingBuffers.Length(); ++i) {
+    DestroySharedSurface(&mTxn->mDyingBuffers[i]);
+  }
+
   MOZ_LAYERS_LOG(("[LayersForwarder] building transaction..."));
 
   // We purposely add attribute-change ops to the final changeset
   // before we add paint ops.  This allows layers to record the
   // attribute changes before new pixels arrive, which can be useful
   // for setting up back/front buffers.
   RenderTraceScope rendertrace2("Foward Transaction", "000092");
   for (ShadowableLayerSet::const_iterator it = mTxn->mMutants.begin();
@@ -572,37 +595,269 @@ ShadowLayerForwarder::IPCOpen() const
 }
 
 bool
 ShadowLayerForwarder::IsSameProcess() const
 {
   return mShadowManager->OtherProcess() == kInvalidProcessHandle;
 }
 
+/*static*/ already_AddRefed<gfxASurface>
+ShadowLayerForwarder::OpenDescriptor(OpenMode aMode,
+                                     const SurfaceDescriptor& aSurface)
+{
+  nsRefPtr<gfxASurface> surf = PlatformOpenDescriptor(aMode, aSurface);
+  if (surf) {
+    return surf.forget();
+  }
+
+  switch (aSurface.type()) {
+  case SurfaceDescriptor::TShmem: {
+    surf = gfxSharedImageSurface::Open(aSurface.get_Shmem());
+    return surf.forget();
+  } case SurfaceDescriptor::TRGBImage: {
+    const RGBImage& rgb = aSurface.get_RGBImage();
+    gfxImageFormat rgbFormat
+      = static_cast<gfxImageFormat>(rgb.rgbFormat());
+    uint32_t stride = gfxASurface::BytesPerPixel(rgbFormat) * rgb.picture().width;
+    nsIntSize size(rgb.picture().width, rgb.picture().height);
+    surf = new gfxImageSurface(rgb.data().get<uint8_t>(),
+                               size,
+                               stride,
+                               rgbFormat);
+    return surf.forget();
+  }
+  case SurfaceDescriptor::TMemoryImage: {
+    const MemoryImage& image = aSurface.get_MemoryImage();
+    gfxImageFormat format
+      = static_cast<gfxImageFormat>(image.format());
+    surf = new gfxImageSurface((unsigned char *)image.data(),
+                               gfx::ThebesIntSize(image.size()),
+                               image.stride(),
+                               format);
+    return surf.forget();
+  }
+  default:
+    NS_ERROR("unexpected SurfaceDescriptor type!");
+    return nullptr;
+  }
+}
+
+/*static*/ gfxContentType
+ShadowLayerForwarder::GetDescriptorSurfaceContentType(
+  const SurfaceDescriptor& aDescriptor, OpenMode aMode,
+  gfxASurface** aSurface)
+{
+  gfxContentType content;
+  if (PlatformGetDescriptorSurfaceContentType(aDescriptor, aMode,
+                                              &content, aSurface)) {
+    return content;
+  }
+
+  nsRefPtr<gfxASurface> surface = OpenDescriptor(aMode, aDescriptor);
+  content = surface->GetContentType();
+  surface.forget(aSurface);
+  return content;
+}
+
+/*static*/ gfx::IntSize
+ShadowLayerForwarder::GetDescriptorSurfaceSize(
+  const SurfaceDescriptor& aDescriptor, OpenMode aMode,
+  gfxASurface** aSurface)
+{
+  gfx::IntSize size;
+  if (PlatformGetDescriptorSurfaceSize(aDescriptor, aMode, &size, aSurface)) {
+    return size;
+  }
+
+  nsRefPtr<gfxASurface> surface = OpenDescriptor(aMode, aDescriptor);
+  size = surface->GetSize().ToIntSize();
+  surface.forget(aSurface);
+  return size;
+}
+
+/*static*/ gfxImageFormat
+ShadowLayerForwarder::GetDescriptorSurfaceImageFormat(
+  const SurfaceDescriptor& aDescriptor, OpenMode aMode,
+  gfxASurface** aSurface)
+{
+  gfxImageFormat format;
+  if (PlatformGetDescriptorSurfaceImageFormat(aDescriptor, aMode, &format, aSurface)) {
+    return format;
+  }
+
+  nsRefPtr<gfxASurface> surface = OpenDescriptor(aMode, aDescriptor);
+  NS_ENSURE_TRUE(surface, gfxImageFormat::Unknown);
+
+  nsRefPtr<gfxImageSurface> img = surface->GetAsImageSurface();
+  NS_ENSURE_TRUE(img, gfxImageFormat::Unknown);
+
+  format = img->Format();
+  NS_ASSERTION(format != gfxImageFormat::Unknown,
+               "ImageSurface RGB format should be known");
+
+  surface.forget(aSurface);
+  return format;
+}
+
+/*static*/ void
+ShadowLayerForwarder::CloseDescriptor(const SurfaceDescriptor& aDescriptor)
+{
+  PlatformCloseDescriptor(aDescriptor);
+  // There's no "close" needed for Shmem surfaces.
+}
+
 /**
   * We bail out when we have no shadow manager. That can happen when the
   * layer manager is created by the preallocated process.
   * See bug 914843 for details.
   */
 PLayerChild*
 ShadowLayerForwarder::ConstructShadowFor(ShadowableLayer* aLayer)
 {
   NS_ABORT_IF_FALSE(HasShadowManager(), "no manager to forward to");
   return mShadowManager->SendPLayerConstructor(new ShadowLayerChild(aLayer));
 }
 
 #if !defined(MOZ_HAVE_PLATFORM_SPECIFIC_LAYER_BUFFERS)
 
+/*static*/ already_AddRefed<gfxASurface>
+ShadowLayerForwarder::PlatformOpenDescriptor(OpenMode,
+                                             const SurfaceDescriptor&)
+{
+  return nullptr;
+}
+
+/*static*/ bool
+ShadowLayerForwarder::PlatformCloseDescriptor(const SurfaceDescriptor&)
+{
+  return false;
+}
+
+/*static*/ bool
+ShadowLayerForwarder::PlatformGetDescriptorSurfaceContentType(
+  const SurfaceDescriptor&,
+  OpenMode,
+  gfxContentType*,
+  gfxASurface**)
+{
+  return false;
+}
+
+/*static*/ bool
+ShadowLayerForwarder::PlatformGetDescriptorSurfaceSize(
+  const SurfaceDescriptor&,
+  OpenMode,
+  gfx::IntSize*,
+  gfxASurface**)
+{
+  return false;
+}
+
+/*static*/ bool
+ShadowLayerForwarder::PlatformGetDescriptorSurfaceImageFormat(
+  const SurfaceDescriptor&,
+  OpenMode,
+  gfxImageFormat*,
+  gfxASurface**)
+{
+  return false;
+}
+
+bool
+ShadowLayerForwarder::PlatformDestroySharedSurface(SurfaceDescriptor*)
+{
+  return false;
+}
+
 /*static*/ void
 ShadowLayerForwarder::PlatformSyncBeforeUpdate()
 {
 }
 
+bool
+ISurfaceAllocator::PlatformDestroySharedSurface(SurfaceDescriptor*)
+{
+  return false;
+}
+
 #endif  // !defined(MOZ_HAVE_PLATFORM_SPECIFIC_LAYER_BUFFERS)
 
+AutoOpenSurface::AutoOpenSurface(OpenMode aMode,
+                                 const SurfaceDescriptor& aDescriptor)
+  : mDescriptor(aDescriptor)
+  , mMode(aMode)
+{
+  MOZ_ASSERT(IsSurfaceDescriptorValid(mDescriptor));
+}
+
+AutoOpenSurface::~AutoOpenSurface()
+{
+  if (mSurface) {
+    mSurface = nullptr;
+    ShadowLayerForwarder::CloseDescriptor(mDescriptor);
+  }
+}
+
+gfxContentType
+AutoOpenSurface::ContentType()
+{
+  if (mSurface) {
+    return mSurface->GetContentType();
+  }
+  return ShadowLayerForwarder::GetDescriptorSurfaceContentType(
+    mDescriptor, mMode, getter_AddRefs(mSurface));
+}
+
+gfxImageFormat
+AutoOpenSurface::ImageFormat()
+{
+  if (mSurface) {
+    nsRefPtr<gfxImageSurface> img = mSurface->GetAsImageSurface();
+    if (img) {
+      gfxImageFormat format = img->Format();
+      NS_ASSERTION(format != gfxImageFormat::Unknown,
+                   "ImageSurface RGB format should be known");
+
+      return format;
+    }
+  }
+
+  return ShadowLayerForwarder::GetDescriptorSurfaceImageFormat(
+    mDescriptor, mMode, getter_AddRefs(mSurface));
+}
+
+gfx::IntSize
+AutoOpenSurface::Size()
+{
+  if (mSurface) {
+    return mSurface->GetSize().ToIntSize();
+  }
+  return ShadowLayerForwarder::GetDescriptorSurfaceSize(
+    mDescriptor, mMode, getter_AddRefs(mSurface));
+}
+
+gfxASurface*
+AutoOpenSurface::Get()
+{
+  if (!mSurface) {
+    mSurface = ShadowLayerForwarder::OpenDescriptor(mMode, mDescriptor);
+  }
+  return mSurface.get();
+}
+
+gfxImageSurface*
+AutoOpenSurface::GetAsImage()
+{
+  if (!mSurfaceAsImage) {
+    mSurfaceAsImage = Get()->GetAsImageSurface();
+  }
+  return mSurfaceAsImage.get();
+}
+
 void
 ShadowLayerForwarder::Connect(CompositableClient* aCompositable)
 {
 #ifdef GFX_COMPOSITOR_LOGGING
   printf("ShadowLayerForwarder::Connect(Compositable)\n");
 #endif
   MOZ_ASSERT(aCompositable);
   MOZ_ASSERT(mShadowManager);
--- a/gfx/layers/ipc/ShadowLayers.h
+++ b/gfx/layers/ipc/ShadowLayers.h
@@ -43,16 +43,17 @@ class ImageLayerComposite;
 class Layer;
 class OptionalThebesBuffer;
 class PLayerChild;
 class PLayerTransactionChild;
 class PLayerTransactionParent;
 class LayerTransactionChild;
 class RefLayerComposite;
 class ShadowableLayer;
+class Shmem;
 class ShmemTextureClient;
 class SurfaceDescriptor;
 class TextureClient;
 class ThebesLayerComposite;
 class ThebesBuffer;
 class ThebesBufferData;
 class TiledLayerComposer;
 class Transaction;
@@ -128,16 +129,17 @@ class Transaction;
  * are always between the content thread and the compositor thread.
  * Compositable transactions are subset of a layer transaction with which only
  * compositables and textures can be manipulated, and does not always originate
  * from the content thread. (See CompositableForwarder.h and ImageBridgeChild.h)
  */
 
 class ShadowLayerForwarder : public CompositableForwarder
 {
+  friend class AutoOpenSurface;
   friend class ContentClientIncremental;
   friend class ClientLayerManager;
 
 public:
   virtual ~ShadowLayerForwarder();
 
   /**
    * Setup the IPDL actor for aCompositable to be part of layers
@@ -194,16 +196,26 @@ public:
   void CreatedThebesLayer(ShadowableLayer* aThebes);
   void CreatedContainerLayer(ShadowableLayer* aContainer);
   void CreatedImageLayer(ShadowableLayer* aImage);
   void CreatedColorLayer(ShadowableLayer* aColor);
   void CreatedCanvasLayer(ShadowableLayer* aCanvas);
   void CreatedRefLayer(ShadowableLayer* aRef);
 
   /**
+   * The specified layer is destroying its buffers.
+   * |aBackBufferToDestroy| is deallocated when this transaction is
+   * posted to the parent.  During the parent-side transaction, the
+   * shadow is told to destroy its front buffer.  This can happen when
+   * a new front/back buffer pair have been created because of a layer
+   * resize, e.g.
+   */
+  virtual void DestroyedThebesBuffer(const SurfaceDescriptor& aBackBufferToDestroy) MOZ_OVERRIDE;
+
+  /**
    * At least one attribute of |aMutant| has changed, and |aMutant|
    * needs to sync to its shadow layer.  This initial implementation
    * forwards all attributes when any is mutated.
    */
   void Mutated(ShadowableLayer* aMutant);
 
   void SetRoot(ShadowableLayer* aRoot);
   /**
@@ -361,16 +373,19 @@ public:
 
   /**
    * Flag the next paint as the first for a document.
    */
   void SetIsFirstPaint() { mIsFirstPaint = true; }
 
   static void PlatformSyncBeforeUpdate();
 
+  static already_AddRefed<gfxASurface>
+  OpenDescriptor(OpenMode aMode, const SurfaceDescriptor& aSurface);
+
 protected:
   ShadowLayerForwarder();
 
 #ifdef DEBUG
   void CheckSurfaceDescriptor(const SurfaceDescriptor* aDescriptor) const;
 #else
   void CheckSurfaceDescriptor(const SurfaceDescriptor* aDescriptor) const {}
 #endif
@@ -383,16 +398,71 @@ protected:
                                                   uint32_t aFormat,
                                                   uint32_t aUsage,
                                                   MaybeMagicGrallocBufferHandle* aHandle) MOZ_OVERRIDE;
 
   virtual void DeallocGrallocBuffer(PGrallocBufferChild* aChild) MOZ_OVERRIDE;
 #endif
 
 private:
+  /**
+   * Try to query the content type efficiently, but at worst map the
+   * surface and return it in *aSurface.
+   */
+  static gfxContentType
+  GetDescriptorSurfaceContentType(const SurfaceDescriptor& aDescriptor,
+                                  OpenMode aMode,
+                                  gfxASurface** aSurface);
+  /**
+   * It can be expensive to open a descriptor just to query its
+   * content type.  If the platform impl can do this cheaply, it will
+   * set *aContent and return true.
+   */
+  static bool
+  PlatformGetDescriptorSurfaceContentType(const SurfaceDescriptor& aDescriptor,
+                                          OpenMode aMode,
+                                          gfxContentType* aContent,
+                                          gfxASurface** aSurface);
+  // (Same as above, but for surface size.)
+  static gfx::IntSize
+  GetDescriptorSurfaceSize(const SurfaceDescriptor& aDescriptor,
+                           OpenMode aMode,
+                           gfxASurface** aSurface);
+  static bool
+  PlatformGetDescriptorSurfaceSize(const SurfaceDescriptor& aDescriptor,
+                                   OpenMode aMode,
+                                   gfx::IntSize* aSize,
+                                   gfxASurface** aSurface);
+  // And again, for the image format.
+  // This function will return gfxImageFormat::Unknown only if |aDescriptor|
+  // describes a non-ImageSurface.
+  static gfxImageFormat
+  GetDescriptorSurfaceImageFormat(const SurfaceDescriptor& aDescriptor,
+                                  OpenMode aMode,
+                                  gfxASurface** aSurface);
+  static bool
+  PlatformGetDescriptorSurfaceImageFormat(const SurfaceDescriptor& aDescriptor,
+                                          OpenMode aMode,
+                                          gfxImageFormat* aContent,
+                                          gfxASurface** aSurface);
+
+  static already_AddRefed<gfxASurface>
+  PlatformOpenDescriptor(OpenMode aMode, const SurfaceDescriptor& aDescriptor);
+
+  /**
+   * Make this descriptor unusable for gfxASurface clients. A
+   * private interface with AutoOpenSurface.
+   */
+  static void
+  CloseDescriptor(const SurfaceDescriptor& aDescriptor);
+
+  static bool
+  PlatformCloseDescriptor(const SurfaceDescriptor& aDescriptor);
+
+  bool PlatformDestroySharedSurface(SurfaceDescriptor* aSurface);
 
   Transaction* mTxn;
   DiagnosticTypes mDiagnosticTypes;
   bool mIsFirstPaint;
   bool mWindowOverlayChanged;
 };
 
 class CompositableClient;
--- a/gfx/layers/opengl/GrallocTextureClient.cpp
+++ b/gfx/layers/opengl/GrallocTextureClient.cpp
@@ -31,17 +31,22 @@ public:
   ~GrallocTextureClientData()
   {
     MOZ_COUNT_DTOR(GrallocTextureClientData);
     MOZ_ASSERT(!mGrallocActor);
   }
 
   virtual void DeallocateSharedData(ISurfaceAllocator* allocator) MOZ_OVERRIDE
   {
-    allocator->DeallocGrallocBuffer(mGrallocActor);
+    // We just need to wrap the actor in a SurfaceDescriptor because that's what
+    // ISurfaceAllocator uses as input, we don't care about the other parameters.
+    SurfaceDescriptor sd = SurfaceDescriptorGralloc(nullptr, mGrallocActor,
+                                                    IntSize(0, 0),
+                                                    false, false);
+    allocator->DestroySharedSurface(&sd);
     mGrallocActor = nullptr;
   }
 
 private:
   GrallocBufferActor* mGrallocActor;
 };
 
 TextureClientData*
@@ -75,18 +80,26 @@ GrallocTextureClientOGL::GrallocTextureC
 {
   MOZ_COUNT_CTOR(GrallocTextureClientOGL);
 }
 
 GrallocTextureClientOGL::~GrallocTextureClientOGL()
 {
   MOZ_COUNT_DTOR(GrallocTextureClientOGL);
     if (ShouldDeallocateInDestructor()) {
+    // If the buffer has never been shared we must deallocate it or it would
+    // leak.
+    // We just need to wrap the actor in a SurfaceDescriptor because that's what
+    // ISurfaceAllocator uses as input, we don't care about the other parameters.
+    SurfaceDescriptor sd = SurfaceDescriptorGralloc(nullptr, mGrallocActor,
+                                                    IntSize(0, 0),
+                                                    false, false);
+
     ISurfaceAllocator* allocator = GetAllocator();
-    allocator->DeallocGrallocBuffer(mGrallocActor);
+    allocator->DestroySharedSurface(&sd);
   }
 }
 
 void
 GrallocTextureClientOGL::InitWith(GrallocBufferActor* aActor, gfx::IntSize aSize)
 {
   MOZ_ASSERT(aActor);
   MOZ_ASSERT(!IsAllocated());
--- a/gfx/layers/opengl/TextureHostOGL.cpp
+++ b/gfx/layers/opengl/TextureHostOGL.cpp
@@ -12,16 +12,17 @@
 #include "SharedSurfaceEGL.h"           // for SharedSurface_EGLImage
 #include "SharedSurfaceGL.h"            // for SharedSurface_GLTexture, etc
 #include "SurfaceStream.h"              // for SurfaceStream
 #include "SurfaceTypes.h"               // for SharedSurfaceType, etc
 #include "TiledLayerBuffer.h"           // for TILEDLAYERBUFFER_TILE_SIZE
 #include "gfx2DGlue.h"                  // for ContentForFormat, etc
 #include "gfxImageSurface.h"            // for gfxImageSurface
 #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"
--- a/media/webrtc/signaling/src/mediapipeline/MediaPipeline.cpp
+++ b/media/webrtc/signaling/src/mediapipeline/MediaPipeline.cpp
@@ -20,17 +20,16 @@
 #ifdef MOZILLA_INTERNAL_API
 #include "VideoSegment.h"
 #include "Layers.h"
 #include "ImageTypes.h"
 #include "ImageContainer.h"
 #include "VideoUtils.h"
 #ifdef MOZ_WIDGET_GONK
 #include "GrallocImages.h"
-#include "mozilla/layers/GrallocTextureClient.h"
 #endif
 #endif
 
 #include "nsError.h"
 #include "AudioSegment.h"
 #include "MediaSegment.h"
 #include "databuffer.h"
 #include "transportflow.h"
@@ -1108,20 +1107,20 @@ void MediaPipelineTransmit::PipelineList
     return;
   }
   last_img_ = serial;
 
   ImageFormat format = img->GetFormat();
 #ifdef MOZ_WIDGET_GONK
   if (format == ImageFormat::GRALLOC_PLANAR_YCBCR) {
     layers::GrallocImage *nativeImage = static_cast<layers::GrallocImage*>(img);
-    layers::GrallocTextureClientOGL* client =
-      static_cast<layers::GrallocTextureClientOGL*>(nativeImage->GetTextureClient(nullptr));
+    layers::SurfaceDescriptor handle = nativeImage->GetSurfaceDescriptor();
+    layers::SurfaceDescriptorGralloc grallocHandle = handle.get_SurfaceDescriptorGralloc();
 
-    android::sp<android::GraphicBuffer> graphicBuffer = client->GetGraphicBuffer();
+    android::sp<android::GraphicBuffer> graphicBuffer = layers::GrallocBufferActor::GetFrom(grallocHandle);
     void *basePtr;
     graphicBuffer->lock(android::GraphicBuffer::USAGE_SW_READ_MASK, &basePtr);
     conduit->SendVideoFrame(static_cast<unsigned char*>(basePtr),
                             (graphicBuffer->getWidth() * graphicBuffer->getHeight() * 3) / 2,
                             graphicBuffer->getWidth(),
                             graphicBuffer->getHeight(),
                             mozilla::kVideoNV21, 0);
     graphicBuffer->unlock();