Skip to content

[Windows] HDR Output: Emit window events when HDR state changes#115666

Merged
Repiteo merged 1 commit into
godotengine:masterfrom
DarkKilauea:rendering/hdr-output-changed
Apr 3, 2026
Merged

[Windows] HDR Output: Emit window events when HDR state changes#115666
Repiteo merged 1 commit into
godotengine:masterfrom
DarkKilauea:rendering/hdr-output-changed

Conversation

@DarkKilauea
Copy link
Copy Markdown
Contributor

Depends on: #94496

This adds a small enhancement to the HDR output feature for windows that triggers a WindowEvent whenever the HDR output state changes.

I noticed when working on my own projects and in sample applications that @allenwp and I put together, that polling was required to respond to external changes to the HDR state. This enhancement tries to address that by allowing UI, game effects, and other nodes to respond to the HDR state actually changing.

Please see the last commit for the changes added by this PR.

@DarkKilauea DarkKilauea requested review from a team as code owners January 31, 2026 07:46
@DarkKilauea DarkKilauea requested a review from a team January 31, 2026 07:46
@DarkKilauea DarkKilauea requested a review from a team as a code owner January 31, 2026 07:46
@DarkKilauea DarkKilauea requested a review from a team January 31, 2026 07:46
@DarkKilauea DarkKilauea requested a review from a team as a code owner January 31, 2026 07:46
@DarkKilauea DarkKilauea force-pushed the rendering/hdr-output-changed branch from 7249096 to 7eb742d Compare January 31, 2026 17:12
@DarkKilauea
Copy link
Copy Markdown
Contributor Author

Whoops, forgot to update the documentation. That's fixed now.

@ArchercatNEO
Copy link
Copy Markdown
Contributor

Since emitting an event is also possible on Wayland (in fact, the Wayland API only provides event-based queries) should this also be implemented for Wayland?

I could rebase on top of this PR but that feels very indirect, I could also wait until both the original and this PR are merged then rebase onto the then-master but that depends on how closely each merge is done.

@DarkKilauea
Copy link
Copy Markdown
Contributor Author

@ArchercatNEO You could also create another PR that implements just the WindowEvent emission and have that depend on both your HDR PR and this one.

It is my hope that once we get the first HDR PR merged, the others will be able to follow shortly after.

@DarkKilauea DarkKilauea force-pushed the rendering/hdr-output-changed branch from 7eb742d to e3a2012 Compare February 2, 2026 01:01
@AThousandShips AThousandShips added this to the 4.x milestone Feb 2, 2026
@DarkKilauea DarkKilauea force-pushed the rendering/hdr-output-changed branch 3 times, most recently from f55ed62 to 1034197 Compare February 10, 2026 04:37
@DarkKilauea DarkKilauea requested review from a team as code owners February 10, 2026 04:37
@DarkKilauea DarkKilauea force-pushed the rendering/hdr-output-changed branch 3 times, most recently from 1afcaa4 to a3bce0d Compare February 12, 2026 17:13
@DarkKilauea DarkKilauea requested review from a team as code owners February 19, 2026 04:39
@Nintorch Nintorch removed request for a team February 19, 2026 04:51
@DarkKilauea DarkKilauea force-pushed the rendering/hdr-output-changed branch 2 times, most recently from f50547e to 398add5 Compare February 25, 2026 06:18
@DarkKilauea DarkKilauea force-pushed the rendering/hdr-output-changed branch from 398add5 to 88c1777 Compare March 2, 2026 06:42
@DarkKilauea
Copy link
Copy Markdown
Contributor Author

@bruvzg Are you the correct person to review this?

@bruvzg bruvzg requested a review from a team March 2, 2026 06:54
Copy link
Copy Markdown
Member

@bruvzg bruvzg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code looks good. No idea if there's a necessity for having the signal/notification.

@DarkKilauea DarkKilauea force-pushed the rendering/hdr-output-changed branch from 88c1777 to ba2f6d5 Compare March 8, 2026 22:55
@DarkKilauea
Copy link
Copy Markdown
Contributor Author

Rebased to resolve conflicts with DisplayServerEnum refactor.

Copy link
Copy Markdown
Contributor

@allenwp allenwp left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is really great!! Thanks! I believe this would be extremely valuable to developers and it would be great to have this for 4.7.

