Skip to content

Commit a6dccbf

Browse files
committed
Merge pull request #118339 from bruvzg/winrt_color
[Windows] Add support for `AdvancedColorInfo` info and change callback.
2 parents e0815c0 + 778e0a7 commit a6dccbf

6 files changed

Lines changed: 253 additions & 43 deletions

File tree

platform/windows/SCsub

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ from pathlib import Path
88

99
import platform_windows_builders
1010

11-
from methods import redirect_emitter
11+
from methods import get_compiler_version, redirect_emitter
1212

1313
sources = []
1414

@@ -92,8 +92,13 @@ if env["winrt"]:
9292
env_winrt["CXXFLAGS"].remove("-fno-exceptions")
9393
env_winrt.Append(CXXFLAGS=["-fexceptions"])
9494
else:
95+
cc_version = get_compiler_version(env)
96+
cc_version_major = cc_version["major"]
9597
if not env["use_llvm"]:
96-
env_winrt.Append(CXXFLAGS=["/await"])
98+
if cc_version_major >= 18:
99+
env_winrt.Append(CXXFLAGS=["/await:strict"]) # /await is deprecated in MSVC 2026+
100+
else:
101+
env_winrt.Append(CXXFLAGS=["/await"])
97102
if "/std:c++17" in env_winrt["CXXFLAGS"]:
98103
env_winrt["CXXFLAGS"].remove("/std:c++17")
99104
env_winrt.Append(CXXFLAGS=["/std:c++20"])

platform/windows/detect.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -427,6 +427,7 @@ def spawn_capture(sh, escape, cmd, args, env):
427427
"ntdll",
428428
"hid",
429429
"mincore",
430+
"coremessaging",
430431
]
431432

432433
if env.debug_features:
@@ -823,6 +824,7 @@ def configure_mingw(env: "SConsEnvironment"):
823824
"ntdll",
824825
"hid",
825826
"mincore",
827+
"coremessaging",
826828
]
827829
)
828830

platform/windows/display_server_windows.cpp

Lines changed: 64 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -3407,48 +3407,61 @@ HWND DisplayServerWindows::_find_window_from_process_id(ProcessID p_pid, HWND p_
34073407
}
34083408

