Skip to content
Permalink
Browse files

Backport of Bug 1138967 - Part 3: Add D3D11 YCbCr texture clients and…

… upload on the client side
  • Loading branch information...
rmottola committed Dec 27, 2018
1 parent e892acb commit 2e421816773b6a57502907ab22c285d994d8b024
@@ -0,0 +1,117 @@
/* -*- 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 "IMFYCbCrImage.h"
#include "mozilla/layers/TextureD3D11.h"
#include "mozilla/layers/CompositableClient.h"
#include "mozilla/layers/CompositableForwarder.h"
#include "mozilla/gfx/Types.h"
#include "mozilla/layers/TextureClient.h"

namespace mozilla {
namespace layers {

IMFYCbCrImage::IMFYCbCrImage(IMFMediaBuffer* aBuffer, IMF2DBuffer* a2DBuffer)
: PlanarYCbCrImage(nullptr)
, mBuffer(aBuffer)
, m2DBuffer(a2DBuffer)
{}

IMFYCbCrImage::~IMFYCbCrImage()
{
if (m2DBuffer) {
m2DBuffer->Unlock2D();
}
else {
mBuffer->Unlock();
}
}

struct AutoLockTexture
{
AutoLockTexture(ID3D11Texture2D* aTexture)
{
aTexture->QueryInterface((IDXGIKeyedMutex**)byRef(mMutex));
HRESULT hr = mMutex->AcquireSync(0, 10000);
if (hr == WAIT_TIMEOUT) {
MOZ_CRASH();
}

if (FAILED(hr)) {
NS_WARNING("Failed to lock the texture");
}
}

~AutoLockTexture()
{
HRESULT hr = mMutex->ReleaseSync(0);
if (FAILED(hr)) {
NS_WARNING("Failed to unlock the texture");
}
}

RefPtr<IDXGIKeyedMutex> mMutex;
};

TextureClient*
IMFYCbCrImage::GetTextureClient(CompositableClient* aClient)
{
ID3D11Device* device = gfxWindowsPlatform::GetPlatform()->GetD3D11MediaDevice();
if (!device ||
aClient->GetForwarder()->GetCompositorBackendType() != LayersBackend::LAYERS_D3D11) {
return nullptr;
}

if (mTextureClient) {
return mTextureClient;
}

RefPtr<ID3D11DeviceContext> ctx;
device->GetImmediateContext(byRef(ctx));

CD3D11_TEXTURE2D_DESC newDesc(DXGI_FORMAT_A8_UNORM,
mData.mYSize.width, mData.mYSize.height, 1, 1);

newDesc.MiscFlags = D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX;

RefPtr<ID3D11Texture2D> textureY;
HRESULT hr = device->CreateTexture2D(&newDesc, nullptr, byRef(textureY));
NS_ENSURE_TRUE(SUCCEEDED(hr), nullptr);

newDesc.Width = mData.mCbCrSize.width;
newDesc.Height = mData.mCbCrSize.height;

RefPtr<ID3D11Texture2D> textureCb;
hr = device->CreateTexture2D(&newDesc, nullptr, byRef(textureCb));
NS_ENSURE_TRUE(SUCCEEDED(hr), nullptr);

RefPtr<ID3D11Texture2D> textureCr;
hr = device->CreateTexture2D(&newDesc, nullptr, byRef(textureCr));
NS_ENSURE_TRUE(SUCCEEDED(hr), nullptr);

{
AutoLockTexture lockY(textureY);
AutoLockTexture lockCb(textureCb);
AutoLockTexture lockCr(textureCr);

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);
}

RefPtr<DXGIYCbCrTextureClientD3D11> texClient =
new DXGIYCbCrTextureClientD3D11(aClient->GetForwarder(), TextureFlags::DEFAULT);
texClient->InitWith(textureY, textureCb, textureCr, GetSize());
mTextureClient = texClient;

return mTextureClient;
}


} /* layers */
} /* mozilla */
@@ -232,6 +232,7 @@ TextureHost::Create(const SurfaceDescriptor& aDesc,
return CreateTextureHostD3D9(aDesc, aDeallocator, aFlags);

case SurfaceDescriptor::TSurfaceDescriptorD3D10:
case SurfaceDescriptor::TSurfaceDescriptorDXGIYCbCr:
if (Compositor::GetBackend() == LayersBackend::LAYERS_D3D9) {
return CreateTextureHostD3D9(aDesc, aDeallocator, aFlags);
} else {
@@ -158,6 +158,11 @@ CreateTextureHostD3D11(const SurfaceDescriptor& aDesc,
aDesc.get_SurfaceDescriptorD3D10());
break;
}
case SurfaceDescriptor::TSurfaceDescriptorDXGIYCbCr: {
result = new DXGIYCbCrTextureHostD3D11(aFlags,
aDesc.get_SurfaceDescriptorDXGIYCbCr());
break;
}
default: {
NS_WARNING("Unsupported SurfaceDescriptor type");
}
@@ -496,6 +501,82 @@ TextureClientD3D11::ToSurfaceDescriptor(SurfaceDescriptor& aOutDescriptor)
return true;
}

