diff --git a/src/platform/windows/virtual_display.cpp b/src/platform/windows/virtual_display.cpp index e0571f6f..06c1ba0f 100644 --- a/src/platform/windows/virtual_display.cpp +++ b/src/platform/windows/virtual_display.cpp @@ -8,6 +8,8 @@ #include #include +#include +#include #include "virtual_display.h" @@ -106,6 +108,83 @@ bool setPrimaryDisplay(const wchar_t* primaryDeviceName) { return true; } + +bool ensureDisplayHDR(const wchar_t* displayName) { + UINT32 pathCount = 0, modeCount = 0; + + if (GetDisplayConfigBufferSizes(QDC_ONLY_ACTIVE_PATHS, &pathCount, &modeCount) != ERROR_SUCCESS) { + printf("Failed to query display configuration.\n"); + return false; + } + + std::vector pathArray(pathCount); + std::vector modeArray(modeCount); + + if (QueryDisplayConfig(QDC_ONLY_ACTIVE_PATHS, &pathCount, pathArray.data(), &modeCount, modeArray.data(), NULL) != ERROR_SUCCESS) { + printf("Failed to query display paths.\n"); + return false; + } + + for (const auto& path : pathArray) { + DISPLAYCONFIG_PATH_SOURCE_INFO sourceInfo = path.sourceInfo; + + DISPLAYCONFIG_SOURCE_DEVICE_NAME deviceName = {}; + deviceName.header.type = DISPLAYCONFIG_DEVICE_INFO_GET_SOURCE_NAME; + deviceName.header.size = sizeof(deviceName); + deviceName.header.adapterId = sourceInfo.adapterId; + deviceName.header.id = sourceInfo.id; + + if (DisplayConfigGetDeviceInfo(&deviceName.header) != ERROR_SUCCESS) { + continue; + } + + if (std::wstring_view(displayName) == deviceName.viewGdiDeviceName) { + DISPLAYCONFIG_GET_ADVANCED_COLOR_INFO hdrInfo = {}; + hdrInfo.header.type = DISPLAYCONFIG_DEVICE_INFO_GET_ADVANCED_COLOR_INFO; + hdrInfo.header.size = sizeof(hdrInfo); + hdrInfo.header.adapterId = path.targetInfo.adapterId; + hdrInfo.header.id = path.targetInfo.id; + + if (DisplayConfigGetDeviceInfo(&hdrInfo.header) != ERROR_SUCCESS) { + wprintf(L"Failed to get HDR info for display: %ls\n", std::wstring(deviceName.viewGdiDeviceName)); + return false; + } + + if (hdrInfo.advancedColorSupported) { + if (hdrInfo.advancedColorEnabled) { + DISPLAYCONFIG_SET_ADVANCED_COLOR_STATE setHdrInfo = {}; + setHdrInfo.header.type = DISPLAYCONFIG_DEVICE_INFO_SET_ADVANCED_COLOR_STATE; + setHdrInfo.header.size = sizeof(setHdrInfo); + setHdrInfo.header.adapterId = path.targetInfo.adapterId; + setHdrInfo.header.id = path.targetInfo.id; + setHdrInfo.enableAdvancedColor = FALSE; // Disable HDR + + if (DisplayConfigSetDeviceInfo(&setHdrInfo.header) == ERROR_SUCCESS) { + wprintf(L"HDR toggled off for display: %ls\n", displayName); + } else { + wprintf(L"Failed to toggle HDR off for display: %ls\n", std::wstring(deviceName.viewGdiDeviceName)); + } + + setHdrInfo.enableAdvancedColor = TRUE; // Enable HDR back on + + if (DisplayConfigSetDeviceInfo(&setHdrInfo.header) == ERROR_SUCCESS) { + wprintf(L"HDR toggled on for display: %ls\n", displayName); + return true; + } else { + wprintf(L"Failed to toggle HDR on for display: %ls\n", std::wstring(deviceName.viewGdiDeviceName)); + } + } else { + wprintf(L"HDR is not enabled on display: %ls\n", displayName); + } + } + return false; + } + } + + wprintf(L"Display not found or HDR not supported: %ls\n", displayName); + return false; +} + void closeVDisplayDevice() { if (SUDOVDA_DRIVER_HANDLE == INVALID_HANDLE_VALUE) { return; @@ -172,29 +251,29 @@ bool setRenderAdapterByName(const std::wstring& adapterName) { return false; } - Microsoft::WRL::ComPtr factory; - if (!SUCCEEDED(CreateDXGIFactory1(IID_PPV_ARGS(&factory)))) { - return false; - } + Microsoft::WRL::ComPtr factory; + if (!SUCCEEDED(CreateDXGIFactory1(IID_PPV_ARGS(&factory)))) { + return false; + } - Microsoft::WRL::ComPtr adapter; + Microsoft::WRL::ComPtr adapter; DXGI_ADAPTER_DESC desc; int i = 0; - while (SUCCEEDED(factory->EnumAdapters(i, &adapter))) { - i += 1; + while (SUCCEEDED(factory->EnumAdapters(i, &adapter))) { + i += 1; - if (!SUCCEEDED(adapter->GetDesc(&desc))) { - continue; - } + if (!SUCCEEDED(adapter->GetDesc(&desc))) { + continue; + } - if (std::wstring_view(desc.Description) != adapterName) { - continue; - } + if (std::wstring_view(desc.Description) != adapterName) { + continue; + } - if (SetRenderAdapter(SUDOVDA_DRIVER_HANDLE, desc.AdapterLuid)) { - return true; - } - } + if (SetRenderAdapter(SUDOVDA_DRIVER_HANDLE, desc.AdapterLuid)) { + return true; + } + } return false; } diff --git a/src/platform/windows/virtual_display.h b/src/platform/windows/virtual_display.h index fcdcd99d..ea27f0bf 100644 --- a/src/platform/windows/virtual_display.h +++ b/src/platform/windows/virtual_display.h @@ -25,6 +25,7 @@ namespace VDISPLAY { LONG changeDisplaySettings(const wchar_t* deviceName, int width, int height, int refresh_rate); std::wstring getPrimaryDisplay(); bool setPrimaryDisplay(const wchar_t* primaryDeviceName); + bool ensureDisplayHDR(const wchar_t* displayName); void closeVDisplayDevice(); DRIVER_STATUS openVDisplayDevice(); diff --git a/src/process.cpp b/src/process.cpp index f3bda283..437c9712 100644 --- a/src/process.cpp +++ b/src/process.cpp @@ -368,6 +368,24 @@ namespace proc { _app_launch_time = std::chrono::steady_clock::now(); + #ifdef _WIN32 + auto resetHDRThread = std::thread([this]{ + std::this_thread::sleep_for(200ms); + // Windows doesn't seem to be able to set HDR correctly when a display is just connected, + // so we have tooggle HDR for the virtual display manually. + std::string currentDisplay = this->display_name; + if (!currentDisplay.empty()) { + if (VDISPLAY::ensureDisplayHDR(platf::from_utf8(currentDisplay).c_str())) { + BOOST_LOG(info) << "HDR rsestted for display " << currentDisplay; + } else { + BOOST_LOG(info) << "HDR not applied for display " << currentDisplay; + }; + } + }); + + resetHDRThread.detach(); + #endif + fg.disable(); return 0; diff --git a/src/video_colorspace.cpp b/src/video_colorspace.cpp index 7b1ddadf..42f7a409 100644 --- a/src/video_colorspace.cpp +++ b/src/video_colorspace.cpp @@ -24,6 +24,8 @@ namespace video { /* See video::config_t declaration for details */ + BOOST_LOG(info) << "Client dynamicRange: " << config.dynamicRange << ", Display is HDR: " << hdr_display; + if (config.dynamicRange > 0 && hdr_display) { // Rec. 2020 with ST 2084 perceptual quantizer colorspace.colorspace = colorspace_e::bt2020;