mirror of https://github.com/godotengine/godot
Compare commits
19 Commits
58b008d5cb
...
bed8d6aa20
| Author | SHA1 | Date |
|---|---|---|
|
|
bed8d6aa20 | |
|
|
15ff450680 | |
|
|
7fb37a088b | |
|
|
33a15a12b1 | |
|
|
c01b9de703 | |
|
|
33a235beb8 | |
|
|
a9c5c4db71 | |
|
|
1af42620fa | |
|
|
672fe2487f | |
|
|
f9c7d348c3 | |
|
|
53faed5351 | |
|
|
dd43d401ec | |
|
|
9014202366 | |
|
|
bb88938596 | |
|
|
ddd807ff7d | |
|
|
0c384e7217 | |
|
|
fd622afb1d | |
|
|
5312811c4d | |
|
|
5ca3862636 |
|
|
@ -1439,7 +1439,7 @@ void ProjectSettings::_add_builtin_input_map() {
|
|||
}
|
||||
|
||||
Dictionary action;
|
||||
action["deadzone"] = Variant(InputMap::DEFAULT_DEADZONE);
|
||||
action["deadzone"] = Variant(InputMap::DEFAULT_TOGGLE_DEADZONE);
|
||||
action["events"] = events;
|
||||
|
||||
String action_name = "input/" + E.key;
|
||||
|
|
@ -1510,6 +1510,13 @@ ProjectSettings::ProjectSettings() {
|
|||
GLOBAL_DEF("display/window/size/no_focus", false);
|
||||
GLOBAL_DEF("display/window/size/sharp_corners", false);
|
||||
|
||||
GLOBAL_DEF("display/window/hdr/enabled", false);
|
||||
GLOBAL_DEF("display/window/hdr/prefer_high_precision", false);
|
||||
GLOBAL_DEF("display/window/hdr/use_screen_luminance", true);
|
||||
GLOBAL_DEF(PropertyInfo(Variant::FLOAT, "display/window/hdr/reference_luminance", PROPERTY_HINT_RANGE, "0,2000,1,or_greater"), 80.0f); // sRGB standard of 80 nits
|
||||
GLOBAL_DEF(PropertyInfo(Variant::FLOAT, "display/window/hdr/min_luminance", PROPERTY_HINT_RANGE, "0,2000,1,or_greater"), 0.0f);
|
||||
GLOBAL_DEF(PropertyInfo(Variant::FLOAT, "display/window/hdr/max_luminance", PROPERTY_HINT_RANGE, "0,2000,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
|
||||
|
||||
|
|
|
|||
|
|
@ -1104,7 +1104,7 @@ JoyAxis InputEventJoypadMotion::get_axis() const {
|
|||
|
||||
void InputEventJoypadMotion::set_axis_value(float p_value) {
|
||||
axis_value = p_value;
|
||||
pressed = Math::abs(axis_value) >= InputMap::DEFAULT_DEADZONE;
|
||||
pressed = Math::abs(axis_value) >= InputMap::DEFAULT_TOGGLE_DEADZONE;
|
||||
emit_changed();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -55,6 +55,8 @@ public:
|
|||
};
|
||||
|
||||
static constexpr float DEFAULT_DEADZONE = 0.2f;
|
||||
// Keep bigger deadzone for toggle actions (default `ui_*` actions, axis `pressed`) (GH-103360).
|
||||
static constexpr float DEFAULT_TOGGLE_DEADZONE = 0.5f;
|
||||
|
||||
private:
|
||||
static InputMap *singleton;
|
||||
|
|
|
|||
|
|
@ -657,22 +657,28 @@ static _FORCE_INLINE_ void vc_ptrcall(void (*method)(T *, P...), void *p_base, c
|
|||
} \
|
||||
};
|
||||
|
||||
#define VARCALL_PACKED_GETTER(m_packed_type, m_return_type) \
|
||||
static m_return_type func_##m_packed_type##_get(m_packed_type *p_instance, int64_t p_index) { \
|
||||
return p_instance->get(p_index); \
|
||||
#define VARCALL_ARRAY_GETTER_SETTER(m_packed_type, m_type) \
|
||||
static m_type func_##m_packed_type##_get(m_packed_type *p_instance, int64_t p_index) { \
|
||||
ERR_FAIL_INDEX_V(p_index, p_instance->size(), m_type()); \
|
||||
return p_instance->get(p_index); \
|
||||
} \
|
||||
static void func_##m_packed_type##_set(m_packed_type *p_instance, int64_t p_index, const m_type &p_value) { \
|
||||
ERR_FAIL_INDEX(p_index, p_instance->size()); \
|
||||
p_instance->set(p_index, p_value); \
|
||||
}
|
||||
|
||||
struct _VariantCall {
|
||||
VARCALL_PACKED_GETTER(PackedByteArray, uint8_t)
|
||||
VARCALL_PACKED_GETTER(PackedColorArray, Color)
|
||||
VARCALL_PACKED_GETTER(PackedFloat32Array, float)
|
||||
VARCALL_PACKED_GETTER(PackedFloat64Array, double)
|
||||
VARCALL_PACKED_GETTER(PackedInt32Array, int32_t)
|
||||
VARCALL_PACKED_GETTER(PackedInt64Array, int64_t)
|
||||
VARCALL_PACKED_GETTER(PackedStringArray, String)
|
||||
VARCALL_PACKED_GETTER(PackedVector2Array, Vector2)
|
||||
VARCALL_PACKED_GETTER(PackedVector3Array, Vector3)
|
||||
VARCALL_PACKED_GETTER(PackedVector4Array, Vector4)
|
||||
VARCALL_ARRAY_GETTER_SETTER(PackedByteArray, uint8_t)
|
||||
VARCALL_ARRAY_GETTER_SETTER(PackedColorArray, Color)
|
||||
VARCALL_ARRAY_GETTER_SETTER(PackedFloat32Array, float)
|
||||
VARCALL_ARRAY_GETTER_SETTER(PackedFloat64Array, double)
|
||||
VARCALL_ARRAY_GETTER_SETTER(PackedInt32Array, int32_t)
|
||||
VARCALL_ARRAY_GETTER_SETTER(PackedInt64Array, int64_t)
|
||||
VARCALL_ARRAY_GETTER_SETTER(PackedStringArray, String)
|
||||
VARCALL_ARRAY_GETTER_SETTER(PackedVector2Array, Vector2)
|
||||
VARCALL_ARRAY_GETTER_SETTER(PackedVector3Array, Vector3)
|
||||
VARCALL_ARRAY_GETTER_SETTER(PackedVector4Array, Vector4)
|
||||
VARCALL_ARRAY_GETTER_SETTER(Array, Variant)
|
||||
|
||||
static String func_PackedByteArray_get_string_from_ascii(PackedByteArray *p_instance) {
|
||||
String s;
|
||||
|
|
@ -2354,8 +2360,8 @@ static void _register_variant_builtin_methods_array() {
|
|||
bind_method(Array, clear, sarray(), varray());
|
||||
bind_method(Array, hash, sarray(), varray());
|
||||
bind_method(Array, assign, sarray("array"), varray());
|
||||
bind_method(Array, get, sarray("index"), varray());
|
||||
bind_method(Array, set, sarray("index", "value"), varray());
|
||||
bind_function(Array, get, _VariantCall::func_Array_get, sarray("index"), varray());
|
||||
bind_functionnc(Array, set, _VariantCall::func_Array_set, sarray("index", "value"), varray());
|
||||
bind_method(Array, push_back, sarray("value"), varray());
|
||||
bind_method(Array, push_front, sarray("value"), varray());
|
||||
bind_method(Array, append, sarray("value"), varray());
|
||||
|
|
@ -2400,7 +2406,7 @@ static void _register_variant_builtin_methods_array() {
|
|||
bind_method(Array, make_read_only, sarray(), varray());
|
||||
bind_method(Array, is_read_only, sarray(), varray());
|
||||
|
||||
/* Packed*Array get (see VARCALL_PACKED_GETTER macro) */
|
||||
/* Packed*Array get/set (see VARCALL_ARRAY_GETTER_SETTER macro) */
|
||||
bind_function(PackedByteArray, get, _VariantCall::func_PackedByteArray_get, sarray("index"), varray());
|
||||
bind_function(PackedColorArray, get, _VariantCall::func_PackedColorArray_get, sarray("index"), varray());
|
||||
bind_function(PackedFloat32Array, get, _VariantCall::func_PackedFloat32Array_get, sarray("index"), varray());
|
||||
|
|
@ -2412,10 +2418,20 @@ static void _register_variant_builtin_methods_array() {
|
|||
bind_function(PackedVector3Array, get, _VariantCall::func_PackedVector3Array_get, sarray("index"), varray());
|
||||
bind_function(PackedVector4Array, get, _VariantCall::func_PackedVector4Array_get, sarray("index"), varray());
|
||||
|
||||
bind_functionnc(PackedByteArray, set, _VariantCall::func_PackedByteArray_set, sarray("index", "value"), varray());
|
||||
bind_functionnc(PackedColorArray, set, _VariantCall::func_PackedColorArray_set, sarray("index", "value"), varray());
|
||||
bind_functionnc(PackedFloat32Array, set, _VariantCall::func_PackedFloat32Array_set, sarray("index", "value"), varray());
|
||||
bind_functionnc(PackedFloat64Array, set, _VariantCall::func_PackedFloat64Array_set, sarray("index", "value"), varray());
|
||||
bind_functionnc(PackedInt32Array, set, _VariantCall::func_PackedInt32Array_set, sarray("index", "value"), varray());
|
||||
bind_functionnc(PackedInt64Array, set, _VariantCall::func_PackedInt64Array_set, sarray("index", "value"), varray());
|
||||
bind_functionnc(PackedStringArray, set, _VariantCall::func_PackedStringArray_set, sarray("index", "value"), varray());
|
||||
bind_functionnc(PackedVector2Array, set, _VariantCall::func_PackedVector2Array_set, sarray("index", "value"), varray());
|
||||
bind_functionnc(PackedVector3Array, set, _VariantCall::func_PackedVector3Array_set, sarray("index", "value"), varray());
|
||||
bind_functionnc(PackedVector4Array, set, _VariantCall::func_PackedVector4Array_set, sarray("index", "value"), varray());
|
||||
|
||||
/* Byte Array */
|
||||
bind_method(PackedByteArray, size, sarray(), varray());
|
||||
bind_method(PackedByteArray, is_empty, sarray(), varray());
|
||||
bind_method(PackedByteArray, set, sarray("index", "value"), varray());
|
||||
bind_method(PackedByteArray, push_back, sarray("value"), varray());
|
||||
bind_method(PackedByteArray, append, sarray("value"), varray());
|
||||
bind_method(PackedByteArray, append_array, sarray("array"), varray());
|
||||
|
|
@ -2481,7 +2497,6 @@ static void _register_variant_builtin_methods_array() {
|
|||
|
||||
bind_method(PackedInt32Array, size, sarray(), varray());
|
||||
bind_method(PackedInt32Array, is_empty, sarray(), varray());
|
||||
bind_method(PackedInt32Array, set, sarray("index", "value"), varray());
|
||||
bind_method(PackedInt32Array, push_back, sarray("value"), varray());
|
||||
bind_method(PackedInt32Array, append, sarray("value"), varray());
|
||||
bind_method(PackedInt32Array, append_array, sarray("array"), varray());
|
||||
|
|
@ -2505,7 +2520,6 @@ static void _register_variant_builtin_methods_array() {
|
|||
|
||||
bind_method(PackedInt64Array, size, sarray(), varray());
|
||||
bind_method(PackedInt64Array, is_empty, sarray(), varray());
|
||||
bind_method(PackedInt64Array, set, sarray("index", "value"), varray());
|
||||
bind_method(PackedInt64Array, push_back, sarray("value"), varray());
|
||||
bind_method(PackedInt64Array, append, sarray("value"), varray());
|
||||
bind_method(PackedInt64Array, append_array, sarray("array"), varray());
|
||||
|
|
@ -2529,7 +2543,6 @@ static void _register_variant_builtin_methods_array() {
|
|||
|
||||
bind_method(PackedFloat32Array, size, sarray(), varray());
|
||||
bind_method(PackedFloat32Array, is_empty, sarray(), varray());
|
||||
bind_method(PackedFloat32Array, set, sarray("index", "value"), varray());
|
||||
bind_method(PackedFloat32Array, push_back, sarray("value"), varray());
|
||||
bind_method(PackedFloat32Array, append, sarray("value"), varray());
|
||||
bind_method(PackedFloat32Array, append_array, sarray("array"), varray());
|
||||
|
|
@ -2553,7 +2566,6 @@ static void _register_variant_builtin_methods_array() {
|
|||
|
||||
bind_method(PackedFloat64Array, size, sarray(), varray());
|
||||
bind_method(PackedFloat64Array, is_empty, sarray(), varray());
|
||||
bind_method(PackedFloat64Array, set, sarray("index", "value"), varray());
|
||||
bind_method(PackedFloat64Array, push_back, sarray("value"), varray());
|
||||
bind_method(PackedFloat64Array, append, sarray("value"), varray());
|
||||
bind_method(PackedFloat64Array, append_array, sarray("array"), varray());
|
||||
|
|
@ -2577,7 +2589,6 @@ static void _register_variant_builtin_methods_array() {
|
|||
|
||||
bind_method(PackedStringArray, size, sarray(), varray());
|
||||
bind_method(PackedStringArray, is_empty, sarray(), varray());
|
||||
bind_method(PackedStringArray, set, sarray("index", "value"), varray());
|
||||
bind_method(PackedStringArray, push_back, sarray("value"), varray());
|
||||
bind_method(PackedStringArray, append, sarray("value"), varray());
|
||||
bind_method(PackedStringArray, append_array, sarray("array"), varray());
|
||||
|
|
@ -2601,7 +2612,6 @@ static void _register_variant_builtin_methods_array() {
|
|||
|
||||
bind_method(PackedVector2Array, size, sarray(), varray());
|
||||
bind_method(PackedVector2Array, is_empty, sarray(), varray());
|
||||
bind_method(PackedVector2Array, set, sarray("index", "value"), varray());
|
||||
bind_method(PackedVector2Array, push_back, sarray("value"), varray());
|
||||
bind_method(PackedVector2Array, append, sarray("value"), varray());
|
||||
bind_method(PackedVector2Array, append_array, sarray("array"), varray());
|
||||
|
|
@ -2625,7 +2635,6 @@ static void _register_variant_builtin_methods_array() {
|
|||
|
||||
bind_method(PackedVector3Array, size, sarray(), varray());
|
||||
bind_method(PackedVector3Array, is_empty, sarray(), varray());
|
||||
bind_method(PackedVector3Array, set, sarray("index", "value"), varray());
|
||||
bind_method(PackedVector3Array, push_back, sarray("value"), varray());
|
||||
bind_method(PackedVector3Array, append, sarray("value"), varray());
|
||||
bind_method(PackedVector3Array, append_array, sarray("array"), varray());
|
||||
|
|
@ -2649,7 +2658,6 @@ static void _register_variant_builtin_methods_array() {
|
|||
|
||||
bind_method(PackedColorArray, size, sarray(), varray());
|
||||
bind_method(PackedColorArray, is_empty, sarray(), varray());
|
||||
bind_method(PackedColorArray, set, sarray("index", "value"), varray());
|
||||
bind_method(PackedColorArray, push_back, sarray("value"), varray());
|
||||
bind_method(PackedColorArray, append, sarray("value"), varray());
|
||||
bind_method(PackedColorArray, append_array, sarray("array"), varray());
|
||||
|
|
@ -2673,7 +2681,6 @@ static void _register_variant_builtin_methods_array() {
|
|||
|
||||
bind_method(PackedVector4Array, size, sarray(), varray());
|
||||
bind_method(PackedVector4Array, is_empty, sarray(), varray());
|
||||
bind_method(PackedVector4Array, set, sarray("index", "value"), varray());
|
||||
bind_method(PackedVector4Array, push_back, sarray("value"), varray());
|
||||
bind_method(PackedVector4Array, append, sarray("value"), varray());
|
||||
bind_method(PackedVector4Array, append_array, sarray("array"), varray());
|
||||
|
|
|
|||
|
|
@ -1090,6 +1090,25 @@
|
|||
[b]Note:[/b] On macOS, this method requires "Screen Recording" permission, if permission is not granted it will return desktop wallpaper color.
|
||||
</description>
|
||||
</method>
|
||||
<method name="screen_get_max_average_luminance" qualifiers="const">
|
||||
<return type="float" />
|
||||
<param index="0" name="screen" type="int" default="-1" />
|
||||
<description>
|
||||
Returns the maximum full screen luminance of [param screen] in nits (cd/m²).
|
||||
Some displays support brighter luminance in small areas, but this is the maximum luminance that can be achieved across the entire screen.
|
||||
[b]Note:[/b] Requires support for [constant FEATURE_HDR].
|
||||
[b]Note:[/b] On Windows, this method is implemented only in builds with D3D12 enabled.
|
||||
</description>
|
||||
</method>
|
||||
<method name="screen_get_max_luminance" qualifiers="const">
|
||||
<return type="float" />
|
||||
<param index="0" name="screen" type="int" default="-1" />
|
||||
<description>
|
||||
Returns the maximum luminance of a pixel on [param screen] in nits (cd/m²).
|
||||
[b]Note:[/b] Requires support for [constant FEATURE_HDR].
|
||||
[b]Note:[/b] On Windows, this method is implemented only in builds with D3D12 enabled.
|
||||
</description>
|
||||
</method>
|
||||
<method name="screen_get_max_scale" qualifiers="const">
|
||||
<return type="float" />
|
||||
<description>
|
||||
|
|
@ -1098,6 +1117,15 @@
|
|||
[b]Note:[/b] This method is implemented only on macOS.
|
||||
</description>
|
||||
</method>
|
||||
<method name="screen_get_min_luminance" qualifiers="const">
|
||||
<return type="float" />
|
||||
<param index="0" name="screen" type="int" default="-1" />
|
||||
<description>
|
||||
Returns the minimum luminance of a pixel on [param screen] in nits (cd/m²).
|
||||
[b]Note:[/b] Requires support for [constant FEATURE_HDR].
|
||||
[b]Note:[/b] On Windows, this method is implemented only in builds with D3D12 enabled.
|
||||
</description>
|
||||
</method>
|
||||
<method name="screen_get_orientation" qualifiers="const">
|
||||
<return type="int" enum="DisplayServer.ScreenOrientation" />
|
||||
<param index="0" name="screen" type="int" default="-1" />
|
||||
|
|
@ -1156,6 +1184,15 @@
|
|||
[b]Note:[/b] This method is implemented on Android, iOS, Web, macOS, and Linux (Wayland).
|
||||
</description>
|
||||
</method>
|
||||
<method name="screen_get_sdr_white_level" qualifiers="const">
|
||||
<return type="float" />
|
||||
<param index="0" name="screen" type="int" default="-1" />
|
||||
<description>
|
||||
Returns the standard dynamic range (SDR) white level of [param screen] in nits (cd/m²).
|
||||
This is the maximum brightness SDR content (such as UI) should be rendered at to match other applications on the display.
|
||||
[b]Note:[/b] Requires support for [constant FEATURE_HDR].
|
||||
</description>
|
||||
</method>
|
||||
<method name="screen_get_size" qualifiers="const">
|
||||
<return type="Vector2i" />
|
||||
<param index="0" name="screen" type="int" default="-1" />
|
||||
|
|
@ -1170,6 +1207,15 @@
|
|||
Returns the portion of the screen that is not obstructed by a status bar in pixels. See also [method screen_get_size].
|
||||
</description>
|
||||
</method>
|
||||
<method name="screen_is_hdr_supported" qualifiers="const">
|
||||
<return type="bool" />
|
||||
<param index="0" name="screen" type="int" default="-1" />
|
||||
<description>
|
||||
Returns [code]true[/code] if the [param screen] supports HDR.
|
||||
[b]Note:[/b] Requires support for [constant FEATURE_HDR].
|
||||
[b]Note:[/b] On Windows, this method is implemented only in builds with D3D12 enabled.
|
||||
</description>
|
||||
</method>
|
||||
<method name="screen_is_kept_on" qualifiers="const">
|
||||
<return type="bool" />
|
||||
<description>
|
||||
|
|
@ -1481,6 +1527,30 @@
|
|||
Returns the current value of the given window's [param flag].
|
||||
</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 content for the window specified by [param window_id].
|
||||
[b]Note:[/b] Requires support for [constant FEATURE_HDR].
|
||||
</description>
|
||||
</method>
|
||||
<method name="window_get_hdr_output_min_luminance" qualifiers="const">
|
||||
<return type="float" />
|
||||
<param index="0" name="window_id" type="int" default="0" />
|
||||
<description>
|
||||
Returns the minimum luminance in nits (cd/m²) set for HDR content for the window specified by [param window_id].
|
||||
[b]Note:[/b] Requires support for [constant FEATURE_HDR].
|
||||
</description>
|
||||
</method>
|
||||
<method name="window_get_hdr_output_reference_luminance" qualifiers="const">
|
||||
<return type="float" />
|
||||
<param index="0" name="window_id" type="int" default="0" />
|
||||
<description>
|
||||
Returns the SDR reference luminance in nits (cd/m²) set for HDR content for the window specified by [param window_id].
|
||||
[b]Note:[/b] Requires support for [constant FEATURE_HDR].
|
||||
</description>
|
||||
</method>
|
||||
<method name="window_get_max_size" qualifiers="const">
|
||||
<return type="Vector2i" />
|
||||
<param index="0" name="window_id" type="int" default="0" />
|
||||
|
|
@ -1576,6 +1646,29 @@
|
|||
Returns [code]true[/code] if the window specified by [param window_id] is focused.
|
||||
</description>
|
||||
</method>
|
||||
<method name="window_is_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 window specified by [param window_id].
|
||||
[b]Note:[/b] Requires support for [constant FEATURE_HDR].
|
||||
</description>
|
||||
</method>
|
||||
<method name="window_is_hdr_output_preferring_high_precision" qualifiers="const">
|
||||
<return type="bool" />
|
||||
<param index="0" name="window_id" type="int" default="0" />
|
||||
<description>
|
||||
Returns whether the window specified by [param window_id] prefers a high precision (16-bit per color) HDR framebuffer.
|
||||
</description>
|
||||
</method>
|
||||
<method name="window_is_hdr_output_using_screen_luminance" qualifiers="const">
|
||||
<return type="bool" />
|
||||
<param index="0" name="window_id" type="int" default="0" />
|
||||
<description>
|
||||
Returns whether the window specified by [param window_id] is using the screen's luminance for HDR output.
|
||||
[b]Note:[/b] Requires support for [constant FEATURE_HDR].
|
||||
</description>
|
||||
</method>
|
||||
<method name="window_is_maximize_allowed" qualifiers="const">
|
||||
<return type="bool" />
|
||||
<param index="0" name="window_id" type="int" default="0" />
|
||||
|
|
@ -1648,6 +1741,71 @@
|
|||
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], 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.
|
||||
[b]Note:[/b] Requires support for [constant FEATURE_HDR].
|
||||
[b]Note:[/b] Requires support by the rendering device.
|
||||
</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 in nits (cd/m²) for HDR content for the window specified by [param window_id].
|
||||
[b]Note:[/b] Requires support for [constant FEATURE_HDR].
|
||||
[b]Note:[/b] Requires support by the rendering device.
|
||||
[b]Note:[/b] Ignored if [method window_is_hdr_output_using_screen_luminance] is [code]true[/code].
|
||||
</description>
|
||||
</method>
|
||||
<method name="window_set_hdr_output_min_luminance">
|
||||
<return type="void" />
|
||||
<param index="0" name="min_luminance" type="float" />
|
||||
<param index="1" name="window_id" type="int" default="0" />
|
||||
<description>
|
||||
Sets the minimum luminance in nits (cd/m²) for HDR content for the window specified by [param window_id].
|
||||
[b]Note:[/b] Requires support for [constant FEATURE_HDR].
|
||||
[b]Note:[/b] Requires support by the rendering device.
|
||||
[b]Note:[/b] Ignored if [method window_is_hdr_output_using_screen_luminance] is [code]true[/code].
|
||||
</description>
|
||||
</method>
|
||||
<method name="window_set_hdr_output_prefer_high_precision">
|
||||
<return type="void" />
|
||||
<param index="0" name="enabled" type="bool" />
|
||||
<param index="1" name="window_id" type="int" default="0" />
|
||||
<description>
|
||||
Sets whether the window specified by [param window_id] prefers a high precision (16-bit per color) framebuffer.
|
||||
[b]Note:[/b] Requires support for [constant FEATURE_HDR].
|
||||
[b]Note:[/b] Requires support by the rendering device.
|
||||
</description>
|
||||
</method>
|
||||
<method name="window_set_hdr_output_reference_luminance">
|
||||
<return type="void" />
|
||||
<param index="0" name="reference_luminance" type="float" />
|
||||
<param index="1" name="window_id" type="int" default="0" />
|
||||
<description>
|
||||
Sets the SDR reference luminance in nits (cd/m²) for HDR content for the window specified by [param window_id].
|
||||
This controls the brightness of SDR content (such as UI) when HDR is enabled.
|
||||
[b]Note:[/b] Requires support for [constant FEATURE_HDR].
|
||||
[b]Note:[/b] Requires support by the rendering device.
|
||||
[b]Note:[/b] Ignored if [method window_is_hdr_output_using_screen_luminance] is [code]true[/code].
|
||||
</description>
|
||||
</method>
|
||||
<method name="window_set_hdr_output_use_screen_luminance">
|
||||
<return type="void" />
|
||||
<param index="0" name="enabled" type="bool" />
|
||||
<param index="1" name="window_id" type="int" default="0" />
|
||||
<description>
|
||||
Sets whether the window specified by [param window_id] should use the screen's luminance for HDR output.
|
||||
While this is enabled, the window will ignore attempts to set luminance values.
|
||||
[b]Note:[/b] Requires support for [constant FEATURE_HDR].
|
||||
</description>
|
||||
</method>
|
||||
<method name="window_set_ime_active">
|
||||
<return type="void" />
|
||||
<param index="0" name="active" type="bool" />
|
||||
|
|
@ -1952,6 +2110,9 @@
|
|||
<constant name="FEATURE_EMOJI_AND_SYMBOL_PICKER" value="31" enum="Feature">
|
||||
Display server supports system emoji and symbol picker. [b]Windows, macOS[/b]
|
||||
</constant>
|
||||
<constant name="FEATURE_HDR" value="32" 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>
|
||||
|
|
|
|||
|
|
@ -836,6 +836,30 @@
|
|||
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.
|
||||
</member>
|
||||
<member name="display/window/hdr/min_luminance" type="float" setter="" getter="" default="0.0">
|
||||
Sets the minimum luminance of the display in nits (cd/m²) when HDR is enabled.
|
||||
</member>
|
||||
<member name="display/window/hdr/prefer_high_precision" type="bool" setter="" getter="" default="false">
|
||||
If [code]true[/code], uses 16 bit per color buffers for the frame buffer when HDR is enabled.
|
||||
If [code]false[/code], uses 10 bit per color buffers, with 2 bits for alpha, for the frame buffer when HDR is enabled.
|
||||
This may improve color precision and reduce banding in the final image, but will use more memory and may reduce performance.
|
||||
If transparent backgrounds are enabled, you may want to enable this setting to enable smooth blending of HDR content.
|
||||
</member>
|
||||
<member name="display/window/hdr/reference_luminance" type="float" setter="" getter="" default="80.0">
|
||||
Sets the SDR reference luminance of the display in nits (cd/m²) when HDR is enabled.
|
||||
This is used to scale the HDR effect to ensure sRGB content looks the same in both SDR and HDR.
|
||||
</member>
|
||||
<member name="display/window/hdr/use_screen_luminance" type="bool" setter="" getter="" default="true">
|
||||
If [code]true[/code], uses the screen's luminance as reported by the display server to set luminance for the window.
|
||||
If information is missing for the display, will fall back to luminance values set in project settings.
|
||||
</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>
|
||||
|
|
@ -3184,6 +3208,9 @@
|
|||
[b]Note:[/b] This setting will have no effect when using the Compatibility renderer, which always renders in low dynamic range for performance reasons.
|
||||
[b]Note:[/b] This property is only read when the project starts. To toggle HDR 2D at runtime, set [member Viewport.use_hdr_2d] on the root [Viewport].
|
||||
</member>
|
||||
<member name="rendering/viewport/tonemap_to_window" type="bool" setter="" getter="" default="true">
|
||||
If [code]true[/code], enables [member Viewport.tonemap_to_window] on the root viewport.
|
||||
</member>
|
||||
<member name="rendering/viewport/transparent_background" type="bool" setter="" getter="" default="false">
|
||||
If [code]true[/code], enables [member Viewport.transparent_bg] on the root viewport. This allows per-pixel transparency to be effective after also enabling [member display/window/size/transparent] and [member display/window/per_pixel_transparency/allowed].
|
||||
</member>
|
||||
|
|
|
|||
|
|
@ -758,6 +758,22 @@
|
|||
Returns [code]true[/code] if implementation supports using a texture of [param format] with the given [param sampler_filter].
|
||||
</description>
|
||||
</method>
|
||||
<method name="screen_get_color_format" qualifiers="const">
|
||||
<return type="int" enum="RenderingDevice.DataFormat" />
|
||||
<param index="0" name="screen" type="int" default="0" />
|
||||
<description>
|
||||
Returns the color format of the given screen.
|
||||
[b]Note:[/b] Only the main [RenderingDevice] returned by [method RenderingServer.get_rendering_device] has a format. If called on a local [RenderingDevice], this method prints an error and returns [constant DATA_FORMAT_MAX].
|
||||
</description>
|
||||
</method>
|
||||
<method name="screen_get_color_space" qualifiers="const">
|
||||
<return type="int" enum="RenderingDevice.ColorSpace" />
|
||||
<param index="0" name="screen" type="int" default="0" />
|
||||
<description>
|
||||
Returns the color space of the given screen.
|
||||
[b]Note:[/b] Only the main [RenderingDevice] returned by [method RenderingServer.get_rendering_device] has a format. If called on a local [RenderingDevice], this method prints an error and returns [constant COLOR_SPACE_MAX].
|
||||
</description>
|
||||
</method>
|
||||
<method name="screen_get_framebuffer_format" qualifiers="const">
|
||||
<return type="int" />
|
||||
<param index="0" name="screen" type="int" default="0" />
|
||||
|
|
@ -1874,6 +1890,18 @@
|
|||
<constant name="DATA_FORMAT_MAX" value="218" enum="DataFormat">
|
||||
Represents the size of the [enum DataFormat] enum.
|
||||
</constant>
|
||||
<constant name="COLOR_SPACE_SRGB_LINEAR" value="0" enum="ColorSpace">
|
||||
Color space using Rec 709 primaries and linear gamma.
|
||||
</constant>
|
||||
<constant name="COLOR_SPACE_SRGB_NONLINEAR" value="1" enum="ColorSpace">
|
||||
Color space using Rec 709 primaries and non-linear sRGB gamma.
|
||||
</constant>
|
||||
<constant name="COLOR_SPACE_HDR10_ST2084" value="2" enum="ColorSpace">
|
||||
Color space using Rec 2020 primaries and the ST 2084 transfer function.
|
||||
</constant>
|
||||
<constant name="COLOR_SPACE_MAX" value="3" enum="ColorSpace">
|
||||
Represents the size of the [enum ColorSpace] enum.
|
||||
</constant>
|
||||
<constant name="BARRIER_MASK_VERTEX" value="1" enum="BarrierMask" is_bitfield="true">
|
||||
Vertex shader barrier mask.
|
||||
</constant>
|
||||
|
|
@ -2454,6 +2482,9 @@
|
|||
<constant name="SUPPORTS_BUFFER_DEVICE_ADDRESS" value="6" enum="Features">
|
||||
Features support for buffer device address extension.
|
||||
</constant>
|
||||
<constant name="SUPPORTS_HDR_OUTPUT" value="7" enum="Features">
|
||||
Features support for high dynamic range (HDR) output.
|
||||
</constant>
|
||||
<constant name="LIMIT_MAX_BOUND_UNIFORM_SETS" value="0" enum="Limit">
|
||||
Maximum number of uniform sets that can be bound at a given time.
|
||||
</constant>
|
||||
|
|
|
|||
|
|
@ -1493,6 +1493,16 @@
|
|||
Sets the variables to be used with the "tonemap" post-process effect. See [Environment] for more details.
|
||||
</description>
|
||||
</method>
|
||||
<method name="environment_set_tonemap_range">
|
||||
<return type="void" />
|
||||
<param index="0" name="env" type="RID" />
|
||||
<param index="1" name="min_value" type="float" />
|
||||
<param index="2" name="max_value" type="float" />
|
||||
<description>
|
||||
Sets the range of the tonemapper, defining the minimum and maximum values after tonemapping.
|
||||
[b]Note:[/b] This is ignored when using [constant ENV_TONE_MAPPER_LINEAR].
|
||||
</description>
|
||||
</method>
|
||||
<method name="environment_set_volumetric_fog">
|
||||
<return type="void" />
|
||||
<param index="0" name="env" type="RID" />
|
||||
|
|
@ -4190,6 +4200,14 @@
|
|||
[b]Note:[/b] When the 3D scaling mode is set to FSR 1.0, this value is used to adjust the automatic mipmap bias which is calculated internally based on the scale factor. The formula for this is [code]-log2(1.0 / scale) + mipmap_bias[/code].
|
||||
</description>
|
||||
</method>
|
||||
<method name="viewport_set_tonemap_to_screen">
|
||||
<return type="void" />
|
||||
<param index="0" name="viewport" type="RID" />
|
||||
<param index="1" name="enabled" type="bool" />
|
||||
<description>
|
||||
If [code]true[/code], the viewport will tonemap its content to the window's HDR output luminance range, if HDR output is enabled.
|
||||
</description>
|
||||
</method>
|
||||
<method name="viewport_set_transparent_background">
|
||||
<return type="void" />
|
||||
<param index="0" name="viewport" type="RID" />
|
||||
|
|
|
|||
|
|
@ -415,6 +415,10 @@
|
|||
[b]Note:[/b] If [member scaling_3d_scale] is lower than [code]1.0[/code] (exclusive), [member texture_mipmap_bias] is used to adjust the automatic mipmap bias which is calculated internally based on the scale factor. The formula for this is [code]log2(scaling_3d_scale) + mipmap_bias[/code].
|
||||
To control this property on the root viewport, set the [member ProjectSettings.rendering/textures/default_filters/texture_mipmap_bias] project setting.
|
||||
</member>
|
||||
<member name="tonemap_to_window" type="bool" setter="set_tonemap_to_window" getter="is_tonemapping_to_window" default="false">
|
||||
If [code]true[/code], the viewport will tonemap its content to the window's HDR output luminance range, if HDR output is enabled.
|
||||
This is useful for viewports that are not the root of the window, but still need their content to adjust to the capabilities of the display.
|
||||
</member>
|
||||
<member name="transparent_bg" type="bool" setter="set_transparent_background" getter="has_transparent_background" default="false">
|
||||
If [code]true[/code], the viewport should render its background as transparent.
|
||||
</member>
|
||||
|
|
|
|||
|
|
@ -614,6 +614,26 @@
|
|||
<member name="force_native" type="bool" setter="set_force_native" getter="get_force_native" default="false">
|
||||
If [code]true[/code], native window will be used regardless of parent viewport and project settings.
|
||||
</member>
|
||||
<member name="hdr_output_enabled" type="bool" setter="set_hdr_output_enabled" getter="is_hdr_output_enabled" default="false">
|
||||
If [code]true[/code], the [Window] will output in HDR.
|
||||
Only available on platforms that support HDR output, have HDR enabled in the system settings, and have a compatible display connected.
|
||||
</member>
|
||||
<member name="hdr_output_max_luminance" type="float" setter="set_hdr_output_max_luminance" getter="get_hdr_output_max_luminance" default="1000.0">
|
||||
The maximum luminance in nits (cd/m²) when HDR is enabled.
|
||||
</member>
|
||||
<member name="hdr_output_min_luminance" type="float" setter="set_hdr_output_min_luminance" getter="get_hdr_output_min_luminance" default="0.0">
|
||||
The minimum luminance in nits (cd/m²) when HDR is enabled.
|
||||
</member>
|
||||
<member name="hdr_output_prefer_high_precision" type="bool" setter="set_hdr_output_prefer_high_precision" getter="is_hdr_output_preferring_high_precision" default="false">
|
||||
If [code]true[/code], the [Window] will prefer high-precision (16-bit per color) framebuffer when available and HDR is enabled.
|
||||
</member>
|
||||
<member name="hdr_output_reference_luminance" type="float" setter="set_hdr_output_reference_luminance" getter="get_hdr_output_reference_luminance" default="80.0">
|
||||
The SDR reference luminance in nits (cd/m²) when HDR is enabled.
|
||||
This controls the brightness of SDR content (such as UI) when HDR is enabled.
|
||||
</member>
|
||||
<member name="hdr_output_use_screen_luminance" type="bool" setter="set_hdr_output_use_screen_luminance" getter="is_hdr_output_using_screen_luminance" default="false">
|
||||
If [code]true[/code], the [Window] will use the screen's luminance to adjust the HDR output.
|
||||
</member>
|
||||
<member name="initial_position" type="int" setter="set_initial_position" getter="get_initial_position" enum="Window.WindowInitialPosition" default="0">
|
||||
Specifies the initial type of position for the [Window]. See [enum WindowInitialPosition] constants.
|
||||
</member>
|
||||
|
|
@ -693,6 +713,7 @@
|
|||
<member name="title" type="String" setter="set_title" getter="get_title" default="""">
|
||||
The window's title. If the [Window] is native, title styles set in [Theme] will have no effect.
|
||||
</member>
|
||||
<member name="tonemap_to_window" type="bool" setter="set_tonemap_to_window" getter="is_tonemapping_to_window" overrides="Viewport" default="true" />
|
||||
<member name="transient" type="bool" setter="set_transient" getter="is_transient" default="false">
|
||||
If [code]true[/code], the [Window] is transient, i.e. it's considered a child of another [Window]. The transient window will be destroyed with its transient parent and will return focus to their parent when closed. The transient window is displayed on top of a non-exclusive full-screen parent window. Transient windows can't enter full-screen mode.
|
||||
Note that behavior might be different depending on the platform.
|
||||
|
|
|
|||
|
|
@ -282,6 +282,58 @@ 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;
|
||||
surface->needs_resize = true;
|
||||
}
|
||||
|
||||
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_prefer_high_precision(SurfaceID p_surface, bool p_enabled) {
|
||||
Surface *surface = (Surface *)(p_surface);
|
||||
surface->hdr_prefer_high_precision = p_enabled;
|
||||
surface->needs_resize = true;
|
||||
}
|
||||
|
||||
bool RenderingContextDriverD3D12::surface_get_hdr_output_prefer_high_precision(SurfaceID p_surface) const {
|
||||
Surface *surface = (Surface *)(p_surface);
|
||||
return surface->hdr_prefer_high_precision;
|
||||
}
|
||||
|
||||
void RenderingContextDriverD3D12::surface_set_hdr_output_reference_luminance(SurfaceID p_surface, float p_reference_luminance) {
|
||||
Surface *surface = (Surface *)(p_surface);
|
||||
surface->hdr_reference_luminance = p_reference_luminance;
|
||||
}
|
||||
|
||||
float RenderingContextDriverD3D12::surface_get_hdr_output_reference_luminance(SurfaceID p_surface) const {
|
||||
Surface *surface = (Surface *)(p_surface);
|
||||
return surface->hdr_reference_luminance;
|
||||
}
|
||||
|
||||
void RenderingContextDriverD3D12::surface_set_hdr_output_min_luminance(SurfaceID p_surface, float p_min_luminance) {
|
||||
Surface *surface = (Surface *)(p_surface);
|
||||
surface->hdr_min_luminance = p_min_luminance;
|
||||
}
|
||||
|
||||
float RenderingContextDriverD3D12::surface_get_hdr_output_min_luminance(SurfaceID p_surface) const {
|
||||
Surface *surface = (Surface *)(p_surface);
|
||||
return surface->hdr_min_luminance;
|
||||
}
|
||||
|
||||
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;
|
||||
|
|
|
|||
|
|
@ -109,6 +109,16 @@ public:
|
|||
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_prefer_high_precision(SurfaceID p_surface, bool p_enabled) override;
|
||||
virtual bool surface_get_hdr_output_prefer_high_precision(SurfaceID p_surface) const override;
|
||||
virtual void surface_set_hdr_output_reference_luminance(SurfaceID p_surface, float p_reference_luminance) override;
|
||||
virtual float surface_get_hdr_output_reference_luminance(SurfaceID p_surface) const override;
|
||||
virtual void surface_set_hdr_output_min_luminance(SurfaceID p_surface, float p_min_luminance) override;
|
||||
virtual float surface_get_hdr_output_min_luminance(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;
|
||||
|
|
@ -128,6 +138,13 @@ public:
|
|||
uint32_t height = 0;
|
||||
DisplayServer::VSyncMode vsync_mode = DisplayServer::VSYNC_ENABLED;
|
||||
bool needs_resize = false;
|
||||
|
||||
bool hdr_output = false;
|
||||
bool hdr_prefer_high_precision = false;
|
||||
float hdr_reference_luminance = 0.0f;
|
||||
float hdr_min_luminance = 0.0f;
|
||||
float hdr_max_luminance = 0.0f;
|
||||
|
||||
ComPtr<IDCompositionDevice> composition_device;
|
||||
ComPtr<IDCompositionTarget> composition_target;
|
||||
ComPtr<IDCompositionVisual> composition_visual;
|
||||
|
|
|
|||
|
|
@ -334,6 +334,12 @@ const RenderingDeviceDriverD3D12::D3D12Format RenderingDeviceDriverD3D12::RD_TO_
|
|||
/* DATA_FORMAT_G16_B16_R16_3PLANE_444_UNORM */ {},
|
||||
};
|
||||
|
||||
const DXGI_COLOR_SPACE_TYPE RenderingDeviceDriverD3D12::RD_TO_DXGI_COLOR_SPACE_TYPE[RDD::COLOR_SPACE_MAX]{
|
||||
/* COLOR_SPACE_SRGB_LINEAR */ DXGI_COLOR_SPACE_RGB_FULL_G10_NONE_P709,
|
||||
/* COLOR_SPACE_SRGB_NONLINEAR */ DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709,
|
||||
/* COLOR_SPACE_HDR10_ST2084 */ DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020,
|
||||
};
|
||||
|
||||
Error RenderingDeviceDriverD3D12::DescriptorsHeap::allocate(ID3D12Device *p_device, D3D12_DESCRIPTOR_HEAP_TYPE p_type, uint32_t p_descriptor_count, bool p_for_gpu) {
|
||||
ERR_FAIL_COND_V(heap, ERR_ALREADY_EXISTS);
|
||||
ERR_FAIL_COND_V(p_descriptor_count == 0, ERR_INVALID_PARAMETER);
|
||||
|
|
@ -2405,6 +2411,11 @@ void RenderingDeviceDriverD3D12::command_buffer_execute_secondary(CommandBufferI
|
|||
void RenderingDeviceDriverD3D12::_swap_chain_release(SwapChain *p_swap_chain) {
|
||||
_swap_chain_release_buffers(p_swap_chain);
|
||||
|
||||
if (p_swap_chain->render_pass.id != 0) {
|
||||
render_pass_free(p_swap_chain->render_pass);
|
||||
p_swap_chain->render_pass = RenderPassID();
|
||||
}
|
||||
|
||||
p_swap_chain->d3d_swap_chain.Reset();
|
||||
}
|
||||
|
||||
|
|
@ -2423,10 +2434,10 @@ void RenderingDeviceDriverD3D12::_swap_chain_release_buffers(SwapChain *p_swap_c
|
|||
p_swap_chain->framebuffers.clear();
|
||||
}
|
||||
|
||||
RDD::SwapChainID RenderingDeviceDriverD3D12::swap_chain_create(RenderingContextDriver::SurfaceID p_surface) {
|
||||
RDD::RenderPassID RenderingDeviceDriverD3D12::_swap_chain_create_render_pass(RDD::DataFormat p_format) {
|
||||
// Create the render pass that will be used to draw to the swap chain's framebuffers.
|
||||
RDD::Attachment attachment;
|
||||
attachment.format = DATA_FORMAT_R8G8B8A8_UNORM;
|
||||
attachment.format = p_format;
|
||||
attachment.samples = RDD::TEXTURE_SAMPLES_1;
|
||||
attachment.load_op = RDD::ATTACHMENT_LOAD_OP_CLEAR;
|
||||
attachment.store_op = RDD::ATTACHMENT_STORE_OP_STORE;
|
||||
|
|
@ -2437,14 +2448,35 @@ RDD::SwapChainID RenderingDeviceDriverD3D12::swap_chain_create(RenderingContextD
|
|||
color_ref.aspect.set_flag(RDD::TEXTURE_ASPECT_COLOR_BIT);
|
||||
subpass.color_references.push_back(color_ref);
|
||||
|
||||
RenderPassID render_pass = render_pass_create(attachment, subpass, {}, 1);
|
||||
ERR_FAIL_COND_V(!render_pass, SwapChainID());
|
||||
return render_pass_create(attachment, subpass, {}, 1);
|
||||
}
|
||||
|
||||
// Create the empty swap chain until it is resized.
|
||||
void RenderingDeviceDriverD3D12::_determine_swap_chain_format(SwapChain *p_swap_chain, DataFormat &r_format, ColorSpace &r_color_space) {
|
||||
DEV_ASSERT(p_swap_chain);
|
||||
DEV_ASSERT(p_swap_chain->surface != 0);
|
||||
|
||||
// Direct3D Hardware level 10 mandates support for all these formats.
|
||||
// Godot requires at least Hardware level 11, so these formats are guaranteed to be supported.
|
||||
if (context_driver->surface_get_hdr_output_enabled(p_swap_chain->surface)) {
|
||||
if (context_driver->surface_get_hdr_output_prefer_high_precision(p_swap_chain->surface)) {
|
||||
r_format = DATA_FORMAT_R16G16B16A16_SFLOAT;
|
||||
r_color_space = COLOR_SPACE_SRGB_LINEAR;
|
||||
} else {
|
||||
r_format = DATA_FORMAT_A2R10G10B10_UNORM_PACK32;
|
||||
r_color_space = COLOR_SPACE_HDR10_ST2084;
|
||||
}
|
||||
} else {
|
||||
r_format = DATA_FORMAT_R8G8B8A8_UNORM;
|
||||
r_color_space = COLOR_SPACE_SRGB_NONLINEAR;
|
||||
}
|
||||
}
|
||||
|
||||
RDD::SwapChainID RenderingDeviceDriverD3D12::swap_chain_create(RenderingContextDriver::SurfaceID p_surface) {
|
||||
DEV_ASSERT(p_surface != 0);
|
||||
|
||||
// Create an empty swap chain until it is resized.
|
||||
SwapChain *swap_chain = memnew(SwapChain);
|
||||
swap_chain->surface = p_surface;
|
||||
swap_chain->data_format = attachment.format;
|
||||
swap_chain->render_pass = render_pass;
|
||||
return SwapChainID(swap_chain);
|
||||
}
|
||||
|
||||
|
|
@ -2486,17 +2518,27 @@ Error RenderingDeviceDriverD3D12::swap_chain_resize(CommandQueueID p_cmd_queue,
|
|||
break;
|
||||
}
|
||||
|
||||
if (swap_chain->d3d_swap_chain != nullptr && creation_flags != swap_chain->creation_flags) {
|
||||
// The swap chain must be recreated if the creation flags are different.
|
||||
RDD::DataFormat new_data_format;
|
||||
RDD::ColorSpace new_color_space;
|
||||
_determine_swap_chain_format(swap_chain, new_data_format, new_color_space);
|
||||
|
||||
if (swap_chain->d3d_swap_chain != nullptr && (creation_flags != swap_chain->creation_flags || new_data_format != swap_chain->data_format)) {
|
||||
// The swap chain must be recreated if the creation flags or data format are different.
|
||||
_swap_chain_release(swap_chain);
|
||||
}
|
||||
|
||||
swap_chain->data_format = new_data_format;
|
||||
|
||||
DXGI_SWAP_CHAIN_DESC1 swap_chain_desc = {};
|
||||
if (swap_chain->d3d_swap_chain != nullptr) {
|
||||
_swap_chain_release_buffers(swap_chain);
|
||||
res = swap_chain->d3d_swap_chain->ResizeBuffers(p_desired_framebuffer_count, surface->width, surface->height, DXGI_FORMAT_UNKNOWN, creation_flags);
|
||||
ERR_FAIL_COND_V(!SUCCEEDED(res), ERR_UNAVAILABLE);
|
||||
} else {
|
||||
DEV_ASSERT(swap_chain->render_pass.id == 0);
|
||||
swap_chain->render_pass = _swap_chain_create_render_pass(new_data_format);
|
||||
ERR_FAIL_COND_V(!swap_chain->render_pass, ERR_CANT_CREATE);
|
||||
|
||||
swap_chain_desc.BufferCount = p_desired_framebuffer_count;
|
||||
swap_chain_desc.Format = RD_TO_D3D12_FORMAT[swap_chain->data_format].general_format;
|
||||
swap_chain_desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
|
||||
|
|
@ -2525,6 +2567,13 @@ Error RenderingDeviceDriverD3D12::swap_chain_resize(CommandQueueID p_cmd_queue,
|
|||
ERR_FAIL_COND_V(!SUCCEEDED(res), ERR_CANT_CREATE);
|
||||
}
|
||||
|
||||
if (swap_chain->color_space != new_color_space) {
|
||||
res = swap_chain->d3d_swap_chain->SetColorSpace1(RD_TO_DXGI_COLOR_SPACE_TYPE[new_color_space]);
|
||||
ERR_FAIL_COND_V(!SUCCEEDED(res), ERR_CANT_CREATE);
|
||||
|
||||
swap_chain->color_space = new_color_space;
|
||||
}
|
||||
|
||||
if (surface->composition_device.Get() == nullptr) {
|
||||
using PFN_DCompositionCreateDevice = HRESULT(WINAPI *)(IDXGIDevice *, REFIID, void **);
|
||||
PFN_DCompositionCreateDevice pfn_DCompositionCreateDevice = (PFN_DCompositionCreateDevice)(void *)GetProcAddress(context_driver->lib_dcomp, "DCompositionCreateDevice");
|
||||
|
|
@ -2634,10 +2683,14 @@ 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) {
|
||||
const SwapChain *swap_chain = (const SwapChain *)(p_swap_chain.id);
|
||||
return swap_chain->color_space;
|
||||
}
|
||||
|
||||
void RenderingDeviceDriverD3D12::swap_chain_free(SwapChainID p_swap_chain) {
|
||||
SwapChain *swap_chain = (SwapChain *)(p_swap_chain.id);
|
||||
_swap_chain_release(swap_chain);
|
||||
render_pass_free(swap_chain->render_pass);
|
||||
memdelete(swap_chain);
|
||||
}
|
||||
|
||||
|
|
@ -6280,6 +6333,8 @@ bool RenderingDeviceDriverD3D12::has_feature(Features p_feature) {
|
|||
return true;
|
||||
case SUPPORTS_BUFFER_DEVICE_ADDRESS:
|
||||
return true;
|
||||
case SUPPORTS_HDR_OUTPUT:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -100,6 +100,7 @@ class RenderingDeviceDriverD3D12 : public RenderingDeviceDriver {
|
|||
};
|
||||
|
||||
static const D3D12Format RD_TO_D3D12_FORMAT[RDD::DATA_FORMAT_MAX];
|
||||
static const DXGI_COLOR_SPACE_TYPE RD_TO_DXGI_COLOR_SPACE_TYPE[RDD::COLOR_SPACE_MAX];
|
||||
|
||||
struct DeviceLimits {
|
||||
uint64_t max_srvs_per_shader_stage = 0;
|
||||
|
|
@ -506,10 +507,13 @@ private:
|
|||
TightLocalVector<TextureInfo> render_targets_info;
|
||||
TightLocalVector<FramebufferID> framebuffers;
|
||||
RDD::DataFormat data_format = DATA_FORMAT_MAX;
|
||||
RDD::ColorSpace color_space = COLOR_SPACE_MAX;
|
||||
};
|
||||
|
||||
void _swap_chain_release(SwapChain *p_swap_chain);
|
||||
void _swap_chain_release_buffers(SwapChain *p_swap_chain);
|
||||
RenderPassID _swap_chain_create_render_pass(RDD::DataFormat p_format);
|
||||
void _determine_swap_chain_format(SwapChain *p_swap_chain, DataFormat &r_format, ColorSpace &r_color_space);
|
||||
|
||||
public:
|
||||
virtual SwapChainID swap_chain_create(RenderingContextDriver::SurfaceID p_surface) override;
|
||||
|
|
@ -517,6 +521,7 @@ public:
|
|||
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;
|
||||
|
||||
/*********************/
|
||||
|
|
|
|||
|
|
@ -76,6 +76,16 @@ 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_prefer_high_precision(SurfaceID p_surface, bool p_enabled) override;
|
||||
virtual bool surface_get_hdr_output_prefer_high_precision(SurfaceID p_surface) const override;
|
||||
virtual void surface_set_hdr_output_reference_luminance(SurfaceID p_surface, float p_reference_luminance) final override;
|
||||
virtual float surface_get_hdr_output_reference_luminance(SurfaceID p_surface) const final override;
|
||||
virtual void surface_set_hdr_output_min_luminance(SurfaceID p_surface, float p_min_luminance) final override;
|
||||
virtual float surface_get_hdr_output_min_luminance(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;
|
||||
|
|
@ -109,6 +119,12 @@ public:
|
|||
bool needs_resize = false;
|
||||
double present_minimum_duration = 0.0;
|
||||
|
||||
bool hdr_output = false;
|
||||
bool hdr_prefer_high_precision = false;
|
||||
float hdr_reference_luminance = 0.0f;
|
||||
float hdr_min_luminance = 0.0f;
|
||||
float hdr_max_luminance = 0.0f;
|
||||
|
||||
Surface(
|
||||
#ifdef __OBJC__
|
||||
id<MTLDevice> p_device
|
||||
|
|
|
|||
|
|
@ -211,6 +211,58 @@ DisplayServer::VSyncMode RenderingContextDriverMetal::surface_get_vsync_mode(Sur
|
|||
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;
|
||||
surface->needs_resize = true;
|
||||
}
|
||||
|
||||
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_prefer_high_precision(SurfaceID p_surface, bool p_enabled) {
|
||||
Surface *surface = (Surface *)(p_surface);
|
||||
surface->hdr_prefer_high_precision = p_enabled;
|
||||
surface->needs_resize = true;
|
||||
}
|
||||
|
||||
bool RenderingContextDriverMetal::surface_get_hdr_output_prefer_high_precision(SurfaceID p_surface) const {
|
||||
Surface *surface = (Surface *)(p_surface);
|
||||
return surface->hdr_prefer_high_precision;
|
||||
}
|
||||
|
||||
void RenderingContextDriverMetal::surface_set_hdr_output_reference_luminance(SurfaceID p_surface, float p_reference_luminance) {
|
||||
Surface *surface = (Surface *)(p_surface);
|
||||
surface->hdr_reference_luminance = p_reference_luminance;
|
||||
}
|
||||
|
||||
float RenderingContextDriverMetal::surface_get_hdr_output_reference_luminance(SurfaceID p_surface) const {
|
||||
Surface *surface = (Surface *)(p_surface);
|
||||
return surface->hdr_reference_luminance;
|
||||
}
|
||||
|
||||
void RenderingContextDriverMetal::surface_set_hdr_output_min_luminance(SurfaceID p_surface, float p_min_luminance) {
|
||||
Surface *surface = (Surface *)(p_surface);
|
||||
surface->hdr_min_luminance = p_min_luminance;
|
||||
}
|
||||
|
||||
float RenderingContextDriverMetal::surface_get_hdr_output_min_luminance(SurfaceID p_surface) const {
|
||||
Surface *surface = (Surface *)(p_surface);
|
||||
return surface->hdr_min_luminance;
|
||||
}
|
||||
|
||||
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;
|
||||
|
|
|
|||
|
|
@ -222,6 +222,7 @@ public:
|
|||
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 void swap_chain_set_max_fps(SwapChainID p_swap_chain, int p_max_fps) 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
|
||||
|
|
|
|||
|
|
@ -1029,6 +1029,10 @@ void RenderingDeviceDriverMetal::swap_chain_set_max_fps(SwapChainID p_swap_chain
|
|||
metal_surface->set_max_fps(p_max_fps);
|
||||
}
|
||||
|
||||
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);
|
||||
|
|
@ -2045,6 +2049,7 @@ Vector<uint8_t> RenderingDeviceDriverMetal::shader_compile_binary_from_spirv(Vec
|
|||
|
||||
#if TARGET_OS_IPHONE
|
||||
msl_options.ios_use_simdgroup_functions = (*device_properties).features.simdPermute;
|
||||
msl_options.ios_support_base_vertex_instance = true;
|
||||
#endif
|
||||
|
||||
bool disable_argument_buffers = false;
|
||||
|
|
|
|||
|
|
@ -436,6 +436,9 @@ Error RenderingContextDriverVulkan::_initialize_instance_extensions() {
|
|||
// This extension allows us to use the properties2 features to query additional device capabilities.
|
||||
_register_requested_instance_extension(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, false);
|
||||
|
||||
// This extension allows us to use colorspaces other than SRGB.
|
||||
_register_requested_instance_extension(VK_EXT_SWAPCHAIN_COLOR_SPACE_EXTENSION_NAME, false);
|
||||
|
||||
#if defined(USE_VOLK) && (defined(MACOS_ENABLED) || defined(IOS_ENABLED))
|
||||
_register_requested_instance_extension(VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME, true);
|
||||
#endif
|
||||
|
|
@ -991,6 +994,58 @@ 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_prefer_high_precision(SurfaceID p_surface, bool p_enabled) {
|
||||
Surface *surface = (Surface *)(p_surface);
|
||||
surface->hdr_prefer_high_precision = p_enabled;
|
||||
surface->needs_resize = true;
|
||||
}
|
||||
|
||||
bool RenderingContextDriverVulkan::surface_get_hdr_output_prefer_high_precision(SurfaceID p_surface) const {
|
||||
Surface *surface = (Surface *)(p_surface);
|
||||
return surface->hdr_prefer_high_precision;
|
||||
}
|
||||
|
||||
void RenderingContextDriverVulkan::surface_set_hdr_output_reference_luminance(SurfaceID p_surface, float p_reference_luminance) {
|
||||
Surface *surface = (Surface *)(p_surface);
|
||||
surface->hdr_reference_luminance = p_reference_luminance;
|
||||
}
|
||||
|
||||
float RenderingContextDriverVulkan::surface_get_hdr_output_reference_luminance(SurfaceID p_surface) const {
|
||||
Surface *surface = (Surface *)(p_surface);
|
||||
return surface->hdr_reference_luminance;
|
||||
}
|
||||
|
||||
void RenderingContextDriverVulkan::surface_set_hdr_output_min_luminance(SurfaceID p_surface, float p_min_luminance) {
|
||||
Surface *surface = (Surface *)(p_surface);
|
||||
surface->hdr_min_luminance = p_min_luminance;
|
||||
}
|
||||
|
||||
float RenderingContextDriverVulkan::surface_get_hdr_output_min_luminance(SurfaceID p_surface) const {
|
||||
Surface *surface = (Surface *)(p_surface);
|
||||
return surface->hdr_min_luminance;
|
||||
}
|
||||
|
||||
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;
|
||||
|
|
@ -1021,6 +1076,10 @@ bool RenderingContextDriverVulkan::is_debug_utils_enabled() const {
|
|||
return enabled_instance_extension_names.has(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
|
||||
}
|
||||
|
||||
bool RenderingContextDriverVulkan::is_colorspace_supported() const {
|
||||
return enabled_instance_extension_names.has(VK_EXT_SWAPCHAIN_COLOR_SPACE_EXTENSION_NAME);
|
||||
}
|
||||
|
||||
VkInstance RenderingContextDriverVulkan::instance_get() const {
|
||||
return instance;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -139,12 +139,23 @@ public:
|
|||
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_prefer_high_precision(SurfaceID p_surface, bool p_enabled) override;
|
||||
virtual bool surface_get_hdr_output_prefer_high_precision(SurfaceID p_surface) const override;
|
||||
virtual void surface_set_hdr_output_reference_luminance(SurfaceID p_surface, float p_reference_luminance) override;
|
||||
virtual float surface_get_hdr_output_reference_luminance(SurfaceID p_surface) const override;
|
||||
virtual void surface_set_hdr_output_min_luminance(SurfaceID p_surface, float p_min_luminance) override;
|
||||
virtual float surface_get_hdr_output_min_luminance(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;
|
||||
virtual bool surface_get_needs_resize(SurfaceID p_surface) const override;
|
||||
virtual void surface_destroy(SurfaceID p_surface) override;
|
||||
virtual bool is_debug_utils_enabled() const override;
|
||||
bool is_colorspace_supported() const;
|
||||
|
||||
// Vulkan-only methods.
|
||||
struct Surface {
|
||||
|
|
@ -153,6 +164,12 @@ public:
|
|||
uint32_t height = 0;
|
||||
DisplayServer::VSyncMode vsync_mode = DisplayServer::VSYNC_ENABLED;
|
||||
bool needs_resize = false;
|
||||
|
||||
bool hdr_output = false;
|
||||
bool hdr_prefer_high_precision = false;
|
||||
float hdr_reference_luminance = 0.0f;
|
||||
float hdr_min_luminance = 0.0f;
|
||||
float hdr_max_luminance = 0.0f;
|
||||
};
|
||||
|
||||
VkInstance instance_get() const;
|
||||
|
|
|
|||
|
|
@ -2862,6 +2862,99 @@ void RenderingDeviceDriverVulkan::command_buffer_execute_secondary(CommandBuffer
|
|||
/**** SWAP CHAIN ****/
|
||||
/********************/
|
||||
|
||||
struct FormatCandidate {
|
||||
VkFormat format;
|
||||
VkColorSpaceKHR colorspace;
|
||||
};
|
||||
|
||||
bool RenderingDeviceDriverVulkan::_determine_swap_chain_format(RenderingContextDriver::SurfaceID p_surface, VkFormat &r_format, VkColorSpaceKHR &r_color_space) {
|
||||
DEV_ASSERT(p_surface != 0);
|
||||
|
||||
RenderingContextDriverVulkan::Surface *surface = (RenderingContextDriverVulkan::Surface *)(p_surface);
|
||||
const RenderingContextDriverVulkan::Functions &functions = context_driver->functions_get();
|
||||
|
||||
// Retrieve the formats supported by the surface.
|
||||
uint32_t format_count = 0;
|
||||
VkResult err = functions.GetPhysicalDeviceSurfaceFormatsKHR(physical_device, surface->vk_surface, &format_count, nullptr);
|
||||
ERR_FAIL_COND_V(err != VK_SUCCESS, false);
|
||||
|
||||
TightLocalVector<VkSurfaceFormatKHR> formats;
|
||||
formats.resize(format_count);
|
||||
err = functions.GetPhysicalDeviceSurfaceFormatsKHR(physical_device, surface->vk_surface, &format_count, formats.ptr());
|
||||
ERR_FAIL_COND_V(err != VK_SUCCESS, false);
|
||||
|
||||
// If the format list includes just one entry of VK_FORMAT_UNDEFINED, the surface has no preferred format.
|
||||
if (format_count == 1 && formats[0].format == VK_FORMAT_UNDEFINED) {
|
||||
r_format = VK_FORMAT_B8G8R8A8_UNORM;
|
||||
r_color_space = formats[0].colorSpace;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool colorspace_supported = context_driver->is_colorspace_supported();
|
||||
bool hdr_output_requested = context_driver->surface_get_hdr_output_enabled(p_surface);
|
||||
bool high_precision_requested = context_driver->surface_get_hdr_output_prefer_high_precision(p_surface);
|
||||
|
||||
// Determine which formats to prefer based on the requested capabilities.
|
||||
LocalVector<FormatCandidate> preferred_formats = LocalVector<FormatCandidate>();
|
||||
preferred_formats.reserve(5);
|
||||
|
||||
// If the surface requests HDR output, try to get an HDR format.
|
||||
if (hdr_output_requested && colorspace_supported) {
|
||||
if (high_precision_requested) {
|
||||
// If high precision is requested, add the high precision format to the top.
|
||||
preferred_formats.push_back({ VK_FORMAT_R16G16B16A16_SFLOAT, VK_COLOR_SPACE_EXTENDED_SRGB_LINEAR_EXT });
|
||||
|
||||
// Followed by the HDR10 formats
|
||||
preferred_formats.push_back({ VK_FORMAT_A2B10G10R10_UNORM_PACK32, VK_COLOR_SPACE_HDR10_ST2084_EXT });
|
||||
preferred_formats.push_back({ VK_FORMAT_A2R10G10B10_UNORM_PACK32, VK_COLOR_SPACE_HDR10_ST2084_EXT });
|
||||
} else {
|
||||
// Otherwise add the HDR10 formats to the top.
|
||||
preferred_formats.push_back({ VK_FORMAT_A2B10G10R10_UNORM_PACK32, VK_COLOR_SPACE_HDR10_ST2084_EXT });
|
||||
preferred_formats.push_back({ VK_FORMAT_A2R10G10B10_UNORM_PACK32, VK_COLOR_SPACE_HDR10_ST2084_EXT });
|
||||
|
||||
// Followed by the high precision format for devices that don't support HDR 10.
|
||||
preferred_formats.push_back({ VK_FORMAT_R16G16B16A16_SFLOAT, VK_COLOR_SPACE_EXTENDED_SRGB_LINEAR_EXT });
|
||||
}
|
||||
}
|
||||
|
||||
// These formats are always considered for SDR.
|
||||
preferred_formats.push_back({ VK_FORMAT_B8G8R8A8_UNORM, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR });
|
||||
preferred_formats.push_back({ VK_FORMAT_R8G8B8A8_UNORM, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR });
|
||||
|
||||
bool found = false;
|
||||
for (const FormatCandidate &candidate : preferred_formats) {
|
||||
for (uint32_t i = 0; i < format_count; i++) {
|
||||
if (formats[i].format == candidate.format && formats[i].colorSpace == candidate.colorspace) {
|
||||
r_format = formats[i].format;
|
||||
r_color_space = formats[i].colorSpace;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (found) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Warnings for when HDR capabilities are requested but not found.
|
||||
if (hdr_output_requested) {
|
||||
if (!colorspace_supported) {
|
||||
WARN_PRINT("HDR output requested but the vulkan driver does not support VK_EXT_swapchain_colorspace, falling back to SDR.");
|
||||
}
|
||||
|
||||
if (high_precision_requested && r_format != VK_FORMAT_R16G16B16A16_SFLOAT) {
|
||||
WARN_PRINT("HDR output requested with high precision but no high precision format was found.");
|
||||
}
|
||||
|
||||
if (r_color_space == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) {
|
||||
WARN_PRINT("HDR output requested but no HDR compatible format was found, falling back to SDR.");
|
||||
}
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
void RenderingDeviceDriverVulkan::_swap_chain_release(SwapChain *swap_chain) {
|
||||
// Destroy views and framebuffers associated to the swapchain's images.
|
||||
for (FramebufferID framebuffer : swap_chain->framebuffers) {
|
||||
|
|
@ -2890,6 +2983,11 @@ void RenderingDeviceDriverVulkan::_swap_chain_release(SwapChain *swap_chain) {
|
|||
swap_chain->vk_swapchain = VK_NULL_HANDLE;
|
||||
}
|
||||
|
||||
if (swap_chain->render_pass.id != 0) {
|
||||
vkDestroyRenderPass(vk_device, VkRenderPass(swap_chain->render_pass.id), VKC::get_allocation_callbacks(VK_OBJECT_TYPE_RENDER_PASS));
|
||||
swap_chain->render_pass = RenderPassID();
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < swap_chain->command_queues_acquired.size(); i++) {
|
||||
_recreate_image_semaphore(swap_chain->command_queues_acquired[i], swap_chain->command_queues_acquired_semaphores[i], false);
|
||||
}
|
||||
|
|
@ -2901,81 +2999,9 @@ void RenderingDeviceDriverVulkan::_swap_chain_release(SwapChain *swap_chain) {
|
|||
RenderingDeviceDriver::SwapChainID RenderingDeviceDriverVulkan::swap_chain_create(RenderingContextDriver::SurfaceID p_surface) {
|
||||
DEV_ASSERT(p_surface != 0);
|
||||
|
||||
RenderingContextDriverVulkan::Surface *surface = (RenderingContextDriverVulkan::Surface *)(p_surface);
|
||||
const RenderingContextDriverVulkan::Functions &functions = context_driver->functions_get();
|
||||
|
||||
// Retrieve the formats supported by the surface.
|
||||
uint32_t format_count = 0;
|
||||
VkResult err = functions.GetPhysicalDeviceSurfaceFormatsKHR(physical_device, surface->vk_surface, &format_count, nullptr);
|
||||
ERR_FAIL_COND_V(err != VK_SUCCESS, SwapChainID());
|
||||
|
||||
TightLocalVector<VkSurfaceFormatKHR> formats;
|
||||
formats.resize(format_count);
|
||||
err = functions.GetPhysicalDeviceSurfaceFormatsKHR(physical_device, surface->vk_surface, &format_count, formats.ptr());
|
||||
ERR_FAIL_COND_V(err != VK_SUCCESS, SwapChainID());
|
||||
|
||||
VkFormat format = VK_FORMAT_UNDEFINED;
|
||||
VkColorSpaceKHR color_space = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR;
|
||||
if (format_count == 1 && formats[0].format == VK_FORMAT_UNDEFINED) {
|
||||
// If the format list includes just one entry of VK_FORMAT_UNDEFINED, the surface has no preferred format.
|
||||
format = VK_FORMAT_B8G8R8A8_UNORM;
|
||||
color_space = formats[0].colorSpace;
|
||||
} else if (format_count > 0) {
|
||||
// Use one of the supported formats, prefer B8G8R8A8_UNORM.
|
||||
const VkFormat preferred_format = VK_FORMAT_B8G8R8A8_UNORM;
|
||||
const VkFormat second_format = VK_FORMAT_R8G8B8A8_UNORM;
|
||||
for (uint32_t i = 0; i < format_count; i++) {
|
||||
if (formats[i].format == preferred_format || formats[i].format == second_format) {
|
||||
format = formats[i].format;
|
||||
if (formats[i].format == preferred_format) {
|
||||
// This is the preferred format, stop searching.
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// No formats are supported.
|
||||
ERR_FAIL_COND_V_MSG(format == VK_FORMAT_UNDEFINED, SwapChainID(), "Surface did not return any valid formats.");
|
||||
|
||||
// Create the render pass for the chosen format.
|
||||
VkAttachmentDescription2KHR attachment = {};
|
||||
attachment.sType = VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2_KHR;
|
||||
attachment.format = format;
|
||||
attachment.samples = VK_SAMPLE_COUNT_1_BIT;
|
||||
attachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
|
||||
attachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
|
||||
attachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
||||
attachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
||||
attachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
attachment.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
|
||||
|
||||
VkAttachmentReference2KHR color_reference = {};
|
||||
color_reference.sType = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2_KHR;
|
||||
color_reference.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||
|
||||
VkSubpassDescription2KHR subpass = {};
|
||||
subpass.sType = VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2_KHR;
|
||||
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
|
||||
subpass.colorAttachmentCount = 1;
|
||||
subpass.pColorAttachments = &color_reference;
|
||||
|
||||
VkRenderPassCreateInfo2KHR pass_info = {};
|
||||
pass_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2_KHR;
|
||||
pass_info.attachmentCount = 1;
|
||||
pass_info.pAttachments = &attachment;
|
||||
pass_info.subpassCount = 1;
|
||||
pass_info.pSubpasses = &subpass;
|
||||
|
||||
VkRenderPass render_pass = VK_NULL_HANDLE;
|
||||
err = _create_render_pass(vk_device, &pass_info, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_RENDER_PASS), &render_pass);
|
||||
ERR_FAIL_COND_V(err != VK_SUCCESS, SwapChainID());
|
||||
|
||||
// Create an empty swap chain until it is resized.
|
||||
SwapChain *swap_chain = memnew(SwapChain);
|
||||
swap_chain->surface = p_surface;
|
||||
swap_chain->format = format;
|
||||
swap_chain->color_space = color_space;
|
||||
swap_chain->render_pass = RenderPassID(render_pass);
|
||||
return SwapChainID(swap_chain);
|
||||
}
|
||||
|
||||
|
|
@ -3109,6 +3135,16 @@ Error RenderingDeviceDriverVulkan::swap_chain_resize(CommandQueueID p_cmd_queue,
|
|||
has_comp_alpha[(uint64_t)p_cmd_queue.id] = (composite_alpha != VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR);
|
||||
}
|
||||
|
||||
// Determine the format and color space for the swap chain.
|
||||
VkFormat format = VK_FORMAT_UNDEFINED;
|
||||
VkColorSpaceKHR color_space = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR;
|
||||
if (!_determine_swap_chain_format(swap_chain->surface, format, color_space)) {
|
||||
ERR_FAIL_V_MSG(ERR_CANT_CREATE, "Surface did not return any valid formats.");
|
||||
} else {
|
||||
swap_chain->format = format;
|
||||
swap_chain->color_space = color_space;
|
||||
}
|
||||
|
||||
VkSwapchainCreateInfoKHR swap_create_info = {};
|
||||
swap_create_info.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
|
||||
swap_create_info.surface = surface->vk_surface;
|
||||
|
|
@ -3207,9 +3243,45 @@ Error RenderingDeviceDriverVulkan::swap_chain_resize(CommandQueueID p_cmd_queue,
|
|||
|
||||
swap_chain->framebuffers.reserve(image_count);
|
||||
|
||||
// Create the render pass for the chosen format.
|
||||
VkAttachmentDescription2KHR attachment = {};
|
||||
attachment.sType = VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2_KHR;
|
||||
attachment.format = format;
|
||||
attachment.samples = VK_SAMPLE_COUNT_1_BIT;
|
||||
attachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
|
||||
attachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
|
||||
attachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
||||
attachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
||||
attachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
attachment.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
|
||||
|
||||
VkAttachmentReference2KHR color_reference = {};
|
||||
color_reference.sType = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2_KHR;
|
||||
color_reference.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||
|
||||
VkSubpassDescription2KHR subpass = {};
|
||||
subpass.sType = VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2_KHR;
|
||||
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
|
||||
subpass.colorAttachmentCount = 1;
|
||||
subpass.pColorAttachments = &color_reference;
|
||||
|
||||
VkRenderPassCreateInfo2KHR pass_info = {};
|
||||
pass_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2_KHR;
|
||||
pass_info.attachmentCount = 1;
|
||||
pass_info.pAttachments = &attachment;
|
||||
pass_info.subpassCount = 1;
|
||||
pass_info.pSubpasses = &subpass;
|
||||
|
||||
VkRenderPass render_pass = VK_NULL_HANDLE;
|
||||
err = _create_render_pass(vk_device, &pass_info, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_RENDER_PASS), &render_pass);
|
||||
ERR_FAIL_COND_V(err != VK_SUCCESS, ERR_CANT_CREATE);
|
||||
|
||||
DEV_ASSERT(swap_chain->render_pass.id == 0);
|
||||
swap_chain->render_pass = RenderPassID(render_pass);
|
||||
|
||||
VkFramebufferCreateInfo fb_create_info = {};
|
||||
fb_create_info.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
|
||||
fb_create_info.renderPass = VkRenderPass(swap_chain->render_pass.id);
|
||||
fb_create_info.renderPass = render_pass;
|
||||
fb_create_info.attachmentCount = 1;
|
||||
fb_create_info.width = surface->width;
|
||||
fb_create_info.height = surface->height;
|
||||
|
|
@ -3322,6 +3394,12 @@ RDD::DataFormat RenderingDeviceDriverVulkan::swap_chain_get_format(SwapChainID p
|
|||
return DATA_FORMAT_B8G8R8A8_UNORM;
|
||||
case VK_FORMAT_R8G8B8A8_UNORM:
|
||||
return DATA_FORMAT_R8G8B8A8_UNORM;
|
||||
case VK_FORMAT_A2B10G10R10_UNORM_PACK32:
|
||||
return DATA_FORMAT_A2B10G10R10_UNORM_PACK32;
|
||||
case VK_FORMAT_A2R10G10B10_UNORM_PACK32:
|
||||
return DATA_FORMAT_A2R10G10B10_UNORM_PACK32;
|
||||
case VK_FORMAT_R16G16B16A16_SFLOAT:
|
||||
return DATA_FORMAT_R16G16B16A16_SFLOAT;
|
||||
default:
|
||||
DEV_ASSERT(false && "Unknown swap chain format.");
|
||||
return DATA_FORMAT_MAX;
|
||||
|
|
@ -3344,16 +3422,29 @@ void RenderingDeviceDriverVulkan::swap_chain_set_max_fps(SwapChainID p_swap_chai
|
|||
#endif
|
||||
}
|
||||
|
||||
RDD::ColorSpace RenderingDeviceDriverVulkan::swap_chain_get_color_space(SwapChainID p_swap_chain) {
|
||||
DEV_ASSERT(p_swap_chain.id != 0);
|
||||
|
||||
SwapChain *swap_chain = (SwapChain *)(p_swap_chain.id);
|
||||
switch (swap_chain->color_space) {
|
||||
case VK_COLOR_SPACE_SRGB_NONLINEAR_KHR:
|
||||
return COLOR_SPACE_SRGB_NONLINEAR;
|
||||
case VK_COLOR_SPACE_HDR10_ST2084_EXT:
|
||||
return COLOR_SPACE_HDR10_ST2084;
|
||||
case VK_COLOR_SPACE_EXTENDED_SRGB_LINEAR_EXT:
|
||||
return COLOR_SPACE_SRGB_LINEAR;
|
||||
default:
|
||||
DEV_ASSERT(false && "Unknown swap chain color space.");
|
||||
return COLOR_SPACE_MAX;
|
||||
}
|
||||
}
|
||||
|
||||
void RenderingDeviceDriverVulkan::swap_chain_free(SwapChainID p_swap_chain) {
|
||||
DEV_ASSERT(p_swap_chain.id != 0);
|
||||
|
||||
SwapChain *swap_chain = (SwapChain *)(p_swap_chain.id);
|
||||
_swap_chain_release(swap_chain);
|
||||
|
||||
if (swap_chain->render_pass.id != 0) {
|
||||
vkDestroyRenderPass(vk_device, VkRenderPass(swap_chain->render_pass.id), VKC::get_allocation_callbacks(VK_OBJECT_TYPE_RENDER_PASS));
|
||||
}
|
||||
|
||||
memdelete(swap_chain);
|
||||
}
|
||||
|
||||
|
|
@ -5951,6 +6042,8 @@ bool RenderingDeviceDriverVulkan::has_feature(Features p_feature) {
|
|||
return true;
|
||||
case SUPPORTS_BUFFER_DEVICE_ADDRESS:
|
||||
return buffer_device_address_support;
|
||||
case SUPPORTS_HDR_OUTPUT:
|
||||
return context_driver->is_colorspace_supported();
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -370,6 +370,7 @@ private:
|
|||
#endif
|
||||
};
|
||||
|
||||
bool _determine_swap_chain_format(RenderingContextDriver::SurfaceID p_surface, VkFormat &r_format, VkColorSpaceKHR &r_color_space);
|
||||
void _swap_chain_release(SwapChain *p_swap_chain);
|
||||
|
||||
public:
|
||||
|
|
@ -380,6 +381,7 @@ public:
|
|||
virtual int swap_chain_get_pre_rotation_degrees(SwapChainID p_swap_chain) override final;
|
||||
virtual DataFormat swap_chain_get_format(SwapChainID p_swap_chain) override final;
|
||||
virtual void swap_chain_set_max_fps(SwapChainID p_swap_chain, int p_max_fps) 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;
|
||||
|
||||
/*********************/
|
||||
|
|
|
|||
|
|
@ -412,6 +412,27 @@ void EditorNode::_update_from_settings() {
|
|||
scene_root->set_default_canvas_item_texture_repeat(tr);
|
||||
}
|
||||
|
||||
// Enable HDR if requested and available.
|
||||
if (DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_HDR) && RD::get_singleton()->has_feature(RD::Features::SUPPORTS_HDR_OUTPUT)) {
|
||||
bool hdr_enabled = GLOBAL_GET("display/window/hdr/enabled");
|
||||
bool prefer_high_precision = GLOBAL_GET("display/window/hdr/prefer_high_precision");
|
||||
bool use_screen_luminance = GLOBAL_GET("display/window/hdr/use_screen_luminance");
|
||||
|
||||
DisplayServer::get_singleton()->window_set_hdr_output_enabled(hdr_enabled);
|
||||
DisplayServer::get_singleton()->window_set_hdr_output_prefer_high_precision(prefer_high_precision);
|
||||
DisplayServer::get_singleton()->window_set_hdr_output_use_screen_luminance(use_screen_luminance);
|
||||
|
||||
if (!use_screen_luminance) {
|
||||
float reference_luminance = GLOBAL_GET("display/window/hdr/reference_luminance");
|
||||
float min_luminance = GLOBAL_GET("display/window/hdr/min_luminance");
|
||||
float max_luminance = GLOBAL_GET("display/window/hdr/max_luminance");
|
||||
|
||||
DisplayServer::get_singleton()->window_set_hdr_output_reference_luminance(reference_luminance);
|
||||
DisplayServer::get_singleton()->window_set_hdr_output_min_luminance(min_luminance);
|
||||
DisplayServer::get_singleton()->window_set_hdr_output_max_luminance(max_luminance);
|
||||
}
|
||||
}
|
||||
|
||||
RS::DOFBokehShape dof_shape = RS::DOFBokehShape(int(GLOBAL_GET("rendering/camera/depth_of_field/depth_of_field_bokeh_shape")));
|
||||
RS::get_singleton()->camera_attributes_set_dof_blur_bokeh_shape(dof_shape);
|
||||
RS::DOFBlurQuality dof_quality = RS::DOFBlurQuality(int(GLOBAL_GET("rendering/camera/depth_of_field/depth_of_field_bokeh_quality")));
|
||||
|
|
@ -470,6 +491,10 @@ void EditorNode::_update_from_settings() {
|
|||
scene_root->set_use_hdr_2d(use_hdr_2d);
|
||||
get_viewport()->set_use_hdr_2d(use_hdr_2d);
|
||||
|
||||
const bool tonemap_to_window = GLOBAL_GET("rendering/viewport/tonemap_to_window");
|
||||
scene_root->set_tonemap_to_window(tonemap_to_window);
|
||||
get_viewport()->set_tonemap_to_window(tonemap_to_window);
|
||||
|
||||
float mesh_lod_threshold = GLOBAL_GET("rendering/mesh_lod/lod_change/threshold_pixels");
|
||||
scene_root->set_mesh_lod_threshold(mesh_lod_threshold);
|
||||
|
||||
|
|
|
|||
|
|
@ -2875,6 +2875,9 @@ void Node3DEditorViewport::_project_settings_changed() {
|
|||
const bool use_hdr_2d = GLOBAL_GET("rendering/viewport/hdr_2d");
|
||||
viewport->set_use_hdr_2d(use_hdr_2d);
|
||||
|
||||
const bool tonemap_to_window = GLOBAL_GET("rendering/viewport/tonemap_to_window");
|
||||
viewport->set_tonemap_to_window(tonemap_to_window);
|
||||
|
||||
const bool use_debanding = GLOBAL_GET("rendering/anti_aliasing/quality/use_debanding");
|
||||
viewport->set_use_debanding(use_debanding);
|
||||
|
||||
|
|
|
|||
|
|
@ -3237,6 +3237,27 @@ Error Main::setup2(bool p_show_boot_logo) {
|
|||
}
|
||||
}
|
||||
|
||||
// Enable HDR if requested and available.
|
||||
if (DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_HDR) && RD::get_singleton()->has_feature(RD::Features::SUPPORTS_HDR_OUTPUT)) {
|
||||
bool hdr_enabled = GLOBAL_GET("display/window/hdr/enabled");
|
||||
bool prefer_high_precision = GLOBAL_GET("display/window/hdr/prefer_high_precision");
|
||||
bool use_screen_luminance = GLOBAL_GET("display/window/hdr/use_screen_luminance");
|
||||
|
||||
DisplayServer::get_singleton()->window_set_hdr_output_enabled(hdr_enabled);
|
||||
DisplayServer::get_singleton()->window_set_hdr_output_prefer_high_precision(prefer_high_precision);
|
||||
DisplayServer::get_singleton()->window_set_hdr_output_use_screen_luminance(use_screen_luminance);
|
||||
|
||||
if (!use_screen_luminance) {
|
||||
float reference_luminance = GLOBAL_GET("display/window/hdr/reference_luminance");
|
||||
float min_luminance = GLOBAL_GET("display/window/hdr/min_luminance");
|
||||
float max_luminance = GLOBAL_GET("display/window/hdr/max_luminance");
|
||||
|
||||
DisplayServer::get_singleton()->window_set_hdr_output_reference_luminance(reference_luminance);
|
||||
DisplayServer::get_singleton()->window_set_hdr_output_min_luminance(min_luminance);
|
||||
DisplayServer::get_singleton()->window_set_hdr_output_max_luminance(max_luminance);
|
||||
}
|
||||
}
|
||||
|
||||
Color clear = GLOBAL_DEF_BASIC("rendering/environment/defaults/default_clear_color", Color(0.3, 0.3, 0.3));
|
||||
RenderingServer::get_singleton()->set_default_clear_color(clear);
|
||||
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
if interface and interface.initialize():
|
||||
get_viewport().use_xr = true
|
||||
[/codeblock]
|
||||
[b]Note:[/b] For Android, [member ProjectSettings.input_devices/sensors/enable_accelerometer], [member ProjectSettings.input_devices/sensors/enable_gravity], [member ProjectSettings.input_devices/sensors/enable_gyroscope] and [member ProjectSettings.input_devices/sensors/enable_magnetometer] must be enabled.
|
||||
</description>
|
||||
<tutorials>
|
||||
</tutorials>
|
||||
|
|
|
|||
|
|
@ -135,7 +135,7 @@ typedef BOOL(WINAPI *LPFN_ISWOW64PROCESS)(HANDLE, PBOOL);
|
|||
BOOL is_wow64() {
|
||||
BOOL wow64 = FALSE;
|
||||
|
||||
LPFN_ISWOW64PROCESS fnIsWow64Process = (LPFN_ISWOW64PROCESS)GetProcAddress(GetModuleHandle(TEXT("kernel32")), "IsWow64Process");
|
||||
LPFN_ISWOW64PROCESS fnIsWow64Process = (LPFN_ISWOW64PROCESS)(void *)GetProcAddress(GetModuleHandle(TEXT("kernel32")), "IsWow64Process");
|
||||
|
||||
if (fnIsWow64Process) {
|
||||
if (!fnIsWow64Process(GetCurrentProcess(), &wow64)) {
|
||||
|
|
|
|||
|
|
@ -3641,10 +3641,10 @@ void OpenXRAPI::set_emulate_environment_blend_mode_alpha_blend(bool p_enabled) {
|
|||
}
|
||||
|
||||
OpenXRAPI::OpenXRAlphaBlendModeSupport OpenXRAPI::is_environment_blend_mode_alpha_blend_supported() {
|
||||
if (is_environment_blend_mode_supported(XR_ENVIRONMENT_BLEND_MODE_ALPHA_BLEND)) {
|
||||
return OPENXR_ALPHA_BLEND_MODE_SUPPORT_REAL;
|
||||
} else if (emulate_environment_blend_mode_alpha_blend) {
|
||||
if (emulate_environment_blend_mode_alpha_blend) {
|
||||
return OPENXR_ALPHA_BLEND_MODE_SUPPORT_EMULATING;
|
||||
} else if (is_environment_blend_mode_supported(XR_ENVIRONMENT_BLEND_MODE_ALPHA_BLEND)) {
|
||||
return OPENXR_ALPHA_BLEND_MODE_SUPPORT_REAL;
|
||||
}
|
||||
return OPENXR_ALPHA_BLEND_MODE_SUPPORT_NONE;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,13 +34,20 @@
|
|||
#include "editor/editor_interface.h"
|
||||
#include "editor/editor_node.h"
|
||||
#include "editor/plugins/game_view_plugin.h"
|
||||
|
||||
static GameViewPlugin *_get_game_view_plugin() {
|
||||
ERR_FAIL_NULL_V(EditorNode::get_singleton(), nullptr);
|
||||
ERR_FAIL_NULL_V(EditorNode::get_singleton()->get_editor_main_screen(), nullptr);
|
||||
return Object::cast_to<GameViewPlugin>(EditorNode::get_singleton()->get_editor_main_screen()->get_plugin_by_name("Game"));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
extern "C" {
|
||||
|
||||
JNIEXPORT void JNICALL Java_org_godotengine_godot_utils_GameMenuUtils_setSuspend(JNIEnv *env, jclass clazz, jboolean enabled) {
|
||||
#ifdef TOOLS_ENABLED
|
||||
GameViewPlugin *game_view_plugin = Object::cast_to<GameViewPlugin>(EditorNode::get_singleton()->get_editor_main_screen()->get_plugin_by_name("Game"));
|
||||
GameViewPlugin *game_view_plugin = _get_game_view_plugin();
|
||||
if (game_view_plugin != nullptr && game_view_plugin->get_debugger().is_valid()) {
|
||||
game_view_plugin->get_debugger()->set_suspend(enabled);
|
||||
}
|
||||
|
|
@ -49,7 +56,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_utils_GameMenuUtils_setSuspend
|
|||
|
||||
JNIEXPORT void JNICALL Java_org_godotengine_godot_utils_GameMenuUtils_nextFrame(JNIEnv *env, jclass clazz) {
|
||||
#ifdef TOOLS_ENABLED
|
||||
GameViewPlugin *game_view_plugin = Object::cast_to<GameViewPlugin>(EditorNode::get_singleton()->get_editor_main_screen()->get_plugin_by_name("Game"));
|
||||
GameViewPlugin *game_view_plugin = _get_game_view_plugin();
|
||||
if (game_view_plugin != nullptr && game_view_plugin->get_debugger().is_valid()) {
|
||||
game_view_plugin->get_debugger()->next_frame();
|
||||
}
|
||||
|
|
@ -58,7 +65,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_utils_GameMenuUtils_nextFrame(
|
|||
|
||||
JNIEXPORT void JNICALL Java_org_godotengine_godot_utils_GameMenuUtils_setNodeType(JNIEnv *env, jclass clazz, jint type) {
|
||||
#ifdef TOOLS_ENABLED
|
||||
GameViewPlugin *game_view_plugin = Object::cast_to<GameViewPlugin>(EditorNode::get_singleton()->get_editor_main_screen()->get_plugin_by_name("Game"));
|
||||
GameViewPlugin *game_view_plugin = _get_game_view_plugin();
|
||||
if (game_view_plugin != nullptr && game_view_plugin->get_debugger().is_valid()) {
|
||||
game_view_plugin->get_debugger()->set_node_type(type);
|
||||
}
|
||||
|
|
@ -67,7 +74,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_utils_GameMenuUtils_setNodeTyp
|
|||
|
||||
JNIEXPORT void JNICALL Java_org_godotengine_godot_utils_GameMenuUtils_setSelectMode(JNIEnv *env, jclass clazz, jint mode) {
|
||||
#ifdef TOOLS_ENABLED
|
||||
GameViewPlugin *game_view_plugin = Object::cast_to<GameViewPlugin>(EditorNode::get_singleton()->get_editor_main_screen()->get_plugin_by_name("Game"));
|
||||
GameViewPlugin *game_view_plugin = _get_game_view_plugin();
|
||||
if (game_view_plugin != nullptr && game_view_plugin->get_debugger().is_valid()) {
|
||||
game_view_plugin->get_debugger()->set_select_mode(mode);
|
||||
}
|
||||
|
|
@ -76,7 +83,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_utils_GameMenuUtils_setSelectM
|
|||
|
||||
JNIEXPORT void JNICALL Java_org_godotengine_godot_utils_GameMenuUtils_setSelectionVisible(JNIEnv *env, jclass clazz, jboolean visible) {
|
||||
#ifdef TOOLS_ENABLED
|
||||
GameViewPlugin *game_view_plugin = Object::cast_to<GameViewPlugin>(EditorNode::get_singleton()->get_editor_main_screen()->get_plugin_by_name("Game"));
|
||||
GameViewPlugin *game_view_plugin = _get_game_view_plugin();
|
||||
if (game_view_plugin != nullptr && game_view_plugin->get_debugger().is_valid()) {
|
||||
game_view_plugin->get_debugger()->set_selection_visible(visible);
|
||||
}
|
||||
|
|
@ -85,7 +92,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_utils_GameMenuUtils_setSelecti
|
|||
|
||||
JNIEXPORT void JNICALL Java_org_godotengine_godot_utils_GameMenuUtils_setCameraOverride(JNIEnv *env, jclass clazz, jboolean enabled) {
|
||||
#ifdef TOOLS_ENABLED
|
||||
GameViewPlugin *game_view_plugin = Object::cast_to<GameViewPlugin>(EditorNode::get_singleton()->get_editor_main_screen()->get_plugin_by_name("Game"));
|
||||
GameViewPlugin *game_view_plugin = _get_game_view_plugin();
|
||||
if (game_view_plugin != nullptr && game_view_plugin->get_debugger().is_valid()) {
|
||||
game_view_plugin->get_debugger()->set_camera_override(enabled);
|
||||
}
|
||||
|
|
@ -94,7 +101,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_utils_GameMenuUtils_setCameraO
|
|||
|
||||
JNIEXPORT void JNICALL Java_org_godotengine_godot_utils_GameMenuUtils_setCameraManipulateMode(JNIEnv *env, jclass clazz, jint mode) {
|
||||
#ifdef TOOLS_ENABLED
|
||||
GameViewPlugin *game_view_plugin = Object::cast_to<GameViewPlugin>(EditorNode::get_singleton()->get_editor_main_screen()->get_plugin_by_name("Game"));
|
||||
GameViewPlugin *game_view_plugin = _get_game_view_plugin();
|
||||
if (game_view_plugin != nullptr && game_view_plugin->get_debugger().is_valid()) {
|
||||
game_view_plugin->get_debugger()->set_camera_manipulate_mode(static_cast<EditorDebuggerNode::CameraOverride>(mode));
|
||||
}
|
||||
|
|
@ -103,7 +110,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_utils_GameMenuUtils_setCameraM
|
|||
|
||||
JNIEXPORT void JNICALL Java_org_godotengine_godot_utils_GameMenuUtils_resetCamera2DPosition(JNIEnv *env, jclass clazz) {
|
||||
#ifdef TOOLS_ENABLED
|
||||
GameViewPlugin *game_view_plugin = Object::cast_to<GameViewPlugin>(EditorNode::get_singleton()->get_editor_main_screen()->get_plugin_by_name("Game"));
|
||||
GameViewPlugin *game_view_plugin = _get_game_view_plugin();
|
||||
if (game_view_plugin != nullptr && game_view_plugin->get_debugger().is_valid()) {
|
||||
game_view_plugin->get_debugger()->reset_camera_2d_position();
|
||||
}
|
||||
|
|
@ -112,7 +119,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_utils_GameMenuUtils_resetCamer
|
|||
|
||||
JNIEXPORT void JNICALL Java_org_godotengine_godot_utils_GameMenuUtils_resetCamera3DPosition(JNIEnv *env, jclass clazz) {
|
||||
#ifdef TOOLS_ENABLED
|
||||
GameViewPlugin *game_view_plugin = Object::cast_to<GameViewPlugin>(EditorNode::get_singleton()->get_editor_main_screen()->get_plugin_by_name("Game"));
|
||||
GameViewPlugin *game_view_plugin = _get_game_view_plugin();
|
||||
if (game_view_plugin != nullptr && game_view_plugin->get_debugger().is_valid()) {
|
||||
game_view_plugin->get_debugger()->reset_camera_3d_position();
|
||||
}
|
||||
|
|
@ -121,7 +128,9 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_utils_GameMenuUtils_resetCamer
|
|||
|
||||
JNIEXPORT void JNICALL Java_org_godotengine_godot_utils_GameMenuUtils_playMainScene(JNIEnv *env, jclass clazz) {
|
||||
#ifdef TOOLS_ENABLED
|
||||
EditorInterface::get_singleton()->play_main_scene();
|
||||
if (EditorInterface::get_singleton()) {
|
||||
EditorInterface::get_singleton()->play_main_scene();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2171,7 +2171,10 @@ void DisplayServerX11::window_set_current_screen(int p_screen, WindowID p_window
|
|||
return;
|
||||
}
|
||||
|
||||
ERR_FAIL_COND_MSG(wd.embed_parent, "Embedded window can't be moved to another screen.");
|
||||
if (wd.embed_parent) {
|
||||
print_line("Embedded window can't be moved to another screen.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (window_get_mode(p_window) == WINDOW_MODE_FULLSCREEN || window_get_mode(p_window) == WINDOW_MODE_MAXIMIZED) {
|
||||
Point2i position = screen_get_position(p_screen);
|
||||
|
|
@ -2330,7 +2333,10 @@ void DisplayServerX11::window_set_position(const Point2i &p_position, WindowID p
|
|||
ERR_FAIL_COND(!windows.has(p_window));
|
||||
WindowData &wd = windows[p_window];
|
||||
|
||||
ERR_FAIL_COND_MSG(wd.embed_parent, "Embedded window can't be moved.");
|
||||
if (wd.embed_parent) {
|
||||
print_line("Embedded window can't be moved.");
|
||||
return;
|
||||
}
|
||||
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
|
|
@ -2364,7 +2370,10 @@ void DisplayServerX11::window_set_max_size(const Size2i p_size, WindowID p_windo
|
|||
ERR_FAIL_COND(!windows.has(p_window));
|
||||
WindowData &wd = windows[p_window];
|
||||
|
||||
ERR_FAIL_COND_MSG(wd.embed_parent, "Embedded windows can't have a maximum size.");
|
||||
if (wd.embed_parent) {
|
||||
print_line("Embedded windows can't have a maximum size.");
|
||||
return;
|
||||
}
|
||||
|
||||
if ((p_size != Size2i()) && ((p_size.x < wd.min_size.x) || (p_size.y < wd.min_size.y))) {
|
||||
ERR_PRINT("Maximum window size can't be smaller than minimum window size!");
|
||||
|
|
@ -2391,7 +2400,10 @@ void DisplayServerX11::window_set_min_size(const Size2i p_size, WindowID p_windo
|
|||
ERR_FAIL_COND(!windows.has(p_window));
|
||||
WindowData &wd = windows[p_window];
|
||||
|
||||
ERR_FAIL_COND_MSG(wd.embed_parent, "Embedded windows can't have a minimum size.");
|
||||
if (wd.embed_parent) {
|
||||
print_line("Embedded windows can't have a minimum size.");
|
||||
return;
|
||||
}
|
||||
|
||||
if ((p_size != Size2i()) && (wd.max_size != Size2i()) && ((p_size.x > wd.max_size.x) || (p_size.y > wd.max_size.y))) {
|
||||
ERR_PRINT("Minimum window size can't be larger than maximum window size!");
|
||||
|
|
@ -2422,7 +2434,10 @@ void DisplayServerX11::window_set_size(const Size2i p_size, WindowID p_window) {
|
|||
|
||||
WindowData &wd = windows[p_window];
|
||||
|
||||
ERR_FAIL_COND_MSG(wd.embed_parent, "Embedded window can't be resized.");
|
||||
if (wd.embed_parent) {
|
||||
print_line("Embedded window can't be resized.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (wd.size.width == size.width && wd.size.height == size.height) {
|
||||
return;
|
||||
|
|
@ -2842,7 +2857,10 @@ void DisplayServerX11::window_set_mode(WindowMode p_mode, WindowID p_window) {
|
|||
return; // do nothing
|
||||
}
|
||||
|
||||
ERR_FAIL_COND_MSG(p_mode != WINDOW_MODE_WINDOWED && wd.embed_parent, "Embedded window only supports Windowed mode.");
|
||||
if (p_mode != WINDOW_MODE_WINDOWED && wd.embed_parent) {
|
||||
print_line("Embedded window only supports Windowed mode.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Remove all "extra" modes.
|
||||
switch (old_mode) {
|
||||
|
|
@ -2944,7 +2962,10 @@ void DisplayServerX11::window_set_flag(WindowFlags p_flag, bool p_enabled, Windo
|
|||
|
||||
switch (p_flag) {
|
||||
case WINDOW_FLAG_RESIZE_DISABLED: {
|
||||
ERR_FAIL_COND_MSG(p_enabled && wd.embed_parent, "Embedded window resize can't be disabled.");
|
||||
if (p_enabled && wd.embed_parent) {
|
||||
print_line("Embedded window resize can't be disabled.");
|
||||
return;
|
||||
}
|
||||
|
||||
wd.resize_disabled = p_enabled;
|
||||
_update_size_hints(p_window);
|
||||
|
|
@ -2971,7 +2992,10 @@ void DisplayServerX11::window_set_flag(WindowFlags p_flag, bool p_enabled, Windo
|
|||
} break;
|
||||
case WINDOW_FLAG_ALWAYS_ON_TOP: {
|
||||
ERR_FAIL_COND_MSG(wd.transient_parent != INVALID_WINDOW_ID, "Can't make a window transient if the 'on top' flag is active.");
|
||||
ERR_FAIL_COND_MSG(p_enabled && wd.embed_parent, "Embedded window can't become on top.");
|
||||
if (p_enabled && wd.embed_parent) {
|
||||
print_line("Embedded window can't become on top.");
|
||||
return;
|
||||
}
|
||||
if (p_enabled && wd.fullscreen) {
|
||||
_set_wm_maximized(p_window, true);
|
||||
}
|
||||
|
|
@ -3013,7 +3037,10 @@ void DisplayServerX11::window_set_flag(WindowFlags p_flag, bool p_enabled, Windo
|
|||
|
||||
ERR_FAIL_COND_MSG(p_window == MAIN_WINDOW_ID, "Main window can't be popup.");
|
||||
ERR_FAIL_COND_MSG((xwa.map_state == IsViewable) && (wd.is_popup != p_enabled), "Popup flag can't changed while window is opened.");
|
||||
ERR_FAIL_COND_MSG(p_enabled && wd.embed_parent, "Embedded window can't be popup.");
|
||||
if (p_enabled && wd.embed_parent) {
|
||||
print_line("Embedded window can't be popup.");
|
||||
return;
|
||||
}
|
||||
wd.is_popup = p_enabled;
|
||||
} break;
|
||||
default: {
|
||||
|
|
|
|||
|
|
@ -83,11 +83,6 @@
|
|||
|
||||
#define WM_INDICATOR_CALLBACK_MESSAGE (WM_USER + 1)
|
||||
|
||||
#if defined(__GNUC__)
|
||||
// Workaround GCC warning from -Wcast-function-type.
|
||||
#define GetProcAddress (void *)GetProcAddress
|
||||
#endif
|
||||
|
||||
static String format_error_message(DWORD id) {
|
||||
LPWSTR messageBuffer = nullptr;
|
||||
size_t size = FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
|
|
@ -141,6 +136,7 @@ bool DisplayServerWindows::has_feature(Feature p_feature) const {
|
|||
case FEATURE_WINDOW_EMBEDDING:
|
||||
case FEATURE_WINDOW_DRAG:
|
||||
case FEATURE_SCREEN_EXCLUDE_FROM_CAPTURE:
|
||||
case FEATURE_HDR:
|
||||
return true;
|
||||
case FEATURE_EMOJI_AND_SYMBOL_PICKER:
|
||||
return (os_ver.dwBuildNumber >= 17134); // Windows 10 Redstone 4 (1803)+ only.
|
||||
|
|
@ -1186,6 +1182,14 @@ typedef struct {
|
|||
float rate;
|
||||
} EnumRefreshRateData;
|
||||
|
||||
typedef struct {
|
||||
Vector<DISPLAYCONFIG_PATH_INFO> paths;
|
||||
Vector<DISPLAYCONFIG_MODE_INFO> modes;
|
||||
int count;
|
||||
int screen;
|
||||
float sdrWhiteLevelInNits;
|
||||
} EnumSdrWhiteLevelData;
|
||||
|
||||
static BOOL CALLBACK _MonitorEnumProcSize(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) {
|
||||
EnumSizeData *data = (EnumSizeData *)dwData;
|
||||
if (data->count == data->screen) {
|
||||
|
|
@ -1294,7 +1298,7 @@ static int QueryDpiForMonitor(HMONITOR hmon, _MonitorDpiType dpiType = MDT_Defau
|
|||
|
||||
if (Shcore == nullptr) {
|
||||
Shcore = LoadLibraryW(L"Shcore.dll");
|
||||
getDPIForMonitor = Shcore ? (GetDPIForMonitor_t)GetProcAddress(Shcore, "GetDpiForMonitor") : nullptr;
|
||||
getDPIForMonitor = Shcore ? (GetDPIForMonitor_t)(void *)GetProcAddress(Shcore, "GetDpiForMonitor") : nullptr;
|
||||
|
||||
if ((Shcore == nullptr) || (getDPIForMonitor == nullptr)) {
|
||||
if (Shcore) {
|
||||
|
|
@ -1496,6 +1500,172 @@ Ref<Image> DisplayServerWindows::screen_get_image_rect(const Rect2i &p_rect) con
|
|||
return img;
|
||||
}
|
||||
|
||||
#ifdef D3D12_ENABLED
|
||||
static bool _get_screen_desc(int p_screen, DXGI_OUTPUT_DESC1 &r_Desc) {
|
||||
ComPtr<IDXGIFactory4> dxgi_factory;
|
||||
r_Desc = {};
|
||||
|
||||
if (FAILED(CreateDXGIFactory2(0, IID_PPV_ARGS(&dxgi_factory)))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Retrieve the current default adapter.
|
||||
ComPtr<IDXGIAdapter1> dxgiAdapter;
|
||||
if (FAILED(dxgi_factory->EnumAdapters1(0, &dxgiAdapter))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
UINT i = 0;
|
||||
ComPtr<IDXGIOutput> screenOutput;
|
||||
while (dxgiAdapter->EnumOutputs(i, &screenOutput) != DXGI_ERROR_NOT_FOUND) {
|
||||
if (i == (UINT)p_screen) {
|
||||
break;
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
ComPtr<IDXGIOutput6> output6;
|
||||
if (FAILED(screenOutput.As(&output6))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
DXGI_OUTPUT_DESC1 desc1;
|
||||
if (FAILED(output6->GetDesc1(&desc1))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
r_Desc = desc1;
|
||||
return true;
|
||||
}
|
||||
#endif // D3D12_ENABLED
|
||||
|
||||
bool DisplayServerWindows::screen_is_hdr_supported(int p_screen) const {
|
||||
_THREAD_SAFE_METHOD_
|
||||
|
||||
p_screen = _get_screen_index(p_screen);
|
||||
#ifdef D3D12_ENABLED
|
||||
DXGI_OUTPUT_DESC1 desc1;
|
||||
if (!_get_screen_desc(p_screen, desc1)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return (desc1.ColorSpace == DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020);
|
||||
#else
|
||||
return false;
|
||||
#endif // D3D12_ENABLED
|
||||
}
|
||||
|
||||
float DisplayServerWindows::screen_get_min_luminance(int p_screen) const {
|
||||
_THREAD_SAFE_METHOD_
|
||||
|
||||
p_screen = _get_screen_index(p_screen);
|
||||
#ifdef D3D12_ENABLED
|
||||
DXGI_OUTPUT_DESC1 desc1;
|
||||
if (!_get_screen_desc(p_screen, desc1)) {
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
return desc1.MinLuminance;
|
||||
#else
|
||||
return 0.0f;
|
||||
#endif // D3D12_ENABLED
|
||||
}
|
||||
|
||||
float DisplayServerWindows::screen_get_max_luminance(int p_screen) const {
|
||||
_THREAD_SAFE_METHOD_
|
||||
|
||||
p_screen = _get_screen_index(p_screen);
|
||||
#ifdef D3D12_ENABLED
|
||||
DXGI_OUTPUT_DESC1 desc1;
|
||||
if (!_get_screen_desc(p_screen, desc1)) {
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
return desc1.MaxLuminance;
|
||||
#else
|
||||
return 0.0f;
|
||||
#endif // D3D12_ENABLED
|
||||
}
|
||||
|
||||
float DisplayServerWindows::screen_get_max_average_luminance(int p_screen) const {
|
||||
_THREAD_SAFE_METHOD_
|
||||
|
||||
p_screen = _get_screen_index(p_screen);
|
||||
#ifdef D3D12_ENABLED
|
||||
DXGI_OUTPUT_DESC1 desc1;
|
||||
if (!_get_screen_desc(p_screen, desc1)) {
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
return desc1.MaxFullFrameLuminance;
|
||||
#else
|
||||
return 0.0f;
|
||||
#endif // D3D12_ENABLED
|
||||
}
|
||||
|
||||
static BOOL CALLBACK _MonitorEnumProcSdrWhiteLevel(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) {
|
||||
EnumSdrWhiteLevelData *data = (EnumSdrWhiteLevelData *)dwData;
|
||||
if (data->count == data->screen) {
|
||||
MONITORINFOEXW minfo;
|
||||
memset(&minfo, 0, sizeof(minfo));
|
||||
minfo.cbSize = sizeof(minfo);
|
||||
GetMonitorInfoW(hMonitor, &minfo);
|
||||
|
||||
// First, find this screen's path.
|
||||
for (const DISPLAYCONFIG_PATH_INFO &path : data->paths) {
|
||||
DISPLAYCONFIG_SOURCE_DEVICE_NAME source_name;
|
||||
memset(&source_name, 0, sizeof(source_name));
|
||||
source_name.header.type = DISPLAYCONFIG_DEVICE_INFO_GET_SOURCE_NAME;
|
||||
source_name.header.size = sizeof(source_name);
|
||||
source_name.header.adapterId = path.sourceInfo.adapterId;
|
||||
source_name.header.id = path.sourceInfo.id;
|
||||
|
||||
if (DisplayConfigGetDeviceInfo(&source_name.header) == ERROR_SUCCESS) {
|
||||
if (wcscmp(minfo.szDevice, source_name.viewGdiDeviceName) == 0) {
|
||||
// Found it, now we can query the SDR white level.
|
||||
DISPLAYCONFIG_SDR_WHITE_LEVEL sdr_white_level;
|
||||
memset(&sdr_white_level, 0, sizeof(sdr_white_level));
|
||||
sdr_white_level.header.type = DISPLAYCONFIG_DEVICE_INFO_GET_SDR_WHITE_LEVEL;
|
||||
sdr_white_level.header.size = sizeof(sdr_white_level);
|
||||
sdr_white_level.header.adapterId = path.targetInfo.adapterId;
|
||||
sdr_white_level.header.id = path.targetInfo.id;
|
||||
|
||||
LONG result = DisplayConfigGetDeviceInfo(&sdr_white_level.header);
|
||||
if (result == ERROR_SUCCESS) {
|
||||
data->sdrWhiteLevelInNits = (float)(sdr_white_level.SDRWhiteLevel / 1000) * 80;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data->count++;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
float DisplayServerWindows::screen_get_sdr_white_level(int p_screen) const {
|
||||
_THREAD_SAFE_METHOD_
|
||||
|
||||
p_screen = _get_screen_index(p_screen);
|
||||
EnumSdrWhiteLevelData data = { Vector<DISPLAYCONFIG_PATH_INFO>(), Vector<DISPLAYCONFIG_MODE_INFO>(), 0, p_screen, 0.0f };
|
||||
|
||||
uint32_t path_count = 0;
|
||||
uint32_t mode_count = 0;
|
||||
if (GetDisplayConfigBufferSizes(QDC_ONLY_ACTIVE_PATHS, &path_count, &mode_count) == ERROR_SUCCESS) {
|
||||
data.paths.resize(path_count);
|
||||
data.modes.resize(mode_count);
|
||||
if (QueryDisplayConfig(QDC_ONLY_ACTIVE_PATHS, &path_count, data.paths.ptrw(), &mode_count, data.modes.ptrw(), nullptr) != ERROR_SUCCESS) {
|
||||
data.paths.clear();
|
||||
data.modes.clear();
|
||||
}
|
||||
}
|
||||
|
||||
EnumDisplayMonitors(nullptr, nullptr, _MonitorEnumProcSdrWhiteLevel, (LPARAM)&data);
|
||||
return data.sdrWhiteLevelInNits;
|
||||
}
|
||||
|
||||
float DisplayServerWindows::screen_get_refresh_rate(int p_screen) const {
|
||||
_THREAD_SAFE_METHOD_
|
||||
|
||||
|
|
@ -1974,7 +2144,10 @@ void DisplayServerWindows::window_set_current_screen(int p_screen, WindowID p_wi
|
|||
return;
|
||||
}
|
||||
const WindowData &wd = windows[p_window];
|
||||
ERR_FAIL_COND_MSG(wd.parent_hwnd, "Embedded window can't be moved to another screen.");
|
||||
if (wd.parent_hwnd) {
|
||||
print_line("Embedded window can't be moved to another screen.");
|
||||
return;
|
||||
}
|
||||
if (wd.fullscreen) {
|
||||
Point2 pos = screen_get_position(p_screen) + _get_screens_origin();
|
||||
Size2 size = screen_get_size(p_screen);
|
||||
|
|
@ -2055,7 +2228,10 @@ void DisplayServerWindows::window_set_position(const Point2i &p_position, Window
|
|||
ERR_FAIL_COND(!windows.has(p_window));
|
||||
WindowData &wd = windows[p_window];
|
||||
|
||||
ERR_FAIL_COND_MSG(wd.parent_hwnd, "Embedded window can't be moved.");
|
||||
if (wd.parent_hwnd) {
|
||||
print_line("Embedded window can't be moved.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (wd.fullscreen || wd.maximized) {
|
||||
return;
|
||||
|
|
@ -2141,7 +2317,10 @@ void DisplayServerWindows::window_set_max_size(const Size2i p_size, WindowID p_w
|
|||
ERR_FAIL_COND(!windows.has(p_window));
|
||||
WindowData &wd = windows[p_window];
|
||||
|
||||
ERR_FAIL_COND_MSG(wd.parent_hwnd, "Embedded windows can't have a maximum size.");
|
||||
if (wd.parent_hwnd) {
|
||||
print_line("Embedded windows can't have a maximum size.");
|
||||
return;
|
||||
}
|
||||
|
||||
if ((p_size != Size2()) && ((p_size.x < wd.min_size.x) || (p_size.y < wd.min_size.y))) {
|
||||
ERR_PRINT("Maximum window size can't be smaller than minimum window size!");
|
||||
|
|
@ -2164,7 +2343,10 @@ void DisplayServerWindows::window_set_min_size(const Size2i p_size, WindowID p_w
|
|||
ERR_FAIL_COND(!windows.has(p_window));
|
||||
WindowData &wd = windows[p_window];
|
||||
|
||||
ERR_FAIL_COND_MSG(wd.parent_hwnd, "Embedded windows can't have a minimum size.");
|
||||
if (wd.parent_hwnd) {
|
||||
print_line("Embedded windows can't have a minimum size.");
|
||||
return;
|
||||
}
|
||||
|
||||
if ((p_size != Size2()) && (wd.max_size != Size2()) && ((p_size.x > wd.max_size.x) || (p_size.y > wd.max_size.y))) {
|
||||
ERR_PRINT("Minimum window size can't be larger than maximum window size!");
|
||||
|
|
@ -2187,7 +2369,10 @@ void DisplayServerWindows::window_set_size(const Size2i p_size, WindowID p_windo
|
|||
ERR_FAIL_COND(!windows.has(p_window));
|
||||
WindowData &wd = windows[p_window];
|
||||
|
||||
ERR_FAIL_COND_MSG(wd.parent_hwnd, "Embedded window can't be resized.");
|
||||
if (wd.parent_hwnd) {
|
||||
print_line("Embedded window can't be resized.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (wd.fullscreen || wd.maximized) {
|
||||
return;
|
||||
|
|
@ -2345,7 +2530,10 @@ void DisplayServerWindows::window_set_mode(WindowMode p_mode, WindowID p_window)
|
|||
ERR_FAIL_COND(!windows.has(p_window));
|
||||
WindowData &wd = windows[p_window];
|
||||
|
||||
ERR_FAIL_COND_MSG(p_mode != WINDOW_MODE_WINDOWED && wd.parent_hwnd, "Embedded window only supports Windowed mode.");
|
||||
if (p_mode != WINDOW_MODE_WINDOWED && wd.parent_hwnd) {
|
||||
print_line("Embedded window only supports Windowed mode.");
|
||||
return;
|
||||
}
|
||||
|
||||
bool was_fullscreen = wd.fullscreen;
|
||||
wd.was_fullscreen_pre_min = false;
|
||||
|
|
@ -2480,7 +2668,10 @@ void DisplayServerWindows::window_set_flag(WindowFlags p_flag, bool p_enabled, W
|
|||
WindowData &wd = windows[p_window];
|
||||
switch (p_flag) {
|
||||
case WINDOW_FLAG_RESIZE_DISABLED: {
|
||||
ERR_FAIL_COND_MSG(p_enabled && wd.parent_hwnd, "Embedded window resize can't be disabled.");
|
||||
if (p_enabled && wd.parent_hwnd) {
|
||||
print_line("Embedded window resize can't be disabled.");
|
||||
return;
|
||||
}
|
||||
wd.resizable = !p_enabled;
|
||||
_update_window_style(p_window);
|
||||
} break;
|
||||
|
|
@ -2492,7 +2683,10 @@ void DisplayServerWindows::window_set_flag(WindowFlags p_flag, bool p_enabled, W
|
|||
} break;
|
||||
case WINDOW_FLAG_ALWAYS_ON_TOP: {
|
||||
ERR_FAIL_COND_MSG(wd.transient_parent != INVALID_WINDOW_ID && p_enabled, "Transient windows can't become on top.");
|
||||
ERR_FAIL_COND_MSG(p_enabled && wd.parent_hwnd, "Embedded window can't become on top.");
|
||||
if (p_enabled && wd.parent_hwnd) {
|
||||
print_line("Embedded window can't become on top.");
|
||||
return;
|
||||
}
|
||||
wd.always_on_top = p_enabled;
|
||||
_update_window_style(p_window);
|
||||
} break;
|
||||
|
|
@ -2552,7 +2746,10 @@ void DisplayServerWindows::window_set_flag(WindowFlags p_flag, bool p_enabled, W
|
|||
case WINDOW_FLAG_POPUP: {
|
||||
ERR_FAIL_COND_MSG(p_window == MAIN_WINDOW_ID, "Main window can't be popup.");
|
||||
ERR_FAIL_COND_MSG(IsWindowVisible(wd.hWnd) && (wd.is_popup != p_enabled), "Popup flag can't changed while window is opened.");
|
||||
ERR_FAIL_COND_MSG(p_enabled && wd.parent_hwnd, "Embedded window can't be popup.");
|
||||
if (p_enabled && wd.parent_hwnd) {
|
||||
print_line("Embedded window can't be popup.");
|
||||
return;
|
||||
}
|
||||
wd.is_popup = p_enabled;
|
||||
} break;
|
||||
default:
|
||||
|
|
@ -2951,6 +3148,74 @@ HWND DisplayServerWindows::_find_window_from_process_id(OS::ProcessID p_pid, HWN
|
|||
return NULL;
|
||||
}
|
||||
|
||||
// Get screen HDR capabilities for internal use only.
|
||||
// Do not report values from this method to the user.
|
||||
DisplayServerWindows::ScreenHdrData DisplayServerWindows::_get_screen_hdr_data(int p_screen) const {
|
||||
ScreenHdrData data;
|
||||
#ifdef D3D12_ENABLED
|
||||
DXGI_OUTPUT_DESC1 desc;
|
||||
if (_get_screen_desc(p_screen, desc)) {
|
||||
data.hdr_supported = desc.ColorSpace == DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020;
|
||||
data.min_luminance = desc.MinLuminance;
|
||||
data.max_luminance = desc.MaxLuminance;
|
||||
data.max_average_luminance = desc.MaxFullFrameLuminance;
|
||||
}
|
||||
#else
|
||||
// If we don't have D3D12, assume HDR is supported to avoid blocking Vulkan only builds.
|
||||
data.hdr_supported = true;
|
||||
data.min_luminance = 0.0f;
|
||||
data.max_luminance = 0.0f;
|
||||
data.max_average_luminance = 0.0f;
|
||||
#endif // D3D12_ENABLED
|
||||
|
||||
data.sdr_white_level = screen_get_sdr_white_level(p_screen);
|
||||
return data;
|
||||
}
|
||||
|
||||
void DisplayServerWindows::_update_hdr_output_for_window(WindowID p_window, const WindowData &p_window_data, ScreenHdrData p_screen_data) {
|
||||
#ifdef RD_ENABLED
|
||||
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;
|
||||
|
||||
if (current_hdr_enabled != desired_hdr_enabled) {
|
||||
rendering_context->window_set_hdr_output_enabled(p_window, desired_hdr_enabled);
|
||||
}
|
||||
|
||||
if (p_window_data.hdr_output_use_screen_luminance) {
|
||||
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);
|
||||
}
|
||||
if (p_screen_data.min_luminance > 0.0f) {
|
||||
rendering_context->window_set_hdr_output_min_luminance(p_window, p_screen_data.min_luminance);
|
||||
}
|
||||
if (p_screen_data.max_luminance > 0.0f) {
|
||||
rendering_context->window_set_hdr_output_max_luminance(p_window, p_screen_data.max_luminance);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // RD_ENABLED
|
||||
}
|
||||
|
||||
void DisplayServerWindows::_update_hdr_output_for_tracked_windows() {
|
||||
HashMap<int, ScreenHdrData> outputs;
|
||||
for (const KeyValue<WindowID, WindowData> &E : windows) {
|
||||
if (E.value.hdr_output_requested) {
|
||||
int screen = window_get_current_screen(E.key);
|
||||
|
||||
ScreenHdrData data;
|
||||
if (!outputs.has(screen)) {
|
||||
data = _get_screen_hdr_data(screen);
|
||||
outputs.insert(screen, data);
|
||||
} else {
|
||||
data = outputs[screen];
|
||||
}
|
||||
|
||||
_update_hdr_output_for_window(E.key, E.value, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Error DisplayServerWindows::embed_process(WindowID p_window, OS::ProcessID p_pid, const Rect2i &p_rect, bool p_visible, bool p_grab_focus) {
|
||||
_THREAD_SAFE_METHOD_
|
||||
|
||||
|
|
@ -3137,7 +3402,7 @@ Error DisplayServerWindows::dialog_show(String p_title, String p_description, Ve
|
|||
if (comctl) {
|
||||
typedef HRESULT(WINAPI * TaskDialogIndirectPtr)(const TASKDIALOGCONFIG *pTaskConfig, int *pnButton, int *pnRadioButton, BOOL *pfVerificationFlagChecked);
|
||||
|
||||
TaskDialogIndirectPtr task_dialog_indirect = (TaskDialogIndirectPtr)GetProcAddress(comctl, "TaskDialogIndirect");
|
||||
TaskDialogIndirectPtr task_dialog_indirect = (TaskDialogIndirectPtr)(void *)GetProcAddress(comctl, "TaskDialogIndirect");
|
||||
int button_pressed;
|
||||
|
||||
if (task_dialog_indirect && SUCCEEDED(task_dialog_indirect(&config, &button_pressed, nullptr, nullptr))) {
|
||||
|
|
@ -4073,6 +4338,155 @@ DisplayServer::VSyncMode DisplayServerWindows::window_get_vsync_mode(WindowID p_
|
|||
return DisplayServer::VSYNC_ENABLED;
|
||||
}
|
||||
|
||||
void DisplayServerWindows::window_set_hdr_output_enabled(const bool p_enabled, WindowID p_window) {
|
||||
_THREAD_SAFE_METHOD_
|
||||
|
||||
#if defined(RD_ENABLED)
|
||||
ERR_FAIL_COND_MSG((rendering_device && rendering_device->has_feature(RenderingDevice::Features::SUPPORTS_HDR_OUTPUT)) == false, "HDR output is not supported by the rendering device.");
|
||||
#endif
|
||||
|
||||
WindowData &wd = windows[p_window];
|
||||
wd.hdr_output_requested = p_enabled;
|
||||
|
||||
int screen = window_get_current_screen(p_window);
|
||||
DisplayServerWindows::ScreenHdrData data = _get_screen_hdr_data(screen);
|
||||
_update_hdr_output_for_window(p_window, wd, data);
|
||||
}
|
||||
|
||||
bool DisplayServerWindows::window_is_hdr_output_enabled(WindowID p_window) const {
|
||||
_THREAD_SAFE_METHOD_
|
||||
#if defined(RD_ENABLED)
|
||||
if (rendering_context) {
|
||||
return rendering_context->window_get_hdr_output_enabled(p_window);
|
||||
}
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void DisplayServerWindows::window_set_hdr_output_prefer_high_precision(const bool p_enabled, WindowID p_window) {
|
||||
_THREAD_SAFE_METHOD_
|
||||
#if defined(RD_ENABLED)
|
||||
if (rendering_context) {
|
||||
if (p_enabled == rendering_context->window_get_hdr_output_prefer_high_precision(p_window)) {
|
||||
return;
|
||||
}
|
||||
|
||||
rendering_context->window_set_hdr_output_prefer_high_precision(p_window, p_enabled);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
bool DisplayServerWindows::window_is_hdr_output_preferring_high_precision(WindowID p_window) const {
|
||||
_THREAD_SAFE_METHOD_
|
||||
#if defined(RD_ENABLED)
|
||||
if (rendering_context) {
|
||||
return rendering_context->window_get_hdr_output_prefer_high_precision(p_window);
|
||||
}
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void DisplayServerWindows::window_set_hdr_output_use_screen_luminance(const bool p_enabled, WindowID p_window) {
|
||||
_THREAD_SAFE_METHOD_
|
||||
|
||||
WindowData &wd = windows[p_window];
|
||||
wd.hdr_output_use_screen_luminance = p_enabled;
|
||||
|
||||
int screen = window_get_current_screen(p_window);
|
||||
DisplayServerWindows::ScreenHdrData data = _get_screen_hdr_data(screen);
|
||||
_update_hdr_output_for_window(p_window, wd, data);
|
||||
}
|
||||
|
||||
bool DisplayServerWindows::window_is_hdr_output_using_screen_luminance(WindowID p_window) const {
|
||||
_THREAD_SAFE_METHOD_
|
||||
|
||||
const WindowData &wd = windows[p_window];
|
||||
return wd.hdr_output_use_screen_luminance;
|
||||
}
|
||||
|
||||
void DisplayServerWindows::window_set_hdr_output_reference_luminance(const float p_reference_luminance, WindowID p_window) {
|
||||
_THREAD_SAFE_METHOD_
|
||||
|
||||
const WindowData &wd = windows[p_window];
|
||||
if (wd.hdr_output_use_screen_luminance) {
|
||||
WARN_PRINT("Reference luminance is ignored when using screen luminance.");
|
||||
return;
|
||||
}
|
||||
|
||||
#if defined(RD_ENABLED)
|
||||
if (rendering_context) {
|
||||
rendering_context->window_set_hdr_output_reference_luminance(p_window, p_reference_luminance);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
float DisplayServerWindows::window_get_hdr_output_reference_luminance(WindowID p_window) const {
|
||||
_THREAD_SAFE_METHOD_
|
||||
#if defined(RD_ENABLED)
|
||||
if (rendering_context) {
|
||||
return rendering_context->window_get_hdr_output_reference_luminance(p_window);
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
void DisplayServerWindows::window_set_hdr_output_min_luminance(const float p_min_luminance, WindowID p_window) {
|
||||
_THREAD_SAFE_METHOD_
|
||||
|
||||
const WindowData &wd = windows[p_window];
|
||||
if (wd.hdr_output_use_screen_luminance) {
|
||||
WARN_PRINT("Minimum luminance is ignored when using screen luminance.");
|
||||
return;
|
||||
}
|
||||
|
||||
#if defined(RD_ENABLED)
|
||||
if (rendering_context) {
|
||||
rendering_context->window_set_hdr_output_min_luminance(p_window, p_min_luminance);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
float DisplayServerWindows::window_get_hdr_output_min_luminance(WindowID p_window) const {
|
||||
_THREAD_SAFE_METHOD_
|
||||
#if defined(RD_ENABLED)
|
||||
if (rendering_context) {
|
||||
return rendering_context->window_get_hdr_output_min_luminance(p_window);
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
void DisplayServerWindows::window_set_hdr_output_max_luminance(const float p_max_luminance, WindowID p_window) {
|
||||
_THREAD_SAFE_METHOD_
|
||||
|
||||
const WindowData &wd = windows[p_window];
|
||||
if (wd.hdr_output_use_screen_luminance) {
|
||||
WARN_PRINT("Maximum luminance is ignored when using screen luminance.");
|
||||
return;
|
||||
}
|
||||
|
||||
#if defined(RD_ENABLED)
|
||||
if (rendering_context) {
|
||||
rendering_context->window_set_hdr_output_max_luminance(p_window, p_max_luminance);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
float DisplayServerWindows::window_get_hdr_output_max_luminance(WindowID p_window) const {
|
||||
_THREAD_SAFE_METHOD_
|
||||
#if defined(RD_ENABLED)
|
||||
if (rendering_context) {
|
||||
return rendering_context->window_get_hdr_output_max_luminance(p_window);
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
void DisplayServerWindows::window_start_drag(WindowID p_window) {
|
||||
_THREAD_SAFE_METHOD_
|
||||
|
||||
|
|
@ -5539,6 +5953,10 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
|
|||
}
|
||||
} break;
|
||||
|
||||
case WM_DISPLAYCHANGE: {
|
||||
_update_hdr_output_for_tracked_windows();
|
||||
} break;
|
||||
|
||||
case WM_WINDOWPOSCHANGED: {
|
||||
Rect2i window_client_rect;
|
||||
Rect2i window_rect;
|
||||
|
|
@ -5622,6 +6040,8 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
|
|||
window.rect_changed_callback.call(Rect2i(window.last_pos.x, window.last_pos.y, window.width, window.height));
|
||||
}
|
||||
|
||||
_update_hdr_output_for_tracked_windows();
|
||||
|
||||
// Update cursor clip region after window rect has changed.
|
||||
if (mouse_mode == MOUSE_MODE_CAPTURED || mouse_mode == MOUSE_MODE_CONFINED || mouse_mode == MOUSE_MODE_CONFINED_HIDDEN) {
|
||||
RECT crect;
|
||||
|
|
@ -6592,9 +7012,9 @@ DisplayServerWindows::DisplayServerWindows(const String &p_rendering_driver, Win
|
|||
|
||||
HMODULE nt_lib = LoadLibraryW(L"ntdll.dll");
|
||||
if (nt_lib) {
|
||||
WineGetVersionPtr wine_get_version = (WineGetVersionPtr)GetProcAddress(nt_lib, "wine_get_version"); // Do not read Windows build number under Wine, it can be set to arbitrary value.
|
||||
WineGetVersionPtr wine_get_version = (WineGetVersionPtr)(void *)GetProcAddress(nt_lib, "wine_get_version"); // Do not read Windows build number under Wine, it can be set to arbitrary value.
|
||||
if (!wine_get_version) {
|
||||
RtlGetVersionPtr RtlGetVersion = (RtlGetVersionPtr)GetProcAddress(nt_lib, "RtlGetVersion");
|
||||
RtlGetVersionPtr RtlGetVersion = (RtlGetVersionPtr)(void *)GetProcAddress(nt_lib, "RtlGetVersion");
|
||||
if (RtlGetVersion) {
|
||||
RtlGetVersion(&os_ver);
|
||||
}
|
||||
|
|
@ -6605,28 +7025,28 @@ DisplayServerWindows::DisplayServerWindows(const String &p_rendering_driver, Win
|
|||
// Load Shell API.
|
||||
HMODULE shellapi_lib = LoadLibraryW(L"shlwapi.dll");
|
||||
if (shellapi_lib) {
|
||||
load_indirect_string = (SHLoadIndirectStringPtr)GetProcAddress(shellapi_lib, "SHLoadIndirectString");
|
||||
load_indirect_string = (SHLoadIndirectStringPtr)(void *)GetProcAddress(shellapi_lib, "SHLoadIndirectString");
|
||||
}
|
||||
|
||||
// Load UXTheme, available on Windows 10+ only.
|
||||
if (os_ver.dwBuildNumber >= 10240) {
|
||||
HMODULE ux_theme_lib = LoadLibraryW(L"uxtheme.dll");
|
||||
if (ux_theme_lib) {
|
||||
ShouldAppsUseDarkMode = (ShouldAppsUseDarkModePtr)GetProcAddress(ux_theme_lib, MAKEINTRESOURCEA(132));
|
||||
GetImmersiveColorFromColorSetEx = (GetImmersiveColorFromColorSetExPtr)GetProcAddress(ux_theme_lib, MAKEINTRESOURCEA(95));
|
||||
GetImmersiveColorTypeFromName = (GetImmersiveColorTypeFromNamePtr)GetProcAddress(ux_theme_lib, MAKEINTRESOURCEA(96));
|
||||
GetImmersiveUserColorSetPreference = (GetImmersiveUserColorSetPreferencePtr)GetProcAddress(ux_theme_lib, MAKEINTRESOURCEA(98));
|
||||
ShouldAppsUseDarkMode = (ShouldAppsUseDarkModePtr)(void *)GetProcAddress(ux_theme_lib, MAKEINTRESOURCEA(132));
|
||||
GetImmersiveColorFromColorSetEx = (GetImmersiveColorFromColorSetExPtr)(void *)GetProcAddress(ux_theme_lib, MAKEINTRESOURCEA(95));
|
||||
GetImmersiveColorTypeFromName = (GetImmersiveColorTypeFromNamePtr)(void *)GetProcAddress(ux_theme_lib, MAKEINTRESOURCEA(96));
|
||||
GetImmersiveUserColorSetPreference = (GetImmersiveUserColorSetPreferencePtr)(void *)GetProcAddress(ux_theme_lib, MAKEINTRESOURCEA(98));
|
||||
if (os_ver.dwBuildNumber >= 17763) { // Windows 10 Redstone 5 (1809)+ only.
|
||||
AllowDarkModeForAppPtr AllowDarkModeForApp = nullptr;
|
||||
SetPreferredAppModePtr SetPreferredAppMode = nullptr;
|
||||
FlushMenuThemesPtr FlushMenuThemes = nullptr;
|
||||
if (os_ver.dwBuildNumber < 18362) { // Windows 10 Redstone 5 (1809) and 19H1 (1903) only.
|
||||
AllowDarkModeForApp = (AllowDarkModeForAppPtr)GetProcAddress(ux_theme_lib, MAKEINTRESOURCEA(135));
|
||||
AllowDarkModeForApp = (AllowDarkModeForAppPtr)(void *)GetProcAddress(ux_theme_lib, MAKEINTRESOURCEA(135));
|
||||
} else { // Windows 10 19H2 (1909)+ only.
|
||||
SetPreferredAppMode = (SetPreferredAppModePtr)GetProcAddress(ux_theme_lib, MAKEINTRESOURCEA(135));
|
||||
FlushMenuThemes = (FlushMenuThemesPtr)GetProcAddress(ux_theme_lib, MAKEINTRESOURCEA(136));
|
||||
SetPreferredAppMode = (SetPreferredAppModePtr)(void *)GetProcAddress(ux_theme_lib, MAKEINTRESOURCEA(135));
|
||||
FlushMenuThemes = (FlushMenuThemesPtr)(void *)GetProcAddress(ux_theme_lib, MAKEINTRESOURCEA(136));
|
||||
}
|
||||
RefreshImmersiveColorPolicyStatePtr RefreshImmersiveColorPolicyState = (RefreshImmersiveColorPolicyStatePtr)GetProcAddress(ux_theme_lib, MAKEINTRESOURCEA(104));
|
||||
RefreshImmersiveColorPolicyStatePtr RefreshImmersiveColorPolicyState = (RefreshImmersiveColorPolicyStatePtr)(void *)GetProcAddress(ux_theme_lib, MAKEINTRESOURCEA(104));
|
||||
if (ShouldAppsUseDarkMode) {
|
||||
bool dark_mode = ShouldAppsUseDarkMode();
|
||||
if (SetPreferredAppMode) {
|
||||
|
|
@ -6659,10 +7079,10 @@ DisplayServerWindows::DisplayServerWindows(const String &p_rendering_driver, Win
|
|||
// Note: DPI conversion API, available on Windows 8.1+ only.
|
||||
HMODULE user32_lib = LoadLibraryW(L"user32.dll");
|
||||
if (user32_lib) {
|
||||
win8p_GetPointerType = (GetPointerTypePtr)GetProcAddress(user32_lib, "GetPointerType");
|
||||
win8p_GetPointerPenInfo = (GetPointerPenInfoPtr)GetProcAddress(user32_lib, "GetPointerPenInfo");
|
||||
win81p_LogicalToPhysicalPointForPerMonitorDPI = (LogicalToPhysicalPointForPerMonitorDPIPtr)GetProcAddress(user32_lib, "LogicalToPhysicalPointForPerMonitorDPI");
|
||||
win81p_PhysicalToLogicalPointForPerMonitorDPI = (PhysicalToLogicalPointForPerMonitorDPIPtr)GetProcAddress(user32_lib, "PhysicalToLogicalPointForPerMonitorDPI");
|
||||
win8p_GetPointerType = (GetPointerTypePtr)(void *)GetProcAddress(user32_lib, "GetPointerType");
|
||||
win8p_GetPointerPenInfo = (GetPointerPenInfoPtr)(void *)GetProcAddress(user32_lib, "GetPointerPenInfo");
|
||||
win81p_LogicalToPhysicalPointForPerMonitorDPI = (LogicalToPhysicalPointForPerMonitorDPIPtr)(void *)GetProcAddress(user32_lib, "LogicalToPhysicalPointForPerMonitorDPI");
|
||||
win81p_PhysicalToLogicalPointForPerMonitorDPI = (PhysicalToLogicalPointForPerMonitorDPIPtr)(void *)GetProcAddress(user32_lib, "PhysicalToLogicalPointForPerMonitorDPI");
|
||||
|
||||
winink_available = win8p_GetPointerType && win8p_GetPointerPenInfo;
|
||||
}
|
||||
|
|
@ -6674,11 +7094,11 @@ DisplayServerWindows::DisplayServerWindows(const String &p_rendering_driver, Win
|
|||
// Note: Wacom WinTab driver API for pen input, for devices incompatible with Windows Ink.
|
||||
HMODULE wintab_lib = LoadLibraryW(L"wintab32.dll");
|
||||
if (wintab_lib) {
|
||||
wintab_WTOpen = (WTOpenPtr)GetProcAddress(wintab_lib, "WTOpenW");
|
||||
wintab_WTClose = (WTClosePtr)GetProcAddress(wintab_lib, "WTClose");
|
||||
wintab_WTInfo = (WTInfoPtr)GetProcAddress(wintab_lib, "WTInfoW");
|
||||
wintab_WTPacket = (WTPacketPtr)GetProcAddress(wintab_lib, "WTPacket");
|
||||
wintab_WTEnable = (WTEnablePtr)GetProcAddress(wintab_lib, "WTEnable");
|
||||
wintab_WTOpen = (WTOpenPtr)(void *)GetProcAddress(wintab_lib, "WTOpenW");
|
||||
wintab_WTClose = (WTClosePtr)(void *)GetProcAddress(wintab_lib, "WTClose");
|
||||
wintab_WTInfo = (WTInfoPtr)(void *)GetProcAddress(wintab_lib, "WTInfoW");
|
||||
wintab_WTPacket = (WTPacketPtr)(void *)GetProcAddress(wintab_lib, "WTPacket");
|
||||
wintab_WTEnable = (WTEnablePtr)(void *)GetProcAddress(wintab_lib, "WTEnable");
|
||||
|
||||
wintab_available = wintab_WTOpen && wintab_WTClose && wintab_WTInfo && wintab_WTPacket && wintab_WTEnable;
|
||||
}
|
||||
|
|
@ -6716,7 +7136,7 @@ DisplayServerWindows::DisplayServerWindows(const String &p_rendering_driver, Win
|
|||
if (Shcore != nullptr) {
|
||||
typedef HRESULT(WINAPI * SetProcessDpiAwareness_t)(SHC_PROCESS_DPI_AWARENESS);
|
||||
|
||||
SetProcessDpiAwareness_t SetProcessDpiAwareness = (SetProcessDpiAwareness_t)GetProcAddress(Shcore, "SetProcessDpiAwareness");
|
||||
SetProcessDpiAwareness_t SetProcessDpiAwareness = (SetProcessDpiAwareness_t)(void *)GetProcAddress(Shcore, "SetProcessDpiAwareness");
|
||||
|
||||
if (SetProcessDpiAwareness) {
|
||||
SetProcessDpiAwareness(SHC_PROCESS_SYSTEM_DPI_AWARE);
|
||||
|
|
@ -6727,7 +7147,7 @@ DisplayServerWindows::DisplayServerWindows(const String &p_rendering_driver, Win
|
|||
HMODULE comctl32 = LoadLibraryW(L"comctl32.dll");
|
||||
if (comctl32) {
|
||||
typedef BOOL(WINAPI * InitCommonControlsExPtr)(_In_ const INITCOMMONCONTROLSEX *picce);
|
||||
InitCommonControlsExPtr init_common_controls_ex = (InitCommonControlsExPtr)GetProcAddress(comctl32, "InitCommonControlsEx");
|
||||
InitCommonControlsExPtr init_common_controls_ex = (InitCommonControlsExPtr)(void *)GetProcAddress(comctl32, "InitCommonControlsEx");
|
||||
|
||||
// Fails if the incorrect version was loaded. Probably not a big enough deal to print an error about.
|
||||
if (init_common_controls_ex) {
|
||||
|
|
@ -6849,7 +7269,7 @@ DisplayServerWindows::DisplayServerWindows(const String &p_rendering_driver, Win
|
|||
#else
|
||||
typedef BOOL(WINAPI * IsWow64Process2Ptr)(HANDLE, USHORT *, USHORT *);
|
||||
|
||||
IsWow64Process2Ptr IsWow64Process2 = (IsWow64Process2Ptr)GetProcAddress(GetModuleHandle(TEXT("kernel32")), "IsWow64Process2");
|
||||
IsWow64Process2Ptr IsWow64Process2 = (IsWow64Process2Ptr)(void *)GetProcAddress(GetModuleHandle(TEXT("kernel32")), "IsWow64Process2");
|
||||
if (IsWow64Process2) {
|
||||
USHORT process_arch = 0;
|
||||
USHORT machine_arch = 0;
|
||||
|
|
|
|||
|
|
@ -548,6 +548,10 @@ class DisplayServerWindows : public DisplayServer {
|
|||
bool is_popup = false;
|
||||
Rect2i parent_safe_rect;
|
||||
|
||||
// HDR
|
||||
bool hdr_output_requested = false;
|
||||
bool hdr_output_use_screen_luminance = false;
|
||||
|
||||
bool initialized = false;
|
||||
|
||||
HWND parent_hwnd = 0;
|
||||
|
|
@ -687,6 +691,17 @@ class DisplayServerWindows : public DisplayServer {
|
|||
|
||||
HWND _find_window_from_process_id(OS::ProcessID p_pid, HWND p_current_hwnd);
|
||||
|
||||
struct ScreenHdrData {
|
||||
bool hdr_supported = false;
|
||||
float min_luminance = 0.0f;
|
||||
float max_luminance = 0.0f;
|
||||
float max_average_luminance = 0.0f;
|
||||
float sdr_white_level = 0.0f;
|
||||
};
|
||||
ScreenHdrData _get_screen_hdr_data(int p_screen) const;
|
||||
void _update_hdr_output_for_window(WindowID p_window, const WindowData &p_window_data, ScreenHdrData p_screen_data);
|
||||
void _update_hdr_output_for_tracked_windows();
|
||||
|
||||
public:
|
||||
LRESULT WndProcFileDialog(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||||
LRESULT WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||||
|
|
@ -747,6 +762,13 @@ public:
|
|||
virtual Ref<Image> screen_get_image(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
|
||||
virtual Ref<Image> screen_get_image_rect(const Rect2i &p_rect) const override;
|
||||
|
||||
// Display capabilities for HDR.
|
||||
virtual bool screen_is_hdr_supported(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
|
||||
virtual float screen_get_min_luminance(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
|
||||
virtual float screen_get_max_luminance(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
|
||||
virtual float screen_get_max_average_luminance(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
|
||||
virtual float screen_get_sdr_white_level(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
|
||||
|
||||
virtual void screen_set_keep_on(bool p_enable) override; //disable screensaver
|
||||
virtual bool screen_is_kept_on() const override;
|
||||
|
||||
|
|
@ -827,6 +849,19 @@ public:
|
|||
virtual void window_set_vsync_mode(DisplayServer::VSyncMode p_vsync_mode, WindowID p_window = MAIN_WINDOW_ID) override;
|
||||
virtual DisplayServer::VSyncMode window_get_vsync_mode(WindowID p_vsync_mode) const override;
|
||||
|
||||
virtual void window_set_hdr_output_enabled(const bool p_enabled, WindowID p_window = MAIN_WINDOW_ID) override;
|
||||
virtual bool window_is_hdr_output_enabled(WindowID p_window = MAIN_WINDOW_ID) const override;
|
||||
virtual void window_set_hdr_output_prefer_high_precision(const bool p_enabled, WindowID p_window = MAIN_WINDOW_ID) override;
|
||||
virtual bool window_is_hdr_output_preferring_high_precision(WindowID p_window = MAIN_WINDOW_ID) const override;
|
||||
virtual void window_set_hdr_output_use_screen_luminance(const bool p_enabled, WindowID p_window = MAIN_WINDOW_ID) override;
|
||||
virtual bool window_is_hdr_output_using_screen_luminance(WindowID p_window = MAIN_WINDOW_ID) const override;
|
||||
virtual void window_set_hdr_output_reference_luminance(const float p_reference_luminance, WindowID p_window = MAIN_WINDOW_ID) override;
|
||||
virtual float window_get_hdr_output_reference_luminance(WindowID p_window = MAIN_WINDOW_ID) const override;
|
||||
virtual void window_set_hdr_output_min_luminance(const float p_min_luminance, WindowID p_window = MAIN_WINDOW_ID) override;
|
||||
virtual float window_get_hdr_output_min_luminance(WindowID p_window = MAIN_WINDOW_ID) const override;
|
||||
virtual void window_set_hdr_output_max_luminance(const float p_max_luminance, WindowID p_window = MAIN_WINDOW_ID) override;
|
||||
virtual float window_get_hdr_output_max_luminance(WindowID p_window = MAIN_WINDOW_ID) const override;
|
||||
|
||||
virtual void window_start_drag(WindowID p_window = MAIN_WINDOW_ID) override;
|
||||
virtual void window_start_resize(WindowResizeEdge p_edge, WindowID p_window = MAIN_WINDOW_ID) override;
|
||||
|
||||
|
|
|
|||
|
|
@ -50,11 +50,6 @@
|
|||
|
||||
#define _WGL_CONTEXT_DEBUG_BIT_ARB 0x0001
|
||||
|
||||
#if defined(__GNUC__)
|
||||
// Workaround GCC warning from -Wcast-function-type.
|
||||
#define GetProcAddress (void *)GetProcAddress
|
||||
#endif
|
||||
|
||||
typedef HGLRC(APIENTRY *PFNWGLCREATECONTEXT)(HDC);
|
||||
typedef BOOL(APIENTRY *PFNWGLDELETECONTEXT)(HGLRC);
|
||||
typedef BOOL(APIENTRY *PFNWGLMAKECURRENT)(HDC, HGLRC);
|
||||
|
|
@ -364,10 +359,10 @@ Error GLManagerNative_Windows::_create_context(GLWindow &win, GLDisplay &gl_disp
|
|||
if (!module) {
|
||||
return ERR_CANT_CREATE;
|
||||
}
|
||||
gd_wglCreateContext = (PFNWGLCREATECONTEXT)GetProcAddress(module, "wglCreateContext");
|
||||
gd_wglMakeCurrent = (PFNWGLMAKECURRENT)GetProcAddress(module, "wglMakeCurrent");
|
||||
gd_wglDeleteContext = (PFNWGLDELETECONTEXT)GetProcAddress(module, "wglDeleteContext");
|
||||
gd_wglGetProcAddress = (PFNWGLGETPROCADDRESS)GetProcAddress(module, "wglGetProcAddress");
|
||||
gd_wglCreateContext = (PFNWGLCREATECONTEXT)(void *)GetProcAddress(module, "wglCreateContext");
|
||||
gd_wglMakeCurrent = (PFNWGLMAKECURRENT)(void *)GetProcAddress(module, "wglMakeCurrent");
|
||||
gd_wglDeleteContext = (PFNWGLDELETECONTEXT)(void *)GetProcAddress(module, "wglDeleteContext");
|
||||
gd_wglGetProcAddress = (PFNWGLGETPROCADDRESS)(void *)GetProcAddress(module, "wglGetProcAddress");
|
||||
if (!gd_wglCreateContext || !gd_wglMakeCurrent || !gd_wglDeleteContext || !gd_wglGetProcAddress) {
|
||||
return ERR_CANT_CREATE;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,11 +33,6 @@
|
|||
#include <oleauto.h>
|
||||
#include <wbemidl.h>
|
||||
|
||||
#if defined(__GNUC__)
|
||||
// Workaround GCC warning from -Wcast-function-type.
|
||||
#define GetProcAddress (void *)GetProcAddress
|
||||
#endif
|
||||
|
||||
DWORD WINAPI _xinput_get_state(DWORD dwUserIndex, XINPUT_STATE *pState) {
|
||||
return ERROR_DEVICE_NOT_CONNECTED;
|
||||
}
|
||||
|
|
@ -597,8 +592,8 @@ void JoypadWindows::load_xinput() {
|
|||
|
||||
// (LPCSTR)100 is the magic number to get XInputGetStateEx, which also provides the state for the guide button
|
||||
LPCSTR get_state_func_name = legacy_xinput ? "XInputGetState" : (LPCSTR)100;
|
||||
XInputGetState_t func = (XInputGetState_t)GetProcAddress((HMODULE)xinput_dll, get_state_func_name);
|
||||
XInputSetState_t set_func = (XInputSetState_t)GetProcAddress((HMODULE)xinput_dll, "XInputSetState");
|
||||
XInputGetState_t func = (XInputGetState_t)(void *)GetProcAddress((HMODULE)xinput_dll, get_state_func_name);
|
||||
XInputSetState_t set_func = (XInputSetState_t)(void *)GetProcAddress((HMODULE)xinput_dll, "XInputSetState");
|
||||
if (!func || !set_func) {
|
||||
unload_xinput();
|
||||
return;
|
||||
|
|
@ -608,7 +603,7 @@ void JoypadWindows::load_xinput() {
|
|||
|
||||
winmm_dll = LoadLibrary("Winmm.dll");
|
||||
if (winmm_dll) {
|
||||
joyGetDevCaps_t caps_func = (joyGetDevCaps_t)GetProcAddress((HMODULE)winmm_dll, "joyGetDevCapsW");
|
||||
joyGetDevCaps_t caps_func = (joyGetDevCaps_t)(void *)GetProcAddress((HMODULE)winmm_dll, "joyGetDevCapsW");
|
||||
if (caps_func) {
|
||||
winmm_get_joycaps = caps_func;
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -106,11 +106,6 @@ __declspec(dllexport) void NoHotPatch() {} // Disable Nahimic code injection.
|
|||
#define DWRITE_FONT_WEIGHT_SEMI_LIGHT (DWRITE_FONT_WEIGHT)350
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__)
|
||||
// Workaround GCC warning from -Wcast-function-type.
|
||||
#define GetProcAddress (void *)GetProcAddress
|
||||
#endif
|
||||
|
||||
static String fix_path(const String &p_path) {
|
||||
String path = p_path;
|
||||
if (p_path.is_relative_path()) {
|
||||
|
|
@ -503,8 +498,8 @@ Error OS_Windows::open_dynamic_library(const String &p_path, void *&p_library_ha
|
|||
typedef DLL_DIRECTORY_COOKIE(WINAPI * PAddDllDirectory)(PCWSTR);
|
||||
typedef BOOL(WINAPI * PRemoveDllDirectory)(DLL_DIRECTORY_COOKIE);
|
||||
|
||||
PAddDllDirectory add_dll_directory = (PAddDllDirectory)GetProcAddress(GetModuleHandle("kernel32.dll"), "AddDllDirectory");
|
||||
PRemoveDllDirectory remove_dll_directory = (PRemoveDllDirectory)GetProcAddress(GetModuleHandle("kernel32.dll"), "RemoveDllDirectory");
|
||||
PAddDllDirectory add_dll_directory = (PAddDllDirectory)(void *)GetProcAddress(GetModuleHandle("kernel32.dll"), "AddDllDirectory");
|
||||
PRemoveDllDirectory remove_dll_directory = (PRemoveDllDirectory)(void *)GetProcAddress(GetModuleHandle("kernel32.dll"), "RemoveDllDirectory");
|
||||
|
||||
bool has_dll_directory_api = ((add_dll_directory != nullptr) && (remove_dll_directory != nullptr));
|
||||
DLL_DIRECTORY_COOKIE cookie = nullptr;
|
||||
|
|
@ -603,7 +598,7 @@ String OS_Windows::get_distribution_name() const {
|
|||
}
|
||||
|
||||
String OS_Windows::get_version() const {
|
||||
RtlGetVersionPtr version_ptr = (RtlGetVersionPtr)GetProcAddress(GetModuleHandle("ntdll.dll"), "RtlGetVersion");
|
||||
RtlGetVersionPtr version_ptr = (RtlGetVersionPtr)(void *)GetProcAddress(GetModuleHandle("ntdll.dll"), "RtlGetVersion");
|
||||
if (version_ptr != nullptr) {
|
||||
RTL_OSVERSIONINFOEXW fow;
|
||||
ZeroMemory(&fow, sizeof(fow));
|
||||
|
|
@ -616,7 +611,7 @@ String OS_Windows::get_version() const {
|
|||
}
|
||||
|
||||
String OS_Windows::get_version_alias() const {
|
||||
RtlGetVersionPtr version_ptr = (RtlGetVersionPtr)GetProcAddress(GetModuleHandle("ntdll.dll"), "RtlGetVersion");
|
||||
RtlGetVersionPtr version_ptr = (RtlGetVersionPtr)(void *)GetProcAddress(GetModuleHandle("ntdll.dll"), "RtlGetVersion");
|
||||
if (version_ptr != nullptr) {
|
||||
RTL_OSVERSIONINFOEXW fow;
|
||||
ZeroMemory(&fow, sizeof(fow));
|
||||
|
|
@ -789,7 +784,7 @@ bool OS_Windows::get_user_prefers_integrated_gpu() const {
|
|||
HMODULE kernel32 = GetModuleHandleW(L"kernel32.dll");
|
||||
if (kernel32) {
|
||||
using GetCurrentApplicationUserModelIdPtr = LONG(WINAPI *)(UINT32 * length, PWSTR id);
|
||||
GetCurrentApplicationUserModelIdPtr GetCurrentApplicationUserModelId = (GetCurrentApplicationUserModelIdPtr)GetProcAddress(kernel32, "GetCurrentApplicationUserModelId");
|
||||
GetCurrentApplicationUserModelIdPtr GetCurrentApplicationUserModelId = (GetCurrentApplicationUserModelIdPtr)(void *)GetProcAddress(kernel32, "GetCurrentApplicationUserModelId");
|
||||
|
||||
if (GetCurrentApplicationUserModelId) {
|
||||
UINT32 length = sizeof(value_name) / sizeof(value_name[0]);
|
||||
|
|
@ -991,7 +986,7 @@ Dictionary OS_Windows::get_memory_info() const {
|
|||
GetPerformanceInfo(&pref_info, sizeof(pref_info));
|
||||
|
||||
typedef void(WINAPI * PGetCurrentThreadStackLimits)(PULONG_PTR, PULONG_PTR);
|
||||
PGetCurrentThreadStackLimits GetCurrentThreadStackLimits = (PGetCurrentThreadStackLimits)GetProcAddress(GetModuleHandleA("kernel32.dll"), "GetCurrentThreadStackLimits");
|
||||
PGetCurrentThreadStackLimits GetCurrentThreadStackLimits = (PGetCurrentThreadStackLimits)(void *)GetProcAddress(GetModuleHandleA("kernel32.dll"), "GetCurrentThreadStackLimits");
|
||||
|
||||
ULONG_PTR LowLimit = 0;
|
||||
ULONG_PTR HighLimit = 0;
|
||||
|
|
|
|||
|
|
@ -53,11 +53,6 @@
|
|||
#define WGL_RENDERER 0x1F01
|
||||
#define WGL_VERSION 0x1F02
|
||||
|
||||
#if defined(__GNUC__)
|
||||
// Workaround GCC warning from -Wcast-function-type.
|
||||
#define GetProcAddress (void *)GetProcAddress
|
||||
#endif
|
||||
|
||||
typedef HGLRC(APIENTRY *PFNWGLCREATECONTEXT)(HDC);
|
||||
typedef BOOL(APIENTRY *PFNWGLDELETECONTEXT)(HGLRC);
|
||||
typedef BOOL(APIENTRY *PFNWGLMAKECURRENT)(HDC, HGLRC);
|
||||
|
|
@ -80,10 +75,10 @@ Dictionary detect_wgl() {
|
|||
if (!module) {
|
||||
return gl_info;
|
||||
}
|
||||
gd_wglCreateContext = (PFNWGLCREATECONTEXT)GetProcAddress(module, "wglCreateContext");
|
||||
gd_wglMakeCurrent = (PFNWGLMAKECURRENT)GetProcAddress(module, "wglMakeCurrent");
|
||||
gd_wglDeleteContext = (PFNWGLDELETECONTEXT)GetProcAddress(module, "wglDeleteContext");
|
||||
gd_wglGetProcAddress = (PFNWGLGETPROCADDRESS)GetProcAddress(module, "wglGetProcAddress");
|
||||
gd_wglCreateContext = (PFNWGLCREATECONTEXT)(void *)GetProcAddress(module, "wglCreateContext");
|
||||
gd_wglMakeCurrent = (PFNWGLMAKECURRENT)(void *)GetProcAddress(module, "wglMakeCurrent");
|
||||
gd_wglDeleteContext = (PFNWGLDELETECONTEXT)(void *)GetProcAddress(module, "wglDeleteContext");
|
||||
gd_wglGetProcAddress = (PFNWGLGETPROCADDRESS)(void *)GetProcAddress(module, "wglGetProcAddress");
|
||||
if (!gd_wglCreateContext || !gd_wglMakeCurrent || !gd_wglDeleteContext || !gd_wglGetProcAddress) {
|
||||
return gl_info;
|
||||
}
|
||||
|
|
@ -143,7 +138,7 @@ Dictionary detect_wgl() {
|
|||
HGLRC new_hRC = gd_wglCreateContextAttribsARB(hDC, nullptr, attribs);
|
||||
if (new_hRC) {
|
||||
if (gd_wglMakeCurrent(hDC, new_hRC)) {
|
||||
PFNWGLGETSTRINGPROC gd_wglGetString = (PFNWGLGETSTRINGPROC)GetProcAddress(module, "glGetString");
|
||||
PFNWGLGETSTRINGPROC gd_wglGetString = (PFNWGLGETSTRINGPROC)(void *)GetProcAddress(module, "glGetString");
|
||||
if (gd_wglGetString) {
|
||||
const char *prefixes[] = {
|
||||
"OpenGL ES-CM ",
|
||||
|
|
|
|||
|
|
@ -1900,6 +1900,9 @@ SceneTree::SceneTree() {
|
|||
const bool use_hdr_2d = GLOBAL_GET("rendering/viewport/hdr_2d");
|
||||
root->set_use_hdr_2d(use_hdr_2d);
|
||||
|
||||
const bool tonemap_to_window = GLOBAL_DEF("rendering/viewport/tonemap_to_window", true);
|
||||
root->set_tonemap_to_window(tonemap_to_window);
|
||||
|
||||
const int ssaa_mode = GLOBAL_DEF_BASIC(PropertyInfo(Variant::INT, "rendering/anti_aliasing/quality/screen_space_aa", PROPERTY_HINT_ENUM, "Disabled (Fastest),FXAA (Fast)"), 0);
|
||||
root->set_screen_space_aa(Viewport::ScreenSpaceAA(ssaa_mode));
|
||||
|
||||
|
|
|
|||
|
|
@ -1206,6 +1206,17 @@ bool Viewport::is_using_hdr_2d() const {
|
|||
return use_hdr_2d;
|
||||
}
|
||||
|
||||
void Viewport::set_tonemap_to_window(bool p_enable) {
|
||||
ERR_MAIN_THREAD_GUARD;
|
||||
tonemap_to_window = p_enable;
|
||||
RS::get_singleton()->viewport_set_tonemap_to_screen(viewport, p_enable);
|
||||
}
|
||||
|
||||
bool Viewport::is_tonemapping_to_window() const {
|
||||
ERR_READ_THREAD_GUARD_V(false);
|
||||
return tonemap_to_window;
|
||||
}
|
||||
|
||||
void Viewport::set_world_2d(const Ref<World2D> &p_world_2d) {
|
||||
ERR_MAIN_THREAD_GUARD;
|
||||
if (world_2d == p_world_2d) {
|
||||
|
|
@ -4777,6 +4788,9 @@ void Viewport::_bind_methods() {
|
|||
ClassDB::bind_method(D_METHOD("set_use_hdr_2d", "enable"), &Viewport::set_use_hdr_2d);
|
||||
ClassDB::bind_method(D_METHOD("is_using_hdr_2d"), &Viewport::is_using_hdr_2d);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_tonemap_to_window", "enable"), &Viewport::set_tonemap_to_window);
|
||||
ClassDB::bind_method(D_METHOD("is_tonemapping_to_window"), &Viewport::is_tonemapping_to_window);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_msaa_2d", "msaa"), &Viewport::set_msaa_2d);
|
||||
ClassDB::bind_method(D_METHOD("get_msaa_2d"), &Viewport::get_msaa_2d);
|
||||
|
||||
|
|
@ -4955,6 +4969,7 @@ void Viewport::_bind_methods() {
|
|||
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "mesh_lod_threshold", PROPERTY_HINT_RANGE, "0,1024,0.1"), "set_mesh_lod_threshold", "get_mesh_lod_threshold");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "debug_draw", PROPERTY_HINT_ENUM, "Disabled,Unshaded,Lighting,Overdraw,Wireframe,Normal Buffer,VoxelGI Albedo,VoxelGI Lighting,VoxelGI Emission,Shadow Atlas,Directional Shadow Map,Scene Luminance,SSAO,SSIL,Directional Shadow Splits,Decal Atlas,SDFGI Cascades,SDFGI Probes,VoxelGI/SDFGI Buffer,Disable Mesh LOD,OmniLight3D Cluster,SpotLight3D Cluster,Decal Cluster,ReflectionProbe Cluster,Occlusion Culling Buffer,Motion Vectors,Internal Buffer"), "set_debug_draw", "get_debug_draw");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_hdr_2d"), "set_use_hdr_2d", "is_using_hdr_2d");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "tonemap_to_window"), "set_tonemap_to_window", "is_tonemapping_to_window");
|
||||
|
||||
#ifndef _3D_DISABLED
|
||||
ADD_GROUP("Scaling 3D", "");
|
||||
|
|
|
|||
|
|
@ -264,6 +264,7 @@ private:
|
|||
bool transparent_bg = false;
|
||||
bool use_hdr_2d = false;
|
||||
bool gen_mipmaps = false;
|
||||
bool tonemap_to_window = false;
|
||||
|
||||
bool snap_controls_to_pixels = true;
|
||||
bool snap_2d_transforms_to_pixel = false;
|
||||
|
|
@ -541,6 +542,9 @@ public:
|
|||
void set_use_hdr_2d(bool p_enable);
|
||||
bool is_using_hdr_2d() const;
|
||||
|
||||
void set_tonemap_to_window(bool p_enable);
|
||||
bool is_tonemapping_to_window() const;
|
||||
|
||||
Ref<ViewportTexture> get_texture() const;
|
||||
|
||||
void set_positional_shadow_atlas_size(int p_size);
|
||||
|
|
|
|||
|
|
@ -578,6 +578,126 @@ bool Window::get_flag(Flags p_flag) const {
|
|||
return flags[p_flag];
|
||||
}
|
||||
|
||||
void Window::set_hdr_output_enabled(bool p_enabled) {
|
||||
ERR_MAIN_THREAD_GUARD;
|
||||
|
||||
hdr_output_enabled = p_enabled;
|
||||
|
||||
if (window_id != DisplayServer::INVALID_WINDOW_ID) {
|
||||
DisplayServer::get_singleton()->window_set_hdr_output_enabled(hdr_output_enabled, window_id);
|
||||
}
|
||||
}
|
||||
|
||||
bool Window::is_hdr_output_enabled() const {
|
||||
ERR_READ_THREAD_GUARD_V(false);
|
||||
|
||||
if (window_id != DisplayServer::INVALID_WINDOW_ID) {
|
||||
hdr_output_enabled = DisplayServer::get_singleton()->window_is_hdr_output_enabled(window_id);
|
||||
}
|
||||
|
||||
return hdr_output_enabled;
|
||||
}
|
||||
|
||||
void Window::set_hdr_output_prefer_high_precision(bool p_enabled) {
|
||||
ERR_MAIN_THREAD_GUARD;
|
||||
|
||||
hdr_output_prefer_high_precision = p_enabled;
|
||||
|
||||
if (window_id != DisplayServer::INVALID_WINDOW_ID) {
|
||||
DisplayServer::get_singleton()->window_set_hdr_output_prefer_high_precision(hdr_output_prefer_high_precision, window_id);
|
||||
}
|
||||
}
|
||||
|
||||
bool Window::is_hdr_output_preferring_high_precision() const {
|
||||
ERR_READ_THREAD_GUARD_V(false);
|
||||
|
||||
if (window_id != DisplayServer::INVALID_WINDOW_ID) {
|
||||
hdr_output_prefer_high_precision = DisplayServer::get_singleton()->window_is_hdr_output_preferring_high_precision(window_id);
|
||||
}
|
||||
|
||||
return hdr_output_prefer_high_precision;
|
||||
}
|
||||
|
||||
void Window::set_hdr_output_use_screen_luminance(bool p_enabled) {
|
||||
ERR_MAIN_THREAD_GUARD;
|
||||
|
||||
hdr_output_use_screen_luminance = p_enabled;
|
||||
|
||||
if (window_id != DisplayServer::INVALID_WINDOW_ID) {
|
||||
DisplayServer::get_singleton()->window_set_hdr_output_use_screen_luminance(hdr_output_use_screen_luminance, window_id);
|
||||
}
|
||||
}
|
||||
|
||||
bool Window::is_hdr_output_using_screen_luminance() const {
|
||||
ERR_READ_THREAD_GUARD_V(false);
|
||||
|
||||
if (window_id != DisplayServer::INVALID_WINDOW_ID) {
|
||||
hdr_output_use_screen_luminance = DisplayServer::get_singleton()->window_is_hdr_output_using_screen_luminance(window_id);
|
||||
}
|
||||
|
||||
return hdr_output_use_screen_luminance;
|
||||
}
|
||||
|
||||
void Window::set_hdr_output_reference_luminance(float p_reference_luminance) {
|
||||
ERR_MAIN_THREAD_GUARD;
|
||||
|
||||
hdr_output_reference_luminance = p_reference_luminance;
|
||||
|
||||
if (window_id != DisplayServer::INVALID_WINDOW_ID) {
|
||||
DisplayServer::get_singleton()->window_set_hdr_output_reference_luminance(hdr_output_reference_luminance, window_id);
|
||||
}
|
||||
}
|
||||
|
||||
float Window::get_hdr_output_reference_luminance() const {
|
||||
ERR_READ_THREAD_GUARD_V(0.0f);
|
||||
|
||||
if (window_id != DisplayServer::INVALID_WINDOW_ID) {
|
||||
hdr_output_reference_luminance = DisplayServer::get_singleton()->window_get_hdr_output_reference_luminance(window_id);
|
||||
}
|
||||
|
||||
return hdr_output_reference_luminance;
|
||||
}
|
||||
|
||||
void Window::set_hdr_output_min_luminance(float p_min_luminance) {
|
||||
ERR_MAIN_THREAD_GUARD;
|
||||
|
||||
hdr_output_min_luminance = p_min_luminance;
|
||||
|
||||
if (window_id != DisplayServer::INVALID_WINDOW_ID) {
|
||||
DisplayServer::get_singleton()->window_set_hdr_output_min_luminance(hdr_output_min_luminance, window_id);
|
||||
}
|
||||
}
|
||||
|
||||
float Window::get_hdr_output_min_luminance() const {
|
||||
ERR_READ_THREAD_GUARD_V(0.0f);
|
||||
|
||||
if (window_id != DisplayServer::INVALID_WINDOW_ID) {
|
||||
hdr_output_min_luminance = DisplayServer::get_singleton()->window_get_hdr_output_min_luminance(window_id);
|
||||
}
|
||||
|
||||
return hdr_output_min_luminance;
|
||||
}
|
||||
|
||||
void Window::set_hdr_output_max_luminance(float p_max_luminance) {
|
||||
ERR_MAIN_THREAD_GUARD;
|
||||
|
||||
hdr_output_max_luminance = p_max_luminance;
|
||||
|
||||
if (window_id != DisplayServer::INVALID_WINDOW_ID) {
|
||||
DisplayServer::get_singleton()->window_set_hdr_output_max_luminance(hdr_output_max_luminance, window_id);
|
||||
}
|
||||
}
|
||||
|
||||
float Window::get_hdr_output_max_luminance() const {
|
||||
ERR_READ_THREAD_GUARD_V(0.0f);
|
||||
|
||||
if (window_id != DisplayServer::INVALID_WINDOW_ID) {
|
||||
hdr_output_max_luminance = DisplayServer::get_singleton()->window_get_hdr_output_max_luminance(window_id);
|
||||
}
|
||||
|
||||
return hdr_output_max_luminance;
|
||||
}
|
||||
|
||||
bool Window::is_maximize_allowed() const {
|
||||
ERR_READ_THREAD_GUARD_V(false);
|
||||
if (window_id != DisplayServer::INVALID_WINDOW_ID) {
|
||||
|
|
@ -678,6 +798,16 @@ void Window::_make_window() {
|
|||
DisplayServer::get_singleton()->window_set_title(tr_title, window_id);
|
||||
DisplayServer::get_singleton()->window_attach_instance_id(get_instance_id(), window_id);
|
||||
|
||||
// Set HDR output settings.
|
||||
DisplayServer::get_singleton()->window_set_hdr_output_enabled(hdr_output_enabled, window_id);
|
||||
DisplayServer::get_singleton()->window_set_hdr_output_prefer_high_precision(hdr_output_prefer_high_precision, window_id);
|
||||
DisplayServer::get_singleton()->window_set_hdr_output_use_screen_luminance(hdr_output_use_screen_luminance, window_id);
|
||||
if (!hdr_output_use_screen_luminance) {
|
||||
DisplayServer::get_singleton()->window_set_hdr_output_reference_luminance(hdr_output_reference_luminance, window_id);
|
||||
DisplayServer::get_singleton()->window_set_hdr_output_min_luminance(hdr_output_min_luminance, window_id);
|
||||
DisplayServer::get_singleton()->window_set_hdr_output_max_luminance(hdr_output_max_luminance, window_id);
|
||||
}
|
||||
|
||||
_update_window_size();
|
||||
|
||||
if (transient_parent) {
|
||||
|
|
@ -1395,6 +1525,15 @@ void Window::_notification(int p_what) {
|
|||
size = DisplayServer::get_singleton()->window_get_size(window_id);
|
||||
focused = DisplayServer::get_singleton()->window_is_focused(window_id);
|
||||
}
|
||||
// Update HDR settings to reflect the current state of the main window.
|
||||
{
|
||||
hdr_output_enabled = DisplayServer::get_singleton()->window_is_hdr_output_enabled(window_id);
|
||||
hdr_output_prefer_high_precision = DisplayServer::get_singleton()->window_is_hdr_output_preferring_high_precision(window_id);
|
||||
hdr_output_use_screen_luminance = DisplayServer::get_singleton()->window_is_hdr_output_using_screen_luminance(window_id);
|
||||
hdr_output_reference_luminance = DisplayServer::get_singleton()->window_get_hdr_output_reference_luminance(window_id);
|
||||
hdr_output_min_luminance = DisplayServer::get_singleton()->window_get_hdr_output_min_luminance(window_id);
|
||||
hdr_output_max_luminance = DisplayServer::get_singleton()->window_get_hdr_output_max_luminance(window_id);
|
||||
}
|
||||
_update_window_size(); // Inform DisplayServer of minimum and maximum size.
|
||||
_update_viewport_size(); // Then feed back to the viewport.
|
||||
_update_window_callbacks();
|
||||
|
|
@ -2916,6 +3055,24 @@ void Window::_bind_methods() {
|
|||
ClassDB::bind_method(D_METHOD("set_flag", "flag", "enabled"), &Window::set_flag);
|
||||
ClassDB::bind_method(D_METHOD("get_flag", "flag"), &Window::get_flag);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_hdr_output_enabled", "enabled"), &Window::set_hdr_output_enabled);
|
||||
ClassDB::bind_method(D_METHOD("is_hdr_output_enabled"), &Window::is_hdr_output_enabled);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_hdr_output_prefer_high_precision", "enabled"), &Window::set_hdr_output_prefer_high_precision);
|
||||
ClassDB::bind_method(D_METHOD("is_hdr_output_preferring_high_precision"), &Window::is_hdr_output_preferring_high_precision);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_hdr_output_use_screen_luminance", "enabled"), &Window::set_hdr_output_use_screen_luminance);
|
||||
ClassDB::bind_method(D_METHOD("is_hdr_output_using_screen_luminance"), &Window::is_hdr_output_using_screen_luminance);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_hdr_output_reference_luminance", "reference_luminance"), &Window::set_hdr_output_reference_luminance);
|
||||
ClassDB::bind_method(D_METHOD("get_hdr_output_reference_luminance"), &Window::get_hdr_output_reference_luminance);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_hdr_output_min_luminance", "min_luminance"), &Window::set_hdr_output_min_luminance);
|
||||
ClassDB::bind_method(D_METHOD("get_hdr_output_min_luminance"), &Window::get_hdr_output_min_luminance);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_hdr_output_max_luminance", "max_luminance"), &Window::set_hdr_output_max_luminance);
|
||||
ClassDB::bind_method(D_METHOD("get_hdr_output_max_luminance"), &Window::get_hdr_output_max_luminance);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("is_maximize_allowed"), &Window::is_maximize_allowed);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("request_attention"), &Window::request_attention);
|
||||
|
|
@ -3098,6 +3255,14 @@ void Window::_bind_methods() {
|
|||
ADD_PROPERTY(PropertyInfo(Variant::INT, "content_scale_stretch", PROPERTY_HINT_ENUM, "Fractional,Integer"), "set_content_scale_stretch", "get_content_scale_stretch");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "content_scale_factor", PROPERTY_HINT_RANGE, "0.5,8.0,0.01"), "set_content_scale_factor", "get_content_scale_factor");
|
||||
|
||||
ADD_GROUP("HDR Output", "hdr_output_");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "hdr_output_enabled"), "set_hdr_output_enabled", "is_hdr_output_enabled");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "hdr_output_prefer_high_precision"), "set_hdr_output_prefer_high_precision", "is_hdr_output_preferring_high_precision");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "hdr_output_use_screen_luminance"), "set_hdr_output_use_screen_luminance", "is_hdr_output_using_screen_luminance");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "hdr_output_reference_luminance", PROPERTY_HINT_RANGE, "0,2000,1,or_greater"), "set_hdr_output_reference_luminance", "get_hdr_output_reference_luminance");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "hdr_output_min_luminance", PROPERTY_HINT_RANGE, "0,2000,1,or_greater"), "set_hdr_output_min_luminance", "get_hdr_output_min_luminance");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "hdr_output_max_luminance", PROPERTY_HINT_RANGE, "0,2000,1,or_greater"), "set_hdr_output_max_luminance", "get_hdr_output_max_luminance");
|
||||
|
||||
#ifndef DISABLE_DEPRECATED
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "auto_translate", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_auto_translate", "is_auto_translating");
|
||||
#endif
|
||||
|
|
@ -3201,6 +3366,10 @@ Window::Window() {
|
|||
|
||||
theme_owner = memnew(ThemeOwner(this));
|
||||
RS::get_singleton()->viewport_set_update_mode(get_viewport_rid(), RS::VIEWPORT_UPDATE_DISABLED);
|
||||
|
||||
// Tonemap the root viewport of this window by default.
|
||||
tonemap_to_window = true;
|
||||
RS::get_singleton()->viewport_set_tonemap_to_screen(get_viewport_rid(), tonemap_to_window);
|
||||
}
|
||||
|
||||
Window::~Window() {
|
||||
|
|
|
|||
|
|
@ -132,6 +132,13 @@ private:
|
|||
WindowInitialPosition initial_position = WINDOW_INITIAL_POSITION_ABSOLUTE;
|
||||
bool force_native = false;
|
||||
|
||||
mutable bool hdr_output_enabled = false;
|
||||
mutable bool hdr_output_prefer_high_precision = false;
|
||||
mutable bool hdr_output_use_screen_luminance = false;
|
||||
mutable float hdr_output_reference_luminance = 80.0f;
|
||||
mutable float hdr_output_min_luminance = 0.0f;
|
||||
mutable float hdr_output_max_luminance = 1000.0f;
|
||||
|
||||
bool use_font_oversampling = false;
|
||||
bool transient = false;
|
||||
bool transient_to_focused = false;
|
||||
|
|
@ -311,6 +318,24 @@ public:
|
|||
void set_flag(Flags p_flag, bool p_enabled);
|
||||
bool get_flag(Flags p_flag) const;
|
||||
|
||||
void set_hdr_output_enabled(bool p_enabled);
|
||||
bool is_hdr_output_enabled() const;
|
||||
|
||||
void set_hdr_output_prefer_high_precision(bool p_enabled);
|
||||
bool is_hdr_output_preferring_high_precision() const;
|
||||
|
||||
void set_hdr_output_use_screen_luminance(bool p_enabled);
|
||||
bool is_hdr_output_using_screen_luminance() const;
|
||||
|
||||
void set_hdr_output_reference_luminance(float p_reference_luminance);
|
||||
float get_hdr_output_reference_luminance() const;
|
||||
|
||||
void set_hdr_output_min_luminance(float p_min_luminance);
|
||||
float get_hdr_output_min_luminance() const;
|
||||
|
||||
void set_hdr_output_max_luminance(float p_max_luminance);
|
||||
float get_hdr_output_max_luminance() const;
|
||||
|
||||
bool is_maximize_allowed() const;
|
||||
|
||||
void request_attention();
|
||||
|
|
|
|||
|
|
@ -810,6 +810,54 @@ DisplayServer::VSyncMode DisplayServer::window_get_vsync_mode(WindowID p_window)
|
|||
return VSyncMode::VSYNC_ENABLED;
|
||||
}
|
||||
|
||||
void DisplayServer::window_set_hdr_output_enabled(const bool p_enabled, WindowID p_window) {
|
||||
WARN_PRINT("HDR output is not supported by this display server.");
|
||||
}
|
||||
|
||||
bool DisplayServer::window_is_hdr_output_enabled(WindowID p_window) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
void DisplayServer::window_set_hdr_output_prefer_high_precision(const bool p_enabled, WindowID p_window) {
|
||||
WARN_PRINT("HDR output is not supported by this display server.");
|
||||
}
|
||||
|
||||
bool DisplayServer::window_is_hdr_output_preferring_high_precision(WindowID p_window) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
void DisplayServer::window_set_hdr_output_use_screen_luminance(const bool p_enabled, WindowID p_window) {
|
||||
WARN_PRINT("HDR output is not supported by this display server.");
|
||||
}
|
||||
|
||||
bool DisplayServer::window_is_hdr_output_using_screen_luminance(WindowID p_window) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
void DisplayServer::window_set_hdr_output_reference_luminance(const float p_reference_luminance, WindowID p_window) {
|
||||
WARN_PRINT("HDR output is not supported by this display server.");
|
||||
}
|
||||
|
||||
float DisplayServer::window_get_hdr_output_reference_luminance(WindowID p_window) const {
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
void DisplayServer::window_set_hdr_output_min_luminance(const float p_min_luminance, WindowID p_window) {
|
||||
WARN_PRINT("HDR output is not supported by this display server.");
|
||||
}
|
||||
|
||||
float DisplayServer::window_get_hdr_output_min_luminance(WindowID p_window) const {
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
void DisplayServer::window_set_hdr_output_max_luminance(const float p_max_luminance, WindowID p_window) {
|
||||
WARN_PRINT("HDR output is not supported by this display server.");
|
||||
}
|
||||
|
||||
float DisplayServer::window_get_hdr_output_max_luminance(WindowID p_window) const {
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
DisplayServer::WindowID DisplayServer::get_focused_window() const {
|
||||
return MAIN_WINDOW_ID; // Proper value for single windows.
|
||||
}
|
||||
|
|
@ -945,6 +993,12 @@ void DisplayServer::_bind_methods() {
|
|||
ClassDB::bind_method(D_METHOD("screen_get_image", "screen"), &DisplayServer::screen_get_image, DEFVAL(SCREEN_OF_MAIN_WINDOW));
|
||||
ClassDB::bind_method(D_METHOD("screen_get_image_rect", "rect"), &DisplayServer::screen_get_image_rect);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("screen_is_hdr_supported", "screen"), &DisplayServer::screen_is_hdr_supported, DEFVAL(SCREEN_OF_MAIN_WINDOW));
|
||||
ClassDB::bind_method(D_METHOD("screen_get_min_luminance", "screen"), &DisplayServer::screen_get_min_luminance, DEFVAL(SCREEN_OF_MAIN_WINDOW));
|
||||
ClassDB::bind_method(D_METHOD("screen_get_max_luminance", "screen"), &DisplayServer::screen_get_max_luminance, DEFVAL(SCREEN_OF_MAIN_WINDOW));
|
||||
ClassDB::bind_method(D_METHOD("screen_get_max_average_luminance", "screen"), &DisplayServer::screen_get_max_average_luminance, DEFVAL(SCREEN_OF_MAIN_WINDOW));
|
||||
ClassDB::bind_method(D_METHOD("screen_get_sdr_white_level", "screen"), &DisplayServer::screen_get_sdr_white_level, DEFVAL(SCREEN_OF_MAIN_WINDOW));
|
||||
|
||||
ClassDB::bind_method(D_METHOD("screen_set_orientation", "orientation", "screen"), &DisplayServer::screen_set_orientation, DEFVAL(SCREEN_OF_MAIN_WINDOW));
|
||||
ClassDB::bind_method(D_METHOD("screen_get_orientation", "screen"), &DisplayServer::screen_get_orientation, DEFVAL(SCREEN_OF_MAIN_WINDOW));
|
||||
|
||||
|
|
@ -1012,6 +1066,19 @@ void DisplayServer::_bind_methods() {
|
|||
ClassDB::bind_method(D_METHOD("window_set_vsync_mode", "vsync_mode", "window_id"), &DisplayServer::window_set_vsync_mode, DEFVAL(MAIN_WINDOW_ID));
|
||||
ClassDB::bind_method(D_METHOD("window_get_vsync_mode", "window_id"), &DisplayServer::window_get_vsync_mode, DEFVAL(MAIN_WINDOW_ID));
|
||||
|
||||
ClassDB::bind_method(D_METHOD("window_set_hdr_output_enabled", "enabled", "window_id"), &DisplayServer::window_set_hdr_output_enabled, DEFVAL(MAIN_WINDOW_ID));
|
||||
ClassDB::bind_method(D_METHOD("window_is_hdr_output_enabled", "window_id"), &DisplayServer::window_is_hdr_output_enabled, DEFVAL(MAIN_WINDOW_ID));
|
||||
ClassDB::bind_method(D_METHOD("window_set_hdr_output_prefer_high_precision", "enabled", "window_id"), &DisplayServer::window_set_hdr_output_prefer_high_precision, DEFVAL(MAIN_WINDOW_ID));
|
||||
ClassDB::bind_method(D_METHOD("window_is_hdr_output_preferring_high_precision", "window_id"), &DisplayServer::window_is_hdr_output_preferring_high_precision, DEFVAL(MAIN_WINDOW_ID));
|
||||
ClassDB::bind_method(D_METHOD("window_set_hdr_output_use_screen_luminance", "enabled", "window_id"), &DisplayServer::window_set_hdr_output_use_screen_luminance, DEFVAL(MAIN_WINDOW_ID));
|
||||
ClassDB::bind_method(D_METHOD("window_is_hdr_output_using_screen_luminance", "window_id"), &DisplayServer::window_is_hdr_output_using_screen_luminance, DEFVAL(MAIN_WINDOW_ID));
|
||||
ClassDB::bind_method(D_METHOD("window_set_hdr_output_reference_luminance", "reference_luminance", "window_id"), &DisplayServer::window_set_hdr_output_reference_luminance, DEFVAL(MAIN_WINDOW_ID));
|
||||
ClassDB::bind_method(D_METHOD("window_get_hdr_output_reference_luminance", "window_id"), &DisplayServer::window_get_hdr_output_reference_luminance, DEFVAL(MAIN_WINDOW_ID));
|
||||
ClassDB::bind_method(D_METHOD("window_set_hdr_output_min_luminance", "min_luminance", "window_id"), &DisplayServer::window_set_hdr_output_min_luminance, DEFVAL(MAIN_WINDOW_ID));
|
||||
ClassDB::bind_method(D_METHOD("window_get_hdr_output_min_luminance", "window_id"), &DisplayServer::window_get_hdr_output_min_luminance, DEFVAL(MAIN_WINDOW_ID));
|
||||
ClassDB::bind_method(D_METHOD("window_set_hdr_output_max_luminance", "max_luminance", "window_id"), &DisplayServer::window_set_hdr_output_max_luminance, DEFVAL(MAIN_WINDOW_ID));
|
||||
ClassDB::bind_method(D_METHOD("window_get_hdr_output_max_luminance", "window_id"), &DisplayServer::window_get_hdr_output_max_luminance, DEFVAL(MAIN_WINDOW_ID));
|
||||
|
||||
ClassDB::bind_method(D_METHOD("window_is_maximize_allowed", "window_id"), &DisplayServer::window_is_maximize_allowed, DEFVAL(MAIN_WINDOW_ID));
|
||||
ClassDB::bind_method(D_METHOD("window_maximize_on_title_dbl_click"), &DisplayServer::window_maximize_on_title_dbl_click);
|
||||
ClassDB::bind_method(D_METHOD("window_minimize_on_title_dbl_click"), &DisplayServer::window_minimize_on_title_dbl_click);
|
||||
|
|
@ -1113,6 +1180,7 @@ void DisplayServer::_bind_methods() {
|
|||
BIND_ENUM_CONSTANT(FEATURE_WINDOW_EMBEDDING);
|
||||
BIND_ENUM_CONSTANT(FEATURE_NATIVE_DIALOG_FILE_MIME);
|
||||
BIND_ENUM_CONSTANT(FEATURE_EMOJI_AND_SYMBOL_PICKER);
|
||||
BIND_ENUM_CONSTANT(FEATURE_HDR);
|
||||
|
||||
BIND_ENUM_CONSTANT(MOUSE_MODE_VISIBLE);
|
||||
BIND_ENUM_CONSTANT(MOUSE_MODE_HIDDEN);
|
||||
|
|
|
|||
|
|
@ -162,6 +162,7 @@ public:
|
|||
FEATURE_WINDOW_EMBEDDING,
|
||||
FEATURE_NATIVE_DIALOG_FILE_MIME,
|
||||
FEATURE_EMOJI_AND_SYMBOL_PICKER,
|
||||
FEATURE_HDR,
|
||||
};
|
||||
|
||||
virtual bool has_feature(Feature p_feature) const = 0;
|
||||
|
|
@ -362,6 +363,13 @@ public:
|
|||
virtual Ref<Image> screen_get_image_rect(const Rect2i &p_rect) const { return Ref<Image>(); }
|
||||
virtual bool is_touchscreen_available() const;
|
||||
|
||||
// Display capabilities for HDR.
|
||||
virtual bool screen_is_hdr_supported(int p_screen = SCREEN_OF_MAIN_WINDOW) const { return false; }
|
||||
virtual float screen_get_min_luminance(int p_screen = SCREEN_OF_MAIN_WINDOW) const { return 0.0f; }
|
||||
virtual float screen_get_max_luminance(int p_screen = SCREEN_OF_MAIN_WINDOW) const { return 0.0f; }
|
||||
virtual float screen_get_max_average_luminance(int p_screen = SCREEN_OF_MAIN_WINDOW) const { return 0.0f; }
|
||||
virtual float screen_get_sdr_white_level(int p_screen = SCREEN_OF_MAIN_WINDOW) const { return 0.0f; }
|
||||
|
||||
// Keep the ScreenOrientation enum values in sync with the `display/window/handheld/orientation`
|
||||
// project setting hint.
|
||||
enum ScreenOrientation {
|
||||
|
|
@ -483,6 +491,19 @@ public:
|
|||
virtual void window_set_vsync_mode(VSyncMode p_vsync_mode, WindowID p_window = MAIN_WINDOW_ID);
|
||||
virtual VSyncMode window_get_vsync_mode(WindowID p_window) const;
|
||||
|
||||
virtual void window_set_hdr_output_enabled(const bool p_enabled, WindowID p_window = MAIN_WINDOW_ID);
|
||||
virtual bool window_is_hdr_output_enabled(WindowID p_window = MAIN_WINDOW_ID) const;
|
||||
virtual void window_set_hdr_output_prefer_high_precision(const bool p_enabled, WindowID p_window = MAIN_WINDOW_ID);
|
||||
virtual bool window_is_hdr_output_preferring_high_precision(WindowID p_window = MAIN_WINDOW_ID) const;
|
||||
virtual void window_set_hdr_output_use_screen_luminance(const bool p_enabled, WindowID p_window = MAIN_WINDOW_ID);
|
||||
virtual bool window_is_hdr_output_using_screen_luminance(WindowID p_window = MAIN_WINDOW_ID) const;
|
||||
virtual void window_set_hdr_output_reference_luminance(const float p_reference_luminance, WindowID p_window = MAIN_WINDOW_ID);
|
||||
virtual float window_get_hdr_output_reference_luminance(WindowID p_window = MAIN_WINDOW_ID) const;
|
||||
virtual void window_set_hdr_output_min_luminance(const float p_min_luminance, WindowID p_window = MAIN_WINDOW_ID);
|
||||
virtual float window_get_hdr_output_min_luminance(WindowID p_window = MAIN_WINDOW_ID) const;
|
||||
virtual void window_set_hdr_output_max_luminance(const float p_max_luminance, WindowID p_window = MAIN_WINDOW_ID);
|
||||
virtual float window_get_hdr_output_max_luminance(WindowID p_window = MAIN_WINDOW_ID) const;
|
||||
|
||||
virtual bool window_is_maximize_allowed(WindowID p_window = MAIN_WINDOW_ID) const = 0;
|
||||
|
||||
virtual void window_set_flag(WindowFlags p_flag, bool p_enabled, WindowID p_window = MAIN_WINDOW_ID) = 0;
|
||||
|
|
|
|||
|
|
@ -120,6 +120,13 @@ void ToneMapper::tonemapper(RID p_source_color, RID p_dst_framebuffer, const Ton
|
|||
tonemap.push_constant.auto_exposure_scale = p_settings.auto_exposure_scale;
|
||||
tonemap.push_constant.luminance_multiplier = p_settings.luminance_multiplier;
|
||||
|
||||
// Static values that work well in most cases
|
||||
// Consider reading from the scene itself in the future.
|
||||
tonemap.push_constant.source_min_value = 0.0f;
|
||||
tonemap.push_constant.source_max_value = 16.0f;
|
||||
tonemap.push_constant.dest_min_value = p_settings.min_value;
|
||||
tonemap.push_constant.dest_max_value = p_settings.max_value;
|
||||
|
||||
tonemap.push_constant.flags |= p_settings.use_color_correction ? TONEMAP_FLAG_USE_COLOR_CORRECTION : 0;
|
||||
|
||||
tonemap.push_constant.flags |= p_settings.use_fxaa ? TONEMAP_FLAG_USE_FXAA : 0;
|
||||
|
|
@ -206,6 +213,13 @@ void ToneMapper::tonemapper(RD::DrawListID p_subpass_draw_list, RID p_source_col
|
|||
tonemap.push_constant.white = p_settings.white;
|
||||
tonemap.push_constant.auto_exposure_scale = p_settings.auto_exposure_scale;
|
||||
|
||||
// Static values that work well in most cases
|
||||
// Consider reading from the scene itself in the future.
|
||||
tonemap.push_constant.source_min_value = 0.0f;
|
||||
tonemap.push_constant.source_max_value = 16.0f;
|
||||
tonemap.push_constant.dest_min_value = p_settings.min_value;
|
||||
tonemap.push_constant.dest_max_value = p_settings.max_value;
|
||||
|
||||
tonemap.push_constant.flags |= p_settings.use_color_correction ? TONEMAP_FLAG_USE_COLOR_CORRECTION : 0;
|
||||
|
||||
tonemap.push_constant.flags |= p_settings.use_debanding ? TONEMAP_FLAG_USE_DEBANDING : 0;
|
||||
|
|
|
|||
|
|
@ -87,6 +87,11 @@ private:
|
|||
float white; // 4 - 88
|
||||
float auto_exposure_scale; // 4 - 92
|
||||
float luminance_multiplier; // 4 - 96
|
||||
|
||||
float source_min_value; // 4 - 100
|
||||
float source_max_value; // 4 - 104
|
||||
float dest_min_value; // 4 - 108
|
||||
float dest_max_value; // 4 - 112
|
||||
};
|
||||
|
||||
/* tonemap actually writes to a framebuffer, which is
|
||||
|
|
@ -126,6 +131,8 @@ public:
|
|||
RS::EnvironmentToneMapper tonemap_mode = RS::ENV_TONE_MAPPER_LINEAR;
|
||||
float exposure = 1.0;
|
||||
float white = 1.0;
|
||||
float min_value = 0.0;
|
||||
float max_value = 1.0;
|
||||
|
||||
bool use_auto_exposure = false;
|
||||
float auto_exposure_scale = 0.5;
|
||||
|
|
|
|||
|
|
@ -43,9 +43,15 @@ void RendererCompositorRD::blit_render_targets_to_screen(DisplayServer::WindowID
|
|||
return;
|
||||
}
|
||||
|
||||
_ensure_blit_pipelines();
|
||||
|
||||
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin_for_screen(p_screen);
|
||||
ERR_FAIL_COND(draw_list == RD::INVALID_ID);
|
||||
|
||||
const RD::ColorSpace color_space = RD::get_singleton()->screen_get_color_space(p_screen);
|
||||
const float reference_luminance = RD::get_singleton()->get_context_driver()->window_get_hdr_output_reference_luminance(p_screen);
|
||||
const float reference_multiplier = _compute_reference_multiplier(color_space, reference_luminance);
|
||||
|
||||
for (int i = 0; i < p_amount; i++) {
|
||||
RID rd_texture = texture_storage->render_target_get_rd_texture(p_render_targets[i].render_target);
|
||||
ERR_CONTINUE(rd_texture.is_null());
|
||||
|
|
@ -65,6 +71,7 @@ void RendererCompositorRD::blit_render_targets_to_screen(DisplayServer::WindowID
|
|||
|
||||
Size2 screen_size(RD::get_singleton()->screen_get_width(p_screen), RD::get_singleton()->screen_get_height(p_screen));
|
||||
BlitMode mode = p_render_targets[i].lens_distortion.apply ? BLIT_MODE_LENS : (p_render_targets[i].multi_view.use_layer ? BLIT_MODE_USE_LAYER : BLIT_MODE_NORMAL);
|
||||
|
||||
RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blit.pipelines[mode]);
|
||||
RD::get_singleton()->draw_list_bind_index_array(draw_list, blit.array);
|
||||
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, render_target_descriptors[rd_texture], 0);
|
||||
|
|
@ -94,7 +101,9 @@ void RendererCompositorRD::blit_render_targets_to_screen(DisplayServer::WindowID
|
|||
blit.push_constant.k2 = p_render_targets[i].lens_distortion.k2;
|
||||
blit.push_constant.upscale = p_render_targets[i].lens_distortion.upscale;
|
||||
blit.push_constant.aspect_ratio = p_render_targets[i].lens_distortion.aspect_ratio;
|
||||
blit.push_constant.convert_to_srgb = texture_storage->render_target_is_using_hdr(p_render_targets[i].render_target);
|
||||
blit.push_constant.source_is_srgb = !texture_storage->render_target_is_using_hdr(p_render_targets[i].render_target);
|
||||
blit.push_constant.target_color_space = color_space;
|
||||
blit.push_constant.reference_multiplier = reference_multiplier;
|
||||
|
||||
RD::get_singleton()->draw_list_set_push_constant(draw_list, &blit.push_constant, sizeof(BlitPushConstant));
|
||||
RD::get_singleton()->draw_list_draw(draw_list, true);
|
||||
|
|
@ -129,16 +138,8 @@ void RendererCompositorRD::initialize() {
|
|||
blit_modes.push_back("\n");
|
||||
|
||||
blit.shader.initialize(blit_modes);
|
||||
|
||||
blit.shader_version = blit.shader.version_create();
|
||||
|
||||
for (int i = 0; i < BLIT_MODE_MAX; i++) {
|
||||
blit.pipelines[i] = RD::get_singleton()->render_pipeline_create(blit.shader.version_get_shader(blit.shader_version, i), RD::get_singleton()->screen_get_framebuffer_format(DisplayServer::MAIN_WINDOW_ID), RD::INVALID_ID, RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), i == BLIT_MODE_NORMAL_ALPHA ? RenderingDevice::PipelineColorBlendState::create_blend() : RenderingDevice::PipelineColorBlendState::create_disabled(), 0);
|
||||
|
||||
// Unload shader modules to save memory.
|
||||
RD::get_singleton()->shader_destroy_modules(blit.shader.version_get_shader(blit.shader_version, i));
|
||||
}
|
||||
|
||||
//create index array for copy shader
|
||||
Vector<uint8_t> pv;
|
||||
pv.resize(6 * 2);
|
||||
|
|
@ -178,6 +179,39 @@ void RendererCompositorRD::finalize() {
|
|||
RD::get_singleton()->free(blit.sampler);
|
||||
}
|
||||
|
||||
void RendererCompositorRD::_ensure_blit_pipelines() {
|
||||
RenderingDevice::FramebufferFormatID main_window_format = RD::get_singleton()->screen_get_framebuffer_format(DisplayServer::MAIN_WINDOW_ID);
|
||||
if (main_window_format != prev_main_window_format) {
|
||||
for (int i = 0; i < BLIT_MODE_MAX; i++) {
|
||||
if (blit.pipelines[i].is_valid()) {
|
||||
RD::get_singleton()->free(blit.pipelines[i]);
|
||||
}
|
||||
|
||||
blit.pipelines[i] = RD::get_singleton()->render_pipeline_create(blit.shader.version_get_shader(blit.shader_version, i), main_window_format, RD::INVALID_ID, RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), i == BLIT_MODE_NORMAL_ALPHA ? RenderingDevice::PipelineColorBlendState::create_blend() : RenderingDevice::PipelineColorBlendState::create_disabled(), 0);
|
||||
}
|
||||
|
||||
prev_main_window_format = main_window_format;
|
||||
}
|
||||
}
|
||||
|
||||
float RendererCompositorRD::_compute_reference_multiplier(RD::ColorSpace p_color_space, const float p_reference_luminance) {
|
||||
switch (p_color_space) {
|
||||
case RD::COLOR_SPACE_HDR10_ST2084:
|
||||
// Max brightness of ST2084 is 10000 nits, we output from 0 to 1.
|
||||
return p_reference_luminance / 10000.0f;
|
||||
case RD::COLOR_SPACE_SRGB_LINEAR:
|
||||
#ifdef WINDOWS_ENABLED
|
||||
// Windows expects multiples of 80 nits.
|
||||
return p_reference_luminance / 80.0f;
|
||||
#else
|
||||
// Default to 100 nits.
|
||||
return p_reference_luminance / 100.0f;
|
||||
#endif
|
||||
default:
|
||||
return 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
void RendererCompositorRD::set_boot_image(const Ref<Image> &p_image, const Color &p_color, bool p_scale, bool p_use_filter) {
|
||||
if (p_image.is_null() || p_image->is_empty()) {
|
||||
return;
|
||||
|
|
@ -189,6 +223,8 @@ void RendererCompositorRD::set_boot_image(const Ref<Image> &p_image, const Color
|
|||
return;
|
||||
}
|
||||
|
||||
_ensure_blit_pipelines();
|
||||
|
||||
RID texture = texture_storage->texture_allocate();
|
||||
texture_storage->texture_2d_initialize(texture, p_image);
|
||||
RID rd_texture = texture_storage->texture_get_rd_texture(texture, false);
|
||||
|
|
@ -225,6 +261,10 @@ void RendererCompositorRD::set_boot_image(const Ref<Image> &p_image, const Color
|
|||
screenrect.position /= window_size;
|
||||
screenrect.size /= window_size;
|
||||
|
||||
const RD::ColorSpace color_space = RD::get_singleton()->screen_get_color_space(DisplayServer::MAIN_WINDOW_ID);
|
||||
const float reference_luminance = RD::get_singleton()->get_context_driver()->window_get_hdr_output_reference_luminance(DisplayServer::MAIN_WINDOW_ID);
|
||||
const float reference_multiplier = _compute_reference_multiplier(color_space, reference_luminance);
|
||||
|
||||
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin_for_screen(DisplayServer::MAIN_WINDOW_ID, p_color);
|
||||
|
||||
RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blit.pipelines[BLIT_MODE_NORMAL_ALPHA]);
|
||||
|
|
@ -250,7 +290,9 @@ void RendererCompositorRD::set_boot_image(const Ref<Image> &p_image, const Color
|
|||
blit.push_constant.k2 = 0;
|
||||
blit.push_constant.upscale = 1.0;
|
||||
blit.push_constant.aspect_ratio = 1.0;
|
||||
blit.push_constant.convert_to_srgb = false;
|
||||
blit.push_constant.source_is_srgb = true;
|
||||
blit.push_constant.target_color_space = color_space;
|
||||
blit.push_constant.reference_multiplier = reference_multiplier;
|
||||
|
||||
RD::get_singleton()->draw_list_set_push_constant(draw_list, &blit.push_constant, sizeof(BlitPushConstant));
|
||||
RD::get_singleton()->draw_list_draw(draw_list, true);
|
||||
|
|
|
|||
|
|
@ -69,21 +69,23 @@ protected:
|
|||
};
|
||||
|
||||
struct BlitPushConstant {
|
||||
float src_rect[4];
|
||||
float dst_rect[4];
|
||||
float src_rect[4]; // 16 - 16
|
||||
float dst_rect[4]; // 16 - 32
|
||||
|
||||
float rotation_sin;
|
||||
float rotation_cos;
|
||||
float pad[2];
|
||||
float rotation_sin; // 4 - 36
|
||||
float rotation_cos; // 4 - 40
|
||||
|
||||
float eye_center[2];
|
||||
float k1;
|
||||
float k2;
|
||||
float eye_center[2]; // 8 - 48
|
||||
float k1; // 4 - 52
|
||||
float k2; // 4 - 56
|
||||
|
||||
float upscale;
|
||||
float aspect_ratio;
|
||||
uint32_t layer;
|
||||
uint32_t convert_to_srgb;
|
||||
float upscale; // 4 - 60
|
||||
float aspect_ratio; // 4 - 64
|
||||
uint32_t layer; // 4 - 68
|
||||
uint32_t source_is_srgb; // 4 - 72
|
||||
|
||||
uint32_t target_color_space; // 4 - 76
|
||||
float reference_multiplier; // 4 - 80
|
||||
};
|
||||
|
||||
struct Blit {
|
||||
|
|
@ -104,6 +106,10 @@ protected:
|
|||
static uint64_t frame;
|
||||
static RendererCompositorRD *singleton;
|
||||
|
||||
RenderingDevice::FramebufferFormatID prev_main_window_format;
|
||||
void _ensure_blit_pipelines();
|
||||
float _compute_reference_multiplier(RD::ColorSpace p_color_space, const float p_reference_luminance);
|
||||
|
||||
public:
|
||||
RendererUtilities *get_utilities() { return utilities; }
|
||||
RendererLightStorage *get_light_storage() { return light_storage; }
|
||||
|
|
|
|||
|
|
@ -630,6 +630,8 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
|
|||
tonemap.tonemap_mode = environment_get_tone_mapper(p_render_data->environment);
|
||||
tonemap.white = environment_get_white(p_render_data->environment);
|
||||
tonemap.exposure = environment_get_exposure(p_render_data->environment);
|
||||
tonemap.min_value = environment_get_min_value(p_render_data->environment);
|
||||
tonemap.max_value = environment_get_max_value(p_render_data->environment);
|
||||
}
|
||||
|
||||
tonemap.use_color_correction = false;
|
||||
|
|
@ -724,6 +726,8 @@ void RendererSceneRenderRD::_post_process_subpass(RID p_source_texture, RID p_fr
|
|||
tonemap.tonemap_mode = environment_get_tone_mapper(p_render_data->environment);
|
||||
tonemap.exposure = environment_get_exposure(p_render_data->environment);
|
||||
tonemap.white = environment_get_white(p_render_data->environment);
|
||||
tonemap.min_value = environment_get_min_value(p_render_data->environment);
|
||||
tonemap.max_value = environment_get_max_value(p_render_data->environment);
|
||||
}
|
||||
|
||||
// We don't support glow or auto exposure here, if they are needed, don't use subpasses!
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ layout(push_constant, std140) uniform Pos {
|
|||
|
||||
float rotation_sin;
|
||||
float rotation_cos;
|
||||
vec2 pad;
|
||||
|
||||
vec2 eye_center;
|
||||
float k1;
|
||||
|
|
@ -19,7 +18,10 @@ layout(push_constant, std140) uniform Pos {
|
|||
float upscale;
|
||||
float aspect_ratio;
|
||||
uint layer;
|
||||
bool convert_to_srgb;
|
||||
bool source_is_srgb;
|
||||
|
||||
uint target_color_space;
|
||||
float reference_multiplier;
|
||||
}
|
||||
data;
|
||||
|
||||
|
|
@ -50,7 +52,6 @@ layout(push_constant, std140) uniform Pos {
|
|||
|
||||
float rotation_sin;
|
||||
float rotation_cos;
|
||||
vec2 pad;
|
||||
|
||||
vec2 eye_center;
|
||||
float k1;
|
||||
|
|
@ -59,7 +60,10 @@ layout(push_constant, std140) uniform Pos {
|
|||
float upscale;
|
||||
float aspect_ratio;
|
||||
uint layer;
|
||||
bool convert_to_srgb;
|
||||
bool source_is_srgb;
|
||||
|
||||
uint target_color_space;
|
||||
float reference_multiplier;
|
||||
}
|
||||
data;
|
||||
|
||||
|
|
@ -73,6 +77,15 @@ layout(binding = 0) uniform sampler2DArray src_rt;
|
|||
layout(binding = 0) uniform sampler2D src_rt;
|
||||
#endif
|
||||
|
||||
// Keep in sync with RenderingDeviceCommons::ColorSpace
|
||||
#define COLOR_SPACE_SRGB_LINEAR 0
|
||||
#define COLOR_SPACE_SRGB_NONLINEAR 1
|
||||
#define COLOR_SPACE_HDR10_ST2084 2
|
||||
|
||||
vec3 srgb_to_linear(vec3 color) {
|
||||
return mix(pow((color.rgb + vec3(0.055)) * (1.0 / (1.0 + 0.055)), vec3(2.4)), color.rgb * (1.0 / 12.92), lessThan(color.rgb, vec3(0.04045)));
|
||||
}
|
||||
|
||||
vec3 linear_to_srgb(vec3 color) {
|
||||
// If going to srgb, clamp from 0 to 1.
|
||||
color = clamp(color, vec3(0.0), vec3(1.0));
|
||||
|
|
@ -80,6 +93,29 @@ vec3 linear_to_srgb(vec3 color) {
|
|||
return mix((vec3(1.0f) + a) * pow(color.rgb, vec3(1.0f / 2.4f)) - a, 12.92f * color.rgb, lessThan(color.rgb, vec3(0.0031308f)));
|
||||
}
|
||||
|
||||
vec3 rec709_to_rec2020(vec3 color) {
|
||||
const mat3 conversion = mat3(
|
||||
0.627402, 0.069095, 0.016394,
|
||||
0.329292, 0.919544, 0.088028,
|
||||
0.043306, 0.011360, 0.895578);
|
||||
return conversion * color;
|
||||
}
|
||||
|
||||
vec3 linear_to_st2084(vec3 color) {
|
||||
// Linear color should already be adjusted between 0 and 10,000 nits.
|
||||
color = clamp(color, vec3(0.0), vec3(1.0));
|
||||
|
||||
// Apply ST2084 curve
|
||||
const float c1 = 0.8359375;
|
||||
const float c2 = 18.8515625;
|
||||
const float c3 = 18.6875;
|
||||
const float m1 = 0.1593017578125;
|
||||
const float m2 = 78.84375;
|
||||
vec3 cp = pow(abs(color), vec3(m1));
|
||||
|
||||
return pow((c1 + c2 * cp) / (1 + c3 * cp), vec3(m2));
|
||||
}
|
||||
|
||||
void main() {
|
||||
#ifdef APPLY_LENS_DISTORTION
|
||||
vec2 coords = uv * 2.0 - 1.0;
|
||||
|
|
@ -116,7 +152,33 @@ void main() {
|
|||
color = texture(src_rt, uv);
|
||||
#endif
|
||||
|
||||
if (data.convert_to_srgb) {
|
||||
color.rgb = linear_to_srgb(color.rgb); // Regular linear -> SRGB conversion.
|
||||
// Colorspace conversion for final blit
|
||||
if (data.target_color_space == COLOR_SPACE_SRGB_LINEAR) {
|
||||
if (data.source_is_srgb == true) {
|
||||
// sRGB -> linear conversion
|
||||
color.rgb = srgb_to_linear(color.rgb);
|
||||
}
|
||||
|
||||
// Adjust brightness of SDR content to reference luminance
|
||||
color.rgb *= data.reference_multiplier;
|
||||
} else if (data.target_color_space == COLOR_SPACE_SRGB_NONLINEAR) {
|
||||
if (data.source_is_srgb == false) {
|
||||
// linear -> sRGB conversion
|
||||
color.rgb = linear_to_srgb(color.rgb);
|
||||
}
|
||||
} else if (data.target_color_space == COLOR_SPACE_HDR10_ST2084) {
|
||||
if (data.source_is_srgb == true) {
|
||||
// sRGB -> linear conversion
|
||||
color.rgb = srgb_to_linear(color.rgb);
|
||||
}
|
||||
|
||||
// Convert to Rec.2020 primaries
|
||||
color.rgb = rec709_to_rec2020(color.rgb);
|
||||
|
||||
// Adjust brightness of SDR content to reference luminance
|
||||
color.rgb *= data.reference_multiplier;
|
||||
|
||||
// Apply the ST2084 curve
|
||||
color.rgb = linear_to_st2084(color.rgb);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -97,6 +97,11 @@ layout(push_constant, std430) uniform Params {
|
|||
float white;
|
||||
float auto_exposure_scale;
|
||||
float luminance_multiplier;
|
||||
|
||||
float source_min_value;
|
||||
float source_max_value;
|
||||
float dest_min_value;
|
||||
float dest_max_value;
|
||||
}
|
||||
params;
|
||||
|
||||
|
|
@ -344,6 +349,14 @@ vec3 linear_to_srgb(vec3 color) {
|
|||
return mix((vec3(1.0f) + a) * pow(color.rgb, vec3(1.0f / 2.4f)) - a, 12.92f * color.rgb, lessThan(color.rgb, vec3(0.0031308f)));
|
||||
}
|
||||
|
||||
vec3 normalize(vec3 value, vec3 min, vec3 max) {
|
||||
return (value - min) / (max - min);
|
||||
}
|
||||
|
||||
vec3 denormalize(vec3 value, vec3 min, vec3 max) {
|
||||
return value * (max - min) + min;
|
||||
}
|
||||
|
||||
#define TONEMAPPER_LINEAR 0
|
||||
#define TONEMAPPER_REINHARD 1
|
||||
#define TONEMAPPER_FILMIC 2
|
||||
|
|
@ -353,17 +366,26 @@ vec3 linear_to_srgb(vec3 color) {
|
|||
vec3 apply_tonemapping(vec3 color, float white) { // inputs are LINEAR
|
||||
// Ensure color values passed to tonemappers are positive.
|
||||
// They can be negative in the case of negative lights, which leads to undesired behavior.
|
||||
// Linear is special: it always passes through with no adjustments.
|
||||
|
||||
if (params.tonemapper == TONEMAPPER_LINEAR) {
|
||||
return color;
|
||||
} else if (params.tonemapper == TONEMAPPER_REINHARD) {
|
||||
return tonemap_reinhard(max(vec3(0.0f), color), white);
|
||||
color = tonemap_reinhard(max(vec3(0.0f), color), white);
|
||||
} else if (params.tonemapper == TONEMAPPER_FILMIC) {
|
||||
return tonemap_filmic(max(vec3(0.0f), color), white);
|
||||
color = tonemap_filmic(max(vec3(0.0f), color), white);
|
||||
} else if (params.tonemapper == TONEMAPPER_ACES) {
|
||||
return tonemap_aces(max(vec3(0.0f), color), white);
|
||||
color = tonemap_aces(max(vec3(0.0f), color), white);
|
||||
} else { // TONEMAPPER_AGX
|
||||
return tonemap_agx(color);
|
||||
color = tonemap_agx(color);
|
||||
}
|
||||
|
||||
// Expand color to the target output range for HDR render targets.
|
||||
if (!bool(params.flags & FLAG_CONVERT_TO_SRGB)) {
|
||||
color = denormalize(color, vec3(params.dest_min_value), vec3(params.dest_max_value));
|
||||
}
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
#ifdef USE_MULTIVIEW
|
||||
|
|
@ -410,14 +432,33 @@ vec3 gather_glow(sampler2D tex, vec2 uv) { // sample all selected glow levels
|
|||
#define GLOW_MODE_REPLACE 3
|
||||
#define GLOW_MODE_MIX 4
|
||||
|
||||
vec3 apply_glow(vec3 color, vec3 glow) { // apply glow using the selected blending mode
|
||||
vec3 apply_glow(vec3 color, vec3 glow, bool hdrInput) { // apply glow using the selected blending mode
|
||||
if (params.glow_mode == GLOW_MODE_ADD) {
|
||||
return color + glow;
|
||||
} else if (params.glow_mode == GLOW_MODE_SCREEN) {
|
||||
if (hdrInput) {
|
||||
// Compress the color and glow from scene intensity to [0, 1] to avoid artifacts due to the color clamping.
|
||||
color = normalize(color, vec3(params.source_min_value), vec3(params.source_max_value));
|
||||
glow = normalize(glow, vec3(params.source_min_value), vec3(params.source_max_value));
|
||||
}
|
||||
|
||||
// Needs color clamping.
|
||||
glow.rgb = clamp(glow.rgb, vec3(0.0f), vec3(1.0f));
|
||||
return max((color + glow) - (color * glow), vec3(0.0));
|
||||
color = max((color + glow) - (color * glow), vec3(0.0));
|
||||
|
||||
if (hdrInput) {
|
||||
// Expand the color back to the original intensity range.
|
||||
color = denormalize(color, vec3(params.source_min_value), vec3(params.source_max_value));
|
||||
}
|
||||
|
||||
return color;
|
||||
} else if (params.glow_mode == GLOW_MODE_SOFTLIGHT) {
|
||||
if (hdrInput) {
|
||||
// Compress the color and glow from scene intensity to [0, 1] to avoid artifacts due to the color clamping.
|
||||
color = normalize(color, vec3(params.source_min_value), vec3(params.source_max_value));
|
||||
glow = normalize(glow, vec3(params.source_min_value), vec3(params.source_max_value));
|
||||
}
|
||||
|
||||
// Needs color clamping.
|
||||
glow.rgb = clamp(glow.rgb, vec3(0.0f), vec3(1.0f));
|
||||
glow = glow * vec3(0.5f) + vec3(0.5f);
|
||||
|
|
@ -425,6 +466,12 @@ vec3 apply_glow(vec3 color, vec3 glow) { // apply glow using the selected blendi
|
|||
color.r = (glow.r <= 0.5f) ? (color.r - (1.0f - 2.0f * glow.r) * color.r * (1.0f - color.r)) : (((glow.r > 0.5f) && (color.r <= 0.25f)) ? (color.r + (2.0f * glow.r - 1.0f) * (4.0f * color.r * (4.0f * color.r + 1.0f) * (color.r - 1.0f) + 7.0f * color.r)) : (color.r + (2.0f * glow.r - 1.0f) * (sqrt(color.r) - color.r)));
|
||||
color.g = (glow.g <= 0.5f) ? (color.g - (1.0f - 2.0f * glow.g) * color.g * (1.0f - color.g)) : (((glow.g > 0.5f) && (color.g <= 0.25f)) ? (color.g + (2.0f * glow.g - 1.0f) * (4.0f * color.g * (4.0f * color.g + 1.0f) * (color.g - 1.0f) + 7.0f * color.g)) : (color.g + (2.0f * glow.g - 1.0f) * (sqrt(color.g) - color.g)));
|
||||
color.b = (glow.b <= 0.5f) ? (color.b - (1.0f - 2.0f * glow.b) * color.b * (1.0f - color.b)) : (((glow.b > 0.5f) && (color.b <= 0.25f)) ? (color.b + (2.0f * glow.b - 1.0f) * (4.0f * color.b * (4.0f * color.b + 1.0f) * (color.b - 1.0f) + 7.0f * color.b)) : (color.b + (2.0f * glow.b - 1.0f) * (sqrt(color.b) - color.b)));
|
||||
|
||||
if (hdrInput) {
|
||||
// Expand the color back to the original intensity range.
|
||||
color = denormalize(color, vec3(params.source_min_value), vec3(params.source_max_value));
|
||||
}
|
||||
|
||||
return color;
|
||||
} else { //replace
|
||||
return glow;
|
||||
|
|
@ -579,7 +626,7 @@ void main() {
|
|||
glow = linear_to_srgb(glow);
|
||||
}
|
||||
|
||||
color.rgb = apply_glow(color.rgb, glow);
|
||||
color.rgb = apply_glow(color.rgb, glow, !bool(params.flags & FLAG_CONVERT_TO_SRGB));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -799,7 +799,7 @@ void MaterialStorage::MaterialData::update_uniform_buffer(const HashMap<StringNa
|
|||
|
||||
} else if (E.value.default_value.size()) {
|
||||
//default value
|
||||
_fill_std140_ubo_value(E.value.type, E.value.default_value, data, p_use_linear_color);
|
||||
_fill_std140_ubo_value(E.value.type, E.value.default_value, data, E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_SOURCE_COLOR && p_use_linear_color);
|
||||
//value=E.value.default_value;
|
||||
} else {
|
||||
//zero because it was not provided
|
||||
|
|
|
|||
|
|
@ -1266,9 +1266,12 @@ public:
|
|||
|
||||
// Tonemap
|
||||
PASS4(environment_set_tonemap, RID, RS::EnvironmentToneMapper, float, float)
|
||||
PASS3(environment_set_tonemap_range, RID, float, float)
|
||||
PASS1RC(RS::EnvironmentToneMapper, environment_get_tone_mapper, RID)
|
||||
PASS1RC(float, environment_get_exposure, RID)
|
||||
PASS1RC(float, environment_get_white, RID)
|
||||
PASS1RC(float, environment_get_min_value, RID)
|
||||
PASS1RC(float, environment_get_max_value, RID)
|
||||
|
||||
// Fog
|
||||
PASS11(environment_set_fog, RID, bool, const Color &, float, float, float, float, float, float, float, RS::EnvironmentFogMode)
|
||||
|
|
|
|||
|
|
@ -365,6 +365,10 @@ void RendererSceneRender::environment_set_tonemap(RID p_env, RS::EnvironmentTone
|
|||
environment_storage.environment_set_tonemap(p_env, p_tone_mapper, p_exposure, p_white);
|
||||
}
|
||||
|
||||
void RendererSceneRender::environment_set_tonemap_range(RID p_env, float p_min_value, float p_max_value) {
|
||||
environment_storage.environment_set_tonemap_range(p_env, p_min_value, p_max_value);
|
||||
}
|
||||
|
||||
RS::EnvironmentToneMapper RendererSceneRender::environment_get_tone_mapper(RID p_env) const {
|
||||
return environment_storage.environment_get_tone_mapper(p_env);
|
||||
}
|
||||
|
|
@ -377,6 +381,14 @@ float RendererSceneRender::environment_get_white(RID p_env) const {
|
|||
return environment_storage.environment_get_white(p_env);
|
||||
}
|
||||
|
||||
float RendererSceneRender::environment_get_min_value(RID p_env) const {
|
||||
return environment_storage.environment_get_min_value(p_env);
|
||||
}
|
||||
|
||||
float RendererSceneRender::environment_get_max_value(RID p_env) const {
|
||||
return environment_storage.environment_get_max_value(p_env);
|
||||
}
|
||||
|
||||
// Fog
|
||||
|
||||
void RendererSceneRender::environment_set_fog(RID p_env, bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_aerial_perspective, float p_sky_affect, RS::EnvironmentFogMode p_mode) {
|
||||
|
|
|
|||
|
|
@ -136,9 +136,12 @@ public:
|
|||
|
||||
// Tonemap
|
||||
void environment_set_tonemap(RID p_env, RS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white);
|
||||
void environment_set_tonemap_range(RID p_env, float p_min_value, float p_max_value);
|
||||
RS::EnvironmentToneMapper environment_get_tone_mapper(RID p_env) const;
|
||||
float environment_get_exposure(RID p_env) const;
|
||||
float environment_get_white(RID p_env) const;
|
||||
float environment_get_min_value(RID p_env) const;
|
||||
float environment_get_max_value(RID p_env) const;
|
||||
|
||||
// Fog
|
||||
void environment_set_fog(RID p_env, bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_aerial_perspective, float p_sky_affect, RS::EnvironmentFogMode p_mode);
|
||||
|
|
|
|||
|
|
@ -333,6 +333,27 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport) {
|
|||
// The scene renderer will still copy over the last frame, so we need to clear the render target.
|
||||
force_clear_render_target = true;
|
||||
}
|
||||
|
||||
// Check if the viewport is tonemapping to the screen.
|
||||
if (p_viewport->tonemap_to_screen) {
|
||||
DisplayServer::WindowID parent_window = _get_containing_window(p_viewport);
|
||||
if (parent_window != DisplayServer::INVALID_WINDOW_ID) {
|
||||
RenderingContextDriver *context_driver = RD::get_singleton()->get_context_driver();
|
||||
|
||||
if (context_driver->window_get_hdr_output_enabled(parent_window)) {
|
||||
float min_luminance = context_driver->window_get_hdr_output_min_luminance(parent_window);
|
||||
float max_luminance = context_driver->window_get_hdr_output_max_luminance(parent_window);
|
||||
float reference_luminance = context_driver->window_get_hdr_output_reference_luminance(parent_window);
|
||||
|
||||
float min_value = MAX(min_luminance / MAX(reference_luminance, 1.0f), 0.0f);
|
||||
float max_value = MAX(max_luminance / MAX(reference_luminance, 1.0f), 1.0f);
|
||||
|
||||
RSG::scene->environment_set_tonemap_range(environment, min_value, max_value);
|
||||
} else {
|
||||
RSG::scene->environment_set_tonemap_range(environment, 0.0f, 1.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -710,6 +731,21 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport) {
|
|||
}
|
||||
}
|
||||
|
||||
DisplayServer::WindowID RendererViewport::_get_containing_window(Viewport *p_viewport) {
|
||||
if (p_viewport->viewport_to_screen != DisplayServer::INVALID_WINDOW_ID) {
|
||||
return p_viewport->viewport_to_screen;
|
||||
}
|
||||
|
||||
if (p_viewport->parent.is_valid()) {
|
||||
Viewport *parent = viewport_owner.get_or_null(p_viewport->parent);
|
||||
if (parent) {
|
||||
return _get_containing_window(parent);
|
||||
}
|
||||
}
|
||||
|
||||
return DisplayServer::INVALID_WINDOW_ID;
|
||||
}
|
||||
|
||||
void RendererViewport::draw_viewports(bool p_swap_buffers) {
|
||||
timestamp_vp_map.clear();
|
||||
|
||||
|
|
@ -1124,6 +1160,13 @@ void RendererViewport::viewport_set_render_direct_to_screen(RID p_viewport, bool
|
|||
}
|
||||
}
|
||||
|
||||
void RendererViewport::viewport_set_tonemap_to_screen(RID p_viewport, bool p_enable) {
|
||||
Viewport *viewport = viewport_owner.get_or_null(p_viewport);
|
||||
ERR_FAIL_NULL(viewport);
|
||||
|
||||
viewport->tonemap_to_screen = p_enable;
|
||||
}
|
||||
|
||||
void RendererViewport::viewport_set_update_mode(RID p_viewport, RS::ViewportUpdateMode p_mode) {
|
||||
Viewport *viewport = viewport_owner.get_or_null(p_viewport);
|
||||
ERR_FAIL_NULL(viewport);
|
||||
|
|
|
|||
|
|
@ -87,6 +87,7 @@ public:
|
|||
DisplayServer::WindowID viewport_to_screen;
|
||||
Rect2 viewport_to_screen_rect;
|
||||
bool viewport_render_direct_to_screen;
|
||||
bool tonemap_to_screen;
|
||||
|
||||
bool disable_2d = false;
|
||||
RS::ViewportEnvironmentMode disable_environment = RS::VIEWPORT_ENVIRONMENT_INHERIT;
|
||||
|
|
@ -211,6 +212,7 @@ private:
|
|||
void _configure_3d_render_buffers(Viewport *p_viewport);
|
||||
void _draw_3d(Viewport *p_viewport);
|
||||
void _draw_viewport(Viewport *p_viewport);
|
||||
DisplayServer::WindowID _get_containing_window(Viewport *p_viewport);
|
||||
|
||||
int occlusion_rays_per_thread = 512;
|
||||
|
||||
|
|
@ -226,6 +228,7 @@ public:
|
|||
|
||||
void viewport_attach_to_screen(RID p_viewport, const Rect2 &p_rect = Rect2(), DisplayServer::WindowID p_screen = DisplayServer::MAIN_WINDOW_ID);
|
||||
void viewport_set_render_direct_to_screen(RID p_viewport, bool p_enable);
|
||||
void viewport_set_tonemap_to_screen(RID p_viewport, bool p_enable);
|
||||
|
||||
void viewport_set_active(RID p_viewport, bool p_active);
|
||||
void viewport_set_parent_viewport(RID p_viewport, RID p_parent_viewport);
|
||||
|
|
|
|||
|
|
@ -75,6 +75,86 @@ DisplayServer::VSyncMode RenderingContextDriver::window_get_vsync_mode(DisplaySe
|
|||
}
|
||||
}
|
||||
|
||||
void RenderingContextDriver::window_set_hdr_output_enabled(DisplayServer::WindowID p_window, bool p_enabled) {
|
||||
SurfaceID surface = surface_get_from_window(p_window);
|
||||
if (surface) {
|
||||
surface_set_hdr_output_enabled(surface, p_enabled);
|
||||
}
|
||||
}
|
||||
|
||||
bool RenderingContextDriver::window_get_hdr_output_enabled(DisplayServer::WindowID p_window) const {
|
||||
SurfaceID surface = surface_get_from_window(p_window);
|
||||
if (surface) {
|
||||
return surface_get_hdr_output_enabled(surface);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void RenderingContextDriver::window_set_hdr_output_prefer_high_precision(DisplayServer::WindowID p_window, bool p_enabled) {
|
||||
SurfaceID surface = surface_get_from_window(p_window);
|
||||
if (surface) {
|
||||
surface_set_hdr_output_prefer_high_precision(surface, p_enabled);
|
||||
}
|
||||
}
|
||||
|
||||
bool RenderingContextDriver::window_get_hdr_output_prefer_high_precision(DisplayServer::WindowID p_window) const {
|
||||
SurfaceID surface = surface_get_from_window(p_window);
|
||||
if (surface) {
|
||||
return surface_get_hdr_output_prefer_high_precision(surface);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void RenderingContextDriver::window_set_hdr_output_reference_luminance(DisplayServer::WindowID p_window, float p_reference_luminance) {
|
||||
SurfaceID surface = surface_get_from_window(p_window);
|
||||
if (surface) {
|
||||
surface_set_hdr_output_reference_luminance(surface, p_reference_luminance);
|
||||
}
|
||||
}
|
||||
|
||||
float RenderingContextDriver::window_get_hdr_output_reference_luminance(DisplayServer::WindowID p_window) const {
|
||||
SurfaceID surface = surface_get_from_window(p_window);
|
||||
if (surface) {
|
||||
return surface_get_hdr_output_reference_luminance(surface);
|
||||
} else {
|
||||
return 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
void RenderingContextDriver::window_set_hdr_output_min_luminance(DisplayServer::WindowID p_window, float p_min_luminance) {
|
||||
SurfaceID surface = surface_get_from_window(p_window);
|
||||
if (surface) {
|
||||
surface_set_hdr_output_min_luminance(surface, p_min_luminance);
|
||||
}
|
||||
}
|
||||
|
||||
float RenderingContextDriver::window_get_hdr_output_min_luminance(DisplayServer::WindowID p_window) const {
|
||||
SurfaceID surface = surface_get_from_window(p_window);
|
||||
if (surface) {
|
||||
return surface_get_hdr_output_min_luminance(surface);
|
||||
} else {
|
||||
return 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
void RenderingContextDriver::window_set_hdr_output_max_luminance(DisplayServer::WindowID p_window, float p_max_luminance) {
|
||||
SurfaceID surface = surface_get_from_window(p_window);
|
||||
if (surface) {
|
||||
surface_set_hdr_output_max_luminance(surface, p_max_luminance);
|
||||
}
|
||||
}
|
||||
|
||||
float RenderingContextDriver::window_get_hdr_output_max_luminance(DisplayServer::WindowID p_window) const {
|
||||
SurfaceID surface = surface_get_from_window(p_window);
|
||||
if (surface) {
|
||||
return surface_get_hdr_output_max_luminance(surface);
|
||||
} else {
|
||||
return 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
void RenderingContextDriver::window_destroy(DisplayServer::WindowID p_window) {
|
||||
SurfaceID surface = surface_get_from_window(p_window);
|
||||
if (surface) {
|
||||
|
|
|
|||
|
|
@ -48,6 +48,16 @@ public:
|
|||
void window_set_size(DisplayServer::WindowID p_window, uint32_t p_width, uint32_t p_height);
|
||||
void window_set_vsync_mode(DisplayServer::WindowID p_window, DisplayServer::VSyncMode p_vsync_mode);
|
||||
DisplayServer::VSyncMode window_get_vsync_mode(DisplayServer::WindowID p_window) const;
|
||||
void window_set_hdr_output_enabled(DisplayServer::WindowID p_window, bool p_enabled);
|
||||
bool window_get_hdr_output_enabled(DisplayServer::WindowID p_window) const;
|
||||
void window_set_hdr_output_prefer_high_precision(DisplayServer::WindowID p_window, bool p_enabled);
|
||||
bool window_get_hdr_output_prefer_high_precision(DisplayServer::WindowID p_window) const;
|
||||
void window_set_hdr_output_reference_luminance(DisplayServer::WindowID p_window, float p_reference_luminance);
|
||||
float window_get_hdr_output_reference_luminance(DisplayServer::WindowID p_window) const;
|
||||
void window_set_hdr_output_min_luminance(DisplayServer::WindowID p_window, float p_min_luminance);
|
||||
float window_get_hdr_output_min_luminance(DisplayServer::WindowID p_window) const;
|
||||
void window_set_hdr_output_max_luminance(DisplayServer::WindowID p_window, float p_max_luminance);
|
||||
float window_get_hdr_output_max_luminance(DisplayServer::WindowID p_window) const;
|
||||
void window_destroy(DisplayServer::WindowID p_window);
|
||||
|
||||
public:
|
||||
|
|
@ -98,6 +108,16 @@ public:
|
|||
virtual void surface_set_size(SurfaceID p_surface, uint32_t p_width, uint32_t p_height) = 0;
|
||||
virtual void surface_set_vsync_mode(SurfaceID p_surface, DisplayServer::VSyncMode p_vsync_mode) = 0;
|
||||
virtual DisplayServer::VSyncMode surface_get_vsync_mode(SurfaceID p_surface) const = 0;
|
||||
virtual void surface_set_hdr_output_enabled(SurfaceID p_surface, bool p_enabled) = 0;
|
||||
virtual bool surface_get_hdr_output_enabled(SurfaceID p_surface) const = 0;
|
||||
virtual void surface_set_hdr_output_prefer_high_precision(SurfaceID p_surface, bool p_enabled) = 0;
|
||||
virtual bool surface_get_hdr_output_prefer_high_precision(SurfaceID p_surface) const = 0;
|
||||
virtual void surface_set_hdr_output_reference_luminance(SurfaceID p_surface, float p_reference_luminance) = 0;
|
||||
virtual float surface_get_hdr_output_reference_luminance(SurfaceID p_surface) const = 0;
|
||||
virtual void surface_set_hdr_output_min_luminance(SurfaceID p_surface, float p_min_luminance) = 0;
|
||||
virtual float surface_get_hdr_output_min_luminance(SurfaceID p_surface) const = 0;
|
||||
virtual void surface_set_hdr_output_max_luminance(SurfaceID p_surface, float p_max_luminance) = 0;
|
||||
virtual float surface_get_hdr_output_max_luminance(SurfaceID p_surface) const = 0;
|
||||
virtual uint32_t surface_get_width(SurfaceID p_surface) const = 0;
|
||||
virtual uint32_t surface_get_height(SurfaceID p_surface) const = 0;
|
||||
virtual void surface_set_needs_resize(SurfaceID p_surface, bool p_needs_resize) = 0;
|
||||
|
|
|
|||
|
|
@ -4209,6 +4209,28 @@ RenderingDevice::FramebufferFormatID RenderingDevice::screen_get_framebuffer_for
|
|||
return const_cast<RenderingDevice *>(this)->framebuffer_format_create(screen_attachment);
|
||||
}
|
||||
|
||||
RenderingDevice::DataFormat RenderingDevice::screen_get_color_format(DisplayServer::WindowID p_screen) const {
|
||||
_THREAD_SAFE_METHOD_
|
||||
|
||||
HashMap<DisplayServer::WindowID, RDD::SwapChainID>::ConstIterator it = screen_swap_chains.find(p_screen);
|
||||
ERR_FAIL_COND_V_MSG(it == screen_swap_chains.end(), DATA_FORMAT_MAX, "Screen was never prepared.");
|
||||
|
||||
DataFormat format = driver->swap_chain_get_format(it->value);
|
||||
ERR_FAIL_COND_V_MSG(format == DATA_FORMAT_MAX, DATA_FORMAT_MAX, "Unknown format.");
|
||||
return format;
|
||||
}
|
||||
|
||||
RenderingDevice::ColorSpace RenderingDevice::screen_get_color_space(DisplayServer::WindowID p_screen) const {
|
||||
_THREAD_SAFE_METHOD_
|
||||
|
||||
HashMap<DisplayServer::WindowID, RDD::SwapChainID>::ConstIterator it = screen_swap_chains.find(p_screen);
|
||||
ERR_FAIL_COND_V_MSG(it == screen_swap_chains.end(), COLOR_SPACE_MAX, "Screen was never prepared.");
|
||||
|
||||
ColorSpace color_space = driver->swap_chain_get_color_space(it->value);
|
||||
ERR_FAIL_COND_V_MSG(color_space == COLOR_SPACE_MAX, COLOR_SPACE_MAX, "Unknown color space.");
|
||||
return color_space;
|
||||
}
|
||||
|
||||
Error RenderingDevice::screen_free(DisplayServer::WindowID p_screen) {
|
||||
_THREAD_SAFE_METHOD_
|
||||
|
||||
|
|
@ -7337,6 +7359,8 @@ void RenderingDevice::_bind_methods() {
|
|||
ClassDB::bind_method(D_METHOD("screen_get_width", "screen"), &RenderingDevice::screen_get_width, DEFVAL(DisplayServer::MAIN_WINDOW_ID));
|
||||
ClassDB::bind_method(D_METHOD("screen_get_height", "screen"), &RenderingDevice::screen_get_height, DEFVAL(DisplayServer::MAIN_WINDOW_ID));
|
||||
ClassDB::bind_method(D_METHOD("screen_get_framebuffer_format", "screen"), &RenderingDevice::screen_get_framebuffer_format, DEFVAL(DisplayServer::MAIN_WINDOW_ID));
|
||||
ClassDB::bind_method(D_METHOD("screen_get_color_format", "screen"), &RenderingDevice::screen_get_color_format, DEFVAL(DisplayServer::MAIN_WINDOW_ID));
|
||||
ClassDB::bind_method(D_METHOD("screen_get_color_space", "screen"), &RenderingDevice::screen_get_color_space, DEFVAL(DisplayServer::MAIN_WINDOW_ID));
|
||||
|
||||
ClassDB::bind_method(D_METHOD("draw_list_begin_for_screen", "screen", "clear_color"), &RenderingDevice::draw_list_begin_for_screen, DEFVAL(DisplayServer::MAIN_WINDOW_ID), DEFVAL(Color()));
|
||||
|
||||
|
|
@ -7682,6 +7706,11 @@ void RenderingDevice::_bind_methods() {
|
|||
BIND_ENUM_CONSTANT(DATA_FORMAT_G16_B16_R16_3PLANE_444_UNORM);
|
||||
BIND_ENUM_CONSTANT(DATA_FORMAT_MAX);
|
||||
|
||||
BIND_ENUM_CONSTANT(COLOR_SPACE_SRGB_LINEAR);
|
||||
BIND_ENUM_CONSTANT(COLOR_SPACE_SRGB_NONLINEAR);
|
||||
BIND_ENUM_CONSTANT(COLOR_SPACE_HDR10_ST2084);
|
||||
BIND_ENUM_CONSTANT(COLOR_SPACE_MAX);
|
||||
|
||||
#ifndef DISABLE_DEPRECATED
|
||||
BIND_BITFIELD_FLAG(BARRIER_MASK_VERTEX);
|
||||
BIND_BITFIELD_FLAG(BARRIER_MASK_FRAGMENT);
|
||||
|
|
@ -7906,6 +7935,7 @@ void RenderingDevice::_bind_methods() {
|
|||
BIND_ENUM_CONSTANT(PIPELINE_SPECIALIZATION_CONSTANT_TYPE_FLOAT);
|
||||
|
||||
BIND_ENUM_CONSTANT(SUPPORTS_BUFFER_DEVICE_ADDRESS);
|
||||
BIND_ENUM_CONSTANT(SUPPORTS_HDR_OUTPUT);
|
||||
|
||||
BIND_ENUM_CONSTANT(LIMIT_MAX_BOUND_UNIFORM_SETS);
|
||||
BIND_ENUM_CONSTANT(LIMIT_MAX_FRAMEBUFFER_COLOR_ATTACHMENTS);
|
||||
|
|
|
|||
|
|
@ -1159,6 +1159,8 @@ public:
|
|||
int screen_get_height(DisplayServer::WindowID p_screen = DisplayServer::MAIN_WINDOW_ID) const;
|
||||
int screen_get_pre_rotation_degrees(DisplayServer::WindowID p_screen = DisplayServer::MAIN_WINDOW_ID) const;
|
||||
FramebufferFormatID screen_get_framebuffer_format(DisplayServer::WindowID p_screen = DisplayServer::MAIN_WINDOW_ID) const;
|
||||
DataFormat screen_get_color_format(DisplayServer::WindowID p_screen = DisplayServer::MAIN_WINDOW_ID) const;
|
||||
ColorSpace screen_get_color_space(DisplayServer::WindowID p_screen = DisplayServer::MAIN_WINDOW_ID) const;
|
||||
Error screen_free(DisplayServer::WindowID p_screen = DisplayServer::MAIN_WINDOW_ID);
|
||||
|
||||
/*************************/
|
||||
|
|
@ -1678,6 +1680,7 @@ VARIANT_ENUM_CAST(RenderingDevice::ShaderStage)
|
|||
VARIANT_ENUM_CAST(RenderingDevice::ShaderLanguage)
|
||||
VARIANT_ENUM_CAST(RenderingDevice::CompareOperator)
|
||||
VARIANT_ENUM_CAST(RenderingDevice::DataFormat)
|
||||
VARIANT_ENUM_CAST(RenderingDevice::ColorSpace)
|
||||
VARIANT_ENUM_CAST(RenderingDevice::TextureType)
|
||||
VARIANT_ENUM_CAST(RenderingDevice::TextureSamples)
|
||||
VARIANT_BITFIELD_CAST(RenderingDevice::TextureUsageBits)
|
||||
|
|
|
|||
|
|
@ -273,6 +273,13 @@ public:
|
|||
DATA_FORMAT_MAX,
|
||||
};
|
||||
|
||||
enum ColorSpace {
|
||||
COLOR_SPACE_SRGB_LINEAR,
|
||||
COLOR_SPACE_SRGB_NONLINEAR,
|
||||
COLOR_SPACE_HDR10_ST2084,
|
||||
COLOR_SPACE_MAX,
|
||||
};
|
||||
|
||||
// Breadcrumb markers are useful for debugging GPU crashes (i.e. DEVICE_LOST). Internally
|
||||
// they're just an uint32_t to "tag" a GPU command. These are only used for debugging and do not
|
||||
// (or at least shouldn't) alter the execution behavior in any way.
|
||||
|
|
@ -887,6 +894,7 @@ public:
|
|||
// If not supported, a fragment shader with only side effects (i.e., writes to buffers, but doesn't output to attachments), may be optimized down to no-op by the GPU driver.
|
||||
SUPPORTS_FRAGMENT_SHADER_WITH_ONLY_SIDE_EFFECTS,
|
||||
SUPPORTS_BUFFER_DEVICE_ADDRESS,
|
||||
SUPPORTS_HDR_OUTPUT,
|
||||
};
|
||||
|
||||
enum SubgroupOperations {
|
||||
|
|
|
|||
|
|
@ -473,6 +473,9 @@ public:
|
|||
// Android uses this with Swappy library. Some implementations or platforms may ignore this hint.
|
||||
virtual void swap_chain_set_max_fps(SwapChainID p_swap_chain, int p_max_fps) {}
|
||||
|
||||
// Retrieve the color space used by the swap chain's framebuffers.
|
||||
virtual ColorSpace swap_chain_get_color_space(SwapChainID p_swap_chain) = 0;
|
||||
|
||||
// Wait until all rendering associated to the swap chain is finished before deleting it.
|
||||
virtual void swap_chain_free(SwapChainID p_swap_chain) = 0;
|
||||
|
||||
|
|
|
|||
|
|
@ -186,10 +186,13 @@ public:
|
|||
|
||||
// Tonemap
|
||||
virtual void environment_set_tonemap(RID p_env, RS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white) = 0;
|
||||
virtual void environment_set_tonemap_range(RID p_env, float p_min_value, float p_max_value) = 0;
|
||||
|
||||
virtual RS::EnvironmentToneMapper environment_get_tone_mapper(RID p_env) const = 0;
|
||||
virtual float environment_get_exposure(RID p_env) const = 0;
|
||||
virtual float environment_get_white(RID p_env) const = 0;
|
||||
virtual float environment_get_min_value(RID p_env) const = 0;
|
||||
virtual float environment_get_max_value(RID p_env) const = 0;
|
||||
|
||||
// Fog
|
||||
virtual void environment_set_fog(RID p_env, bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_aerial_perspective, float p_sky_affect, RS::EnvironmentFogMode p_mode = RS::EnvironmentFogMode::ENV_FOG_MODE_EXPONENTIAL) = 0;
|
||||
|
|
|
|||
|
|
@ -690,6 +690,7 @@ public:
|
|||
|
||||
FUNC3(viewport_attach_to_screen, RID, const Rect2 &, int)
|
||||
FUNC2(viewport_set_render_direct_to_screen, RID, bool)
|
||||
FUNC2(viewport_set_tonemap_to_screen, RID, bool)
|
||||
|
||||
FUNC2(viewport_set_scaling_3d_mode, RID, ViewportScaling3DMode)
|
||||
FUNC2(viewport_set_scaling_3d_scale, RID, float)
|
||||
|
|
@ -813,6 +814,7 @@ public:
|
|||
FUNC1(environment_glow_set_use_bicubic_upscale, bool)
|
||||
|
||||
FUNC4(environment_set_tonemap, RID, EnvironmentToneMapper, float, float)
|
||||
FUNC3(environment_set_tonemap_range, RID, float, float)
|
||||
|
||||
FUNC7(environment_set_adjustment, RID, bool, float, float, float, bool, RID)
|
||||
|
||||
|
|
|
|||
|
|
@ -211,6 +211,14 @@ void RendererEnvironmentStorage::environment_set_tonemap(RID p_env, RS::Environm
|
|||
env->white = p_white;
|
||||
}
|
||||
|
||||
void RendererEnvironmentStorage::environment_set_tonemap_range(RID p_env, float p_min_value, float p_max_value) {
|
||||
Environment *env = environment_owner.get_or_null(p_env);
|
||||
ERR_FAIL_NULL(env);
|
||||
ERR_FAIL_COND(p_min_value >= p_max_value);
|
||||
env->min_value = p_min_value;
|
||||
env->max_value = p_max_value;
|
||||
}
|
||||
|
||||
RS::EnvironmentToneMapper RendererEnvironmentStorage::environment_get_tone_mapper(RID p_env) const {
|
||||
Environment *env = environment_owner.get_or_null(p_env);
|
||||
ERR_FAIL_NULL_V(env, RS::ENV_TONE_MAPPER_LINEAR);
|
||||
|
|
@ -229,6 +237,18 @@ float RendererEnvironmentStorage::environment_get_white(RID p_env) const {
|
|||
return env->white;
|
||||
}
|
||||
|
||||
float RendererEnvironmentStorage::environment_get_min_value(RID p_env) const {
|
||||
Environment *env = environment_owner.get_or_null(p_env);
|
||||
ERR_FAIL_NULL_V(env, 0.0);
|
||||
return env->min_value;
|
||||
}
|
||||
|
||||
float RendererEnvironmentStorage::environment_get_max_value(RID p_env) const {
|
||||
Environment *env = environment_owner.get_or_null(p_env);
|
||||
ERR_FAIL_NULL_V(env, 1.0);
|
||||
return env->max_value;
|
||||
}
|
||||
|
||||
// Fog
|
||||
|
||||
void RendererEnvironmentStorage::environment_set_fog(RID p_env, bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_fog_aerial_perspective, float p_sky_affect, RS::EnvironmentFogMode p_mode) {
|
||||
|
|
|
|||
|
|
@ -63,6 +63,8 @@ private:
|
|||
RS::EnvironmentToneMapper tone_mapper;
|
||||
float exposure = 1.0;
|
||||
float white = 1.0;
|
||||
float min_value = 0.0;
|
||||
float max_value = 1.0;
|
||||
|
||||
// Fog
|
||||
bool fog_enabled = false;
|
||||
|
|
@ -201,9 +203,12 @@ public:
|
|||
|
||||
// Tonemap
|
||||
void environment_set_tonemap(RID p_env, RS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white);
|
||||
void environment_set_tonemap_range(RID p_env, float p_min_value, float p_max_value);
|
||||
RS::EnvironmentToneMapper environment_get_tone_mapper(RID p_env) const;
|
||||
float environment_get_exposure(RID p_env) const;
|
||||
float environment_get_white(RID p_env) const;
|
||||
float environment_get_min_value(RID p_env) const;
|
||||
float environment_get_max_value(RID p_env) const;
|
||||
|
||||
// Fog
|
||||
void environment_set_fog(RID p_env, bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_aerial_perspective, float p_sky_affect, RS::EnvironmentFogMode p_mode);
|
||||
|
|
|
|||
|
|
@ -2810,6 +2810,7 @@ void RenderingServer::_bind_methods() {
|
|||
ClassDB::bind_method(D_METHOD("viewport_set_parent_viewport", "viewport", "parent_viewport"), &RenderingServer::viewport_set_parent_viewport);
|
||||
ClassDB::bind_method(D_METHOD("viewport_attach_to_screen", "viewport", "rect", "screen"), &RenderingServer::viewport_attach_to_screen, DEFVAL(Rect2()), DEFVAL(DisplayServer::MAIN_WINDOW_ID));
|
||||
ClassDB::bind_method(D_METHOD("viewport_set_render_direct_to_screen", "viewport", "enabled"), &RenderingServer::viewport_set_render_direct_to_screen);
|
||||
ClassDB::bind_method(D_METHOD("viewport_set_tonemap_to_screen", "viewport", "enabled"), &RenderingServer::viewport_set_tonemap_to_screen);
|
||||
ClassDB::bind_method(D_METHOD("viewport_set_canvas_cull_mask", "viewport", "canvas_cull_mask"), &RenderingServer::viewport_set_canvas_cull_mask);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("viewport_set_scaling_3d_mode", "viewport", "scaling_3d_mode"), &RenderingServer::viewport_set_scaling_3d_mode);
|
||||
|
|
@ -3022,6 +3023,7 @@ void RenderingServer::_bind_methods() {
|
|||
ClassDB::bind_method(D_METHOD("environment_set_ambient_light", "env", "color", "ambient", "energy", "sky_contribution", "reflection_source"), &RenderingServer::environment_set_ambient_light, DEFVAL(RS::ENV_AMBIENT_SOURCE_BG), DEFVAL(1.0), DEFVAL(0.0), DEFVAL(RS::ENV_REFLECTION_SOURCE_BG));
|
||||
ClassDB::bind_method(D_METHOD("environment_set_glow", "env", "enable", "levels", "intensity", "strength", "mix", "bloom_threshold", "blend_mode", "hdr_bleed_threshold", "hdr_bleed_scale", "hdr_luminance_cap", "glow_map_strength", "glow_map"), &RenderingServer::environment_set_glow);
|
||||
ClassDB::bind_method(D_METHOD("environment_set_tonemap", "env", "tone_mapper", "exposure", "white"), &RenderingServer::environment_set_tonemap);
|
||||
ClassDB::bind_method(D_METHOD("environment_set_tonemap_range", "env", "min_value", "max_value"), &RenderingServer::environment_set_tonemap_range);
|
||||
ClassDB::bind_method(D_METHOD("environment_set_adjustment", "env", "enable", "brightness", "contrast", "saturation", "use_1d_color_correction", "color_correction"), &RenderingServer::environment_set_adjustment);
|
||||
ClassDB::bind_method(D_METHOD("environment_set_ssr", "env", "enable", "max_steps", "fade_in", "fade_out", "depth_tolerance"), &RenderingServer::environment_set_ssr);
|
||||
ClassDB::bind_method(D_METHOD("environment_set_ssao", "env", "enable", "radius", "intensity", "power", "detail", "horizon", "sharpness", "light_affect", "ao_channel_affect"), &RenderingServer::environment_set_ssao);
|
||||
|
|
|
|||
|
|
@ -966,6 +966,7 @@ public:
|
|||
|
||||
virtual void viewport_attach_to_screen(RID p_viewport, const Rect2 &p_rect = Rect2(), DisplayServer::WindowID p_screen = DisplayServer::MAIN_WINDOW_ID) = 0;
|
||||
virtual void viewport_set_render_direct_to_screen(RID p_viewport, bool p_enable) = 0;
|
||||
virtual void viewport_set_tonemap_to_screen(RID p_viewport, bool p_enable) = 0;
|
||||
|
||||
virtual void viewport_set_scaling_3d_mode(RID p_viewport, ViewportScaling3DMode p_scaling_3d_mode) = 0;
|
||||
virtual void viewport_set_scaling_3d_scale(RID p_viewport, float p_scaling_3d_scale) = 0;
|
||||
|
|
@ -1257,6 +1258,7 @@ public:
|
|||
};
|
||||
|
||||
virtual void environment_set_tonemap(RID p_env, EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white) = 0;
|
||||
virtual void environment_set_tonemap_range(RID p_env, float p_min_value, float p_max_value) = 0;
|
||||
virtual void environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, bool p_use_1d_color_correction, RID p_color_correction) = 0;
|
||||
|
||||
virtual void environment_set_ssr(RID p_env, bool p_enable, int p_max_steps, float p_fade_in, float p_fade_out, float p_depth_tolerance) = 0;
|
||||
|
|
|
|||
Loading…
Reference in New Issue