Bug 1200595 - D3D11 TextureData implementation. r=Bas
authorNicolas Silva <nsilva@mozilla.com>
Thu, 15 Oct 2015 17:53:37 +0200
changeset 308846 981a6bc9b1aea682f912099fb57257640e8f9359
parent 308845 8cb40615eeb03288aab83a9ffb8d17ee9cd0f0f5
child 308847 4b2a5d9c0ccd4aa98a18c6d245019feabf357ecd
push id5513
push userraliiev@mozilla.com
push dateMon, 25 Jan 2016 13:55:34 +0000
treeherdermozilla-beta@5ee97dd05b5c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersBas
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 - D3D11 TextureData implementation. r=Bas
gfx/layers/D3D11ShareHandleImage.cpp
gfx/layers/D3D11ShareHandleImage.h
gfx/layers/IMFYCbCrImage.cpp
gfx/layers/LayersLogging.cpp
gfx/layers/client/TextureClient.cpp
gfx/layers/client/TextureClient.h
gfx/layers/client/TextureClientPool.cpp
gfx/layers/d3d11/TextureD3D11.cpp
gfx/layers/d3d11/TextureD3D11.h
--- a/gfx/layers/D3D11ShareHandleImage.cpp
+++ b/gfx/layers/D3D11ShareHandleImage.cpp
@@ -124,45 +124,38 @@ D3D11ShareHandleImage::GetAsSourceSurfac
   context->Unmap(softTexture, 0);
   surface->Unmap();
 
   return surface.forget();
 }
 
 ID3D11Texture2D*
 D3D11ShareHandleImage::GetTexture() const {
-  return mTextureClient->GetD3D11Texture();
+  return static_cast<D3D11TextureData*>(mTextureClient->GetInternalData())->GetD3D11Texture();
 }
 
 already_AddRefed<TextureClient>
 D3D11RecycleAllocator::Allocate(gfx::SurfaceFormat aFormat,
                                 gfx::IntSize aSize,
                                 BackendSelector aSelector,
                                 TextureFlags aTextureFlags,
                                 TextureAllocationFlags aAllocFlags)
 {
-  return TextureClientD3D11::Create(mSurfaceAllocator,
-                                    aFormat,
-                                    TextureFlags::DEFAULT,
-                                    mDevice,
-                                    aSize);
+  return CreateD3D11TextureClientWithDevice(aSize, aFormat,
+                                            aTextureFlags, aAllocFlags,
+                                            mDevice, mSurfaceAllocator);
 }
 
-already_AddRefed<TextureClientD3D11>
+already_AddRefed<TextureClient>
 D3D11RecycleAllocator::CreateOrRecycleClient(gfx::SurfaceFormat aFormat,
                                              const gfx::IntSize& aSize)
 {
   RefPtr<TextureClient> textureClient =
     CreateOrRecycle(aFormat,
                     aSize,
                     BackendSelector::Content,
                     layers::TextureFlags::DEFAULT);
-  if (!textureClient) {
-    return nullptr;
-  }
-
-  RefPtr<TextureClientD3D11> textureD3D11 = static_cast<TextureClientD3D11*>(textureClient.get());
-  return textureD3D11.forget();
+  return textureClient.forget();
 }
 
 
 } // namespace layers
 } // namespace mozilla
--- a/gfx/layers/D3D11ShareHandleImage.h
+++ b/gfx/layers/D3D11ShareHandleImage.h
@@ -21,17 +21,17 @@ class D3D11RecycleAllocator : public Tex
 {
 public:
   explicit D3D11RecycleAllocator(CompositableForwarder* aAllocator,
                                  ID3D11Device* aDevice)
     : TextureClientRecycleAllocator(aAllocator)
     , mDevice(aDevice)
   {}
 
-  already_AddRefed<TextureClientD3D11>
+  already_AddRefed<TextureClient>
   CreateOrRecycleClient(gfx::SurfaceFormat aFormat,
                         const gfx::IntSize& aSize);
 
 protected:
   virtual already_AddRefed<TextureClient>
   Allocate(gfx::SurfaceFormat aFormat,
            gfx::IntSize aSize,
            BackendSelector aSelector,
@@ -58,15 +58,15 @@ public:
   virtual TextureClient* GetTextureClient(CompositableClient* aClient) override;
   virtual gfx::IntRect GetPictureRect() override { return mPictureRect; }
 
   ID3D11Texture2D* GetTexture() const;
 
 private:
   gfx::IntSize mSize;
   gfx::IntRect mPictureRect;
-  RefPtr<TextureClientD3D11> mTextureClient;
+  RefPtr<TextureClient> mTextureClient;
 };
 
 } // namepace layers
 } // namespace mozilla
 
 #endif // GFX_D3DSURFACEIMAGE_H
--- a/gfx/layers/IMFYCbCrImage.cpp
+++ b/gfx/layers/IMFYCbCrImage.cpp
@@ -199,27 +199,25 @@ IMFYCbCrImage::GetD3D9TextureClient(Comp
     }
     break;
   }
 
   if (!valid) {
     return nullptr;
   }
 
-  mTextureClient = DXGIYCbCrTextureClient::Create(aClient->GetForwarder(),
-                                                  TextureFlags::DEFAULT,
-                                                  textureY,
-                                                  textureCb,
-                                                  textureCr,
-                                                  shareHandleY,
-                                                  shareHandleCb,
-                                                  shareHandleCr,
-                                                  GetSize(),
-                                                  mData.mYSize,
-                                                  mData.mCbCrSize);
+  mTextureClient = TextureClient::CreateWithData(
+    DXGIYCbCrTextureData::Create(aClient->GetForwarder(),
+                                 TextureFlags::DEFAULT,
+                                 textureY, textureCb, textureCr,
+                                 shareHandleY, shareHandleCb, shareHandleCr,
+                                 GetSize(), mData.mYSize, mData.mCbCrSize),
+    TextureFlags::DEFAULT,
+    aClient->GetForwarder()
+  );
 
   return mTextureClient;
 }
 
 TextureClient*
 IMFYCbCrImage::GetTextureClient(CompositableClient* aClient)
 {
   LayersBackend backend = aClient->GetForwarder()->GetCompositorBackendType();
@@ -268,22 +266,22 @@ IMFYCbCrImage::GetTextureClient(Composit
     ctx->UpdateSubresource(textureY, 0, nullptr, mData.mYChannel,
                            mData.mYStride, mData.mYStride * mData.mYSize.height);
     ctx->UpdateSubresource(textureCb, 0, nullptr, mData.mCbChannel,
                            mData.mCbCrStride, mData.mCbCrStride * mData.mCbCrSize.height);
     ctx->UpdateSubresource(textureCr, 0, nullptr, mData.mCrChannel,
                            mData.mCbCrStride, mData.mCbCrStride * mData.mCbCrSize.height);
   }
 
-  mTextureClient = DXGIYCbCrTextureClient::Create(aClient->GetForwarder(),
-                                                  TextureFlags::DEFAULT,
-                                                  textureY,
-                                                  textureCb,
-                                                  textureCr,
-                                                  GetSize(),
-                                                  mData.mYSize,
-                                                  mData.mCbCrSize);
+  mTextureClient = TextureClient::CreateWithData(
+    DXGIYCbCrTextureData::Create(aClient->GetForwarder(),
+                                 TextureFlags::DEFAULT,
+                                 textureY, textureCb, textureCr,
+                                 GetSize(), mData.mYSize, mData.mCbCrSize),
+    TextureFlags::DEFAULT,
+    aClient->GetForwarder()
+  );
 
   return mTextureClient;
 }
 
 } // namespace layers
 } // namespace mozilla
--- a/gfx/layers/LayersLogging.cpp
+++ b/gfx/layers/LayersLogging.cpp
@@ -8,16 +8,17 @@
 #include "LayersLogging.h"
 #include <stdint.h>                     // for uint8_t
 #include "ImageTypes.h"                 // for ImageFormat
 #include "mozilla/gfx/Matrix.h"         // for Matrix4x4, Matrix
 #include "mozilla/gfx/Point.h"          // for IntSize
 #include "nsDebug.h"                    // for NS_ERROR
 #include "nsPoint.h"                    // for nsIntPoint
 #include "nsRect.h"                     // for mozilla::gfx::IntRect
