Bug 1200595 - Consolidate the TextureClient's destruction logic. r=mattwoodrow
☠☠ backed out by 9783264529d3 ☠ ☠
authorNicolas Silva <nsilva@mozilla.com>
Fri, 20 Nov 2015 14:25:03 +0100
changeset 309918 cf8cf1a039dd370d157b2afaa1fed719f1e34069
parent 309917 65da564f952c211fde3a7512251b3d98e3ed8bb4
child 309919 1e426f4d6f3625d2b3f51bee8f003bb1a0bec635
push id1040
push userraliiev@mozilla.com
push dateMon, 29 Feb 2016 17:11:22 +0000
treeherdermozilla-release@8c3167321162 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmattwoodrow
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 - Consolidate the TextureClient's destruction logic. r=mattwoodrow
gfx/gl/SharedSurfaceGralloc.cpp
gfx/layers/AsyncCanvasRenderer.cpp
gfx/layers/CompositorTypes.h
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/client/TextureClientSharedSurface.h
gfx/layers/d3d11/TextureD3D11.cpp
gfx/layers/d3d11/TextureD3D11.h
gfx/layers/d3d9/TextureD3D9.cpp
gfx/layers/d3d9/TextureD3D9.h
gfx/layers/ipc/CompositableForwarder.h
gfx/layers/ipc/ImageBridgeChild.cpp
gfx/layers/ipc/ImageBridgeChild.h
gfx/layers/ipc/LayerTransactionChild.cpp
gfx/layers/ipc/ShadowLayers.cpp
gfx/layers/ipc/ShadowLayers.h
gfx/layers/opengl/GrallocTextureClient.cpp
gfx/layers/opengl/GrallocTextureClient.h
gfx/layers/opengl/MacIOSurfaceTextureClientOGL.cpp
gfx/layers/opengl/MacIOSurfaceTextureClientOGL.h
--- a/gfx/gl/SharedSurfaceGralloc.cpp
+++ b/gfx/gl/SharedSurfaceGralloc.cpp
@@ -274,17 +274,16 @@ void
 SharedSurface_Gralloc::WaitForBufferOwnership()
 {
     mTextureClient->WaitForBufferOwnership();
 }
 
 bool
 SharedSurface_Gralloc::ToSurfaceDescriptor(layers::SurfaceDescriptor* const out_descriptor)
 {
-    mTextureClient->MarkShared();
     return mTextureClient->ToSurfaceDescriptor(*out_descriptor);
 }
 
 bool
 SharedSurface_Gralloc::ReadbackBySharedHandle(gfx::DataSourceSurface* out_surface)
 {
     MOZ_ASSERT(out_surface);
     sp<GraphicBuffer> buffer = static_cast<GrallocTextureData*>(
--- a/gfx/layers/AsyncCanvasRenderer.cpp
+++ b/gfx/layers/AsyncCanvasRenderer.cpp
@@ -144,17 +144,17 @@ AsyncCanvasRenderer::GetActiveThread()
   return result.forget();
 }
 
 void
 AsyncCanvasRenderer::CopyFromTextureClient(TextureClient* aTextureClient)
 {
   MutexAutoLock lock(mMutex);
   TextureClientAutoLock texLock(aTextureClient, layers::OpenMode::OPEN_READ);
-  if (texLock.Succeeded()) {
+  if (!texLock.Succeeded()) {
     return;
   }
 
   const gfx::IntSize& size = aTextureClient->GetSize();
   // This buffer would be used later for content rendering. So we choose
   // B8G8R8A8 format here.
   const gfx::SurfaceFormat format = gfx::SurfaceFormat::B8G8R8A8;
   // Avoid to create buffer every time.
--- a/gfx/layers/CompositorTypes.h
+++ b/gfx/layers/CompositorTypes.h
@@ -46,29 +46,31 @@ enum class TextureFlags : uint32_t {
   NON_PREMULTIPLIED  = 1 << 4,
   // The texture should be recycled when no longer in used
   RECYCLE            = 1 << 5,
   // If DEALLOCATE_CLIENT is set, the shared data is deallocated on the
   // client side and requires some extra synchronizaion to ensure race-free
   // deallocation.
   // The default behaviour is to deallocate on the host side.
   DEALLOCATE_CLIENT  = 1 << 6,
+  DEALLOCATE_SYNC    = 1 << 6, // XXX - make it a separate flag.
+  DEALLOCATE_MAIN_THREAD = 1 << 8,
   // After being shared ith the compositor side, an immutable texture is never
   // modified, it can only be read. It is safe to not Lock/Unlock immutable
   // textures.
-  IMMUTABLE          = 1 << 7,
+  IMMUTABLE          = 1 << 9,
   // The contents of the texture must be uploaded or copied immediately
   // during the transaction, because the producer may want to write
   // to it again.
-  IMMEDIATE_UPLOAD   = 1 << 8,
+  IMMEDIATE_UPLOAD   = 1 << 10,
   // The texture is part of a component-alpha pair
-  COMPONENT_ALPHA    = 1 << 9,
+  COMPONENT_ALPHA    = 1 << 11,
 
   // OR union of all valid bits
-  ALL_BITS           = (1 << 10) - 1,
+  ALL_BITS           = (1 << 12) - 1,
   // the default flags
   DEFAULT = NO_FLAGS
 };
 MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(TextureFlags)
 
 static inline bool
 TextureRequiresLocking(TextureFlags aFlags)
 {
--- a/gfx/layers/basic/TextureClientX11.cpp
+++ b/gfx/layers/basic/TextureClientX11.cpp
@@ -16,27 +16,16 @@
 #include <X11/Xlib.h>
 
 using namespace mozilla;
 using namespace mozilla::gfx;
 
 namespace mozilla {
 namespace layers {
 
-already_AddRefed<TextureClient>
-CreateX11TextureClient(gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
-                       TextureFlags aFlags, ISurfaceAllocator* aAllocator)
-{
-  TextureData* data = X11TextureData::Create(aSize, aFormat, aFlags, aAllocator);
-  if (!data) {
-    return nullptr;
-  }
-  return MakeAndAddRef<TextureClient>(data, aFlags, aAllocator);
-}
-
 X11TextureData::X11TextureData(gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
                                bool aClientDeallocation, bool aIsCrossProcess,
                                gfxXlibSurface* aSurface)
 : mSize(aSize)
 , mFormat(aFormat)
 , mSurface(aSurface)
 , mClientDeallocation(aClientDeallocation)
 , mIsCrossProcess(aIsCrossProcess)
--- a/gfx/layers/basic/TextureClientX11.h
+++ b/gfx/layers/basic/TextureClientX11.h
@@ -51,16 +51,12 @@ protected:
 
   gfx::IntSize mSize;
   gfx::SurfaceFormat mFormat;
   RefPtr<gfxXlibSurface> mSurface;
   bool mClientDeallocation;
   bool mIsCrossProcess;
 };
 
-already_AddRefed<TextureClient>
-CreateX11TextureClient(gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
-                       TextureFlags aFlags, ISurfaceAllocator* aAllocator);
-
 } // namespace layers
 } // namespace mozilla
 
 #endif
--- a/gfx/layers/client/TextureClient.cpp
+++ b/gfx/layers/client/TextureClient.cpp
@@ -62,62 +62,60 @@
 
 namespace mozilla {
 namespace layers {
 
 using namespace mozilla::ipc;
 using namespace mozilla::gl;
 using namespace mozilla::gfx;
 
-struct ReleaseKeepAlive : public nsRunnable
+struct TextureDeallocParams
 {
-  NS_IMETHOD Run()
-  {
-    mKeep = nullptr;
-    return NS_OK;
-  }
+  TextureData* data;
+  RefPtr<TextureChild> actor;
+  RefPtr<ISurfaceAllocator> allocator;
+  bool clientDeallocation;
+  bool syncDeallocation;
+};
 
-  UniquePtr<KeepAlive> mKeep;
-};
+void DeallocateTextureClient(TextureDeallocParams params);
 
 /**
  * TextureChild is the content-side incarnation of the PTexture IPDL actor.
  *
  * TextureChild is used to synchronize a texture client and its corresponding
  * TextureHost if needed (a TextureClient that is not shared with the compositor
  * does not have a TextureChild)
  *
  * During the deallocation phase, a TextureChild may hold its recently destroyed
  * TextureClient's data until the compositor side confirmed that it is safe to
  * deallocte or recycle the it.
  */
 class TextureChild final : public ChildActor<PTextureChild>
 {
   ~TextureChild()
   {
-    if (mKeep && mMainThreadOnly && !NS_IsMainThread()) {
-      RefPtr<ReleaseKeepAlive> release = new ReleaseKeepAlive();
-      release->mKeep = Move(mKeep);
-      NS_DispatchToMainThread(release);
-    }
+    // We should have deallocated mTextureData in ActorDestroy
+    MOZ_ASSERT(!mTextureData);
   }
 public:
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(TextureChild)
 
   TextureChild()
   : mForwarder(nullptr)
   , mMonitor("TextureChild")
   , mTextureClient(nullptr)
+  , mTextureData(nullptr)
   , mDestroyed(false)
   , mMainThreadOnly(false)
   , mIPCOpen(false)
-  {
-  }
+  , mOwnsTextureData(false)
+  {}
 
-  bool Recv__delete__() override;
+  bool Recv__delete__() override { return true; }
 
   bool RecvCompositorRecycle() override
   {
     RECYCLE_LOG("[CLIENT] Receive recycle %p (%p)\n", mTextureClient, mWaitForRecycle.get());
     mWaitForRecycle = nullptr;
     return true;
   }
 
@@ -163,61 +161,211 @@ private:
   }
 
   RefPtr<CompositableForwarder> mForwarder;
   RefPtr<TextureClient> mWaitForRecycle;
 
   // Monitor protecting mTextureClient.
   Monitor mMonitor;
   TextureClient* mTextureClient;
-  UniquePtr<KeepAlive> mKeep;
+  TextureData* mTextureData;
   Atomic<bool> mDestroyed;
   bool mMainThreadOnly;
   bool mIPCOpen;
+  bool mOwnsTextureData;
 
   friend class TextureClient;
+  friend void DeallocateTextureClient(TextureDeallocParams params);
 };
 
-bool
-TextureChild::Recv__delete__()
+
+static void DestroyTextureData(TextureData* aTextureData, ISurfaceAllocator* aAllocator,
+                               bool aDeallocate, bool aMainThreadOnly)
 {
-  return true;
+  MOZ_ASSERT(aTextureData);
+  if (!aTextureData) {
+    return;
+  }
+
+  if (aMainThreadOnly && !NS_IsMainThread()) {
+    RefPtr<ISurfaceAllocator> allocatorRef = aAllocator;
+    NS_DispatchToMainThread(NS_NewRunnableFunction([aTextureData, allocatorRef, aDeallocate]() -> void {
+      DestroyTextureData(aTextureData, allocatorRef, aDeallocate, true);
+    }));
+    return;
+  }
+
+  if (aDeallocate) {
+    aTextureData->Deallocate(aAllocator);
+  } else {
+    aTextureData->Forget(aAllocator);
+  }
+  delete aTextureData;
 }
 
 void
 TextureChild::ActorDestroy(ActorDestroyReason why)
 {
-  if (mTextureClient) {
-    mTextureClient->mActor = nullptr;
-    mTextureClient->mAllocator = nullptr;
+  mWaitForRecycle = nullptr;
+
+  if (mTextureData) {
+    DestroyTextureData(mTextureData, GetAllocator(), mOwnsTextureData, mMainThreadOnly);
+    mTextureData = nullptr;
   }
-  mWaitForRecycle = nullptr;
-  mKeep = nullptr;
+}
+
+void DeallocateTextureClientSyncProxy(TextureDeallocParams params,
+                                        ReentrantMonitor* aBarrier, bool* aDone)
+{
+  DeallocateTextureClient(params);
+  ReentrantMonitorAutoEnter autoMon(*aBarrier);
+  *aDone = true;
+  aBarrier->NotifyAll();
 }
 
+/// The logic for synchronizing a TextureClient's deallocation goes here.
+///
+/// This funciton takes care of dispatching work to the right thread using
+/// a synchronous proxy if needed, and handles client/host deallocation.
+void
+DeallocateTextureClient(TextureDeallocParams params)
+{
+  TextureChild* actor = params.actor;
+  MessageLoop* ipdlMsgLoop = nullptr;
+
+  if (params.allocator) {
+    ipdlMsgLoop = params.allocator->GetMessageLoop();
+    if (!ipdlMsgLoop) {
+      // An allocator with no message loop means we are too late in the shutdown
+      // sequence.
+      gfxCriticalError() << "Texture deallocated too late during shutdown";
+      return;
+    }
+  }
+
+  // First make sure that the work is happening on the IPDL thread.
+  if (ipdlMsgLoop && MessageLoop::current() != ipdlMsgLoop) {
+    if (params.syncDeallocation) {
+      bool done = false;
+      ReentrantMonitor barrier("DeallocateTextureClient");
+      ReentrantMonitorAutoEnter autoMon(barrier);
+      ipdlMsgLoop->PostTask(FROM_HERE,
+        NewRunnableFunction(DeallocateTextureClientSyncProxy,
+                            params, &barrier, &done));
+      while (!done) {
+        barrier.Wait();
+      }
+    } else {
+      ipdlMsgLoop->PostTask(FROM_HERE,
+        NewRunnableFunction(DeallocateTextureClient, params));
+    }
+    // The work has been forwarded to the IPDL thread, we are done.
+    return;
+  }
+
+  // Below this line, we are either in the IPDL thread or ther is no IPDL
+  // thread anymore.
+
+  if (!ipdlMsgLoop) {
+    // If we don't have a message loop we can't know for sure that we are in
+    // the IPDL thread and use the ISurfaceAllocator.
+    // This should ideally not happen outside of gtest, but some shutdown raciness
+    // could put us in this situation.
+    params.allocator = nullptr;
+  }
+
+  if (!actor) {
+    // We don't have an IPDL actor, probably because we destroyed the TextureClient
+    // before sharing it with the compositor. It means the data cannot be owned by
+    // the TextureHost since we never created the TextureHost.
+    DestroyTextureData(params.data, params.allocator,
+                       true,    // client-side deallocation
+                       false);  // main-thread deallocation
+    return;
+  }
+
+  if (!actor->IPCOpen()) {
+    // The actor is already deallocated which probably means there was a shutdown
+    // race causing this function to be called concurrently which is bad!
+    gfxCriticalError() << "Racy texture deallocation";
+    return;
+  }
+
+  if (params.syncDeallocation) {
+    MOZ_PERFORMANCE_WARNING("gfx",
+      "TextureClient/Host pair requires synchronous deallocation");
+    actor->DestroySynchronously();
+    DestroyTextureData(params.data, params.allocator, params.clientDeallocation,
+                       actor->mMainThreadOnly);
+  } else {
+    actor->mTextureData = params.data;
+    actor->mOwnsTextureData = params.clientDeallocation;
+    actor->Destroy();
+    // DestroyTextureData will be called by TextureChild::ActorDestroy
+  }
+}
+
+void TextureClient::Destroy(bool aForceSync)
+{
+  MOZ_ASSERT(!IsLocked());
+
+  RefPtr<TextureChild> actor = mActor;
+  mActor = nullptr;
+
+  if (actor && !actor->mDestroyed.compareExchange(false, true)) {
+    actor = nullptr;
+  }
+
+  TextureData* data = mData;
+  if (!mWorkaroundAnnoyingSharedSurfaceLifetimeIssues) {
+    mData = nullptr;
+  }
+
+  if (data || actor) {
+    TextureDeallocParams params;
+    params.actor = actor;
+    params.allocator = mAllocator;
+    params.clientDeallocation = !!(mFlags & TextureFlags::DEALLOCATE_CLIENT);
+    if (mWorkaroundAnnoyingSharedSurfaceLifetimeIssues) {
+      params.data = nullptr;
+    } else {
+      params.data = data;
+    }
+    // At the moment we always deallocate synchronously when deallocating on the
+    // client side, but having asynchronous deallocate in some of the cases will
+    // be a worthwhile optimization.
+    params.syncDeallocation = !!(mFlags & TextureFlags::DEALLOCATE_CLIENT) || aForceSync;
+    DeallocateTextureClient(params);
+  }
+}
 
 bool
 TextureClient::Lock(OpenMode aMode)
 {
-  MOZ_ASSERT(mValid);
+  MOZ_ASSERT(IsValid());
   MOZ_ASSERT(!mIsLocked);
   if (mIsLocked) {
     return mOpenMode == aMode;
   }
 
+  if (mRemoveFromCompositableWaiter) {
+    mRemoveFromCompositableWaiter->WaitComplete();
+    mRemoveFromCompositableWaiter = nullptr;
+  }
+
   mIsLocked = mData->Lock(aMode, mReleaseFenceHandle.IsValid() ? &mReleaseFenceHandle : nullptr);
   mOpenMode = aMode;
 
   return mIsLocked;
 }
 
 void
 TextureClient::Unlock()
 {
-  MOZ_ASSERT(mValid);
+  MOZ_ASSERT(IsValid());
   MOZ_ASSERT(mIsLocked);
   if (!mIsLocked) {
     return;
   }
 
   if (mBorrowedDrawTarget) {
     MOZ_ASSERT(mBorrowedDrawTarget->refCount() <= mExpectedDtRefs);
     if (mOpenMode & OpenMode::OPEN_WRITE) {
@@ -236,54 +384,43 @@ TextureClient::Unlock()
   mData->Unlock();
   mIsLocked = false;
   mOpenMode = OpenMode::OPEN_NONE;
 }
 
 bool
 TextureClient::HasInternalBuffer() const
 {
-  MOZ_ASSERT(mValid);
+  MOZ_ASSERT(IsValid());
   return mData->HasInternalBuffer();
 }
 
 gfx::IntSize
 TextureClient::GetSize() const
 {
-  MOZ_ASSERT(mValid);
+  MOZ_ASSERT(IsValid());
   return mData->GetSize();
 }
 
 gfx::SurfaceFormat
 TextureClient::GetFormat() const
 {
-  MOZ_ASSERT(mValid);
+  MOZ_ASSERT(IsValid());
   return mData->GetFormat();
 }
 
 TextureClient::~TextureClient()
 {
-  if (ShouldDeallocateInDestructor()) {
-    mData->Deallocate(mAllocator);
-  } else {
-    mData->Forget(mAllocator);
-  }
-  delete mData;
-}
-
-void
-TextureClient::FinalizeOnIPDLThread()
-{
-  mData->FinalizeOnIPDLThread(this);
+  Destroy(false);
 }
 
 void
 TextureClient::UpdateFromSurface(gfx::SourceSurface* aSurface)
 {
-  MOZ_ASSERT(mValid);
+  MOZ_ASSERT(IsValid());
   MOZ_ASSERT(mIsLocked);
   MOZ_ASSERT(aSurface);
 
   // XXX - It would be better to first try the DrawTarget approach and fallback
   // to the backend-specific implementation because the latter will usually do
   // an expensive read-back + cpu-side copy if the texture is on the gpu.
   // There is a bug with the DrawTarget approach, though specific to reading back
   // from WebGL (where R and B channel end up inverted) to figure out first.
@@ -303,29 +440,29 @@ TextureClient::UpdateFromSurface(gfx::So
   }
   NS_WARNING("TextureClient::UpdateFromSurface failed");
 }
 
 
 already_AddRefed<TextureClient>
 TextureClient::CreateSimilar(TextureFlags aFlags, TextureAllocationFlags aAllocFlags) const
 {
-  MOZ_ASSERT(mValid);
+  MOZ_ASSERT(IsValid());
   TextureData* data = mData->CreateSimilar(mAllocator, aFlags, aAllocFlags);
   if (!data) {
     return nullptr;
   }
 
   return MakeAndAddRef<TextureClient>(data, aFlags, mAllocator);
 }
 
 gfx::DrawTarget*
 TextureClient::BorrowDrawTarget()
 {
-  MOZ_ASSERT(mValid);
+  MOZ_ASSERT(IsValid());
   MOZ_ASSERT(mIsLocked);
   // TODO- We can't really assert that at the moment because there is code that Borrows
   // the DrawTarget, just to get a snapshot, which is legit in term of OpenMode
   // but we should have a way to get a SourceSurface directly instead.
   //MOZ_ASSERT(mOpenMode & OpenMode::OPEN_WRITE);
 
   if (!mIsLocked) {
     return nullptr;
@@ -343,54 +480,56 @@ TextureClient::BorrowDrawTarget()
   }
 
   return mBorrowedDrawTarget;
 }
 
 bool
 TextureClient::BorrowMappedData(MappedTextureData& aMap)
 {
-  MOZ_ASSERT(mValid);
+  MOZ_ASSERT(IsValid());
 
   // TODO - SharedRGBImage just accesses the buffer without properly locking
   // the texture. It's bad.
   //MOZ_ASSERT(mIsLocked);
   //if (!mIsLocked) {
   //  return nullptr;
   //}
 
   return mData->BorrowMappedData(aMap);
 }
 
 bool
 TextureClient::BorrowMappedYCbCrData(MappedYCbCrTextureData& aMap)
 {
-  MOZ_ASSERT(mValid);
+  MOZ_ASSERT(IsValid());
   return mData->BorrowMappedYCbCrData(aMap);
 }
 
 bool
 TextureClient::ToSurfaceDescriptor(SurfaceDescriptor& aOutDescriptor)
 {
-  MOZ_ASSERT(mValid);
+  MOZ_ASSERT(IsValid());
   return mData->Serialize(aOutDescriptor);
 }
 
 void
 TextureClient::WaitForBufferOwnership(bool aWaitReleaseFence)
 {
   if (mRemoveFromCompositableWaiter) {
     mRemoveFromCompositableWaiter->WaitComplete();
     mRemoveFromCompositableWaiter = nullptr;
   }
 
+#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION < 21
   if (aWaitReleaseFence && mReleaseFenceHandle.IsValid()) {
     mData->WaitForFence(&mReleaseFenceHandle);
     mReleaseFenceHandle = FenceHandle();
   }
+#endif
 }
 
 // static
 PTextureChild*
 TextureClient::CreateIPDLActor()
 {
   TextureChild* c = new TextureChild();
   c->AddIPDLReference();
@@ -404,55 +543,63 @@ TextureClient::DestroyIPDLActor(PTexture
   static_cast<TextureChild*>(actor)->ReleaseIPDLReference();
   return true;
 }
 
 // static
 TextureClient*
 TextureClient::AsTextureClient(PTextureChild* actor)
 {
-  return actor ? static_cast<TextureChild*>(actor)->mTextureClient : nullptr;
+  if (!actor) {
+    return nullptr;
+  }
+  TextureChild* tc = static_cast<TextureChild*>(actor);
+  if (tc->mDestroyed) {
+    return nullptr;
+  }
+
+  return tc->mTextureClient;
 }
 
 bool
 TextureClient::IsSharedWithCompositor() const {
-  return mShared && mActor && mActor->IPCOpen();
+  return mActor && mActor->IPCOpen();
 }
 
 void
 TextureClient::AddFlags(TextureFlags aFlags)
 {
   MOZ_ASSERT(!IsSharedWithCompositor() ||
              ((GetFlags() & TextureFlags::RECYCLE) && !IsAddedToCompositableClient()));
   mFlags |= aFlags;
-  if (mValid && mActor && !mActor->mDestroyed && mActor->IPCOpen()) {
+  if (IsValid() && mActor && !mActor->mDestroyed && mActor->IPCOpen()) {
     mActor->SendRecycleTexture(mFlags);
   }
 }
 
 void
 TextureClient::RemoveFlags(TextureFlags aFlags)
 {
   MOZ_ASSERT(!IsSharedWithCompositor() ||
              ((GetFlags() & TextureFlags::RECYCLE) && !IsAddedToCompositableClient()));
   mFlags &= ~aFlags;
-  if (mValid && mActor && !mActor->mDestroyed && mActor->IPCOpen()) {
+  if (IsValid() && mActor && !mActor->mDestroyed && mActor->IPCOpen()) {
     mActor->SendRecycleTexture(mFlags);
   }
 }
 
 void
 TextureClient::RecycleTexture(TextureFlags aFlags)
 {
   MOZ_ASSERT(GetFlags() & TextureFlags::RECYCLE);
 
   mAddedToCompositableClient = false;
   if (mFlags != aFlags) {
     mFlags = aFlags;
-    if (mValid && mActor && !mActor->mDestroyed && mActor->IPCOpen()) {
+    if (IsValid() && mActor && !mActor->mDestroyed && mActor->IPCOpen()) {
       mActor->SendRecycleTexture(mFlags);
     }
   }
 }
 
 void
 TextureClient::WaitForCompositorRecycle()
 {
@@ -498,17 +645,17 @@ TextureClient::InitIPDLActor(Compositabl
   if (!ToSurfaceDescriptor(desc)) {
     return false;
   }
 
   mActor = static_cast<TextureChild*>(aForwarder->CreateTexture(desc, aForwarder->GetCompositorBackendType(), GetFlags()));
   MOZ_ASSERT(mActor);
   mActor->mForwarder = aForwarder;
   mActor->mTextureClient = this;
-  mShared = true;
+  mActor->mMainThreadOnly = !!(mFlags & TextureFlags::DEALLOCATE_MAIN_THREAD);
   return mActor->IPCOpen();
 }
 
 PTextureChild*
 TextureClient::GetIPDLActor()
 {
   return mActor;
 }
@@ -543,94 +690,81 @@ TextureClient::CreateForDrawing(Composit
 
   if (!gfx::Factory::AllowedSurfaceSize(aSize)) {
     return nullptr;
   }
 
   LayersBackend parentBackend = aAllocator->GetCompositorBackendType();
   gfx::BackendType moz2DBackend = BackendTypeForBackendSelector(parentBackend, aSelector);
 
-  RefPtr<TextureClient> texture;
+  TextureData* data = nullptr;
 
 #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 &&
       aSize.height <= maxTextureSize)
   {
-    texture = CreateDXGITextureClient(aSize, aFormat, aTextureFlags, aAllocFlags, aAllocator);
-    if (texture) {
-      return texture.forget();
-    }
+    data = DXGITextureData::Create(aSize, aFormat, aAllocFlags);
   }
   if (parentBackend == LayersBackend::LAYERS_D3D9 &&
       moz2DBackend == gfx::BackendType::CAIRO &&
       aAllocator->IsSameProcess() &&
       aSize.width <= maxTextureSize &&
       aSize.height <= maxTextureSize &&
-      NS_IsMainThread()) {
-    if (gfxWindowsPlatform::GetPlatform()->GetD3D9Device()) {
-      TextureData* data = D3D9TextureData::Create(aSize, aFormat, aAllocFlags);
-      if (data) {
-        return MakeAndAddRef<TextureClient>(data, aTextureFlags, aAllocator);
-      }
-    }
+      NS_IsMainThread() &&
+      gfxWindowsPlatform::GetPlatform()->GetD3D9Device()) {
+    data = D3D9TextureData::Create(aSize, aFormat, aAllocFlags);
   }
 
-  if (!texture && aFormat == SurfaceFormat::B8G8R8X8 &&
+  if (!data && aFormat == SurfaceFormat::B8G8R8X8 &&
       aAllocator->IsSameProcess() &&
       moz2DBackend == gfx::BackendType::CAIRO &&
       NS_IsMainThread()) {
-    TextureData* data = DIBTextureData::Create(aSize, aFormat, aAllocator);
-    if (data) {
-      return MakeAndAddRef<TextureClient>(data, aTextureFlags, aAllocator);
-    }
+    data = DIBTextureData::Create(aSize, aFormat, aAllocator);
   }
 #endif
 
 #ifdef MOZ_X11
   gfxSurfaceType type =
     gfxPlatform::GetPlatform()->ScreenReferenceSurface()->GetType();
 
-  if (parentBackend == LayersBackend::LAYERS_BASIC &&
+  if (!data && parentBackend == LayersBackend::LAYERS_BASIC &&
       moz2DBackend == gfx::BackendType::CAIRO &&
       type == gfxSurfaceType::Xlib)
   {
-    texture = CreateX11TextureClient(aSize, aFormat, aTextureFlags, aAllocator);
-    if (texture) {
-      return texture.forget();
-    }
+    data = X11TextureData::Create(aSize, aFormat, aTextureFlags, aAllocator);
   }
 #ifdef GL_PROVIDER_GLX
-  if (parentBackend == LayersBackend::LAYERS_OPENGL &&
+  if (!data && parentBackend == LayersBackend::LAYERS_OPENGL &&
       type == gfxSurfaceType::Xlib &&
       aFormat != SurfaceFormat::A8 &&
       gl::sGLXLibrary.UseTextureFromPixmap())
   {
-    texture = CreateX11TextureClient(aSize, aFormat, aTextureFlags, aAllocator);
-    if (texture) {
-      return texture.forget();
-    }
+    data = X11TextureData::Create(aSize, aFormat, aTextureFlags, aAllocator);
   }
 #endif
 #endif
 
 #ifdef MOZ_WIDGET_GONK
-  texture = CreateGrallocTextureClientForDrawing(aSize, aFormat, moz2DBackend,
-                                                 aTextureFlags, aAllocator);
-  if (texture) {
-    return texture.forget();
+  if (!data) {
+    data = GrallocTextureData::CreateForDrawing(aSize, aFormat, moz2DBackend,
+                                                aAllocator);
   }
 #endif
 
+  if (data) {
+    return MakeAndAddRef<TextureClient>(data, aTextureFlags, aAllocator);
+  }
+
   // Can't do any better than a buffer texture client.
   return TextureClient::CreateForRawBufferAccess(aAllocator, aFormat, aSize,
                                                  moz2DBackend, aTextureFlags, aAllocFlags);
 }
 
 // static
 already_AddRefed<TextureClient>
 TextureClient::CreateForRawBufferAccess(ISurfaceAllocator* aAllocator,
@@ -640,16 +774,20 @@ TextureClient::CreateForRawBufferAccess(
                                         TextureFlags aTextureFlags,
                                         TextureAllocationFlags aAllocFlags)
 {
   MOZ_ASSERT(aAllocator->IPCOpen());
   if (!aAllocator || !aAllocator->IPCOpen()) {
     return nullptr;
   }
 
+  if (aAllocFlags & ALLOC_DISALLOW_BUFFERTEXTURECLIENT) {
+    return nullptr;
+  }
+
   if (!gfx::Factory::AllowedSurfaceSize(aSize)) {
     return nullptr;
   }
 
   TextureData* texData = BufferTextureData::Create(aSize, aFormat, aMoz2DBackend,
                                                    aTextureFlags, aAllocFlags,
                                                    aAllocator);
   if (!texData) {
@@ -712,49 +850,23 @@ TextureClient::TextureClient(TextureData
 , mActor(nullptr)
 , mData(aData)
 , mFlags(aFlags)
 , mOpenMode(OpenMode::OPEN_NONE)
 #ifdef DEBUG
 , mExpectedDtRefs(0)
 #endif
 , mIsLocked(false)
-, mShared(false)
-, mValid(true)
 , mAddedToCompositableClient(false)
+, mWorkaroundAnnoyingSharedSurfaceLifetimeIssues(false)
 #ifdef GFX_DEBUG_TRACK_CLIENTS_IN_POOL
 , mPoolTracker(nullptr)
 #endif
-{}
-
-void
-TextureClient::KeepUntilFullDeallocation(UniquePtr<KeepAlive> aKeep, bool aMainThreadOnly)
 {
-  MOZ_ASSERT(mActor);
-  MOZ_ASSERT(!mActor->mKeep);
-  mActor->mKeep = Move(aKeep);
-  mActor->mMainThreadOnly = aMainThreadOnly;
-}
-
-void TextureClient::ForceRemove(bool sync)
-{
-  if (mActor && mActor->mDestroyed) {
-    mActor = nullptr;
-  }
-  if (mValid && mActor) {
-    FinalizeOnIPDLThread();
-    if (mActor->CanSend()) {
-      if (sync || GetFlags() & TextureFlags::DEALLOCATE_CLIENT) {
-        mActor->DestroySynchronously();
-      } else {
-        mActor->Destroy();
-      }
-    }
-  }
-  MarkInvalid();
+  mFlags |= mData->GetTextureFlags();
 }
 
 bool TextureClient::CopyToTextureClient(TextureClient* aTarget,
                                         const gfx::IntRect* aRect,
                                         const gfx::IntPoint* aPoint)
 {
   MOZ_ASSERT(IsLocked());
   MOZ_ASSERT(aTarget->IsLocked());
@@ -778,55 +890,16 @@ bool TextureClient::CopyToTextureClient(
   RefPtr<gfx::SourceSurface> source = sourceTarget->Snapshot();
   destinationTarget->CopySurface(source,
                                  aRect ? *aRect : gfx::IntRect(gfx::IntPoint(0, 0), GetSize()),
                                  aPoint ? *aPoint : gfx::IntPoint(0, 0));
   return true;
 }
 
 void
-TextureClient::Finalize()
-{
-  MOZ_ASSERT(!IsLocked());
-
-  // Always make a temporary strong reference to the actor before we use it,
-  // in case TextureChild::ActorDestroy might null mActor concurrently.
-  RefPtr<TextureChild> actor = mActor;
-
-  if (actor) {
-    if (actor->mDestroyed) {
-      actor = nullptr;
-      return;
-    }
-    // The actor has a raw pointer to us, actor->mTextureClient.
-    // Null it before RemoveTexture calls to avoid invalid actor->mTextureClient
-    // when calling TextureChild::ActorDestroy()
-    actor->SetTextureClient(nullptr);
-
-    // `actor->mWaitForRecycle` may not be null, as we may be being called from setting
-    // this RefPtr to null! Clearing it here will double-Release() it.
-
-    // this will call ForceRemove in the right thread, using a sync proxy if needed
-    if (actor->GetForwarder()) {
-      actor->GetForwarder()->RemoveTexture(this);
-    }
-  }
-}
-
-bool
-TextureClient::ShouldDeallocateInDestructor() const
-{
-  // 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;
--- a/gfx/layers/client/TextureClient.h
+++ b/gfx/layers/client/TextureClient.h
@@ -209,18 +209,17 @@ public:
   virtual bool ReadBack(TextureReadbackSink* aReadbackSink) { 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) {};
 
   virtual void SyncWithObject(SyncObject* aFence) {};
 
-  /// Needed until the destruction sequence of TextureClient is revamped.
-  virtual void FinalizeOnIPDLThread(TextureClient*) {}
+  virtual TextureFlags GetTextureFlags() const { return TextureFlags::NO_FLAGS; }
 };
 
 /**
  * TextureClient is a thin abstraction over texture data that need to be shared
  * between the content process and the compositor process. It is the
  * content-side half of a TextureClient/TextureHost pair. A corresponding
  * TextureHost lives on the compositor-side.
  *
@@ -378,17 +377,17 @@ public:
   /**
    * Returns true if this texture has a synchronization mechanism (mutex, fence, etc.).
    * Textures that do not implement synchronization should be immutable or should
    * use immediate uploads (see TextureFlags in CompositorTypes.h)
    * Even if a texture does not implement synchronization, Lock and Unlock need
    * to be used appropriately since the latter are also there to map/numap data.
    */
   bool HasSynchronization() const { return false; }
- 
+
   /**
    * Indicates whether the TextureClient implementation is backed by an
    * in-memory buffer. The consequence of this is that locking the
    * TextureClient does not contend with locking the texture on the host side.
    */
   bool HasInternalBuffer() const;
 
   /**
@@ -443,46 +442,34 @@ public:
    * textures.
    */
   bool IsImmutable() const { return !!(mFlags & TextureFlags::IMMUTABLE); }
 
   void MarkImmutable() { AddFlags(TextureFlags::IMMUTABLE); }
 
   bool IsSharedWithCompositor() const;
 
-  bool ShouldDeallocateInDestructor() const;
-
   /**
    * If this method returns false users of TextureClient are not allowed
    * to access the shared data.
    */
-  bool IsValid() const { return mValid; }
+  bool IsValid() const { return !!mData; }
 
   /**
    * Called when TextureClient is added to CompositableClient.
    */
   void SetAddedToCompositableClient();
 
   /**
    * If this method retuns false, TextureClient is already added to CompositableClient,
    * since its creation or recycling.
    */
   bool IsAddedToCompositableClient() const { return mAddedToCompositableClient; }
 
   /**
-   * kee the passed object alive until the IPDL actor is destroyed. This can
-   * help avoid race conditions in some cases.
-   * It's a temporary hack to ensure that DXGI textures don't get destroyed
-   * between serialization and deserialization.
-   *
-   * This must not be called off the texture's IPDL thread.
-   */
-  void KeepUntilFullDeallocation(UniquePtr<KeepAlive> aKeep, bool aMainThreadOnly = false);
-
-  /**
    * Create and init the TextureChild/Parent IPDL actor pair.
    *
    * Should be called only once per TextureClient.
    */
   bool InitIPDLActor(CompositableForwarder* aForwarder);
 
   /**
    * Return a pointer to the IPDLActor.
@@ -496,17 +483,17 @@ public:
    * Triggers the destruction of the shared data and the corresponding TextureHost.
    *
    * If the texture flags contain TextureFlags::DEALLOCATE_CLIENT, the destruction
    * will be synchronously coordinated with the compositor side, otherwise it
    * will be done asynchronously.
    * If sync is true, the destruction will be synchronous regardless of the
    * texture's flags (bad for performance, use with care).
    */
-  void ForceRemove(bool sync = false);
+  void Destroy(bool sync = false);
 
   virtual void SetReleaseFenceHandle(const FenceHandle& aReleaseFenceHandle)
   {
     mReleaseFenceHandle.Merge(aReleaseFenceHandle);
   }
 
   virtual FenceHandle GetAndResetReleaseFenceHandle()
   {
@@ -527,16 +514,19 @@ public:
 
   /**
    * Set AsyncTransactionTracker of RemoveTextureFromCompositableAsync() transaction.
    */
   virtual void SetRemoveFromCompositableWaiter(AsyncTransactionWaiter* aWaiter);
 
   /**
    * This function waits until the buffer is no longer being used.
+   *
+   * XXX - Ideally we shouldn't need this method because Lock the right
+   * thing already.
    */
   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) {
@@ -549,18 +539,16 @@ public:
    * texture unlock.
    */
   virtual void SetReadbackSink(TextureReadbackSink* aReadbackSink) {
     mReadbackSink = aReadbackSink;
   }
 
   void SyncWithObject(SyncObject* aFence) { mData->SyncWithObject(aFence); }
 
-  void MarkShared() { mShared = true; }
-
   ISurfaceAllocator* GetAllocator() { return mAllocator; }
 
    TextureClientRecycleAllocator* GetRecycleAllocator() { return mRecycleAllocator; }
    void SetRecycleAllocator(TextureClientRecycleAllocator* aAllocator);
 
   /// If you add new code that uses this method, you are probably doing something wrong.
   TextureData* GetInternalData() { return mData; }
   const TextureData* GetInternalData() const { return mData; }
@@ -570,34 +558,22 @@ private:
 
   /**
    * 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.
    * Must only be called by Release().
    */
-  B2G_ACL_EXPORT void Finalize();
-
-  /**
-   * 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).
-   */
-  void FinalizeOnIPDLThread();
+  B2G_ACL_EXPORT void Finalize() {}
 
   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; }
-
-  /**
    * Should only be called *once* per texture, in TextureClient::InitIPDLActor.
    * Some texture implementations rely on the fact that the descriptor will be
    * deserialized.
    * Calling ToSurfaceDescriptor again after it has already returned true,
    * or never constructing a TextureHost with aDescriptor may result in a memory
    * leak (see TextureClientD3D9 for example).
    */
   bool ToSurfaceDescriptor(SurfaceDescriptor& aDescriptor);
@@ -615,19 +591,18 @@ protected:
   FenceHandle mReleaseFenceHandle;
   FenceHandle mAcquireFenceHandle;
   gl::GfxTextureWasteTracker mWasteTracker;
 
   OpenMode mOpenMode;
   DebugOnly<uint32_t> mExpectedDtRefs;
   bool mIsLocked;
 
-  bool mShared;
-  bool mValid;
   bool mAddedToCompositableClient;
+  bool mWorkaroundAnnoyingSharedSurfaceLifetimeIssues;
 
   RefPtr<TextureReadbackSink> mReadbackSink;
 
   friend class TextureChild;
   friend class RemoveTextureFromCompositableTracker;
   friend void TestTextureClientSurface(TextureClient*, gfxImageSurface*);
   friend void TestTextureClientYCbCr(TextureClient*, PlanarYCbCrData&);
 
--- a/gfx/layers/client/TextureClientSharedSurface.cpp
+++ b/gfx/layers/client/TextureClientSharedSurface.cpp
@@ -47,17 +47,19 @@ SharedSurfaceTextureData::Serialize(Surf
   return mSurf->ToSurfaceDescriptor(&aOutDescriptor);
 }
 
 
 SharedSurfaceTextureClient::SharedSurfaceTextureClient(SharedSurfaceTextureData* aData,
                                                        TextureFlags aFlags,
                                                        ISurfaceAllocator* aAllocator)
 : TextureClient(aData, aFlags, aAllocator)
-{}
+{
+  mWorkaroundAnnoyingSharedSurfaceLifetimeIssues = true;
+}
 
 already_AddRefed<SharedSurfaceTextureClient>
 SharedSurfaceTextureClient::Create(UniquePtr<gl::SharedSurface> surf, gl::SurfaceFactory* factory,
                                    ISurfaceAllocator* aAllocator, TextureFlags aFlags)
 {
   if (!surf) {
     return nullptr;
   }
@@ -122,10 +124,34 @@ SharedSurfaceTextureClient::GetAcquireFe
   }
   if (surf && surf->GetTextureClient()) {
     return surf->GetTextureClient()->GetAcquireFenceHandle();
   }
 #endif
   return TextureClient::GetAcquireFenceHandle();
 }
 
+SharedSurfaceTextureClient::~SharedSurfaceTextureClient()
+{
+  // XXX - Things break when using the proper destruction handshake with
+  // SharedSurfaceTextureData because the TextureData outlives its gl
+  // context. Having a strong reference to the gl context creates a cycle.
+  // This needs to be fixed in a better way, though, because deleting
+  // the TextureData here can race with the compositor and cause flashing.
+  TextureData* data = mData;
+  mData = nullptr;
+
+  Destroy();
+
+  if (data) {
+    // Destroy mData right away without doing the proper deallocation handshake,
+    // because SharedSurface depends on things that may not outlive the texture's
+    // destructor so we can't wait until we know the compositor isn't using the
+    // texture anymore.
+    // It goes without saying that this is really bad and we should fix the bugs
+    // that block doing the right thing such as bug 1224199 sooner rather than
+    // later.
+    delete data;
+  }
+}
+
 } // namespace layers
 } // namespace mozilla
--- a/gfx/layers/client/TextureClientSharedSurface.h
+++ b/gfx/layers/client/TextureClientSharedSurface.h
@@ -61,16 +61,18 @@ public:
 
 class SharedSurfaceTextureClient : public TextureClient
 {
 public:
   SharedSurfaceTextureClient(SharedSurfaceTextureData* aData,
                              TextureFlags aFlags,
                              ISurfaceAllocator* aAllocator);
 
+  ~SharedSurfaceTextureClient();
+
   static already_AddRefed<SharedSurfaceTextureClient>
   Create(UniquePtr<gl::SharedSurface> surf, gl::SurfaceFactory* factory,
          ISurfaceAllocator* aAllocator, TextureFlags aFlags);
 
   virtual void SetReleaseFenceHandle(const FenceHandle& aReleaseFenceHandle) override;
 
   virtual FenceHandle GetAndResetReleaseFenceHandle() override;
 
--- a/gfx/layers/d3d11/TextureD3D11.cpp
+++ b/gfx/layers/d3d11/TextureD3D11.cpp
@@ -428,29 +428,16 @@ DXGITextureData::Create(IntSize aSize, S
 
   if (haveD3d11Backend) {
     return D3D11TextureData::Create(aSize, aFormat, aFlags);
   } else {
     return D3D10TextureData::Create(aSize, aFormat, aFlags);
   }
 }
 
-already_AddRefed<TextureClient>
-CreateDXGITextureClient(IntSize aSize, SurfaceFormat aFormat,
-                        TextureFlags aTextureFlags, TextureAllocationFlags aAllocFlags,
-                        ISurfaceAllocator* aAllocator)
-{
-  TextureData* data = DXGITextureData::Create(aSize, aFormat, aAllocFlags);
-  if (!data) {
-    return nullptr;
-  }
-  return MakeAndAddRef<TextureClient>(data, aTextureFlags, aAllocator);
-}
-
-
 DXGITextureData*
 D3D11TextureData::Create(IntSize aSize, SurfaceFormat aFormat, TextureAllocationFlags aFlags,
                          ID3D11Device* aDevice)
 {
   RefPtr<ID3D11Texture2D> texture11;
   ID3D11Device* d3d11device = aDevice ? aDevice
                             : gfxWindowsPlatform::GetPlatform()->GetD3D11DeviceForCurrentThread();
   MOZ_ASSERT(d3d11device != nullptr);
@@ -649,36 +636,16 @@ DXGIYCbCrTextureData::Serialize(SurfaceD
 {
   aOutDescriptor = SurfaceDescriptorDXGIYCbCr(
     (WindowsHandle)mHandles[0], (WindowsHandle)mHandles[1], (WindowsHandle)mHandles[2],
     GetSize(), mSizeY, mSizeCbCr
   );
   return true;
 }
 
-class YCbCrKeepAliveD3D11 : public KeepAlive
-{
-public:
-  YCbCrKeepAliveD3D11(RefPtr<IUnknown> aTextures[3])
-  {
-    mTextures[0] = aTextures[0];
-    mTextures[1] = aTextures[1];
-    mTextures[2] = aTextures[2];
-  }
-
-protected:
-  RefPtr<IUnknown> mTextures[3];
-};
-
-void
-DXGIYCbCrTextureData::FinalizeOnIPDLThread(TextureClient* aWrapper)
-{
-  aWrapper->KeepUntilFullDeallocation(MakeUnique<YCbCrKeepAliveD3D11>(mHoldRefs));
-}
-
 void
 DXGIYCbCrTextureData::Deallocate(ISurfaceAllocator*)
 {
   mHoldRefs[0] = nullptr;
   mHoldRefs[1] = nullptr;
   mHoldRefs[2] = nullptr;
 }
 
@@ -807,28 +774,16 @@ D3D10TextureData::UpdateFromSurface(gfx:
 
   device->UpdateSubresource(mTexture, 0, &box, sourceMap.mData, sourceMap.mStride, 0);
 
   srcSurf->Unmap();
 
   return true;
 }
 
-void
-D3D11TextureData::FinalizeOnIPDLThread(TextureClient* aWrapper)
-{
-  aWrapper->KeepUntilFullDeallocation(MakeUnique<TKeepAlive<ID3D11Texture2D>>(mTexture));
-}
-
-void
-D3D10TextureData::FinalizeOnIPDLThread(TextureClient* aWrapper)
-{
-  aWrapper->KeepUntilFullDeallocation(MakeUnique<TKeepAlive<ID3D10Texture2D>>(mTexture));
-}
-
 DXGITextureHostD3D11::DXGITextureHostD3D11(TextureFlags aFlags,
                                            const SurfaceDescriptorD3D10& aDescriptor)
   : TextureHost(aFlags)
   , mSize(aDescriptor.size())
   , mHandle(aDescriptor.handle())
   , mFormat(aDescriptor.format())
   , mIsLocked(false)
 {
--- a/gfx/layers/d3d11/TextureD3D11.h
+++ b/gfx/layers/d3d11/TextureD3D11.h
@@ -50,21 +50,16 @@ protected:
   RefPtr<gfx::DrawTarget> mDrawTarget;
   gfx::IntSize mSize;
   gfx::SurfaceFormat mFormat;
   bool mNeedsClear;
   bool mNeedsClearWhite;
   bool mHasSynchronization;
 };
 
-already_AddRefed<TextureClient>
-CreateDXGITextureClient(gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
-                        TextureFlags atextureFlags, TextureAllocationFlags aFlags,
-                        ISurfaceAllocator* aAllocator);
-
 class D3D11TextureData : public DXGITextureData
 {
 public:
   // If aDevice is null, use one provided by gfxWindowsPlatform.
   static DXGITextureData*
   Create(gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
          TextureAllocationFlags aAllocFlags,
          ID3D11Device* aDevice = nullptr);
@@ -90,18 +85,16 @@ public:
   virtual void Deallocate(ISurfaceAllocator* aAllocator) override;
 
   ~D3D11TextureData();
 protected:
   D3D11TextureData(ID3D11Texture2D* aTexture,
                    gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
                    bool aNeedsClear, bool aNeedsClearWhite);
 
-  virtual void FinalizeOnIPDLThread(TextureClient* aWrapper) override;
-
   virtual void GetDXGIResource(IDXGIResource** aOutResource) override;
 
   RefPtr<ID3D11Texture2D> mTexture;
 };
 
 already_AddRefed<TextureClient>
 CreateD3D11extureClientWithDevice(gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
                                   TextureFlags aTextureFlags, TextureAllocationFlags aAllocFlags,
@@ -136,18 +129,16 @@ public:
   virtual void Deallocate(ISurfaceAllocator* aAllocator) override;
 
   ~D3D10TextureData();
 protected:
   D3D10TextureData(ID3D10Texture2D* aTexture,
                    gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
                    bool aNeedsClear, bool aNeedsClearWhite);
 
-  virtual void FinalizeOnIPDLThread(TextureClient*) override;
-
   virtual void GetDXGIResource(IDXGIResource** aOutResource) override;
 
   RefPtr<ID3D10Texture2D> mTexture;
 };
 
 class DXGIYCbCrTextureData : public TextureData
 {
 public:
@@ -196,19 +187,22 @@ public:
   // an external producer.
   virtual DXGIYCbCrTextureData*
   CreateSimilar(ISurfaceAllocator*, TextureFlags, TextureAllocationFlags) const override { return nullptr; }
 
   virtual void Deallocate(ISurfaceAllocator* aAllocator) override;
 
   virtual bool UpdateFromSurface(gfx::SourceSurface*) override { return false; }
 
+  virtual TextureFlags GetTextureFlags() const override
+  {
+    return TextureFlags::DEALLOCATE_MAIN_THREAD;
+  }
+
 protected:
-  virtual void FinalizeOnIPDLThread(TextureClient*) override;
-
    RefPtr<IUnknown> mHoldRefs[3];
    HANDLE mHandles[3];
    gfx::IntSize mSize;
    gfx::IntSize mSizeY;
    gfx::IntSize mSizeCbCr;
 };
 
 /**
@@ -416,19 +410,19 @@ private:
 
   RefPtr<ID3D11RenderTargetView> mRTView;
 };
 
 class SyncObjectD3D11 : public SyncObject
 {
 public:
   SyncObjectD3D11(SyncHandle aSyncHandle);
+  virtual void FinalizeFrame();
 
   virtual SyncType GetSyncType() { return SyncType::D3D11; }
-  virtual void FinalizeFrame();
 
   void RegisterTexture(ID3D11Texture2D* aTexture);
   void RegisterTexture(ID3D10Texture2D* aTexture);
 
 private:
   RefPtr<ID3D11Texture2D> mD3D11Texture;
   RefPtr<ID3D10Texture2D> mD3D10Texture;
   std::vector<ID3D10Texture2D*> mD3D10SyncedTextures;
--- a/gfx/layers/d3d9/TextureD3D9.cpp
+++ b/gfx/layers/d3d9/TextureD3D9.cpp
@@ -482,24 +482,16 @@ D3D9TextureData::Create(gfx::IntSize aSi
 }
 
 TextureData*
 D3D9TextureData::CreateSimilar(ISurfaceAllocator*, TextureFlags aFlags, TextureAllocationFlags aAllocFlags) const
 {
   return D3D9TextureData::Create(mSize, mFormat, aAllocFlags);
 }
 
-void
-D3D9TextureData::FinalizeOnIPDLThread(TextureClient* aWrapper)
-{
-  if (mTexture) {
-    aWrapper->KeepUntilFullDeallocation(MakeUnique<TKeepAlive<IDirect3DTexture9>>(mTexture));
-  }
-}
-
 bool
 D3D9TextureData::Lock(OpenMode aMode, FenceHandle*)
 {
   if (!gfxWindowsPlatform::GetPlatform()->GetD3D9Device()) {
     // If the device has failed then we should not lock the surface,
     // even if we could.
     mD3D9Surface = nullptr;
     return false;
--- a/gfx/layers/d3d9/TextureD3D9.h
+++ b/gfx/layers/d3d9/TextureD3D9.h
@@ -204,18 +204,16 @@ public:
                 TextureAllocationFlags aAllocFlags) const override;
 
   static D3D9TextureData*
   Create(gfx::IntSize aSize, gfx::SurfaceFormat aFormat, TextureAllocationFlags aFlags);
 
   virtual void Deallocate(ISurfaceAllocator* aAllocator) {}
 
 protected:
-  virtual void FinalizeOnIPDLThread(TextureClient* aWrapper) override;
-
   D3D9TextureData(gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
                   IDirect3DTexture9* aTexture);
 
   RefPtr<IDirect3DTexture9> mTexture;
   RefPtr<IDirect3DSurface9> mD3D9Surface;
   gfx::IntSize mSize;
   gfx::SurfaceFormat mFormat;
   bool mNeedsClear;
--- a/gfx/layers/ipc/CompositableForwarder.h
+++ b/gfx/layers/ipc/CompositableForwarder.h
@@ -103,22 +103,16 @@ public:
    * It is used when the TextureClient recycled.
    * Only ImageBridge implements it.
    */
   virtual void RemoveTextureFromCompositableAsync(AsyncTransactionTracker* aAsyncTransactionTracker,
                                                   CompositableClient* aCompositable,
                                                   TextureClient* aTexture) {}
 
   /**
-   * Tell the compositor side to delete the TextureHost corresponding to the
-   * TextureClient passed in parameter.
-   */
-  virtual void RemoveTexture(TextureClient* aTexture) = 0;
-
-  /**
    * Holds a reference to a TextureClient until after the next
    * compositor transaction, and then drops it.
    */
   virtual void HoldUntilTransaction(TextureClient* aClient)
   {
     if (aClient) {
       mTexturesToRemove.AppendElement(aClient);
     }
--- a/gfx/layers/ipc/ImageBridgeChild.cpp
+++ b/gfx/layers/ipc/ImageBridgeChild.cpp
@@ -193,17 +193,17 @@ static void ImageBridgeShutdownStep1(Ree
     for (int i = compositables.Length() - 1; i >= 0; --i) {
       CompositableClient::FromIPDLActor(compositables[i])->Destroy();
     }
     InfallibleTArray<PTextureChild*> textures;
     sImageBridgeChildSingleton->ManagedPTextureChild(textures);
     for (int i = textures.Length() - 1; i >= 0; --i) {
       RefPtr<TextureClient> client = TextureClient::AsTextureClient(textures[i]);
       if (client) {
-        client->ForceRemove();
+        client->Destroy();
       }
     }
     sImageBridgeChildSingleton->SendWillStop();
     sImageBridgeChildSingleton->MarkShutDown();
     // From now on, no message can be sent through the image bridge from the
     // client side except the final Stop message.
   }
 
@@ -761,17 +761,17 @@ bool ImageBridgeChild::StartUpOnThread(T
 bool InImageBridgeChildThread()
 {
   return ImageBridgeChild::IsCreated() &&
     sImageBridgeChildThread->thread_id() == PlatformThread::CurrentId();
 }
 
 MessageLoop * ImageBridgeChild::GetMessageLoop() const
 {
-  return sImageBridgeChildThread->message_loop();
+  return sImageBridgeChildThread ? sImageBridgeChildThread->message_loop() : nullptr;
 }
 
 void ImageBridgeChild::ConnectAsync(ImageBridgeParent* aParent)
 {
   GetMessageLoop()->PostTask(FROM_HERE, NewRunnableFunction(&ConnectImageBridge,
                                                             this, aParent));
 }
 
@@ -1125,48 +1125,16 @@ ImageBridgeChild::RemoveTextureFromCompo
                                            aAsyncTransactionTracker->GetId(),
                                            nullptr, aCompositable->GetIPDLActor(),
                                            nullptr, aTexture->GetIPDLActor()));
   // Hold AsyncTransactionTracker until receving reply
   CompositableClient::HoldUntilComplete(aCompositable->GetIPDLActor(),
                                         aAsyncTransactionTracker);
 }
 
-static void RemoveTextureSync(TextureClient* aTexture, ReentrantMonitor* aBarrier, bool* aDone)
-{
-  aTexture->ForceRemove();
-
-  ReentrantMonitorAutoEnter autoMon(*aBarrier);
-  *aDone = true;
-  aBarrier->NotifyAll();
-}
-
-void ImageBridgeChild::RemoveTexture(TextureClient* aTexture)
-{
-  if (InImageBridgeChildThread()) {
-    MOZ_ASSERT(!mShuttingDown);
-    aTexture->ForceRemove();
-    return;
-  }
-
-  ReentrantMonitor barrier("RemoveTexture Lock");
-  ReentrantMonitorAutoEnter autoMon(barrier);
-  bool done = false;
-
-  sImageBridgeChildSingleton->GetMessageLoop()->PostTask(
-    FROM_HERE,
-    NewRunnableFunction(&RemoveTextureSync, aTexture, &barrier, &done));
-
-  // should stop the thread until the ImageClient has been created on
-  // the other thread
-  while (!done) {
-    barrier.Wait();
-  }
-}
-
 bool ImageBridgeChild::IsSameProcess() const
 {
   return OtherPid() == base::GetCurrentProcId();
 }
 
 void ImageBridgeChild::SendPendingAsyncMessges()
 {
 }
--- a/gfx/layers/ipc/ImageBridgeChild.h
+++ b/gfx/layers/ipc/ImageBridgeChild.h
@@ -254,18 +254,16 @@ public:
 
   virtual void RemoveTextureFromCompositable(CompositableClient* aCompositable,
                                              TextureClient* aTexture) override;
 
   virtual void RemoveTextureFromCompositableAsync(AsyncTransactionTracker* aAsyncTransactionTracker,
                                                   CompositableClient* aCompositable,
                                                   TextureClient* aTexture) override;
 
-  virtual void RemoveTexture(TextureClient* aTexture) override;
-
   virtual void UseTiledLayerBuffer(CompositableClient* aCompositable,
                                    const SurfaceDescriptorTiles& aTileLayerDescriptor) override
   {
     NS_RUNTIMEABORT("should not be called");
   }
 
   virtual void UpdateTextureRegion(CompositableClient* aCompositable,
                                    const ThebesBufferData& aThebesBufferData,
--- a/gfx/layers/ipc/LayerTransactionChild.cpp
+++ b/gfx/layers/ipc/LayerTransactionChild.cpp
@@ -35,17 +35,17 @@ LayerTransactionChild::Destroy()
   mDestroyed = true;
   MOZ_ASSERT(0 == ManagedPLayerChild().Count(),
              "layers should have been cleaned up by now");
 
   const ManagedContainer<PTextureChild>& textures = ManagedPTextureChild();
   for (auto iter = textures.ConstIter(); !iter.Done(); iter.Next()) {
     TextureClient* texture = TextureClient::AsTextureClient(iter.Get()->GetKey());
     if (texture) {
-      texture->ForceRemove();
+      texture->Destroy();
     }
   }
 
   SendShutdown();
 }
 
 
 PLayerChild*
--- a/gfx/layers/ipc/ShadowLayers.cpp
+++ b/gfx/layers/ipc/ShadowLayers.cpp
@@ -465,48 +465,16 @@ ShadowLayerForwarder::RemoveTextureFromC
 }
 
 bool
 ShadowLayerForwarder::InWorkerThread()
 {
   return MessageLoop::current() && (GetMessageLoop()->id() == MessageLoop::current()->id());
 }
 
-static void RemoveTextureWorker(TextureClient* aTexture, ReentrantMonitor* aBarrier, bool* aDone)
-{
-  aTexture->ForceRemove();
-
-  ReentrantMonitorAutoEnter autoMon(*aBarrier);
-  *aDone = true;
-  aBarrier->NotifyAll();
-}
-
-void
-ShadowLayerForwarder::RemoveTexture(TextureClient* aTexture)
-{
-  MOZ_ASSERT(aTexture);
-  if (InWorkerThread()) {
-    aTexture->ForceRemove();
-    return;
-  }
-
-  ReentrantMonitor barrier("ShadowLayerForwarder::RemoveTexture Lock");
-  ReentrantMonitorAutoEnter autoMon(barrier);
-  bool done = false;
-
-  GetMessageLoop()->PostTask(
-    FROM_HERE,
-    NewRunnableFunction(&RemoveTextureWorker, aTexture, &barrier, &done));
-
-  // Wait until the TextureClient has been ForceRemoved on the worker thread
-  while (!done) {
-    barrier.Wait();
-  }
-}
-
 void
 ShadowLayerForwarder::StorePluginWidgetConfigurations(const nsTArray<nsIWidget::Configuration>&
                                                       aConfigurations)
 {
   // Cache new plugin widget configs here until we call update, at which
   // point this data will get shipped over to chrome.
   mPluginWindowData.Clear();
   for (uint32_t idx = 0; idx < aConfigurations.Length(); idx++) {
--- a/gfx/layers/ipc/ShadowLayers.h
+++ b/gfx/layers/ipc/ShadowLayers.h
@@ -216,18 +216,16 @@ public:
 
   virtual void RemoveTextureFromCompositable(CompositableClient* aCompositable,
                                              TextureClient* aTexture) override;
 
   virtual void RemoveTextureFromCompositableAsync(AsyncTransactionTracker* aAsyncTransactionTracker,
                                                   CompositableClient* aCompositable,
                                                   TextureClient* aTexture) override;
 
-  virtual void RemoveTexture(TextureClient* aTexture) override;
-
   /**
    * Communicate to the compositor that aRegion in the texture identified by aLayer
    * and aIdentifier has been updated to aThebesBuffer.
    */
   virtual void UpdateTextureRegion(CompositableClient* aCompositable,
                                    const ThebesBufferData& aThebesBufferData,
                                    const nsIntRegion& aUpdatedRegion) override;
 
--- a/gfx/layers/opengl/GrallocTextureClient.cpp
+++ b/gfx/layers/opengl/GrallocTextureClient.cpp
@@ -113,41 +113,49 @@ GrallocTextureData::GrallocTextureData(M
 GrallocTextureData::~GrallocTextureData()
 {
   MOZ_COUNT_DTOR(GrallocTextureData);
 }
 
 void
 GrallocTextureData::Deallocate(ISurfaceAllocator* aAllocator)
 {
-  aAllocator->DeallocGrallocBuffer(&mGrallocHandle);
+  MOZ_ASSERT(aAllocator);
+  if (aAllocator) {
+    aAllocator->DeallocGrallocBuffer(&mGrallocHandle);
+  }
+
   mGrallocHandle = null_t();
   mGraphicBuffer = nullptr;
 }
 
 void
 GrallocTextureData::Forget(ISurfaceAllocator* aAllocator)
 {
-  aAllocator->DropGrallocBuffer(&mGrallocHandle);
+  MOZ_ASSERT(aAllocator);
+  if (aAllocator) {
+    aAllocator->DropGrallocBuffer(&mGrallocHandle);
+  }
+
   mGrallocHandle = null_t();
   mGraphicBuffer = nullptr;
 }
 
 bool
 GrallocTextureData::Serialize(SurfaceDescriptor& aOutDescriptor)
 {
   aOutDescriptor = NewSurfaceDescriptorGralloc(mGrallocHandle, gfx::IsOpaque(mFormat));
   return true;
 }
 
 void
 GrallocTextureData::WaitForFence(FenceHandle* aFence)
 {
 #if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION < 21 && ANDROID_VERSION >= 17
-   if (aFence->IsValid()) {
+   if (aFence && 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");
@@ -156,39 +164,47 @@ GrallocTextureData::WaitForFence(FenceHa
 #endif
 }
 
 bool
 GrallocTextureData::Lock(OpenMode aMode, FenceHandle* aReleaseFence)
 {
   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;
   }
+
+  void** mappedBufferPtr = reinterpret_cast<void**>(&mMappedBuffer);
+
+  int32_t rv = 0;
 #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());
+  if (aReleaseFence) {
+    RefPtr<FenceHandle::FdObj> fdObj = aReleaseFence->GetAndResetFdObj();
+    rv = mGraphicBuffer->lockAsync(usage, mappedBufferPtr,
+                                   fdObj->GetAndResetFd());
+  } else {
+    rv = mGraphicBuffer->lock(usage, mappedBufferPtr);
+  }
 #else
-  int32_t rv = mGraphicBuffer->lock(usage,
-                                    reinterpret_cast<void**>(&mMappedBuffer));
+  // older versions of android don't have lockAsync
+  WaitForFence(aReleaseFence);
+  rv = mGraphicBuffer->lock(usage, mappedBufferPtr);
 #endif
+
   if (rv) {
     mMappedBuffer = nullptr;
     NS_WARNING("Couldn't lock graphic buffer");
     return false;
   }
+
   return true;
 }
 
 void
 GrallocTextureData::Unlock()
 {
   MOZ_ASSERT(mMappedBuffer);
   mMappedBuffer = nullptr;
@@ -266,16 +282,19 @@ GrallocTextureData::UpdateFromSurface(gf
 }
 
 // static
 GrallocTextureData*
 GrallocTextureData::Create(gfx::IntSize aSize, AndroidFormat aAndroidFormat,
                            gfx::BackendType aMoz2dBackend, uint32_t aUsage,
                            ISurfaceAllocator* aAllocator)
 {
+  if (!aAllocator) {
+    return nullptr;
+  }
   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;
@@ -341,33 +360,26 @@ GrallocTextureData::CreateForDrawing(gfx
   // 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;
 }
 
-already_AddRefed<TextureClient>
-CreateGrallocTextureClientForDrawing(gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
-                                     gfx::BackendType aMoz2dBackend,
-                                     TextureFlags aFlags,
-                                     ISurfaceAllocator* aAllocator)
+TextureFlags
+GrallocTextureData::GetTextureFlags() const
 {
-  TextureData* data = GrallocTextureData::CreateForDrawing(aSize, aFormat, aMoz2dBackend,
-                                                           aAllocator);
-  if (!data) {
-    return nullptr;
+  if (IsGrallocRBSwapped(mFormat)) {
+    return TextureFlags::RB_SWAPPED;
   }
-  if (IsGrallocRBSwapped(aFormat)) {
-    aFlags |= TextureFlags::RB_SWAPPED;
-  }
-  return MakeAndAddRef<TextureClient>(data, aFlags, aAllocator);
+  return TextureFlags::NO_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,
--- a/gfx/layers/opengl/GrallocTextureClient.h
+++ b/gfx/layers/opengl/GrallocTextureClient.h
@@ -102,16 +102,18 @@ public:
   android::MediaBuffer* GetMediaBuffer() { return mMediaBuffer; }
 
   android::sp<android::GraphicBuffer> GetGraphicBuffer() { return mGraphicBuffer; }
 
   virtual void WaitForFence(FenceHandle* aFence) override;
 
   ~GrallocTextureData();
 
+  virtual TextureFlags GetTextureFlags() const override;
+
 protected:
   GrallocTextureData(MaybeMagicGrallocBufferHandle aGrallocHandle,
                      gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
                      gfx::BackendType aMoz2DBackend);
 
   gfx::IntSize mSize;
   gfx::SurfaceFormat mFormat;
   gfx::BackendType mMoz2DBackend;
@@ -123,17 +125,13 @@ protected:
   // Should be null outside of the lock-unlock pair.
   uint8_t* mMappedBuffer;
 
   android::MediaBuffer* mMediaBuffer;
 };
 
 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/gfx/layers/opengl/MacIOSurfaceTextureClientOGL.cpp
+++ b/gfx/layers/opengl/MacIOSurfaceTextureClientOGL.cpp
@@ -13,24 +13,16 @@ MacIOSurfaceTextureData::MacIOSurfaceTex
 : mSurface(aSurface)
 {
   MOZ_ASSERT(mSurface);
 }
 
 MacIOSurfaceTextureData::~MacIOSurfaceTextureData()
 {}
 
-void
-MacIOSurfaceTextureData::FinalizeOnIPDLThread(TextureClient* aWrapper)
-{
-  if (mSurface) {
-    aWrapper->KeepUntilFullDeallocation(MakeUnique<TKeepAlive<MacIOSurface>>(mSurface));
-  }
-}
-
 // static
 MacIOSurfaceTextureData*
 MacIOSurfaceTextureData::Create(MacIOSurface* aSurface)
 {
   MOZ_ASSERT(aSurface);
   if (!aSurface) {
     return nullptr;
   }
--- a/gfx/layers/opengl/MacIOSurfaceTextureClientOGL.h
+++ b/gfx/layers/opengl/MacIOSurfaceTextureClientOGL.h
@@ -37,17 +37,15 @@ public:
   virtual void Forget(ISurfaceAllocator* aAllocator) override { mSurface = nullptr; }
 
   // For debugging purposes only.
   already_AddRefed<gfx::DataSourceSurface> GetAsSurface();
 
 protected:
   explicit MacIOSurfaceTextureData(MacIOSurface* aSurface);
 
-  virtual void FinalizeOnIPDLThread(TextureClient* aWrapper) override;
-
   RefPtr<MacIOSurface> mSurface;
 };
 
 } // namespace layers
 } // namespace mozilla
 
 #endif // MOZILLA_GFX_MACIOSURFACETEXTURECLIENTOGL_H