Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 34 additions & 21 deletions platform/windows/display_server_windows.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3385,7 +3385,7 @@ HWND DisplayServerWindows::_find_window_from_process_id(ProcessID p_pid, HWND p_
}

// Get screen HDR capabilities for internal use only.
DisplayServerWindows::ScreenHdrData DisplayServerWindows::_get_screen_hdr_data(int p_screen) const {
DisplayServerWindows::ScreenHdrData DisplayServerWindows::_get_screen_hdr_data(int p_screen, bool p_include_sdr_white_level) const {
ScreenHdrData data;
HMONITOR monitor = _get_hmonitor_of_screen(p_screen);
if (!monitor) {
Expand All @@ -3408,17 +3408,19 @@ DisplayServerWindows::ScreenHdrData DisplayServerWindows::_get_screen_hdr_data(i
}
#endif // D3D12_ENABLED

uint32_t path_count = 0;
uint32_t mode_count = 0;
if (p_include_sdr_white_level) {
uint32_t path_count = 0;
uint32_t mode_count = 0;

if (GetDisplayConfigBufferSizes(QDC_ONLY_ACTIVE_PATHS, &path_count, &mode_count) == ERROR_SUCCESS) {
LocalVector<DISPLAYCONFIG_PATH_INFO> paths;
LocalVector<DISPLAYCONFIG_MODE_INFO> modes;
paths.resize(path_count);
modes.resize(mode_count);
if (GetDisplayConfigBufferSizes(QDC_ONLY_ACTIVE_PATHS, &path_count, &mode_count) == ERROR_SUCCESS) {
LocalVector<DISPLAYCONFIG_PATH_INFO> paths;
LocalVector<DISPLAYCONFIG_MODE_INFO> modes;
paths.resize(path_count);
modes.resize(mode_count);

if (QueryDisplayConfig(QDC_ONLY_ACTIVE_PATHS, &path_count, paths.ptr(), &mode_count, modes.ptr(), nullptr) == ERROR_SUCCESS) {
data.sdr_white_level = _get_sdr_white_level_for_hmonitor(monitor, paths);
if (QueryDisplayConfig(QDC_ONLY_ACTIVE_PATHS, &path_count, paths.ptr(), &mode_count, modes.ptr(), nullptr) == ERROR_SUCCESS) {
data.sdr_white_level = _get_sdr_white_level_for_hmonitor(monitor, paths);
}
}
}

Expand Down Expand Up @@ -3455,15 +3457,15 @@ void DisplayServerWindows::_update_hdr_output_for_window(DisplayServerEnums::Win
#endif // RD_ENABLED
}

void DisplayServerWindows::_update_hdr_output_for_tracked_windows() {
void DisplayServerWindows::_update_hdr_output_for_tracked_windows(bool p_include_sdr_white_level) {
hdr_output_cache.clear();
for (const KeyValue<DisplayServerEnums::WindowID, WindowData> &E : windows) {
if (E.value.hdr_output_requested) {
int screen = window_get_current_screen(E.key);

ScreenHdrData data;
if (!hdr_output_cache.has(screen)) {
data = _get_screen_hdr_data(screen);
data = _get_screen_hdr_data(screen, p_include_sdr_white_level);
hdr_output_cache.insert(screen, data);
} else {
data = hdr_output_cache[screen];
Expand Down Expand Up @@ -4161,7 +4163,16 @@ void DisplayServerWindows::process_events() {

// Poll HDR output state for windows that have requested it.
// Needed to detect changes in luminance values due to a lack of Windows events for such changes.
_update_hdr_output_for_tracked_windows();
// System-reported max luminance changes when the user adjust the screen brightness of a laptop
// with a built-in HDR screen. Additionally, some computers may continue to report a
// DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709 color space for a period of time after the
// WM_DISPLAYCHANGE event is received by Godot which means we must poll this regularly to
// capture this change in HDR capabilities of the screen triggered by the Win + Alt + B shortcut.
// The SDR white level (reference white luminance) does not need to be polled every frame
// because the only way to adjust this is to leave the Godot Window and adjust the SDR/HDR
// Content Brightness Windows display setting. This means the user must return to the Godot
// window, which triggers a WM_WINDOWPOSCHANGED event.
_update_hdr_output_for_tracked_windows(false);

LocalVector<List<FileDialogData *>::Element *> to_remove;
for (List<FileDialogData *>::Element *E = file_dialogs.front(); E; E = E->next()) {
Expand Down Expand Up @@ -4633,7 +4644,7 @@ bool DisplayServerWindows::window_is_hdr_output_supported(DisplayServerEnums::Wi

// The window supports HDR if the screen it is on supports HDR.
int screen = window_get_current_screen(p_window);
DisplayServerWindows::ScreenHdrData data = _get_screen_hdr_data(screen);
DisplayServerWindows::ScreenHdrData data = _get_screen_hdr_data(screen, false);
return data.hdr_supported;
}

Expand All @@ -4648,7 +4659,7 @@ void DisplayServerWindows::window_request_hdr_output(const bool p_enable, Displa
wd.hdr_output_requested = p_enable;

int screen = window_get_current_screen(p_window);
DisplayServerWindows::ScreenHdrData data = _get_screen_hdr_data(screen);
DisplayServerWindows::ScreenHdrData data = _get_screen_hdr_data(screen, true);
_update_hdr_output_for_window(p_window, wd, data);
}

Expand Down Expand Up @@ -4685,7 +4696,7 @@ void DisplayServerWindows::window_set_hdr_output_reference_luminance(const float
// Negative luminance means auto-adjust
if (wd.hdr_output_reference_luminance < 0.0f) {
int screen = window_get_current_screen(p_window);
DisplayServerWindows::ScreenHdrData data = _get_screen_hdr_data(screen);
DisplayServerWindows::ScreenHdrData data = _get_screen_hdr_data(screen, true);
_update_hdr_output_for_window(p_window, wd, data);
} else {
// Otherwise, apply the requested luminance
Expand Down Expand Up @@ -4730,7 +4741,7 @@ void DisplayServerWindows::window_set_hdr_output_max_luminance(const float p_max
// Negative luminance means auto-adjust
if (wd.hdr_output_max_luminance < 0.0f) {
int screen = window_get_current_screen(p_window);
DisplayServerWindows::ScreenHdrData data = _get_screen_hdr_data(screen);
DisplayServerWindows::ScreenHdrData data = _get_screen_hdr_data(screen, true);
_update_hdr_output_for_window(p_window, wd, data);
} else {
// Otherwise, apply the requested luminance
Expand Down Expand Up @@ -6249,7 +6260,7 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA

case WM_DISPLAYCHANGE: {
// Update HDR capabilities and reference luminance when display changes.
_update_hdr_output_for_tracked_windows();
_update_hdr_output_for_tracked_windows(true);
} break;

case WM_WINDOWPOSCHANGED: {
Expand Down Expand Up @@ -6347,9 +6358,6 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
window.rect_changed_callback.call(Rect2i(window.last_pos.x, window.last_pos.y, window.width, window.height));
}

// Update HDR capabilities and reference luminance when window moves to different screen.
_update_hdr_output_for_tracked_windows();

// Update cursor clip region after window rect has changed.
if (mouse_mode == DisplayServerEnums::MOUSE_MODE_CAPTURED || mouse_mode == DisplayServerEnums::MOUSE_MODE_CONFINED || mouse_mode == DisplayServerEnums::MOUSE_MODE_CONFINED_HIDDEN) {
RECT crect;
Expand Down Expand Up @@ -6388,6 +6396,11 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
}
}

// Update HDR capabilities and reference luminance when window moves to different screen.
// Also update when Godot has regained focus because the user may have adjusted their SDR white
// level while Godot was not in focus.
_update_hdr_output_for_tracked_windows(true);

// Return here to prevent WM_MOVE and WM_SIZE from being sent
// See: https://docs.microsoft.com/en-us/windows/win32/winmsg/wm-windowposchanged#remarks
return 0;
Expand Down
4 changes: 2 additions & 2 deletions platform/windows/display_server_windows.h
Original file line number Diff line number Diff line change
Expand Up @@ -548,9 +548,9 @@ class DisplayServerWindows : public DisplayServer {
};
AHashMap<int, ScreenHdrData> hdr_output_cache;

ScreenHdrData _get_screen_hdr_data(int p_screen) const;
ScreenHdrData _get_screen_hdr_data(int p_screen, bool p_include_sdr_white_level) const;
void _update_hdr_output_for_window(DisplayServerEnums::WindowID p_window, const WindowData &p_window_data, ScreenHdrData p_screen_data);
void _update_hdr_output_for_tracked_windows();
void _update_hdr_output_for_tracked_windows(bool p_include_sdr_white_level);

public:
LRESULT WndProcFileDialog(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
Expand Down
Loading