+#include "base/basictypes.h"
 
 using namespace mozilla::gfx;
 
 namespace mozilla {
 namespace layers {
 
 void
 AppendToString(std::stringstream& aStream, const void* p,
--- a/gfx/layers/client/TextureClient.cpp
+++ b/gfx/layers/client/TextureClient.cpp
@@ -226,17 +226,19 @@ ClientTexture::Unlock()
   if (!mIsLocked) {
     return;
   }
 
   if (mBorrowedDrawTarget) {
     MOZ_ASSERT(mBorrowedDrawTarget->refCount() <= mExpectedDtRefs);
     if (mOpenMode & OpenMode::OPEN_WRITE) {
       mBorrowedDrawTarget->Flush();
-      if (mReadbackSink) {
+      if (mReadbackSink && !mData->ReadBack(mReadbackSink)) {
+        // Fallback implementation for reading back, because mData does not
+        // have a backend-specific implementation and returned false.
         RefPtr<SourceSurface> snapshot = mBorrowedDrawTarget->Snapshot();
         RefPtr<DataSourceSurface> dataSurf = snapshot->GetDataSurface();
         mReadbackSink->ProcessReadback(dataSurf);
       }
     }
     mBorrowedDrawTarget = nullptr;
   }
 
@@ -263,29 +265,31 @@ gfx::SurfaceFormat
 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::FinalizeOnIPDLThread()
+{
+  mData->FinalizeOnIPDLThread(this);
+}
+
+void
 ClientTexture::UpdateFromSurface(gfx::SourceSurface* aSurface)
 {
   MOZ_ASSERT(mValid);
   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
@@ -331,16 +335,20 @@ ClientTexture::BorrowDrawTarget()
   // 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;
   }
 
+  if (!NS_IsMainThread()) {
+    return nullptr;
+  }
+
   if (!mBorrowedDrawTarget) {
     mBorrowedDrawTarget = mData->BorrowDrawTarget();
 #ifdef DEBUG
     mExpectedDtRefs = mBorrowedDrawTarget ? mBorrowedDrawTarget->refCount() : 0;
 #endif
   }
 
   return mBorrowedDrawTarget;
@@ -557,17 +565,20 @@ TextureClient::CreateForDrawing(Composit
 
 #ifdef XP_WIN
   if (parentBackend == LayersBackend::LAYERS_D3D11 &&
       (moz2DBackend == gfx::BackendType::DIRECT2D ||
        moz2DBackend == gfx::BackendType::DIRECT2D1_1) &&
       aSize.width <= maxTextureSize &&
       aSize.height <= maxTextureSize)
   {
-    texture = new TextureClientD3D11(aAllocator, aFormat, aTextureFlags);
+    texture = CreateDXGITextureClient(aSize, aFormat, aTextureFlags, aAllocFlags, aAllocator);
+    if (texture) {
+      return texture.forget();
+    }
   }
   if (parentBackend == LayersBackend::LAYERS_D3D9 &&
       moz2DBackend == gfx::BackendType::CAIRO &&
       aAllocator->IsSameProcess() &&
       aSize.width <= maxTextureSize &&
       aSize.height <= maxTextureSize &&
       NS_IsMainThread()) {
     if (gfxWindowsPlatform::GetPlatform()->GetD3D9Device()) {
@@ -916,16 +927,25 @@ SyncObject::CreateSyncObject(SyncHandle 
 #ifdef XP_WIN
   return MakeAndAddRef<SyncObjectD3D11>(aHandle);
 #else
   MOZ_ASSERT_UNREACHABLE();
   return nullptr;
 #endif
 }
 
+already_AddRefed<TextureClient>
+TextureClient::CreateWithData(TextureData* aData, TextureFlags aFlags, ISurfaceAllocator* aAllocator)
+{
+  if (!aData) {
+    return nullptr;
+  }
+  return MakeAndAddRef<ClientTexture>(aData, aFlags, aAllocator);
+}
+
 bool
 MappedYCbCrChannelData::CopyInto(MappedYCbCrChannelData& aDst)
 {
   if (!data || !aDst.data || size != aDst.size) {
     return false;
   }
 
   if (stride == aDst.stride) {
--- a/gfx/layers/client/TextureClient.h
+++ b/gfx/layers/client/TextureClient.h
@@ -190,16 +190,19 @@ struct MappedYCbCrTextureData {
 class TextureClient
   : public AtomicRefCountedWithFinalize<TextureClient>
 {
 public:
   explicit TextureClient(ISurfaceAllocator* aAllocator,
                          TextureFlags aFlags = TextureFlags::DEFAULT);
   virtual ~TextureClient();
 
+  static already_AddRefed<TextureClient>
+  CreateWithData(TextureData* aData, TextureFlags aFlags, ISurfaceAllocator* aAllocator);
+
   // Creates and allocates a TextureClient usable with Moz2D.
   static already_AddRefed<TextureClient>
   CreateForDrawing(CompositableForwarder* aAllocator,
                    gfx::SurfaceFormat aFormat,
                    gfx::IntSize aSize,
                    BackendSelector aSelector,
                    TextureFlags aTextureFlags,
                    TextureAllocationFlags flags = ALLOC_DEFAULT);
@@ -634,19 +637,26 @@ public:
 
   virtual TextureData*
   CreateSimilar(ISurfaceAllocator* aAllocator,
                 TextureFlags aFlags = TextureFlags::DEFAULT,
                 TextureAllocationFlags aAllocFlags = ALLOC_DEFAULT) const { return nullptr; }
 
   virtual bool UpdateFromSurface(gfx::SourceSurface* aSurface) { return false; };
 
+  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*) {}
 };
 
 /// 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);
 
@@ -682,21 +692,26 @@ public:
   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;
 
+  virtual void SyncWithObject(SyncObject* aFence) override { mData->SyncWithObject(aFence); }
+
   // 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; }
+
+  virtual void FinalizeOnIPDLThread() override;
+
 protected:
   TextureData* mData;
   RefPtr<gfx::DrawTarget> mBorrowedDrawTarget;
   RefPtr<TextureReadbackSink> mReadbackSink;
 
   OpenMode mOpenMode;
   DebugOnly<uint32_t> mExpectedDtRefs;
   bool mIsLocked;
--- a/gfx/layers/client/TextureClientPool.cpp
+++ b/gfx/layers/client/TextureClientPool.cpp
@@ -1,16 +1,16 @@
 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "TextureClientPool.h"
 #include "CompositableClient.h"
-#include "mozilla/layers/ISurfaceAllocator.h"
+#include "mozilla/layers/CompositableForwarder.h"
 
 #include "gfxPrefs.h"
 
 #include "nsComponentManagerUtils.h"
 
 #define TCP_LOG(...)
 //#define TCP_LOG(...) printf_stderr(__VA_ARGS__);
 
--- a/gfx/layers/d3d11/TextureD3D11.cpp
+++ b/gfx/layers/d3d11/TextureD3D11.cpp
@@ -15,16 +15,64 @@
 #include "mozilla/gfx/Logging.h"
 
 namespace mozilla {
 
 using namespace gfx;
 
 namespace layers {
 
+static const GUID sD3D11TextureUsage =
+{ 0xd89275b0, 0x6c7d, 0x4038, { 0xb5, 0xfa, 0x4d, 0x87, 0x16, 0xd5, 0xcc, 0x4e } };
+
+/* This class gets its lifetime tied to a D3D texture
+ * and increments memory usage on construction and decrements
+ * on destruction */
+class TextureMemoryMeasurer : public IUnknown
+{
+public:
+  TextureMemoryMeasurer(size_t aMemoryUsed)
+  {
+    mMemoryUsed = aMemoryUsed;
+    gfxWindowsPlatform::sD3D11MemoryUsed += mMemoryUsed;
+    mRefCnt = 0;
+  }
+  STDMETHODIMP_(ULONG) AddRef() {
+    mRefCnt++;
+    return mRefCnt;
+  }
+  STDMETHODIMP QueryInterface(REFIID riid,
+                              void **ppvObject)
+  {
+    IUnknown *punk = nullptr;
+    if (riid == IID_IUnknown) {
+      punk = this;
+    }
+    *ppvObject = punk;
+    if (punk) {
+      punk->AddRef();
+      return S_OK;
+    } else {
+      return E_NOINTERFACE;
+    }
+  }
+
+  STDMETHODIMP_(ULONG) Release() {
+    int refCnt = --mRefCnt;
+    if (refCnt == 0) {
+      gfxWindowsPlatform::sD3D11MemoryUsed -= mMemoryUsed;
+      delete this;
+    }
+    return refCnt;
+  }
+private:
+  int mRefCnt;
+  int mMemoryUsed;
+};
+
 static DXGI_FORMAT
 SurfaceFormatToDXGIFormat(gfx::SurfaceFormat aFormat)
 {
   switch (aFormat) {
     case SurfaceFormat::B8G8R8A8:
       return DXGI_FORMAT_B8G8R8A8_UNORM;
     case SurfaceFormat::B8G8R8X8:
       return DXGI_FORMAT_B8G8R8A8_UNORM;
@@ -160,16 +208,485 @@ static void UnlockD3DTexture(T* aTexture
   if (mutex) {
     HRESULT hr = mutex->ReleaseSync(0);
     if (FAILED(hr)) {
       NS_WARNING("Failed to unlock the texture");
     }
   }
 }
 
+DXGITextureData::DXGITextureData(gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
+                                 bool aNeedsClear, bool aNeedsClearWhite)
+: mSize(aSize)
+, mFormat(aFormat)
+, mNeedsClear(aNeedsClear)
+, mNeedsClearWhite(aNeedsClearWhite)
+, mHasSynchronization(false)
+{}
+
+D3D11TextureData::D3D11TextureData(ID3D11Texture2D* aTexture,
+                                   gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
+                                   bool aNeedsClear, bool aNeedsClearWhite)
+: DXGITextureData(aSize, aFormat, aNeedsClear, aNeedsClearWhite)
+, mTexture(aTexture)
+{
+  MOZ_ASSERT(aTexture);
+  mHasSynchronization = HasKeyedMutex(aTexture);
+}
+
+D3D11TextureData::~D3D11TextureData()
+{
+#ifdef DEBUG
+  // An Azure DrawTarget needs to be locked when it gets nullptr'ed as this is
+  // when it calls EndDraw. This EndDraw should not execute anything so it
+  // shouldn't -really- need the lock but the debug layer chokes on this.
+  if (mDrawTarget) {
+    Lock(OpenMode::OPEN_NONE, nullptr);
+    mDrawTarget = nullptr;
+    Unlock();
+  }
+#endif
+}
+
+D3D10TextureData::D3D10TextureData(ID3D10Texture2D* aTexture,
+                 gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
+                 bool aNeedsClear, bool aNeedsClearWhite)
+: DXGITextureData(aSize, aFormat, aNeedsClear, aNeedsClearWhite)
+, mTexture(aTexture)
+{
+  MOZ_ASSERT(aTexture);
+  mHasSynchronization = HasKeyedMutex(aTexture);
+}
+
+D3D10TextureData::~D3D10TextureData()
+{
+#ifdef DEBUG
+  // An Azure DrawTarget needs to be locked when it gets nullptr'ed as this is
+  // when it calls EndDraw. This EndDraw should not execute anything so it
+  // shouldn't -really- need the lock but the debug layer chokes on this.
+  if (mDrawTarget) {
+    Lock(OpenMode::OPEN_NONE, nullptr);
+    mDrawTarget = nullptr;
+    Unlock();
+  }
+#endif
+}
+
+bool
+D3D11TextureData::Lock(OpenMode aMode, FenceHandle*)
+{
+  if (!LockD3DTexture(mTexture.get())) {
+    return false;
+  }
+
+  if (NS_IsMainThread()) {
+    if (!PrepareDrawTargetInLock(aMode)) {
+      Unlock();
+      return false;
+    }
+  }
+
+  return true;
+}
+
+bool
+D3D10TextureData::Lock(OpenMode aMode, FenceHandle*)
+{
+  if (!LockD3DTexture(mTexture.get())) {
+    return false;
+  }
+
+  if (NS_IsMainThread()) {
+    if (!PrepareDrawTargetInLock(aMode)) {
+      Unlock();
+      return false;
+    }
+  }
+
+  return true;
+}
+
+bool
+DXGITextureData::PrepareDrawTargetInLock(OpenMode aMode)
+{
+  // Make sure that successful write-lock means we will have a DrawTarget to
+  // write into.
+  if (!mDrawTarget && (aMode & OpenMode::OPEN_WRITE || mNeedsClear || mNeedsClearWhite)) {
+    mDrawTarget = BorrowDrawTarget();
+    if (!mDrawTarget) {
+      return false;
+    }
+  }
+
+  if (mNeedsClear) {
+    mDrawTarget->ClearRect(Rect(0, 0, GetSize().width, GetSize().height));
+    mNeedsClear = false;
+  }
+  if (mNeedsClearWhite) {
+    mDrawTarget->FillRect(Rect(0, 0, GetSize().width, GetSize().height), ColorPattern(Color(1.0, 1.0, 1.0, 1.0)));
+    mNeedsClearWhite = false;
+  }
+
+  return true;
+}
+
+void
+D3D11TextureData::Unlock()
+{
+  UnlockD3DTexture(mTexture.get());
+}
+
+void
+D3D10TextureData::Unlock()
+{
+  UnlockD3DTexture(mTexture.get());
+}
+
+void
+D3D11TextureData::SyncWithObject(SyncObject* aSyncObject)
+{
+  if (!aSyncObject || !NS_IsMainThread()) {
+    // When off the main thread we sync using a keyed mutex per texture.
+    return;
+  }
+
+  MOZ_ASSERT(aSyncObject->GetSyncType() == SyncObject::SyncType::D3D11);
+  SyncObjectD3D11* sync = static_cast<SyncObjectD3D11*>(aSyncObject);
+  sync->RegisterTexture(mTexture);
+}
+
+void
+D3D10TextureData::SyncWithObject(SyncObject* aSyncObject)
+{
+  if (!aSyncObject || !NS_IsMainThread()) {
+    // When off the main thread we sync using a keyed mutex per texture.
+    return;
+  }
+
+  MOZ_ASSERT(aSyncObject->GetSyncType() == SyncObject::SyncType::D3D11);
+  SyncObjectD3D11* sync = static_cast<SyncObjectD3D11*>(aSyncObject);
+  sync->RegisterTexture(mTexture);
+}
+
+bool
+DXGITextureData::Serialize(SurfaceDescriptor& aOutDescriptor)
+{
+  RefPtr<IDXGIResource> resource;
+  GetDXGIResource((IDXGIResource**)getter_AddRefs(resource));
+  if (!resource) {
+    return false;
+  }
+  HANDLE sharedHandle;
+  HRESULT hr = resource->GetSharedHandle(&sharedHandle);
+  if (FAILED(hr)) {
+    LOGD3D11("Error getting shared handle for texture.");
+    return false;
+  }
+
+  aOutDescriptor = SurfaceDescriptorD3D10((WindowsHandle)sharedHandle, mFormat, mSize);
+  return true;
+}
+
+bool
+D3D10TextureData::ReadBack(TextureReadbackSink* aReadbackSinc)
+{
+  if (NS_IsMainThread() && aReadbackSinc && mTexture) {
+    ID3D10Device* device = gfxWindowsPlatform::GetPlatform()->GetD3D10Device();
+
+    D3D10_TEXTURE2D_DESC desc;
+    mTexture->GetDesc(&desc);
+    desc.BindFlags = 0;
+    desc.Usage = D3D10_USAGE_STAGING;
+    desc.CPUAccessFlags = D3D10_CPU_ACCESS_READ;
+    desc.MiscFlags = 0;
+
+    RefPtr<ID3D10Texture2D> tex;
+    HRESULT hr = device->CreateTexture2D(&desc, nullptr, getter_AddRefs(tex));
+
+    if (SUCCEEDED(hr)) {
+      device->CopyResource(tex, mTexture);
+      gfxWindowsPlatform::GetPlatform()->GetReadbackManager()->PostTask(tex, aReadbackSinc);
+    } else {
+      gfxCriticalError(CriticalLog::DefaultOptions(Factory::ReasonableSurfaceSize(mSize))) << "[D3D11] CreateTexture2D failure " << mSize << " Code: " << gfx::hexa(hr);
+      aReadbackSinc->ProcessReadback(nullptr);
+    }
+  }
+
+  return true;
+}
+
+DXGITextureData*
+DXGITextureData::Create(IntSize aSize, SurfaceFormat aFormat, TextureAllocationFlags aFlags)
+{
+  if (aFormat == SurfaceFormat::A8) {
+    // Currently we don't support A8 surfaces. Fallback.
+    return nullptr;
+  }
+
+  gfxWindowsPlatform* windowsPlatform = gfxWindowsPlatform::GetPlatform();
+  // When we're not on the main thread we're not going to be using Direct2D
+  // to access the contents of this texture client so we will always use D3D11.
+  bool haveD3d11Backend = windowsPlatform->GetContentBackendFor(LayersBackend::LAYERS_D3D11) == BackendType::DIRECT2D1_1 || !NS_IsMainThread();
+
+  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<ClientTexture>(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);
+  if (!d3d11device) {
+    return nullptr;
+  }
+
+  CD3D11_TEXTURE2D_DESC newDesc(DXGI_FORMAT_B8G8R8A8_UNORM,
+                                aSize.width, aSize.height, 1, 1,
+                                D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE);
+
+  newDesc.MiscFlags = D3D11_RESOURCE_MISC_SHARED;
+  if (!NS_IsMainThread()) {
+    // On the main thread we use the syncobject to handle synchronization.
+    newDesc.MiscFlags = D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX;
+  }
+
+  HRESULT hr = d3d11device->CreateTexture2D(&newDesc, nullptr, getter_AddRefs(texture11));
+  if (FAILED(hr)) {
+    gfxCriticalError(CriticalLog::DefaultOptions(Factory::ReasonableSurfaceSize(aSize)))
+      << "[D3D11] 2 CreateTexture2D failure " << aSize << " Code: " << gfx::hexa(hr);
+    return nullptr;
+  }
+  texture11->SetPrivateDataInterface(sD3D11TextureUsage,
+                                     new TextureMemoryMeasurer(newDesc.Width * newDesc.Height * 4));
+  return new D3D11TextureData(texture11, aSize, aFormat,
+                              aFlags & ALLOC_CLEAR_BUFFER,
+                              aFlags & ALLOC_CLEAR_BUFFER_WHITE);
+}
+
+void
+D3D11TextureData::Deallocate(ISurfaceAllocator* aAllocator)
+{
+  mTexture = nullptr;
+}
+
+already_AddRefed<TextureClient>
+CreateD3D11TextureClientWithDevice(IntSize aSize, SurfaceFormat aFormat,
+                                   TextureFlags aTextureFlags, TextureAllocationFlags aAllocFlags,
+                                   ID3D11Device* aDevice,
+                                   ISurfaceAllocator* aAllocator)
+{
+  TextureData* data = D3D11TextureData::Create(aSize, aFormat, aAllocFlags, aDevice);
+  if (!data) {
+    return nullptr;
+  }
+  return MakeAndAddRef<ClientTexture>(data, aTextureFlags, aAllocator);
+}
+
+TextureData*
+D3D11TextureData::CreateSimilar(ISurfaceAllocator* aAllocator,
+                                TextureFlags aFlags,
+                                TextureAllocationFlags aAllocFlags) const
+{
+  return D3D11TextureData::Create(mSize, mFormat, aAllocFlags);
+}
+
+DXGITextureData*
+D3D10TextureData::Create(IntSize aSize, SurfaceFormat aFormat, TextureAllocationFlags aFlags)
+{
+  RefPtr<ID3D10Texture2D> texture10;
+  ID3D10Device* device = gfxWindowsPlatform::GetPlatform()->GetD3D10Device();
+
+  CD3D10_TEXTURE2D_DESC newDesc(DXGI_FORMAT_B8G8R8A8_UNORM,
+    aSize.width, aSize.height, 1, 1,
+    D3D10_BIND_RENDER_TARGET | D3D10_BIND_SHADER_RESOURCE);
+
+  newDesc.MiscFlags = D3D10_RESOURCE_MISC_SHARED;
+
+  HRESULT hr = device->CreateTexture2D(&newDesc, nullptr, getter_AddRefs(texture10));
+  if (FAILED(hr)) {
+    gfxCriticalError(CriticalLog::DefaultOptions(Factory::ReasonableSurfaceSize(aSize)))
+      << "[D3D10] 2 CreateTexture2D failure " << aSize << " Code: " << gfx::hexa(hr);
+    return nullptr;
+  }
+  texture10->SetPrivateDataInterface(sD3D11TextureUsage,
+                                     new TextureMemoryMeasurer(newDesc.Width * newDesc.Height * 4));
+
+  return new D3D10TextureData(texture10, aSize, aFormat,
+                              aFlags & ALLOC_CLEAR_BUFFER,
+                              aFlags & ALLOC_CLEAR_BUFFER_WHITE);
+}
+
+void
+D3D10TextureData::Deallocate(ISurfaceAllocator* aAllocator)
+{
+  mTexture = nullptr;
+}
+
+TextureData*
+D3D10TextureData::CreateSimilar(ISurfaceAllocator* aAllocator,
+                                TextureFlags aFlags,
+                                TextureAllocationFlags aAllocFlags) const
+{
+  return D3D10TextureData::Create(mSize, mFormat, aAllocFlags);
+}
+
+void
+D3D11TextureData::GetDXGIResource(IDXGIResource** aOutResource)
+{
+  mTexture->QueryInterface(aOutResource);
+}
+
+void
+D3D10TextureData::GetDXGIResource(IDXGIResource** aOutResource)
+{
+  mTexture->QueryInterface(aOutResource);
+}
+
+DXGIYCbCrTextureData*
+DXGIYCbCrTextureData::Create(ISurfaceAllocator* aAllocator,
+                             TextureFlags aFlags,
+                             IUnknown* aTextureY,
+                             IUnknown* aTextureCb,
+                             IUnknown* aTextureCr,
+                             HANDLE aHandleY,
+                             HANDLE aHandleCb,
+                             HANDLE aHandleCr,
+                             const gfx::IntSize& aSize,
+                             const gfx::IntSize& aSizeY,
+                             const gfx::IntSize& aSizeCbCr)
+{
+  if (!aHandleY || !aHandleCb || !aHandleCr ||
+      !aTextureY || !aTextureCb || !aTextureCr) {
+    return nullptr;
+  }
+
+  DXGIYCbCrTextureData* texture = new DXGIYCbCrTextureData();
+  texture->mHandles[0] = aHandleY;
+  texture->mHandles[1] = aHandleCb;
+  texture->mHandles[2] = aHandleCr;
+  texture->mHoldRefs[0] = aTextureY;
+  texture->mHoldRefs[1] = aTextureCb;
+  texture->mHoldRefs[2] = aTextureCr;
+  texture->mSize = aSize;
+  texture->mSizeY = aSizeY;
+  texture->mSizeCbCr = aSizeCbCr;
+
+  return texture;
+}
+
+DXGIYCbCrTextureData*
+DXGIYCbCrTextureData::Create(ISurfaceAllocator* aAllocator,
+                             TextureFlags aFlags,
+                             ID3D11Texture2D* aTextureY,
+                             ID3D11Texture2D* aTextureCb,
+                             ID3D11Texture2D* aTextureCr,
+                             const gfx::IntSize& aSize,
+                             const gfx::IntSize& aSizeY,
+                             const gfx::IntSize& aSizeCbCr)
+{
+  if (!aTextureY || !aTextureCb || !aTextureCr) {
+    return nullptr;
+  }
+
+  aTextureY->SetPrivateDataInterface(sD3D11TextureUsage,
+    new TextureMemoryMeasurer(aSize.width * aSize.height));
+  aTextureCb->SetPrivateDataInterface(sD3D11TextureUsage,
+    new TextureMemoryMeasurer(aSizeCbCr.width * aSizeCbCr.height));
+  aTextureCr->SetPrivateDataInterface(sD3D11TextureUsage,
+    new TextureMemoryMeasurer(aSizeCbCr.width * aSizeCbCr.height));
+
+  RefPtr<IDXGIResource> resource;
+
+  aTextureY->QueryInterface((IDXGIResource**)getter_AddRefs(resource));
+
+  HANDLE handleY;
+  HRESULT hr = resource->GetSharedHandle(&handleY);
+  if (FAILED(hr)) {
+    return nullptr;
+  }
+
+  aTextureCb->QueryInterface((IDXGIResource**)getter_AddRefs(resource));
+
+  HANDLE handleCb;
+  hr = resource->GetSharedHandle(&handleCb);
+  if (FAILED(hr)) {
+    return nullptr;
+  }
+
+  aTextureCr->QueryInterface((IDXGIResource**)getter_AddRefs(resource));
+  HANDLE handleCr;
+  hr = resource->GetSharedHandle(&handleCr);
+  if (FAILED(hr)) {
+    return nullptr;
+  }
+
+  return DXGIYCbCrTextureData::Create(aAllocator, aFlags,
+                                      aTextureY, aTextureCb, aTextureCr,
+                                      handleY, handleCb, handleCr,
+                                      aSize, aSizeY, aSizeCbCr);
+}
+
+bool
+DXGIYCbCrTextureData::Serialize(SurfaceDescriptor& aOutDescriptor)
+{
+  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;
+}
+
 already_AddRefed<TextureHost>
 CreateTextureHostD3D11(const SurfaceDescriptor& aDesc,
                        ISurfaceAllocator* aDeallocator,
                        TextureFlags aFlags)
 {
   RefPtr<TextureHost> result;
   switch (aDesc.type()) {
     case SurfaceDescriptor::TSurfaceDescriptorShmem:
@@ -189,632 +706,127 @@ CreateTextureHostD3D11(const SurfaceDesc
     }
     default: {
       NS_WARNING("Unsupported SurfaceDescriptor type");
     }
   }
   return result.forget();
 }
 
-TextureClientD3D11::TextureClientD3D11(ISurfaceAllocator* aAllocator,
-                                       gfx::SurfaceFormat aFormat,
-                                       TextureFlags aFlags)
-  : TextureClient(aAllocator, aFlags)
-  , mFormat(aFormat)
-  , mIsLocked(false)
-  , mNeedsClear(false)
-  , mNeedsClearWhite(false)
-{}
 
-TextureClientD3D11::~TextureClientD3D11()
+already_AddRefed<DrawTarget>
+D3D11TextureData::BorrowDrawTarget()
 {
-#ifdef DEBUG
-  // An Azure DrawTarget needs to be locked when it gets nullptr'ed as this is
-  // when it calls EndDraw. This EndDraw should not execute anything so it
-  // shouldn't -really- need the lock but the debug layer chokes on this.
-  if (mDrawTarget) {
-    MOZ_ASSERT(!mIsLocked);
-    MOZ_ASSERT(mTexture || mTexture10);
-    MOZ_ASSERT(mDrawTarget->refCount() == 1);
-    if (mTexture) {
-      LockD3DTexture(mTexture.get());
-    } else {
-      LockD3DTexture(mTexture10.get());
-    }
-    mDrawTarget = nullptr;
-    if (mTexture) {
-      UnlockD3DTexture(mTexture.get());
-    } else {
-      UnlockD3DTexture(mTexture10.get());
+  MOZ_ASSERT(NS_IsMainThread());
+
+  if (!mDrawTarget && mTexture) {
+    // This may return a null DrawTarget
+    mDrawTarget = Factory::CreateDrawTargetForD3D11Texture(mTexture, mFormat);
+    if (!mDrawTarget) {
+      gfxCriticalNote << "Could not borrow DrawTarget (D3D11) " << (int)mFormat;
     }
   }
-#endif
-}
 
-void
-TextureClientD3D11::FinalizeOnIPDLThread()
-{
-  if (mActor) {
-    if (mTexture) {
-      KeepUntilFullDeallocation(MakeUnique<TKeepAlive<ID3D11Texture2D>>(mTexture));
-    } else if (mTexture10) {
-      KeepUntilFullDeallocation(MakeUnique<TKeepAlive<ID3D10Texture2D>>(mTexture10));
-    }
-  }
+  RefPtr<DrawTarget> result = mDrawTarget;
+  return result.forget();
 }
 
-// static
-already_AddRefed<TextureClientD3D11>
-TextureClientD3D11::Create(ISurfaceAllocator* aAllocator,
-                           gfx::SurfaceFormat aFormat,
-                           TextureFlags aFlags,
-                           ID3D11Texture2D* aTexture,
-                           gfx::IntSize aSize)
+already_AddRefed<DrawTarget>
+D3D10TextureData::BorrowDrawTarget()
 {
-  RefPtr<TextureClientD3D11> texture = new TextureClientD3D11(aAllocator,
-                                                             aFormat,
-                                                             aFlags);
-  texture->mTexture = aTexture;
-  texture->mSize = aSize;
-  return texture.forget();
-}
+  MOZ_ASSERT(NS_IsMainThread());
 
-already_AddRefed<TextureClientD3D11>
-TextureClientD3D11::Create(ISurfaceAllocator* aAllocator,
-                           gfx::SurfaceFormat aFormat,
-                           TextureFlags aFlags,
-                           ID3D11Device* aDevice,
-                           const gfx::IntSize& aSize)
-{
-  RefPtr<TextureClientD3D11> texture = new TextureClientD3D11(aAllocator,
-                                                              aFormat,
-                                                              aFlags);
-  if (!texture->AllocateD3D11Surface(aDevice, aSize)) {
-    return nullptr;
-  }
-  return texture.forget();
-}
-
-already_AddRefed<TextureClient>
-TextureClientD3D11::CreateSimilar(TextureFlags aFlags,
-                                  TextureAllocationFlags aAllocFlags) const
-{
-  RefPtr<TextureClient> tex = new TextureClientD3D11(mAllocator, mFormat,
-                                                     mFlags | aFlags);
-
-  if (!tex->AllocateForSurface(mSize, aAllocFlags)) {
-    return nullptr;
+  if (!mDrawTarget && mTexture) {
+    // This may return a null DrawTarget
+    mDrawTarget = Factory::CreateDrawTargetForD3D10Texture(mTexture, mFormat);
+    if (!mDrawTarget) {
+      gfxCriticalNote << "Could not borrow DrawTarget (D3D10) " << (int)mFormat;
+    }
   }
 
-  return tex.forget();
-}
-
-void
-TextureClientD3D11::SyncWithObject(SyncObject* aSyncObject)
-{
-  if (!aSyncObject || !NS_IsMainThread()) {
-    // When off the main thread we sync using a keyed mutex per texture.
-    return;
-  }
-
-  MOZ_ASSERT(aSyncObject->GetSyncType() == SyncObject::SyncType::D3D11);
-
-  SyncObjectD3D11* sync = static_cast<SyncObjectD3D11*>(aSyncObject);
-
-  if (mTexture) {
-    sync->RegisterTexture(mTexture);
-  } else {
-    sync->RegisterTexture(mTexture10);
-  }
+  RefPtr<DrawTarget> result = mDrawTarget;
+  return result.forget();
 }
 
 bool
-TextureClientD3D11::Lock(OpenMode aMode)
-{
-  if (!IsAllocated()) {
-    return false;
-  }
-  MOZ_ASSERT(!mIsLocked, "The Texture is already locked!");
-
-  if (mTexture) {
-    MOZ_ASSERT(!mTexture10);
-    mIsLocked = LockD3DTexture(mTexture.get());
-  } else {
-    MOZ_ASSERT(!mTexture);
-    mIsLocked = LockD3DTexture(mTexture10.get());
-  }
-  if (!mIsLocked) {
-    return false;
-  }
-
-  if (NS_IsMainThread()) {
-    // Make sure that successful write-lock means we will have a DrawTarget to
-    // write into.
-    if (aMode & OpenMode::OPEN_WRITE) {
-      mDrawTarget = BorrowDrawTarget();
-      if (!mDrawTarget) {
-        Unlock();
-        return false;
-      }
-    }
-
-    if (mNeedsClear) {
-      mDrawTarget = BorrowDrawTarget();
-      if (!mDrawTarget) {
-        Unlock();
-        return false;
-      }
-      mDrawTarget->ClearRect(Rect(0, 0, GetSize().width, GetSize().height));
-      mNeedsClear = false;
-    }
-    if (mNeedsClearWhite) {
-      mDrawTarget = BorrowDrawTarget();
-      if (!mDrawTarget) {
-        Unlock();
-        return false;
-      }
-      mDrawTarget->FillRect(Rect(0, 0, GetSize().width, GetSize().height), ColorPattern(Color(1.0, 1.0, 1.0, 1.0)));
-      mNeedsClearWhite = false;
-    }
-  }
-
-  return true;
-}
-
-void
-TextureClientD3D11::Unlock()
-{
-  MOZ_ASSERT(mIsLocked, "Unlocked called while the texture is not locked!");
-  if (!mIsLocked) {
-    return;
-  }
-
-  if (mDrawTarget) {
-    // see the comment on TextureClient::BorrowDrawTarget.
-    // This DrawTarget is internal to the TextureClient and is only exposed to the
-    // outside world between Lock() and Unlock(). This assertion checks that no outside
-    // reference remains by the time Unlock() is called.
-    MOZ_ASSERT(mDrawTarget->refCount() == 1);
-    mDrawTarget->Flush();
-  }
-
-  if (NS_IsMainThread() && mReadbackSink && mTexture10) {
-    ID3D10Device* device = gfxWindowsPlatform::GetPlatform()->GetD3D10Device();
-    if (!device) {
-      return;
-    }
-
-    D3D10_TEXTURE2D_DESC desc;
-    mTexture10->GetDesc(&desc);
-    desc.BindFlags = 0;
-    desc.Usage = D3D10_USAGE_STAGING;
-    desc.CPUAccessFlags = D3D10_CPU_ACCESS_READ;
-    desc.MiscFlags = 0;
-
-    RefPtr<ID3D10Texture2D> tex;
-    HRESULT hr = device->CreateTexture2D(&desc, nullptr, getter_AddRefs(tex));
-
-    if (SUCCEEDED(hr)) {
-      device->CopyResource(tex, mTexture10);
-      gfxWindowsPlatform::GetPlatform()->GetReadbackManager()->PostTask(tex, mReadbackSink);
-    } else {
-      gfxCriticalError(CriticalLog::DefaultOptions(Factory::ReasonableSurfaceSize(mSize))) << "[D3D11] CreateTexture2D failure " << mSize << " Code: " << gfx::hexa(hr);
-      mReadbackSink->ProcessReadback(nullptr);
-    }
-  }
-
-  // The DrawTarget is created only once, and is only usable between calls
-  // to Lock and Unlock.
-  if (mTexture) {
-    UnlockD3DTexture(mTexture.get());
-  } else {
-    UnlockD3DTexture(mTexture10.get());
-  }
-  mIsLocked = false;
-}
-
-DrawTarget*
-TextureClientD3D11::BorrowDrawTarget()
-{
-  MOZ_ASSERT(mIsLocked, "Calling TextureClient::BorrowDrawTarget without locking :(");
-  MOZ_ASSERT(NS_IsMainThread());
-
-  if (!mIsLocked || (!mTexture && !mTexture10)) {
-    gfxCriticalError() << "Attempted to borrow a DrawTarget without locking the texture.";
-    return nullptr;
-  }
-
-  if (mDrawTarget) {
-    return mDrawTarget;
-  }
-
-  // This may return a null DrawTarget
-  if (mTexture) {
-    mDrawTarget = Factory::CreateDrawTargetForD3D11Texture(mTexture, mFormat);
-  } else
-  {
-    MOZ_ASSERT(mTexture10);
-    mDrawTarget = Factory::CreateDrawTargetForD3D10Texture(mTexture10, mFormat);
-  }
-  if (!mDrawTarget) {
-    gfxCriticalNote << "Invalid draw target for borrowing D3D11 " << (int)mFormat;
-  }
-  return mDrawTarget;
-}
-
-void
-TextureClientD3D11::UpdateFromSurface(gfx::SourceSurface* aSurface)
+D3D11TextureData::UpdateFromSurface(gfx::SourceSurface* aSurface)
 {
   RefPtr<DataSourceSurface> srcSurf = aSurface->GetDataSurface();
 
   if (!srcSurf) {
     gfxCriticalError() << "Failed to GetDataSurface in UpdateFromSurface.";
-    return;
-  }
-
-  if (mDrawTarget) {
-    // Ensure unflushed work from our outstanding drawtarget won't override this
-    // update later.
-    mDrawTarget->Flush();
-  }
-
-  if (mSize != srcSurf->GetSize() || mFormat != srcSurf->GetFormat()) {
-    gfxCriticalError() << "Attempt to update texture client from a surface with a different size or format!";
-    return;
+    return false;
   }
 
   DataSourceSurface::MappedSurface sourceMap;
   if (!srcSurf->Map(DataSourceSurface::READ, &sourceMap)) {
     gfxCriticalError() << "Failed to map source surface for UpdateFromSurface.";
-    return;
-  }
-
-  if (mTexture) {
-    RefPtr<ID3D11Device> device;
-    mTexture->GetDevice(getter_AddRefs(device));
-    RefPtr<ID3D11DeviceContext> ctx;
-    device->GetImmediateContext(getter_AddRefs(ctx));
-
-    D3D11_BOX box;
-    box.front = 0;
-    box.back = 1;
-    box.top = box.left = 0;
-    box.right = aSurface->GetSize().width;
-    box.bottom = aSurface->GetSize().height;
-
-    ctx->UpdateSubresource(mTexture, 0, &box, sourceMap.mData, sourceMap.mStride, 0);
-  } else {
-    RefPtr<ID3D10Device> device;
-    mTexture10->GetDevice(getter_AddRefs(device));
-
-    D3D10_BOX box;
-    box.front = 0;
-    box.back = 1;
-    box.top = box.left = 0;
-    box.right = aSurface->GetSize().width;
-    box.bottom = aSurface->GetSize().height;
-
-    device->UpdateSubresource(mTexture10, 0, &box, sourceMap.mData, sourceMap.mStride, 0);
-  }
-  srcSurf->Unmap();
-}
-
-static const GUID sD3D11TextureUsage =
-{ 0xd89275b0, 0x6c7d, 0x4038, { 0xb5, 0xfa, 0x4d, 0x87, 0x16, 0xd5, 0xcc, 0x4e } };
-
-/* This class gets its lifetime tied to a D3D texture
- * and increments memory usage on construction and decrements
- * on destruction */
-class TextureMemoryMeasurer : public IUnknown
-{
-public:
-  TextureMemoryMeasurer(size_t aMemoryUsed)
-  {
-    mMemoryUsed = aMemoryUsed;
-    gfxWindowsPlatform::sD3D11MemoryUsed += mMemoryUsed;
-    mRefCnt = 0;
-  }
-  STDMETHODIMP_(ULONG) AddRef() {
-    mRefCnt++;
-    return mRefCnt;
-  }
-  STDMETHODIMP QueryInterface(REFIID riid,
-                              void **ppvObject)
-  {
-    IUnknown *punk = nullptr;
-    if (riid == IID_IUnknown) {
-      punk = this;
-    }
-    *ppvObject = punk;
-    if (punk) {
-      punk->AddRef();
-      return S_OK;
-    } else {
-      return E_NOINTERFACE;
-    }
-  }
-
-  STDMETHODIMP_(ULONG) Release() {
-    int refCnt = --mRefCnt;
-    if (refCnt == 0) {
-      gfxWindowsPlatform::sD3D11MemoryUsed -= mMemoryUsed;
-      delete this;
-    }
-    return refCnt;
-  }
-private:
-  int mRefCnt;
-  int mMemoryUsed;
-};
-
-bool
-TextureClientD3D11::AllocateD3D11Surface(ID3D11Device* aDevice, const gfx::IntSize& aSize)
-{
-  MOZ_ASSERT(aDevice != nullptr);
-
-  CD3D11_TEXTURE2D_DESC newDesc(mFormat == SurfaceFormat::A8 ? DXGI_FORMAT_R8_UNORM : DXGI_FORMAT_B8G8R8A8_UNORM,
-                                aSize.width, aSize.height, 1, 1,
-                                D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE);
-
-  newDesc.MiscFlags = D3D11_RESOURCE_MISC_SHARED;
-
-  if (!NS_IsMainThread()) {
-    // On the main thread we use the syncobject to handle synchronization.
-    newDesc.MiscFlags = D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX;
-  }
-
-  HRESULT hr = aDevice->CreateTexture2D(&newDesc, nullptr, getter_AddRefs(mTexture));
-  if (FAILED(hr)) {
-    gfxCriticalError(CriticalLog::DefaultOptions(Factory::ReasonableSurfaceSize(aSize))) << "[D3D11] 2 CreateTexture2D failure " << aSize << " Code: " << gfx::hexa(hr);
-    return false;
-  }
-  mTexture->SetPrivateDataInterface(sD3D11TextureUsage,
-                                    new TextureMemoryMeasurer(newDesc.Width * newDesc.Height *
-                                                              (mFormat == SurfaceFormat::A8 ?
-                                                               1 : 4)));
-  mSize = aSize;
-  return true;
-}
-
-bool
-TextureClientD3D11::AllocateForSurface(gfx::IntSize aSize, TextureAllocationFlags aFlags)
-{
-  mSize = aSize;
-  HRESULT hr;
-
-  if (mFormat == SurfaceFormat::A8) {
-    // Currently TextureClientD3D11 does not support A8 surfaces. Fallback.
     return false;
   }
 
-  gfxWindowsPlatform* windowsPlatform = gfxWindowsPlatform::GetPlatform();
-  ID3D11Device* d3d11device = windowsPlatform->GetD3D11DeviceForCurrentThread();
-
-  // When we're not on the main thread we're not going to be using Direct2D
-  // to access the contents of this texture client so we will always use D3D11.
-  BackendType backend = windowsPlatform->GetContentBackendFor(LayersBackend::LAYERS_D3D11);
-  bool haveD3d11Backend = (backend == BackendType::DIRECT2D1_1) || !NS_IsMainThread();
-
-  if (haveD3d11Backend) {
-    if (!AllocateD3D11Surface(d3d11device, aSize)) {
-      return false;
-    }
-  } else {
-    ID3D10Device* device = gfxWindowsPlatform::GetPlatform()->GetD3D10Device();
-    if (!device) {
-      return false;
-    }
+  RefPtr<ID3D11Device> device;
+  mTexture->GetDevice(getter_AddRefs(device));
+  RefPtr<ID3D11DeviceContext> ctx;
+  device->GetImmediateContext(getter_AddRefs(ctx));
 
-    CD3D10_TEXTURE2D_DESC newDesc(DXGI_FORMAT_B8G8R8A8_UNORM,
-      aSize.width, aSize.height, 1, 1,
-      D3D10_BIND_RENDER_TARGET | D3D10_BIND_SHADER_RESOURCE);
-
-    newDesc.MiscFlags = D3D10_RESOURCE_MISC_SHARED;
-
-    hr = device->CreateTexture2D(&newDesc, nullptr, getter_AddRefs(mTexture10));
-    if (FAILED(hr)) {
-      gfxCriticalError(CriticalLog::DefaultOptions(Factory::ReasonableSurfaceSize(aSize))) << "[D3D10] 2 CreateTexture2D failure " << aSize << " Code: " << gfx::hexa(hr);
-      return false;
-    }
-    mTexture10->SetPrivateDataInterface(sD3D11TextureUsage,
-                                        new TextureMemoryMeasurer(newDesc.Width * newDesc.Height *
-                                                                  (mFormat == SurfaceFormat::A8 ?
-                                                                   1 : 4)));
-
-  }
-
-  // Defer clearing to the next time we lock to avoid an extra (expensive) lock.
-  mNeedsClear = aFlags & ALLOC_CLEAR_BUFFER;
-  mNeedsClearWhite = aFlags & ALLOC_CLEAR_BUFFER_WHITE;
+  D3D11_BOX box;
+  box.front = 0;
+  box.back = 1;
+  box.top = box.left = 0;
+  box.right = aSurface->GetSize().width;
+  box.bottom = aSurface->GetSize().height;
+  ctx->UpdateSubresource(mTexture, 0, &box, sourceMap.mData, sourceMap.mStride, 0);
+  srcSurf->Unmap();
 
   return true;
 }
 
 bool
-TextureClientD3D11::ToSurfaceDescriptor(SurfaceDescriptor& aOutDescriptor)
+D3D10TextureData::UpdateFromSurface(gfx::SourceSurface* aSurface)
 {
-  if (!IsAllocated()) {
+  RefPtr<DataSourceSurface> srcSurf = aSurface->GetDataSurface();
+
+  if (!srcSurf) {
+    gfxCriticalError() << "Failed to GetDataSurface in UpdateFromSurface.";
     return false;
   }
-  RefPtr<IDXGIResource> resource;
-  if (mTexture) {
-    mTexture->QueryInterface((IDXGIResource**)getter_AddRefs(resource));
-  } else {
-    mTexture10->QueryInterface((IDXGIResource**)getter_AddRefs(resource));
-  }
 
-  HANDLE sharedHandle;
-  HRESULT hr = resource->GetSharedHandle(&sharedHandle);
-
-  if (FAILED(hr)) {
-    LOGD3D11("Error getting shared handle for texture.");
+  DataSourceSurface::MappedSurface sourceMap;
+  if (!srcSurf->Map(DataSourceSurface::READ, &sourceMap)) {
+    gfxCriticalError() << "Failed to map source surface for UpdateFromSurface.";
     return false;
   }
 
-  aOutDescriptor = SurfaceDescriptorD3D10((WindowsHandle)sharedHandle, mFormat, mSize);
-  return true;
-}
-
-DXGIYCbCrTextureClient::DXGIYCbCrTextureClient(ISurfaceAllocator* aAllocator,
-                                               TextureFlags aFlags)
-  : TextureClient(aAllocator, aFlags)
-  , mIsLocked(false)
-{
-  MOZ_COUNT_CTOR(DXGIYCbCrTextureClient);
-}
-
-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];
-};
-
-DXGIYCbCrTextureClient::~DXGIYCbCrTextureClient()
-{
-  MOZ_COUNT_DTOR(DXGIYCbCrTextureClient);
-}
-
-void
-DXGIYCbCrTextureClient::FinalizeOnIPDLThread()
-{
-  if (mHoldRefs[0] && mActor) {
-    KeepUntilFullDeallocation(MakeUnique<YCbCrKeepAliveD3D11>(mHoldRefs), true);
-  }
-}
-
-// static
-already_AddRefed<DXGIYCbCrTextureClient>
-DXGIYCbCrTextureClient::Create(ISurfaceAllocator* aAllocator,
-                               TextureFlags aFlags,
-                               IDirect3DTexture9* aTextureY,
-                               IDirect3DTexture9* aTextureCb,
-                               IDirect3DTexture9* aTextureCr,
-                               HANDLE aHandleY,
-                               HANDLE aHandleCb,
-                               HANDLE aHandleCr,
-                               const gfx::IntSize& aSize,
-                               const gfx::IntSize& aSizeY,
-                               const gfx::IntSize& aSizeCbCr)
-{
-  if (!aHandleY || !aHandleCb || !aHandleCr ||
-      !aTextureY || !aTextureCb || !aTextureCr) {
-    return nullptr;
-  }
-
-  aTextureY->SetPrivateData(sD3D11TextureUsage,
-    new TextureMemoryMeasurer(aSizeY.width * aSizeY.height), sizeof(IUnknown*), D3DSPD_IUNKNOWN);
-  aTextureCb->SetPrivateData(sD3D11TextureUsage,
-    new TextureMemoryMeasurer(aSizeCbCr.width * aSizeCbCr.height), sizeof(IUnknown*), D3DSPD_IUNKNOWN);
-  aTextureCr->SetPrivateData(sD3D11TextureUsage,
-    new TextureMemoryMeasurer(aSizeCbCr.width * aSizeCbCr.height), sizeof(IUnknown*), D3DSPD_IUNKNOWN);
+  RefPtr<ID3D10Device> device;
+  mTexture->GetDevice(getter_AddRefs(device));
 
-  RefPtr<DXGIYCbCrTextureClient> texture =
-    new DXGIYCbCrTextureClient(aAllocator, aFlags);
-  texture->mHandles[0] = aHandleY;
-  texture->mHandles[1] = aHandleCb;
-  texture->mHandles[2] = aHandleCr;
-  texture->mHoldRefs[0] = aTextureY;
-  texture->mHoldRefs[1] = aTextureCb;
-  texture->mHoldRefs[2] = aTextureCr;
-  texture->mSize = aSize;
-  texture->mSizeY = aSizeY;
-  texture->mSizeCbCr = aSizeCbCr;
-  return texture.forget();
-}
-
-already_AddRefed<DXGIYCbCrTextureClient>
-DXGIYCbCrTextureClient::Create(ISurfaceAllocator* aAllocator,
-                               TextureFlags aFlags,
-                               ID3D11Texture2D* aTextureY,
-                               ID3D11Texture2D* aTextureCb,
-                               ID3D11Texture2D* aTextureCr,
-                               const gfx::IntSize& aSize,
-                               const gfx::IntSize& aSizeY,
-                               const gfx::IntSize& aSizeCbCr)
-{
-  if (!aTextureY || !aTextureCb || !aTextureCr) {
-    return nullptr;
-  }
-
-  aTextureY->SetPrivateDataInterface(sD3D11TextureUsage,
-    new TextureMemoryMeasurer(aSize.width * aSize.height));
-  aTextureCb->SetPrivateDataInterface(sD3D11TextureUsage,
-    new TextureMemoryMeasurer(aSizeCbCr.width * aSizeCbCr.height));
-  aTextureCr->SetPrivateDataInterface(sD3D11TextureUsage,
-    new TextureMemoryMeasurer(aSizeCbCr.width * aSizeCbCr.height));
-
-  RefPtr<DXGIYCbCrTextureClient> texture =
-    new DXGIYCbCrTextureClient(aAllocator, aFlags);
+  D3D10_BOX box;
+  box.front = 0;
+  box.back = 1;
+  box.top = box.left = 0;
+  box.right = aSurface->GetSize().width;
+  box.bottom = aSurface->GetSize().height;
 
-  RefPtr<IDXGIResource> resource;
-
-  aTextureY->QueryInterface((IDXGIResource**)getter_AddRefs(resource));
-  HRESULT hr = resource->GetSharedHandle(&texture->mHandles[0]);
-  if (FAILED(hr)) {
-    return nullptr;
-  }
-
-  aTextureCb->QueryInterface((IDXGIResource**)getter_AddRefs(resource));
-  hr = resource->GetSharedHandle(&texture->mHandles[1]);
-  if (FAILED(hr)) {
-    return nullptr;
-  }
+  device->UpdateSubresource(mTexture, 0, &box, sourceMap.mData, sourceMap.mStride, 0);
 
-  aTextureCr->QueryInterface((IDXGIResource**)getter_AddRefs(resource));
-  hr = resource->GetSharedHandle(&texture->mHandles[2]);
-  if (FAILED(hr)) {
-    return nullptr;
-  }
+  srcSurf->Unmap();
 
-  texture->mHoldRefs[0] = aTextureY;
-  texture->mHoldRefs[1] = aTextureCb;
-  texture->mHoldRefs[2] = aTextureCr;
-  texture->mSize = aSize;
-  texture->mSizeY = aSizeY;
-  texture->mSizeCbCr = aSizeCbCr;
-  return texture.forget();
-}
-
-bool
-DXGIYCbCrTextureClient::Lock(OpenMode)
-{
-  MOZ_ASSERT(!mIsLocked);
-  if (!IsValid()) {
-    return false;
-  }
-  mIsLocked = true;
   return true;
 }
 
 void
-DXGIYCbCrTextureClient::Unlock()
+D3D11TextureData::FinalizeOnIPDLThread(TextureClient* aWrapper)
 {
-  MOZ_ASSERT(mIsLocked, "Unlock called while the texture is not locked!");
-  mIsLocked = false;
+  aWrapper->KeepUntilFullDeallocation(MakeUnique<TKeepAlive<ID3D11Texture2D>>(mTexture));
 }
 
-bool
-DXGIYCbCrTextureClient::ToSurfaceDescriptor(SurfaceDescriptor& aOutDescriptor)
+void
+D3D10TextureData::FinalizeOnIPDLThread(TextureClient* aWrapper)
 {
-  MOZ_ASSERT(IsValid());
-  if (!IsAllocated()) {
-    return false;
-  }
-
-  aOutDescriptor = SurfaceDescriptorDXGIYCbCr((WindowsHandle)mHandles[0], (WindowsHandle)mHandles[1], (WindowsHandle)mHandles[2],
-                                              GetSize(), mSizeY, mSizeCbCr);
-  return true;
+  aWrapper->KeepUntilFullDeallocation(MakeUnique<TKeepAlive<ID3D10Texture2D>>(mTexture));
 }
 
 DXGITextureHostD3D11::DXGITextureHostD3D11(TextureFlags aFlags,
                                            const SurfaceDescriptorD3D10& aDescriptor)
   : TextureHost(aFlags)
   , mSize(aDescriptor.size())
   , mHandle(aDescriptor.handle())
   , mFormat(aDescriptor.format())
@@ -877,19 +889,17 @@ DXGITextureHostD3D11::Lock()
   mIsLocked = LockD3DTexture(mTextureSource->GetD3D11Texture());
 
   return mIsLocked;
 }
 
 void
 DXGITextureHostD3D11::Unlock()
 {
-  MOZ_ASSERT(mIsLocked);
   UnlockD3DTexture(mTextureSource->GetD3D11Texture());
-  mIsLocked = false;
 }
 
 bool
 DXGITextureHostD3D11::BindTextureSource(CompositableTextureSourceRef& aTexture)
 {
   MOZ_ASSERT(mIsLocked);
   // If Lock was successful we must have a valid TextureSource.
   MOZ_ASSERT(mTextureSource);
@@ -1138,17 +1148,17 @@ DataTextureSourceD3D11::GetD3D11Texture(
 ID3D11ShaderResourceView*
 DataTextureSourceD3D11::GetShaderResourceView()
 {
   if (mIterating) {
     if (!mTileSRVs[mCurrentTile]) {
       if (!mTileTextures[mCurrentTile]) {
         return nullptr;
       }
-      
+
       RefPtr<ID3D11Device> device;
       mTileTextures[mCurrentTile]->GetDevice(getter_AddRefs(device));
       HRESULT hr = device->CreateShaderResourceView(mTileTextures[mCurrentTile], nullptr, getter_AddRefs(mTileSRVs[mCurrentTile]));
       if (FAILED(hr)) {
         gfxCriticalNote << "[D3D11] DataTextureSourceD3D11:GetShaderResourceView CreateSRV failure " << gfx::hexa(hr);
         return nullptr;
       }
     }
@@ -1254,17 +1264,17 @@ SyncObjectD3D11::FinalizeFrame()
 
   if (!mD3D10Texture && mD3D10SyncedTextures.size()) {
     ID3D10Device* device = gfxWindowsPlatform::GetPlatform()->GetD3D10Device();
     if (!device) {
       return;
     }
 
     hr = device->OpenSharedResource(mHandle, __uuidof(ID3D10Texture2D), (void**)(ID3D10Texture2D**)getter_AddRefs(mD3D10Texture));
-    
+
     if (FAILED(hr) || !mD3D10Texture) {
       gfxCriticalError() << "Failed to D3D10 OpenSharedResource for frame finalization: " << hexa(hr);
 
       if (gfxWindowsPlatform::GetPlatform()->DidRenderingDeviceReset()) {
         return;
       }
 
       gfxDevCrash(LogReason::D3D10FinalizeFrame) << "Without device reset: " << hexa(hr);
@@ -1281,17 +1291,17 @@ SyncObjectD3D11::FinalizeFrame()
       MOZ_CRASH("GFX: Cannot get D3D10 KeyedMutex");
     }
   }
 
   if (!mD3D11Texture && mD3D11SyncedTextures.size()) {
     ID3D11Device* device = gfxWindowsPlatform::GetPlatform()->GetD3D11ContentDevice();
 
     hr = device->OpenSharedResource(mHandle, __uuidof(ID3D11Texture2D), (void**)(ID3D11Texture2D**)getter_AddRefs(mD3D11Texture));
-    
+
     if (FAILED(hr) || !mD3D11Texture) {
       gfxCriticalError() << "Failed to D3D11 OpenSharedResource for frame finalization: " << hexa(hr);
 
       if (gfxWindowsPlatform::GetPlatform()->DidRenderingDeviceReset()) {
         return;
       }
 
       gfxDevCrash(LogReason::D3D11FinalizeFrame) << "Without device reset: " << hexa(hr);
--- a/gfx/layers/d3d11/TextureD3D11.h
+++ b/gfx/layers/d3d11/TextureD3D11.h
@@ -1,180 +1,221 @@
 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef MOZILLA_GFX_TEXTURED3D11_H
 #define MOZILLA_GFX_TEXTURED3D11_H
 
+#include "mozilla/gfx/2D.h"
 #include "mozilla/layers/Compositor.h"
 #include "mozilla/layers/TextureClient.h"
 #include "mozilla/layers/TextureHost.h"
 #include "gfxWindowsPlatform.h"
 #include "mozilla/GfxMessageUtils.h"
 #include <d3d11.h>
 #include "d3d9.h"
 #include <vector>
 
 namespace mozilla {
 namespace layers {
 
 class CompositorD3D11;
 
-/**
- * A TextureClient to share a D3D10 texture with the compositor thread.
- * The corresponding TextureHost is DXGITextureHostD3D11
- */
-class TextureClientD3D11 : public TextureClient
+class DXGITextureData : public TextureData
 {
 public:
-  TextureClientD3D11(ISurfaceAllocator* aAllocator,
-                     gfx::SurfaceFormat aFormat,
-                     TextureFlags aFlags);
-
-  virtual ~TextureClientD3D11();
-
-  // Creates a TextureClient and init width.
-  static already_AddRefed<TextureClientD3D11>
-  Create(ISurfaceAllocator* aAllocator,
-         gfx::SurfaceFormat aFormat,
-         TextureFlags aFlags,
-         ID3D11Texture2D* aTexture,
-         gfx::IntSize aSize);
-
-  static already_AddRefed<TextureClientD3D11>
-  Create(ISurfaceAllocator* aAllocator,
-         gfx::SurfaceFormat aFormat,
-         TextureFlags aFlags,
-         ID3D11Device* aDevice,
-         const gfx::IntSize& aSize);
-
-  // TextureClient
-
-  virtual bool IsAllocated() const override { return mTexture || mTexture10; }
-
-  virtual bool Lock(OpenMode aOpenMode) override;
-
-  virtual void Unlock() override;
-
-  virtual bool IsLocked() const override { return mIsLocked; }
-
-  virtual bool ImplementsLocking() const override { return true; }
+  virtual gfx::IntSize GetSize() const override { return mSize; }
+ 
+  virtual gfx::SurfaceFormat GetFormat() const override { return mFormat; }
+ 
+  virtual bool SupportsMoz2D() const override { return true; }
 
   virtual bool HasInternalBuffer() const override { return false; }
 
-  virtual bool ToSurfaceDescriptor(SurfaceDescriptor& aOutDescriptor) override;
+  virtual bool HasSynchronization() const override { return mHasSynchronization; }
+
+  virtual bool Serialize(SurfaceDescriptor& aOutDescrptor) override;
 
-  virtual gfx::IntSize GetSize() const override { return mSize; }
+  static DXGITextureData*
+  Create(gfx::IntSize aSize, gfx::SurfaceFormat aFormat, TextureAllocationFlags aFlags);
+
+protected:
+  bool PrepareDrawTargetInLock(OpenMode aMode);
 
-  virtual gfx::SurfaceFormat GetFormat() const override { return mFormat; }
+  DXGITextureData(gfx::IntSize aSize, gfx::SurfaceFormat aFormat, bool aNeedsClear, bool aNeedsClearWhite);
+
+  virtual void GetDXGIResource(IDXGIResource** aOutResource) = 0;
 
-  virtual bool CanExposeDrawTarget() const override { return true; }
-
-  virtual gfx::DrawTarget* BorrowDrawTarget() override;
+  // Hold on to the DrawTarget because it is expensive to create one each ::Lock.
+  RefPtr<gfx::DrawTarget> mDrawTarget;
+  gfx::IntSize mSize;
+  gfx::SurfaceFormat mFormat;
+  bool mNeedsClear;
+  bool mNeedsClearWhite;
+  bool mHasSynchronization;
+};
 
-  virtual void UpdateFromSurface(gfx::SourceSurface* aSurface) override;
+already_AddRefed<TextureClient>
+CreateDXGITextureClient(gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
+                        TextureFlags atextureFlags, TextureAllocationFlags aFlags,
+                        ISurfaceAllocator* aAllocator);
 
-  virtual bool AllocateForSurface(gfx::IntSize aSize,
-                                  TextureAllocationFlags aFlags = ALLOC_DEFAULT) override;
+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);
 
-  virtual already_AddRefed<TextureClient>
-  CreateSimilar(TextureFlags aFlags = TextureFlags::DEFAULT,
-                TextureAllocationFlags aAllocFlags = ALLOC_DEFAULT) const override;
+  virtual bool UpdateFromSurface(gfx::SourceSurface* aSurface) override;
+
+  virtual bool Lock(OpenMode aMode, FenceHandle*) override;
+
+  virtual void Unlock() override;
+
+  virtual already_AddRefed<gfx::DrawTarget> BorrowDrawTarget() override;
 
-  virtual void SyncWithObject(SyncObject* aSyncObject) override;
+  virtual TextureData*
+  CreateSimilar(ISurfaceAllocator* aAllocator,
+                TextureFlags aFlags,
+                TextureAllocationFlags aAllocFlags) const override;
+
+  // TODO - merge this with the FenceHandle API!
+  virtual void SyncWithObject(SyncObject* aSync) override;
 
   ID3D11Texture2D* GetD3D11Texture() { return mTexture; }
 
-protected:
-  bool AllocateD3D11Surface(ID3D11Device* aDevice, const gfx::IntSize& aSize);
-
-  virtual void FinalizeOnIPDLThread() override;
+  virtual void Deallocate(ISurfaceAllocator* aAllocator) override;
 
-  gfx::IntSize mSize;
-  RefPtr<ID3D10Texture2D> mTexture10;
+  ~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;
-  RefPtr<gfx::DrawTarget> mDrawTarget;
-  gfx::SurfaceFormat mFormat;
-  bool mIsLocked;
-  bool mNeedsClear;
-  bool mNeedsClearWhite;
 };
 
-class DXGIYCbCrTextureClient : public TextureClient
+already_AddRefed<TextureClient>
+CreateD3D11extureClientWithDevice(gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
+                                  TextureFlags aTextureFlags, TextureAllocationFlags aAllocFlags,
+                                  ID3D11Device* aDevice,
+                                  ISurfaceAllocator* aAllocator);
+
+
+class D3D10TextureData : public DXGITextureData
 {
 public:
-  DXGIYCbCrTextureClient(ISurfaceAllocator* aAllocator,
-                         TextureFlags aFlags);
+  static DXGITextureData*
+  Create(gfx::IntSize aSize, gfx::SurfaceFormat aFormat, TextureAllocationFlags aFlags);
+
+  virtual bool Lock(OpenMode aMode, FenceHandle*) override;
+
+  virtual void Unlock() override;
+
+  virtual bool UpdateFromSurface(gfx::SourceSurface* aSurface) override;
+
+  virtual already_AddRefed<gfx::DrawTarget> BorrowDrawTarget() override;
+
+  virtual TextureData*
+  CreateSimilar(ISurfaceAllocator* aAllocator,
+                TextureFlags aFlags,
+                TextureAllocationFlags aAllocFlags) const override;
+
+  // TODO - merge this with the FenceHandle API!
+  virtual void SyncWithObject(SyncObject* aSync) override;
 
-  virtual ~DXGIYCbCrTextureClient();
+  virtual bool ReadBack(TextureReadbackSink* aReadbackSinc) override;
+
+  virtual void Deallocate(ISurfaceAllocator* aAllocator) override;
+
+  ~D3D10TextureData();
+protected:
+  D3D10TextureData(ID3D10Texture2D* aTexture,
+                   gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
+                   bool aNeedsClear, bool aNeedsClearWhite);
 
-  // Creates a TextureClient and init width.
-  static already_AddRefed<DXGIYCbCrTextureClient>
+  virtual void FinalizeOnIPDLThread(TextureClient*) override;
+
+  virtual void GetDXGIResource(IDXGIResource** aOutResource) override;
+
+  RefPtr<ID3D10Texture2D> mTexture;
+};
+
+class DXGIYCbCrTextureData : public TextureData
+{
+public:
+  static DXGIYCbCrTextureData*
   Create(ISurfaceAllocator* aAllocator,
          TextureFlags aFlags,
-         IDirect3DTexture9* aTextureY,
-         IDirect3DTexture9* aTextureCb,
-         IDirect3DTexture9* aTextureCr,
+         IUnknown* aTextureY,
+         IUnknown* aTextureCb,
+         IUnknown* aTextureCr,
          HANDLE aHandleY,
          HANDLE aHandleCb,
          HANDLE aHandleCr,
          const gfx::IntSize& aSize,
          const gfx::IntSize& aSizeY,
          const gfx::IntSize& aSizeCbCr);
 
-  // Creates a TextureClient and init width.
-  static already_AddRefed<DXGIYCbCrTextureClient>
+  static DXGIYCbCrTextureData*
   Create(ISurfaceAllocator* aAllocator,
          TextureFlags aFlags,
+         ID3D11Texture2D* aTextureCb,
          ID3D11Texture2D* aTextureY,
-         ID3D11Texture2D* aTextureCb,
          ID3D11Texture2D* aTextureCr,
          const gfx::IntSize& aSize,
          const gfx::IntSize& aSizeY,
          const gfx::IntSize& aSizeCbCr);
 
-  // TextureClient
-
-  virtual bool IsAllocated() const override{ return !!mHoldRefs[0]; }
+  virtual bool Lock(OpenMode, FenceHandle*) override { return true; }
 
-  virtual bool Lock(OpenMode aOpenMode) override;
+  virtual void Unlock() override {}
 
-  virtual void Unlock() override;
+  virtual bool Serialize(SurfaceDescriptor& aOutDescriptor) override;
 
-  virtual bool IsLocked() const override{ return mIsLocked; }
+  // TODO - DXGIYCbCrTextureClient returned true but that looks like a mistake
+  virtual bool HasInternalBuffer() const override{ return false; }
 
-  virtual bool ToSurfaceDescriptor(SurfaceDescriptor& aOutDescriptor) override;
+  virtual gfx::IntSize GetSize() const override { return mSize; }
 
-  virtual gfx::IntSize GetSize() const
-  {
-    return mSize;
-  }
+  virtual gfx::SurfaceFormat GetFormat() const { return gfx::SurfaceFormat::YUV; }
+
+  virtual bool SupportsMoz2D() const { return false; }
+
+  virtual already_AddRefed<gfx::DrawTarget> BorrowDrawTarget() { return nullptr; }
 
-  virtual bool HasInternalBuffer() const override{ return true; }
+  // This TextureData should not be used in a context where we use CreateSimilar
+  // (ex. component alpha) because the underlying texture is always created by
+  // an external producer.
+  virtual DXGIYCbCrTextureData*
+  CreateSimilar(ISurfaceAllocator*, TextureFlags, TextureAllocationFlags) const override { return nullptr; }
 
-    // This TextureClient should not be used in a context where we use CreateSimilar
-    // (ex. component alpha) because the underlying texture data is always created by
-    // an external producer.
-    virtual already_AddRefed<TextureClient>
-    CreateSimilar(TextureFlags, TextureAllocationFlags) const override{ return nullptr; }
+  virtual void Deallocate(ISurfaceAllocator* aAllocator) override;
+
+  virtual bool UpdateFromSurface(gfx::SourceSurface*) override { return false; }
 
-private:
-  virtual void FinalizeOnIPDLThread() override;
+protected:
+  virtual void FinalizeOnIPDLThread(TextureClient*) override;
 
-  RefPtr<IUnknown> mHoldRefs[3];
-  HANDLE mHandles[3];
-  gfx::IntSize mSize;
-  gfx::IntSize mSizeY;
-  gfx::IntSize mSizeCbCr;
-  bool mIsLocked;
+   RefPtr<IUnknown> mHoldRefs[3];
+   HANDLE mHandles[3];
+   gfx::IntSize mSize;
+   gfx::IntSize mSizeY;
+   gfx::IntSize mSizeCbCr;
 };
 
-
 /**
  * TextureSource that provides with the necessary APIs to be composited by a
  * CompositorD3D11.
  */
 class TextureSourceD3D11
 {
 public:
   TextureSourceD3D11() {}
@@ -262,16 +303,23 @@ protected:
   gfx::SurfaceFormat mFormat;
   TextureFlags mFlags;
   uint32_t mCurrentTile;
   bool mIsTiled;
   bool mIterating;
 
 };
 
+already_AddRefed<TextureClient>
+CreateD3D11TextureClientWithDevice(gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
+                                   TextureFlags aTextureFlags, TextureAllocationFlags aAllocFlags,
+                                   ID3D11Device* aDevice,
+                                   ISurfaceAllocator* aAllocator);
+
+
 /**
  * A TextureHost for shared D3D11 textures.
  */
 class DXGITextureHostD3D11 : public TextureHost
 {
 public:
   DXGITextureHostD3D11(TextureFlags aFlags,
                        const SurfaceDescriptorD3D10& aDescriptor);
@@ -322,17 +370,17 @@ public:
   virtual void SetCompositor(Compositor* aCompositor) override;
 
   virtual gfx::SurfaceFormat GetFormat() const override{ return gfx::SurfaceFormat::YUV; }
 
   virtual bool Lock() override;
 
   virtual void Unlock() override;
 
-  virtual gfx::IntSize GetSize() const override{ return mSize; }
+  virtual gfx::IntSize GetSize() const override { return mSize; }
 
   virtual already_AddRefed<gfx::DataSourceSurface> GetAsSurface() override
   {
     return nullptr;
   }
 
 protected:
   ID3D11Device* GetDevice();