Bug 1540581 - P11. Handle colorspace correctly with D3D11 images. r=mattwoodrow,nical
authorJean-Yves Avenard <jyavenard@mozilla.com>
Thu, 11 Apr 2019 12:38:49 +0000
changeset 527956 bfef6e9e74d53eaa3ef44f27498f31c2b5aee34f
parent 527955 cf9c8ae660ddbc7711844d943097b7ad53edc2d6
child 527957 a0176a275ee5a60ce1bef7bde28055cc49cc2a26
push id11265
push userffxbld-merge
push dateMon, 13 May 2019 10:53:39 +0000
treeherdermozilla-beta@77e0fe8dbdd3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmattwoodrow, nical
bugs1540581
milestone68.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 1540581 - P11. Handle colorspace correctly with D3D11 images. r=mattwoodrow,nical Differential Revision: https://phabricator.services.mozilla.com/D26466
dom/media/platforms/wmf/DXVA2Manager.cpp
gfx/gl/GLBlitHelperD3D.cpp
gfx/gl/SharedSurfaceANGLE.cpp
gfx/gl/SharedSurfaceD3D11Interop.cpp
gfx/layers/D3D11ShareHandleImage.cpp
gfx/layers/D3D11ShareHandleImage.h
gfx/layers/D3D9SurfaceImage.cpp
gfx/layers/d3d11/TextureD3D11.cpp
gfx/layers/d3d11/TextureD3D11.h
gfx/layers/ipc/LayersSurfaces.ipdlh
--- a/dom/media/platforms/wmf/DXVA2Manager.cpp
+++ b/dom/media/platforms/wmf/DXVA2Manager.cpp
@@ -877,18 +877,19 @@ D3D11DXVA2Manager::CreateOutputSample(Re
 
 HRESULT
 D3D11DXVA2Manager::CopyToImage(IMFSample* aVideoSample,
                                const gfx::IntRect& aRegion, Image** aOutImage) {
   NS_ENSURE_TRUE(aVideoSample, E_POINTER);
   NS_ENSURE_TRUE(aOutImage, E_POINTER);
   MOZ_ASSERT(mTextureClientAllocator);
 
-  RefPtr<D3D11ShareHandleImage> image = new D3D11ShareHandleImage(
-      gfx::IntSize(mWidth, mHeight), aRegion, mInputSubType);
+  RefPtr<D3D11ShareHandleImage> image =
+      new D3D11ShareHandleImage(gfx::IntSize(mWidth, mHeight), aRegion,
+                                mInputSubType, gfx::YUVColorSpace::UNKNOWN);
 
   // Retrieve the DXGI_FORMAT for the current video sample.
   RefPtr<IMFMediaBuffer> buffer;
   HRESULT hr = aVideoSample->GetBufferByIndex(0, getter_AddRefs(buffer));
   NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
 
   RefPtr<IMFDXGIBuffer> dxgiBuf;
   hr = buffer->QueryInterface((IMFDXGIBuffer**)getter_AddRefs(dxgiBuf));
--- a/gfx/gl/GLBlitHelperD3D.cpp
+++ b/gfx/gl/GLBlitHelperD3D.cpp
@@ -224,17 +224,17 @@ bool GLBlitHelper::BlitDescriptor(const 
   if (!d3d) return false;
 
   const auto& handle = desc.handle();
   const auto& format = desc.format();
   const auto& clipSize = desc.size();
 
   const auto srcOrigin = OriginPos::BottomLeft;
   const gfx::IntRect clipRect(0, 0, clipSize.width, clipSize.height);
-  const auto colorSpace = gfx::YUVColorSpace::BT601;
+  const auto colorSpace = desc.yUVColorSpace();
 
   if (format != gfx::SurfaceFormat::NV12 &&
       format != gfx::SurfaceFormat::P010 &&
       format != gfx::SurfaceFormat::P016) {
     gfxCriticalError() << "Non-NV12 format for SurfaceDescriptorD3D10: "
                        << uint32_t(format);
     return false;
   }
--- a/gfx/gl/SharedSurfaceANGLE.cpp
+++ b/gfx/gl/SharedSurfaceANGLE.cpp
@@ -144,18 +144,18 @@ void SharedSurface_ANGLEShareHandle::Pro
     return;
   }
 }
 
 bool SharedSurface_ANGLEShareHandle::ToSurfaceDescriptor(
     layers::SurfaceDescriptor* const out_descriptor) {
   gfx::SurfaceFormat format =
       mHasAlpha ? gfx::SurfaceFormat::B8G8R8A8 : gfx::SurfaceFormat::B8G8R8X8;
-  *out_descriptor = layers::SurfaceDescriptorD3D10((WindowsHandle)mShareHandle,
-                                                   format, mSize);
+  *out_descriptor = layers::SurfaceDescriptorD3D10(
+      (WindowsHandle)mShareHandle, format, mSize, gfx::YUVColorSpace::UNKNOWN);
   return true;
 }
 
 class ScopedLockTexture final {
  public:
   explicit ScopedLockTexture(ID3D11Texture2D* texture, bool* succeeded)
       : mIsLocked(false), mTexture(texture) {
     MOZ_ASSERT(NS_IsMainThread(),
--- a/gfx/gl/SharedSurfaceD3D11Interop.cpp
+++ b/gfx/gl/SharedSurfaceD3D11Interop.cpp
@@ -461,18 +461,18 @@ void SharedSurface_D3D11Interop::Produce
 
   mLockedForGL = false;
 }
 
 bool SharedSurface_D3D11Interop::ToSurfaceDescriptor(
     layers::SurfaceDescriptor* const out_descriptor) {
   const auto format =
       (mHasAlpha ? gfx::SurfaceFormat::B8G8R8A8 : gfx::SurfaceFormat::B8G8R8X8);
-  *out_descriptor =
-      layers::SurfaceDescriptorD3D10(WindowsHandle(mDXGIHandle), format, mSize);
+  *out_descriptor = layers::SurfaceDescriptorD3D10(
+      WindowsHandle(mDXGIHandle), format, mSize, gfx::YUVColorSpace::UNKNOWN);
   return true;
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////
 // Factory
 
 /*static*/
 UniquePtr<SurfaceFactory_D3D11Interop> SurfaceFactory_D3D11Interop::Create(
--- a/gfx/layers/D3D11ShareHandleImage.cpp
+++ b/gfx/layers/D3D11ShareHandleImage.cpp
@@ -1,68 +1,69 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
+#include "D3D11ShareHandleImage.h"
+#include <memory>
+#include "DXVA2Manager.h"
 #include "WMF.h"
-#include "D3D11ShareHandleImage.h"
+#include "d3d11.h"
 #include "gfxImageSurface.h"
+#include "gfxPrefs.h"
 #include "gfxWindowsPlatform.h"
+#include "mozilla/gfx/DeviceManagerDx.h"
+#include "mozilla/layers/CompositableClient.h"
+#include "mozilla/layers/CompositableForwarder.h"
 #include "mozilla/layers/TextureClient.h"
 #include "mozilla/layers/TextureD3D11.h"
-#include "mozilla/layers/CompositableClient.h"
-#include "mozilla/layers/CompositableForwarder.h"
-#include "mozilla/gfx/DeviceManagerDx.h"
-#include "d3d11.h"
-#include "gfxPrefs.h"
-#include "DXVA2Manager.h"
-#include <memory>
 
 namespace mozilla {
 namespace layers {
 
 using namespace gfx;
 
 D3D11ShareHandleImage::D3D11ShareHandleImage(const gfx::IntSize& aSize,
                                              const gfx::IntRect& aRect,
-                                             const GUID& aSourceFormat)
+                                             const GUID& aSourceFormat,
+                                             gfx::YUVColorSpace aColorSpace)
     : Image(nullptr, ImageFormat::D3D11_SHARE_HANDLE_TEXTURE),
       mSize(aSize),
       mPictureRect(aRect),
-      mSourceFormat(aSourceFormat)
-
-{}
+      mSourceFormat(aSourceFormat),
+      mYUVColorSpace(aColorSpace) {}
 
 bool D3D11ShareHandleImage::AllocateTexture(D3D11RecycleAllocator* aAllocator,
                                             ID3D11Device* aDevice) {
   if (aAllocator) {
     if (mSourceFormat == MFVideoFormat_NV12 &&
         gfxPrefs::PDMWMFUseNV12Format() &&
         gfx::DeviceManagerDx::Get()->CanUseNV12()) {
-      mTextureClient =
-          aAllocator->CreateOrRecycleClient(gfx::SurfaceFormat::NV12, mSize);
+      mTextureClient = aAllocator->CreateOrRecycleClient(
+          gfx::SurfaceFormat::NV12, mYUVColorSpace, mSize);
     } else if (((mSourceFormat == MFVideoFormat_P010 &&
                  gfx::DeviceManagerDx::Get()->CanUseP010()) ||
                 (mSourceFormat == MFVideoFormat_P016 &&
                  gfx::DeviceManagerDx::Get()->CanUseP016())) &&
                gfxPrefs::PDMWMFUseNV12Format()) {
       mTextureClient = aAllocator->CreateOrRecycleClient(
           mSourceFormat == MFVideoFormat_P010 ? gfx::SurfaceFormat::P010
                                               : gfx::SurfaceFormat::P016,
-          mSize);
+          mYUVColorSpace, mSize);
     } else {
       mTextureClient = aAllocator->CreateOrRecycleClient(
-          gfx::SurfaceFormat::B8G8R8A8, mSize);
+          gfx::SurfaceFormat::B8G8R8A8, gfx::YUVColorSpace::UNKNOWN, mSize);
     }
     if (mTextureClient) {
-      mTexture =
-          static_cast<D3D11TextureData*>(mTextureClient->GetInternalData())
-              ->GetD3D11Texture();
+      D3D11TextureData* textureData =
+          mTextureClient->GetInternalData()->AsD3D11TextureData();
+      MOZ_DIAGNOSTIC_ASSERT(textureData, "Wrong TextureDataType");
+      mTexture = textureData->GetD3D11Texture();
       return true;
     }
     return false;
   } else {
     MOZ_ASSERT(aDevice);
     CD3D11_TEXTURE2D_DESC newDesc(
         DXGI_FORMAT_B8G8R8A8_UNORM, mSize.width, mSize.height, 1, 1,
         D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE);
@@ -187,41 +188,83 @@ D3D11ShareHandleImage::GetAsSourceSurfac
   context->Unmap(softTexture, 0);
   surface->Unmap();
 
   return surface.forget();
 }
 
 ID3D11Texture2D* D3D11ShareHandleImage::GetTexture() const { return mTexture; }
 
-already_AddRefed<TextureClient> D3D11RecycleAllocator::Allocate(
-    gfx::SurfaceFormat aFormat, gfx::IntSize aSize, BackendSelector aSelector,
-    TextureFlags aTextureFlags, TextureAllocationFlags aAllocFlags) {
-  return CreateD3D11TextureClientWithDevice(
-      aSize, aFormat, aTextureFlags, aAllocFlags, mDevice,
-      mSurfaceAllocator->GetTextureForwarder());
-}
+class D3D11TextureClientAllocationHelper
+    : public ITextureClientAllocationHelper {
+ public:
+  D3D11TextureClientAllocationHelper(gfx::SurfaceFormat aFormat,
+                                     gfx::YUVColorSpace aColorSpace,
+                                     const gfx::IntSize& aSize,
+                                     TextureAllocationFlags aAllocFlags,
+                                     ID3D11Device* aDevice,
+                                     TextureFlags aTextureFlags)
+      : ITextureClientAllocationHelper(aFormat, aSize, BackendSelector::Content,
+                                       aTextureFlags, aAllocFlags),
+        mYUVColorSpace(aColorSpace),
+        mDevice(aDevice) {}
+
+  bool IsCompatible(TextureClient* aTextureClient) override {
+    D3D11TextureData* textureData =
+        aTextureClient->GetInternalData()->AsD3D11TextureData();
+    if (!textureData || aTextureClient->GetFormat() != mFormat ||
+        aTextureClient->GetSize() != mSize) {
+      return false;
+    }
+    // TODO: Should we also check for change in the allocation flags if RGBA?
+    return (aTextureClient->GetFormat() != gfx::SurfaceFormat::NV12 &&
+            aTextureClient->GetFormat() != gfx::SurfaceFormat::P010 &&
+            aTextureClient->GetFormat() != gfx::SurfaceFormat::P016) ||
+           (textureData->GetYUVColorSpace() == mYUVColorSpace &&
+            textureData->GetTextureAllocationFlags() == mAllocationFlags);
+  }
+
+  already_AddRefed<TextureClient> Allocate(
+      KnowsCompositor* aAllocator) override {
+    DXGITextureData* data =
+        D3D11TextureData::Create(mSize, mFormat, mAllocationFlags, mDevice);
+    if (!data) {
+      return nullptr;
+    }
+    data->SetYUVColorSpace(mYUVColorSpace);
+    return MakeAndAddRef<TextureClient>(data, mTextureFlags,
+                                        aAllocator->GetTextureForwarder());
+  }
+
+ private:
+  gfx::YUVColorSpace mYUVColorSpace;
+  const RefPtr<ID3D11Device> mDevice;
+};
 
 already_AddRefed<TextureClient> D3D11RecycleAllocator::CreateOrRecycleClient(
-    gfx::SurfaceFormat aFormat, const gfx::IntSize& aSize) {
+    gfx::SurfaceFormat aFormat, gfx::YUVColorSpace aColorSpace,
+    const gfx::IntSize& aSize) {
   // When CompositorDevice or ContentDevice is updated,
   // we could not reuse old D3D11Textures. It could cause video flickering.
   RefPtr<ID3D11Device> device = gfx::DeviceManagerDx::Get()->GetImageDevice();
   if (!!mImageDevice && mImageDevice != device) {
     ShrinkToMinimumSize();
   }
   mImageDevice = device;
 
   TextureAllocationFlags allocFlags = TextureAllocationFlags::ALLOC_DEFAULT;
   if (gfxPrefs::PDMWMFUseSyncTexture() ||
       mDevice == DeviceManagerDx::Get()->GetCompositorDevice()) {
     // If our device is the compositor device, we don't need any synchronization
     // in practice.
     allocFlags = TextureAllocationFlags::ALLOC_MANUAL_SYNCHRONIZATION;
   }
-  RefPtr<TextureClient> textureClient =
-      CreateOrRecycle(aFormat, aSize, BackendSelector::Content,
-                      layers::TextureFlags::DEFAULT, allocFlags);
+
+  D3D11TextureClientAllocationHelper helper(aFormat, aColorSpace, aSize,
+                                            allocFlags, mDevice,
+                                            layers::TextureFlags::DEFAULT);
+
+  RefPtr<TextureClient> textureClient = CreateOrRecycle(helper);
   return textureClient.forget();
 }
 
 }  // namespace layers
 }  // namespace mozilla
--- a/gfx/layers/D3D11ShareHandleImage.h
+++ b/gfx/layers/D3D11ShareHandleImage.h
@@ -2,70 +2,73 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef GFX_D311_SHARE_HANDLE_IMAGE_H
 #define GFX_D311_SHARE_HANDLE_IMAGE_H
 
-#include "mozilla/RefPtr.h"
 #include "ImageContainer.h"
 #include "d3d11.h"
+#include "mozilla/Atomics.h"
+#include "mozilla/RefPtr.h"
+#include "mozilla/gfx/Types.h"
 #include "mozilla/layers/TextureClient.h"
+#include "mozilla/layers/TextureClientRecycleAllocator.h"
 #include "mozilla/layers/TextureD3D11.h"
-#include "mozilla/layers/TextureClientRecycleAllocator.h"
 
 namespace mozilla {
 namespace layers {
 
-class D3D11RecycleAllocator : public TextureClientRecycleAllocator {
+class D3D11RecycleAllocator final : public TextureClientRecycleAllocator {
  public:
   D3D11RecycleAllocator(KnowsCompositor* aAllocator, ID3D11Device* aDevice)
       : TextureClientRecycleAllocator(aAllocator), mDevice(aDevice) {}
 
   already_AddRefed<TextureClient> CreateOrRecycleClient(
-      gfx::SurfaceFormat aFormat, const gfx::IntSize& aSize);
+      gfx::SurfaceFormat aFormat, gfx::YUVColorSpace aColorSpace,
+      const gfx::IntSize& aSize);
 
  protected:
-  already_AddRefed<TextureClient> Allocate(
-      gfx::SurfaceFormat aFormat, gfx::IntSize aSize, BackendSelector aSelector,
-      TextureFlags aTextureFlags, TextureAllocationFlags aAllocFlags) override;
-
   RefPtr<ID3D11Device> mDevice;
   /**
    * Used for checking if CompositorDevice/ContentDevice is updated.
    */
   RefPtr<ID3D11Device> mImageDevice;
 };
 
 // Image class that wraps a ID3D11Texture2D. This class copies the image
 // passed into SetData(), so that it can be accessed from other D3D devices.
 // This class also manages the synchronization of the copy, to ensure the
 // resource is ready to use.
 class D3D11ShareHandleImage final : public Image {
  public:
   D3D11ShareHandleImage(const gfx::IntSize& aSize, const gfx::IntRect& aRect,
-                        const GUID& aSourceFormat);
+                        const GUID& aSourceFormat,
+                        gfx::YUVColorSpace aColorSpace);
   virtual ~D3D11ShareHandleImage() = default;
 
   bool AllocateTexture(D3D11RecycleAllocator* aAllocator,
                        ID3D11Device* aDevice);
 
   gfx::IntSize GetSize() const override;
   already_AddRefed<gfx::SourceSurface> GetAsSourceSurface() override;
   TextureClient* GetTextureClient(KnowsCompositor* aForwarder) override;
   gfx::IntRect GetPictureRect() const override { return mPictureRect; }
 
   ID3D11Texture2D* GetTexture() const;
 
+  gfx::YUVColorSpace GetYUVColorSpace() const { return mYUVColorSpace; }
+
  private:
   gfx::IntSize mSize;
   gfx::IntRect mPictureRect;
   const GUID mSourceFormat;
+  gfx::YUVColorSpace mYUVColorSpace;
   RefPtr<TextureClient> mTextureClient;
   RefPtr<ID3D11Texture2D> mTexture;
 };
 
 }  // namespace layers
 }  // namespace mozilla
 
 #endif  // GFX_D3DSURFACEIMAGE_H
--- a/gfx/layers/D3D9SurfaceImage.cpp
+++ b/gfx/layers/D3D9SurfaceImage.cpp
@@ -75,18 +75,22 @@ already_AddRefed<IDirect3DSurface9> DXGI
   RefPtr<IDirect3DSurface9> textureSurface;
   HRESULT hr = mTexture->GetSurfaceLevel(0, getter_AddRefs(textureSurface));
   NS_ENSURE_TRUE(SUCCEEDED(hr), nullptr);
 
   return textureSurface.forget();
 }
 
 bool DXGID3D9TextureData::Serialize(SurfaceDescriptor& aOutDescriptor) {
-  aOutDescriptor =
-      SurfaceDescriptorD3D10((WindowsHandle)(mHandle), mFormat, GetSize());
+  // In reality, with D3D9 we will only ever deal with RGBA textures.
+  bool isYUV = mFormat == SurfaceFormat::NV12 ||
+               mFormat == SurfaceFormat::P010 || mFormat == SurfaceFormat::P016;
+  aOutDescriptor = SurfaceDescriptorD3D10(
+      (WindowsHandle)(mHandle), mFormat, GetSize(),
+      isYUV ? gfx::YUVColorSpace::BT601 : gfx::YUVColorSpace::UNKNOWN);
   return true;
 }
 
 D3D9SurfaceImage::D3D9SurfaceImage()
     : Image(nullptr, ImageFormat::D3D9_RGB32_TEXTURE),
       mSize(0, 0),
       mShareHandle(0),
       mValid(true) {}
--- a/gfx/layers/d3d11/TextureD3D11.cpp
+++ b/gfx/layers/d3d11/TextureD3D11.cpp
@@ -261,22 +261,23 @@ DXGITextureData::DXGITextureData(gfx::In
       mFormat(aFormat),
       mNeedsClear(aNeedsClear),
       mNeedsClearWhite(aNeedsClearWhite),
       mHasSynchronization(false),
       mIsForOutOfBandContent(aIsForOutOfBandContent) {}
 
 D3D11TextureData::D3D11TextureData(ID3D11Texture2D* aTexture,
                                    gfx::IntSize aSize,
-                                   gfx::SurfaceFormat aFormat, bool aNeedsClear,
-                                   bool aNeedsClearWhite,
-                                   bool aIsForOutOfBandContent)
-    : DXGITextureData(aSize, aFormat, aNeedsClear, aNeedsClearWhite,
-                      aIsForOutOfBandContent),
-      mTexture(aTexture) {
+                                   gfx::SurfaceFormat aFormat,
+                                   TextureAllocationFlags aFlags)
+    : DXGITextureData(aSize, aFormat, aFlags & ALLOC_CLEAR_BUFFER,
+                      aFlags & ALLOC_CLEAR_BUFFER_WHITE,
+                      aFlags & ALLOC_FOR_OUT_OF_BAND_CONTENT),
+      mTexture(aTexture),
+      mAllocationFlags(aFlags) {
   MOZ_ASSERT(aTexture);
   mHasSynchronization = HasKeyedMutex(aTexture);
 }
 
 static void DestroyDrawTarget(RefPtr<DrawTarget>& aDT,
                               RefPtr<ID3D11Texture2D>& aTexture) {
   // 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
@@ -382,18 +383,18 @@ bool DXGITextureData::SerializeSpecific(
   }
   HANDLE sharedHandle;
   HRESULT hr = resource->GetSharedHandle(&sharedHandle);
   if (FAILED(hr)) {
     LOGD3D11("Error getting shared handle for texture.");
     return false;
   }
 
-  *aOutDesc =
-      SurfaceDescriptorD3D10((WindowsHandle)sharedHandle, mFormat, mSize);
+  *aOutDesc = SurfaceDescriptorD3D10((WindowsHandle)sharedHandle, mFormat,
+                                     mSize, mYUVColorSpace);
   return true;
 }
 
 bool DXGITextureData::Serialize(SurfaceDescriptor& aOutDescriptor) {
   SurfaceDescriptorD3D10 desc;
   if (!SerializeSpecific(&desc)) return false;
 
   aOutDescriptor = std::move(desc);
@@ -529,20 +530,17 @@ DXGITextureData* D3D11TextureData::Creat
     if (!LockD3DTexture(texture11.get())) {
       return nullptr;
     }
     UnlockD3DTexture(texture11.get());
   }
   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,
-                              aFlags & ALLOC_FOR_OUT_OF_BAND_CONTENT);
+  return new D3D11TextureData(texture11, aSize, aFormat, aFlags);
 }
 
 DXGITextureData* D3D11TextureData::Create(IntSize aSize, SurfaceFormat aFormat,
                                           TextureAllocationFlags aFlags,
                                           ID3D11Device* aDevice) {
   return D3D11TextureData::Create(aSize, aFormat, nullptr, aFlags, aDevice);
 }
 
