diff options
Diffstat (limited to 'gfx/webrender_bindings/DCLayerTree.cpp')
-rw-r--r-- | gfx/webrender_bindings/DCLayerTree.cpp | 255 |
1 files changed, 190 insertions, 65 deletions
diff --git a/gfx/webrender_bindings/DCLayerTree.cpp b/gfx/webrender_bindings/DCLayerTree.cpp index eee5601182..177979a466 100644 --- a/gfx/webrender_bindings/DCLayerTree.cpp +++ b/gfx/webrender_bindings/DCLayerTree.cpp @@ -1178,6 +1178,126 @@ void DCSurfaceVideo::AttachExternalImage(wr::ExternalImageId aExternalImage) { mRenderTextureHost = texture; } +static UINT GetVendorId(ID3D11VideoDevice* const aVideoDevice) { + RefPtr<IDXGIDevice> dxgiDevice; + RefPtr<IDXGIAdapter> adapter; + aVideoDevice->QueryInterface((IDXGIDevice**)getter_AddRefs(dxgiDevice)); + dxgiDevice->GetAdapter(getter_AddRefs(adapter)); + + DXGI_ADAPTER_DESC adapterDesc; + adapter->GetDesc(&adapterDesc); + + return adapterDesc.VendorId; +} + +static HRESULT SetNvidiaVpSuperResolution(ID3D11VideoContext* aVideoContext, + ID3D11VideoProcessor* aVideoProcessor, + bool aEnable) { + LOG("SetNvidiaVpSuperResolution() aEnable=%d", aEnable); + + // Undocumented NVIDIA driver constants + constexpr GUID nvGUID = {0xD43CE1B3, + 0x1F4B, + 0x48AC, + {0xBA, 0xEE, 0xC3, 0xC2, 0x53, 0x75, 0xE6, 0xF7}}; + + constexpr UINT nvExtensionVersion = 0x1; + constexpr UINT nvExtensionMethodSuperResolution = 0x2; + struct { + UINT version; + UINT method; + UINT enable; + } streamExtensionInfo = {nvExtensionVersion, nvExtensionMethodSuperResolution, + aEnable ? 1u : 0}; + + HRESULT hr; + hr = aVideoContext->VideoProcessorSetStreamExtension( + aVideoProcessor, 0, &nvGUID, sizeof(streamExtensionInfo), + &streamExtensionInfo); + return hr; +} + +static HRESULT SetVpSuperResolution(UINT aGpuVendorId, + ID3D11VideoContext* aVideoContext, + ID3D11VideoProcessor* aVideoProcessor, + bool aEnable) { + MOZ_ASSERT(aVideoContext); + MOZ_ASSERT(aVideoProcessor); + + if (aGpuVendorId == 0x10DE) { + return SetNvidiaVpSuperResolution(aVideoContext, aVideoProcessor, aEnable); + } + return E_NOTIMPL; +} + +static bool GetNvidiaRTXVideoTrueHDRSupported( + ID3D11VideoContext* aVideoContext, ID3D11VideoProcessor* aVideoProcessor) { + const GUID kNvidiaTrueHDRInterfaceGUID = { + 0xfdd62bb4, + 0x620b, + 0x4fd7, + {0x9a, 0xb3, 0x1e, 0x59, 0xd0, 0xd5, 0x44, 0xb3}}; + UINT available = 0; + HRESULT hr = aVideoContext->VideoProcessorGetStreamExtension( + aVideoProcessor, 0, &kNvidiaTrueHDRInterfaceGUID, sizeof(available), + &available); + if (FAILED(hr)) { + return false; + } + + bool driverSupportsTrueHdr = (available == 1); + return driverSupportsTrueHdr; +} + +static HRESULT SetNvidiaRTXVideoTrueHDR(ID3D11VideoContext* aVideoContext, + ID3D11VideoProcessor* aVideoProcessor, + bool aEnable) { + constexpr GUID kNvidiaTrueHDRInterfaceGUID = { + 0xfdd62bb4, + 0x620b, + 0x4fd7, + {0x9a, 0xb3, 0x1e, 0x59, 0xd0, 0xd5, 0x44, 0xb3}}; + constexpr UINT kStreamExtensionMethodTrueHDR = 0x3; + const UINT TrueHDRVersion4 = 4; + struct { + UINT version; + UINT method; + UINT enable : 1; + UINT reserved : 31; + } streamExtensionInfo = {TrueHDRVersion4, kStreamExtensionMethodTrueHDR, + aEnable ? 1u : 0u, 0u}; + HRESULT hr = aVideoContext->VideoProcessorSetStreamExtension( + aVideoProcessor, 0, &kNvidiaTrueHDRInterfaceGUID, + sizeof(streamExtensionInfo), &streamExtensionInfo); + return hr; +} + +static bool GetVpAutoHDRSupported(UINT aGpuVendorId, + ID3D11VideoContext* aVideoContext, + ID3D11VideoProcessor* aVideoProcessor) { + MOZ_ASSERT(aVideoContext); + MOZ_ASSERT(aVideoProcessor); + + if (aGpuVendorId == 0x10DE) { + return GetNvidiaRTXVideoTrueHDRSupported(aVideoContext, aVideoProcessor); + } + return false; +} + +static HRESULT SetVpAutoHDR(UINT aGpuVendorId, + ID3D11VideoContext* aVideoContext, + ID3D11VideoProcessor* aVideoProcessor, + bool aEnable) { + MOZ_ASSERT(aVideoContext); + MOZ_ASSERT(aVideoProcessor); + + if (aGpuVendorId == 0x10DE) { + return SetNvidiaRTXVideoTrueHDR(aVideoContext, aVideoProcessor, aEnable); + } + MOZ_ASSERT_UNREACHABLE("Unexpected to be called"); + return E_NOTIMPL; +} + bool DCSurfaceVideo::CalculateSwapChainSize(gfx::Matrix& aTransform) { if (!mRenderTextureHost) { MOZ_ASSERT_UNREACHABLE("unexpected to be called"); @@ -1225,18 +1345,39 @@ bool DCSurfaceVideo::CalculateSwapChainSize(gfx::Matrix& aTransform) { transform = gfx::Matrix::Translation(aTransform.GetTranslation()); } - if (!mVideoSwapChain || mSwapChainSize != swapChainSize || mIsDRM != isDRM) { + if (!mDCLayerTree->EnsureVideoProcessor(mVideoSize, swapChainSize)) { + gfxCriticalNote << "EnsureVideoProcessor Failed"; + return false; + } + + MOZ_ASSERT(mDCLayerTree->GetVideoContext()); + MOZ_ASSERT(mDCLayerTree->GetVideoProcessor()); + + const UINT vendorId = GetVendorId(mDCLayerTree->GetVideoDevice()); + const bool driverSupportsTrueHDR = + GetVpAutoHDRSupported(vendorId, mDCLayerTree->GetVideoContext(), + mDCLayerTree->GetVideoProcessor()); + const bool contentIsHDR = false; // XXX for now, only non-HDR is supported. + const bool monitorIsHDR = gfx::DeviceManagerDx::Get()->SystemHDREnabled(); + const bool powerIsCharging = RenderThread::Get()->GetPowerIsCharging(); + + bool useVpAutoHDR = gfx::gfxVars::WebRenderOverlayVpAutoHDR() && + !contentIsHDR && monitorIsHDR && driverSupportsTrueHDR && + powerIsCharging && !mVpAutoHDRFailed; + + if (!mVideoSwapChain || mSwapChainSize != swapChainSize || mIsDRM != isDRM || + mUseVpAutoHDR != useVpAutoHDR) { needsToPresent = true; ReleaseDecodeSwapChainResources(); // Update mSwapChainSize before creating SwapChain mSwapChainSize = swapChainSize; mIsDRM = isDRM; - auto swapChainFormat = GetSwapChainFormat(); + auto swapChainFormat = GetSwapChainFormat(useVpAutoHDR); bool useYUVSwapChain = IsYUVSwapChainFormat(swapChainFormat); if (useYUVSwapChain) { // Tries to create YUV SwapChain - CreateVideoSwapChain(); + CreateVideoSwapChain(swapChainFormat); if (!mVideoSwapChain) { mFailedYuvSwapChain = true; ReleaseDecodeSwapChainResources(); @@ -1246,11 +1387,21 @@ bool DCSurfaceVideo::CalculateSwapChainSize(gfx::Matrix& aTransform) { } // Tries to create RGB SwapChain if (!mVideoSwapChain) { - CreateVideoSwapChain(); + CreateVideoSwapChain(swapChainFormat); + } + if (!mVideoSwapChain && useVpAutoHDR) { + mVpAutoHDRFailed = true; + gfxCriticalNoteOnce << "Failed to create video SwapChain for VpAutoHDR"; + + // Disable VpAutoHDR + useVpAutoHDR = false; + swapChainFormat = GetSwapChainFormat(useVpAutoHDR); + CreateVideoSwapChain(swapChainFormat); } } aTransform = transform; + mUseVpAutoHDR = useVpAutoHDR; return needsToPresent; } @@ -1270,8 +1421,7 @@ void DCSurfaceVideo::PresentVideo() { mVisual->SetContent(mVideoSwapChain); if (!CallVideoProcessorBlt()) { - auto swapChainFormat = GetSwapChainFormat(); - bool useYUVSwapChain = IsYUVSwapChainFormat(swapChainFormat); + bool useYUVSwapChain = IsYUVSwapChainFormat(mSwapChainFormat); if (useYUVSwapChain) { mFailedYuvSwapChain = true; ReleaseDecodeSwapChainResources(); @@ -1392,14 +1542,17 @@ void DCSurfaceVideo::PresentVideo() { } } -DXGI_FORMAT DCSurfaceVideo::GetSwapChainFormat() { +DXGI_FORMAT DCSurfaceVideo::GetSwapChainFormat(bool aUseVpAutoHDR) { + if (aUseVpAutoHDR) { + return DXGI_FORMAT_R16G16B16A16_FLOAT; + } if (mFailedYuvSwapChain || !mDCLayerTree->SupportsHardwareOverlays()) { return DXGI_FORMAT_B8G8R8A8_UNORM; } return mDCLayerTree->GetOverlayFormatForSDR(); } -bool DCSurfaceVideo::CreateVideoSwapChain() { +bool DCSurfaceVideo::CreateVideoSwapChain(DXGI_FORMAT aSwapChainFormat) { MOZ_ASSERT(mRenderTextureHost); mFirstPresent = true; @@ -1423,12 +1576,10 @@ bool DCSurfaceVideo::CreateVideoSwapChain() { return false; } - auto swapChainFormat = GetSwapChainFormat(); - DXGI_SWAP_CHAIN_DESC1 desc = {}; desc.Width = mSwapChainSize.width; desc.Height = mSwapChainSize.height; - desc.Format = swapChainFormat; + desc.Format = aSwapChainFormat; desc.Stereo = FALSE; desc.SampleDesc.Count = 1; desc.BufferCount = mSwapChainBufferCount; @@ -1436,7 +1587,7 @@ bool DCSurfaceVideo::CreateVideoSwapChain() { desc.Scaling = DXGI_SCALING_STRETCH; desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; desc.Flags = DXGI_SWAP_CHAIN_FLAG_FULLSCREEN_VIDEO; - if (IsYUVSwapChainFormat(swapChainFormat)) { + if (IsYUVSwapChainFormat(aSwapChainFormat)) { desc.Flags |= DXGI_SWAP_CHAIN_FLAG_YUV_VIDEO; } if (mIsDRM) { @@ -1455,7 +1606,7 @@ bool DCSurfaceVideo::CreateVideoSwapChain() { return false; } - mSwapChainFormat = swapChainFormat; + mSwapChainFormat = aSwapChainFormat; return true; } @@ -1494,50 +1645,6 @@ static Maybe<DXGI_COLOR_SPACE_TYPE> GetSourceDXGIColorSpace( return GetSourceDXGIColorSpace(info.space, info.range); } -static void SetNvidiaVideoSuperRes(ID3D11VideoContext* videoContext, - ID3D11VideoProcessor* videoProcessor, - bool enabled) { - LOG("SetNvidiaVideoSuperRes() enabled=%d", enabled); - - // Undocumented NVIDIA driver constants - constexpr GUID nvGUID = {0xD43CE1B3, - 0x1F4B, - 0x48AC, - {0xBA, 0xEE, 0xC3, 0xC2, 0x53, 0x75, 0xE6, 0xF7}}; - - constexpr UINT nvExtensionVersion = 0x1; - constexpr UINT nvExtensionMethodSuperResolution = 0x2; - struct { - UINT version; - UINT method; - UINT enable; - } streamExtensionInfo = {nvExtensionVersion, nvExtensionMethodSuperResolution, - enabled ? 1u : 0}; - - HRESULT hr; - hr = videoContext->VideoProcessorSetStreamExtension( - videoProcessor, 0, &nvGUID, sizeof(streamExtensionInfo), - &streamExtensionInfo); - - // Ignore errors as could be unsupported - if (FAILED(hr)) { - LOG("SetNvidiaVideoSuperRes() error: %lx", hr); - return; - } -} - -static UINT GetVendorId(ID3D11VideoDevice* const videoDevice) { - RefPtr<IDXGIDevice> dxgiDevice; - RefPtr<IDXGIAdapter> adapter; - videoDevice->QueryInterface((IDXGIDevice**)getter_AddRefs(dxgiDevice)); - dxgiDevice->GetAdapter(getter_AddRefs(adapter)); - - DXGI_ADAPTER_DESC adapterDesc; - adapter->GetDesc(&adapterDesc); - - return adapterDesc.VendorId; -} - bool DCSurfaceVideo::CallVideoProcessorBlt() { MOZ_ASSERT(mRenderTextureHost); @@ -1576,11 +1683,6 @@ bool DCSurfaceVideo::CallVideoProcessorBlt() { } } - if (!mDCLayerTree->EnsureVideoProcessor(mVideoSize, mSwapChainSize)) { - gfxCriticalNote << "EnsureVideoProcessor Failed"; - return false; - } - RefPtr<IDXGISwapChain3> swapChain3; mVideoSwapChain->QueryInterface( (IDXGISwapChain3**)getter_AddRefs(swapChain3)); @@ -1609,6 +1711,13 @@ bool DCSurfaceVideo::CallVideoProcessorBlt() { IsYUVSwapChainFormat(mSwapChainFormat) ? inputColorSpace : DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709; + + if (mUseVpAutoHDR) { + outputColorSpace = mSwapChainFormat == DXGI_FORMAT_R16G16B16A16_FLOAT + ? DXGI_COLOR_SPACE_RGB_FULL_G10_NONE_P709 + : DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020; + } + hr = swapChain3->SetColorSpace1(outputColorSpace); if (FAILED(hr)) { gfxCriticalNoteOnce << "SetColorSpace1 failed: " << gfx::hexa(hr); @@ -1679,9 +1788,24 @@ bool DCSurfaceVideo::CallVideoProcessorBlt() { } const UINT vendorId = GetVendorId(videoDevice); - if (vendorId == 0x10DE && - StaticPrefs::gfx_webrender_super_resolution_nvidia_AtStartup()) { - SetNvidiaVideoSuperRes(videoContext, videoProcessor, true); + const auto powerIsCharging = RenderThread::Get()->GetPowerIsCharging(); + if (gfx::gfxVars::WebRenderOverlayVpSuperResolution() && + !mVpSuperResolutionFailed && powerIsCharging) { + hr = SetVpSuperResolution(vendorId, videoContext, videoProcessor, true); + if (FAILED(hr)) { + if (hr != E_NOTIMPL) { + gfxCriticalNoteOnce << "SetVpSuperResolution failed: " << gfx::hexa(hr); + } + mVpSuperResolutionFailed = true; + } + } + + if (mUseVpAutoHDR) { + hr = SetVpAutoHDR(vendorId, videoContext, videoProcessor, true); + if (FAILED(hr)) { + gfxCriticalNoteOnce << "SetVpAutoHDR failed: " << gfx::hexa(hr); + mVpAutoHDRFailed = true; + } } hr = videoContext->VideoProcessorBlt(videoProcessor, mOutputView, 0, 1, @@ -1703,6 +1827,7 @@ void DCSurfaceVideo::ReleaseDecodeSwapChainResources() { ::CloseHandle(mSwapChainSurfaceHandle); mSwapChainSurfaceHandle = 0; } + mUseVpAutoHDR = false; } DCSurfaceHandle::DCSurfaceHandle(bool aIsOpaque, DCLayerTree* aDCLayerTree) |