DXGIYCbCrTextureClientD3D11::DXGIYCbCrTextureClientD3D11(ISurfaceAllocator* aAllocator,
TextureFlags aFlags)
: TextureClient(aAllocator, aFlags)
, mIsLocked(false)
{
MOZ_COUNT_CTOR(DXGIYCbCrTextureClientD3D11);
}

class YCbCrKeepAliveD3D11 : public KeepAlive
{
public:
YCbCrKeepAliveD3D11(RefPtr<ID3D11Texture2D> aTextures[3])
{
mTextures[0] = aTextures[0];
mTextures[1] = aTextures[1];
mTextures[2] = aTextures[2];
}

protected:
RefPtr<ID3D11Texture2D> mTextures[3];
};

DXGIYCbCrTextureClientD3D11::~DXGIYCbCrTextureClientD3D11()
{
if (mTextures[0] && mActor) {
KeepUntilFullDeallocation(MakeUnique<YCbCrKeepAliveD3D11>(mTextures));
}
MOZ_COUNT_DTOR(DXGIYCbCrTextureClientD3D11);
}

bool
DXGIYCbCrTextureClientD3D11::Lock(OpenMode)
{
MOZ_ASSERT(!mIsLocked);
if (!IsValid()) {
return false;
}
mIsLocked = true;
return true;
}

void
DXGIYCbCrTextureClientD3D11::Unlock()
{
MOZ_ASSERT(mIsLocked, "Unlock called while the texture is not locked!");
mIsLocked = false;
}

bool
DXGIYCbCrTextureClientD3D11::ToSurfaceDescriptor(SurfaceDescriptor& aOutDescriptor)
{
MOZ_ASSERT(IsValid());
if (!IsAllocated()) {
return false;
}

RefPtr<IDXGIResource> resource;
mTextures[0]->QueryInterface((IDXGIResource**)byRef(resource));

HANDLE sharedHandleY;
HRESULT hr = resource->GetSharedHandle(&sharedHandleY);

mTextures[1]->QueryInterface((IDXGIResource**)byRef(resource));

HANDLE sharedHandleCb;
hr = resource->GetSharedHandle(&sharedHandleCb);

mTextures[2]->QueryInterface((IDXGIResource**)byRef(resource));

HANDLE sharedHandleCr;
hr = resource->GetSharedHandle(&sharedHandleCr);

aOutDescriptor = SurfaceDescriptorDXGIYCbCr((WindowsHandle)sharedHandleY, (WindowsHandle)sharedHandleCb, (WindowsHandle)sharedHandleCr, GetSize());
return true;
}

DXGITextureHostD3D11::DXGITextureHostD3D11(TextureFlags aFlags,
const SurfaceDescriptorD3D10& aDescriptor)
: TextureHost(aFlags)
@@ -576,6 +657,108 @@ DXGITextureHostD3D11::GetTextureSources()
return mTextureSource.get();
}