@@ -558,28 +556,16 @@ DXGITextureData* D3D11TextureData::Creat
                                   aSurface, aFlags, aDevice);
 }
 
 void D3D11TextureData::Deallocate(LayersIPCChannel* aAllocator) {
   mDrawTarget = nullptr;
   mTexture = nullptr;
 }
 
-already_AddRefed<TextureClient> CreateD3D11TextureClientWithDevice(
-    IntSize aSize, SurfaceFormat aFormat, TextureFlags aTextureFlags,
-    TextureAllocationFlags aAllocFlags, ID3D11Device* aDevice,
-    LayersIPCChannel* aAllocator) {
-  TextureData* data =
-      D3D11TextureData::Create(aSize, aFormat, aAllocFlags, aDevice);
-  if (!data) {
-    return nullptr;
-  }
-  return MakeAndAddRef<TextureClient>(data, aTextureFlags, aAllocator);
-}
-
 TextureData* D3D11TextureData::CreateSimilar(
     LayersIPCChannel* aAllocator, LayersBackend aLayersBackend,
     TextureFlags aFlags, TextureAllocationFlags aAllocFlags) const {
   return D3D11TextureData::Create(mSize, mFormat, aAllocFlags);
 }
 
 void D3D11TextureData::GetDXGIResource(IDXGIResource** aOutResource) {
   mTexture->QueryInterface(aOutResource);
@@ -762,16 +748,17 @@ bool D3D11TextureData::UpdateFromSurface
 }
 
 DXGITextureHostD3D11::DXGITextureHostD3D11(
     TextureFlags aFlags, const SurfaceDescriptorD3D10& aDescriptor)
     : TextureHost(aFlags),
       mSize(aDescriptor.size()),
       mHandle(aDescriptor.handle()),
       mFormat(aDescriptor.format()),
