Bug 1540581 - P18. Move destination texture type choice to the D3D11 texture allocator. r=mattwoodrow

It allows for more readable code, not having to store multiple times different storage type across multiple objects.

Now each class does one task and only deal with a single texture data type.

Differential Revision: https://phabricator.services.mozilla.com/D26473

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Jean-Yves Avenard 2019-04-11 12:39:12 +00:00
parent 896eec30a3
commit 51d9f4be53
4 changed files with 81 additions and 42 deletions

View File

@ -589,7 +589,7 @@ class D3D11DXVA2Manager : public DXVA2Manager {
HRESULT CopyToImage(IMFSample* aVideoSample, const gfx::IntRect& aRegion,
Image** aOutImage) override;
HRESULT CopyToBGRATexture(ID3D11Texture2D* aInTexture, const GUID& aSubType,
HRESULT CopyToBGRATexture(ID3D11Texture2D* aInTexture,
ID3D11Texture2D** aOutTexture) override;
HRESULT ConfigureForSize(IMFMediaType* aInputType,
@ -676,7 +676,8 @@ D3D11DXVA2Manager::Init(layers::KnowsCompositor* aKnowsCompositor,
// There's no proper KnowsCompositor for ImageBridge currently (and it
// implements the interface), so just use that if it's available.
mTextureClientAllocator = new D3D11RecycleAllocator(
layers::ImageBridgeChild::GetSingleton().get(), mDevice);
layers::ImageBridgeChild::GetSingleton().get(), mDevice,
gfx::SurfaceFormat::NV12);
if (ImageBridgeChild::GetSingleton() && gfxPrefs::PDMWMFUseSyncTexture() &&
mDevice != DeviceManagerDx::Get()->GetCompositorDevice()) {
@ -691,8 +692,8 @@ D3D11DXVA2Manager::Init(layers::KnowsCompositor* aKnowsCompositor,
mDevice);
}
} else {
mTextureClientAllocator =
new D3D11RecycleAllocator(aKnowsCompositor, mDevice);
mTextureClientAllocator = new D3D11RecycleAllocator(
aKnowsCompositor, mDevice, gfx::SurfaceFormat::NV12);
if (gfxPrefs::PDMWMFUseSyncTexture()) {
// We use a syncobject to avoid the cost of the mutex lock when
// compositing, and because it allows color conversion ocurring directly
@ -886,7 +887,7 @@ D3D11DXVA2Manager::CopyToImage(IMFSample* aVideoSample,
MOZ_ASSERT(mTextureClientAllocator);
RefPtr<D3D11ShareHandleImage> image = new D3D11ShareHandleImage(
gfx::IntSize(mWidth, mHeight), aRegion, mInputSubType, mYUVColorSpace);
gfx::IntSize(mWidth, mHeight), aRegion, mYUVColorSpace);
// Retrieve the DXGI_FORMAT for the current video sample.
RefPtr<IMFMediaBuffer> buffer;
@ -928,6 +929,8 @@ D3D11DXVA2Manager::CopyToImage(IMFSample* aVideoSample,
NS_ENSURE_TRUE(mSyncObject, E_FAIL);
}
// The D3D11TextureClientAllocator may return a different texture format
// than preferred. In which case the destination texture will be BGRA32.
if (outDesc.Format == inDesc.Format) {
// Our video frame is stored in a non-sharable ID3D11Texture2D. We need
// to create a copy of that frame as a sharable resource, save its share
@ -974,7 +977,6 @@ D3D11DXVA2Manager::CopyToImage(IMFSample* aVideoSample,
HRESULT
D3D11DXVA2Manager::CopyToBGRATexture(ID3D11Texture2D* aInTexture,
const GUID& aSubType,
ID3D11Texture2D** aOutTexture) {
NS_ENSURE_TRUE(aInTexture, E_POINTER);
NS_ENSURE_TRUE(aOutTexture, E_POINTER);
@ -995,7 +997,21 @@ D3D11DXVA2Manager::CopyToBGRATexture(ID3D11Texture2D* aInTexture,
hr = inputType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video);
NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
hr = inputType->SetGUID(MF_MT_SUBTYPE, aSubType);
const GUID subType = [&]() {
switch (desc.Format) {
case DXGI_FORMAT_NV12:
return MFVideoFormat_NV12;
case DXGI_FORMAT_P010:
return MFVideoFormat_P010;
case DXGI_FORMAT_P016:
return MFVideoFormat_P016;
default:
MOZ_ASSERT_UNREACHABLE("Unexpected texture type");
return MFVideoFormat_NV12;
}
}();
hr = inputType->SetGUID(MF_MT_SUBTYPE, subType);
NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
hr = inputType->SetUINT32(MF_MT_INTERLACE_MODE,
@ -1136,6 +1152,21 @@ D3D11DXVA2Manager::ConfigureForSize(IMFMediaType* aInputType,
mInputType = inputType;
mInputSubType = subType;
mYUVColorSpace = aColorSpace;
if (mTextureClientAllocator) {
gfx::SurfaceFormat format = [&]() {
if (subType == MFVideoFormat_NV12) {
return gfx::SurfaceFormat::NV12;
} else if (subType == MFVideoFormat_P010) {
return gfx::SurfaceFormat::P010;
} else if (subType == MFVideoFormat_P016) {
return gfx::SurfaceFormat::P016;
} else {
MOZ_ASSERT_UNREACHABLE("Unexpected texture type");
return gfx::SurfaceFormat::NV12;
}
}();
mTextureClientAllocator->SetPreferredSurfaceFormat(format);
}
return S_OK;
}

View File

@ -43,7 +43,6 @@ class DXVA2Manager {
layers::Image** aOutImage) = 0;
virtual HRESULT CopyToBGRATexture(ID3D11Texture2D* aInTexture,
const GUID& aSubType,
ID3D11Texture2D** aOutTexture) {
// Not implemented!
MOZ_CRASH("CopyToBGRATexture not implemented on this manager.");

View File

@ -25,35 +25,16 @@ using namespace gfx;
D3D11ShareHandleImage::D3D11ShareHandleImage(const gfx::IntSize& aSize,
const gfx::IntRect& aRect,
const GUID& aSourceFormat,
gfx::YUVColorSpace aColorSpace)
: Image(nullptr, ImageFormat::D3D11_SHARE_HANDLE_TEXTURE),
mSize(aSize),
mPictureRect(aRect),
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, 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,
mYUVColorSpace, mSize);
} else {
mTextureClient = aAllocator->CreateOrRecycleClient(
gfx::SurfaceFormat::B8G8R8A8, gfx::YUVColorSpace::UNKNOWN, mSize);
}
mTextureClient = aAllocator->CreateOrRecycleClient(mYUVColorSpace, mSize);
if (mTextureClient) {
D3D11TextureData* textureData =
mTextureClient->GetInternalData()->AsD3D11TextureData();
@ -111,8 +92,7 @@ D3D11ShareHandleImage::GetAsSourceSurface() {
RefPtr<ID3D11Texture2D> outTexture;
hr = manager->CopyToBGRATexture(texture, mSourceFormat,
getter_AddRefs(outTexture));
hr = manager->CopyToBGRATexture(texture, getter_AddRefs(outTexture));
if (FAILED(hr)) {
gfxWarning() << "Failed to copy to BGRA texture.";
@ -239,9 +219,35 @@ class MOZ_RAII D3D11TextureClientAllocationHelper
const RefPtr<ID3D11Device> mDevice;
};
D3D11RecycleAllocator::D3D11RecycleAllocator(
KnowsCompositor* aAllocator, ID3D11Device* aDevice,
gfx::SurfaceFormat aPreferredFormat)
: TextureClientRecycleAllocator(aAllocator),
mDevice(aDevice),
mCanUseNV12(gfxPrefs::PDMWMFUseNV12Format() &&
gfx::DeviceManagerDx::Get()->CanUseNV12()),
mCanUseP010(gfxPrefs::PDMWMFUseNV12Format() &&
gfx::DeviceManagerDx::Get()->CanUseP010()),
mCanUseP016(gfxPrefs::PDMWMFUseNV12Format() &&
gfx::DeviceManagerDx::Get()->CanUseP016()) {
SetPreferredSurfaceFormat(aPreferredFormat);
}
void D3D11RecycleAllocator::SetPreferredSurfaceFormat(
gfx::SurfaceFormat aPreferredFormat) {
if ((aPreferredFormat == gfx::SurfaceFormat::NV12 && mCanUseNV12) ||
(aPreferredFormat == gfx::SurfaceFormat::P010 && mCanUseP010) ||
(aPreferredFormat == gfx::SurfaceFormat::P016 && mCanUseP016)) {
mUsableSurfaceFormat = aPreferredFormat;
return;
}
// We can't handle the native source format, set it to BGRA which will
// force the caller to convert it later.
mUsableSurfaceFormat = gfx::SurfaceFormat::B8G8R8A8;
}
already_AddRefed<TextureClient> D3D11RecycleAllocator::CreateOrRecycleClient(
gfx::SurfaceFormat aFormat, gfx::YUVColorSpace aColorSpace,
const gfx::IntSize& aSize) {
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();
@ -258,8 +264,8 @@ already_AddRefed<TextureClient> D3D11RecycleAllocator::CreateOrRecycleClient(
allocFlags = TextureAllocationFlags::ALLOC_MANUAL_SYNCHRONIZATION;
}
D3D11TextureClientAllocationHelper helper(aFormat, aColorSpace, aSize,
allocFlags, mDevice,
D3D11TextureClientAllocationHelper helper(mUsableSurfaceFormat, aColorSpace,
aSize, allocFlags, mDevice,
layers::TextureFlags::DEFAULT);
RefPtr<TextureClient> textureClient = CreateOrRecycle(helper);

View File

@ -21,19 +21,24 @@ namespace layers {
class D3D11RecycleAllocator final : public TextureClientRecycleAllocator {
public:
D3D11RecycleAllocator(KnowsCompositor* aAllocator, ID3D11Device* aDevice)
: TextureClientRecycleAllocator(aAllocator), mDevice(aDevice) {}
D3D11RecycleAllocator(KnowsCompositor* aAllocator, ID3D11Device* aDevice,
gfx::SurfaceFormat aPreferredFormat);
already_AddRefed<TextureClient> CreateOrRecycleClient(
gfx::SurfaceFormat aFormat, gfx::YUVColorSpace aColorSpace,
const gfx::IntSize& aSize);
gfx::YUVColorSpace aColorSpace, const gfx::IntSize& aSize);
protected:
RefPtr<ID3D11Device> mDevice;
void SetPreferredSurfaceFormat(gfx::SurfaceFormat aPreferredFormat);
private:
const RefPtr<ID3D11Device> mDevice;
const bool mCanUseNV12;
const bool mCanUseP010;
const bool mCanUseP016;
/**
* Used for checking if CompositorDevice/ContentDevice is updated.
*/
RefPtr<ID3D11Device> mImageDevice;
gfx::SurfaceFormat mUsableSurfaceFormat;
};
// Image class that wraps a ID3D11Texture2D. This class copies the image
@ -43,7 +48,6 @@ class D3D11RecycleAllocator final : public TextureClientRecycleAllocator {
class D3D11ShareHandleImage final : public Image {
public:
D3D11ShareHandleImage(const gfx::IntSize& aSize, const gfx::IntRect& aRect,
const GUID& aSourceFormat,
gfx::YUVColorSpace aColorSpace);
virtual ~D3D11ShareHandleImage() = default;
@ -62,7 +66,6 @@ class D3D11ShareHandleImage final : public Image {
private:
gfx::IntSize mSize;
gfx::IntRect mPictureRect;
const GUID mSourceFormat;
gfx::YUVColorSpace mYUVColorSpace;
RefPtr<TextureClient> mTextureClient;
RefPtr<ID3D11Texture2D> mTexture;