summaryrefslogtreecommitdiffstats
path: root/gfx/webrender_bindings/DCLayerTree.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/webrender_bindings/DCLayerTree.cpp')
-rw-r--r--gfx/webrender_bindings/DCLayerTree.cpp255
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)