+      mYUVColorSpace(aDescriptor.yUVColorSpace()),
       mIsLocked(false) {}
 
 bool DXGITextureHostD3D11::EnsureTexture() {
   RefPtr<ID3D11Device> device;
   if (mTexture) {
     mTexture->GetDevice(getter_AddRefs(device));
     if (device == DeviceManagerDx::Get()->GetCompositorDevice()) {
       NS_WARNING("Incompatible texture.");
@@ -1070,21 +1057,21 @@ void DXGITextureHostD3D11::PushDisplayIt
       aBuilder.PushImage(aBounds, aClip, true, aFilter, aImageKeys[0],
                          !(mFlags & TextureFlags::NON_PREMULTIPLIED));
       break;
     }
     case gfx::SurfaceFormat::P010:
     case gfx::SurfaceFormat::P016:
     case gfx::SurfaceFormat::NV12: {
       MOZ_ASSERT(aImageKeys.length() == 2);
-      aBuilder.PushNV12Image(
-          aBounds, aClip, true, aImageKeys[0], aImageKeys[1],
-          GetFormat() == gfx::SurfaceFormat::NV12 ? wr::ColorDepth::Color8
-                                                  : wr::ColorDepth::Color16,
-          wr::ToWrYuvColorSpace(YUVColorSpace::BT601), aFilter);
+      aBuilder.PushNV12Image(aBounds, aClip, true, aImageKeys[0], aImageKeys[1],
+                             GetFormat() == gfx::SurfaceFormat::NV12
+                                 ? wr::ColorDepth::Color8
+                                 : wr::ColorDepth::Color16,
+                             wr::ToWrYuvColorSpace(mYUVColorSpace), aFilter);
       break;
     }
     default: {
       MOZ_ASSERT_UNREACHABLE("unexpected to be called");
     }
   }
 }
 
