Bug 1757698 - Add D3D11TextureIMFSampleImage and array index handling to D3D11TextureData r=jgilbert,gfx-reviewers,jrmuizel

This is a preparation of Bug 1723207.

D3D11TextureIMFSampleImage is used for storing ID3D11Texture2D of IMFSample. Array index handling is added, since there are cases that hardware decoder uses array texture. D3D11TextureIMFSampleImage is expected to be used in GPU process.

Differential Revision: https://phabricator.services.mozilla.com/D140017
This commit is contained in:
sotaro 2022-03-03 02:30:28 +00:00
parent 548e1083fa
commit 33ec38c192
16 changed files with 238 additions and 23 deletions

View File

@ -33,6 +33,7 @@
#ifdef XP_WIN
# include "mozilla/layers/D3D11ShareHandleImage.h"
# include "mozilla/layers/D3D11TextureIMFSampleImage.h"
# include "mozilla/layers/D3D11YCbCrImage.h"
#endif
@ -787,6 +788,10 @@ bool GLBlitHelper::BlitImageToFramebuffer(layers::Image* const srcImage,
case ImageFormat::D3D11_SHARE_HANDLE_TEXTURE:
return BlitImage(static_cast<layers::D3D11ShareHandleImage*>(srcImage),
destSize, destOrigin);
case ImageFormat::D3D11_TEXTURE_IMF_SAMPLE:
return BlitImage(
static_cast<layers::D3D11TextureIMFSampleImage*>(srcImage), destSize,
destOrigin);
case ImageFormat::D3D11_YCBCR_IMAGE:
return BlitImage(static_cast<layers::D3D11YCbCrImage*>(srcImage),
destSize, destOrigin);
@ -794,6 +799,7 @@ bool GLBlitHelper::BlitImageToFramebuffer(layers::Image* const srcImage,
return false; // todo
#else
case ImageFormat::D3D11_SHARE_HANDLE_TEXTURE:
case ImageFormat::D3D11_TEXTURE_IMF_SAMPLE:
case ImageFormat::D3D11_YCBCR_IMAGE:
case ImageFormat::D3D9_RGB32_TEXTURE:
MOZ_ASSERT(false);

View File

@ -52,6 +52,7 @@ class SurfaceDescriptorBuffer;
#ifdef XP_WIN
class D3D11ShareHandleImage;
class D3D11TextureIMFSampleImage;
class D3D11YCbCrImage;
class SurfaceDescriptorD3D10;
class SurfaceDescriptorDXGIYCbCr;
@ -239,6 +240,8 @@ class GLBlitHelper final {
// GLBlitHelperD3D.cpp:
bool BlitImage(layers::D3D11ShareHandleImage* srcImage,
const gfx::IntSize& destSize, OriginPos destOrigin) const;
bool BlitImage(layers::D3D11TextureIMFSampleImage* srcImage,
const gfx::IntSize& destSize, OriginPos destOrigin) const;
bool BlitImage(layers::D3D11YCbCrImage* srcImage,
const gfx::IntSize& destSize, OriginPos destOrigin) const;

View File

@ -14,6 +14,7 @@
#include "ScopedGLHelpers.h"
#include "mozilla/layers/D3D11ShareHandleImage.h"
#include "mozilla/layers/D3D11TextureIMFSampleImage.h"
#include "mozilla/layers/D3D11YCbCrImage.h"
#include "mozilla/layers/TextureD3D11.h"
@ -186,6 +187,20 @@ bool GLBlitHelper::BlitImage(layers::D3D11ShareHandleImage* const srcImage,
// -------------------------------------
bool GLBlitHelper::BlitImage(layers::D3D11TextureIMFSampleImage* const srcImage,
const gfx::IntSize& destSize,
const OriginPos destOrigin) const {
const auto& data = srcImage->GetData();
if (!data) return false;
layers::SurfaceDescriptorD3D10 desc;
if (!data->SerializeSpecific(&desc)) return false;
return BlitDescriptor(desc, destSize, destOrigin);
}
// -------------------------------------
bool GLBlitHelper::BlitImage(layers::D3D11YCbCrImage* const srcImage,
const gfx::IntSize& destSize,
const OriginPos destOrigin) const {
@ -209,6 +224,7 @@ bool GLBlitHelper::BlitDescriptor(const layers::SurfaceDescriptorD3D10& desc,
if (!d3d) return false;
const auto& handle = desc.handle();
const auto& arrayIndex = desc.arrayIndex();
const auto& format = desc.format();
const auto& clipSize = desc.size();
@ -231,8 +247,12 @@ bool GLBlitHelper::BlitDescriptor(const layers::SurfaceDescriptorD3D10& desc,
}
const RefPtr<ID3D11Texture2D> texList[2] = {tex, tex};
const EGLAttrib postAttribs0[] = {LOCAL_EGL_NATIVE_BUFFER_PLANE_OFFSET_IMG, 0,
LOCAL_EGL_D3D_TEXTURE_SUBRESOURCE_ID_ANGLE,
static_cast<EGLAttrib>(arrayIndex),
LOCAL_EGL_NONE};
const EGLAttrib postAttribs1[] = {LOCAL_EGL_NATIVE_BUFFER_PLANE_OFFSET_IMG, 1,
LOCAL_EGL_D3D_TEXTURE_SUBRESOURCE_ID_ANGLE,
static_cast<EGLAttrib>(arrayIndex),
LOCAL_EGL_NONE};
const EGLAttrib* const postAttribsList[2] = {postAttribs0, postAttribs1};
// /layers/d3d11/CompositorD3D11.cpp uses bt601 for EffectTypes::NV12.

View File

@ -142,7 +142,7 @@ Maybe<layers::SurfaceDescriptor>
SharedSurface_ANGLEShareHandle::ToSurfaceDescriptor() {
const auto format = gfx::SurfaceFormat::B8G8R8A8;
return Some(layers::SurfaceDescriptorD3D10(
(WindowsHandle)mShareHandle, format, mDesc.size,
(WindowsHandle)mShareHandle, /* arrayIndex */ 0, format, mDesc.size,
gfx::YUVColorSpace::Identity, gfx::ColorRange::FULL));
}

View File

@ -438,7 +438,7 @@ Maybe<layers::SurfaceDescriptor>
SharedSurface_D3D11Interop::ToSurfaceDescriptor() {
const auto format = gfx::SurfaceFormat::B8G8R8A8;
return Some(layers::SurfaceDescriptorD3D10(
WindowsHandle(mData.dxgiHandle), format, mDesc.size,
WindowsHandle(mData.dxgiHandle), /* arrayIndex */ 0, format, mDesc.size,
gfx::YUVColorSpace::Identity, gfx::ColorRange::FULL));
}

View File

@ -0,0 +1,68 @@
/* -*- 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 <memory>
#include <mfobjects.h>
#include "D3D11TextureIMFSampleImage.h"
#include "WMF.h"
#include "d3d11.h"
#include "mozilla/layers/KnowsCompositor.h"
#include "mozilla/layers/TextureForwarder.h"
namespace mozilla {
namespace layers {
using namespace gfx;
D3D11TextureIMFSampleImage::D3D11TextureIMFSampleImage(
IMFSample* aVideoSample, ID3D11Texture2D* aTexture, uint32_t aArrayIndex,
const gfx::IntSize& aSize, const gfx::IntRect& aRect,
gfx::YUVColorSpace aColorSpace, gfx::ColorRange aColorRange)
: Image(nullptr, ImageFormat::D3D11_TEXTURE_IMF_SAMPLE),
mVideoSample(aVideoSample),
mTexture(aTexture),
mArrayIndex(aArrayIndex),
mSize(aSize),
mPictureRect(aRect),
mYUVColorSpace(aColorSpace),
mColorRange(aColorRange) {
MOZ_ASSERT(XRE_IsGPUProcess());
}
void D3D11TextureIMFSampleImage::AllocateTextureClient(
KnowsCompositor* aKnowsCompositor) {
mTextureClient = D3D11TextureData::CreateTextureClient(
mTexture, mArrayIndex, mSize, gfx::SurfaceFormat::NV12, mYUVColorSpace,
mColorRange, aKnowsCompositor);
MOZ_ASSERT(mTextureClient);
}
gfx::IntSize D3D11TextureIMFSampleImage::GetSize() const { return mSize; }
TextureClient* D3D11TextureIMFSampleImage::GetTextureClient(
KnowsCompositor* aKnowsCompositor) {
return mTextureClient;
}
already_AddRefed<gfx::SourceSurface>
D3D11TextureIMFSampleImage::GetAsSourceSurface() {
RefPtr<ID3D11Texture2D> src = GetTexture();
if (!src) {
gfxWarning() << "Cannot readback from shared texture because no texture is "
"available.";
return nullptr;
}
return gfx::Factory::CreateBGRA8DataSourceSurfaceForD3D11Texture(src);
}
ID3D11Texture2D* D3D11TextureIMFSampleImage::GetTexture() const {
return mTexture;
}
} // namespace layers
} // namespace mozilla

View File

@ -0,0 +1,73 @@
/* -*- 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/. */
#ifndef GFX_D311_TEXTURE_IMF_SAMPLE_IMAGE_H
#define GFX_D311_TEXTURE_IMF_SAMPLE_IMAGE_H
#include "ImageContainer.h"
#include "d3d11.h"
#include "mozilla/RefPtr.h"
#include "mozilla/gfx/Types.h"
#include "mozilla/layers/TextureClient.h"
#include "mozilla/layers/TextureD3D11.h"
struct ID3D11Texture2D;
struct IMFSample;
namespace mozilla {
namespace gl {
class GLBlitHelper;
}
namespace layers {
// Image class that wraps ID3D11Texture2D of IMFSample
// Expected to be used in GPU process.
class D3D11TextureIMFSampleImage final : public Image {
public:
D3D11TextureIMFSampleImage(IMFSample* aVideoSample, ID3D11Texture2D* aTexture,
uint32_t aArrayIndex, const gfx::IntSize& aSize,
const gfx::IntRect& aRect,
gfx::YUVColorSpace aColorSpace,
gfx::ColorRange aColorRange);
virtual ~D3D11TextureIMFSampleImage() = default;
void AllocateTextureClient(KnowsCompositor* aKnowsCompositor);
gfx::IntSize GetSize() const override;
already_AddRefed<gfx::SourceSurface> GetAsSourceSurface() override;
TextureClient* GetTextureClient(KnowsCompositor* aKnowsCompositor) override;
gfx::IntRect GetPictureRect() const override { return mPictureRect; }
ID3D11Texture2D* GetTexture() const;
gfx::YUVColorSpace GetYUVColorSpace() const { return mYUVColorSpace; }
gfx::ColorRange GetColorRange() const { return mColorRange; }
private:
friend class gl::GLBlitHelper;
D3D11TextureData* GetData() const {
if (!mTextureClient) {
return nullptr;
}
return mTextureClient->GetInternalData()->AsD3D11TextureData();
}
// When ref of IMFSample is held, its ID3D11Texture2D is not reused by
// IMFTransform.
RefPtr<IMFSample> mVideoSample;
RefPtr<ID3D11Texture2D> mTexture;
const uint32_t mArrayIndex;
const gfx::IntSize mSize;
const gfx::IntRect mPictureRect;
const gfx::YUVColorSpace mYUVColorSpace;
const gfx::ColorRange mColorRange;
RefPtr<TextureClient> mTextureClient;
};
} // namespace layers
} // namespace mozilla
#endif // GFX_D311_TEXTURE_IMF_SAMPLE_IMAGE_H

View File

@ -80,8 +80,8 @@ already_AddRefed<IDirect3DSurface9> DXGID3D9TextureData::GetD3D9Surface()
}
bool DXGID3D9TextureData::Serialize(SurfaceDescriptor& aOutDescriptor) {
SurfaceDescriptorD3D10 desc((WindowsHandle)(mHandle), mFormat, GetSize(),
gfx::YUVColorSpace::Identity,
SurfaceDescriptorD3D10 desc((WindowsHandle)(mHandle), /* arrayIndex */ 0,
mFormat, GetSize(), gfx::YUVColorSpace::Identity,
gfx::ColorRange::FULL);
// In reality, with D3D9 we will only ever deal with RGBA textures.
bool isYUV = mFormat == gfx::SurfaceFormat::NV12 ||

View File

@ -75,6 +75,12 @@ enum class ImageFormat {
*/
D3D11_SHARE_HANDLE_TEXTURE,
/**
* A wrapper of ID3D11Texture2D of IMFSample.
* Expected to be used in GPU process.
*/
D3D11_TEXTURE_IMF_SAMPLE,
/**
* A wrapper around a drawable TextureClient.
*/

View File

@ -282,7 +282,7 @@ static void UnlockD3DTexture(
}
D3D11TextureData::D3D11TextureData(ID3D11Texture2D* aTexture,
gfx::IntSize aSize,
uint32_t aArrayIndex, gfx::IntSize aSize,
gfx::SurfaceFormat aFormat,
TextureAllocationFlags aFlags)
: mSize(aSize),
@ -290,6 +290,7 @@ D3D11TextureData::D3D11TextureData(ID3D11Texture2D* aTexture,
mNeedsClear(aFlags & ALLOC_CLEAR_BUFFER),
mHasSynchronization(HasKeyedMutex(aTexture)),
mTexture(aTexture),
mArrayIndex(aArrayIndex),
mAllocationFlags(aFlags) {
MOZ_ASSERT(aTexture);
}
@ -386,9 +387,9 @@ bool D3D11TextureData::SerializeSpecific(
LOGD3D11("Error getting shared handle for texture.");
return false;
}
*aOutDesc = SurfaceDescriptorD3D10((WindowsHandle)sharedHandle, mFormat,
mSize, mYUVColorSpace, mColorRange);
*aOutDesc =
SurfaceDescriptorD3D10((WindowsHandle)sharedHandle, mArrayIndex, mFormat,
mSize, mYUVColorSpace, mColorRange);
return true;
}
@ -408,6 +409,23 @@ void D3D11TextureData::GetSubDescriptor(
*aOutDesc = std::move(ret);
}
/* static */
already_AddRefed<TextureClient> D3D11TextureData::CreateTextureClient(
ID3D11Texture2D* aTexture, uint32_t aIndex, gfx::IntSize aSize,
gfx::SurfaceFormat aFormat, gfx::YUVColorSpace aColorSpace,
gfx::ColorRange aColorRange, KnowsCompositor* aKnowsCompositor) {
D3D11TextureData* data = new D3D11TextureData(
aTexture, aIndex, aSize, aFormat,
TextureAllocationFlags::ALLOC_MANUAL_SYNCHRONIZATION);
data->SetYUVColorSpace(aColorSpace);
data->SetColorRange(aColorRange);
RefPtr<TextureClient> textureClient = MakeAndAddRef<TextureClient>(
data, TextureFlags::NO_FLAGS, aKnowsCompositor->GetTextureForwarder());
return textureClient.forget();
}
D3D11TextureData* D3D11TextureData::Create(IntSize aSize, SurfaceFormat aFormat,
TextureAllocationFlags aFlags,
ID3D11Device* aDevice) {
@ -544,7 +562,7 @@ D3D11TextureData* D3D11TextureData::Create(IntSize aSize, SurfaceFormat aFormat,
texture11->SetPrivateDataInterface(
sD3D11TextureUsage,
new TextureMemoryMeasurer(newDesc.Width * newDesc.Height * 4));
return new D3D11TextureData(texture11, aSize, aFormat, aFlags);
return new D3D11TextureData(texture11, 0, aSize, aFormat, aFlags);
}
void D3D11TextureData::Deallocate(LayersIPCChannel* aAllocator) {
@ -765,6 +783,7 @@ bool D3D11TextureData::UpdateFromSurface(gfx::SourceSurface* aSurface) {
DXGITextureHostD3D11::DXGITextureHostD3D11(
TextureFlags aFlags, const SurfaceDescriptorD3D10& aDescriptor)
: TextureHost(aFlags),
mArrayIndex(aDescriptor.arrayIndex()),
mSize(aDescriptor.size()),
mHandle(aDescriptor.handle()),
mFormat(aDescriptor.format()),
@ -916,8 +935,7 @@ void DXGITextureHostD3D11::UnlockInternal() {
void DXGITextureHostD3D11::CreateRenderTexture(
const wr::ExternalImageId& aExternalImageId) {
RefPtr<wr::RenderTextureHost> texture = new wr::RenderDXGITextureHost(
mHandle, mFormat, mYUVColorSpace, mColorRange, mSize);
mHandle, mArrayIndex, mFormat, mYUVColorSpace, mColorRange, mSize);
wr::RenderThread::Get()->RegisterExternalImage(aExternalImageId,
texture.forget());
}

View File

@ -56,6 +56,11 @@ class D3D11TextureData final : public TextureData {
TextureAllocationFlags aAllocFlags,
ID3D11Device* aDevice = nullptr);
static already_AddRefed<TextureClient> CreateTextureClient(
ID3D11Texture2D* aTexture, uint32_t aIndex, gfx::IntSize aSize,
gfx::SurfaceFormat aFormat, gfx::YUVColorSpace aColorSpace,
gfx::ColorRange aColorRange, KnowsCompositor* aKnowsCompositor);
virtual ~D3D11TextureData();
bool UpdateFromSurface(gfx::SourceSurface* aSurface) override;
@ -100,8 +105,9 @@ class D3D11TextureData final : public TextureData {
TextureFlags GetTextureFlags() const override;
private:
D3D11TextureData(ID3D11Texture2D* aTexture, gfx::IntSize aSize,
gfx::SurfaceFormat aFormat, TextureAllocationFlags aFlags);
D3D11TextureData(ID3D11Texture2D* aTexture, uint32_t aArrayIndex,
gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
TextureAllocationFlags aFlags);
void GetDXGIResource(IDXGIResource** aOutResource);
@ -127,6 +133,7 @@ class D3D11TextureData final : public TextureData {
const bool mHasSynchronization;
RefPtr<ID3D11Texture2D> mTexture;
uint32_t mArrayIndex = 0;
const TextureAllocationFlags mAllocationFlags;
};
@ -299,8 +306,8 @@ class DataTextureSourceD3D11 : public DataTextureSource,
protected:
gfx::IntRect GetTileRect(uint32_t aIndex) const;
std::vector<RefPtr<ID3D11Texture2D> > mTileTextures;
std::vector<RefPtr<ID3D11ShaderResourceView> > mTileSRVs;
std::vector<RefPtr<ID3D11Texture2D>> mTileTextures;
std::vector<RefPtr<ID3D11ShaderResourceView>> mTileSRVs;
RefPtr<ID3D11Device> mDevice;
gfx::SurfaceFormat mFormat;
TextureFlags mFlags;
@ -369,6 +376,7 @@ class DXGITextureHostD3D11 : public TextureHost {
RefPtr<ID3D11Device> mDevice;
RefPtr<ID3D11Texture2D> mTexture;
uint32_t mArrayIndex = 0;
RefPtr<DataTextureSourceD3D11> mTextureSource;
gfx::IntSize mSize;
WindowsHandle mHandle;

View File

@ -25,6 +25,7 @@ namespace layers {
[Comparable] struct SurfaceDescriptorD3D10 {
WindowsHandle handle;
uint32_t arrayIndex;
SurfaceFormat format;
IntSize size;
YUVColorSpace yUVColorSpace;

View File

@ -30,6 +30,7 @@ EXPORTS += [
if CONFIG["MOZ_WIDGET_TOOLKIT"] == "windows":
SOURCES += [
"D3D11ShareHandleImage.cpp",
"D3D11TextureIMFSampleImage.cpp",
"D3D11YCbCrImage.cpp",
]
UNIFIED_SOURCES += [
@ -126,6 +127,7 @@ EXPORTS.mozilla.layers += [
"CompositorAnimationStorage.h",
"CompositorTypes.h",
"D3D11ShareHandleImage.h",
"D3D11TextureIMFSampleImage.h",
"D3D11YCbCrImage.h",
"D3D9SurfaceImage.h",
"DirectionUtils.h",

View File

@ -999,7 +999,7 @@ bool DCSurfaceVideo::CallVideoProcessorBlt(RenderTextureHost* aTexture) {
D3D11_VIDEO_PROCESSOR_INPUT_VIEW_DESC inputDesc = {};
inputDesc.ViewDimension = D3D11_VPIV_DIMENSION_TEXTURE2D;
inputDesc.Texture2D.ArraySlice = 0;
inputDesc.Texture2D.ArraySlice = texture->ArrayIndex();
RefPtr<ID3D11VideoProcessorInputView> inputView;
hr = videoDevice->CreateVideoProcessorInputView(

View File

@ -18,11 +18,13 @@ namespace mozilla {
namespace wr {
RenderDXGITextureHost::RenderDXGITextureHost(WindowsHandle aHandle,
uint32_t aArrayIndex,
gfx::SurfaceFormat aFormat,
gfx::YUVColorSpace aYUVColorSpace,
gfx::ColorRange aColorRange,
gfx::IntSize aSize)
: mHandle(aHandle),
mArrayIndex(aArrayIndex),
mSurface(0),
mStream(0),
mTextureHandle{0},
@ -294,9 +296,15 @@ bool RenderDXGITextureHost::EnsureLockable(wr::ImageRendering aRendering) {
ok &= bool(egl->fCreateStreamProducerD3DTextureANGLE(mStream, nullptr));
}
const EGLAttrib frameAttributes[] = {
LOCAL_EGL_D3D_TEXTURE_SUBRESOURCE_ID_ANGLE,
static_cast<EGLAttrib>(mArrayIndex),
LOCAL_EGL_NONE,
};
// Insert the d3d texture.
ok &= bool(
egl->fStreamPostD3DTextureANGLE(mStream, (void*)mTexture.get(), nullptr));
ok &= bool(egl->fStreamPostD3DTextureANGLE(mStream, (void*)mTexture.get(),
frameAttributes));
if (!ok) {
gfxCriticalNote << "RenderDXGITextureHost init stream failed";

View File

@ -19,11 +19,10 @@ namespace wr {
class RenderDXGITextureHost final : public RenderTextureHostSWGL {
public:
explicit RenderDXGITextureHost(WindowsHandle aHandle,
gfx::SurfaceFormat aFormat,
gfx::YUVColorSpace aYUVColorSpace,
gfx::ColorRange aColorRange,
gfx::IntSize aSize);
RenderDXGITextureHost(WindowsHandle aHandle, uint32_t aArrayIndex,
gfx::SurfaceFormat aFormat,
gfx::YUVColorSpace aYUVColorSpace,
gfx::ColorRange aColorRange, gfx::IntSize aSize);
wr::WrExternalImage Lock(uint8_t aChannelIndex, gl::GLContext* aGL,
wr::ImageRendering aRendering) override;
@ -78,6 +77,8 @@ class RenderDXGITextureHost final : public RenderTextureHostSWGL {
return bytes;
}
uint32_t ArrayIndex() const { return mArrayIndex; }
private:
virtual ~RenderDXGITextureHost();
@ -90,6 +91,7 @@ class RenderDXGITextureHost final : public RenderTextureHostSWGL {
WindowsHandle mHandle;
RefPtr<ID3D11Texture2D> mTexture;
uint32_t mArrayIndex = 0;
RefPtr<IDXGIKeyedMutex> mKeyedMutex;
// Temporary state between MapPlane and UnmapPlanes.