diff --git a/doc/classes/DisplayServer.xml b/doc/classes/DisplayServer.xml index 2d5754680429..1959df5e2246 100644 --- a/doc/classes/DisplayServer.xml +++ b/doc/classes/DisplayServer.xml @@ -3375,6 +3375,11 @@ 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). + + 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. + [b]Note:[/b] This flag is implemented on Windows and Linux (Wayland). + Top-left edge of a window. diff --git a/doc/classes/Node.xml b/doc/classes/Node.xml index 532859a28f0a..c7997bba55e6 100644 --- a/doc/classes/Node.xml +++ b/doc/classes/Node.xml @@ -1276,6 +1276,10 @@ Notification received when the window is moved. + + 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. + Notification received from the OS when the application is exceeding its allocated memory. Implemented only on iOS. diff --git a/doc/classes/Window.xml b/doc/classes/Window.xml index 19f8050c3153..543a8c04019e 100644 --- a/doc/classes/Window.xml +++ b/doc/classes/Window.xml @@ -123,8 +123,8 @@ - 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): @@ -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. + + + + 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. + + Emitted when the [constant NOTIFICATION_THEME_CHANGED] notification is sent. diff --git a/platform/linuxbsd/wayland/display_server_wayland.cpp b/platform/linuxbsd/wayland/display_server_wayland.cpp index 4208922392f6..e33b1f0273b2 100644 --- a/platform/linuxbsd/wayland/display_server_wayland.cpp +++ b/platform/linuxbsd/wayland/display_server_wayland.cpp @@ -2023,6 +2023,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; } } diff --git a/platform/windows/display_server_windows.cpp b/platform/windows/display_server_windows.cpp index a71beacc6aec..534b398a23e1 100644 --- a/platform/windows/display_server_windows.cpp +++ b/platform/windows/display_server_windows.cpp @@ -3422,16 +3422,22 @@ 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. } @@ -3439,10 +3445,19 @@ void DisplayServerWindows::_update_hdr_output_for_window(DisplayServerEnums::Win // 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 } @@ -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 } @@ -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 } diff --git a/scene/main/node.cpp b/scene/main/node.cpp index daf4299533ae..cd1d9b72a6d3 100644 --- a/scene/main/node.cpp +++ b/scene/main/node.cpp @@ -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); diff --git a/scene/main/node.h b/scene/main/node.h index 111ead3fa611..993780421a87 100644 --- a/scene/main/node.h +++ b/scene/main/node.h @@ -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, diff --git a/scene/main/window.cpp b/scene/main/window.cpp index e08204d9ac67..56d9326eb7d1 100644 --- a/scene/main/window.cpp +++ b/scene/main/window.cpp @@ -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; } } @@ -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); diff --git a/servers/display/display_server.cpp b/servers/display/display_server.cpp index cac5c9d2b355..aed97a9ee238 100644 --- a/servers/display/display_server.cpp +++ b/servers/display/display_server.cpp @@ -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); diff --git a/servers/display/display_server_enums.h b/servers/display/display_server_enums.h index 57e68ee759e0..5c8b7e997ce5 100644 --- a/servers/display/display_server_enums.h +++ b/servers/display/display_server_enums.h @@ -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 {