mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-03-05 16:22:53 +00:00
Bug 1766282 - Do not use SharedHandle of ID3D11Texture2D of hardware decoded video during no video copy r=jgilbert,jrmuizel,gfx-reviewers
With CI's NVIDIA GPU, SharedHandle of ID3D11Texture2D of hardware decoded video during no video copy caused rendering problem. When SharedHandle is not used, the rendering problem did not happen. But when video is rendered to WebGL texture, SharedHandle need to be used. In this case, D3D11TextureIMFSampleImage copies original ID3D11Texture2D to a new ID3D11Texture2D and use a shared handled of the copied texture. And no video copy of future video frames are disabled. NoCopyNV12Texture is renamed to ZeroCopyNV12Texture to clarify its meaning. Differential Revision: https://phabricator.services.mozilla.com/D144598
This commit is contained in:
parent
eb18c942c1
commit
4f8549101c
@ -4219,6 +4219,15 @@ void ClientWebGLContext::TexImage(uint8_t funcDims, GLenum imageTarget,
|
||||
}
|
||||
}
|
||||
|
||||
if (sdType == layers::SurfaceDescriptor::TSurfaceDescriptorD3D10) {
|
||||
const auto& sdD3D = sd.get_SurfaceDescriptorD3D10();
|
||||
const auto& inProcess = mNotLost->inProcess;
|
||||
if (sdD3D.gpuProcessTextureId().isSome() && inProcess) {
|
||||
return Some(
|
||||
std::string{"gpuProcessTextureId works only in GPU process."});
|
||||
}
|
||||
}
|
||||
|
||||
if (StaticPrefs::webgl_disable_DOM_blit_uploads()) {
|
||||
return Some(std::string{"DOM blit uploads are disabled."});
|
||||
}
|
||||
|
@ -626,6 +626,7 @@ already_AddRefed<IDirectXVideoDecoder> D3D9DXVA2Manager::CreateDecoder(
|
||||
|
||||
class D3D11DXVA2Manager : public DXVA2Manager {
|
||||
public:
|
||||
D3D11DXVA2Manager();
|
||||
virtual ~D3D11DXVA2Manager();
|
||||
|
||||
HRESULT Init(layers::KnowsCompositor* aKnowsCompositor,
|
||||
@ -659,6 +660,14 @@ class D3D11DXVA2Manager : public DXVA2Manager {
|
||||
|
||||
void BeforeShutdownVideoMFTDecoder() override;
|
||||
|
||||
bool SupportsZeroCopyNV12Texture() override {
|
||||
if (mIMFSampleUsageInfo->SupportsZeroCopyNV12Texture() &&
|
||||
(mDevice != DeviceManagerDx::Get()->GetCompositorDevice())) {
|
||||
mIMFSampleUsageInfo->DisableZeroCopyNV12Texture();
|
||||
}
|
||||
return mIMFSampleUsageInfo->SupportsZeroCopyNV12Texture();
|
||||
}
|
||||
|
||||
private:
|
||||
HRESULT CreateOutputSample(RefPtr<IMFSample>& aSample,
|
||||
ID3D11Texture2D* aTexture);
|
||||
@ -686,6 +695,7 @@ class D3D11DXVA2Manager : public DXVA2Manager {
|
||||
gfx::YUVColorSpace mYUVColorSpace;
|
||||
gfx::ColorRange mColorRange = gfx::ColorRange::LIMITED;
|
||||
std::list<ThreadSafeWeakPtr<layers::IMFSampleWrapper>> mIMFSampleWrappers;
|
||||
RefPtr<layers::IMFSampleUsageInfo> mIMFSampleUsageInfo;
|
||||
};
|
||||
|
||||
bool D3D11DXVA2Manager::SupportsConfig(const VideoInfo& aInfo,
|
||||
@ -828,6 +838,9 @@ bool D3D11DXVA2Manager::SupportsConfig(const VideoInfo& aInfo,
|
||||
return CanCreateDecoder(desc);
|
||||
}
|
||||
|
||||
D3D11DXVA2Manager::D3D11DXVA2Manager()
|
||||
: mIMFSampleUsageInfo(new layers::IMFSampleUsageInfo) {}
|
||||
|
||||
D3D11DXVA2Manager::~D3D11DXVA2Manager() {}
|
||||
|
||||
IUnknown* D3D11DXVA2Manager::GetDXVADeviceManager() {
|
||||
@ -997,6 +1010,11 @@ D3D11DXVA2Manager::InitInternal(layers::KnowsCompositor* aKnowsCompositor,
|
||||
}
|
||||
}
|
||||
|
||||
if (!IsD3D11() || !XRE_IsGPUProcess() ||
|
||||
(mDevice != DeviceManagerDx::Get()->GetCompositorDevice())) {
|
||||
mIMFSampleUsageInfo->DisableZeroCopyNV12Texture();
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
@ -1153,7 +1171,7 @@ HRESULT D3D11DXVA2Manager::WrapTextureWithImage(IMFSample* aVideoSample,
|
||||
RefPtr<D3D11TextureIMFSampleImage> image = new D3D11TextureIMFSampleImage(
|
||||
aVideoSample, texture, arrayIndex, gfx::IntSize(mWidth, mHeight), aRegion,
|
||||
mYUVColorSpace, mColorRange);
|
||||
image->AllocateTextureClient(mKnowsCompositor);
|
||||
image->AllocateTextureClient(mKnowsCompositor, mIMFSampleUsageInfo);
|
||||
|
||||
RefPtr<IMFSampleWrapper> wrapper = image->GetIMFSampleWrapper();
|
||||
ThreadSafeWeakPtr<IMFSampleWrapper> weak(wrapper);
|
||||
|
@ -74,6 +74,8 @@ class DXVA2Manager {
|
||||
// Called before shutdown video MFTDecoder.
|
||||
virtual void BeforeShutdownVideoMFTDecoder() {}
|
||||
|
||||
virtual bool SupportsZeroCopyNV12Texture() { return false; }
|
||||
|
||||
static bool IsNV12Supported(uint32_t aVendorID, uint32_t aDeviceID,
|
||||
const nsAString& aDriverVersionString);
|
||||
|
||||
|
@ -139,7 +139,7 @@ WMFVideoMFTManager::WMFVideoMFTManager(
|
||||
mDXVAEnabled(aDXVAEnabled &&
|
||||
!aOptions.contains(
|
||||
CreateDecoderParams::Option::HardwareDecoderNotAllowed)),
|
||||
mNoCopyNV12Texture(false),
|
||||
mZeroCopyNV12Texture(false),
|
||||
mFramerate(aFramerate),
|
||||
mLowLatency(aOptions.contains(CreateDecoderParams::Option::LowLatency))
|
||||
// mVideoStride, mVideoWidth, mVideoHeight, mUseHwAccel are initialized in
|
||||
@ -335,10 +335,10 @@ MediaResult WMFVideoMFTManager::InitInternal() {
|
||||
}
|
||||
}
|
||||
|
||||
if (gfxVars::HwDecodedVideoNoCopy() && mKnowsCompositor &&
|
||||
if (gfxVars::HwDecodedVideoZeroCopy() && mKnowsCompositor &&
|
||||
mKnowsCompositor->UsingHardwareWebRender() && mDXVA2Manager &&
|
||||
mDXVA2Manager->IsD3D11() && XRE_IsGPUProcess()) {
|
||||
mNoCopyNV12Texture = true;
|
||||
mDXVA2Manager->SupportsZeroCopyNV12Texture()) {
|
||||
mZeroCopyNV12Texture = true;
|
||||
const int kOutputBufferSize = 10;
|
||||
|
||||
// Each picture buffer can store a sample, plus one in
|
||||
@ -522,7 +522,7 @@ WMFVideoMFTManager::SetDecoderMediaTypes() {
|
||||
hr = outputType->SetGUID(MF_MT_SUBTYPE, outputSubType);
|
||||
NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
|
||||
|
||||
if (mNoCopyNV12Texture) {
|
||||
if (mZeroCopyNV12Texture) {
|
||||
RefPtr<IMFAttributes> attr(mDecoder->GetOutputStreamAttributes());
|
||||
if (attr) {
|
||||
hr = attr->SetUINT32(MF_SA_D3D11_SHARED_WITHOUT_MUTEX, TRUE);
|
||||
@ -770,7 +770,7 @@ WMFVideoMFTManager::CreateD3DVideoFrame(IMFSample* aSample,
|
||||
gfx::IntRect pictureRegion =
|
||||
mVideoInfo.ScaledImageRect(mImageSize.width, mImageSize.height);
|
||||
RefPtr<Image> image;
|
||||
if (mNoCopyNV12Texture) {
|
||||
if (mZeroCopyNV12Texture && mDXVA2Manager->SupportsZeroCopyNV12Texture()) {
|
||||
hr = mDXVA2Manager->WrapTextureWithImage(aSample, pictureRegion,
|
||||
getter_AddRefs(image));
|
||||
} else {
|
||||
|
@ -95,7 +95,7 @@ class WMFVideoMFTManager : public MFTManager {
|
||||
bool mDXVAEnabled;
|
||||
bool mUseHwAccel;
|
||||
|
||||
bool mNoCopyNV12Texture;
|
||||
bool mZeroCopyNV12Texture;
|
||||
|
||||
nsCString mDXVAFailureReason;
|
||||
|
||||
|
@ -91,7 +91,7 @@ class gfxVarReceiver;
|
||||
_(AllowWebGPU, bool, false) \
|
||||
_(UseVP8HwDecode, bool, false) \
|
||||
_(UseVP9HwDecode, bool, false) \
|
||||
_(HwDecodedVideoNoCopy, bool, false)
|
||||
_(HwDecodedVideoZeroCopy, bool, false)
|
||||
|
||||
/* Add new entries above this line. */
|
||||
|
||||
|
@ -14,7 +14,6 @@
|
||||
#include "ScopedGLHelpers.h"
|
||||
|
||||
#include "mozilla/layers/D3D11ShareHandleImage.h"
|
||||
#include "mozilla/layers/D3D11TextureIMFSampleImage.h"
|
||||
#include "mozilla/layers/D3D11YCbCrImage.h"
|
||||
#include "mozilla/layers/TextureD3D11.h"
|
||||
|
||||
@ -224,6 +223,7 @@ bool GLBlitHelper::BlitDescriptor(const layers::SurfaceDescriptorD3D10& desc,
|
||||
if (!d3d) return false;
|
||||
|
||||
const auto& handle = desc.handle();
|
||||
const auto& gpuProcessTextureId = desc.gpuProcessTextureId();
|
||||
const auto& arrayIndex = desc.arrayIndex();
|
||||
const auto& format = desc.format();
|
||||
const auto& clipSize = desc.size();
|
||||
@ -240,7 +240,19 @@ bool GLBlitHelper::BlitDescriptor(const layers::SurfaceDescriptorD3D10& desc,
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto tex = OpenSharedTexture(d3d, handle);
|
||||
RefPtr<ID3D11Texture2D> tex;
|
||||
if (gpuProcessTextureId.isSome()) {
|
||||
auto* textureMap = layers::GpuProcessD3D11TextureMap::Get();
|
||||
if (textureMap) {
|
||||
Maybe<HANDLE> handle =
|
||||
textureMap->GetSharedHandleOfCopiedTexture(gpuProcessTextureId.ref());
|
||||
if (handle.isSome()) {
|
||||
tex = OpenSharedTexture(d3d, (WindowsHandle)handle.ref());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
tex = OpenSharedTexture(d3d, handle);
|
||||
}
|
||||
if (!tex) {
|
||||
MOZ_GL_ASSERT(mGL, false); // Get a nullptr from OpenSharedResource.
|
||||
return false;
|
||||
|
@ -142,8 +142,9 @@ Maybe<layers::SurfaceDescriptor>
|
||||
SharedSurface_ANGLEShareHandle::ToSurfaceDescriptor() {
|
||||
const auto format = gfx::SurfaceFormat::B8G8R8A8;
|
||||
return Some(layers::SurfaceDescriptorD3D10(
|
||||
(WindowsHandle)mShareHandle, /* arrayIndex */ 0, format, mDesc.size,
|
||||
gfx::YUVColorSpace::Identity, gfx::ColorRange::FULL));
|
||||
(WindowsHandle)mShareHandle, /* gpuProcessTextureId */ Nothing(),
|
||||
/* arrayIndex */ 0, format, mDesc.size, gfx::YUVColorSpace::Identity,
|
||||
gfx::ColorRange::FULL));
|
||||
}
|
||||
|
||||
class ScopedLockTexture final {
|
||||
|
@ -438,8 +438,9 @@ Maybe<layers::SurfaceDescriptor>
|
||||
SharedSurface_D3D11Interop::ToSurfaceDescriptor() {
|
||||
const auto format = gfx::SurfaceFormat::B8G8R8A8;
|
||||
return Some(layers::SurfaceDescriptorD3D10(
|
||||
WindowsHandle(mData.dxgiHandle), /* arrayIndex */ 0, format, mDesc.size,
|
||||
gfx::YUVColorSpace::Identity, gfx::ColorRange::FULL));
|
||||
WindowsHandle(mData.dxgiHandle), /* gpuProcessTextureId */ Nothing(),
|
||||
/* arrayIndex */ 0, format, mDesc.size, gfx::YUVColorSpace::Identity,
|
||||
gfx::ColorRange::FULL));
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -72,6 +72,7 @@
|
||||
# include "gfxWindowsPlatform.h"
|
||||
# include "mozilla/WindowsVersion.h"
|
||||
# include "mozilla/gfx/DeviceManagerDx.h"
|
||||
# include "mozilla/layers/TextureD3D11.h"
|
||||
# include "mozilla/widget/WinCompositorWindowThread.h"
|
||||
#else
|
||||
# include <unistd.h>
|
||||
@ -189,6 +190,7 @@ bool GPUParent::Init(base::ProcessId aParentPid, const char* aParentBuildID,
|
||||
#if defined(XP_WIN)
|
||||
gfxWindowsPlatform::InitMemoryReportersForGPUProcess();
|
||||
DeviceManagerDx::Init();
|
||||
GpuProcessD3D11TextureMap::Init();
|
||||
#endif
|
||||
|
||||
CompositorThreadHolder::Start();
|
||||
@ -721,6 +723,7 @@ void GPUParent::ActorDestroy(ActorDestroyReason aWhy) {
|
||||
#endif
|
||||
|
||||
#if defined(XP_WIN)
|
||||
GpuProcessD3D11TextureMap::Shutdown();
|
||||
DeviceManagerDx::Shutdown();
|
||||
#endif
|
||||
LayerTreeOwnerTracker::Shutdown();
|
||||
|
@ -48,10 +48,10 @@ D3D11TextureIMFSampleImage::D3D11TextureIMFSampleImage(
|
||||
}
|
||||
|
||||
void D3D11TextureIMFSampleImage::AllocateTextureClient(
|
||||
KnowsCompositor* aKnowsCompositor) {
|
||||
KnowsCompositor* aKnowsCompositor, RefPtr<IMFSampleUsageInfo> aUsageInfo) {
|
||||
mTextureClient = D3D11TextureData::CreateTextureClient(
|
||||
mTexture, mArrayIndex, mSize, gfx::SurfaceFormat::NV12, mYUVColorSpace,
|
||||
mColorRange, aKnowsCompositor);
|
||||
mColorRange, aKnowsCompositor, aUsageInfo);
|
||||
MOZ_ASSERT(mTextureClient);
|
||||
}
|
||||
|
||||
|
@ -37,6 +37,21 @@ class IMFSampleWrapper : public SupportsThreadSafeWeakPtr<IMFSampleWrapper> {
|
||||
RefPtr<IMFSample> mVideoSample;
|
||||
};
|
||||
|
||||
class IMFSampleUsageInfo final {
|
||||
public:
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(IMFSampleUsageInfo)
|
||||
|
||||
IMFSampleUsageInfo() = default;
|
||||
|
||||
bool SupportsZeroCopyNV12Texture() { return mSupportsZeroCopyNV12Texture; }
|
||||
void DisableZeroCopyNV12Texture() { mSupportsZeroCopyNV12Texture = false; }
|
||||
|
||||
protected:
|
||||
~IMFSampleUsageInfo() = default;
|
||||
|
||||
Atomic<bool> mSupportsZeroCopyNV12Texture{true};
|
||||
};
|
||||
|
||||
// Image class that wraps ID3D11Texture2D of IMFSample
|
||||
// Expected to be used in GPU process.
|
||||
class D3D11TextureIMFSampleImage final : public Image {
|
||||
@ -48,7 +63,8 @@ class D3D11TextureIMFSampleImage final : public Image {
|
||||
gfx::ColorRange aColorRange);
|
||||
virtual ~D3D11TextureIMFSampleImage() = default;
|
||||
|
||||
void AllocateTextureClient(KnowsCompositor* aKnowsCompositor);
|
||||
void AllocateTextureClient(KnowsCompositor* aKnowsCompositor,
|
||||
RefPtr<IMFSampleUsageInfo> aUsageInfo);
|
||||
|
||||
gfx::IntSize GetSize() const override;
|
||||
already_AddRefed<gfx::SourceSurface> GetAsSourceSurface() override;
|
||||
@ -72,7 +88,6 @@ class D3D11TextureIMFSampleImage final : public Image {
|
||||
|
||||
// When ref of IMFSample is held, its ID3D11Texture2D is not reused by
|
||||
// IMFTransform.
|
||||
// RefPtr<IMFSample> mVideoSample;
|
||||
RefPtr<IMFSampleWrapper> mVideoSample;
|
||||
RefPtr<ID3D11Texture2D> mTexture;
|
||||
const uint32_t mArrayIndex;
|
||||
|
@ -80,9 +80,10 @@ already_AddRefed<IDirect3DSurface9> DXGID3D9TextureData::GetD3D9Surface()
|
||||
}
|
||||
|
||||
bool DXGID3D9TextureData::Serialize(SurfaceDescriptor& aOutDescriptor) {
|
||||
SurfaceDescriptorD3D10 desc((WindowsHandle)(mHandle), /* arrayIndex */ 0,
|
||||
mFormat, GetSize(), gfx::YUVColorSpace::Identity,
|
||||
gfx::ColorRange::FULL);
|
||||
SurfaceDescriptorD3D10 desc(
|
||||
(WindowsHandle)(mHandle), /* gpuProcessTextureId */ Nothing(),
|
||||
/* 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 ||
|
||||
mFormat == gfx::SurfaceFormat::P010 ||
|
||||
|
@ -19,6 +19,8 @@
|
||||
#include "mozilla/gfx/Logging.h"
|
||||
#include "mozilla/gfx/gfxVars.h"
|
||||
#include "mozilla/layers/CompositorBridgeChild.h"
|
||||
#include "mozilla/layers/D3D11TextureIMFSampleImage.h"
|
||||
#include "mozilla/layers/HelpersD3D11.h"
|
||||
#include "mozilla/webrender/RenderD3D11TextureHost.h"
|
||||
#include "mozilla/webrender/RenderThread.h"
|
||||
#include "mozilla/webrender/WebRenderAPI.h"
|
||||
@ -313,6 +315,15 @@ D3D11TextureData::~D3D11TextureData() {
|
||||
if (mDrawTarget) {
|
||||
DestroyDrawTarget(mDrawTarget, mTexture);
|
||||
}
|
||||
|
||||
if (mGpuProcessTextureId.isSome()) {
|
||||
auto* textureMap = GpuProcessD3D11TextureMap::Get();
|
||||
if (textureMap) {
|
||||
textureMap->Unregister(mGpuProcessTextureId.ref());
|
||||
} else {
|
||||
gfxCriticalNoteOnce << "GpuProcessD3D11TextureMap does not exist";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool D3D11TextureData::Lock(OpenMode aMode) {
|
||||
@ -381,15 +392,17 @@ bool D3D11TextureData::SerializeSpecific(
|
||||
if (!resource) {
|
||||
return false;
|
||||
}
|
||||
HANDLE sharedHandle;
|
||||
HRESULT hr = resource->GetSharedHandle(&sharedHandle);
|
||||
if (FAILED(hr)) {
|
||||
LOGD3D11("Error getting shared handle for texture.");
|
||||
return false;
|
||||
HANDLE sharedHandle = 0;
|
||||
if (mGpuProcessTextureId.isNothing()) {
|
||||
HRESULT hr = resource->GetSharedHandle(&sharedHandle);
|
||||
if (FAILED(hr)) {
|
||||
LOGD3D11("Error getting shared handle for texture.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
*aOutDesc =
|
||||
SurfaceDescriptorD3D10((WindowsHandle)sharedHandle, mArrayIndex, mFormat,
|
||||
mSize, mYUVColorSpace, mColorRange);
|
||||
*aOutDesc = SurfaceDescriptorD3D10((WindowsHandle)sharedHandle,
|
||||
mGpuProcessTextureId, mArrayIndex, mFormat,
|
||||
mSize, mYUVColorSpace, mColorRange);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -413,7 +426,8 @@ void D3D11TextureData::GetSubDescriptor(
|
||||
already_AddRefed<TextureClient> D3D11TextureData::CreateTextureClient(
|
||||
ID3D11Texture2D* aTexture, uint32_t aIndex, gfx::IntSize aSize,
|
||||
gfx::SurfaceFormat aFormat, gfx::YUVColorSpace aColorSpace,
|
||||
gfx::ColorRange aColorRange, KnowsCompositor* aKnowsCompositor) {
|
||||
gfx::ColorRange aColorRange, KnowsCompositor* aKnowsCompositor,
|
||||
RefPtr<IMFSampleUsageInfo> aUsageInfo) {
|
||||
D3D11TextureData* data = new D3D11TextureData(
|
||||
aTexture, aIndex, aSize, aFormat,
|
||||
TextureAllocationFlags::ALLOC_MANUAL_SYNCHRONIZATION);
|
||||
@ -422,6 +436,16 @@ already_AddRefed<TextureClient> D3D11TextureData::CreateTextureClient(
|
||||
|
||||
RefPtr<TextureClient> textureClient = MakeAndAddRef<TextureClient>(
|
||||
data, TextureFlags::NO_FLAGS, aKnowsCompositor->GetTextureForwarder());
|
||||
const auto textureId = GpuProcessD3D11TextureMap::GetNextTextureId();
|
||||
data->SetGpuProcessTextureId(textureId);
|
||||
|
||||
// Register ID3D11Texture2D to GpuProcessD3D11TextureMap
|
||||
auto* textureMap = GpuProcessD3D11TextureMap::Get();
|
||||
if (textureMap) {
|
||||
textureMap->Register(textureId, aTexture, aIndex, aSize, aUsageInfo);
|
||||
} else {
|
||||
gfxCriticalNoteOnce << "GpuProcessD3D11TextureMap does not exist";
|
||||
}
|
||||
|
||||
return textureClient.forget();
|
||||
}
|
||||
@ -783,6 +807,7 @@ bool D3D11TextureData::UpdateFromSurface(gfx::SourceSurface* aSurface) {
|
||||
DXGITextureHostD3D11::DXGITextureHostD3D11(
|
||||
TextureFlags aFlags, const SurfaceDescriptorD3D10& aDescriptor)
|
||||
: TextureHost(aFlags),
|
||||
mGpuProcessTextureId(aDescriptor.gpuProcessTextureId()),
|
||||
mArrayIndex(aDescriptor.arrayIndex()),
|
||||
mSize(aDescriptor.size()),
|
||||
mHandle(aDescriptor.handle()),
|
||||
@ -792,6 +817,10 @@ DXGITextureHostD3D11::DXGITextureHostD3D11(
|
||||
mIsLocked(false) {}
|
||||
|
||||
bool DXGITextureHostD3D11::EnsureTexture() {
|
||||
if (mGpuProcessTextureId.isSome()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
RefPtr<ID3D11Device> device;
|
||||
if (mTexture) {
|
||||
mTexture->GetDevice(getter_AddRefs(device));
|
||||
@ -935,7 +964,8 @@ void DXGITextureHostD3D11::UnlockInternal() {
|
||||
void DXGITextureHostD3D11::CreateRenderTexture(
|
||||
const wr::ExternalImageId& aExternalImageId) {
|
||||
RefPtr<wr::RenderTextureHost> texture = new wr::RenderDXGITextureHost(
|
||||
mHandle, mArrayIndex, mFormat, mYUVColorSpace, mColorRange, mSize);
|
||||
mHandle, mGpuProcessTextureId, mArrayIndex, mFormat, mYUVColorSpace,
|
||||
mColorRange, mSize);
|
||||
wr::RenderThread::Get()->RegisterExternalImage(aExternalImageId,
|
||||
texture.forget());
|
||||
}
|
||||
@ -968,7 +998,7 @@ void DXGITextureHostD3D11::PushResourceUpdates(
|
||||
return;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(mHandle);
|
||||
MOZ_ASSERT(mHandle || mGpuProcessTextureId.isSome());
|
||||
auto method = aOp == TextureHost::ADD_IMAGE
|
||||
? &wr::TransactionBuilder::AddExternalImage
|
||||
: &wr::TransactionBuilder::UpdateExternalImage;
|
||||
@ -1764,5 +1794,183 @@ void SyncObjectD3D11ClientContentDevice::EnsureInitialized() {
|
||||
mContentDevice = DeviceManagerDx::Get()->GetContentDevice();
|
||||
}
|
||||
|
||||
StaticAutoPtr<GpuProcessD3D11TextureMap> GpuProcessD3D11TextureMap::sInstance;
|
||||
|
||||
/* static */
|
||||
void GpuProcessD3D11TextureMap::Init() {
|
||||
MOZ_ASSERT(XRE_IsGPUProcess());
|
||||
sInstance = new GpuProcessD3D11TextureMap();
|
||||
}
|
||||
|
||||
/* static */
|
||||
void GpuProcessD3D11TextureMap::Shutdown() {
|
||||
MOZ_ASSERT(XRE_IsGPUProcess());
|
||||
sInstance = nullptr;
|
||||
}
|
||||
|
||||
/* static */
|
||||
uint64_t GpuProcessD3D11TextureMap::GetNextTextureId() {
|
||||
MOZ_ASSERT(XRE_IsGPUProcess());
|
||||
|
||||
static std::atomic<uint64_t> sNextId = 0;
|
||||
uint64_t id = ++sNextId;
|
||||
return id;
|
||||
}
|
||||
|
||||
GpuProcessD3D11TextureMap::GpuProcessD3D11TextureMap()
|
||||
: mD3D11TexturesById("D3D11TextureMap::mD3D11TexturesById") {}
|
||||
|
||||
GpuProcessD3D11TextureMap::~GpuProcessD3D11TextureMap() {}
|
||||
|
||||
void GpuProcessD3D11TextureMap::Register(
|
||||
uint64_t aTextureId, ID3D11Texture2D* aTexture, uint32_t aArrayIndex,
|
||||
const gfx::IntSize& aSize, RefPtr<IMFSampleUsageInfo> aUsageInfo) {
|
||||
MOZ_RELEASE_ASSERT(aTexture);
|
||||
MOZ_RELEASE_ASSERT(aUsageInfo);
|
||||
|
||||
auto textures = mD3D11TexturesById.Lock();
|
||||
|
||||
auto it = textures->find(aTextureId);
|
||||
if (it != textures->end()) {
|
||||
MOZ_ASSERT_UNREACHABLE("unexpected to be called");
|
||||
return;
|
||||
}
|
||||
textures->emplace(aTextureId,
|
||||
TextureHolder(aTexture, aArrayIndex, aSize, aUsageInfo));
|
||||
}
|
||||
|
||||
void GpuProcessD3D11TextureMap::Unregister(uint64_t aTextureId) {
|
||||
auto textures = mD3D11TexturesById.Lock();
|
||||
|
||||
auto it = textures->find(aTextureId);
|
||||
if (it == textures->end()) {
|
||||
return;
|
||||
}
|
||||
textures->erase(it);
|
||||
}
|
||||
|
||||
RefPtr<ID3D11Texture2D> GpuProcessD3D11TextureMap::GetTexture(
|
||||
uint64_t aTextureId) {
|
||||
auto textures = mD3D11TexturesById.Lock();
|
||||
|
||||
auto it = textures->find(aTextureId);
|
||||
if (it == textures->end()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return it->second.mTexture;
|
||||
}
|
||||
|
||||
Maybe<HANDLE> GpuProcessD3D11TextureMap::GetSharedHandleOfCopiedTexture(
|
||||
uint64_t aTextureId) {
|
||||
TextureHolder holder;
|
||||
{
|
||||
auto textures = mD3D11TexturesById.Lock();
|
||||
|
||||
auto it = textures->find(aTextureId);
|
||||
if (it == textures->end()) {
|
||||
return Nothing();
|
||||
}
|
||||
|
||||
if (it->second.mCopiedTextureSharedHandle.isSome()) {
|
||||
return it->second.mCopiedTextureSharedHandle;
|
||||
}
|
||||
|
||||
holder = it->second;
|
||||
}
|
||||
|
||||
RefPtr<ID3D11Device> device;
|
||||
holder.mTexture->GetDevice(getter_AddRefs(device));
|
||||
if (!device) {
|
||||
return Nothing();
|
||||
}
|
||||
|
||||
RefPtr<ID3D11DeviceContext> context;
|
||||
device->GetImmediateContext(getter_AddRefs(context));
|
||||
if (!context) {
|
||||
return Nothing();
|
||||
}
|
||||
|
||||
CD3D11_TEXTURE2D_DESC newDesc(
|
||||
DXGI_FORMAT_NV12, holder.mSize.width, holder.mSize.height, 1, 1,
|
||||
D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE);
|
||||
newDesc.MiscFlags = D3D11_RESOURCE_MISC_SHARED;
|
||||
|
||||
RefPtr<ID3D11Texture2D> copiedTexture;
|
||||
HRESULT hr =
|
||||
device->CreateTexture2D(&newDesc, nullptr, getter_AddRefs(copiedTexture));
|
||||
if (FAILED(hr)) {
|
||||
return Nothing();
|
||||
}
|
||||
|
||||
D3D11_TEXTURE2D_DESC inDesc;
|
||||
holder.mTexture->GetDesc(&inDesc);
|
||||
|
||||
D3D11_TEXTURE2D_DESC outDesc;
|
||||
copiedTexture->GetDesc(&outDesc);
|
||||
|
||||
UINT height = std::min(inDesc.Height, outDesc.Height);
|
||||
UINT width = std::min(inDesc.Width, outDesc.Width);
|
||||
D3D11_BOX srcBox = {0, 0, 0, width, height, 1};
|
||||
|
||||
context->CopySubresourceRegion(copiedTexture, 0, 0, 0, 0, holder.mTexture,
|
||||
holder.mArrayIndex, &srcBox);
|
||||
|
||||
RefPtr<IDXGIResource> resource;
|
||||
copiedTexture->QueryInterface((IDXGIResource**)getter_AddRefs(resource));
|
||||
if (!resource) {
|
||||
return Nothing();
|
||||
}
|
||||
|
||||
HANDLE sharedHandle;
|
||||
hr = resource->GetSharedHandle(&sharedHandle);
|
||||
if (FAILED(hr)) {
|
||||
return Nothing();
|
||||
}
|
||||
|
||||
RefPtr<ID3D11Query> query;
|
||||
CD3D11_QUERY_DESC desc(D3D11_QUERY_EVENT);
|
||||
hr = device->CreateQuery(&desc, getter_AddRefs(query));
|
||||
if (FAILED(hr) || !query) {
|
||||
gfxWarning() << "Could not create D3D11_QUERY_EVENT: " << gfx::hexa(hr);
|
||||
return Nothing();
|
||||
}
|
||||
|
||||
context->End(query);
|
||||
|
||||
BOOL result;
|
||||
bool ret = WaitForFrameGPUQuery(device, context, query, &result);
|
||||
if (!ret) {
|
||||
gfxCriticalNoteOnce << "WaitForFrameGPUQuery() failed";
|
||||
}
|
||||
|
||||
{
|
||||
auto textures = mD3D11TexturesById.Lock();
|
||||
|
||||
auto it = textures->find(aTextureId);
|
||||
if (it == textures->end()) {
|
||||
MOZ_ASSERT_UNREACHABLE("unexpected to be called");
|
||||
return Nothing();
|
||||
}
|
||||
|
||||
// Disable no video copy for future decoded video frames. Since
|
||||
// GetSharedHandleOfCopiedTexture() is slow.
|
||||
it->second.mIMFSampleUsageInfo->DisableZeroCopyNV12Texture();
|
||||
|
||||
it->second.mCopiedTexture = copiedTexture;
|
||||
it->second.mCopiedTextureSharedHandle = Some(sharedHandle);
|
||||
}
|
||||
|
||||
return Some(sharedHandle);
|
||||
}
|
||||
|
||||
GpuProcessD3D11TextureMap::TextureHolder::TextureHolder(
|
||||
ID3D11Texture2D* aTexture, uint32_t aArrayIndex, const gfx::IntSize& aSize,
|
||||
RefPtr<IMFSampleUsageInfo> aUsageInfo)
|
||||
: mTexture(aTexture),
|
||||
mArrayIndex(aArrayIndex),
|
||||
mSize(aSize),
|
||||
mIMFSampleUsageInfo(aUsageInfo) {}
|
||||
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
||||
|
@ -13,6 +13,7 @@
|
||||
|
||||
#include "d3d9.h"
|
||||
#include "gfxWindowsPlatform.h"
|
||||
#include "mozilla/DataMutex.h"
|
||||
#include "mozilla/GfxMessageUtils.h"
|
||||
#include "mozilla/Maybe.h"
|
||||
#include "mozilla/gfx/2D.h"
|
||||
@ -44,6 +45,7 @@ class MOZ_RAII AutoTextureLock final {
|
||||
};
|
||||
|
||||
class CompositorD3D11;
|
||||
class IMFSampleUsageInfo;
|
||||
|
||||
class D3D11TextureData final : public TextureData {
|
||||
public:
|
||||
@ -59,7 +61,8 @@ class D3D11TextureData final : public TextureData {
|
||||
static already_AddRefed<TextureClient> CreateTextureClient(
|
||||
ID3D11Texture2D* aTexture, uint32_t aIndex, gfx::IntSize aSize,
|
||||
gfx::SurfaceFormat aFormat, gfx::YUVColorSpace aColorSpace,
|
||||
gfx::ColorRange aColorRange, KnowsCompositor* aKnowsCompositor);
|
||||
gfx::ColorRange aColorRange, KnowsCompositor* aKnowsCompositor,
|
||||
RefPtr<IMFSampleUsageInfo> aUsageInfo);
|
||||
|
||||
virtual ~D3D11TextureData();
|
||||
|
||||
@ -104,6 +107,12 @@ class D3D11TextureData final : public TextureData {
|
||||
|
||||
TextureFlags GetTextureFlags() const override;
|
||||
|
||||
void SetGpuProcessTextureId(uint64_t aTextureId) {
|
||||
mGpuProcessTextureId = Some(aTextureId);
|
||||
}
|
||||
|
||||
Maybe<uint64_t> GetGpuProcessTextureId() { return mGpuProcessTextureId; }
|
||||
|
||||
private:
|
||||
D3D11TextureData(ID3D11Texture2D* aTexture, uint32_t aArrayIndex,
|
||||
gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
|
||||
@ -133,6 +142,7 @@ class D3D11TextureData final : public TextureData {
|
||||
const bool mHasSynchronization;
|
||||
|
||||
RefPtr<ID3D11Texture2D> mTexture;
|
||||
Maybe<uint64_t> mGpuProcessTextureId;
|
||||
uint32_t mArrayIndex = 0;
|
||||
const TextureAllocationFlags mAllocationFlags;
|
||||
};
|
||||
@ -376,6 +386,7 @@ class DXGITextureHostD3D11 : public TextureHost {
|
||||
|
||||
RefPtr<ID3D11Device> mDevice;
|
||||
RefPtr<ID3D11Texture2D> mTexture;
|
||||
Maybe<uint64_t> mGpuProcessTextureId;
|
||||
uint32_t mArrayIndex = 0;
|
||||
RefPtr<DataTextureSourceD3D11> mTextureSource;
|
||||
gfx::IntSize mSize;
|
||||
@ -584,6 +595,49 @@ class D3D11MTAutoEnter {
|
||||
RefPtr<ID3D10Multithread> mMT;
|
||||
};
|
||||
|
||||
/**
|
||||
* A class to manage ID3D11Texture2Ds that is shared without using shared handle
|
||||
* in GPU process. On some GPUs, ID3D11Texture2Ds of hardware decoded video
|
||||
* frames with zero video frame copy could not use shared handle.
|
||||
*/
|
||||
class GpuProcessD3D11TextureMap {
|
||||
public:
|
||||
static void Init();
|
||||
static void Shutdown();
|
||||
static GpuProcessD3D11TextureMap* Get() { return sInstance; }
|
||||
static uint64_t GetNextTextureId();
|
||||
|
||||
GpuProcessD3D11TextureMap();
|
||||
~GpuProcessD3D11TextureMap();
|
||||
|
||||
void Register(uint64_t aTextureId, ID3D11Texture2D* aTexture,
|
||||
uint32_t aArrayIndex, const gfx::IntSize& aSize,
|
||||
RefPtr<IMFSampleUsageInfo> aUsageInfo);
|
||||
void Unregister(uint64_t aTextureId);
|
||||
|
||||
RefPtr<ID3D11Texture2D> GetTexture(uint64_t aTextureId);
|
||||
Maybe<HANDLE> GetSharedHandleOfCopiedTexture(uint64_t aTextureId);
|
||||
|
||||
private:
|
||||
struct TextureHolder {
|
||||
TextureHolder(ID3D11Texture2D* aTexture, uint32_t aArrayIndex,
|
||||
const gfx::IntSize& aSize,
|
||||
RefPtr<IMFSampleUsageInfo> aUsageInfo);
|
||||
TextureHolder() = default;
|
||||
|
||||
RefPtr<ID3D11Texture2D> mTexture;
|
||||
uint32_t mArrayIndex = 0;
|
||||
gfx::IntSize mSize;
|
||||
RefPtr<IMFSampleUsageInfo> mIMFSampleUsageInfo;
|
||||
RefPtr<ID3D11Texture2D> mCopiedTexture;
|
||||
Maybe<HANDLE> mCopiedTextureSharedHandle;
|
||||
};
|
||||
|
||||
DataMutex<std::unordered_map<uint64_t, TextureHolder>> mD3D11TexturesById;
|
||||
|
||||
static StaticAutoPtr<GpuProcessD3D11TextureMap> sInstance;
|
||||
};
|
||||
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
||||
|
||||
|
@ -27,6 +27,7 @@ namespace layers {
|
||||
|
||||
[Comparable] struct SurfaceDescriptorD3D10 {
|
||||
WindowsHandle handle;
|
||||
uint64_t? gpuProcessTextureId;
|
||||
uint32_t arrayIndex;
|
||||
SurfaceFormat format;
|
||||
IntSize size;
|
||||
|
@ -2698,16 +2698,16 @@ void gfxPlatform::InitWebRenderConfig() {
|
||||
gfxVars::SetUseWebRenderDCompVideoOverlayWin(true);
|
||||
}
|
||||
|
||||
bool useHwVideoNoCopy = false;
|
||||
if (StaticPrefs::media_wmf_no_copy_nv12_textures_AtStartup()) {
|
||||
bool useHwVideoZeroCopy = false;
|
||||
if (StaticPrefs::media_wmf_zero_copy_nv12_textures_AtStartup()) {
|
||||
// XXX relax limitation to Windows 8.1
|
||||
if (IsWin10OrLater() && hasHardware) {
|
||||
useHwVideoNoCopy = true;
|
||||
useHwVideoZeroCopy = true;
|
||||
}
|
||||
|
||||
if (useHwVideoNoCopy &&
|
||||
if (useHwVideoZeroCopy &&
|
||||
!StaticPrefs::
|
||||
media_wmf_no_copy_nv12_textures_force_enabled_AtStartup()) {
|
||||
media_wmf_zero_copy_nv12_textures_force_enabled_AtStartup()) {
|
||||
nsCString failureId;
|
||||
int32_t status;
|
||||
const nsCOMPtr<nsIGfxInfo> gfxInfo = components::GfxInfo::Service();
|
||||
@ -2719,24 +2719,24 @@ void gfxPlatform::InitWebRenderConfig() {
|
||||
feature.DisableByDefault(FeatureStatus::BlockedNoGfxInfo,
|
||||
"gfxInfo is broken",
|
||||
"FEATURE_FAILURE_WR_NO_GFX_INFO"_ns);
|
||||
useHwVideoNoCopy = false;
|
||||
useHwVideoZeroCopy = false;
|
||||
} else {
|
||||
if (status != nsIGfxInfo::FEATURE_ALLOW_ALWAYS) {
|
||||
FeatureState& feature =
|
||||
gfxConfig::GetFeature(Feature::HW_DECODED_VIDEO_NO_COPY);
|
||||
feature.DisableByDefault(FeatureStatus::Blocked,
|
||||
"Blocklisted by gfxInfo", failureId);
|
||||
useHwVideoNoCopy = false;
|
||||
useHwVideoZeroCopy = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (useHwVideoNoCopy) {
|
||||
if (useHwVideoZeroCopy) {
|
||||
FeatureState& feature =
|
||||
gfxConfig::GetFeature(Feature::HW_DECODED_VIDEO_NO_COPY);
|
||||
feature.EnableByDefault();
|
||||
gfxVars::SetHwDecodedVideoNoCopy(true);
|
||||
gfxVars::SetHwDecodedVideoZeroCopy(true);
|
||||
}
|
||||
|
||||
if (Preferences::GetBool("gfx.webrender.flip-sequential", false)) {
|
||||
|
@ -17,13 +17,13 @@
|
||||
namespace mozilla {
|
||||
namespace wr {
|
||||
|
||||
RenderDXGITextureHost::RenderDXGITextureHost(WindowsHandle aHandle,
|
||||
uint32_t aArrayIndex,
|
||||
gfx::SurfaceFormat aFormat,
|
||||
gfx::YUVColorSpace aYUVColorSpace,
|
||||
gfx::ColorRange aColorRange,
|
||||
gfx::IntSize aSize)
|
||||
RenderDXGITextureHost::RenderDXGITextureHost(
|
||||
WindowsHandle aHandle, Maybe<uint64_t>& aGpuProcessTextureId,
|
||||
uint32_t aArrayIndex, gfx::SurfaceFormat aFormat,
|
||||
gfx::YUVColorSpace aYUVColorSpace, gfx::ColorRange aColorRange,
|
||||
gfx::IntSize aSize)
|
||||
: mHandle(aHandle),
|
||||
mGpuProcessTextureId(aGpuProcessTextureId),
|
||||
mArrayIndex(aArrayIndex),
|
||||
mSurface(0),
|
||||
mStream(0),
|
||||
@ -38,7 +38,8 @@ RenderDXGITextureHost::RenderDXGITextureHost(WindowsHandle aHandle,
|
||||
mFormat != gfx::SurfaceFormat::P010 &&
|
||||
mFormat != gfx::SurfaceFormat::P016) ||
|
||||
(mSize.width % 2 == 0 && mSize.height % 2 == 0));
|
||||
MOZ_ASSERT(aHandle);
|
||||
MOZ_ASSERT((aHandle && aGpuProcessTextureId.isNothing()) ||
|
||||
(!aHandle && aGpuProcessTextureId.isSome()));
|
||||
}
|
||||
|
||||
RenderDXGITextureHost::~RenderDXGITextureHost() {
|
||||
@ -159,6 +160,18 @@ bool RenderDXGITextureHost::EnsureD3D11Texture2DWithGL() {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (mGpuProcessTextureId.isSome()) {
|
||||
auto* textureMap = layers::GpuProcessD3D11TextureMap::Get();
|
||||
if (textureMap) {
|
||||
RefPtr<ID3D11Texture2D> texture;
|
||||
mTexture = textureMap->GetTexture(mGpuProcessTextureId.ref());
|
||||
if (mTexture) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto& gle = gl::GLContextEGL::Cast(mGL);
|
||||
const auto& egl = gle->mEgl;
|
||||
|
||||
|
@ -19,8 +19,9 @@ namespace wr {
|
||||
|
||||
class RenderDXGITextureHost final : public RenderTextureHostSWGL {
|
||||
public:
|
||||
RenderDXGITextureHost(WindowsHandle aHandle, uint32_t aArrayIndex,
|
||||
gfx::SurfaceFormat aFormat,
|
||||
RenderDXGITextureHost(WindowsHandle aHandle,
|
||||
Maybe<uint64_t>& aGpuProcessTextureId,
|
||||
uint32_t aArrayIndex, gfx::SurfaceFormat aFormat,
|
||||
gfx::YUVColorSpace aYUVColorSpace,
|
||||
gfx::ColorRange aColorRange, gfx::IntSize aSize);
|
||||
|
||||
@ -90,6 +91,7 @@ class RenderDXGITextureHost final : public RenderTextureHostSWGL {
|
||||
RefPtr<gl::GLContext> mGL;
|
||||
|
||||
WindowsHandle mHandle;
|
||||
Maybe<uint64_t> mGpuProcessTextureId;
|
||||
RefPtr<ID3D11Texture2D> mTexture;
|
||||
uint32_t mArrayIndex = 0;
|
||||
RefPtr<IDXGIKeyedMutex> mKeyedMutex;
|
||||
|
@ -9076,12 +9076,12 @@
|
||||
value: true
|
||||
mirror: always
|
||||
|
||||
- name: media.wmf.no-copy-nv12-textures
|
||||
- name: media.wmf.zero-copy-nv12-textures
|
||||
type: bool
|
||||
value: true
|
||||
mirror: once
|
||||
# Enable hardware decoded video no copy even when it is blocked.
|
||||
- name: media.wmf.no-copy-nv12-textures-force-enabled
|
||||
- name: media.wmf.zero-copy-nv12-textures-force-enabled
|
||||
type: bool
|
||||
value: false
|
||||
mirror: once
|
||||
|
Loading…
x
Reference in New Issue
Block a user