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,