--- a/gfx/layers/d3d11/TextureD3D11.h
+++ b/gfx/layers/d3d11/TextureD3D11.h
@@ -2,26 +2,27 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef MOZILLA_GFX_TEXTURED3D11_H
 #define MOZILLA_GFX_TEXTURED3D11_H
 
+#include <d3d11.h>
+#include <vector>
+#include "d3d9.h"
+#include "gfxWindowsPlatform.h"
+#include "mozilla/GfxMessageUtils.h"
+#include "mozilla/Maybe.h"
 #include "mozilla/gfx/2D.h"
 #include "mozilla/layers/Compositor.h"
 #include "mozilla/layers/SyncObject.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 gl {
 class GLBlitHelper;
 }
 
 namespace layers {
 
@@ -48,30 +49,39 @@ class DXGITextureData : public TextureDa
 
   bool SerializeSpecific(SurfaceDescriptorD3D10* aOutDesc);
   bool Serialize(SurfaceDescriptor& aOutDescrptor) override;
   void GetSubDescriptor(GPUVideoSubDescriptor* aOutDesc) override;
 
   static DXGITextureData* Create(gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
                                  TextureAllocationFlags aFlags);
 
+  gfx::YUVColorSpace GetYUVColorSpace() const { return mYUVColorSpace; }
+  void SetYUVColorSpace(gfx::YUVColorSpace aColorSpace) {
+    mYUVColorSpace = aColorSpace;
+  }
+
+  gfx::IntSize GetSize() const { return mSize; }
+  gfx::SurfaceFormat GetSurfaceFormat() const { return mFormat; }
+
  protected:
   bool PrepareDrawTargetInLock(OpenMode aMode);
 
   DXGITextureData(gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
                   bool aNeedsClear, bool aNeedsClearWhite,
                   bool aIsForOutOfBandContent);
 
   virtual void GetDXGIResource(IDXGIResource** aOutResource) = 0;
 
   // Hold on to the DrawTarget because it is expensive to create one each
   // ::Lock.
   RefPtr<gfx::DrawTarget> mDrawTarget;
   gfx::IntSize mSize;
   gfx::SurfaceFormat mFormat;
+  gfx::YUVColorSpace mYUVColorSpace = gfx::YUVColorSpace::UNKNOWN;
   bool mNeedsClear;
   bool mNeedsClearWhite;
   bool mHasSynchronization;
   bool mIsForOutOfBandContent;
 };
 
 class D3D11TextureData : public DXGITextureData {
  public:
@@ -98,38 +108,37 @@ class D3D11TextureData : public DXGIText
   void SyncWithObject(SyncObjectClient* aSyncObject) override;
 
   ID3D11Texture2D* GetD3D11Texture() { return mTexture; }
 
   void Deallocate(LayersIPCChannel* aAllocator) override;
 
   D3D11TextureData* AsD3D11TextureData() override { return this; }
 
+  TextureAllocationFlags GetTextureAllocationFlags() const {
+    return mAllocationFlags;
+  }
+
   virtual ~D3D11TextureData();
 
  protected:
   D3D11TextureData(ID3D11Texture2D* aTexture, gfx::IntSize aSize,
-                   gfx::SurfaceFormat aFormat, bool aNeedsClear,
-                   bool aNeedsClearWhite, bool aIsForOutOfBandContent);
+                   gfx::SurfaceFormat aFormat, TextureAllocationFlags aFlags);
 
   void GetDXGIResource(IDXGIResource** aOutResource) override;
 
   static DXGITextureData* Create(gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
                                  gfx::SourceSurface* aSurface,
                                  TextureAllocationFlags aAllocFlags,
                                  ID3D11Device* aDevice = nullptr);
 
   RefPtr<ID3D11Texture2D> mTexture;
+  const TextureAllocationFlags mAllocationFlags;
 };
 
-already_AddRefed<TextureClient> CreateD3D11extureClientWithDevice(
-    gfx::IntSize aSize, gfx::SurfaceFormat aFormat, TextureFlags aTextureFlags,
-    TextureAllocationFlags aAllocFlags, ID3D11Device* aDevice,
-    LayersIPCChannel* aAllocator);
-
 class DXGIYCbCrTextureData : public TextureData {
   friend class gl::GLBlitHelper;
 
  public:
   static DXGIYCbCrTextureData* Create(
       IDirect3DTexture9* aTextureY, IDirect3DTexture9* aTextureCb,
       IDirect3DTexture9* aTextureCr, HANDLE aHandleY, HANDLE aHandleCb,
       HANDLE aHandleCr, const gfx::IntSize& aSize, const gfx::IntSize& aSizeY,
@@ -305,21 +314,16 @@ class DataTextureSourceD3D11 : public Da
   // the cases where we want to perform texture uploads through the
   // DataTextureSource interface, and the cases where we wrap the texture around
   // an existing DXGI handle in which case we should not use it as a
   // DataTextureSource. This member differentiates the two scenarios. When it is
   // false the texture "pretends" to not be a DataTextureSource.
   bool mAllowTextureUploads;
 };
 
-already_AddRefed<TextureClient> CreateD3D11TextureClientWithDevice(
-    gfx::IntSize aSize, gfx::SurfaceFormat aFormat, TextureFlags aTextureFlags,
-    TextureAllocationFlags aAllocFlags, ID3D11Device* aDevice,
-    LayersIPCChannel* aAllocator);
-
 /**
  * A TextureHost for shared D3D11 textures.
  */
 class DXGITextureHostD3D11 : public TextureHost {
  public:
   DXGITextureHostD3D11(TextureFlags aFlags,
                        const SurfaceDescriptorD3D10& aDescriptor);
 
@@ -334,16 +338,19 @@ class DXGITextureHostD3D11 : public Text
 
   bool Lock() override;
   void Unlock() override;
 
   bool LockWithoutCompositor() override;
   void UnlockWithoutCompositor() override;
 
   gfx::IntSize GetSize() const override { return mSize; }
+  gfx::YUVColorSpace GetYUVColorSpace() const override {
+    return mYUVColorSpace;
+  }
 
   already_AddRefed<gfx::DataSourceSurface> GetAsSurface() override;
 
   void CreateRenderTexture(
       const wr::ExternalImageId& aExternalImageId) override;
 
   uint32_t NumSubTextures() const override;
 
@@ -370,16 +377,17 @@ class DXGITextureHostD3D11 : public Text
   bool EnsureTexture();
 
   RefPtr<ID3D11Device> mDevice;
   RefPtr<ID3D11Texture2D> mTexture;
   RefPtr<DataTextureSourceD3D11> mTextureSource;
   gfx::IntSize mSize;
   WindowsHandle mHandle;
   gfx::SurfaceFormat mFormat;
+  const gfx::YUVColorSpace mYUVColorSpace;
   bool mIsLocked;
 };
 
 class DXGIYCbCrTextureHostD3D11 : public TextureHost {
  public:
   DXGIYCbCrTextureHostD3D11(TextureFlags aFlags,
                             const SurfaceDescriptorDXGIYCbCr& aDescriptor);
 
--- a/gfx/layers/ipc/LayersSurfaces.ipdlh
+++ b/gfx/layers/ipc/LayersSurfaces.ipdlh
@@ -29,16 +29,17 @@ struct SurfaceDescriptorDIB {
   // gfxWindowsSurface*
   uintptr_t surface;
 };
 
 struct SurfaceDescriptorD3D10 {
   WindowsHandle handle;
   SurfaceFormat format;
   IntSize size;
+  YUVColorSpace yUVColorSpace;
 };
 
 struct SurfaceDescriptorDXGIYCbCr {
   WindowsHandle handleY;
   WindowsHandle handleCb;
   WindowsHandle handleCr;
   IntSize size;
   IntSize sizeY;