Bug 1200595 - Gralloc TextureData implementation. r=sotaro
☠☠ backed out by 9783264529d3 ☠ ☠
authorNicolas Silva <nsilva@mozilla.com>
Thu, 15 Oct 2015 17:53:37 +0200
changeset 273900 0dc93424546c50a7b74b2ae78d0cb4b3919ea58c
parent 273899 8cc12f12f3d1916c87d14871e86b1c5ad17ead43
child 273901 ed34bc528a1b7ab01d2b36dddf60c58b00c16246
push id68425
push usernsilva@mozilla.com
push dateTue, 24 Nov 2015 11:20:28 +0000
treeherdermozilla-inbound@cf8cf1a039dd [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssotaro
bugs1200595
milestone45.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1200595 - Gralloc TextureData implementation. r=sotaro
dom/media/omx/OmxDecoder.cpp
dom/media/platforms/gonk/GonkVideoDecoderManager.cpp
dom/media/webrtc/MediaEngineGonkVideoSource.cpp
gfx/gl/SharedSurfaceGralloc.cpp
gfx/gl/SharedSurfaceGralloc.h
gfx/layers/BufferTexture.h
gfx/layers/GrallocImages.cpp
gfx/layers/GrallocImages.h
gfx/layers/basic/GrallocTextureHostBasic.cpp
gfx/layers/basic/TextureClientX11.cpp
gfx/layers/basic/TextureClientX11.h
gfx/layers/client/TextureClient.cpp
gfx/layers/client/TextureClient.h
gfx/layers/client/TextureClientSharedSurface.cpp
gfx/layers/opengl/GrallocTextureClient.cpp
gfx/layers/opengl/GrallocTextureClient.h
widget/gonk/nativewindow/GonkBufferQueueJB.cpp
widget/gonk/nativewindow/GonkBufferQueueKK.cpp
widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferQueueProducer.cpp
widget/gonk/nativewindow/GonkNativeWindowICS.cpp
--- a/dom/media/omx/OmxDecoder.cpp
+++ b/dom/media/omx/OmxDecoder.cpp
@@ -349,20 +349,20 @@ OmxDecoder::ReleaseMediaResources() {
     MOZ_ASSERT(mPendingRecycleTexutreClients.empty());
     // Release all pending recycle TextureClients, if they are not recycled yet.
     // This should not happen. See Bug 1042308.
     if (!mPendingRecycleTexutreClients.empty()) {
       printf_stderr("OmxDecoder::ReleaseMediaResources -- TextureClients are not recycled yet\n");
       for (std::set<TextureClient*>::iterator it=mPendingRecycleTexutreClients.begin();
            it!=mPendingRecycleTexutreClients.end(); it++)
       {
-        GrallocTextureClientOGL* client = static_cast<GrallocTextureClientOGL*>(*it);
-        client->ClearRecycleCallback();
+        GrallocTextureData* client = static_cast<GrallocTextureData*>((*it)->GetInternalData());
+        (*it)->ClearRecycleCallback();
         if (client->GetMediaBuffer()) {
-          mPendingVideoBuffers.push(BufferItem(client->GetMediaBuffer(), client->GetAndResetReleaseFenceHandle()));
+          mPendingVideoBuffers.push(BufferItem(client->GetMediaBuffer(), (*it)->GetAndResetReleaseFenceHandle()));
         }
       }
       mPendingRecycleTexutreClients.clear();
     }
   }
 
   {
     // Free all pending video buffers.
@@ -648,18 +648,17 @@ OmxDecoder::ReadVideo(VideoFrame *aFrame
     if ((mVideoBuffer->graphicBuffer().get())) {
       textureClient = mNativeWindow->getTextureClientFromBuffer(mVideoBuffer->graphicBuffer().get());
     }
 
     if (textureClient) {
       // Manually increment reference count to keep MediaBuffer alive
       // during TextureClient is in use.
       mVideoBuffer->add_ref();
-      GrallocTextureClientOGL* grallocClient = static_cast<GrallocTextureClientOGL*>(textureClient.get());
-      grallocClient->SetMediaBuffer(mVideoBuffer);
+      static_cast<GrallocTextureData*>(textureClient->GetInternalData())->SetMediaBuffer(mVideoBuffer);
       // Set recycle callback for TextureClient
       textureClient->SetRecycleCallback(OmxDecoder::RecycleCallback, this);
       {
         Mutex::Autolock autoLock(mPendingVideoBuffersLock);
         // Store pending recycle TextureClient.
         MOZ_ASSERT(mPendingRecycleTexutreClients.find(textureClient) == mPendingRecycleTexutreClients.end());
         mPendingRecycleTexutreClients.insert(textureClient);
       }
@@ -912,19 +911,19 @@ OmxDecoder::RecycleCallbackImp(TextureCl
   aClient->ClearRecycleCallback();
   {
     Mutex::Autolock autoLock(mPendingVideoBuffersLock);
     if (mPendingRecycleTexutreClients.find(aClient) == mPendingRecycleTexutreClients.end()) {
       printf_stderr("OmxDecoder::RecycleCallbackImp -- TextureClient is not pending recycle\n");
       return;
     }
     mPendingRecycleTexutreClients.erase(aClient);
-    GrallocTextureClientOGL* client = static_cast<GrallocTextureClientOGL*>(aClient);
-    if (client->GetMediaBuffer()) {
-      mPendingVideoBuffers.push(BufferItem(client->GetMediaBuffer(), client->GetAndResetReleaseFenceHandle()));
+    GrallocTextureData* grallocData = static_cast<GrallocTextureData*>(aClient->GetInternalData());
+    if (grallocData->GetMediaBuffer()) {
+      mPendingVideoBuffers.push(BufferItem(grallocData->GetMediaBuffer(), aClient->GetAndResetReleaseFenceHandle()));
     }
   }
   sp<AMessage> notify =
             new AMessage(kNotifyPostReleaseVideoBuffer, mReflector->id());
   // post AMessage to OmxDecoder via ALooper.
   notify->post();
 }
 
--- a/dom/media/platforms/gonk/GonkVideoDecoderManager.cpp
+++ b/dom/media/platforms/gonk/GonkVideoDecoderManager.cpp
@@ -369,24 +369,24 @@ GonkVideoDecoderManager::CreateVideoData
       GVDM_LOG("Copy buffer allocation failed!");
       return nullptr;
     }
     // Update size to match buffer's.
     aPicture.width = size.width;
     aPicture.height = size.height;
 
     sp<GraphicBuffer> destBuffer =
-      static_cast<GrallocTextureClientOGL*>(textureClient.get())->GetGraphicBuffer();
-
+      static_cast<GrallocTextureData*>(textureClient->GetInternalData())->GetGraphicBuffer();
+     
     CopyGraphicBuffer(srcBuffer, destBuffer, aPicture);
   } else {
     textureClient = mNativeWindow->getTextureClientFromBuffer(srcBuffer.get());
     textureClient->SetRecycleCallback(GonkVideoDecoderManager::RecycleCallback, this);
-    GrallocTextureClientOGL* grallocClient = static_cast<GrallocTextureClientOGL*>(textureClient.get());
-    grallocClient->SetMediaBuffer(aSource);
+
+    static_cast<GrallocTextureData*>(textureClient->GetInternalData())->SetMediaBuffer(aSource);
   }
 
   RefPtr<VideoData> data = VideoData::Create(mInfo.mVideo,
                                              mImageContainer,
                                              0, // Filled later by caller.
                                              0, // Filled later by caller.
                                              1, // No way to pass sample duration from muxer to
                                                 // OMX codec, so we hardcode the duration here.
@@ -678,17 +678,17 @@ GonkVideoDecoderManager::GetColorConvert
 }
 
 /* static */
 void
 GonkVideoDecoderManager::RecycleCallback(TextureClient* aClient, void* aClosure)
 {
   MOZ_ASSERT(aClient && !aClient->IsDead());
   GonkVideoDecoderManager* videoManager = static_cast<GonkVideoDecoderManager*>(aClosure);
-  GrallocTextureClientOGL* client = static_cast<GrallocTextureClientOGL*>(aClient);
+  GrallocTextureData* client = static_cast<GrallocTextureData*>(aClient->GetInternalData());
   aClient->ClearRecycleCallback();
   FenceHandle handle = aClient->GetAndResetReleaseFenceHandle();
   videoManager->PostReleaseVideoBuffer(client->GetMediaBuffer(), handle);
 }
 
 void GonkVideoDecoderManager::PostReleaseVideoBuffer(
                                 android::MediaBuffer *aBuffer,
                                 FenceHandle aReleaseFence)
--- a/dom/media/webrtc/MediaEngineGonkVideoSource.cpp
+++ b/dom/media/webrtc/MediaEngineGonkVideoSource.cpp
@@ -758,19 +758,18 @@ MediaEngineGonkVideoSource::RotateImage(
   MOZ_ASSERT(mTextureClientAllocator);
   RefPtr<layers::TextureClient> textureClient
     = mTextureClientAllocator->CreateOrRecycle(gfx::SurfaceFormat::YUV,
                                                gfx::IntSize(dstWidth, dstHeight),
                                                layers::BackendSelector::Content,
                                                layers::TextureFlags::DEFAULT,
                                                layers::ALLOC_DISALLOW_BUFFERTEXTURECLIENT);
   if (textureClient) {
-    RefPtr<layers::GrallocTextureClientOGL> grallocTextureClient = textureClient->AsGrallocTextureClientOGL();
-
-    android::sp<android::GraphicBuffer> destBuffer = grallocTextureClient->GetGraphicBuffer();
+    android::sp<android::GraphicBuffer> destBuffer =
+      static_cast<layers::GrallocTextureData*>(textureClient->GetInternalData())->GetGraphicBuffer();
 
     void* destMem = nullptr;
     destBuffer->lock(android::GraphicBuffer::USAGE_SW_WRITE_OFTEN, &destMem);
     uint8_t* dstPtr = static_cast<uint8_t*>(destMem);
 
     int32_t yStride = destBuffer->getStride();
     // Align to 16 bytes boundary
     int32_t uvStride = ((yStride / 2) + 15) & ~0x0F;
--- a/gfx/gl/SharedSurfaceGralloc.cpp
+++ b/gfx/gl/SharedSurfaceGralloc.cpp
@@ -58,27 +58,27 @@ SharedSurface_Gralloc::Create(GLContext*
     DEBUG_PRINT("SharedSurface_Gralloc::Create -------\n");
 
     if (!HasExtensions(egl, prodGL))
         return Move(ret);
 
     gfxContentType type = hasAlpha ? gfxContentType::COLOR_ALPHA
                                    : gfxContentType::COLOR;
 
-    typedef GrallocTextureClientOGL ptrT;
-    RefPtr<ptrT> grallocTC = new ptrT(allocator,
-                                      gfxPlatform::GetPlatform()->Optimal2DFormatForContent(type),
-                                      gfx::BackendType::NONE, // we don't need to use it with a DrawTarget
-                                      flags);
+    GrallocTextureData* texData = GrallocTextureData::CreateForGLRendering(
+        size, gfxPlatform::GetPlatform()->Optimal2DFormatForContent(type), allocator
+    );
 
-    if (!grallocTC->AllocateForGLRendering(size)) {
+    if (!texData) {
         return Move(ret);
     }
 
-    sp<GraphicBuffer> buffer = grallocTC->GetGraphicBuffer();
+    RefPtr<TextureClient> grallocTC = new ClientTexture(texData, flags, allocator);
+
+    sp<GraphicBuffer> buffer = texData->GetGraphicBuffer();
 
     EGLDisplay display = egl->Display();
     EGLClientBuffer clientBuffer = buffer->getNativeBuffer();
     EGLint attrs[] = {
         LOCAL_EGL_NONE, LOCAL_EGL_NONE
     };
     EGLImage image = egl->fCreateImage(display,
                                        EGL_NO_CONTEXT,
@@ -114,17 +114,17 @@ SharedSurface_Gralloc::Create(GLContext*
 }
 
 
 SharedSurface_Gralloc::SharedSurface_Gralloc(GLContext* prodGL,
                                              const gfx::IntSize& size,
                                              bool hasAlpha,
                                              GLLibraryEGL* egl,
                                              layers::ISurfaceAllocator* allocator,
-                                             layers::GrallocTextureClientOGL* textureClient,
+                                             layers::TextureClient* textureClient,
                                              GLuint prodTex)
     : SharedSurface(SharedSurfaceType::Gralloc,
                     AttachmentType::GLTexture,
                     prodGL,
                     size,
                     hasAlpha,
                     true)
     , mEGL(egl)
@@ -282,17 +282,19 @@ SharedSurface_Gralloc::ToSurfaceDescript
     mTextureClient->MarkShared();
     return mTextureClient->ToSurfaceDescriptor(*out_descriptor);
 }
 
 bool
 SharedSurface_Gralloc::ReadbackBySharedHandle(gfx::DataSourceSurface* out_surface)
 {
     MOZ_ASSERT(out_surface);
-    sp<GraphicBuffer> buffer = mTextureClient->GetGraphicBuffer();
+    sp<GraphicBuffer> buffer = static_cast<GrallocTextureData*>(
+        mTextureClient->GetInternalData()
+    )->GetGraphicBuffer();
 
     const uint8_t* grallocData = nullptr;
     auto result = buffer->lock(
         GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_NEVER,
         const_cast<void**>(reinterpret_cast<const void**>(&grallocData))
     );
 
     if (result == BAD_VALUE) {
--- a/gfx/gl/SharedSurfaceGralloc.h
+++ b/gfx/gl/SharedSurfaceGralloc.h
@@ -8,17 +8,17 @@
 
 #include "mozilla/layers/CompositorTypes.h"
 #include "mozilla/layers/LayersSurfaces.h"
 #include "SharedSurface.h"
 
 namespace mozilla {
 namespace layers {
 class ISurfaceAllocator;
-class GrallocTextureClientOGL;
+class TextureClient;
 }
 
 namespace gl {
 class GLContext;
 class GLLibraryEGL;
 
 class SharedSurface_Gralloc
     : public SharedSurface
@@ -36,25 +36,25 @@ public:
 
         return (SharedSurface_Gralloc*)surf;
     }
 
 protected:
     GLLibraryEGL* const mEGL;
     EGLSync mSync;
     RefPtr<layers::ISurfaceAllocator> mAllocator;
-    RefPtr<layers::GrallocTextureClientOGL> mTextureClient;
+    RefPtr<layers::TextureClient> mTextureClient;
     const GLuint mProdTex;
 
     SharedSurface_Gralloc(GLContext* prodGL,
                           const gfx::IntSize& size,
                           bool hasAlpha,
                           GLLibraryEGL* egl,
                           layers::ISurfaceAllocator* allocator,
-                          layers::GrallocTextureClientOGL* textureClient,
+                          layers::TextureClient* textureClient,
                           GLuint prodTex);
 
     static bool HasExtensions(GLLibraryEGL* egl, GLContext* gl);
 
 public:
     virtual ~SharedSurface_Gralloc();
 
     virtual void Fence() override;
@@ -65,17 +65,17 @@ public:
 
     virtual void LockProdImpl() override {}
     virtual void UnlockProdImpl() override {}
 
     virtual GLuint ProdTexture() override {
         return mProdTex;
     }
 
-    layers::GrallocTextureClientOGL* GetTextureClient() {
+    layers::TextureClient* GetTextureClient() {
         return mTextureClient;
     }
 
     virtual bool ToSurfaceDescriptor(layers::SurfaceDescriptor* const out_descriptor) override;
 
     virtual bool ReadbackBySharedHandle(gfx::DataSourceSurface* out_surface) override;
 };
 
--- a/gfx/layers/BufferTexture.h
+++ b/gfx/layers/BufferTexture.h
@@ -31,17 +31,17 @@ public:
                                                  TextureFlags aTextureFlags);
 
   static BufferTextureData* CreateForYCbCr(ISurfaceAllocator* aAllocator,
                                            gfx::IntSize aYSize,
                                            gfx::IntSize aCbCrSize,
                                            StereoMode aStereoMode,
                                            TextureFlags aTextureFlags);
 
-  virtual bool Lock(OpenMode aMode) override { return true; }
+  virtual bool Lock(OpenMode aMode, FenceHandle*) override { return true; }
 
   virtual void Unlock() override {}
 
   virtual gfx::IntSize GetSize() const override { return mSize; }
 
   virtual gfx::SurfaceFormat GetFormat() const override { return mFormat; }
 
   virtual already_AddRefed<gfx::DrawTarget> BorrowDrawTarget() override;
--- a/gfx/layers/GrallocImages.cpp
+++ b/gfx/layers/GrallocImages.cpp
@@ -68,35 +68,31 @@ GrallocImage::SetData(const Data& aData)
   mData = aData;
   mSize = aData.mPicSize;
 
   if (gfxPlatform::GetPlatform()->IsInGonkEmulator()) {
     // Emulator does not support HAL_PIXEL_FORMAT_YV12.
     return false;
   }
 
-  RefPtr<GrallocTextureClientOGL> textureClient =
-       new GrallocTextureClientOGL(ImageBridgeChild::GetSingleton(),
-                                   gfx::SurfaceFormat::UNKNOWN,
-                                   gfx::BackendType::NONE);
-  // GrallocImages are all YUV and don't support alpha.
-  textureClient->SetIsOpaque(true);
-  bool result =
-    textureClient->AllocateGralloc(mData.mYSize,
-                                   HAL_PIXEL_FORMAT_YV12,
-                                   GraphicBuffer::USAGE_SW_READ_OFTEN |
-                                   GraphicBuffer::USAGE_SW_WRITE_OFTEN |
-                                   GraphicBuffer::USAGE_HW_TEXTURE);
-  sp<GraphicBuffer> graphicBuffer = textureClient->GetGraphicBuffer();
-  if (!result || !graphicBuffer.get()) {
-    mTextureClient = nullptr;
+  ISurfaceAllocator* allocator = ImageBridgeChild::GetSingleton();
+  GrallocTextureData* texData = GrallocTextureData::Create(mData.mYSize, HAL_PIXEL_FORMAT_YV12,
+                                                           gfx::BackendType::NONE,
+                                                           GraphicBuffer::USAGE_SW_READ_OFTEN |
+                                                             GraphicBuffer::USAGE_SW_WRITE_OFTEN |
+                                                             GraphicBuffer::USAGE_HW_TEXTURE,
+                                                           allocator
+  );
+
+  if (!texData) {
     return false;
   }
 
-  mTextureClient = textureClient;
+  mTextureClient = new ClientTexture(texData, TextureFlags::DEFAULT, allocator);
+  sp<GraphicBuffer> graphicBuffer = texData->GetGraphicBuffer();
 
   void* vaddr;
   if (graphicBuffer->lock(GraphicBuffer::USAGE_SW_WRITE_OFTEN,
                           &vaddr) != OK) {
     return false;
   }
 
   uint8_t* yChannel = static_cast<uint8_t*>(vaddr);
@@ -145,18 +141,17 @@ GrallocImage::SetData(const Data& aData)
   mData.mCrChannel    = nullptr;
   mData.mCbChannel    = nullptr;
   return true;
 }
 
 void
 GrallocImage::SetData(TextureClient* aGraphicBuffer, const gfx::IntSize& aSize)
 {
-  MOZ_ASSERT(aGraphicBuffer->AsGrallocTextureClientOGL());
-  mTextureClient = aGraphicBuffer->AsGrallocTextureClientOGL();
+  mTextureClient = aGraphicBuffer;
   mSize = aSize;
 }
 
 /**
  * Converts YVU420 semi planar frames to RGB565, possibly taking different
  * stride values.
  * Needed because the Android ColorConverter class assumes that the Y and UV
  * channels have equal stride.
@@ -438,42 +433,40 @@ GetDataSourceSurfaceFrom(android::sp<and
 
 already_AddRefed<gfx::SourceSurface>
 GrallocImage::GetAsSourceSurface()
 {
   if (!mTextureClient) {
     return nullptr;
   }
 
-  android::sp<GraphicBuffer> graphicBuffer =
-    mTextureClient->GetGraphicBuffer();
+  android::sp<GraphicBuffer> graphicBuffer = GetGraphicBuffer();
 
   RefPtr<gfx::DataSourceSurface> surface =
     GetDataSourceSurfaceFrom(graphicBuffer, mSize, mData);
 
   return surface.forget();
 }
 
 android::sp<android::GraphicBuffer>
 GrallocImage::GetGraphicBuffer() const
 {
   if (!mTextureClient) {
     return nullptr;
   }
-  return mTextureClient->GetGraphicBuffer();
+  return static_cast<GrallocTextureData*>(mTextureClient->GetInternalData())->GetGraphicBuffer();
 }
 
 void*
 GrallocImage::GetNativeBuffer()
 {
   if (!mTextureClient) {
     return nullptr;
   }
-  android::sp<android::GraphicBuffer> graphicBuffer =
-    mTextureClient->GetGraphicBuffer();
+  android::sp<android::GraphicBuffer> graphicBuffer = GetGraphicBuffer();
   if (!graphicBuffer.get()) {
     return nullptr;
   }
   return graphicBuffer->getNativeBuffer();
 }
 
 TextureClient*
 GrallocImage::GetTextureClient(CompositableClient* aClient)
--- a/gfx/layers/GrallocImages.h
+++ b/gfx/layers/GrallocImages.h
@@ -15,17 +15,17 @@
 #include "mozilla/layers/FenceUtils.h"
 #include "mozilla/layers/LayersSurfaces.h"
 
 #include <ui/GraphicBuffer.h>
 
 namespace mozilla {
 namespace layers {
 
-class GrallocTextureClientOGL;
+class TextureClient;
 
 already_AddRefed<gfx::DataSourceSurface>
 GetDataSourceSurfaceFrom(android::sp<android::GraphicBuffer>& aGraphicBuffer,
                          gfx::IntSize aSize,
                          const layers::PlanarYCbCrData& aYcbcrData);
 
 /**
  * The YUV format supported by Android HAL
@@ -119,17 +119,17 @@ public:
         break;
       }
     }
 
     return omxFormat;
   }
 
 private:
-  RefPtr<GrallocTextureClientOGL> mTextureClient;
+  RefPtr<TextureClient> mTextureClient;
 };
 
 } // namespace layers
 } // namespace mozilla
 
 #endif
 
 #endif /* GRALLOCIMAGES_H */
--- a/gfx/layers/basic/GrallocTextureHostBasic.cpp
+++ b/gfx/layers/basic/GrallocTextureHostBasic.cpp
@@ -9,17 +9,17 @@
 
 #if ANDROID_VERSION >= 17
 #include <ui/Fence.h>
 #endif
 
 namespace mozilla {
 namespace layers {
 
-static SurfaceFormat
+static gfx::SurfaceFormat
 HalFormatToSurfaceFormat(int aHalFormat, TextureFlags aFlags)
 {
   bool swapRB = bool(aFlags & TextureFlags::RB_SWAPPED);
   switch (aHalFormat) {
   case android::PIXEL_FORMAT_BGRA_8888:
     return swapRB ? gfx::SurfaceFormat::R8G8B8A8 : gfx::SurfaceFormat::B8G8R8A8;
   case android::PIXEL_FORMAT_RGBA_8888:
     return swapRB ? gfx::SurfaceFormat::B8G8R8A8 : gfx::SurfaceFormat::R8G8B8A8;
@@ -40,17 +40,17 @@ HalFormatToSurfaceFormat(int aHalFormat,
       return gfx::SurfaceFormat::R5G6B5_UINT16;
   default:
     if (aHalFormat >= 0x100 && aHalFormat <= 0x1FF) {
       // Reserved range for HAL specific formats.
       // Needs convert to RGB565
       return gfx::SurfaceFormat::R5G6B5_UINT16;
     } else {
       MOZ_CRASH("Unhandled HAL pixel format");
-      return SurfaceFormat::UNKNOWN; // not reached
+      return gfx::SurfaceFormat::UNKNOWN; // not reached
     }
   }
 }
 
 static bool
 NeedsConvertFromYUVtoRGB565(int aHalFormat)
 {
   switch (aHalFormat) {
@@ -129,17 +129,17 @@ GrallocTextureHostBasic::Lock()
     uint32_t usage = GRALLOC_USAGE_SW_READ_OFTEN;
     int32_t rv = graphicBuffer->lock(usage,
                                      reinterpret_cast<void**>(&mMappedBuffer));
     if (rv) {
       mMappedBuffer = nullptr;
       NS_WARNING("Couldn't lock graphic buffer");
       return false;
     }
-    surf = Factory::CreateWrappingDataSourceSurface(
+    surf = gfx::Factory::CreateWrappingDataSourceSurface(
              mMappedBuffer,
              graphicBuffer->getStride() * gfx::BytesPerPixel(mFormat),
              mCropSize,
              mFormat);
   }
   mTextureSource = mCompositor->CreateDataTextureSource(mFlags);
   mTextureSource->Update(surf, nullptr);
   return true;
@@ -212,17 +212,17 @@ GrallocTextureHostBasic::WaitAcquireFenc
     NS_ERROR("failed to wait fence complete");
   }
 #endif
 }
 
 void
 GrallocTextureHostBasic::SetCropRect(nsIntRect aCropRect)
 {
-  MOZ_ASSERT(aCropRect.TopLeft() == IntPoint(0, 0));
+  MOZ_ASSERT(aCropRect.TopLeft() == gfx::IntPoint(0, 0));
   MOZ_ASSERT(!aCropRect.IsEmpty());
   MOZ_ASSERT(aCropRect.width <= mSize.width);
   MOZ_ASSERT(aCropRect.height <= mSize.height);
 
   gfx::IntSize cropSize(aCropRect.width, aCropRect.height);
   if (mCropSize == cropSize) {
     return;
   }
--- a/gfx/layers/basic/TextureClientX11.cpp
+++ b/gfx/layers/basic/TextureClientX11.cpp
@@ -40,17 +40,17 @@ X11TextureData::X11TextureData(gfx::IntS
 , mSurface(aSurface)
 , mClientDeallocation(aClientDeallocation)
 , mIsCrossProcess(aIsCrossProcess)
 {
   MOZ_ASSERT(mSurface);
 }
 
 bool
-X11TextureData::Lock(OpenMode aMode)
+X11TextureData::Lock(OpenMode aMode, FenceHandle*)
 {
   return true;
 }
 
 void
 X11TextureData::Unlock()
 {
   if (mSurface && mIsCrossProcess) {
--- a/gfx/layers/basic/TextureClientX11.h
+++ b/gfx/layers/basic/TextureClientX11.h
@@ -16,17 +16,17 @@ namespace layers {
 class X11TextureData : public TextureData
 {
 public:
   static X11TextureData* Create(gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
                                 TextureFlags aFlags, ISurfaceAllocator* aAllocator);
 
   virtual bool Serialize(SurfaceDescriptor& aOutDescriptor) override;
 
-  virtual bool Lock(OpenMode aMode) override;
+  virtual bool Lock(OpenMode aMode, FenceHandle*) override;
 
   virtual void Unlock() override;
 
   virtual gfx::IntSize GetSize() const override { return mSize; }
 
   virtual gfx::SurfaceFormat GetFormat() const override { return mFormat; }
 
   virtual already_AddRefed<gfx::DrawTarget> BorrowDrawTarget() override;
--- a/gfx/layers/client/TextureClient.cpp
+++ b/gfx/layers/client/TextureClient.cpp
@@ -207,17 +207,17 @@ bool
 ClientTexture::Lock(OpenMode aMode)
 {
   MOZ_ASSERT(mValid);
   MOZ_ASSERT(!mIsLocked);
   if (mIsLocked) {
     return mOpenMode == aMode;
   }
 
-  mIsLocked = mData->Lock(aMode);
+  mIsLocked = mData->Lock(aMode, mReleaseFenceHandle.IsValid() ? &mReleaseFenceHandle : nullptr);
   mOpenMode = aMode;
 
   return mIsLocked;
 }
 
 void
 ClientTexture::Unlock()
 {
@@ -265,18 +265,22 @@ ClientTexture::GetFormat() const
   MOZ_ASSERT(mValid);
   return mData->GetFormat();
 }
 
 ClientTexture::~ClientTexture()
 {
   // All the destruction code that may lead to virtual method calls must
   // be in Finalize() which is called just before the destructor.
+
+  // TODO[nical] temporarily integrate this with FinalizeOnIPDLThred
   if (ShouldDeallocateInDestructor()) {
     mData->Deallocate(mAllocator);
+  } else {
+    mData->Forget(mAllocator);
   }
   delete mData;
 }
 
 void
 ClientTexture::UpdateFromSurface(gfx::SourceSurface* aSurface)
 {
   MOZ_ASSERT(mValid);
@@ -366,16 +370,30 @@ ClientTexture::BorrowMappedYCbCrData(Map
 
 bool
 ClientTexture::ToSurfaceDescriptor(SurfaceDescriptor& aOutDescriptor)
 {
   MOZ_ASSERT(mValid);
   return mData->Serialize(aOutDescriptor);
 }
 
+void
+ClientTexture::WaitForBufferOwnership(bool aWaitReleaseFence)
+{
+  if (mRemoveFromCompositableWaiter) {
+    mRemoveFromCompositableWaiter->WaitComplete();
+    mRemoveFromCompositableWaiter = nullptr;
+  }
+
+  if (aWaitReleaseFence && mReleaseFenceHandle.IsValid()) {
+    mData->WaitForFence(&mReleaseFenceHandle);
+    mReleaseFenceHandle = FenceHandle();
+  }
+}
+
 // static
 PTextureChild*
 TextureClient::CreateIPDLActor()
 {
   TextureChild* c = new TextureChild();
   c->AddIPDLReference();
   return c;
 }
@@ -491,40 +509,16 @@ TextureClient::InitIPDLActor(Compositabl
 }
 
 PTextureChild*
 TextureClient::GetIPDLActor()
 {
   return mActor;
 }
 
-#ifdef MOZ_WIDGET_GONK
-static bool
-DisableGralloc(SurfaceFormat aFormat, const gfx::IntSize& aSizeHint)
-{
-  if (gfxPrefs::DisableGralloc()) {
-    return true;
-  }
-  if (aFormat == gfx::SurfaceFormat::A8) {
-    return true;
-  }
-
-#if ANDROID_VERSION <= 15
-  // Adreno 200 has a problem of drawing gralloc buffer width less than 64 and
-  // drawing gralloc buffer with a height 9px-16px.
-  // See Bug 983971.
-  if (aSizeHint.width < 64 || aSizeHint.height < 32) {
-    return true;
-  }
-#endif
-
-  return false;
-}
-#endif
-
 static inline gfx::BackendType
 BackendTypeForBackendSelector(LayersBackend aLayersBackend, BackendSelector aSelector)
 {
   switch (aSelector) {
     case BackendSelector::Canvas:
       return gfxPlatform::GetPlatform()->GetPreferredCanvasBackend();
     case BackendSelector::Content:
       return gfxPlatform::GetPlatform()->GetContentBackendFor(aLayersBackend);
@@ -552,17 +546,17 @@ TextureClient::CreateForDrawing(Composit
     return nullptr;
   }
 
   LayersBackend parentBackend = aAllocator->GetCompositorBackendType();
   gfx::BackendType moz2DBackend = BackendTypeForBackendSelector(parentBackend, aSelector);
 
   RefPtr<TextureClient> texture;
 
-#if defined(MOZ_WIDGET_GONK) || defined(XP_WIN)
+#if defined(XP_WIN)
   int32_t maxTextureSize = aAllocator->GetMaxTextureSize();
 #endif
 
 #ifdef XP_WIN
   if (parentBackend == LayersBackend::LAYERS_D3D11 &&
       (moz2DBackend == gfx::BackendType::DIRECT2D ||
        moz2DBackend == gfx::BackendType::DIRECT2D1_1) &&
       aSize.width <= maxTextureSize &&
@@ -616,23 +610,20 @@ TextureClient::CreateForDrawing(Composit
     if (texture) {
       return texture.forget();
     }
   }
 #endif
 #endif
 
 #ifdef MOZ_WIDGET_GONK
-  if (!DisableGralloc(aFormat, aSize)) {
-    // Don't allow Gralloc texture clients to exceed the maximum texture size.
-    // BufferTextureClients have code to handle tiling the surface client-side.
-    if (aSize.width <= maxTextureSize && aSize.height <= maxTextureSize) {
-      texture = new GrallocTextureClientOGL(aAllocator, aFormat, moz2DBackend,
-                                           aTextureFlags);
-    }
+  texture = CreateGrallocTextureClientForDrawing(aSize, aFormat, moz2DBackend,
+                                                 aTextureFlags, aAllocator);
+  if (texture) {
+    return texture.forget();
   }
 #endif
 
   MOZ_ASSERT(!texture || texture->CanExposeDrawTarget(), "texture cannot expose a DrawTarget?");
 
   if (texture && texture->AllocateForSurface(aSize, aAllocFlags)) {
     return texture.forget();
   }
@@ -839,16 +830,21 @@ TextureClient::ShouldDeallocateInDestruc
   // If we're meant to be deallocated by the host,
   // but we haven't been shared yet or
   // TextureFlags::DEALLOCATE_CLIENT is set, then we should
   // deallocate on the client instead.
   return !mShared || (GetFlags() & TextureFlags::DEALLOCATE_CLIENT);
 }
 
 void
+TextureClient::SetRemoveFromCompositableWaiter(AsyncTransactionWaiter* aWaiter) {
+  mRemoveFromCompositableWaiter = aWaiter;
+}
+
+void
 TextureClient::PrintInfo(std::stringstream& aStream, const char* aPrefix)
 {
   aStream << aPrefix;
   aStream << nsPrintfCString("TextureClient (0x%p)", this).get();
   AppendToString(aStream, GetSize(), " [size=", "]");
   AppendToString(aStream, GetFormat(), " [format=", "]");
   AppendToString(aStream, mFlags, " [flags=", "]");
 
--- a/gfx/layers/client/TextureClient.h
+++ b/gfx/layers/client/TextureClient.h
@@ -34,35 +34,39 @@ class gfxImageSurface;
 namespace mozilla {
 
 // When defined, we track which pool the tile came from and test for
 // any inconsistencies.  This can be defined in release build as well.
 #ifdef DEBUG
 #define GFX_DEBUG_TRACK_CLIENTS_IN_POOL 1
 #endif
 
+namespace gl {
+class SharedSurface_Gralloc;
+}
+
 namespace layers {
 
 class AsyncTransactionWaiter;
 class CompositableForwarder;
 class ISurfaceAllocator;
 class CompositableClient;
 struct PlanarYCbCrData;
 class Image;
 class PTextureChild;
 class TextureChild;
+class TextureData;
 struct RawTextureBuffer;
 class RawYCbCrTextureBuffer;
 class TextureClient;
 class TextureClientRecycleAllocator;
 #ifdef GFX_DEBUG_TRACK_CLIENTS_IN_POOL
 class TextureClientPool;
 #endif
 class KeepAlive;
-class GrallocTextureClientOGL;
 
 /**
  * TextureClient is the abstraction that allows us to share data between the
  * content and the compositor side.
  */
 
 enum TextureAllocationFlags {
   ALLOC_DEFAULT = 0,
@@ -242,18 +246,16 @@ public:
    * TextureClients that can expose a DrawTarget should override this method.
    */
   virtual bool AllocateForSurface(gfx::IntSize aSize,
                                   TextureAllocationFlags flags = ALLOC_DEFAULT)
   {
     return false;
   }
 
-  virtual GrallocTextureClientOGL* AsGrallocTextureClientOGL() { return nullptr; }
-
   /**
    * Locks the shared data, allowing the caller to get access to it.
    *
    * Please always lock/unlock when accessing the shared data.
    * If Lock() returns false, you should not attempt to access the shared data.
    */
   virtual bool Lock(OpenMode aMode) { return IsValid(); }
 
@@ -485,54 +487,57 @@ public:
   virtual const FenceHandle& GetAcquireFenceHandle() const
   {
     return mAcquireFenceHandle;
   }
 
   /**
    * Set AsyncTransactionTracker of RemoveTextureFromCompositableAsync() transaction.
    */
-  virtual void SetRemoveFromCompositableWaiter(AsyncTransactionWaiter* aWaiter) {}
+  virtual void SetRemoveFromCompositableWaiter(AsyncTransactionWaiter* aWaiter);
 
   /**
    * This function waits until the buffer is no longer being used.
    */
   virtual void WaitForBufferOwnership(bool aWaitReleaseFence = true) {}
 
   /**
    * Track how much of this texture is wasted.
    * For example we might allocate a 256x256 tile but only use 10x10.
    */
    void SetWaste(int aWasteArea) {
      mWasteTracker.Update(aWasteArea, BytesPerPixel(GetFormat()));
    }
 
-   /**
-    * This sets the readback sink that this texture is to use. This will
-    * receive the data for this texture as soon as it becomes available after
-    * texture unlock.
-    */
-   virtual void SetReadbackSink(TextureReadbackSink* aReadbackSink) {
-     mReadbackSink = aReadbackSink;
-   }
+  /**
+   * This sets the readback sink that this texture is to use. This will
+   * receive the data for this texture as soon as it becomes available after
+   * texture unlock.
+   */
+  virtual void SetReadbackSink(TextureReadbackSink* aReadbackSink) {
+    mReadbackSink = aReadbackSink;
+  }
 
-   virtual void SyncWithObject(SyncObject* aSyncObject) { }
+  virtual void SyncWithObject(SyncObject* aSyncObject) { }
 
-   void MarkShared() {
-     mShared = true;
-   }
+  void MarkShared() {
+    mShared = true;
+  }
 
   ISurfaceAllocator* GetAllocator()
   {
     return mAllocator;
   }
 
    TextureClientRecycleAllocator* GetRecycleAllocator() { return mRecycleAllocator; }
    void SetRecycleAllocator(TextureClientRecycleAllocator* aAllocator);
 
+  /// If you add new code that uses this funtion, you are probably doing something wrong.
+  virtual TextureData* GetInternalData() { return nullptr; }
+
 private:
   static void TextureClientRecycleCallback(TextureClient* aClient, void* aClosure);
 
   /**
    * Called once, during the destruction of the Texture, on the thread in which
    * texture's reference count reaches 0 (could be any thread).
    *
    * Here goes the shut-down code that uses virtual methods.
@@ -542,17 +547,17 @@ private:
 
   /**
    * Called once during the destruction of the texture on the IPDL thread, if
    * the texture is shared on the compositor (otherwise it is not called at all).
    */
   virtual void FinalizeOnIPDLThread() {}
 
   friend class AtomicRefCountedWithFinalize<TextureClient>;
-
+  friend class gl::SharedSurface_Gralloc;
 protected:
   /**
    * An invalid TextureClient cannot provide access to its shared data
    * anymore. This usually means it will soon be destroyed.
    */
   void MarkInvalid() { mValid = false; }
 
   /**
@@ -563,16 +568,18 @@ protected:
    * or never constructing a TextureHost with aDescriptor may result in a memory
    * leak (see TextureClientD3D9 for example).
    */
   virtual bool ToSurfaceDescriptor(SurfaceDescriptor& aDescriptor) = 0;
 
   RefPtr<TextureChild> mActor;
   RefPtr<ISurfaceAllocator> mAllocator;
   RefPtr<TextureClientRecycleAllocator> mRecycleAllocator;
+  RefPtr<AsyncTransactionWaiter> mRemoveFromCompositableWaiter;
+
   TextureFlags mFlags;
   FenceHandle mReleaseFenceHandle;
   FenceHandle mAcquireFenceHandle;
   gl::GfxTextureWasteTracker mWasteTracker;
   bool mShared;
   bool mValid;
   bool mAddedToCompositableClient;
 
@@ -595,17 +602,17 @@ public:
   TextureData() { MOZ_COUNT_CTOR(TextureData); }
 
   virtual ~TextureData() { MOZ_COUNT_DTOR(TextureData); }
 
   virtual gfx::IntSize GetSize() const = 0;
 
   virtual gfx::SurfaceFormat GetFormat() const = 0;
 
-  virtual bool Lock(OpenMode aMode) = 0;
+  virtual bool Lock(OpenMode aMode, FenceHandle* aFence) = 0;
 
   virtual void Unlock() = 0;
 
   virtual bool SupportsMoz2D() const { return false; }
 
   virtual bool CanExposeMappedData() const { return false; }
 
   virtual bool HasInternalBuffer() const = 0;
@@ -615,24 +622,31 @@ public:
   virtual already_AddRefed<gfx::DrawTarget> BorrowDrawTarget() { return nullptr; }
 
   virtual bool BorrowMappedData(MappedTextureData&) { return false; }
 
   virtual bool BorrowMappedYCbCrData(MappedYCbCrTextureData&) { return false; }
 
   virtual void Deallocate(ISurfaceAllocator* aAllocator) = 0;
 
+  /// Depending on the texture's flags either Deallocate or Forget is called.
+  virtual void Forget(ISurfaceAllocator* aAllocator) {}
+
   virtual bool Serialize(SurfaceDescriptor& aDescriptor) = 0;
 
   virtual TextureData*
   CreateSimilar(ISurfaceAllocator* aAllocator,
                 TextureFlags aFlags = TextureFlags::DEFAULT,
                 TextureAllocationFlags aAllocFlags = ALLOC_DEFAULT) const { return nullptr; }
 
   virtual bool UpdateFromSurface(gfx::SourceSurface* aSurface) { return false; };
+
+  /// Ideally this should not be exposed and users of TextureClient would use Lock/Unlock
+  /// preoperly but that requires a few changes to SharedSurface and maybe gonk video.
+  virtual void WaitForFence(FenceHandle* aFence) {};
 };
 
 /// temporary class that will be merged back into TextureClient when all texture implementations
 /// are based on TextureData.
 class ClientTexture : public TextureClient {
 public:
   ClientTexture(TextureData* aData, TextureFlags aFlags, ISurfaceAllocator* aAllocator);
 
@@ -665,19 +679,24 @@ public:
   virtual bool ToSurfaceDescriptor(SurfaceDescriptor& aOutDescriptor) override;
 
   virtual already_AddRefed<TextureClient>
   CreateSimilar(TextureFlags aFlags = TextureFlags::DEFAULT,
                 TextureAllocationFlags aAllocFlags = ALLOC_DEFAULT) const override;
 
   virtual void UpdateFromSurface(gfx::SourceSurface* aSurface) override;
 
+  // TODO - we should be able to make this implicit and not expose the method.
+  virtual void WaitForBufferOwnership(bool aWaitReleaseFence = true) override;
+
   // by construction, ClientTexture cannot be created without successful allocation.
   virtual bool IsAllocated() const override { return true; }
 
+  /// If you add new code that uses this method, you are probably doing something wrong.
+  virtual TextureData* GetInternalData() override { return mData; }
 protected:
   TextureData* mData;
   RefPtr<gfx::DrawTarget> mBorrowedDrawTarget;
   RefPtr<TextureReadbackSink> mReadbackSink;
 
   OpenMode mOpenMode;
   DebugOnly<uint32_t> mExpectedDtRefs;
   bool mIsLocked;
--- a/gfx/layers/client/TextureClientSharedSurface.cpp
+++ b/gfx/layers/client/TextureClientSharedSurface.cpp
@@ -49,65 +49,65 @@ SharedSurfaceTextureClient::ToSurfaceDes
 {
   return mSurf->ToSurfaceDescriptor(&aOutDescriptor);
 }
 
 void
 SharedSurfaceTextureClient::SetReleaseFenceHandle(const FenceHandle& aReleaseFenceHandle)
 {
 #ifdef MOZ_WIDGET_GONK
-  SharedSurface_Gralloc* surf = nullptr;
-  if (mSurf->mType == SharedSurfaceType::Gralloc) {
-    surf = SharedSurface_Gralloc::Cast(mSurf.get());
+  gl::SharedSurface_Gralloc* surf = nullptr;
+  if (mSurf->mType == gl::SharedSurfaceType::Gralloc) {
+    surf = gl::SharedSurface_Gralloc::Cast(mSurf.get());
   }
   if (surf && surf->GetTextureClient()) {
     surf->GetTextureClient()->SetReleaseFenceHandle(aReleaseFenceHandle);
     return;
   }
 #endif
   TextureClient::SetReleaseFenceHandle(aReleaseFenceHandle);
 }
 
 FenceHandle
 SharedSurfaceTextureClient::GetAndResetReleaseFenceHandle()
 {
 #ifdef MOZ_WIDGET_GONK
-  SharedSurface_Gralloc* surf = nullptr;
-  if (mSurf->mType == SharedSurfaceType::Gralloc) {
-    surf = SharedSurface_Gralloc::Cast(mSurf.get());
+  gl::SharedSurface_Gralloc* surf = nullptr;
+  if (mSurf->mType == gl::SharedSurfaceType::Gralloc) {
+    surf = gl::SharedSurface_Gralloc::Cast(mSurf.get());
   }
   if (surf && surf->GetTextureClient()) {
     return surf->GetTextureClient()->GetAndResetReleaseFenceHandle();
   }
 #endif
   return TextureClient::GetAndResetReleaseFenceHandle();
 }
 
 void
 SharedSurfaceTextureClient::SetAcquireFenceHandle(const FenceHandle& aAcquireFenceHandle)
 {
 #ifdef MOZ_WIDGET_GONK
-  SharedSurface_Gralloc* surf = nullptr;
-  if (mSurf->mType == SharedSurfaceType::Gralloc) {
-    surf = SharedSurface_Gralloc::Cast(mSurf.get());
+  gl::SharedSurface_Gralloc* surf = nullptr;
+  if (mSurf->mType == gl::SharedSurfaceType::Gralloc) {
+    surf = gl::SharedSurface_Gralloc::Cast(mSurf.get());
   }
   if (surf && surf->GetTextureClient()) {
     return surf->GetTextureClient()->SetAcquireFenceHandle(aAcquireFenceHandle);
   }
 #endif
   TextureClient::SetAcquireFenceHandle(aAcquireFenceHandle);
 }
 
 const FenceHandle&
 SharedSurfaceTextureClient::GetAcquireFenceHandle() const
 {
 #ifdef MOZ_WIDGET_GONK
-  SharedSurface_Gralloc* surf = nullptr;
-  if (mSurf->mType == SharedSurfaceType::Gralloc) {
-    surf = SharedSurface_Gralloc::Cast(mSurf.get());
+  gl::SharedSurface_Gralloc* surf = nullptr;
+  if (mSurf->mType == gl::SharedSurfaceType::Gralloc) {
+    surf = gl::SharedSurface_Gralloc::Cast(mSurf.get());
   }
   if (surf && surf->GetTextureClient()) {
     return surf->GetTextureClient()->GetAcquireFenceHandle();
   }
 #endif
   return TextureClient::GetAcquireFenceHandle();
 }
 
--- a/gfx/layers/opengl/GrallocTextureClient.cpp
+++ b/gfx/layers/opengl/GrallocTextureClient.cpp
@@ -19,369 +19,386 @@
 #endif
 
 namespace mozilla {
 namespace layers {
 
 using namespace mozilla::gfx;
 using namespace android;
 
-GrallocTextureClientOGL::GrallocTextureClientOGL(ISurfaceAllocator* aAllocator,
-                                                 gfx::SurfaceFormat aFormat,
-                                                 gfx::BackendType aMoz2dBackend,
-                                                 TextureFlags aFlags)
-: BufferTextureClient(aAllocator, aFormat, aMoz2dBackend, aFlags)
-, mGrallocHandle(null_t())
-, mMappedBuffer(nullptr)
-, mMediaBuffer(nullptr)
-, mIsOpaque(gfx::IsOpaque(aFormat))
-{
-  MOZ_COUNT_CTOR(GrallocTextureClientOGL);
-}
-
-GrallocTextureClientOGL::~GrallocTextureClientOGL()
-{
-  MOZ_COUNT_DTOR(GrallocTextureClientOGL);
-  ISurfaceAllocator* allocator = GetAllocator();
-  if (ShouldDeallocateInDestructor()) {
-    allocator->DeallocGrallocBuffer(&mGrallocHandle);
-  } else {
-    allocator->DropGrallocBuffer(&mGrallocHandle);
-  }
-}
-
-already_AddRefed<TextureClient>
-GrallocTextureClientOGL::CreateSimilar(TextureFlags aFlags,
-                                       TextureAllocationFlags aAllocFlags) const
+static bool
+DisableGralloc(SurfaceFormat aFormat, const gfx::IntSize& aSizeHint)
 {
-  RefPtr<TextureClient> tex = new GrallocTextureClientOGL(
-    mAllocator, mFormat, mBackend, mFlags | aFlags
-  );
-
-  if (!tex->AllocateForSurface(mSize, aAllocFlags)) {
-    return nullptr;
+  if (gfxPrefs::DisableGralloc()) {
+    return true;
+  }
+  if (aFormat == gfx::SurfaceFormat::A8) {
+    return true;
   }
-
-  return tex.forget();
-}
+#if ANDROID_VERSION <= 15
+  // Adreno 200 has a problem of drawing gralloc buffer width less than 64 and
+  // drawing gralloc buffer with a height 9px-16px.
+  // See Bug 983971.
+  if (aSizeHint.width < 64 || aSizeHint.height < 32) {
+    return true;
+  }
+#endif
 
-bool
-GrallocTextureClientOGL::ToSurfaceDescriptor(SurfaceDescriptor& aOutDescriptor)
-{
-  MOZ_ASSERT(IsValid());
-  if (!IsAllocated()) {
-    return false;
-  }
-
-  aOutDescriptor = NewSurfaceDescriptorGralloc(mGrallocHandle, mIsOpaque);
-  return true;
-}
-
-void
-GrallocTextureClientOGL::SetRemoveFromCompositableWaiter(AsyncTransactionWaiter* aWaiter)
-{
-  mRemoveFromCompositableWaiter = aWaiter;
+  return false;
 }
 
-void
-GrallocTextureClientOGL::WaitForBufferOwnership(bool aWaitReleaseFence)
-{
-  if (mRemoveFromCompositableWaiter) {
-    mRemoveFromCompositableWaiter->WaitComplete();
-    mRemoveFromCompositableWaiter = nullptr;
-  }
-
-  if (!aWaitReleaseFence) {
-    return;
-  }
-
-#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17
-   if (mReleaseFenceHandle.IsValid()) {
-     RefPtr<FenceHandle::FdObj> fdObj = mReleaseFenceHandle.GetAndResetFdObj();
-     android::sp<Fence> fence = new Fence(fdObj->GetAndResetFd());
-#if ANDROID_VERSION == 17
-     fence->waitForever(1000, "GrallocTextureClientOGL::Lock");
-     // 1000 is what Android uses. It is a warning timeout in ms.
-     // This timeout was removed in ANDROID_VERSION 18.
-#else
-     fence->waitForever("GrallocTextureClientOGL::Lock");
-#endif
-     mReleaseFenceHandle = FenceHandle();
-   }
-#endif
-}
-
-bool
-GrallocTextureClientOGL::Lock(OpenMode aMode)
-{
-  MOZ_ASSERT(!mIsLocked);
-  MOZ_ASSERT(IsValid());
-  if (!IsValid() || !IsAllocated()) {
-    return false;
-  }
-
-  if (mMappedBuffer) {
-    return true;
-  }
-
-#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 21
-  WaitForBufferOwnership(false /* aWaitReleaseFence */);
-#else
-  WaitForBufferOwnership();
-#endif
-
-  uint32_t usage = 0;
-  if (aMode & OpenMode::OPEN_READ) {
-    usage |= GRALLOC_USAGE_SW_READ_OFTEN;
-  }
-  if (aMode & OpenMode::OPEN_WRITE) {
-    usage |= GRALLOC_USAGE_SW_WRITE_OFTEN;
-  }
-#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 21
-  RefPtr<FenceHandle::FdObj> fdObj = mReleaseFenceHandle.GetAndResetFdObj();
-  int32_t rv = mGraphicBuffer->lockAsync(usage,
-                                         reinterpret_cast<void**>(&mMappedBuffer),
-                                         fdObj->GetAndResetFd());
-#else
-  int32_t rv = mGraphicBuffer->lock(usage,
-                                    reinterpret_cast<void**>(&mMappedBuffer));
-#endif
-  if (rv) {
-    mMappedBuffer = nullptr;
-    NS_WARNING("Couldn't lock graphic buffer");
-    return false;
-  }
-  mIsLocked = true;
-  return true;
-}
-
-void
-GrallocTextureClientOGL::Unlock()
-{
-  MOZ_ASSERT(mIsLocked);
-  mIsLocked = false;
-  mDrawTarget = nullptr;
-  if (mMappedBuffer) {
-    mMappedBuffer = nullptr;
-    mGraphicBuffer->unlock();
-  }
-}
-
-static gfx::SurfaceFormat
+gfx::SurfaceFormat
 SurfaceFormatForPixelFormat(android::PixelFormat aFormat)
 {
   switch (aFormat) {
   case PIXEL_FORMAT_RGBA_8888:
     return gfx::SurfaceFormat::R8G8B8A8;
   case PIXEL_FORMAT_BGRA_8888:
     return gfx::SurfaceFormat::B8G8R8A8;
   case PIXEL_FORMAT_RGBX_8888:
     return gfx::SurfaceFormat::R8G8B8X8;
   case PIXEL_FORMAT_RGB_565:
     return gfx::SurfaceFormat::R5G6B5_UINT16;
   case HAL_PIXEL_FORMAT_YV12:
     return gfx::SurfaceFormat::YUV;
   default:
-    MOZ_CRASH("Unknown gralloc pixel format");
+    return gfx::SurfaceFormat::UNKNOWN;
+  }
+}
+
+bool
+IsGrallocRBSwapped(gfx::SurfaceFormat aFormat) {
+  switch (aFormat) {
+  case gfx::SurfaceFormat::B8G8R8A8:
+  case gfx::SurfaceFormat::B8G8R8X8:
+    return true;
+  default:
+    return false;
   }
-  return gfx::SurfaceFormat::R8G8B8A8;
+}
+
+uint32_t GetAndroidFormat(gfx::SurfaceFormat aFormat)
+{
+  switch (aFormat) {
+  case gfx::SurfaceFormat::R8G8B8A8:
+  case gfx::SurfaceFormat::B8G8R8A8:
+    return android::PIXEL_FORMAT_RGBA_8888;
+  case gfx::SurfaceFormat::R8G8B8X8:
+  case gfx::SurfaceFormat::B8G8R8X8:
+    return android::PIXEL_FORMAT_RGBX_8888;
+  case gfx::SurfaceFormat::R5G6B5_UINT16:
+    return android::PIXEL_FORMAT_RGB_565;
+  case gfx::SurfaceFormat::YUV:
+    return HAL_PIXEL_FORMAT_YV12;
+  case gfx::SurfaceFormat::A8:
+    NS_WARNING("gralloc does not support SurfaceFormat::A8");
+  default:
+    NS_WARNING("Unsupported surface format");
+    return android::PIXEL_FORMAT_UNKNOWN;
+  }
 }
 
-gfx::DrawTarget*
-GrallocTextureClientOGL::BorrowDrawTarget()
+GrallocTextureData::GrallocTextureData(MaybeMagicGrallocBufferHandle aGrallocHandle,
+                                       gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
+                                       gfx::BackendType aMoz2DBackend)
+: mSize(aSize)
+, mFormat(aFormat)
+, mMoz2DBackend(aMoz2DBackend)
+, mGrallocHandle(aGrallocHandle)
+, mMappedBuffer(nullptr)
+, mMediaBuffer(nullptr)
 {
-  MOZ_ASSERT(IsValid());
-  MOZ_ASSERT(mMappedBuffer, "Calling TextureClient::BorrowDrawTarget without locking :(");
+  mGraphicBuffer = GetGraphicBufferFrom(aGrallocHandle);
+  MOZ_COUNT_CTOR(GrallocTextureData);
+}
 
-  if (!IsValid() || !IsAllocated() || !mMappedBuffer) {
-    return nullptr;
-  }
+GrallocTextureData::~GrallocTextureData()
+{
+  MOZ_COUNT_DTOR(GrallocTextureData);
+}
 
-  if (mDrawTarget) {
-    return mDrawTarget;
-  }
+void
+GrallocTextureData::Deallocate(ISurfaceAllocator* aAllocator)
+{
+  aAllocator->DeallocGrallocBuffer(&mGrallocHandle);
+  mGrallocHandle = null_t();
+  mGraphicBuffer = nullptr;
+}
 
-  gfx::SurfaceFormat format = SurfaceFormatForPixelFormat(mGraphicBuffer->getPixelFormat());
-  long pixelStride = mGraphicBuffer->getStride();
-  long byteStride = pixelStride * BytesPerPixel(format);
-  mDrawTarget = gfxPlatform::GetPlatform()->CreateDrawTargetForData(GetBuffer(),
-                                                                    mSize,
-                                                                    byteStride,
-                                                                    mFormat);
-  return mDrawTarget;
+void
+GrallocTextureData::Forget(ISurfaceAllocator* aAllocator)
+{
+  aAllocator->DropGrallocBuffer(&mGrallocHandle);
+  mGrallocHandle = null_t();
+  mGraphicBuffer = nullptr;
+}
+
+bool
+GrallocTextureData::Serialize(SurfaceDescriptor& aOutDescriptor)
+{
+  aOutDescriptor = NewSurfaceDescriptorGralloc(mGrallocHandle, gfx::IsOpaque(mFormat));
+  return true;
 }
 
 void
-GrallocTextureClientOGL::UpdateFromSurface(gfx::SourceSurface* aSurface)
+GrallocTextureData::WaitForFence(FenceHandle* aFence)
+{
+#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION < 21 && ANDROID_VERSION >= 17
+   if (aFence->IsValid()) {
+     RefPtr<FenceHandle::FdObj> fdObj = aFence->GetAndResetFdObj();
+     android::sp<Fence> fence = new Fence(fdObj->GetAndResetFd());
+#if ANDROID_VERSION == 17
+     fence->waitForever(1000, "GrallocTextureData::Lock");
+     // 1000 is what Android uses. It is a warning timeout in ms.
+     // This timeout was removed in ANDROID_VERSION 18.
+#else
+     fence->waitForever("GrallocTextureData::Lock");
+#endif
+   }
+#endif
+}
+
+bool
+GrallocTextureData::Lock(OpenMode aMode, FenceHandle* aReleaseFence)
 {
-  MOZ_ASSERT(IsValid());
+  MOZ_ASSERT(!mMappedBuffer);
+
+  WaitForFence(aReleaseFence);
+
+  uint32_t usage = 0;
+  if (aMode & OpenMode::OPEN_READ) {
+    usage |= GRALLOC_USAGE_SW_READ_OFTEN;
+  }
+  if (aMode & OpenMode::OPEN_WRITE) {
+    usage |= GRALLOC_USAGE_SW_WRITE_OFTEN;
+  }
+#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 21
+  RefPtr<FenceHandle::FdObj> fdObj = aReleaseFence->GetAndResetFdObj();
+  int32_t rv = mGraphicBuffer->lockAsync(usage,
+                                         reinterpret_cast<void**>(&mMappedBuffer),
+                                         fdObj->GetAndResetFd());
+#else
+  int32_t rv = mGraphicBuffer->lock(usage,
+                                    reinterpret_cast<void**>(&mMappedBuffer));
+#endif
+  if (rv) {
+    mMappedBuffer = nullptr;
+    NS_WARNING("Couldn't lock graphic buffer");
+    return false;
+  }
+  return true;
+}
+
+void
+GrallocTextureData::Unlock()
+{
+  MOZ_ASSERT(mMappedBuffer);
+  mMappedBuffer = nullptr;
+  mGraphicBuffer->unlock();
+}
+
+already_AddRefed<gfx::DrawTarget>
+GrallocTextureData::BorrowDrawTarget()
+{
+  MOZ_ASSERT(mMappedBuffer);
+  if (!mMappedBuffer) {
+    return nullptr;
+  }
+  long byteStride = mGraphicBuffer->getStride() * BytesPerPixel(mFormat);
+  return gfxPlatform::GetPlatform()->CreateDrawTargetForData(mMappedBuffer, mSize,
+                                                             byteStride, mFormat);
+}
+
+bool
+GrallocTextureData::BorrowMappedData(MappedTextureData& aMap)
+{
+  if (mFormat == gfx::SurfaceFormat::YUV || !mMappedBuffer) {
+    return false;
+  }
+
+  aMap.data = mMappedBuffer;
+  aMap.size = mSize;
+  aMap.stride = mGraphicBuffer->getStride() * BytesPerPixel(mFormat);
+  aMap.format = mFormat;
+
+  return true;
+}
+
+bool
+GrallocTextureData::UpdateFromSurface(gfx::SourceSurface* aSurface)
+{
   MOZ_ASSERT(mMappedBuffer, "Calling TextureClient::BorrowDrawTarget without locking :(");
 
-  if (!IsValid() || !IsAllocated() || !mMappedBuffer) {
-    return;
+  if (!mMappedBuffer) {
+    return false;
   }
 
   RefPtr<DataSourceSurface> srcSurf = aSurface->GetDataSurface();
 
   if (!srcSurf) {
     gfxCriticalError() << "Failed to GetDataSurface in UpdateFromSurface.";
-    return;
+    return false;
   }
 
   gfx::SurfaceFormat format = SurfaceFormatForPixelFormat(mGraphicBuffer->getPixelFormat());
   if (mSize != srcSurf->GetSize() || mFormat != srcSurf->GetFormat()) {
     gfxCriticalError() << "Attempt to update texture client from a surface with a different size or format! This: " << mSize << " " << format << " Other: " << srcSurf->GetSize() << " " << srcSurf->GetFormat();
-    return;
+    return false;
   }
 
   long pixelStride = mGraphicBuffer->getStride();
   long byteStride = pixelStride * BytesPerPixel(format);
 
   DataSourceSurface::MappedSurface sourceMap;
 
   if (!srcSurf->Map(DataSourceSurface::READ, &sourceMap)) {
     gfxCriticalError() << "Failed to map source surface for UpdateFromSurface.";
-    return;
+    return false;
   }
 
-  uint8_t* buffer = GetBuffer();
-
   for (int y = 0; y < srcSurf->GetSize().height; y++) {
-    memcpy(buffer + byteStride * y,
+    memcpy(mMappedBuffer + byteStride * y,
            sourceMap.mData + sourceMap.mStride * y,
            srcSurf->GetSize().width * BytesPerPixel(srcSurf->GetFormat()));
   }
 
   srcSurf->Unmap();
-}
 
-bool
-GrallocTextureClientOGL::AllocateForSurface(gfx::IntSize aSize,
-                                            TextureAllocationFlags)
-{
-  MOZ_ASSERT(IsValid());
-
-  uint32_t format;
-  uint32_t usage = android::GraphicBuffer::USAGE_SW_READ_OFTEN |
-                   android::GraphicBuffer::USAGE_SW_WRITE_OFTEN |
-                   android::GraphicBuffer::USAGE_HW_TEXTURE;
-
-  switch (mFormat) {
-  case gfx::SurfaceFormat::R8G8B8A8:
-    format = android::PIXEL_FORMAT_RGBA_8888;
-    break;
-  case gfx::SurfaceFormat::B8G8R8A8:
-     format = android::PIXEL_FORMAT_RGBA_8888;
-     mFlags |= TextureFlags::RB_SWAPPED;
-    break;
-  case gfx::SurfaceFormat::R8G8B8X8:
-    format = android::PIXEL_FORMAT_RGBX_8888;
-    break;
-  case gfx::SurfaceFormat::B8G8R8X8:
-     format = android::PIXEL_FORMAT_RGBX_8888;
-     mFlags |= TextureFlags::RB_SWAPPED;
-    break;
-  case gfx::SurfaceFormat::R5G6B5_UINT16:
-    format = android::PIXEL_FORMAT_RGB_565;
-    break;
-  case gfx::SurfaceFormat::YUV:
-    format = HAL_PIXEL_FORMAT_YV12;
-    break;
-  case gfx::SurfaceFormat::A8:
-    NS_WARNING("gralloc does not support gfx::SurfaceFormat::A8");
-    return false;
-  default:
-    NS_WARNING("Unsupported surface format");
-    return false;
-  }
-
-  return AllocateGralloc(aSize, format, usage);
+  return true;
 }
 
-bool
-GrallocTextureClientOGL::AllocateForYCbCr(gfx::IntSize aYSize, gfx::IntSize aCbCrSize, StereoMode aStereoMode)
-{
-  MOZ_ASSERT(IsValid());
-  return AllocateGralloc(aYSize,
-                         HAL_PIXEL_FORMAT_YV12,
-                         android::GraphicBuffer::USAGE_SW_READ_OFTEN);
-}
-
-bool
-GrallocTextureClientOGL::AllocateForGLRendering(gfx::IntSize aSize)
+// static
+GrallocTextureData*
+GrallocTextureData::Create(gfx::IntSize aSize, AndroidFormat aAndroidFormat,
+                           gfx::BackendType aMoz2dBackend, uint32_t aUsage,
+                           ISurfaceAllocator* aAllocator)
 {
-  MOZ_ASSERT(IsValid());
-
-  uint32_t format;
-  uint32_t usage = android::GraphicBuffer::USAGE_HW_RENDER |
-                   android::GraphicBuffer::USAGE_HW_TEXTURE;
-
-  switch (mFormat) {
-  case gfx::SurfaceFormat::R8G8B8A8:
-  case gfx::SurfaceFormat::B8G8R8A8:
-    format = android::PIXEL_FORMAT_RGBA_8888;
+  int32_t maxSize = aAllocator->GetMaxTextureSize();
+  if (aSize.width > maxSize || aSize.height > maxSize) {
+    return nullptr;
+  }
+  gfx::SurfaceFormat format;
+  switch (aAndroidFormat) {
+  case android::PIXEL_FORMAT_RGBA_8888:
+    format = gfx::SurfaceFormat::B8G8R8A8;
     break;
-  case gfx::SurfaceFormat::R8G8B8X8:
-  case gfx::SurfaceFormat::B8G8R8X8:
-    // there is no android BGRX format?
-    format = android::PIXEL_FORMAT_RGBX_8888;
+  case android::PIXEL_FORMAT_BGRA_8888:
+    format = gfx::SurfaceFormat::B8G8R8A8;
+    break;
+  case android::PIXEL_FORMAT_RGBX_8888:
+    format = gfx::SurfaceFormat::B8G8R8X8;
     break;
-  case gfx::SurfaceFormat::R5G6B5_UINT16:
-    format = android::PIXEL_FORMAT_RGB_565;
+  case android::PIXEL_FORMAT_RGB_565:
+    format = gfx::SurfaceFormat::R5G6B5_UINT16;
+    break;
+  case HAL_PIXEL_FORMAT_YV12:
+    format = gfx::SurfaceFormat::YUV;
     break;
   default:
-    NS_WARNING("Unsupported surface format");
-    return false;
+    format = gfx::SurfaceFormat::UNKNOWN;
   }
 
-  return AllocateGralloc(aSize, format, usage);
-}
-
-bool
-GrallocTextureClientOGL::AllocateGralloc(gfx::IntSize aSize,
-                                         uint32_t aAndroidFormat,
-                                         uint32_t aUsage)
-{
-  MOZ_ASSERT(IsValid());
-  ISurfaceAllocator* allocator = GetAllocator();
+  if (DisableGralloc(format, aSize)) {
+    return nullptr;
+  }
 
   MaybeMagicGrallocBufferHandle handle;
-  bool allocateResult =
-    allocator->AllocGrallocBuffer(aSize,
-                                  aAndroidFormat,
-                                  aUsage,
-                                  &handle);
-  if (!allocateResult) {
-    return false;
+  if (!aAllocator->AllocGrallocBuffer(aSize, aAndroidFormat, aUsage, &handle)) {
+    return nullptr;
   }
 
   sp<GraphicBuffer> graphicBuffer = GetGraphicBufferFrom(handle);
   if (!graphicBuffer.get()) {
-    return false;
+    return nullptr;
   }
 
   if (graphicBuffer->initCheck() != NO_ERROR) {
-    return false;
+    return nullptr;
   }
 
-  mGrallocHandle = handle;
-  mGraphicBuffer = graphicBuffer;
-  mSize = aSize;
-  return true;
+  return new GrallocTextureData(handle, aSize, format, aMoz2dBackend);
+}
+
+// static
+GrallocTextureData*
+GrallocTextureData::CreateForDrawing(gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
+                                     gfx::BackendType aMoz2dBackend,
+                                     ISurfaceAllocator* aAllocator)
+{
+  if (DisableGralloc(aFormat, aSize)) {
+    return nullptr;
+  }
+  uint32_t usage = android::GraphicBuffer::USAGE_SW_READ_OFTEN |
+                   android::GraphicBuffer::USAGE_SW_WRITE_OFTEN |
+                   android::GraphicBuffer::USAGE_HW_TEXTURE;
+  auto data =  GrallocTextureData::Create(aSize, GetAndroidFormat(aFormat),
+                                          aMoz2dBackend, usage, aAllocator);
+
+  if (!data) {
+    return nullptr;
+  }
+
+  DebugOnly<gfx::SurfaceFormat> grallocFormat =
+    SurfaceFormatForPixelFormat(data->mGraphicBuffer->getPixelFormat());
+  // mFormat may be different from the format the graphic buffer reports if we
+  // swap the R and B channels but we should always have at least the same bytes
+  // per pixel!
+  MOZ_ASSERT(BytesPerPixel(data->mFormat) == BytesPerPixel(grallocFormat));
+
+  return data;
 }
 
-bool
-GrallocTextureClientOGL::IsAllocated() const
+already_AddRefed<TextureClient>
+CreateGrallocTextureClientForDrawing(gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
+                                     gfx::BackendType aMoz2dBackend,
+                                     TextureFlags aFlags,
+                                     ISurfaceAllocator* aAllocator)
 {
-  return !!mGraphicBuffer.get();
+  TextureData* data = GrallocTextureData::CreateForDrawing(aSize, aFormat, aMoz2dBackend,
+                                                           aAllocator);
+  if (!data) {
+    return nullptr;
+  }
+  if (IsGrallocRBSwapped(aFormat)) {
+    aFlags |= TextureFlags::RB_SWAPPED;
+  }
+  return MakeAndAddRef<ClientTexture>(data, aFlags, aAllocator);
 }
 
-/*static*/ already_AddRefed<TextureClient>
-GrallocTextureClientOGL::FromSharedSurface(gl::SharedSurface* abstractSurf,
-                                           TextureFlags flags)
+// static
+GrallocTextureData*
+GrallocTextureData::CreateForYCbCr(gfx::IntSize aYSize, gfx::IntSize aCbCrSize,
+                                   ISurfaceAllocator* aAllocator)
+{
+  MOZ_ASSERT(aYSize.width == aCbCrSize.width * 2);
+  MOZ_ASSERT(aYSize.height == aCbCrSize.height * 2);
+  return GrallocTextureData::Create(aYSize, HAL_PIXEL_FORMAT_YV12,
+                                    gfx::BackendType::NONE,
+                                    android::GraphicBuffer::USAGE_SW_READ_OFTEN,
+                                    aAllocator);
+}
+
+// static
+GrallocTextureData*
+GrallocTextureData::CreateForGLRendering(gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
+                                         ISurfaceAllocator* aAllocator)
+{
+  if (aFormat == gfx::SurfaceFormat::YUV) {
+    return nullptr;
+  }
+  uint32_t usage = android::GraphicBuffer::USAGE_HW_RENDER |
+                   android::GraphicBuffer::USAGE_HW_TEXTURE;
+  return GrallocTextureData::Create(aSize, GetAndroidFormat(aFormat),
+                                    gfx::BackendType::NONE, usage, aAllocator);
+}
+
+// static
+already_AddRefed<TextureClient>
+GrallocTextureData::TextureClientFromSharedSurface(gl::SharedSurface* abstractSurf,
+                                                   TextureFlags flags)
 {
   auto surf = gl::SharedSurface_Gralloc::Cast(abstractSurf);
 
   RefPtr<TextureClient> ret = surf->GetTextureClient();
 
   TextureFlags mask = TextureFlags::ORIGIN_BOTTOM_LEFT |
                       TextureFlags::RB_SWAPPED |
                       TextureFlags::NON_PREMULTIPLIED;
@@ -392,12 +409,24 @@ GrallocTextureClientOGL::FromSharedSurfa
     printf_stderr("Present flags: 0x%x. Required: 0x%x.\n",
                   (uint32_t)present,
                   (uint32_t)required);
     MOZ_CRASH("Flag requirement mismatch.");
   }
   return ret.forget();
 }
 
+TextureData*
+GrallocTextureData::CreateSimilar(ISurfaceAllocator* aAllocator,
+                                  TextureFlags aFlags,
+                                  TextureAllocationFlags aAllocFlags) const
+{
+  if (mFormat == gfx::SurfaceFormat::YUV) {
+    return GrallocTextureData::CreateForYCbCr(mSize, mSize*2, aAllocator);
+  } else {
+    return GrallocTextureData::CreateForDrawing(mSize, mFormat, mMoz2DBackend, aAllocator);
+  }
+}
+
 } // namesapace layers
 } // namesapace mozilla
 
 #endif // MOZ_WIDGET_GONK
--- a/gfx/layers/opengl/GrallocTextureClient.h
+++ b/gfx/layers/opengl/GrallocTextureClient.h
@@ -20,138 +20,120 @@ class MediaBuffer;
 
 namespace mozilla {
 namespace gl {
 class SharedSurface;
 }
 
 namespace layers {
 
-/**
- * A TextureClient implementation based on android::GraphicBuffer (also referred to
- * as "gralloc").
- *
- * Gralloc lets us map texture data in memory (accessible through pointers)
- * and also use it directly as an OpenGL texture without the cost of texture
- * uploads.
- * Gralloc buffers can also be shared accros processes.
- *
- * More info about Gralloc here: https://wiki.mozilla.org/Platform/GFX/Gralloc
- *
- * This is only used in Firefox OS
- */
-class GrallocTextureClientOGL : public TextureClient
-{
+/// A TextureData implementation based on android::GraphicBuffer (also referred to
+/// as "gralloc").
+///
+/// Gralloc lets us map texture data in memory (accessible through pointers)
+/// and also use it directly as an OpenGL texture without the cost of texture
+/// uploads.
+/// Gralloc buffers can also be shared accros processes.
+///
+/// More info about Gralloc here: https://wiki.mozilla.org/Platform/GFX/Gralloc
+///
+/// This is only used in Firefox OS
+class GrallocTextureData : public TextureData {
 public:
-  GrallocTextureClientOGL(ISurfaceAllocator* aAllocator,
-                          gfx::SurfaceFormat aFormat,
-                          gfx::BackendType aMoz2dBackend,
-                          TextureFlags aFlags = TextureFlags::DEFAULT);
+  typedef uint32_t AndroidFormat;
 
-  ~GrallocTextureClientOGL();
+  virtual bool Serialize(SurfaceDescriptor& aOutDescriptor) override;
 
-  virtual bool Lock(OpenMode aMode) override;
+  virtual bool Lock(OpenMode aMode, FenceHandle* aFence) override;
 
   virtual void Unlock() override;
 
-  virtual bool ImplementsLocking() const override { return true; }
+  virtual gfx::IntSize GetSize() const override { return mSize; }
+
+  virtual gfx::SurfaceFormat GetFormat() const override { return mFormat; }
+
+  virtual already_AddRefed<gfx::DrawTarget> BorrowDrawTarget() override;
+
+  virtual bool CanExposeMappedData() const override { return true; }
+
+  virtual bool BorrowMappedData(MappedTextureData& aMap) override;
+
+  virtual bool SupportsMoz2D() const override { return true; }
 
   virtual bool HasInternalBuffer() const override { return false; }
 
-  virtual bool IsAllocated() const override;
-
-  virtual bool ToSurfaceDescriptor(SurfaceDescriptor& aOutDescriptor) override;
-
-  virtual void SetRemoveFromCompositableWaiter(AsyncTransactionWaiter* aWaiter) override;
+  virtual bool HasSynchronization() const override { return true; }
 
-  virtual void WaitForBufferOwnership(bool aWaitReleaseFence = true) override;
+  virtual void Deallocate(ISurfaceAllocator*) override;
 
-  GrallocTextureClientOGL* AsGrallocTextureClientOGL() override {
-    return this;
-  }
-
-  void SetTextureFlags(TextureFlags aFlags) { AddFlags(aFlags); }
+  virtual void Forget(ISurfaceAllocator*) override;
 
-  gfx::IntSize GetSize() const override { return mSize; }
-
-  android::sp<android::GraphicBuffer> GetGraphicBuffer()
-  {
-    return mGraphicBuffer;
-  }
+  static GrallocTextureData* CreateForDrawing(gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
+                                              gfx::BackendType aMoz2dBackend,
+                                              ISurfaceAllocator* aAllocator);
 
-  android::PixelFormat GetPixelFormat()
-  {
-    return mGraphicBuffer->getPixelFormat();
-  }
-
-  virtual gfx::DrawTarget* BorrowDrawTarget() override;
-
-  virtual void UpdateFromSurface(gfx::SourceSurface* aSurface) override;
+  static GrallocTextureData* CreateForYCbCr(gfx::IntSize aYSize, gfx::IntSize aCbCrSize,
+                                            ISurfaceAllocator* aAllocator);
 
-  virtual bool AllocateForSurface(gfx::IntSize aSize,
-                                  TextureAllocationFlags aFlags = ALLOC_DEFAULT) override;
+  static GrallocTextureData* CreateForGLRendering(gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
+                                                  ISurfaceAllocator* aAllocator);
 
-  virtual bool AllocateForYCbCr(gfx::IntSize aYSize,
-                                gfx::IntSize aCbCrSize,
-                                StereoMode aStereoMode);
-
-  bool AllocateForGLRendering(gfx::IntSize aSize);
-
-  bool AllocateGralloc(gfx::IntSize aYSize, uint32_t aAndroidFormat, uint32_t aUsage);
-
-  void SetIsOpaque(bool aIsOpaque) { mIsOpaque = aIsOpaque; }
+  static GrallocTextureData* Create(gfx::IntSize aSize, AndroidFormat aFormat,
+                                    gfx::BackendType aMoz2DBackend, uint32_t aUsage,
+                                    ISurfaceAllocator* aAllocator);
 
-  /**
-   * Hold android::MediaBuffer.
-   * MediaBuffer needs to be add refed to keep MediaBuffer alive
-   * during TextureClient is in use.
-   */
-  void SetMediaBuffer(android::MediaBuffer* aMediaBuffer)
-  {
-    mMediaBuffer = aMediaBuffer;
-  }
+
+  static already_AddRefed<TextureClient>
+  TextureClientFromSharedSurface(gl::SharedSurface* abstractSurf, TextureFlags flags);
 
-  android::MediaBuffer* GetMediaBuffer()
-  {
-    return mMediaBuffer;
-  }
-
-  virtual already_AddRefed<TextureClient>
-  CreateSimilar(TextureFlags aFlags = TextureFlags::DEFAULT,
+  virtual TextureData*
+  CreateSimilar(ISurfaceAllocator* aAllocator,
+                TextureFlags aFlags = TextureFlags::DEFAULT,
                 TextureAllocationFlags aAllocFlags = ALLOC_DEFAULT) const override;
 
-  static already_AddRefed<TextureClient> FromSharedSurface(gl::SharedSurface* surf,
-                                                       TextureFlags flags);
+  // use ClientTexture's default implementation
+  virtual bool UpdateFromSurface(gfx::SourceSurface* aSurface) override;
+
+  /// Hold android::MediaBuffer.
+  /// MediaBuffer needs to be add refed to keep MediaBuffer alive while the texture
+  /// is in use.
+  ///
+  /// TODO - ideally we should be able to put the MediaBuffer in the texture's
+  /// constructor and not expose these methods.
+  void SetMediaBuffer(android::MediaBuffer* aMediaBuffer) { mMediaBuffer = aMediaBuffer; }
+  android::MediaBuffer* GetMediaBuffer() { return mMediaBuffer; }
+
+  android::sp<android::GraphicBuffer> GetGraphicBuffer() { return mGraphicBuffer; }
+
+  virtual void WaitForFence(FenceHandle* aFence) override;
+
+  ~GrallocTextureData();
 
 protected:
-  gfx::SurfaceFormat mFormat;
-  gfx::IntSize mSize;
-  gfx::BackendType mBackend;
-  OpenMode mOpenMode;
+  GrallocTextureData(MaybeMagicGrallocBufferHandle aGrallocHandle,
+                     gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
+                     gfx::BackendType aMoz2DBackend);
 
-  /**
-   * Unfortunately, until bug 879681 is fixed we need to use a GrallocBufferActor.
-   */
+  gfx::IntSize mSize;
+  gfx::SurfaceFormat mFormat;
+  gfx::BackendType mMoz2DBackend;
+
   MaybeMagicGrallocBufferHandle mGrallocHandle;
-
-  RefPtr<AsyncTransactionWaiter> mRemoveFromCompositableWaiter;
-
   android::sp<android::GraphicBuffer> mGraphicBuffer;
 
-  /**
-   * Points to a mapped gralloc buffer between calls to lock and unlock.
-   * Should be null outside of the lock-unlock pair.
-   */
+  // Points to a mapped gralloc buffer between calls to lock and unlock.
+  // Should be null outside of the lock-unlock pair.
   uint8_t* mMappedBuffer;
 
-  RefPtr<gfx::DrawTarget> mDrawTarget;
-
   android::MediaBuffer* mMediaBuffer;
+};
 
-  bool mIsOpaque;
-  bool mLocked;
-};
+gfx::SurfaceFormat SurfaceFormatForPixelFormat(android::PixelFormat aFormat);
+
+already_AddRefed<TextureClient> CreateGrallocTextureClientForDrawing(gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
+                                                                     gfx::BackendType aMoz2dBackend, TextureFlags aFlags,
+                                                                     ISurfaceAllocator* aAllocator);
 
 } // namespace layers
 } // namespace mozilla
 
 #endif // MOZ_WIDGET_GONK
 #endif
--- a/widget/gonk/nativewindow/GonkBufferQueueJB.cpp
+++ b/widget/gonk/nativewindow/GonkBufferQueueJB.cpp
@@ -416,29 +416,28 @@ status_t GonkBufferQueue::dequeueBuffer(
         }
 
         *outFence = mSlots[buf].mFence;
         mSlots[buf].mFence = Fence::NO_FENCE;
     }  // end lock scope
 
     sp<GraphicBuffer> graphicBuffer;
     if (returnFlags & IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION) {
-        RefPtr<GrallocTextureClientOGL> textureClient =
-            new GrallocTextureClientOGL(ImageBridgeChild::GetSingleton(),
-                                        gfx::SurfaceFormat::UNKNOWN,
-                                        gfx::BackendType::NONE,
-                                        TextureFlags::DEALLOCATE_CLIENT);
-        textureClient->SetIsOpaque(true);
+
         usage |= GraphicBuffer::USAGE_HW_TEXTURE;
-        bool result = textureClient->AllocateGralloc(IntSize(w, h), format, usage);
-        sp<GraphicBuffer> graphicBuffer = textureClient->GetGraphicBuffer();
-        if (!result || !graphicBuffer.get()) {
+        ISurfaceAllocator* allocator = ImageBridgeChild::GetSingleton();
+        GrallocTextureData* texData = GrallocTextureData::Create(IntSize(w,h), format,
+                                                                 gfx::BackendType::NONE, usage,
+                                                                 allocator);
+        if (!texData) {
             ST_LOGE("dequeueBuffer: failed to alloc gralloc buffer");
             return -ENOMEM;
         }
+        RefPtr<TextureClient> textureClient = new ClientTexture(texData, TextureFlags::DEALLOCATE_CLIENT, allocator);
+        sp<GraphicBuffer> graphicBuffer = texData->GetGraphicBuffer();
 
         { // Scope for the lock
             Mutex::Autolock lock(mMutex);
 
             if (mAbandoned) {
                 ST_LOGE("dequeueBuffer: SurfaceTexture has been abandoned!");
                 return NO_INIT;
             }
--- a/widget/gonk/nativewindow/GonkBufferQueueKK.cpp
+++ b/widget/gonk/nativewindow/GonkBufferQueueKK.cpp
@@ -435,41 +435,38 @@ status_t GonkBufferQueue::dequeueBuffer(
             ALOGE("dequeueBuffer: about to return a NULL fence from mSlot. "
                     "buf=%d, w=%d, h=%d, format=%d",
                     buf, buffer->width, buffer->height, buffer->format);
         }
         *outFence = mSlots[buf].mFence;
         mSlots[buf].mFence = Fence::NO_FENCE;
     }  // end lock scope
 
-    sp<GraphicBuffer> graphicBuffer;
     if (returnFlags & IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION) {
-        RefPtr<GrallocTextureClientOGL> textureClient =
-            new GrallocTextureClientOGL(ImageBridgeChild::GetSingleton(),
-                                        gfx::SurfaceFormat::UNKNOWN,
-                                        gfx::BackendType::NONE,
-                                        TextureFlags::DEALLOCATE_CLIENT);
-        textureClient->SetIsOpaque(true);
+
+        ISurfaceAllocator* allocator = ImageBridgeChild::GetSingleton();
         usage |= GraphicBuffer::USAGE_HW_TEXTURE;
-        bool result = textureClient->AllocateGralloc(IntSize(w, h), format, usage);
-        sp<GraphicBuffer> graphicBuffer = textureClient->GetGraphicBuffer();
-        if (!result || !graphicBuffer.get()) {
-            ALOGE("dequeueBuffer: failed to alloc gralloc buffer");
+        GrallocTextureData* texData = GrallocTextureData::Create(IntSize(w, h), format,
+                                                                 gfx::BackendType::NONE, usage,
+                                                                 allocator);
+        if (!texData) {
             return -ENOMEM;
         }
 
+        RefPtr<TextureClient> textureClient = new ClientTexture(texData, TextureFlags::DEALLOCATE_CLIENT, allocator);
+
         { // Scope for the lock
             Mutex::Autolock lock(mMutex);
 
             if (mAbandoned) {
                 ALOGE("dequeueBuffer: SurfaceTexture has been abandoned!");
                 return NO_INIT;
             }
 
-            mSlots[buf].mGraphicBuffer = graphicBuffer;
+            mSlots[buf].mGraphicBuffer = texData->GetGraphicBuffer();
             mSlots[buf].mTextureClient = textureClient;
             ALOGD("dequeueBuffer: returning slot=%d buf=%p ", buf,
                     mSlots[buf].mGraphicBuffer->handle);
 
         }
 
     }
 
--- a/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferQueueProducer.cpp
+++ b/widget/gonk/nativewindow/GonkBufferQueueLL/GonkBufferQueueProducer.cpp
@@ -336,29 +336,29 @@ status_t GonkBufferQueueProducer::dequeu
                     found, buffer->width, buffer->height, buffer->format);
         }
 
         *outFence = mSlots[found].mFence;
         mSlots[found].mFence = Fence::NO_FENCE;
     } // Autolock scope
 
     if (returnFlags & BUFFER_NEEDS_REALLOCATION) {
-        RefPtr<GrallocTextureClientOGL> textureClient =
-            new GrallocTextureClientOGL(ImageBridgeChild::GetSingleton(),
-                                        gfx::SurfaceFormat::UNKNOWN,
-                                        gfx::BackendType::NONE,
-                                        TextureFlags::DEALLOCATE_CLIENT);
-        textureClient->SetIsOpaque(true);
+        ISurfaceAllocator* allocator = ImageBridgeChild::GetSingleton();
         usage |= GraphicBuffer::USAGE_HW_TEXTURE;
-        bool result = textureClient->AllocateGralloc(IntSize(width, height), format, usage);
-        sp<GraphicBuffer> graphicBuffer = textureClient->GetGraphicBuffer();
-        if (!result || !graphicBuffer.get()) {
+        GrallocTextureData* texData = GrallocTextureData::Create(IntSize(width,height), format,
+                                                                 gfx::BackendType::NONE,
+                                                                 usage, allocator);
+        if (!texData) {
             ALOGE("dequeueBuffer: failed to alloc gralloc buffer");
             return -ENOMEM;
         }
+        RefPtr<TextureClient> textureClient = TextureClient::CreateWithData(
+            texData, TextureFlags::DEALLOCATE_CLIENT, allocator);
+
+        sp<GraphicBuffer> graphicBuffer = texData->GetGraphicBuffer();
 
         { // Autolock scope
             Mutex::Autolock lock(mCore->mMutex);
 
             if (mCore->mIsAbandoned) {
                 ALOGE("dequeueBuffer: GonkBufferQueue has been abandoned");
                 return NO_INIT;
             }
--- a/widget/gonk/nativewindow/GonkNativeWindowICS.cpp
+++ b/widget/gonk/nativewindow/GonkNativeWindowICS.cpp
@@ -313,44 +313,40 @@ status_t GonkNativeWindow::dequeueBuffer
                 TextureClientReleaseTask* task = new TextureClientReleaseTask(mSlots[buf].mTextureClient);
                 mSlots[buf].mTextureClient = NULL;
                 ImageBridgeChild::GetSingleton()->GetMessageLoop()->PostTask(FROM_HERE, task);
             }
             alloc = true;
         }
     }  // end lock scope
 
-    sp<GraphicBuffer> graphicBuffer;
     if (alloc) {
-        RefPtr<GrallocTextureClientOGL> textureClient =
-            new GrallocTextureClientOGL(ImageBridgeChild::GetSingleton(),
-                                        gfx::SurfaceFormat::UNKNOWN,
-                                        gfx::BackendType::NONE,
-                                        TextureFlags::DEALLOCATE_CLIENT);
-        textureClient->SetIsOpaque(true);
+        ISurfaceAllocator* allocator = ImageBridgeChild::GetSingleton();
         usage |= GraphicBuffer::USAGE_HW_TEXTURE;
-        bool result = textureClient->AllocateGralloc(IntSize(w, h), format, usage);
-        sp<GraphicBuffer> graphicBuffer = textureClient->GetGraphicBuffer();
-        if (!result || !graphicBuffer.get()) {
-            CNW_LOGE("dequeueBuffer: failed to alloc gralloc buffer");
+        GrallocTextureData* texData = GrallocTextureData::Create(IntSize(w, h), format,
+                                                                 gfx::BackendType::NONE, usage,
+                                                                 allocator);
+        if (!texData) {
             return -ENOMEM;
         }
 
+        RefPtr<TextureClient> textureClient = new ClientTexture(texData, TextureFlags::DEALLOCATE_CLIENT, allocator);
+
         { // Scope for the lock
             Mutex::Autolock lock(mMutex);
 
             if (mAbandoned) {
                 CNW_LOGE("dequeueBuffer: SurfaceTexture has been abandoned!");
                 return NO_INIT;
             }
 
             if (updateFormat) {
                 mPixelFormat = format;
             }
-            mSlots[buf].mGraphicBuffer = graphicBuffer;
+            mSlots[buf].mGraphicBuffer = texData->GetGraphicBuffer();
             mSlots[buf].mTextureClient = textureClient;
 
             returnFlags |= ISurfaceTexture::BUFFER_NEEDS_REALLOCATION;
 
             CNW_LOGD("dequeueBuffer: returning slot=%d buf=%p ", buf,
                     mSlots[buf].mGraphicBuffer->handle);
         }
     }