DXGIYCbCrTextureHostD3D11::DXGIYCbCrTextureHostD3D11(TextureFlags aFlags,
const SurfaceDescriptorDXGIYCbCr& aDescriptor)
: TextureHost(aFlags)
, mSize(aDescriptor.size())
, mIsLocked(false)
{
mHandles[0] = aDescriptor.handleY();
mHandles[1] = aDescriptor.handleCb();
mHandles[2] = aDescriptor.handleCr();
}

bool
DXGIYCbCrTextureHostD3D11::OpenSharedHandle()
{
if (!GetDevice()) {
return false;
}

HRESULT hr = GetDevice()->OpenSharedResource((HANDLE)mHandles[0],
__uuidof(ID3D11Texture2D),
(void**)(ID3D11Texture2D**)byRef(mTextures[0]));
if (FAILED(hr)) {
NS_WARNING("Failed to open shared texture for Y Plane");
return false;
}

hr = GetDevice()->OpenSharedResource((HANDLE)mHandles[1],
__uuidof(ID3D11Texture2D),
(void**)(ID3D11Texture2D**)byRef(mTextures[1]));
if (FAILED(hr)) {
NS_WARNING("Failed to open shared texture for Cb Plane");
return false;
}

hr = GetDevice()->OpenSharedResource((HANDLE)mHandles[2],
__uuidof(ID3D11Texture2D),
(void**)(ID3D11Texture2D**)byRef(mTextures[2]));
if (FAILED(hr)) {
NS_WARNING("Failed to open shared texture for Cr Plane");
return false;
}

return true;
}

ID3D11Device*
DXGIYCbCrTextureHostD3D11::GetDevice()
{
return gfxWindowsPlatform::GetPlatform()->GetD3D11Device();
}

void
DXGIYCbCrTextureHostD3D11::SetCompositor(Compositor* aCompositor)
{
mCompositor = static_cast<CompositorD3D11*>(aCompositor);
}

bool
DXGIYCbCrTextureHostD3D11::Lock()
{
if (!GetDevice()) {
NS_WARNING("trying to lock a TextureHost without a D3D device");
return false;
}
if (!mTextureSources[0]) {
if (!mTextures[0] && !OpenSharedHandle()) {
return false;
}

mTextureSources[0] = new DataTextureSourceD3D11(SurfaceFormat::A8, mCompositor, mTextures[0]);
mTextureSources[1] = new DataTextureSourceD3D11(SurfaceFormat::A8, mCompositor, mTextures[1]);
mTextureSources[2] = new DataTextureSourceD3D11(SurfaceFormat::A8, mCompositor, mTextures[2]);
mTextureSources[0]->SetNextSibling(mTextureSources[1]);
mTextureSources[1]->SetNextSibling(mTextureSources[2]);
}

mIsLocked = LockD3DTexture(mTextureSources[0]->GetD3D11Texture()) &&
LockD3DTexture(mTextureSources[1]->GetD3D11Texture()) &&
LockD3DTexture(mTextureSources[2]->GetD3D11Texture());

return mIsLocked;
}

void
DXGIYCbCrTextureHostD3D11::Unlock()
{
MOZ_ASSERT(mIsLocked);
UnlockD3DTexture(mTextureSources[0]->GetD3D11Texture());
UnlockD3DTexture(mTextureSources[1]->GetD3D11Texture());
UnlockD3DTexture(mTextureSources[2]->GetD3D11Texture());
mIsLocked = false;
}

TextureSource*
DXGIYCbCrTextureHostD3D11::GetTextureSources()
{
MOZ_ASSERT(mIsLocked);
// If Lock was successful we must have a valid TextureSource.
MOZ_ASSERT(mTextureSources[0] && mTextureSources[1] && mTextureSources[2]);
return mTextureSources[0].get();
}

bool
DataTextureSourceD3D11::Update(DataSourceSurface* aSurface,
nsIntRegion* aDestRegion,
Oops, something went wrong.

0 comments on commit 2e42181

Please sign in to comment.
You can’t perform that action at this time.