Skip to content

Commit

Permalink
Support output to HDR monitors
Browse files Browse the repository at this point in the history
  • Loading branch information
DarkKilauea committed Sep 16, 2024
1 parent 6681f25 commit aa929d4
Show file tree
Hide file tree
Showing 34 changed files with 489 additions and 72 deletions.
2 changes: 2 additions & 0 deletions core/config/project_settings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1467,6 +1467,8 @@ ProjectSettings::ProjectSettings() {
GLOBAL_DEF("display/window/size/transparent", false);
GLOBAL_DEF("display/window/size/extend_to_title", false);
GLOBAL_DEF("display/window/size/no_focus", false);
GLOBAL_DEF("display/window/hdr/enabled", false);
GLOBAL_DEF(PropertyInfo(Variant::FLOAT, "display/window/hdr/max_luminance", PROPERTY_HINT_RANGE, "0,1500,1,or_greater"), 1000.0f);

GLOBAL_DEF(PropertyInfo(Variant::INT, "display/window/size/window_width_override", PROPERTY_HINT_RANGE, "0,7680,1,or_greater"), 0); // 8K resolution
GLOBAL_DEF(PropertyInfo(Variant::INT, "display/window/size/window_height_override", PROPERTY_HINT_RANGE, "0,4320,1,or_greater"), 0); // 8K resolution
Expand Down
35 changes: 35 additions & 0 deletions doc/classes/DisplayServer.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1448,6 +1448,20 @@
Returns the current value of the given window's [param flag].
</description>
</method>
<method name="window_get_hdr_output_enabled" qualifiers="const">
<return type="bool" />
<param index="0" name="window_id" type="int" default="0" />
<description>
Returns whether HDR output is requested for the given window.
</description>
</method>
<method name="window_get_hdr_output_max_luminance" qualifiers="const">
<return type="float" />
<param index="0" name="window_id" type="int" default="0" />
<description>
Returns the maximum luminance in nits (cd/m²) set for HDR output for the given window.
</description>
</method>
<method name="window_get_max_size" qualifiers="const">
<return type="Vector2i" />
<param index="0" name="window_id" type="int" default="0" />
Expand Down Expand Up @@ -1615,6 +1629,24 @@
Enables or disables the given window's given [param flag]. See [enum WindowFlags] for possible values and their behavior.
</description>
</method>
<method name="window_set_hdr_output_enabled">
<return type="void" />
<param index="0" name="enabled" type="bool" />
<param index="1" name="window_id" type="int" default="0" />
<description>
Sets whether HDR output should be enabled for the window specified by [param window_id].
Only available on platforms that support HDR output, have HDR enabled in the system settings, and have a compatible display connected.
</description>
</method>
<method name="window_set_hdr_output_max_luminance">
<return type="void" />
<param index="0" name="max_luminance" type="float" />
<param index="1" name="window_id" type="int" default="0" />
<description>
Sets the maximum luminance of the display in nits (cd/m²) when HDR is enabled.
This is used to scale the HDR effect to avoid clipping.
</description>
</method>
<method name="window_set_ime_active">
<return type="void" />
<param index="0" name="active" type="bool" />
Expand Down Expand Up @@ -1883,6 +1915,9 @@
<constant name="FEATURE_NATIVE_DIALOG_FILE" value="25" enum="Feature">
Display server supports spawning dialogs for selecting files or directories using the operating system's native look-and-feel. See [method file_dialog_show] and [method file_dialog_with_options_show]. [b]Windows, macOS, Linux (X11/Wayland)[/b]
</constant>
<constant name="FEATURE_HDR" value="26" enum="Feature">
Display server supports HDR output. [b]Windows[/b]
</constant>
<constant name="MOUSE_MODE_VISIBLE" value="0" enum="MouseMode">
Makes the mouse cursor visible if it is hidden.
</constant>
Expand Down
8 changes: 8 additions & 0 deletions doc/classes/ProjectSettings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -820,6 +820,14 @@
The default screen orientation to use on mobile devices. See [enum DisplayServer.ScreenOrientation] for possible values.
[b]Note:[/b] When set to a portrait orientation, this project setting does not flip the project resolution's width and height automatically. Instead, you have to set [member display/window/size/viewport_width] and [member display/window/size/viewport_height] accordingly.
</member>
<member name="display/window/hdr/enabled" type="bool" setter="" getter="" default="false">
If [code]true[/code], enables HDR output on supported platforms, falling back to SDR if not supported.
Only available on platforms that support HDR output, have HDR enabled in the system settings, and have a compatible display connected.
</member>
<member name="display/window/hdr/max_luminance" type="float" setter="" getter="" default="1000.0">
Sets the maximum luminance of the display in nits (cd/m²) when HDR is enabled.
This is used to scale the HDR effect to avoid clipping.
</member>
<member name="display/window/ios/allow_high_refresh_rate" type="bool" setter="" getter="" default="true">
If [code]true[/code], iOS devices that support high refresh rate/"ProMotion" will be allowed to render at up to 120 frames per second.
</member>
Expand Down
20 changes: 20 additions & 0 deletions drivers/d3d12/rendering_context_driver_d3d12.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,26 @@ DisplayServer::VSyncMode RenderingContextDriverD3D12::surface_get_vsync_mode(Sur
return surface->vsync_mode;
}

void RenderingContextDriverD3D12::surface_set_hdr_output_enabled(SurfaceID p_surface, bool p_enabled) {
Surface *surface = (Surface *)(p_surface);
surface->hdr_output = p_enabled;
}

bool RenderingContextDriverD3D12::surface_get_hdr_output_enabled(SurfaceID p_surface) const {
Surface *surface = (Surface *)(p_surface);
return surface->hdr_output;
}

void RenderingContextDriverD3D12::surface_set_hdr_output_max_luminance(SurfaceID p_surface, float p_max_luminance) {
Surface *surface = (Surface *)(p_surface);
surface->hdr_max_luminance = p_max_luminance;
}

float RenderingContextDriverD3D12::surface_get_hdr_output_max_luminance(SurfaceID p_surface) const {
Surface *surface = (Surface *)(p_surface);
return surface->hdr_max_luminance;
}

uint32_t RenderingContextDriverD3D12::surface_get_width(SurfaceID p_surface) const {
Surface *surface = (Surface *)(p_surface);
return surface->width;
Expand Down
6 changes: 6 additions & 0 deletions drivers/d3d12/rendering_context_driver_d3d12.h
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,10 @@ class RenderingContextDriverD3D12 : public RenderingContextDriver {
virtual void surface_set_size(SurfaceID p_surface, uint32_t p_width, uint32_t p_height) override;
virtual void surface_set_vsync_mode(SurfaceID p_surface, DisplayServer::VSyncMode p_vsync_mode) override;
virtual DisplayServer::VSyncMode surface_get_vsync_mode(SurfaceID p_surface) const override;
virtual void surface_set_hdr_output_enabled(SurfaceID p_surface, bool p_enabled) override;
virtual bool surface_get_hdr_output_enabled(SurfaceID p_surface) const override;
virtual void surface_set_hdr_output_max_luminance(SurfaceID p_surface, float p_max_luminance) override;
virtual float surface_get_hdr_output_max_luminance(SurfaceID p_surface) const override;
virtual uint32_t surface_get_width(SurfaceID p_surface) const override;
virtual uint32_t surface_get_height(SurfaceID p_surface) const override;
virtual void surface_set_needs_resize(SurfaceID p_surface, bool p_needs_resize) override;
Expand All @@ -113,6 +117,8 @@ class RenderingContextDriverD3D12 : public RenderingContextDriver {
uint32_t width = 0;
uint32_t height = 0;
DisplayServer::VSyncMode vsync_mode = DisplayServer::VSYNC_ENABLED;
bool hdr_output = false;
float hdr_max_luminance = 0.0f;
bool needs_resize = false;
};

Expand Down
4 changes: 4 additions & 0 deletions drivers/d3d12/rendering_device_driver_d3d12.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2642,6 +2642,10 @@ RDD::DataFormat RenderingDeviceDriverD3D12::swap_chain_get_format(SwapChainID p_
return swap_chain->data_format;
}

RDD::ColorSpace RenderingDeviceDriverD3D12::swap_chain_get_color_space(SwapChainID p_swap_chain) {
return RDD::COLOR_SPACE_SRGB_NONLINEAR;
}

void RenderingDeviceDriverD3D12::swap_chain_free(SwapChainID p_swap_chain) {
SwapChain *swap_chain = (SwapChain *)(p_swap_chain.id);
_swap_chain_release(swap_chain);
Expand Down
1 change: 1 addition & 0 deletions drivers/d3d12/rendering_device_driver_d3d12.h
Original file line number Diff line number Diff line change
Expand Up @@ -528,6 +528,7 @@ class RenderingDeviceDriverD3D12 : public RenderingDeviceDriver {
virtual FramebufferID swap_chain_acquire_framebuffer(CommandQueueID p_cmd_queue, SwapChainID p_swap_chain, bool &r_resize_required) override;
virtual RenderPassID swap_chain_get_render_pass(SwapChainID p_swap_chain) override;
virtual DataFormat swap_chain_get_format(SwapChainID p_swap_chain) override;
virtual ColorSpace swap_chain_get_color_space(SwapChainID p_swap_chain) override;
virtual void swap_chain_free(SwapChainID p_swap_chain) override;

/*********************/
Expand Down
6 changes: 6 additions & 0 deletions drivers/metal/rendering_context_driver_metal.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,10 @@ class API_AVAILABLE(macos(11.0), ios(14.0)) RenderingContextDriverMetal : public
void surface_set_size(SurfaceID p_surface, uint32_t p_width, uint32_t p_height) final override;
void surface_set_vsync_mode(SurfaceID p_surface, DisplayServer::VSyncMode p_vsync_mode) final override;
DisplayServer::VSyncMode surface_get_vsync_mode(SurfaceID p_surface) const final override;
virtual void surface_set_hdr_output_enabled(SurfaceID p_surface, bool p_enabled) final override;
virtual bool surface_get_hdr_output_enabled(SurfaceID p_surface) const final override;
virtual void surface_set_hdr_output_max_luminance(SurfaceID p_surface, float p_max_luminance) final override;
virtual float surface_get_hdr_output_max_luminance(SurfaceID p_surface) const final override;
uint32_t surface_get_width(SurfaceID p_surface) const final override;
uint32_t surface_get_height(SurfaceID p_surface) const final override;
void surface_set_needs_resize(SurfaceID p_surface, bool p_needs_resize) final override;
Expand Down Expand Up @@ -106,6 +110,8 @@ class API_AVAILABLE(macos(11.0), ios(14.0)) RenderingContextDriverMetal : public
uint32_t width = 0;
uint32_t height = 0;
DisplayServer::VSyncMode vsync_mode = DisplayServer::VSYNC_ENABLED;
bool hdr_output = false;
float hdr_max_luminance = 0.0f;
bool needs_resize = false;

Surface(
Expand Down
20 changes: 20 additions & 0 deletions drivers/metal/rendering_context_driver_metal.mm
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,26 @@ void present(MDCommandBuffer *p_cmd_buffer) override final {
return surface->vsync_mode;
}

void RenderingContextDriverMetal::surface_set_hdr_output_enabled(SurfaceID p_surface, bool p_enabled) {
Surface *surface = (Surface *)(p_surface);
surface->hdr_output = p_enabled;
}

bool RenderingContextDriverMetal::surface_get_hdr_output_enabled(SurfaceID p_surface) const {
Surface *surface = (Surface *)(p_surface);
return surface->hdr_output;
}

void RenderingContextDriverMetal::surface_set_hdr_output_max_luminance(SurfaceID p_surface, float p_max_luminance) {
Surface *surface = (Surface *)(p_surface);
surface->hdr_max_luminance = p_max_luminance;
}

float RenderingContextDriverMetal::surface_get_hdr_output_max_luminance(SurfaceID p_surface) const {
Surface *surface = (Surface *)(p_surface);
return surface->hdr_max_luminance;
}

uint32_t RenderingContextDriverMetal::surface_get_width(SurfaceID p_surface) const {
Surface *surface = (Surface *)(p_surface);
return surface->width;
Expand Down
1 change: 1 addition & 0 deletions drivers/metal/rendering_device_driver_metal.h
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,7 @@ class API_AVAILABLE(macos(11.0), ios(14.0)) RenderingDeviceDriverMetal : public
virtual FramebufferID swap_chain_acquire_framebuffer(CommandQueueID p_cmd_queue, SwapChainID p_swap_chain, bool &r_resize_required) override final;
virtual RenderPassID swap_chain_get_render_pass(SwapChainID p_swap_chain) override final;
virtual DataFormat swap_chain_get_format(SwapChainID p_swap_chain) override final;
virtual ColorSpace swap_chain_get_color_space(SwapChainID p_swap_chain) override final;
virtual void swap_chain_free(SwapChainID p_swap_chain) override final;

#pragma mark - Frame Buffer
Expand Down
4 changes: 4 additions & 0 deletions drivers/metal/rendering_device_driver_metal.mm
Original file line number Diff line number Diff line change
Expand Up @@ -978,6 +978,10 @@ static const API_AVAILABLE(macos(11.0), ios(14.0)) MTLSamplerBorderColor SAMPLER
return swap_chain->data_format;
}

RDD::ColorSpace RenderingDeviceDriverMetal::swap_chain_get_color_space(SwapChainID p_swap_chain) {
return RDD::COLOR_SPACE_SRGB_NONLINEAR;
}

void RenderingDeviceDriverMetal::swap_chain_free(SwapChainID p_swap_chain) {
SwapChain *swap_chain = (SwapChain *)(p_swap_chain.id);
_swap_chain_release(swap_chain);
Expand Down
21 changes: 21 additions & 0 deletions drivers/vulkan/rendering_context_driver_vulkan.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -991,6 +991,27 @@ DisplayServer::VSyncMode RenderingContextDriverVulkan::surface_get_vsync_mode(Su
return surface->vsync_mode;
}

void RenderingContextDriverVulkan::surface_set_hdr_output_enabled(SurfaceID p_surface, bool p_enabled) {
Surface *surface = (Surface *)(p_surface);
surface->hdr_output = p_enabled;
surface->needs_resize = true;
}

bool RenderingContextDriverVulkan::surface_get_hdr_output_enabled(SurfaceID p_surface) const {
Surface *surface = (Surface *)(p_surface);
return surface->hdr_output;
}

void RenderingContextDriverVulkan::surface_set_hdr_output_max_luminance(SurfaceID p_surface, float p_max_luminance) {
Surface *surface = (Surface *)(p_surface);
surface->hdr_max_luminance = p_max_luminance;
}

float RenderingContextDriverVulkan::surface_get_hdr_output_max_luminance(SurfaceID p_surface) const {
Surface *surface = (Surface *)(p_surface);
return surface->hdr_max_luminance;
}

uint32_t RenderingContextDriverVulkan::surface_get_width(SurfaceID p_surface) const {
Surface *surface = (Surface *)(p_surface);
return surface->width;
Expand Down
6 changes: 6 additions & 0 deletions drivers/vulkan/rendering_context_driver_vulkan.h
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,10 @@ class RenderingContextDriverVulkan : public RenderingContextDriver {
virtual void surface_set_size(SurfaceID p_surface, uint32_t p_width, uint32_t p_height) override;
virtual void surface_set_vsync_mode(SurfaceID p_surface, DisplayServer::VSyncMode p_vsync_mode) override;
virtual DisplayServer::VSyncMode surface_get_vsync_mode(SurfaceID p_surface) const override;
virtual void surface_set_hdr_output_enabled(SurfaceID p_surface, bool p_enabled) override;
virtual bool surface_get_hdr_output_enabled(SurfaceID p_surface) const override;
virtual void surface_set_hdr_output_max_luminance(SurfaceID p_surface, float p_max_luminance) override;
virtual float surface_get_hdr_output_max_luminance(SurfaceID p_surface) const override;
virtual uint32_t surface_get_width(SurfaceID p_surface) const override;
virtual uint32_t surface_get_height(SurfaceID p_surface) const override;
virtual void surface_set_needs_resize(SurfaceID p_surface, bool p_needs_resize) override;
Expand All @@ -156,6 +160,8 @@ class RenderingContextDriverVulkan : public RenderingContextDriver {
uint32_t width = 0;
uint32_t height = 0;
DisplayServer::VSyncMode vsync_mode = DisplayServer::VSYNC_ENABLED;
bool hdr_output = false;
float hdr_max_luminance = 0.0f;
bool needs_resize = false;
};

Expand Down
Loading

0 comments on commit aa929d4

Please sign in to comment.