Bug 1415763 - Fix DXGIYCbCrTextureData as to deliver YUVColorSpace r=mattwoodrow
authorsotaro <sotaro.ikeda.g@gmail.com>
Fri, 10 Nov 2017 18:15:54 +0900
changeset 444433 c65b327ad81bb2c10f2e02400c69c6127a050633
parent 444432 cd5fb16264419253aa515e80b4d6aeed41ac0fbe
child 444434 d32f44d0cdba89134bf75004340b5c456af89ad6
push id1618
push userCallek@gmail.com
push dateThu, 11 Jan 2018 17:45:48 +0000
treeherdermozilla-release@882ca853e05a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmattwoodrow
bugs1415763
milestone58.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 1415763 - Fix DXGIYCbCrTextureData as to deliver YUVColorSpace r=mattwoodrow
gfx/layers/D3D11YCbCrImage.cpp
gfx/layers/D3D11YCbCrImage.h
gfx/layers/IMFYCbCrImage.cpp
gfx/layers/client/TextureClient.h
gfx/layers/d3d11/TextureD3D11.cpp
gfx/layers/d3d11/TextureD3D11.h
gfx/layers/ipc/LayersSurfaces.ipdlh
--- a/gfx/layers/D3D11YCbCrImage.cpp
+++ b/gfx/layers/D3D11YCbCrImage.cpp
@@ -11,16 +11,32 @@
 #include "mozilla/layers/CompositableForwarder.h"
 #include "mozilla/layers/TextureD3D11.h"
 
 using namespace mozilla::gfx;
 
 namespace mozilla {
 namespace layers {
 
+class DXGIYCbCrTextureAllocationHelper : public ITextureClientAllocationHelper
+{
+public:
+  DXGIYCbCrTextureAllocationHelper(const PlanarYCbCrData& aData,
+                                   TextureFlags aTextureFlags,
+                                   ID3D11Device* aDevice);
+
+  bool IsCompatible(TextureClient* aTextureClient) override;
+
+  already_AddRefed<TextureClient> Allocate(KnowsCompositor* aAllocator) override;
+
+protected:
+  const PlanarYCbCrData& mData;
+  RefPtr<ID3D11Device> mDevice;
+};
+
 D3D11YCbCrImage::D3D11YCbCrImage()
  : Image(NULL, ImageFormat::D3D11_YCBCR_IMAGE)
 {
 }
 
 D3D11YCbCrImage::~D3D11YCbCrImage() { }
 
 bool
@@ -34,28 +50,28 @@ D3D11YCbCrImage::SetData(KnowsCompositor
   mCbCrSize = aData.mCbCrSize;
   mColorSpace = aData.mYUVColorSpace;
 
   D3D11YCbCrRecycleAllocator* allocator =
     aContainer->GetD3D11YCbCrRecycleAllocator(aAllocator);
   if (!allocator) {
     return false;
   }
-  allocator->SetSizes(aData.mYSize, aData.mCbCrSize);
 
-  mTextureClient = allocator->CreateOrRecycle(SurfaceFormat::A8,
-                                              mYSize,
-                                              BackendSelector::Content,
-                                              TextureFlags::DEFAULT);
+  {
+    DXGIYCbCrTextureAllocationHelper helper(aData, TextureFlags::DEFAULT, allocator->GetDevice());
+    mTextureClient = allocator->CreateOrRecycle(helper);
+  }
+
   if (!mTextureClient) {
     return false;
   }
 
-  DXGIYCbCrTextureData *data =
-    static_cast<DXGIYCbCrTextureData*>(mTextureClient->GetInternalData());
+  DXGIYCbCrTextureData* data =
+    mTextureClient->GetInternalData()->AsDXGIYCbCrTextureData();
 
   ID3D11Texture2D* textureY = data->GetD3D11Texture(0);
   ID3D11Texture2D* textureCb = data->GetD3D11Texture(1);
   ID3D11Texture2D* textureCr = data->GetD3D11Texture(2);
 
   RefPtr<ID3D10Multithread> mt;
   HRESULT hr = allocator->GetDevice()->QueryInterface(
     (ID3D10Multithread**)getter_AddRefs(mt));
@@ -119,17 +135,17 @@ D3D11YCbCrImage::GetTextureClient(KnowsC
 }
 
 const DXGIYCbCrTextureData*
 D3D11YCbCrImage::GetData() const
 {
   if (!mTextureClient)
     return nullptr;
 
-  return static_cast<DXGIYCbCrTextureData*>(mTextureClient->GetInternalData());
+  return mTextureClient->GetInternalData()->AsDXGIYCbCrTextureData();
 }
 
 already_AddRefed<SourceSurface>
 D3D11YCbCrImage::GetAsSourceSurface()
 {
   if (!mTextureClient) {
     gfxWarning()
       << "GetAsSourceSurface() called on uninitialized D3D11YCbCrImage.";
@@ -138,18 +154,18 @@ D3D11YCbCrImage::GetAsSourceSurface()
 
   gfx::IntSize size(mPictureRect.Size());
   gfx::SurfaceFormat format =
     gfx::ImageFormatToSurfaceFormat(gfxVars::OffscreenFormat());
   HRESULT hr;
 
   PlanarYCbCrData data;
 
-  DXGIYCbCrTextureData *dxgiData =
-    static_cast<DXGIYCbCrTextureData*>(mTextureClient->GetInternalData());
+  DXGIYCbCrTextureData* dxgiData =
+    mTextureClient->GetInternalData()->AsDXGIYCbCrTextureData();
 
   if (!dxgiData) {
     gfxCriticalError() << "Failed to get texture client internal data.";
     return nullptr;
   }
 
   RefPtr<ID3D11Texture2D> texY = dxgiData->GetD3D11Texture(0);
   RefPtr<ID3D11Texture2D> texCb = dxgiData->GetD3D11Texture(1);
@@ -269,37 +285,49 @@ D3D11YCbCrImage::GetAsSourceSurface()
 
   ctx->Unmap(softTexY, 0);
   ctx->Unmap(softTexCb, 0);
   ctx->Unmap(softTexCr, 0);
 
   return surface.forget();
 }
 
-void
-D3D11YCbCrRecycleAllocator::SetSizes(const gfx::IntSize& aYSize,
-                                     const gfx::IntSize& aCbCrSize)
+DXGIYCbCrTextureAllocationHelper::DXGIYCbCrTextureAllocationHelper(const PlanarYCbCrData& aData,
+                                                                   TextureFlags aTextureFlags,
+                                                                   ID3D11Device* aDevice)
+  : ITextureClientAllocationHelper(gfx::SurfaceFormat::YUV,
+                                   aData.mYSize,
+                                   BackendSelector::Content,
+                                   aTextureFlags,
+                                   ALLOC_DEFAULT)
+  , mData(aData)
+  , mDevice(aDevice)
 {
-  mYSize = Some(aYSize);
-  mCbCrSize = Some(aCbCrSize);
+}
+
+bool
+DXGIYCbCrTextureAllocationHelper::IsCompatible(TextureClient* aTextureClient)
+{
+  MOZ_ASSERT(aTextureClient->GetFormat() == gfx::SurfaceFormat::YUV);
+
+  DXGIYCbCrTextureData* dxgiData = aTextureClient->GetInternalData()->AsDXGIYCbCrTextureData();
+  if (!dxgiData ||
+      aTextureClient->GetSize() != mData.mYSize ||
+      dxgiData->GetYSize() != mData.mYSize ||
+      dxgiData->GetCbCrSize() != mData.mCbCrSize ||
+      dxgiData->GetYUVColorSpace() != mData.mYUVColorSpace) {
+    return false;
+  }
+  return true;
 }
 
 already_AddRefed<TextureClient>
-D3D11YCbCrRecycleAllocator::Allocate(SurfaceFormat aFormat,
-                                     IntSize aSize,
-                                     BackendSelector aSelector,
-                                     TextureFlags aTextureFlags,
-                                     TextureAllocationFlags aAllocFlags)
+DXGIYCbCrTextureAllocationHelper::Allocate(KnowsCompositor* aAllocator)
 {
-  MOZ_ASSERT(aFormat == SurfaceFormat::A8);
-
-  gfx::IntSize YSize = mYSize.refOr(aSize);
-  gfx::IntSize CbCrSize =
-    mCbCrSize.refOr(gfx::IntSize(YSize.width, YSize.height));
-  CD3D11_TEXTURE2D_DESC newDesc(DXGI_FORMAT_R8_UNORM, YSize.width, YSize.height,
+  CD3D11_TEXTURE2D_DESC newDesc(DXGI_FORMAT_R8_UNORM, mData.mYSize.width, mData.mYSize.height,
                                 1, 1);
   newDesc.MiscFlags = D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX;
 
   RefPtr<ID3D10Multithread> mt;
   HRESULT hr = mDevice->QueryInterface(
     (ID3D10Multithread**)getter_AddRefs(mt));
 
   if (FAILED(hr) || !mt) {
@@ -313,33 +341,45 @@ D3D11YCbCrRecycleAllocator::Allocate(Sur
   }
 
   D3D11MTAutoEnter mtAutoEnter(mt.forget());
 
   RefPtr<ID3D11Texture2D> textureY;
   hr = mDevice->CreateTexture2D(&newDesc, nullptr, getter_AddRefs(textureY));
   NS_ENSURE_TRUE(SUCCEEDED(hr), nullptr);
 
-  newDesc.Width = CbCrSize.width;
-  newDesc.Height = CbCrSize.height;
+  newDesc.Width = mData.mCbCrSize.width;
+  newDesc.Height = mData.mCbCrSize.height;
 
   RefPtr<ID3D11Texture2D> textureCb;
   hr = mDevice->CreateTexture2D(&newDesc, nullptr, getter_AddRefs(textureCb));
   NS_ENSURE_TRUE(SUCCEEDED(hr), nullptr);
 
   RefPtr<ID3D11Texture2D> textureCr;
   hr = mDevice->CreateTexture2D(&newDesc, nullptr, getter_AddRefs(textureCr));
   NS_ENSURE_TRUE(SUCCEEDED(hr), nullptr);
 
   return TextureClient::CreateWithData(
     DXGIYCbCrTextureData::Create(
       textureY,
       textureCb,
       textureCr,
-      aSize,
-      YSize,
-      CbCrSize),
-    TextureFlags::DEFAULT,
-    mSurfaceAllocator->GetTextureForwarder());
+      mData.mYSize,
+      mData.mYSize,
+      mData.mCbCrSize,
+      mData.mYUVColorSpace),
+    mTextureFlags,
+    aAllocator->GetTextureForwarder());
+}
+
+already_AddRefed<TextureClient>
+D3D11YCbCrRecycleAllocator::Allocate(SurfaceFormat aFormat,
+                                     IntSize aSize,
+                                     BackendSelector aSelector,
+                                     TextureFlags aTextureFlags,
+                                     TextureAllocationFlags aAllocFlags)
+{
+  MOZ_ASSERT_UNREACHABLE("unexpected to be called");
+  return nullptr;
 }
 
 } // namespace layers
 } // namespace mozilla
--- a/gfx/layers/D3D11YCbCrImage.h
+++ b/gfx/layers/D3D11YCbCrImage.h
@@ -29,29 +29,26 @@ public:
                                       ID3D11Device* aDevice)
     : TextureClientRecycleAllocator(aAllocator)
     , mDevice(aDevice)
   {
   }
 
   ID3D11Device* GetDevice() { return mDevice; }
   KnowsCompositor* GetAllocator() { return mSurfaceAllocator; }
-  void SetSizes(const gfx::IntSize& aYSize, const gfx::IntSize& aCbCrSize);
 
 protected:
   already_AddRefed<TextureClient>
   Allocate(gfx::SurfaceFormat aFormat,
            gfx::IntSize aSize,
            BackendSelector aSelector,
            TextureFlags aTextureFlags,
            TextureAllocationFlags aAllocFlags) override;
 
   RefPtr<ID3D11Device> mDevice;
-  Maybe<gfx::IntSize> mYSize;
-  Maybe<gfx::IntSize> mCbCrSize;
 };
 
 class D3D11YCbCrImage : public Image
 {
   friend class gl::GLBlitHelper;
 public:
   D3D11YCbCrImage();
   virtual ~D3D11YCbCrImage();
--- a/gfx/layers/IMFYCbCrImage.cpp
+++ b/gfx/layers/IMFYCbCrImage.cpp
@@ -182,17 +182,18 @@ IMFYCbCrImage::GetD3D11TextureData(Data 
 
     box.right = aData.mCbCrSize.width;
     box.bottom = aData.mCbCrSize.height;
     ctx->UpdateSubresource(textureCb, 0, &box, aData.mCbChannel, aData.mCbCrStride, 0);
     ctx->UpdateSubresource(textureCr, 0, &box, aData.mCrChannel, aData.mCbCrStride, 0);
   }
 
   return DXGIYCbCrTextureData::Create(textureY, textureCb, textureCr,
-                                      aSize, aData.mYSize, aData.mCbCrSize);
+                                      aSize, aData.mYSize, aData.mCbCrSize,
+                                      aData.mYUVColorSpace);
 }
 
 TextureClient*
 IMFYCbCrImage::GetD3D11TextureClient(KnowsCompositor* aForwarder)
 {
   DXGIYCbCrTextureData* textureData = GetD3D11TextureData(mData, GetSize());
 
   if (textureData == nullptr) {
--- a/gfx/layers/client/TextureClient.h
+++ b/gfx/layers/client/TextureClient.h
@@ -220,16 +220,17 @@ public:
   static already_AddRefed<TextureReadLock>
   Create(LayersIPCChannel* aAllocator);
 
   virtual NonBlockingTextureReadLock* AsNonBlockingLock() override { return this; }
 };
 
 #ifdef XP_WIN
 class D3D11TextureData;
+class DXGIYCbCrTextureData;
 #endif
 
 class TextureData {
 public:
   struct Info {
     gfx::IntSize size;
     gfx::SurfaceFormat format;
     bool hasIntermediateBuffer;
@@ -287,16 +288,19 @@ public:
   virtual void SyncWithObject(SyncObjectClient* aSyncObject) {};
 
   virtual TextureFlags GetTextureFlags() const { return TextureFlags::NO_FLAGS; }
 
 #ifdef XP_WIN
   virtual D3D11TextureData* AsD3D11TextureData() {
     return nullptr;
   }
+  virtual DXGIYCbCrTextureData* AsDXGIYCbCrTextureData() {
+    return nullptr;
+  }
 #endif
 
   virtual BufferTextureData* AsBufferTextureData() { return nullptr; }
 
   virtual GPUVideoTextureData* AsGPUVideoTextureData() { return nullptr; }
 };
 
 /**
--- a/gfx/layers/d3d11/TextureD3D11.cpp
+++ b/gfx/layers/d3d11/TextureD3D11.cpp
@@ -598,44 +598,47 @@ DXGIYCbCrTextureData*
 DXGIYCbCrTextureData::Create(IDirect3DTexture9* aTextureY,
                              IDirect3DTexture9* aTextureCb,
                              IDirect3DTexture9* aTextureCr,
                              HANDLE aHandleY,
                              HANDLE aHandleCb,
                              HANDLE aHandleCr,
                              const gfx::IntSize& aSize,
                              const gfx::IntSize& aSizeY,
-                             const gfx::IntSize& aSizeCbCr)
+                             const gfx::IntSize& aSizeCbCr,
+                             YUVColorSpace aYUVColorSpace)
 {
   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->mD3D9Textures[0] = aTextureY;
   texture->mD3D9Textures[1] = aTextureCb;
   texture->mD3D9Textures[2] = aTextureCr;
   texture->mSize = aSize;
   texture->mSizeY = aSizeY;
   texture->mSizeCbCr = aSizeCbCr;
+  texture->mYUVColorSpace = aYUVColorSpace;
 
   return texture;
 }
 
 DXGIYCbCrTextureData*
 DXGIYCbCrTextureData::Create(ID3D11Texture2D* aTextureY,
                              ID3D11Texture2D* aTextureCb,
                              ID3D11Texture2D* aTextureCr,
                              const gfx::IntSize& aSize,
                              const gfx::IntSize& aSizeY,
-                             const gfx::IntSize& aSizeCbCr)
+                             const gfx::IntSize& aSizeCbCr,
+                             YUVColorSpace aYUVColorSpace)
 {
   if (!aTextureY || !aTextureCb || !aTextureCr) {
     return nullptr;
   }
 
   aTextureY->SetPrivateDataInterface(sD3D11TextureUsage,
     new TextureMemoryMeasurer(aSize.width * aSize.height));
   aTextureCb->SetPrivateDataInterface(sD3D11TextureUsage,
@@ -673,16 +676,17 @@ DXGIYCbCrTextureData::Create(ID3D11Textu
   texture->mHandles[1] = handleCb;
   texture->mHandles[2] = handleCr;
   texture->mD3D11Textures[0] = aTextureY;
   texture->mD3D11Textures[1] = aTextureCb;
   texture->mD3D11Textures[2] = aTextureCr;
   texture->mSize = aSize;
   texture->mSizeY = aSizeY;
   texture->mSizeCbCr = aSizeCbCr;
+  texture->mYUVColorSpace = aYUVColorSpace;
 
   return texture;
 }
 
 void
 DXGIYCbCrTextureData::FillInfo(TextureData::Info& aInfo) const
 {
   aInfo.size = mSize;
@@ -692,17 +696,17 @@ DXGIYCbCrTextureData::FillInfo(TextureDa
   aInfo.hasSynchronization = false;
 }
 
 void
 DXGIYCbCrTextureData::SerializeSpecific(SurfaceDescriptorDXGIYCbCr* const aOutDesc)
 {
   *aOutDesc = SurfaceDescriptorDXGIYCbCr(
     (WindowsHandle)mHandles[0], (WindowsHandle)mHandles[1], (WindowsHandle)mHandles[2],
-    mSize, mSizeY, mSizeCbCr
+    mSize, mSizeY, mSizeCbCr, mYUVColorSpace
   );
 }
 
 bool
 DXGIYCbCrTextureData::Serialize(SurfaceDescriptor& aOutDescriptor)
 {
   SurfaceDescriptorDXGIYCbCr desc;
   SerializeSpecific(&desc);
@@ -1137,16 +1141,17 @@ DXGITextureHostD3D11::PushDisplayItems(w
   }
 }
 
 DXGIYCbCrTextureHostD3D11::DXGIYCbCrTextureHostD3D11(TextureFlags aFlags,
   const SurfaceDescriptorDXGIYCbCr& aDescriptor)
   : TextureHost(aFlags)
   , mSize(aDescriptor.size())
   , mIsLocked(false)
+  , mYUVColorSpace(aDescriptor.yUVColorSpace())
 {
   mHandles[0] = aDescriptor.handleY();
   mHandles[1] = aDescriptor.handleCb();
   mHandles[2] = aDescriptor.handleCr();
 }
 
 bool
 DXGIYCbCrTextureHostD3D11::EnsureTexture()
--- a/gfx/layers/d3d11/TextureD3D11.h
+++ b/gfx/layers/d3d11/TextureD3D11.h
@@ -139,25 +139,27 @@ public:
   Create(IDirect3DTexture9* aTextureY,
          IDirect3DTexture9* aTextureCb,
          IDirect3DTexture9* aTextureCr,
          HANDLE aHandleY,
          HANDLE aHandleCb,
          HANDLE aHandleCr,
          const gfx::IntSize& aSize,
          const gfx::IntSize& aSizeY,
-         const gfx::IntSize& aSizeCbCr);
+         const gfx::IntSize& aSizeCbCr,
+         YUVColorSpace aYUVColorSpace);
 
   static DXGIYCbCrTextureData*
   Create(ID3D11Texture2D* aTextureCb,
          ID3D11Texture2D* aTextureY,
          ID3D11Texture2D* aTextureCr,
          const gfx::IntSize& aSize,
          const gfx::IntSize& aSizeY,
-         const gfx::IntSize& aSizeCbCr);
+         const gfx::IntSize& aSizeCbCr,
+         YUVColorSpace aYUVColorSpace);
 
   virtual bool Lock(OpenMode) override { return true; }
 
   virtual void Unlock() override {}
 
   virtual void FillInfo(TextureData::Info& aInfo) const override;
 
   void SerializeSpecific(SurfaceDescriptorDXGIYCbCr* aOutDesc);
@@ -170,25 +172,45 @@ public:
 
   virtual bool UpdateFromSurface(gfx::SourceSurface*) override { return false; }
 
   virtual TextureFlags GetTextureFlags() const override
   {
     return TextureFlags::DEALLOCATE_MAIN_THREAD;
   }
 
+  DXGIYCbCrTextureData* AsDXGIYCbCrTextureData() override {
+    return this;
+  }
+
+  gfx::IntSize GetYSize() const
+  {
+    return mSizeY;
+  }
+
+  gfx::IntSize GetCbCrSize() const
+  {
+    return mSizeCbCr;
+  }
+
+  YUVColorSpace GetYUVColorSpace() const
+  {
+    return mYUVColorSpace;
+  }
+
   ID3D11Texture2D* GetD3D11Texture(size_t index) { return mD3D11Textures[index]; }
 
 protected:
    RefPtr<ID3D11Texture2D> mD3D11Textures[3];
    RefPtr<IDirect3DTexture9> mD3D9Textures[3];
    HANDLE mHandles[3];
    gfx::IntSize mSize;
    gfx::IntSize mSizeY;
    gfx::IntSize mSizeCbCr;
+   YUVColorSpace mYUVColorSpace;
 };
 
 /**
  * TextureSource that provides with the necessary APIs to be composited by a
  * CompositorD3D11.
  */
 class TextureSourceD3D11
 {
@@ -378,18 +400,17 @@ public:
   virtual bool AcquireTextureSource(CompositableTextureSourceRef& aTexture) override;
 
   virtual void DeallocateDeviceData() override{}
 
   virtual void SetTextureSourceProvider(TextureSourceProvider* aProvider) override;
 
   virtual gfx::SurfaceFormat GetFormat() const override{ return gfx::SurfaceFormat::YUV; }
 
-  // Bug 1305906 fixes YUVColorSpace handling
-  virtual YUVColorSpace GetYUVColorSpace() const override { return YUVColorSpace::BT601; }
+  virtual YUVColorSpace GetYUVColorSpace() const override { return mYUVColorSpace; }
 
   virtual bool Lock() override;
 
   virtual void Unlock() override;
 
   virtual gfx::IntSize GetSize() const override { return mSize; }
 
   virtual already_AddRefed<gfx::DataSourceSurface> GetAsSurface() override
@@ -421,16 +442,17 @@ protected:
   bool EnsureTexture();
 
   RefPtr<ID3D11Texture2D> mTextures[3];
   RefPtr<DataTextureSourceD3D11> mTextureSources[3];
 
   gfx::IntSize mSize;
   WindowsHandle mHandles[3];
   bool mIsLocked;
+  YUVColorSpace mYUVColorSpace;
 };
 
 class CompositingRenderTargetD3D11 : public CompositingRenderTarget,
                                      public TextureSourceD3D11
 {
 public:
   CompositingRenderTargetD3D11(ID3D11Texture2D* aTexture,
                                const gfx::IntPoint& aOrigin,
--- a/gfx/layers/ipc/LayersSurfaces.ipdlh
+++ b/gfx/layers/ipc/LayersSurfaces.ipdlh
@@ -47,16 +47,17 @@ struct SurfaceDescriptorD3D10 {
 
 struct SurfaceDescriptorDXGIYCbCr {
   WindowsHandle handleY;
   WindowsHandle handleCb;
   WindowsHandle handleCr;
   IntSize size;
   IntSize sizeY;
   IntSize sizeCbCr;
+  YUVColorSpace yUVColorSpace;
 };
 
 struct SurfaceDescriptorMacIOSurface {
   uint32_t surfaceId;
   double scaleFactor;
   bool isOpaque;
 };