diff --git a/gfx/gl/GLBlitHelperD3D.cpp b/gfx/gl/GLBlitHelperD3D.cpp index 8dda3e45fd37..2c4e96719e04 100644 --- a/gfx/gl/GLBlitHelperD3D.cpp +++ b/gfx/gl/GLBlitHelperD3D.cpp @@ -16,6 +16,7 @@ #include "mozilla/layers/D3D11ShareHandleImage.h" #include "mozilla/layers/D3D11TextureIMFSampleImage.h" #include "mozilla/layers/D3D11YCbCrImage.h" +#include "mozilla/layers/GpuProcessD3D11TextureMap.h" #include "mozilla/layers/TextureD3D11.h" #include "mozilla/StaticPrefs_gl.h" diff --git a/gfx/ipc/GPUParent.cpp b/gfx/ipc/GPUParent.cpp index f13e5d91e03e..d8705880f702 100644 --- a/gfx/ipc/GPUParent.cpp +++ b/gfx/ipc/GPUParent.cpp @@ -73,6 +73,7 @@ # include "gfxWindowsPlatform.h" # include "mozilla/WindowsVersion.h" # include "mozilla/gfx/DeviceManagerDx.h" +# include "mozilla/layers/GpuProcessD3D11TextureMap.h" # include "mozilla/layers/TextureD3D11.h" # include "mozilla/widget/WinCompositorWindowThread.h" #else diff --git a/gfx/layers/d3d11/GpuProcessD3D11TextureMap.cpp b/gfx/layers/d3d11/GpuProcessD3D11TextureMap.cpp new file mode 100644 index 000000000000..d5a0f5a82caf --- /dev/null +++ b/gfx/layers/d3d11/GpuProcessD3D11TextureMap.cpp @@ -0,0 +1,193 @@ +/* -*- 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 "GpuProcessD3D11TextureMap.h" + +#include "mozilla/layers/D3D11TextureIMFSampleImage.h" +#include "mozilla/layers/HelpersD3D11.h" + +namespace mozilla { + +namespace layers { + +StaticAutoPtr GpuProcessD3D11TextureMap::sInstance; + +/* static */ +void GpuProcessD3D11TextureMap::Init() { + MOZ_ASSERT(XRE_IsGPUProcess()); + sInstance = new GpuProcessD3D11TextureMap(); +} + +/* static */ +void GpuProcessD3D11TextureMap::Shutdown() { + MOZ_ASSERT(XRE_IsGPUProcess()); + sInstance = nullptr; +} + +/* static */ +GpuProcessTextureId GpuProcessD3D11TextureMap::GetNextTextureId() { + MOZ_ASSERT(XRE_IsGPUProcess()); + return GpuProcessTextureId::GetNext(); +} + +GpuProcessD3D11TextureMap::GpuProcessD3D11TextureMap() + : mD3D11TexturesById("D3D11TextureMap::mD3D11TexturesById") {} + +GpuProcessD3D11TextureMap::~GpuProcessD3D11TextureMap() {} + +void GpuProcessD3D11TextureMap::Register( + GpuProcessTextureId aTextureId, ID3D11Texture2D* aTexture, + uint32_t aArrayIndex, const gfx::IntSize& aSize, + RefPtr 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(GpuProcessTextureId aTextureId) { + auto textures = mD3D11TexturesById.Lock(); + + auto it = textures->find(aTextureId); + if (it == textures->end()) { + return; + } + textures->erase(it); +} + +RefPtr GpuProcessD3D11TextureMap::GetTexture( + GpuProcessTextureId aTextureId) { + auto textures = mD3D11TexturesById.Lock(); + + auto it = textures->find(aTextureId); + if (it == textures->end()) { + return nullptr; + } + + return it->second.mTexture; +} + +Maybe GpuProcessD3D11TextureMap::GetSharedHandleOfCopiedTexture( + GpuProcessTextureId 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 device; + holder.mTexture->GetDevice(getter_AddRefs(device)); + if (!device) { + return Nothing(); + } + + RefPtr 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 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 resource; + copiedTexture->QueryInterface((IDXGIResource**)getter_AddRefs(resource)); + if (!resource) { + return Nothing(); + } + + HANDLE sharedHandle; + hr = resource->GetSharedHandle(&sharedHandle); + if (FAILED(hr)) { + return Nothing(); + } + + RefPtr 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 aUsageInfo) + : mTexture(aTexture), + mArrayIndex(aArrayIndex), + mSize(aSize), + mIMFSampleUsageInfo(aUsageInfo) {} + +} // namespace layers +} // namespace mozilla diff --git a/gfx/layers/d3d11/GpuProcessD3D11TextureMap.h b/gfx/layers/d3d11/GpuProcessD3D11TextureMap.h new file mode 100644 index 000000000000..96668fa1b895 --- /dev/null +++ b/gfx/layers/d3d11/GpuProcessD3D11TextureMap.h @@ -0,0 +1,72 @@ +/* -*- 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 MOZILLA_GFX_GpuProcessD3D11TextureMap_H +#define MOZILLA_GFX_GpuProcessD3D11TextureMap_H + +#include +#include + +#include "mozilla/DataMutex.h" +#include "mozilla/gfx/2D.h" +#include "mozilla/layers/LayersTypes.h" +#include "mozilla/Maybe.h" +#include "mozilla/StaticPtr.h" + +namespace mozilla { +namespace layers { + +class IMFSampleUsageInfo; + +/** + * 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 GpuProcessTextureId GetNextTextureId(); + + GpuProcessD3D11TextureMap(); + ~GpuProcessD3D11TextureMap(); + + void Register(GpuProcessTextureId aTextureId, ID3D11Texture2D* aTexture, + uint32_t aArrayIndex, const gfx::IntSize& aSize, + RefPtr aUsageInfo); + void Unregister(GpuProcessTextureId aTextureId); + + RefPtr GetTexture(GpuProcessTextureId aTextureId); + Maybe GetSharedHandleOfCopiedTexture(GpuProcessTextureId aTextureId); + + private: + struct TextureHolder { + TextureHolder(ID3D11Texture2D* aTexture, uint32_t aArrayIndex, + const gfx::IntSize& aSize, + RefPtr aUsageInfo); + TextureHolder() = default; + + RefPtr mTexture; + uint32_t mArrayIndex = 0; + gfx::IntSize mSize; + RefPtr mIMFSampleUsageInfo; + RefPtr mCopiedTexture; + Maybe mCopiedTextureSharedHandle; + }; + + DataMutex> + mD3D11TexturesById; + + static StaticAutoPtr sInstance; +}; + +} // namespace layers +} // namespace mozilla + +#endif /* MOZILLA_GFX_GpuProcessD3D11TextureMap_H */ diff --git a/gfx/layers/d3d11/TextureD3D11.cpp b/gfx/layers/d3d11/TextureD3D11.cpp index 675d40c62f23..009d38e55c42 100644 --- a/gfx/layers/d3d11/TextureD3D11.cpp +++ b/gfx/layers/d3d11/TextureD3D11.cpp @@ -20,6 +20,7 @@ #include "mozilla/gfx/gfxVars.h" #include "mozilla/layers/CompositorBridgeChild.h" #include "mozilla/layers/D3D11TextureIMFSampleImage.h" +#include "mozilla/layers/GpuProcessD3D11TextureMap.h" #include "mozilla/layers/HelpersD3D11.h" #include "mozilla/webrender/RenderD3D11TextureHost.h" #include "mozilla/webrender/RenderThread.h" @@ -1778,181 +1779,5 @@ void SyncObjectD3D11ClientContentDevice::EnsureInitialized() { mContentDevice = DeviceManagerDx::Get()->GetContentDevice(); } -StaticAutoPtr GpuProcessD3D11TextureMap::sInstance; - -/* static */ -void GpuProcessD3D11TextureMap::Init() { - MOZ_ASSERT(XRE_IsGPUProcess()); - sInstance = new GpuProcessD3D11TextureMap(); -} - -/* static */ -void GpuProcessD3D11TextureMap::Shutdown() { - MOZ_ASSERT(XRE_IsGPUProcess()); - sInstance = nullptr; -} - -/* static */ -GpuProcessTextureId GpuProcessD3D11TextureMap::GetNextTextureId() { - MOZ_ASSERT(XRE_IsGPUProcess()); - return GpuProcessTextureId::GetNext(); -} - -GpuProcessD3D11TextureMap::GpuProcessD3D11TextureMap() - : mD3D11TexturesById("D3D11TextureMap::mD3D11TexturesById") {} - -GpuProcessD3D11TextureMap::~GpuProcessD3D11TextureMap() {} - -void GpuProcessD3D11TextureMap::Register( - GpuProcessTextureId aTextureId, ID3D11Texture2D* aTexture, - uint32_t aArrayIndex, const gfx::IntSize& aSize, - RefPtr 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(GpuProcessTextureId aTextureId) { - auto textures = mD3D11TexturesById.Lock(); - - auto it = textures->find(aTextureId); - if (it == textures->end()) { - return; - } - textures->erase(it); -} - -RefPtr GpuProcessD3D11TextureMap::GetTexture( - GpuProcessTextureId aTextureId) { - auto textures = mD3D11TexturesById.Lock(); - - auto it = textures->find(aTextureId); - if (it == textures->end()) { - return nullptr; - } - - return it->second.mTexture; -} - -Maybe GpuProcessD3D11TextureMap::GetSharedHandleOfCopiedTexture( - GpuProcessTextureId 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 device; - holder.mTexture->GetDevice(getter_AddRefs(device)); - if (!device) { - return Nothing(); - } - - RefPtr 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 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 resource; - copiedTexture->QueryInterface((IDXGIResource**)getter_AddRefs(resource)); - if (!resource) { - return Nothing(); - } - - HANDLE sharedHandle; - hr = resource->GetSharedHandle(&sharedHandle); - if (FAILED(hr)) { - return Nothing(); - } - - RefPtr 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 aUsageInfo) - : mTexture(aTexture), - mArrayIndex(aArrayIndex), - mSize(aSize), - mIMFSampleUsageInfo(aUsageInfo) {} - } // namespace layers } // namespace mozilla diff --git a/gfx/layers/d3d11/TextureD3D11.h b/gfx/layers/d3d11/TextureD3D11.h index 2947f114a8ca..1b64fc52f823 100644 --- a/gfx/layers/d3d11/TextureD3D11.h +++ b/gfx/layers/d3d11/TextureD3D11.h @@ -599,51 +599,6 @@ class D3D11MTAutoEnter { RefPtr 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 GpuProcessTextureId GetNextTextureId(); - - GpuProcessD3D11TextureMap(); - ~GpuProcessD3D11TextureMap(); - - void Register(GpuProcessTextureId aTextureId, ID3D11Texture2D* aTexture, - uint32_t aArrayIndex, const gfx::IntSize& aSize, - RefPtr aUsageInfo); - void Unregister(GpuProcessTextureId aTextureId); - - RefPtr GetTexture(GpuProcessTextureId aTextureId); - Maybe GetSharedHandleOfCopiedTexture(GpuProcessTextureId aTextureId); - - private: - struct TextureHolder { - TextureHolder(ID3D11Texture2D* aTexture, uint32_t aArrayIndex, - const gfx::IntSize& aSize, - RefPtr aUsageInfo); - TextureHolder() = default; - - RefPtr mTexture; - uint32_t mArrayIndex = 0; - gfx::IntSize mSize; - RefPtr mIMFSampleUsageInfo; - RefPtr mCopiedTexture; - Maybe mCopiedTextureSharedHandle; - }; - - DataMutex> - mD3D11TexturesById; - - static StaticAutoPtr sInstance; -}; - } // namespace layers } // namespace mozilla diff --git a/gfx/layers/moz.build b/gfx/layers/moz.build index 8b1277c2daaa..45586ad7e706 100644 --- a/gfx/layers/moz.build +++ b/gfx/layers/moz.build @@ -40,11 +40,13 @@ if CONFIG["MOZ_WIDGET_TOOLKIT"] == "windows": EXPORTS.mozilla.layers += [ "d3d11/CompositorD3D11.h", "d3d11/DeviceAttachmentsD3D11.h", + "d3d11/GpuProcessD3D11TextureMap.h", "d3d11/HelpersD3D11.h", "d3d11/ShaderDefinitionsD3D11.h", "d3d11/TextureD3D11.h", ] UNIFIED_SOURCES += [ + "d3d11/GpuProcessD3D11TextureMap.cpp", "d3d11/TextureD3D11.cpp", ] SOURCES += [ diff --git a/gfx/webrender_bindings/RenderD3D11TextureHost.cpp b/gfx/webrender_bindings/RenderD3D11TextureHost.cpp index c53f77949651..b79aeb343b49 100644 --- a/gfx/webrender_bindings/RenderD3D11TextureHost.cpp +++ b/gfx/webrender_bindings/RenderD3D11TextureHost.cpp @@ -14,6 +14,7 @@ #include "ScopedGLHelpers.h" #include "mozilla/DebugOnly.h" #include "mozilla/gfx/Logging.h" +#include "mozilla/layers/GpuProcessD3D11TextureMap.h" #include "mozilla/layers/TextureD3D11.h" namespace mozilla {