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
4 changes: 4 additions & 0 deletions doc/classes/DisplayServer.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3375,6 +3375,10 @@
Sent when the window has been forcibly closed by the display server. The window will immediately hide and clean any internal rendering references.
[b]Note:[/b] This flag is implemented only on Linux (Wayland).
</constant>
<constant name="WINDOW_EVENT_OUTPUT_MAX_LINEAR_VALUE_CHANGED" value="9" enum="WindowEvent">
Sent when the output max linear value returned by [method Window.get_output_max_linear_value] has changed.
This occurs when HDR output is enabled or disabled and when any HDR output luminance values of the window have changed, such as when the player adjusts their screen brightness setting or moves the window to a different screen.
</constant>
<constant name="WINDOW_EDGE_TOP_LEFT" value="0" enum="WindowResizeEdge">
Top-left edge of a window.
</constant>
Expand Down
4 changes: 4 additions & 0 deletions doc/classes/Node.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1276,6 +1276,10 @@
<constant name="NOTIFICATION_WM_POSITION_CHANGED" value="1012">
Notification received when the window is moved.
</constant>
<constant name="NOTIFICATION_WM_OUTPUT_MAX_LINEAR_VALUE_CHANGED" value="1013">
Notification received when the output max linear value returned by [method Window.get_output_max_linear_value] has changed.
This occurs when HDR output is enabled or disabled and when any HDR output luminance values of the window have changed, such as when the player adjusts their screen brightness setting or moves the window to a different screen.
</constant>
<constant name="NOTIFICATION_OS_MEMORY_WARNING" value="2009">
Notification received from the OS when the application is exceeding its allocated memory.
Implemented only on iOS.
Expand Down
10 changes: 8 additions & 2 deletions doc/classes/Window.xml
Original file line number Diff line number Diff line change
Expand Up @@ -123,8 +123,8 @@
<method name="get_output_max_linear_value" qualifiers="const">
<return type="float" />
<description>
Returns the maximum value for linear color components that can be displayed in this window, regardless of SDR or HDR output. Returns [code]1.0[/code] if HDR is not enabled or not supported. This value is used by tonemapping and other [Environment] effects to ensure that bright colors are presented in the range that can be displayed by this window.
When using the Linear tonemapper without [Environment] effects or no [WorldEnvironment], use the returned value to scale content to maximize the screen's brightness, such as for lasers or other bright effects. The following is an example that produces the brightest purple color that the screen can produce:
Returns the maximum value for linear color components that can be displayed in this window, regardless of SDR or HDR output. Returns [code]1.0[/code] if HDR is not enabled or not supported. The [signal output_max_linear_value_changed] signal will be emitted whenever this value changes.
This value is used by tonemapping and other [Environment] effects to ensure that bright colors are presented in the range that can be displayed by this window. When using the Linear tonemapper without [Environment] effects or no [WorldEnvironment], use the returned value to scale content to maximize the screen's brightness, such as for lasers or other bright effects. The following is an example that produces the brightest purple color that the screen can produce:
[codeblocks]
[gdscript]
func _process(_delta):
Expand Down Expand Up @@ -867,6 +867,12 @@
Emitted when the mouse event is received by the custom decoration area defined by [member nonclient_area], and normal input to the window is blocked (such as when it has an exclusive child opened). [param event]'s position is in the embedder's coordinate system.
</description>
</signal>
<signal name="output_max_linear_value_changed">
<param index="0" name="output_max_linear_value" type="float" />
<description>
Emitted when the output max linear value returned by [method Window.get_output_max_linear_value] has changed. This occurs when HDR output is enabled or disabled and when any HDR output luminance values of the window have changed, such as when the player adjusts their screen brightness setting or moves the window to a different screen. [param output_max_linear_value] is the new value.
</description>
</signal>
<signal name="theme_changed">
<description>
Emitted when the [constant NOTIFICATION_THEME_CHANGED] notification is sent.
Expand Down
2 changes: 1 addition & 1 deletion drivers/apple_embedded/display_server_apple_embedded.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ class DisplayServerAppleEmbedded : public DisplayServer {
void initialize_tts() const;

bool edr_requested = false;
void _update_hdr_output();
void _update_hdr_output(bool edr_headroom_changed);
float _calculate_current_reference_luminance() const;

protected:
Expand Down
13 changes: 9 additions & 4 deletions drivers/apple_embedded/display_server_apple_embedded.mm
Original file line number Diff line number Diff line change
Expand Up @@ -823,14 +823,15 @@ _FORCE_INLINE_ int _convert_utf32_offset_to_utf16(const String &p_existing_text,

// MARK: - HDR / EDR

void DisplayServerAppleEmbedded::_update_hdr_output() {
void DisplayServerAppleEmbedded::_update_hdr_output(bool edr_headroom_changed) {
#ifdef RD_ENABLED
if (!rendering_context) {
return;
}

bool desired = edr_requested && _screen_hdr_is_supported();
if (rendering_context->window_get_hdr_output_enabled(DisplayServerEnums::MAIN_WINDOW_ID) != desired) {
bool hdr_state_changed = rendering_context->window_get_hdr_output_enabled(DisplayServerEnums::MAIN_WINDOW_ID) != desired;
if (hdr_state_changed) {
rendering_context->window_set_hdr_output_enabled(DisplayServerEnums::MAIN_WINDOW_ID, desired);
}

Expand All @@ -839,11 +840,15 @@ _FORCE_INLINE_ int _convert_utf32_offset_to_utf16(const String &p_existing_text,

float max_luminance = _screen_potential_edr_headroom() * hardware_reference_luminance_nits;
rendering_context->window_set_hdr_output_max_luminance(DisplayServerEnums::MAIN_WINDOW_ID, max_luminance);

if (hdr_state_changed || edr_headroom_changed) {
send_window_event(DisplayServerEnums::WINDOW_EVENT_OUTPUT_MAX_LINEAR_VALUE_CHANGED);
}
#endif
}

void DisplayServerAppleEmbedded::current_edr_headroom_changed() {
_update_hdr_output();
_update_hdr_output(true);
}

bool DisplayServerAppleEmbedded::window_is_hdr_output_supported(DisplayServerEnums::WindowID p_window) const {
Expand All @@ -861,7 +866,7 @@ _FORCE_INLINE_ int _convert_utf32_offset_to_utf16(const String &p_existing_text,
#endif

edr_requested = p_enabled;
_update_hdr_output();
_update_hdr_output(false);
}

bool DisplayServerAppleEmbedded::window_is_hdr_output_requested(DisplayServerEnums::WindowID p_window) const {
Expand Down
8 changes: 8 additions & 0 deletions platform/linuxbsd/wayland/display_server_wayland.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1496,6 +1496,7 @@ void DisplayServerWayland::_window_update_hdr_state(WindowData &p_window) {

if (rendering_context->window_get_hdr_output_enabled(window_id) != hdr_desired) {
rendering_context->window_set_hdr_output_enabled(window_id, hdr_desired);
_send_window_event(DisplayServerEnums::WINDOW_EVENT_OUTPUT_MAX_LINEAR_VALUE_CHANGED, window_id);
}

if (hdr_desired) {
Expand Down Expand Up @@ -1873,13 +1874,19 @@ void DisplayServerWayland::process_events() {
if (pair.value.visible) {
wayland_thread.window_set_color_profile(pair.key, pair.value.color_profile);
}

rendering_context->window_set_hdr_output_enabled(pair.key, false);
_send_window_event(DisplayServerEnums::WINDOW_EVENT_OUTPUT_MAX_LINEAR_VALUE_CHANGED, pair.key);
} else if (dirty_linear) {
pair.value.color_profile.named_primary = WP_COLOR_MANAGER_V1_PRIMARIES_SRGB;
pair.value.color_profile.named_transfer_function = WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_EXT_LINEAR;

if (pair.value.visible) {
wayland_thread.window_set_color_profile(pair.key, pair.value.color_profile);
}

rendering_context->window_set_hdr_output_enabled(pair.key, true);
_send_window_event(DisplayServerEnums::WINDOW_EVENT_OUTPUT_MAX_LINEAR_VALUE_CHANGED, pair.key);
}
}
}
Expand Down Expand Up @@ -2023,6 +2030,7 @@ void DisplayServerWayland::process_events() {
wd.color_profile = color_profile_msg->color_profile;

_window_update_hdr_state(wd);
_send_window_event(DisplayServerEnums::WINDOW_EVENT_OUTPUT_MAX_LINEAR_VALUE_CHANGED, wd.id);
continue;
}
}
Expand Down
3 changes: 2 additions & 1 deletion platform/macos/display_server_macos.h
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,8 @@ class DisplayServerMacOS : public DisplayServerMacOSBase {
void set_menu_delegate(NSMenu *p_menu);

void send_event(NSEvent *p_event);
void send_window_event(const WindowData &p_wd, DisplayServerEnums::WindowEvent p_event);
void send_window_event(const WindowData &p_wd, DisplayServerEnums::WindowEvent p_event) const;
virtual void send_window_event_by_id(DisplayServerEnums::WindowEvent p_event, DisplayServerEnums::WindowID p_id = DisplayServerEnums::MAIN_WINDOW_ID) const override;
void release_pressed_events();
void sync_mouse_state();
void get_key_modifier_state(unsigned int p_macos_state, Ref<InputEventWithModifiers> r_state) const;
Expand Down
7 changes: 6 additions & 1 deletion platform/macos/display_server_macos.mm
Original file line number Diff line number Diff line change
Expand Up @@ -658,7 +658,7 @@
}
}

void DisplayServerMacOS::send_window_event(const WindowData &wd, DisplayServerEnums::WindowEvent p_event) {
void DisplayServerMacOS::send_window_event(const WindowData &wd, DisplayServerEnums::WindowEvent p_event) const {
_THREAD_SAFE_METHOD_

if (wd.event_callback.is_valid()) {
Expand All @@ -667,6 +667,11 @@
}
}

void DisplayServerMacOS::send_window_event_by_id(DisplayServerEnums::WindowEvent p_event, DisplayServerEnums::WindowID p_id) const {
const WindowData &wd = windows[p_id];
send_window_event(wd, p_event);
}

void DisplayServerMacOS::release_pressed_events() {
_THREAD_SAFE_METHOD_
if (Input::get_singleton()) {
Expand Down
2 changes: 2 additions & 0 deletions platform/macos/display_server_macos_base.h
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,8 @@ class DisplayServerMacOSBase : public DisplayServer {
virtual Color get_base_color() const override;
virtual void set_system_theme_change_callback(const Callable &p_callable) override;

virtual void send_window_event_by_id(DisplayServerEnums::WindowEvent p_event, DisplayServerEnums::WindowID p_id = DisplayServerEnums::MAIN_WINDOW_ID) const = 0;

virtual void mouse_set_mode(DisplayServerEnums::MouseMode p_mode) override;
virtual DisplayServerEnums::MouseMode mouse_get_mode() const override;
virtual void mouse_set_mode_override(DisplayServerEnums::MouseMode p_mode) override;
Expand Down
22 changes: 18 additions & 4 deletions platform/macos/display_server_macos_base.mm
Original file line number Diff line number Diff line change
Expand Up @@ -559,15 +559,29 @@
window_get_edr_values(p_window, &max_potential_edr, &max_edr);
bool desired_hdr_enabled = p_hdr.requested && max_potential_edr > 1.0f;
bool current_hdr_enabled = rendering_context->window_get_hdr_output_enabled(p_window);
bool hdr_state_changed = false;
if (current_hdr_enabled != desired_hdr_enabled) {
rendering_context->window_set_hdr_output_enabled(p_window, desired_hdr_enabled);
hdr_state_changed = true;
}

float reference_luminance = _calculate_current_reference_luminance(max_potential_edr, max_edr);
rendering_context->window_set_hdr_output_reference_luminance(p_window, reference_luminance);
float new_reference_luminance = _calculate_current_reference_luminance(max_potential_edr, max_edr);
float current_ref_luminance = rendering_context->window_get_hdr_output_reference_luminance(p_window);
if (!Math::is_equal_approx(current_ref_luminance, new_reference_luminance)) {
rendering_context->window_set_hdr_output_reference_luminance(p_window, new_reference_luminance);
hdr_state_changed = true;
}

float new_max_luminance = p_hdr.is_auto_max_luminance() ? max_potential_edr * HARDWARE_REFERENCE_LUMINANCE_NITS : p_hdr.max_luminance;
float current_max_luminance = rendering_context->window_get_hdr_output_max_luminance(p_window);
if (!Math::is_equal_approx(current_max_luminance, new_max_luminance)) {
rendering_context->window_set_hdr_output_max_luminance(p_window, new_max_luminance);
hdr_state_changed = true;
}

float max_luminance = p_hdr.is_auto_max_luminance() ? max_potential_edr * HARDWARE_REFERENCE_LUMINANCE_NITS : p_hdr.max_luminance;
rendering_context->window_set_hdr_output_max_luminance(p_window, max_luminance);
if (hdr_state_changed) {
send_window_event_by_id(DisplayServerEnums::WINDOW_EVENT_OUTPUT_MAX_LINEAR_VALUE_CHANGED, p_window);
}
#endif
}

Expand Down
2 changes: 1 addition & 1 deletion platform/macos/display_server_macos_embedded.h
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ class DisplayServerMacOSEmbedded : public DisplayServerMacOSBase {
static void _dispatch_input_events(const Ref<InputEvent> &p_event);
void send_input_event(const Ref<InputEvent> &p_event, DisplayServerEnums::WindowID p_id = DisplayServerEnums::MAIN_WINDOW_ID) const;
void send_input_text(const String &p_text, DisplayServerEnums::WindowID p_id = DisplayServerEnums::MAIN_WINDOW_ID) const;
void send_window_event(DisplayServerEnums::WindowEvent p_event, DisplayServerEnums::WindowID p_id = DisplayServerEnums::MAIN_WINDOW_ID) const;
virtual void send_window_event_by_id(DisplayServerEnums::WindowEvent p_event, DisplayServerEnums::WindowID p_id = DisplayServerEnums::MAIN_WINDOW_ID) const override;
void _window_callback(const Callable &p_callable, const Variant &p_arg) const;

// MARK: - Mouse
Expand Down
2 changes: 1 addition & 1 deletion platform/macos/display_server_macos_embedded.mm
Original file line number Diff line number Diff line change
Expand Up @@ -378,7 +378,7 @@
}
}

void DisplayServerMacOSEmbedded::send_window_event(DisplayServerEnums::WindowEvent p_event, DisplayServerEnums::WindowID p_id) const {
void DisplayServerMacOSEmbedded::send_window_event_by_id(DisplayServerEnums::WindowEvent p_event, DisplayServerEnums::WindowID p_id) const {
const Callable *cb = window_event_callbacks.getptr(p_id);
if (cb) {
_window_callback(*cb, int(p_event));
Expand Down
2 changes: 1 addition & 1 deletion platform/macos/embedded_debugger.mm
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@
Error EmbeddedDebugger::_msg_win_event(const Array &p_args) {
ERR_FAIL_COND_V_MSG(p_args.size() != 1, ERR_INVALID_PARAMETER, "Invalid number of arguments for 'win_event' message.");
DisplayServerEnums::WindowEvent win_event = p_args[0];
ds->send_window_event(win_event, DisplayServerEnums::MAIN_WINDOW_ID);
ds->send_window_event_by_id(win_event, DisplayServerEnums::MAIN_WINDOW_ID);
if (win_event == DisplayServerEnums::WindowEvent::WINDOW_EVENT_MOUSE_EXIT) {
Input::get_singleton()->release_pressed_events();
}
Expand Down
21 changes: 19 additions & 2 deletions platform/windows/display_server_windows.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3422,27 +3422,42 @@ void DisplayServerWindows::_update_hdr_output_for_window(DisplayServerEnums::Win
if (rendering_context) {
bool current_hdr_enabled = rendering_context->window_get_hdr_output_enabled(p_window);
bool desired_hdr_enabled = p_window_data.hdr_output_requested && p_screen_data.hdr_supported;
bool hdr_state_changed = false;

if (current_hdr_enabled != desired_hdr_enabled) {
rendering_context->window_set_hdr_output_enabled(p_window, desired_hdr_enabled);
rendering_context->window_set_hdr_output_linear_luminance_scale(p_window, 80.0f);
hdr_state_changed = true;
}

// If auto reference luminance is enabled, update it based on the current SDR white level.
if (p_window_data.hdr_output_reference_luminance < 0.0f) {
if (p_screen_data.sdr_white_level > 0.0f) {
rendering_context->window_set_hdr_output_reference_luminance(p_window, p_screen_data.sdr_white_level);
float current_ref_luminance = rendering_context->window_get_hdr_output_reference_luminance(p_window);
if (!Math::is_equal_approx(current_ref_luminance, p_screen_data.sdr_white_level)) {
rendering_context->window_set_hdr_output_reference_luminance(p_window, p_screen_data.sdr_white_level);
hdr_state_changed = true;
}
}
// If we cannot get the SDR white level, leave the previous value unchanged.
}

// If auto max luminance is enabled, update it based on the screen's max luminance.
if (p_window_data.hdr_output_max_luminance < 0.0f) {
if (p_screen_data.max_luminance > 0.0f) {
rendering_context->window_set_hdr_output_max_luminance(p_window, p_screen_data.max_luminance);
float current_max_luminance = rendering_context->window_get_hdr_output_max_luminance(p_window);
if (!Math::is_equal_approx(current_max_luminance, p_screen_data.max_luminance)) {
rendering_context->window_set_hdr_output_max_luminance(p_window, p_screen_data.max_luminance);
hdr_state_changed = true;
}
}
// If we cannot get the screen's max luminance, leave the previous value unchanged.
}

// Trigger HDR output changed event if any HDR parameter was modified.
if (hdr_state_changed) {
_send_window_event(p_window_data, DisplayServerEnums::WINDOW_EVENT_OUTPUT_MAX_LINEAR_VALUE_CHANGED);
}
}
#endif // RD_ENABLED
}
Expand Down Expand Up @@ -4684,6 +4699,7 @@ void DisplayServerWindows::window_set_hdr_output_reference_luminance(const float
#if defined(RD_ENABLED)
if (rendering_context) {
rendering_context->window_set_hdr_output_reference_luminance(p_window, p_reference_luminance);
_send_window_event(wd, DisplayServerEnums::WINDOW_EVENT_OUTPUT_MAX_LINEAR_VALUE_CHANGED);
}
#endif
}
Expand Down Expand Up @@ -4729,6 +4745,7 @@ void DisplayServerWindows::window_set_hdr_output_max_luminance(const float p_max
#if defined(RD_ENABLED)
if (rendering_context) {
rendering_context->window_set_hdr_output_max_luminance(p_window, p_max_luminance);
_send_window_event(wd, DisplayServerEnums::WINDOW_EVENT_OUTPUT_MAX_LINEAR_VALUE_CHANGED);
}
#endif
}
Expand Down
1 change: 1 addition & 0 deletions scene/main/node.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3966,6 +3966,7 @@ void Node::_bind_methods() {
BIND_CONSTANT(NOTIFICATION_VP_MOUSE_ENTER);
BIND_CONSTANT(NOTIFICATION_VP_MOUSE_EXIT);
BIND_CONSTANT(NOTIFICATION_WM_POSITION_CHANGED);
BIND_CONSTANT(NOTIFICATION_WM_OUTPUT_MAX_LINEAR_VALUE_CHANGED);
BIND_CONSTANT(NOTIFICATION_OS_MEMORY_WARNING);
BIND_CONSTANT(NOTIFICATION_TRANSLATION_CHANGED);
BIND_CONSTANT(NOTIFICATION_WM_ABOUT);
Expand Down
1 change: 1 addition & 0 deletions scene/main/node.h
Original file line number Diff line number Diff line change
Expand Up @@ -487,6 +487,7 @@ class Node : public Object {
NOTIFICATION_VP_MOUSE_ENTER = 1010,
NOTIFICATION_VP_MOUSE_EXIT = 1011,
NOTIFICATION_WM_POSITION_CHANGED = 1012,
NOTIFICATION_WM_OUTPUT_MAX_LINEAR_VALUE_CHANGED = 1013,

// Keep these in sync with MainLoop.
NOTIFICATION_OS_MEMORY_WARNING = 2009,
Expand Down
5 changes: 5 additions & 0 deletions scene/main/window.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -925,6 +925,10 @@ void Window::_event_callback(DisplayServerEnums::WindowEvent p_event) {
case DisplayServerEnums::WINDOW_EVENT_FORCE_CLOSE: {
hide();
} break;
case DisplayServerEnums::WINDOW_EVENT_OUTPUT_MAX_LINEAR_VALUE_CHANGED: {
_propagate_window_notification(this, NOTIFICATION_WM_OUTPUT_MAX_LINEAR_VALUE_CHANGED);
emit_signal(SNAME("output_max_linear_value_changed"), get_output_max_linear_value());
} break;
}
}

Expand Down Expand Up @@ -3589,6 +3593,7 @@ void Window::_bind_methods() {
ADD_SIGNAL(MethodInfo("dpi_changed"));
ADD_SIGNAL(MethodInfo("titlebar_changed"));
ADD_SIGNAL(MethodInfo("title_changed"));
ADD_SIGNAL(MethodInfo("output_max_linear_value_changed", PropertyInfo(Variant::FLOAT, "output_max_linear_value")));

BIND_CONSTANT(NOTIFICATION_VISIBILITY_CHANGED);
BIND_CONSTANT(NOTIFICATION_THEME_CHANGED);
Expand Down
1 change: 1 addition & 0 deletions servers/display/display_server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1966,6 +1966,7 @@ void DisplayServer::_bind_methods() {
BIND_ENUM_CONSTANT(DisplayServerEnums::WINDOW_EVENT_DPI_CHANGE);
BIND_ENUM_CONSTANT(DisplayServerEnums::WINDOW_EVENT_TITLEBAR_CHANGE);
BIND_ENUM_CONSTANT(DisplayServerEnums::WINDOW_EVENT_FORCE_CLOSE);
BIND_ENUM_CONSTANT(DisplayServerEnums::WINDOW_EVENT_OUTPUT_MAX_LINEAR_VALUE_CHANGED);

BIND_ENUM_CONSTANT(DisplayServerEnums::WINDOW_EDGE_TOP_LEFT);
BIND_ENUM_CONSTANT(DisplayServerEnums::WINDOW_EDGE_TOP);
Expand Down
1 change: 1 addition & 0 deletions servers/display/display_server_enums.h
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,7 @@ enum WindowEvent {
WINDOW_EVENT_DPI_CHANGE,
WINDOW_EVENT_TITLEBAR_CHANGE,
WINDOW_EVENT_FORCE_CLOSE,
WINDOW_EVENT_OUTPUT_MAX_LINEAR_VALUE_CHANGED,
};

enum WindowResizeEdge {
Expand Down
Loading