I haven't tested this as thoroughly as I normally would, but this seems like something that's pretty simple and will be easy to bug fix if there are any edge cases that are discovered after merging.

I've left a couple of comments about the documentation and signal/constant naming.

No idea if there's a necessity for having the signal/notification.

@bruvzg Currently the developer must poll this value every frame, even though it may never change (if the player is using an SDR screen or an HDR screen that has a stable brightness setting). An example of the current approach is shown in the documentation here: https://docs.godotengine.org/en/latest/tutorials/rendering/hdr_output.html#using-output-max-linear-value

So I think the signal is valuable in addition to the other events?? You might want to hook a shader uniform up to this value... does a signal help with this? I really am not the one to make the call on this, so if someone else wants to jump in who is more well versed in what justifies a signal and what doesn't, please do so.

Comment thread scene/main/window.cpp Outdated
Comment thread doc/classes/Window.xml Outdated
Comment thread doc/classes/Window.xml Outdated
@DarkKilauea DarkKilauea force-pushed the rendering/hdr-output-changed branch from ba2f6d5 to 0a3cc29 Compare March 16, 2026 02:53
@allenwp
Copy link
Copy Markdown
Contributor

allenwp commented Mar 18, 2026

Current usage of this signal looks something like this in most any use case I can think of:

func _ready() -> void:
	get_window().hdr_output_changed.connect(_on_hdr_output_changed)
	_on_hdr_output_changed()


func _on_hdr_output_changed() -> void:
	var output_max_linear_value = get_window().get_output_max_linear_value()
	...

It might be nice to have the output_max_linear_value passed as an argument of the signal? This way the user doesn't need to retrieve it from the Window every time the signal is sent. Combined with a signal name change to output_max_linear_value_changed, this probably makes it more intuitive.

func _ready() -> void:
	var window: Window = get_window()
	window.output_max_linear_value_changed.connect(_on_output_max_linear_value_changed)
	_on_output_max_linear_value_changed(window.get_output_max_linear_value())


func _on_output_max_linear_value_changed(output_max_linear_value: float) -> void:
	...

@DarkKilauea DarkKilauea force-pushed the rendering/hdr-output-changed branch from 0a3cc29 to 3060254 Compare March 21, 2026 21:18
@DarkKilauea
Copy link
Copy Markdown
Contributor Author

It might be nice to have the output_max_linear_value passed as an argument of the signal? This way the user doesn't need to retrieve it from the Window every time the signal is sent. Combined with a signal name change to output_max_linear_value_changed, this probably makes it more intuitive.

func _ready() -> void:
	var window: Window = get_window()
	window.output_max_linear_value_changed.connect(_on_output_max_linear_value_changed)
	_on_output_max_linear_value_changed(window.get_output_max_linear_value())


func _on_output_max_linear_value_changed(output_max_linear_value: float) -> void:
	...

Done! The signal will now emit the current value of Window.output_max_linear_value.

@allenwp
Copy link
Copy Markdown
Contributor

allenwp commented Mar 24, 2026

This is looking great to me! Scripts that used to be:

func _process(_delta: float) -> void:
	var output_max_linear_value = get_window().get_output_max_linear_value()
	# Do something with output_max_linear_value

Can now be written as:

func _enter_tree() -> void:
	var window: Window = get_window()
	window.output_max_linear_value_changed.connect(_on_output_max_linear_value_changed)
	_on_output_max_linear_value_changed(window.get_output_max_linear_value())


func _exit_tree() -> void:
	get_window().output_max_linear_value_changed.disconnect(_on_output_max_linear_value_changed)


func _on_output_max_linear_value_changed(output_max_linear_value: float) -> void:
	# Do something with output_max_linear_value

This seems like a good improvement to me.

I'm adding this to the agenda for tomorrow's Core meeting so we can make sure the public API is appropriate before porting this to the other platforms.

Copy link
Copy Markdown
Contributor

@allenwp allenwp left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks great to me!

I'm approving now, but this shouldn't be merged until we have this feature ready to merge for other platforms that support HDR output.

@allenwp
Copy link
Copy Markdown
Contributor

allenwp commented Apr 1, 2026

I created a followup PR to this one that adds the events for Apple and Wayland: #118076

@Repiteo
Copy link
Copy Markdown
Contributor

Repiteo commented Apr 3, 2026

Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants