From aa4bf1818fd8d9b3bb8c0572ede9ac1474885883 Mon Sep 17 00:00:00 2001 From: elvissteinjr Date: Wed, 20 Nov 2024 02:48:23 +0100 Subject: [PATCH] Add HDR support for Desktop Duplication & Graphics Capture - Add optional R16G16B16A16_FLOAT texture handling to Desktop Duplication, using DuplicateOutput1 interface - Add DPWinRT_SetHDREnabled() to control texture format used by Graphics Capture - Add setting to toggle HDR mirroring - Mark dashboard app as PerMonitorHighDPIAware (confusingly necessary for DuplicateOutput1 to work) - Remove unused overlay texture shader resource view --- assets/lang/de.ini | 4 +- assets/lang/en.ini | 2 + src/DesktopPlus/DesktopPlus.cpp | 5 +- src/DesktopPlus/DesktopPlus.vcxproj | 4 +- src/DesktopPlus/DuplicationManager.cpp | 67 ++++++++++++++---- src/DesktopPlus/DuplicationManager.h | 2 +- src/DesktopPlus/OutputManager.cpp | 85 ++++++++++++++++------- src/DesktopPlus/OutputManager.h | 2 +- src/DesktopPlusUI/TranslationManager.cpp | 2 + src/DesktopPlusUI/TranslationManager.h | 2 + src/DesktopPlusUI/UIManager.cpp | 15 ++++ src/DesktopPlusUI/WindowSettings.cpp | 13 +++- src/DesktopPlusWinRT/DesktopPlusWinRT.cpp | 28 ++++++++ src/DesktopPlusWinRT/DesktopPlusWinRT.h | 14 ++-- src/DesktopPlusWinRT/OverlayCapture.cpp | 6 +- src/Shared/ConfigManager.cpp | 4 ++ src/Shared/ConfigManager.h | 1 + 17 files changed, 202 insertions(+), 54 deletions(-) diff --git a/assets/lang/de.ini b/assets/lang/de.ini index e21cd85..911bbca 100644 --- a/assets/lang/de.ini +++ b/assets/lang/de.ini @@ -313,8 +313,10 @@ tstr_SettingsPerformanceUpdateLimiterOverrideTip=Wenn mehrere Überschreibungen tstr_SettingsPerformanceUpdateLimiterModeOverride=Überschreibe Updatelimiter tstr_SettingsPerformanceRapidUpdates=Verringere Laserpointer-Latenz tstr_SettingsPerformanceRapidUpdatesTip=Verringere die Latenz von Laserpointer-Eingaben auf Kosten zusätzlicher CPU-Last, solange auf ein Overlay gezeigt wird -tstr_SettingsPerformanceSingleDesktopMirror=Einzelne Desktopspiegellung +tstr_SettingsPerformanceSingleDesktopMirror=Einzelne Desktopspiegelung tstr_SettingsPerformanceSingleDesktopMirrorTip=Spiegele individuelle Desktops, wenn zu ihnen gewechselt wird, anstatt vom gesamten Desktop zuzuschneiden.\nSolange diese Einstellung aktiv ist, werden alle Overlays den selben Desktop zeigen. +tstr_SettingsPerformanceUseHDR=HDR-Spiegelung +tstr_SettingsPerformanceUseHDRTip=Verwende beim Spiegeln von Desktops und Fenstern Texturen mit höherer Bittiefe, zur HDR-Unterstützung.\nKann die Leistung beeinträchtigen, falls nicht erforderlich, und erhöht VRAM-Verbrauch. tstr_SettingsPerformanceShowFPS=Zeige FPS in Floating UI tstr_SettingsWarningsHidden=Versteckte Warnungen: diff --git a/assets/lang/en.ini b/assets/lang/en.ini index 881d691..69921bd 100644 --- a/assets/lang/en.ini +++ b/assets/lang/en.ini @@ -318,6 +318,8 @@ tstr_SettingsPerformanceRapidUpdates=Reduce Laser Pointer Latency tstr_SettingsPerformanceRapidUpdatesTip=Reduce latency of laser pointer input at the cost of additional CPU load while pointing at an overlay tstr_SettingsPerformanceSingleDesktopMirror=Single Desktop Mirroring tstr_SettingsPerformanceSingleDesktopMirrorTip=Mirror individual desktops when switching to them instead of cropping from the combined desktop.\nWhen this is active, all overlays will be showing the same desktop. +tstr_SettingsPerformanceUseHDR=HDR Mirroring +tstr_SettingsPerformanceUseHDRTip=Mirror desktops and windows using higher bit-depth textures, supporting HDR output.\nMay negatively impact performance when not required and increases VRAM usage. tstr_SettingsPerformanceShowFPS=Show FPS in Floating UI tstr_SettingsWarningsHidden=Warnings Hidden: diff --git a/src/DesktopPlus/DesktopPlus.cpp b/src/DesktopPlus/DesktopPlus.cpp index ab39a3d..a171076 100644 --- a/src/DesktopPlus/DesktopPlus.cpp +++ b/src/DesktopPlus/DesktopPlus.cpp @@ -766,8 +766,11 @@ DWORD WINAPI CaptureThreadEntry(_In_ void* Param) goto Exit; } + D3D11_TEXTURE2D_DESC SharedSurfDesc; + SharedSurf->GetDesc(&SharedSurfDesc); + // Make duplication manager - Ret = DuplMgr.InitDupl(TData->DxRes.Device, TData->Output, TData->WMRIgnoreVScreens); + Ret = DuplMgr.InitDupl(TData->DxRes.Device, TData->Output, TData->WMRIgnoreVScreens, SharedSurfDesc.Format != DXGI_FORMAT_B8G8R8A8_UNORM); if (Ret != DUPL_RETURN_SUCCESS) { goto Exit; diff --git a/src/DesktopPlus/DesktopPlus.vcxproj b/src/DesktopPlus/DesktopPlus.vcxproj index 0aa1d52..95fd4f3 100644 --- a/src/DesktopPlus/DesktopPlus.vcxproj +++ b/src/DesktopPlus/DesktopPlus.vcxproj @@ -68,7 +68,7 @@ $(SolutionDir)Shared;$(OutputPath) - true + PerMonitorHighDPIAware "DesktopPlus_$([System.DateTime]::Now.ToFileTime()), version=1" @@ -99,7 +99,7 @@ $(SolutionDir)Shared;$(OutputPath) - true + PerMonitorHighDPIAware "DesktopPlus_$([System.DateTime]::Now.ToFileTime()), version=1" diff --git a/src/DesktopPlus/DuplicationManager.cpp b/src/DesktopPlus/DuplicationManager.cpp index 6257d72..b67e304 100644 --- a/src/DesktopPlus/DuplicationManager.cpp +++ b/src/DesktopPlus/DuplicationManager.cpp @@ -1,6 +1,15 @@ #include "DuplicationManager.h" #include +#include + +//Keep building with 10.0.17763.0 / 1809 SDK optional +#ifdef NTDDI_WIN10_RS5 + #include +#else + #define DPLUS_DUP_NO_HDR +#endif + // // Constructor sets up references / variables // @@ -47,10 +56,14 @@ DUPLICATIONMANAGER::~DUPLICATIONMANAGER() // // Initialize duplication interfaces // -DUPL_RETURN DUPLICATIONMANAGER::InitDupl(_In_ ID3D11Device* Device, UINT Output, bool WMRIgnoreVScreens) +DUPL_RETURN DUPLICATIONMANAGER::InitDupl(_In_ ID3D11Device* Device, UINT Output, bool WMRIgnoreVScreens, bool UseHDR) { m_OutputNumber = Output; + #ifdef DPLUS_DUP_NO_HDR + UseHDR = false; + #endif + // Take a reference on the device m_Device = Device; m_Device->AddRef(); @@ -119,23 +132,51 @@ DUPL_RETURN DUPLICATIONMANAGER::InitDupl(_In_ ID3D11Device* Device, UINT Output, DxgiOutput->GetDesc(&m_OutputDesc); - Microsoft::WRL::ComPtr DxgiOutput1; - hr = DxgiOutput.As(&DxgiOutput1); - if (FAILED(hr)) + //Create desktop duplication + if (!UseHDR) { - return ProcessFailure(nullptr, L"Failed to get output as DxgiOutput1", L"Desktop+ Error", hr); - } + Microsoft::WRL::ComPtr DxgiOutput1; + hr = DxgiOutput.As(&DxgiOutput1); + if (FAILED(hr)) + { + return ProcessFailure(nullptr, L"Failed to get output as DxgiOutput1", L"Desktop+ Error", hr); + } - //Create desktop duplication - hr = DxgiOutput1->DuplicateOutput(m_Device, &m_DeskDupl); - if (FAILED(hr)) + hr = DxgiOutput1->DuplicateOutput(m_Device, &m_DeskDupl); + if (FAILED(hr)) + { + if (hr == DXGI_ERROR_NOT_CURRENTLY_AVAILABLE) + { + ProcessFailure(m_Device, L"There is already the maximum number of applications using the Desktop Duplication API running, please close one of those applications and then try again", L"Desktop+ Error", hr); + return DUPL_RETURN_ERROR_UNEXPECTED; + } + return ProcessFailure(m_Device, L"Failed to get duplicate output", L"Desktop+ Error", hr, CreateDuplicationExpectedErrors); + } + } + else { - if (hr == DXGI_ERROR_NOT_CURRENTLY_AVAILABLE) + #ifndef DPLUS_DUP_NO_HDR + + Microsoft::WRL::ComPtr DxgiOutput5; + hr = DxgiOutput.As(&DxgiOutput5); + if (FAILED(hr)) { - ProcessFailure(m_Device, L"There is already the maximum number of applications using the Desktop Duplication API running, please close one of those applications and then try again", L"Desktop+ Error", hr); - return DUPL_RETURN_ERROR_UNEXPECTED; + return ProcessFailure(nullptr, L"Failed to get output as DxgiOutput5", L"Desktop+ Error", hr); } - return ProcessFailure(m_Device, L"Failed to get duplicate output", L"Desktop+ Error", hr, CreateDuplicationExpectedErrors); + + const DXGI_FORMAT supported_formats[] = {DXGI_FORMAT_R16G16B16A16_FLOAT}; + hr = DxgiOutput5->DuplicateOutput1(m_Device, 0, 1, supported_formats, &m_DeskDupl); + if (FAILED(hr)) + { + if (hr == DXGI_ERROR_NOT_CURRENTLY_AVAILABLE) + { + ProcessFailure(m_Device, L"There is already the maximum number of applications using the Desktop Duplication API running, please close one of those applications and then try again", L"Desktop+ Error", hr); + return DUPL_RETURN_ERROR_UNEXPECTED; + } + return ProcessFailure(m_Device, L"Failed to get duplicate output", L"Desktop+ Error", hr, CreateDuplicationExpectedErrors); + } + + #endif } return DUPL_RETURN_SUCCESS; diff --git a/src/DesktopPlus/DuplicationManager.h b/src/DesktopPlus/DuplicationManager.h index ff66f6a..85f2c7d 100644 --- a/src/DesktopPlus/DuplicationManager.h +++ b/src/DesktopPlus/DuplicationManager.h @@ -13,7 +13,7 @@ class DUPLICATIONMANAGER ~DUPLICATIONMANAGER(); _Success_(*Timeout == false && return == DUPL_RETURN_SUCCESS) DUPL_RETURN GetFrame(_Out_ FRAME_DATA* Data, _Out_ bool* Timeout); DUPL_RETURN DoneWithFrame(); - DUPL_RETURN InitDupl(_In_ ID3D11Device* Device, UINT Output, bool WMRIgnoreVScreens); + DUPL_RETURN InitDupl(_In_ ID3D11Device* Device, UINT Output, bool WMRIgnoreVScreens, bool UseHDR); DUPL_RETURN GetMouse(_Inout_ PTR_INFO* PtrInfo, _In_ DXGI_OUTDUPL_FRAME_INFO* FrameInfo, INT OffsetX, INT OffsetY); void GetOutputDesc(_Out_ DXGI_OUTPUT_DESC* DescPtr); diff --git a/src/DesktopPlus/OutputManager.cpp b/src/DesktopPlus/OutputManager.cpp index 8ff3de3..4d7be5b 100644 --- a/src/DesktopPlus/OutputManager.cpp +++ b/src/DesktopPlus/OutputManager.cpp @@ -1,5 +1,12 @@ #include "OutputManager.h" +//Keep building with 10.0.17763.0 / 1809 SDK optional +#ifdef NTDDI_WIN10_RS5 + #include +#else + #define DPLUS_DUP_NO_HDR +#endif + #include #include #include @@ -58,6 +65,7 @@ OutputManager::OutputManager(HANDLE PauseDuplicationEvent, HANDLE ResumeDuplicat m_MaxActiveRefreshDelay(16), m_OutputPendingSkippedFrame(false), m_OutputPendingFullRefresh(false), + m_OutputHDRAvailable(false), m_OutputInvalid(false), m_OutputPendingDirtyRect{-1, -1, -1, -1}, m_OutputAlphaCheckFailed(false), @@ -67,7 +75,6 @@ OutputManager::OutputManager(HANDLE PauseDuplicationEvent, HANDLE ResumeDuplicat m_OvrlHandleDesktopTexture(vr::k_ulOverlayHandleInvalid), m_OvrlTex(nullptr), m_OvrlRTV(nullptr), - m_OvrlShaderResView(nullptr), m_OvrlActiveCount(0), m_OvrlDesktopDuplActiveCount(0), m_OvrlDashboardActive(false), @@ -215,12 +222,6 @@ void OutputManager::CleanRefs() m_OvrlRTV = nullptr; } - if (m_OvrlShaderResView) - { - m_OvrlShaderResView->Release(); - m_OvrlShaderResView = nullptr; - } - if (m_MouseTex) { m_MouseTex->Release(); @@ -368,10 +369,6 @@ DUPL_RETURN OutputManager::InitOutput(HWND Window, _Out_ INT& SingleOutput, _Out } } } - else - { - adapter_ptr_preferred = nullptr; - } if (FAILED(hr)) { @@ -394,6 +391,33 @@ DUPL_RETURN OutputManager::InitOutput(HWND Window, _Out_ INT& SingleOutput, _Out LOG_F(INFO, "Using cross-GPU copy"); } + //Check Desktop Duplication HDR support + m_OutputHDRAvailable = false; + + #ifndef DPLUS_DUP_NO_HDR + { + Microsoft::WRL::ComPtr DxgiOutput; + hr = adapter_ptr_preferred->EnumOutputs(0, &DxgiOutput); + if (SUCCEEDED(hr)) + { + Microsoft::WRL::ComPtr DxgiOutput5; + hr = DxgiOutput.As(&DxgiOutput5); + m_OutputHDRAvailable = SUCCEEDED(hr); + } + + if (m_OutputHDRAvailable) + { + LOG_F(INFO, "Desktop Duplication HDR mirroring is supported"); + } + else + { + LOG_F(INFO, "Desktop Duplication HDR mirroring is not supported"); + } + } + #else + LOG_F(INFO, "Desktop+ was not built with Desktop Duplication HDR support"); + #endif + // Create shared texture DUPL_RETURN Return = CreateTextures(SingleOutput, OutCount, DeskBounds); if (Return != DUPL_RETURN_SUCCESS) @@ -1539,6 +1563,12 @@ bool OutputManager::HandleIPCMessage(const MSG& msg) reset_mirroring = true; break; } + case configid_bool_performance_hdr_mirroring: + { + reset_mirroring = true; + DPWinRT_SetHDREnabled(msg.lParam); + break; + } case configid_bool_input_mouse_render_cursor: { m_OutputPendingFullRefresh = true; @@ -3100,24 +3130,18 @@ DUPL_RETURN OutputManager::ProcessMonoMask(bool IsMono, _Inout_ PTR_INFO* PtrInf // DUPL_RETURN OutputManager::MakeRTV() { - // Create render target for overlay texture - D3D11_RENDER_TARGET_VIEW_DESC ovrl_tex_rtv_desc; - D3D11_SHADER_RESOURCE_VIEW_DESC ovrl_tex_shader_res_view_desc; + D3D11_TEXTURE2D_DESC desc_ovrl_tex; + m_OvrlTex->GetDesc(&desc_ovrl_tex); - ovrl_tex_rtv_desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; + //Create render target view for overlay texture + D3D11_RENDER_TARGET_VIEW_DESC ovrl_tex_rtv_desc = {}; + + ovrl_tex_rtv_desc.Format = desc_ovrl_tex.Format; ovrl_tex_rtv_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; ovrl_tex_rtv_desc.Texture2D.MipSlice = 0; m_Device->CreateRenderTargetView(m_OvrlTex, &ovrl_tex_rtv_desc, &m_OvrlRTV); - // Create the shader resource view for overlay texture while we're at it - ovrl_tex_shader_res_view_desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; - ovrl_tex_shader_res_view_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; - ovrl_tex_shader_res_view_desc.Texture2D.MostDetailedMip = 0; - ovrl_tex_shader_res_view_desc.Texture2D.MipLevels = 1; - - m_Device->CreateShaderResourceView(m_OvrlTex, &ovrl_tex_shader_res_view_desc, &m_OvrlShaderResView); - return DUPL_RETURN_SUCCESS; } @@ -3256,7 +3280,7 @@ DUPL_RETURN OutputManager::CreateTextures(INT SingleOutput, _Out_ UINT* OutCount TexD.Height = m_DesktopHeight; TexD.MipLevels = 1; TexD.ArraySize = 1; - TexD.Format = DXGI_FORMAT_B8G8R8A8_UNORM; + TexD.Format = ((m_OutputHDRAvailable) && (ConfigManager::GetValue(configid_bool_performance_hdr_mirroring))) ? DXGI_FORMAT_R16G16B16A16_FLOAT : DXGI_FORMAT_B8G8R8A8_UNORM; TexD.SampleDesc.Count = 1; TexD.Usage = D3D11_USAGE_DEFAULT; TexD.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE; @@ -3614,7 +3638,7 @@ DUPL_RETURN_UPD OutputManager::RefreshOpenVROverlayTexture(DPRect& DirtyRectTota { vr::Texture_t vrtex; vrtex.eType = vr::TextureType_DirectX; - vrtex.eColorSpace = vr::ColorSpace_Gamma; + vrtex.eColorSpace = ((m_OutputHDRAvailable) && (ConfigManager::GetValue(configid_bool_performance_hdr_mirroring))) ? vr::ColorSpace_Linear : vr::ColorSpace_Gamma; vrtex.handle = m_OvrlTex; //The intermediate texture can be assumed to be not complete when a full copy is forced, so redraw that @@ -3773,7 +3797,7 @@ bool OutputManager::DesktopTextureAlphaCheck() desc.Height = 1; desc.MipLevels = 1; desc.ArraySize = 1; - desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; + desc.Format = desc_ovrl_tex.Format; desc.SampleDesc.Count = 1; desc.SampleDesc.Quality = 0; desc.Usage = D3D11_USAGE_STAGING; @@ -5517,6 +5541,8 @@ void OutputManager::ApplySetting3DMode() void OutputManager::ApplySettingTransform() { Overlay& overlay = OverlayManager::Get().GetCurrentOverlay(); + const OverlayConfigData& data = OverlayManager::Get().GetCurrentConfigData(); + vr::VROverlayHandle_t ovrl_handle = overlay.GetHandle(); //Fixup overlay visibility if needed @@ -5742,6 +5768,13 @@ void OutputManager::ApplySettingTransform() //Update Brightness //We use the logarithmic counterpart since the changes in higher steps are barely visible while the lower range can really use those additional steps float brightness = lin2log(ConfigManager::Get().GetValue(configid_float_overlay_brightness)); + + //Apply HDR brightness multiplier if needed + if ((ConfigManager::GetValue(configid_bool_performance_hdr_mirroring)) && (data.ConfigInt[configid_int_overlay_capture_source] == ovrl_capsource_winrt_capture)) + { + brightness *= DPLUSWINRT_HDR_BRIGHTNESS_ADJUST; + } + vr::VROverlay()->SetOverlayColor(ovrl_handle, brightness, brightness, brightness); //Set last tick for dashboard dummy delayed update diff --git a/src/DesktopPlus/OutputManager.h b/src/DesktopPlus/OutputManager.h index 9f40214..a6356d6 100644 --- a/src/DesktopPlus/OutputManager.h +++ b/src/DesktopPlus/OutputManager.h @@ -194,6 +194,7 @@ class OutputManager std::vector m_DesktopRects; //Cached position and size of available desktops DPRect m_DesktopRectTotal; //Total rect of all available desktops (may not be the same as above Desktop Duplication rect if that's not using the combined desktop) DWORD m_MaxActiveRefreshDelay; + bool m_OutputHDRAvailable; //False if OS doesn't support the required interface, regardless of hardware connected bool m_OutputInvalid; bool m_OutputPendingSkippedFrame; bool m_OutputPendingFullRefresh; @@ -207,7 +208,6 @@ class OutputManager vr::VROverlayHandle_t m_OvrlHandleDesktopTexture; ID3D11Texture2D* m_OvrlTex; ID3D11RenderTargetView* m_OvrlRTV; - ID3D11ShaderResourceView* m_OvrlShaderResView; int m_OvrlActiveCount; int m_OvrlDesktopDuplActiveCount; bool m_OvrlDashboardActive; diff --git a/src/DesktopPlusUI/TranslationManager.cpp b/src/DesktopPlusUI/TranslationManager.cpp index 4477e00..4fd99c0 100644 --- a/src/DesktopPlusUI/TranslationManager.cpp +++ b/src/DesktopPlusUI/TranslationManager.cpp @@ -301,6 +301,8 @@ const char* TranslationManager::s_StringIDNames[tstr_MAX] = "tstr_SettingsPerformanceRapidUpdatesTip", "tstr_SettingsPerformanceSingleDesktopMirror", "tstr_SettingsPerformanceSingleDesktopMirrorTip", + "tstr_SettingsPerformanceUseHDR", + "tstr_SettingsPerformanceUseHDRTip", "tstr_SettingsPerformanceShowFPS", "tstr_SettingsWarningsHidden", "tstr_SettingsWarningsReset", diff --git a/src/DesktopPlusUI/TranslationManager.h b/src/DesktopPlusUI/TranslationManager.h index 8f68092..fdc12b6 100644 --- a/src/DesktopPlusUI/TranslationManager.h +++ b/src/DesktopPlusUI/TranslationManager.h @@ -299,6 +299,8 @@ enum TRMGRStrID tstr_SettingsPerformanceRapidUpdatesTip, tstr_SettingsPerformanceSingleDesktopMirror, tstr_SettingsPerformanceSingleDesktopMirrorTip, + tstr_SettingsPerformanceUseHDR, + tstr_SettingsPerformanceUseHDRTip, tstr_SettingsPerformanceShowFPS, tstr_SettingsWarningsHidden, tstr_SettingsWarningsReset, diff --git a/src/DesktopPlusUI/UIManager.cpp b/src/DesktopPlusUI/UIManager.cpp index d51e225..0288f35 100644 --- a/src/DesktopPlusUI/UIManager.cpp +++ b/src/DesktopPlusUI/UIManager.cpp @@ -13,6 +13,8 @@ #include "Util.h" #include "OpenVRExt.h" #include "WindowManager.h" + +#include "DesktopPlusWinRT.h" #include "DPBrowserAPIClient.h" //This one holds mostly constant data, but depends on how the application was launched @@ -2132,6 +2134,13 @@ void UIManager::HighlightOverlay(unsigned int overlay_id) { const OverlayConfigData& data = OverlayManager::Get().GetConfigData((unsigned int)overlay_id); float brightness = lin2log(data.ConfigFloat[configid_float_overlay_brightness]); + + //Apply HDR brightness multiplier if needed + if ((ConfigManager::GetValue(configid_bool_performance_hdr_mirroring)) && (data.ConfigInt[configid_int_overlay_capture_source] == ovrl_capsource_winrt_capture)) + { + brightness *= DPLUSWINRT_HDR_BRIGHTNESS_ADJUST; + } + ImVec4 col = ImGui::GetStyleColorVec4(ImGuiCol_ButtonHovered); vr::VROverlay()->SetOverlayColor(ovrl_handle, col.x * brightness, col.y * brightness, col.z * brightness); @@ -2143,6 +2152,12 @@ void UIManager::HighlightOverlay(unsigned int overlay_id) const OverlayConfigData& data = OverlayManager::Get().GetConfigData(OverlayManager::Get().FindOverlayID(colored_handle)); float brightness = lin2log(data.ConfigFloat[configid_float_overlay_brightness]); + //Apply HDR brightness multiplier if needed + if ((ConfigManager::GetValue(configid_bool_performance_hdr_mirroring)) && (data.ConfigInt[configid_int_overlay_capture_source] == ovrl_capsource_winrt_capture)) + { + brightness *= DPLUSWINRT_HDR_BRIGHTNESS_ADJUST; + } + vr::VROverlay()->SetOverlayColor(colored_handle, brightness, brightness, brightness); colored_handle = vr::k_ulOverlayHandleInvalid; diff --git a/src/DesktopPlusUI/WindowSettings.cpp b/src/DesktopPlusUI/WindowSettings.cpp index 79739a3..8855aa2 100644 --- a/src/DesktopPlusUI/WindowSettings.cpp +++ b/src/DesktopPlusUI/WindowSettings.cpp @@ -2005,7 +2005,18 @@ void WindowSettings::UpdatePageMainCatPerformance() HelpMarker(TranslationManager::GetString(tstr_SettingsPerformanceSingleDesktopMirrorTip)); ImGui::NextColumn(); - ImGui::Spacing(); //Only use additional spacing when this is visible since it looks odd with just 2 checkboxes + ImGui::Spacing(); + + bool& use_hdr = ConfigManager::Get().GetRef(configid_bool_performance_hdr_mirroring); + if (ImGui::Checkbox(TranslationManager::GetString(tstr_SettingsPerformanceUseHDR), &use_hdr)) + { + IPCManager::Get().PostMessageToDashboardApp(ipcmsg_set_config, ConfigManager::GetWParamForConfigID(configid_bool_performance_hdr_mirroring), use_hdr); + } + ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x); + HelpMarker(TranslationManager::GetString(tstr_SettingsPerformanceUseHDRTip)); + + ImGui::NextColumn(); + ImGui::NextColumn(); } bool& show_fps = ConfigManager::Get().GetRef(configid_bool_performance_show_fps); diff --git a/src/DesktopPlusWinRT/DesktopPlusWinRT.cpp b/src/DesktopPlusWinRT/DesktopPlusWinRT.cpp index 8e96489..af29005 100644 --- a/src/DesktopPlusWinRT/DesktopPlusWinRT.cpp +++ b/src/DesktopPlusWinRT/DesktopPlusWinRT.cpp @@ -32,6 +32,7 @@ static std::vector g_Threads; static bool g_IsCursorEnabled; //- Rarely accessed atomics +static std::atomic g_IsHDREnabled; static std::atomic g_DesktopEnumFlagIgnoreWMRScreens; namespace winrt @@ -39,6 +40,7 @@ namespace winrt using namespace Windows::Foundation; using namespace Windows::Foundation::Metadata; using namespace Windows::Graphics::Capture; + using namespace Windows::Graphics::DirectX; } namespace util @@ -165,6 +167,7 @@ void DPWinRT_Init() winrt::uninit_apartment(); g_IsCursorEnabled = true; + g_IsHDREnabled = true; g_DesktopEnumFlagIgnoreWMRScreens = true; #endif @@ -472,6 +475,25 @@ void DPWinRT_SetCaptureCursorEnabled(bool is_cursor_enabled) #endif //DPLUSWINRT_STUB } +void DPWinRT_SetHDREnabled(bool is_hdr_enabled) +{ + #ifndef DPLUSWINRT_STUB + + //Send enable cursor message to all threads if the value changed + if (g_IsHDREnabled != is_hdr_enabled) + { + std::lock_guard lock(g_ThreadsMutex); + + for (const auto& thread : g_Threads) + { + ::PostThreadMessage(thread.ThreadID, WM_DPLUSWINRT_ENABLE_HDR, is_hdr_enabled, 0); + } + + g_IsHDREnabled = is_hdr_enabled; + } + #endif //DPLUSWINRT_STUB +} + void DPWinRT_SetDesktopEnumerationFlags(bool ignore_wmr_screens) { //This really is just a flag that could be hard coded to true in theory, but we keep our options open down the line even if it means carrying this everywhere @@ -510,6 +532,7 @@ DWORD WINAPI WinRTCaptureThreadEntry(_In_ void* Param) // Create the capture manager auto capture_manager = std::make_unique(data, g_MainThreadID); + capture_manager->PixelFormat( (g_IsHDREnabled) ? winrt::DirectXPixelFormat::R16G16B16A16Float : winrt::DirectXPixelFormat::B8G8R8A8UIntNormalized ); //Start capture if (DPWinRT_IsCaptureFromHandleSupported()) @@ -615,6 +638,11 @@ DWORD WINAPI WinRTCaptureThreadEntry(_In_ void* Param) capture_manager->IsCursorEnabled(msg.wParam); break; } + case WM_DPLUSWINRT_ENABLE_HDR: + { + capture_manager->PixelFormat( (msg.wParam) ? winrt::DirectXPixelFormat::R16G16B16A16Float : winrt::DirectXPixelFormat::B8G8R8A8UIntNormalized ); + break; + } case WM_DPLUSWINRT_THREAD_QUIT: { //Clear overlays here so they won't receive any more updates before the actually thread exits diff --git a/src/DesktopPlusWinRT/DesktopPlusWinRT.h b/src/DesktopPlusWinRT/DesktopPlusWinRT.h index 7ef3a78..4d50b25 100644 --- a/src/DesktopPlusWinRT/DesktopPlusWinRT.h +++ b/src/DesktopPlusWinRT/DesktopPlusWinRT.h @@ -36,10 +36,15 @@ #define WM_DPLUSWINRT_CAPTURE_PAUSE WM_DPLUSWINRT+2 //Sent to capture thread to pause/resume capture. wParam = overlay handle, lParam = pause bool #define WM_DPLUSWINRT_CAPTURE_LOST WM_DPLUSWINRT+3 //Sent to main thread when capture item was closed, should call StopCapture() in response. wParam = overlay handle #define WM_DPLUSWINRT_ENABLE_CURSOR WM_DPLUSWINRT+4 //Sent to capture thread to change cursor enabled state, wParam = cursor enabled bool -#define WM_DPLUSWINRT_THREAD_QUIT WM_DPLUSWINRT+5 //Sent to capture thread to quit when no overlays are left to capture -#define WM_DPLUSWINRT_THREAD_ERROR WM_DPLUSWINRT+6 //Sent to main thread when an unexpected error occured in the capture thread. wParam = thread ID, lParam = hresult -#define WM_DPLUSWINRT_THREAD_ACK WM_DPLUSWINRT+7 //Sent to main thread to acknowledge thread messages from StopCapture() (main thread is blocked until this is received) -#define WM_DPLUSWINRT_FPS WM_DPLUSWINRT+8 //Sent to main thread when fps count has changed. wParam = overlay handle, lParam = frames per second +#define WM_DPLUSWINRT_ENABLE_HDR WM_DPLUSWINRT+5 //Sent to capture thread to change HDR enabled state, wParam = HDR enabled bool +#define WM_DPLUSWINRT_THREAD_QUIT WM_DPLUSWINRT+6 //Sent to capture thread to quit when no overlays are left to capture +#define WM_DPLUSWINRT_THREAD_ERROR WM_DPLUSWINRT+7 //Sent to main thread when an unexpected error occured in the capture thread. wParam = thread ID, lParam = hresult +#define WM_DPLUSWINRT_THREAD_ACK WM_DPLUSWINRT+8 //Sent to main thread to acknowledge thread messages from StopCapture() (main thread is blocked until this is received) +#define WM_DPLUSWINRT_FPS WM_DPLUSWINRT+9 //Sent to main thread when fps count has changed. wParam = overlay handle, lParam = frames per second + +//The HDR texture returned by Graphics Capture appears to need a fixed brightness adjustment to match expectations +//Desktop Duplication doesn't require this, so perhaps there's more to it... or not +#define DPLUSWINRT_HDR_BRIGHTNESS_ADJUST 0.5f #ifdef __cplusplus extern "C" { @@ -64,6 +69,7 @@ DPLUSWINRT_API bool DPWinRT_StopCapture(vr::VROverlayHandle_t overlay_handle); DPLUSWINRT_API bool DPWinRT_SetOverlayUpdateLimitDelay(vr::VROverlayHandle_t overlay_handle, LONGLONG delay_quadpart); DPLUSWINRT_API bool DPWinRT_SetOverlayOverUnder3D(vr::VROverlayHandle_t overlay_handle, bool is_over_under_3D, int crop_x, int crop_y, int crop_width, int crop_height); DPLUSWINRT_API void DPWinRT_SetCaptureCursorEnabled(bool is_cursor_enabled); +DPLUSWINRT_API void DPWinRT_SetHDREnabled(bool is_hdr_enabled); DPLUSWINRT_API void DPWinRT_SetDesktopEnumerationFlags(bool ignore_wmr_screens); diff --git a/src/DesktopPlusWinRT/OverlayCapture.cpp b/src/DesktopPlusWinRT/OverlayCapture.cpp index 973df3a..e6a0f4e 100644 --- a/src/DesktopPlusWinRT/OverlayCapture.cpp +++ b/src/DesktopPlusWinRT/OverlayCapture.cpp @@ -258,7 +258,7 @@ void OverlayCapture::OnFrameArrived(winrt::Direct3D11CaptureFramePool const& sen //Set overlay textures vr::Texture_t vrtex = {}; vrtex.eType = vr::TextureType_DirectX; - vrtex.eColorSpace = vr::ColorSpace_Gamma; + vrtex.eColorSpace = (m_PixelFormat == winrt::DirectXPixelFormat::R16G16B16A16Float) ? vr::ColorSpace_Linear : vr::ColorSpace_Gamma; vrtex.handle = surface_texture.get(); size_t ou_count = 0; @@ -274,9 +274,7 @@ void OverlayCapture::OnFrameArrived(winrt::Direct3D11CaptureFramePool const& sen if (hr == S_OK) { - vr::Texture_t vrtex_ou; - vrtex_ou.eType = vr::TextureType_DirectX; - vrtex_ou.eColorSpace = vr::ColorSpace_Gamma; + vr::Texture_t vrtex_ou = vrtex; vrtex_ou.handle = m_OUConverters[ou_count].GetTexture(); vr::VROverlayEx()->SetOverlayTextureEx(overlay.Handle, &vrtex_ou, m_OUConverters[ou_count].GetTextureSizeSBS()); diff --git a/src/Shared/ConfigManager.cpp b/src/Shared/ConfigManager.cpp index 9b27453..e33c6d7 100644 --- a/src/Shared/ConfigManager.cpp +++ b/src/Shared/ConfigManager.cpp @@ -578,6 +578,7 @@ bool ConfigManager::LoadConfigFromFile() m_ConfigInt[configid_int_performance_update_limit_fps] = config.ReadInt( "Performance", "UpdateLimitFPS", update_limit_fps_30); m_ConfigBool[configid_bool_performance_rapid_laser_pointer_updates] = config.ReadBool("Performance", "RapidLaserPointerUpdates", false); m_ConfigBool[configid_bool_performance_single_desktop_mirroring] = config.ReadBool("Performance", "SingleDesktopMirroring", false); + m_ConfigBool[configid_bool_performance_hdr_mirroring] = config.ReadBool("Performance", "HDRMirroring", false); m_ConfigBool[configid_bool_performance_show_fps] = config.ReadBool("Performance", "ShowFPS", false); m_ConfigBool[configid_bool_performance_monitor_large_style] = config.ReadBool("Performance", "PerformanceMonitorStyleLarge", true); m_ConfigBool[configid_bool_performance_monitor_show_graphs] = config.ReadBool("Performance", "PerformanceMonitorShowGraphs", true); @@ -648,6 +649,8 @@ bool ConfigManager::LoadConfigFromFile() DPWinRT_SetCaptureCursorEnabled(m_ConfigBool[configid_bool_input_mouse_render_cursor]); } + DPWinRT_SetHDREnabled(m_ConfigBool[configid_bool_performance_hdr_mirroring]); + //Apply global settings for DPBrowser if (DPBrowserAPIClient::Get().IsBrowserAvailable()) { @@ -1547,6 +1550,7 @@ void ConfigManager::SaveConfigToFile() config.WriteInt( "Performance", "UpdateLimitFPS", m_ConfigInt[configid_int_performance_update_limit_fps]); config.WriteBool("Performance", "RapidLaserPointerUpdates", m_ConfigBool[configid_bool_performance_rapid_laser_pointer_updates]); config.WriteBool("Performance", "SingleDesktopMirroring", m_ConfigBool[configid_bool_performance_single_desktop_mirroring]); + config.WriteBool("Performance", "HDRMirroring", m_ConfigBool[configid_bool_performance_hdr_mirroring]); config.WriteBool("Performance", "ShowFPS", m_ConfigBool[configid_bool_performance_show_fps]); config.WriteBool("Performance", "PerformanceMonitorStyleLarge", m_ConfigBool[configid_bool_performance_monitor_large_style]); config.WriteBool("Performance", "PerformanceMonitorShowGraphs", m_ConfigBool[configid_bool_performance_monitor_show_graphs]); diff --git a/src/Shared/ConfigManager.h b/src/Shared/ConfigManager.h index 5747178..e867e48 100644 --- a/src/Shared/ConfigManager.h +++ b/src/Shared/ConfigManager.h @@ -65,6 +65,7 @@ enum ConfigID_Bool configid_bool_interface_quick_start_hidden, configid_bool_performance_rapid_laser_pointer_updates, configid_bool_performance_single_desktop_mirroring, + configid_bool_performance_hdr_mirroring, configid_bool_performance_show_fps, configid_bool_performance_monitor_large_style, configid_bool_performance_monitor_show_graphs,