Skip to content

Commit

Permalink
fix(hdr): use new HDR WinAPI for W11 24H2 and above (#137)
Browse files Browse the repository at this point in the history
  • Loading branch information
FrogTheFrog authored Jan 26, 2025
1 parent 1975f75 commit f434ff2
Showing 1 changed file with 60 additions and 0 deletions.
60 changes: 60 additions & 0 deletions src/windows/win_api_layer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,33 @@ namespace display_device {

return output;
}

/**
* @brief Check if the Windows 11 version is equal to 24H2 update or later.
* @param w_api Reference to the WinApiLayer.
* @return True if version >= W11 24H2, false otherwise.
*/
bool is_W11_24H2_OrAbove(const WinApiLayerInterface &w_api) {
OSVERSIONINFOEXA os_version_info;
os_version_info.dwOSVersionInfoSize = sizeof(os_version_info);
os_version_info.dwMajorVersion = HIBYTE(_WIN32_WINNT_WIN10);
os_version_info.dwMinorVersion = LOBYTE(_WIN32_WINNT_WIN10);
os_version_info.dwBuildNumber = 26100; // The earliest pre-release version is 25947, whereas the stable is 26100

ULONGLONG condition_mask {0};
condition_mask = VerSetConditionMask(condition_mask, VER_MAJORVERSION, VER_GREATER_EQUAL); // Major version condition
condition_mask = VerSetConditionMask(condition_mask, VER_MINORVERSION, VER_GREATER_EQUAL); // Minor version condition
condition_mask = VerSetConditionMask(condition_mask, VER_BUILDNUMBER, VER_GREATER_EQUAL); // Build number condition

BOOL result {VerifyVersionInfoA(&os_version_info, VER_MAJORVERSION | VER_MINORVERSION | VER_BUILDNUMBER, condition_mask)};
if (result == FALSE) {
DD_LOG(verbose) << w_api.getErrorString(static_cast<LONG>(GetLastError())) << " \"is_W11_24H2_OrAbove\" returned false.";
return false;
}

DD_LOG(verbose) << "\"is_W11_24H2_OrAbove\" returned true.";
return true;
}
} // namespace

std::string WinApiLayer::getErrorString(LONG error_code) const {
Expand Down Expand Up @@ -520,6 +547,22 @@ namespace display_device {
}

std::optional<HdrState> WinApiLayer::getHdrState(const DISPLAYCONFIG_PATH_INFO &path) const {
if (is_W11_24H2_OrAbove(*this)) {
DISPLAYCONFIG_GET_ADVANCED_COLOR_INFO_2 color_info = {};
color_info.header.adapterId = path.targetInfo.adapterId;
color_info.header.id = path.targetInfo.id;
color_info.header.type = DISPLAYCONFIG_DEVICE_INFO_GET_ADVANCED_COLOR_INFO_2;
color_info.header.size = sizeof(color_info);

LONG result {DisplayConfigGetDeviceInfo(&color_info.header)};
if (result != ERROR_SUCCESS) {
DD_LOG(error) << getErrorString(result) << " failed to get advanced color info 2!";
return std::nullopt;
}

return color_info.highDynamicRangeSupported ? std::make_optional(color_info.highDynamicRangeUserEnabled ? HdrState::Enabled : HdrState::Disabled) : std::nullopt;
}

DISPLAYCONFIG_GET_ADVANCED_COLOR_INFO color_info = {};
color_info.header.adapterId = path.targetInfo.adapterId;
color_info.header.id = path.targetInfo.id;
Expand All @@ -536,6 +579,23 @@ namespace display_device {
}

bool WinApiLayer::setHdrState(const DISPLAYCONFIG_PATH_INFO &path, HdrState state) {
if (is_W11_24H2_OrAbove(*this)) {
DISPLAYCONFIG_SET_HDR_STATE hdr_state = {};
hdr_state.header.adapterId = path.targetInfo.adapterId;
hdr_state.header.id = path.targetInfo.id;
hdr_state.header.type = DISPLAYCONFIG_DEVICE_INFO_TYPE(16);
hdr_state.header.size = sizeof(hdr_state);
hdr_state.enableHdr = state == HdrState::Enabled ? 1 : 0;

LONG result {DisplayConfigSetDeviceInfo(&hdr_state.header)};
if (result != ERROR_SUCCESS) {
DD_LOG(error) << getErrorString(result) << " failed to set HDR state!";
return false;
}

return true;
}

DISPLAYCONFIG_SET_ADVANCED_COLOR_STATE color_state = {};
color_state.header.adapterId = path.targetInfo.adapterId;
color_state.header.id = path.targetInfo.id;
Expand Down

0 comments on commit f434ff2

Please sign in to comment.