34093409
// Get screen HDR capabilities for internal use only.
3410-
DisplayServerWindows::ScreenHdrData DisplayServerWindows::_get_screen_hdr_data(int p_screen, bool p_include_sdr_white_level) const {
3410+
DisplayServerWindows::ScreenHdrData DisplayServerWindows::_get_screen_hdr_data(DisplayServerEnums::WindowID p_window, bool p_include_sdr_white_level) const {
34113411
ScreenHdrData data;
3412-
HMONITOR monitor = _get_hmonitor_of_screen(p_screen);
3413-
if (!monitor) {
3414-
return data;
3415-
}
3412+
const WindowData &wd = windows[p_window];
3413+
if (WinRTUtils::window_has_display_info(wd.wrt_wd)) {
3414+
WinRTUtils::window_get_advanced_color_info(wd.wrt_wd, data.hdr_supported, data.min_luminance, data.max_luminance, data.max_average_luminance, data.sdr_white_level);
3415+
} else {
3416+
int screen = window_get_current_screen(p_window);
3417+
HMONITOR monitor = _get_hmonitor_of_screen(screen);
3418+
if (!monitor) {
3419+
return data;
3420+
}
34163421

34173422
#ifdef D3D12_ENABLED
3418-
// A dynamic cast is used here because the rendering context is not an Object and Object:cast is not supported.
3419-
RenderingContextDriverD3D12 *rendering_context_d3d12 = dynamic_cast<RenderingContextDriverD3D12 *>(rendering_context);
3420-
if (rendering_context_d3d12) {
3421-
IDXGIFactory2 *dxgi_factory = rendering_context_d3d12->dxgi_factory_get();
3423+
// A dynamic cast is used here because the rendering context is not an Object and Object:cast is not supported.
3424+
RenderingContextDriverD3D12 *rendering_context_d3d12 = dynamic_cast<RenderingContextDriverD3D12 *>(rendering_context);
3425+
if (rendering_context_d3d12) {
3426+
IDXGIFactory2 *dxgi_factory = rendering_context_d3d12->dxgi_factory_get();
34223427

3423-
DXGI_OUTPUT_DESC1 desc;
3424-
if (_get_monitor_desc(monitor, dxgi_factory, desc)) {
3425-
data.hdr_supported = desc.ColorSpace == DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020;
3426-
data.min_luminance = desc.MinLuminance;
3427-
data.max_luminance = desc.MaxLuminance;
3428-
data.max_average_luminance = desc.MaxFullFrameLuminance;
3428+
DXGI_OUTPUT_DESC1 desc;
3429+
if (_get_monitor_desc(monitor, dxgi_factory, desc)) {
3430+
data.hdr_supported = desc.ColorSpace == DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020;
3431+
data.min_luminance = desc.MinLuminance;
3432+
data.max_luminance = desc.MaxLuminance;
3433+
data.max_average_luminance = desc.MaxFullFrameLuminance;
3434+
}
34293435
}
3430-
}
34313436
#endif // D3D12_ENABLED
34323437

3433-
if (p_include_sdr_white_level) {
3434-
uint32_t path_count = 0;
3435-
uint32_t mode_count = 0;
3438+
if (p_include_sdr_white_level) {
3439+
uint32_t path_count = 0;
3440+
uint32_t mode_count = 0;
34363441

3437-
if (GetDisplayConfigBufferSizes(QDC_ONLY_ACTIVE_PATHS, &path_count, &mode_count) == ERROR_SUCCESS) {
3438-
LocalVector<DISPLAYCONFIG_PATH_INFO> paths;
3439-
LocalVector<DISPLAYCONFIG_MODE_INFO> modes;
3440-
paths.resize(path_count);
3441-
modes.resize(mode_count);
3442+
if (GetDisplayConfigBufferSizes(QDC_ONLY_ACTIVE_PATHS, &path_count, &mode_count) == ERROR_SUCCESS) {
3443+
LocalVector<DISPLAYCONFIG_PATH_INFO> paths;
3444+
LocalVector<DISPLAYCONFIG_MODE_INFO> modes;
3445+
paths.resize(path_count);
3446+
modes.resize(mode_count);
34423447

3443-
if (QueryDisplayConfig(QDC_ONLY_ACTIVE_PATHS, &path_count, paths.ptr(), &mode_count, modes.ptr(), nullptr) == ERROR_SUCCESS) {
3444-
data.sdr_white_level = _get_sdr_white_level_for_hmonitor(monitor, paths);
3448+
if (QueryDisplayConfig(QDC_ONLY_ACTIVE_PATHS, &path_count, paths.ptr(), &mode_count, modes.ptr(), nullptr) == ERROR_SUCCESS) {
3449+
data.sdr_white_level = _get_sdr_white_level_for_hmonitor(monitor, paths);
3450+
}
34453451
}
34463452
}
34473453
}
34483454

34493455
return data;
34503456
}
34513457

3458+
void DisplayServerWindows::_winrt_adv_color_info_cb(DisplayServerEnums::WindowID p_id) {
3459+
WindowData &wd = windows[p_id];
3460+
3461+
DisplayServerWindows::ScreenHdrData data = _get_screen_hdr_data(p_id, true);
3462+
_update_hdr_output_for_window(p_id, wd, data);
3463+
}
3464+
34523465
void DisplayServerWindows::_update_hdr_output_for_window(DisplayServerEnums::WindowID p_window, const WindowData &p_window_data, ScreenHdrData p_screen_data) {
34533466
#ifdef RD_ENABLED
34543467
if (rendering_context) {
@@ -3494,15 +3507,18 @@ void DisplayServerWindows::_update_hdr_output_for_window(DisplayServerEnums::Win
34943507
#endif // RD_ENABLED
34953508
}
34963509

3497-
void DisplayServerWindows::_update_hdr_output_for_tracked_windows(bool p_include_sdr_white_level) {
3510+
void DisplayServerWindows::_legacy_update_hdr_output_for_tracked_windows(bool p_include_sdr_white_level) {
34983511
hdr_output_cache.clear();
34993512
for (const KeyValue<DisplayServerEnums::WindowID, WindowData> &E : windows) {
3513+
if (WinRTUtils::window_has_display_info(E.value.wrt_wd)) {
3514+
continue; // Updated by "_winrt_adv_color_info_cb" callback.
3515+
}
35003516
if (E.value.hdr_output_requested) {
35013517
int screen = window_get_current_screen(E.key);
35023518

35033519
ScreenHdrData data;
35043520
if (!hdr_output_cache.has(screen)) {
3505-
data = _get_screen_hdr_data(screen, p_include_sdr_white_level);
3521+
data = _get_screen_hdr_data(E.key, p_include_sdr_white_level);
35063522
hdr_output_cache.insert(screen, data);
35073523
} else {
35083524
data = hdr_output_cache[screen];
@@ -4211,7 +4227,7 @@ void DisplayServerWindows::process_events() {
42114227
// because the only way to adjust this is to leave the Godot Window and adjust the SDR/HDR
42124228
// Content Brightness Windows display setting. This means the user must return to the Godot
42134229
// window, which triggers a WM_WINDOWPOSCHANGED event.
4214-
_update_hdr_output_for_tracked_windows(false);
4230+
_legacy_update_hdr_output_for_tracked_windows(false);
42154231

42164232
LocalVector<List<FileDialogData *>::Element *> to_remove;
42174233
for (List<FileDialogData *>::Element *E = file_dialogs.front(); E; E = E->next()) {
@@ -4737,8 +4753,7 @@ bool DisplayServerWindows::window_is_hdr_output_supported(DisplayServerEnums::Wi
47374753
#endif
47384754

47394755
// The window supports HDR if the screen it is on supports HDR.
4740-
int screen = window_get_current_screen(p_window);
4741-
DisplayServerWindows::ScreenHdrData data = _get_screen_hdr_data(screen, false);
4756+
DisplayServerWindows::ScreenHdrData data = _get_screen_hdr_data(p_window, false);
47424757
return data.hdr_supported;
47434758
}
47444759

@@ -4752,8 +4767,7 @@ void DisplayServerWindows::window_request_hdr_output(const bool p_enable, Displa
47524767
WindowData &wd = windows[p_window];
47534768
wd.hdr_output_requested = p_enable;
47544769

4755-
int screen = window_get_current_screen(p_window);
4756-
DisplayServerWindows::ScreenHdrData data = _get_screen_hdr_data(screen, true);
4770+
DisplayServerWindows::ScreenHdrData data = _get_screen_hdr_data(p_window, true);
47574771
_update_hdr_output_for_window(p_window, wd, data);
47584772
}
47594773

@@ -4789,8 +4803,7 @@ void DisplayServerWindows::window_set_hdr_output_reference_luminance(const float
47894803

47904804
// Negative luminance means auto-adjust
47914805
if (wd.hdr_output_reference_luminance < 0.0f) {
4792-
int screen = window_get_current_screen(p_window);
4793-
DisplayServerWindows::ScreenHdrData data = _get_screen_hdr_data(screen, true);
4806+
DisplayServerWindows::ScreenHdrData data = _get_screen_hdr_data(p_window, true);
47944807
_update_hdr_output_for_window(p_window, wd, data);
47954808
} else {
47964809
// Otherwise, apply the requested luminance
@@ -4835,8 +4848,7 @@ void DisplayServerWindows::window_set_hdr_output_max_luminance(const float p_max
48354848

48364849
// Negative luminance means auto-adjust
48374850
if (wd.hdr_output_max_luminance < 0.0f) {
4838-
int screen = window_get_current_screen(p_window);
4839-
DisplayServerWindows::ScreenHdrData data = _get_screen_hdr_data(screen, true);
4851+
DisplayServerWindows::ScreenHdrData data = _get_screen_hdr_data(p_window, true);
48404852
_update_hdr_output_for_window(p_window, wd, data);
48414853
} else {
48424854
// Otherwise, apply the requested luminance
@@ -6356,7 +6368,7 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
63566368

63576369
case WM_DISPLAYCHANGE: {
63586370
// Update HDR capabilities and reference luminance when display changes.
6359-
_update_hdr_output_for_tracked_windows(true);
6371+
_legacy_update_hdr_output_for_tracked_windows(true);
63606372
} break;
63616373

63626374
case WM_WINDOWPOSCHANGED: {
@@ -6497,7 +6509,7 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
64976509
// Update HDR capabilities and reference luminance when window moves to different screen.
64986510
// Also update when Godot has regained focus because the user may have adjusted their SDR white
64996511
// level while Godot was not in focus.
6500-
_update_hdr_output_for_tracked_windows(true);
6512+
_legacy_update_hdr_output_for_tracked_windows(true);
65016513

65026514
// Return here to prevent WM_MOVE and WM_SIZE from being sent
65036515
// See: https://docs.microsoft.com/en-us/windows/win32/winmsg/wm-windowposchanged#remarks
@@ -7036,6 +7048,10 @@ Error DisplayServerWindows::_create_window(DisplayServerEnums::WindowID p_window
70367048

70377049
wd.parent_hwnd = p_parent_hwnd;
70387050

7051+
if (has_winrt_queue) {
7052+
wd.wrt_wd = WinRTUtils::create_wd(wd.hWnd, callable_mp(this, &DisplayServerWindows::_winrt_adv_color_info_cb), wd.id);
7053+
}
7054+
70397055
// Detach the input queue from the parent window.
70407056
// This prevents the embedded window from waiting on the main window's input queue,
70417057
// causing lags input lags when resizing or moving the main window.
@@ -7228,6 +7244,9 @@ void DisplayServerWindows::_destroy_window(DisplayServerEnums::WindowID p_window
72287244
wd.icon_small = nullptr;
72297245
}
72307246

7247+
if (has_winrt_queue) {
7248+
WinRTUtils::destroy_wd(wd.wrt_wd);
7249+
}
72317250
DestroyWindow(wd.hWnd);
72327251
windows.erase(p_window_id);
72337252
}
@@ -7565,6 +7584,8 @@ DisplayServerWindows::DisplayServerWindows(const String &p_rendering_driver, Dis
75657584
}
75667585
native_menu = memnew(NativeMenuWindows);
75677586

7587+
has_winrt_queue = WinRTUtils::create_queue();
7588+
75687589
// Enforce default keep screen on value.
75697590
screen_set_keep_on(GLOBAL_GET("display/window/energy_saving/keep_screen_on"));
75707591

@@ -8238,6 +8259,10 @@ DisplayServerWindows::~DisplayServerWindows() {
82388259

82398260
cursors_cache.clear();
82408261

8262+
if (has_winrt_queue) {
8263+
WinRTUtils::destroy_queue();
8264+
}
8265+
82418266
// Destroy all status indicators.
82428267
for (HashMap<DisplayServerEnums::IndicatorID, IndicatorData>::Iterator E = indicators.begin(); E; ++E) {
82438268
NOTIFYICONDATAW ndat;

platform/windows/display_server_windows.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,7 @@ typedef struct {
184184
class DropTargetWindows;
185185
class NativeMenuWindows;
186186
class TTS_Windows;
187+
class WinRTWindowData;
187188

188189
#ifndef WDA_EXCLUDEFROMCAPTURE
189190
#define WDA_EXCLUDEFROMCAPTURE 0x00000011
@@ -282,9 +283,13 @@ class DisplayServerWindows : public DisplayServer {
282283
NativeMenuWindows *native_menu = nullptr;
283284
ITaskbarList3 *taskbar = nullptr;
284285

286+
bool has_winrt_queue = false;
287+
void _winrt_adv_color_info_cb(DisplayServerEnums::WindowID p_id);
288+
285289
struct WindowData {
286290
HWND hWnd;
287291
DisplayServerEnums::WindowID id;
292+
WinRTWindowData *wrt_wd = nullptr;
288293

289294
Vector<Vector2> mpath;
290295
DisplayServerEnums::ProgressState progress_state = DisplayServerEnums::PROGRESS_STATE_NOPROGRESS;
@@ -556,9 +561,9 @@ class DisplayServerWindows : public DisplayServer {
556561
};
557562
AHashMap<int, ScreenHdrData> hdr_output_cache;
558563

559-
ScreenHdrData _get_screen_hdr_data(int p_screen, bool p_include_sdr_white_level) const;
564+
ScreenHdrData _get_screen_hdr_data(DisplayServerEnums::WindowID p_window, bool p_include_sdr_white_level) const;
560565
void _update_hdr_output_for_window(DisplayServerEnums::WindowID p_window, const WindowData &p_window_data, ScreenHdrData p_screen_data);
561-
void _update_hdr_output_for_tracked_windows(bool p_include_sdr_white_level);
566+
void _legacy_update_hdr_output_for_tracked_windows(bool p_include_sdr_white_level);
562567

563568
public:
564569
LRESULT WndProcFileDialog(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);

0 commit comments

Comments
 (0)