mirror of
https://github.com/godotengine/godot.git
synced 2025-10-19 07:53:26 +00:00
Compare commits
36 commits
fc7065d2b4
...
e825169957
Author | SHA1 | Date | |
---|---|---|---|
![]() |
e825169957 | ||
![]() |
4ae535b3b9 | ||
![]() |
c0c75561d2 | ||
![]() |
8ce4f80dd9 | ||
![]() |
d3285f5468 | ||
![]() |
c6df8d3253 | ||
![]() |
988a7f7bdf | ||
![]() |
0b4cca38ea | ||
![]() |
8be090c03a | ||
![]() |
c5754ccc52 | ||
![]() |
21a6488c7f | ||
![]() |
3dbd7d36d0 | ||
![]() |
cd74a9cb12 | ||
![]() |
cd13a9df14 | ||
![]() |
58894136b7 | ||
![]() |
40dde2a9a1 | ||
![]() |
3ef37d7bf3 | ||
![]() |
2568505535 | ||
![]() |
cbc960c997 | ||
![]() |
914a72f8a4 | ||
![]() |
082766a990 | ||
![]() |
276e1c222c | ||
![]() |
ba268416d5 | ||
![]() |
7cee91f05b | ||
![]() |
2e00156657 | ||
![]() |
e38bbf88e5 | ||
![]() |
03923c6ed7 | ||
![]() |
70f180975b | ||
![]() |
2dce5172e2 | ||
![]() |
7998b5e8d2 | ||
![]() |
0de3f8b21f | ||
![]() |
9894256e3a | ||
![]() |
3fa500d2f3 | ||
![]() |
5d492e1aed | ||
![]() |
da9a77ce42 | ||
![]() |
78045df591 |
185 changed files with 9075 additions and 7199 deletions
|
@ -5,7 +5,7 @@
|
|||
</brief_description>
|
||||
<description>
|
||||
[EditorTranslationParserPlugin] is invoked when a file is being parsed to extract strings that require translation. To define the parsing and string extraction logic, override the [method _parse_file] method in script.
|
||||
The return value should be an [Array] of [PackedStringArray]s, one for each extracted translatable string. Each entry should contain [code][msgid, msgctxt, msgid_plural, comment][/code], where all except [code]msgid[/code] are optional. Empty strings will be ignored.
|
||||
The return value should be an [Array] of [PackedStringArray]s, one for each extracted translatable string. Each entry should contain [code][msgid, msgctxt, msgid_plural, comment, source_line][/code], where all except [code]msgid[/code] are optional. Empty strings will be ignored.
|
||||
The extracted strings will be written into a POT file selected by user under "POT Generation" in "Localization" tab in "Project Settings" menu.
|
||||
Below shows an example of a custom parser that extracts strings from a CSV file to write into a POT.
|
||||
[codeblocks]
|
||||
|
@ -54,19 +54,19 @@
|
|||
}
|
||||
[/csharp]
|
||||
[/codeblocks]
|
||||
To add a translatable string associated with a context, plural, or comment:
|
||||
To add a translatable string associated with a context, plural, comment, or source line:
|
||||
[codeblocks]
|
||||
[gdscript]
|
||||
# This will add a message with msgid "Test 1", msgctxt "context", msgid_plural "test 1 plurals", and comment "test 1 comment".
|
||||
ret.append(PackedStringArray(["Test 1", "context", "test 1 plurals", "test 1 comment"]))
|
||||
# This will add a message with msgid "Test 1", msgctxt "context", msgid_plural "test 1 plurals", comment "test 1 comment", and source line "7".
|
||||
ret.append(PackedStringArray(["Test 1", "context", "test 1 plurals", "test 1 comment", "7"]))
|
||||
# This will add a message with msgid "A test without context" and msgid_plural "plurals".
|
||||
ret.append(PackedStringArray(["A test without context", "", "plurals"]))
|
||||
# This will add a message with msgid "Only with context" and msgctxt "a friendly context".
|
||||
ret.append(PackedStringArray(["Only with context", "a friendly context"]))
|
||||
[/gdscript]
|
||||
[csharp]
|
||||
// This will add a message with msgid "Test 1", msgctxt "context", msgid_plural "test 1 plurals", and comment "test 1 comment".
|
||||
ret.Add(["Test 1", "context", "test 1 plurals", "test 1 comment"]);
|
||||
// This will add a message with msgid "Test 1", msgctxt "context", msgid_plural "test 1 plurals", comment "test 1 comment", and source line "7".
|
||||
ret.Add(["Test 1", "context", "test 1 plurals", "test 1 comment", "7"]);
|
||||
// This will add a message with msgid "A test without context" and msgid_plural "plurals".
|
||||
ret.Add(["A test without context", "", "plurals"]);
|
||||
// This will add a message with msgid "Only with context" and msgctxt "a friendly context".
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
[b]Note:[/b] This singleton can be disabled at build-time to improve security. By default, the JavaScriptBridge singleton is enabled. Official export templates also have the JavaScriptBridge singleton enabled. See [url=$DOCS_URL/engine_details/development/compiling/compiling_for_web.html]Compiling for the Web[/url] in the documentation for more information.
|
||||
</description>
|
||||
<tutorials>
|
||||
<link title="Exporting for the Web: Calling JavaScript from script">$DOCS_URL/tutorials/export/exporting_for_web.html#calling-javascript-from-script</link>
|
||||
<link title="The JavaScriptBridge singleton">$DOCS_URL/tutorials/platform/web/javascript_bridge.html</link>
|
||||
</tutorials>
|
||||
<methods>
|
||||
<method name="create_callback">
|
||||
|
|
|
@ -19,11 +19,11 @@
|
|||
Multiplies the current scale by the [param ratio] vector.
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_angle_to" qualifiers="const">
|
||||
<method name="get_angle_to" qualifiers="const" keywords="look_at">
|
||||
<return type="float" />
|
||||
<param index="0" name="point" type="Vector2" />
|
||||
<description>
|
||||
Returns the angle between the node and the [param point] in radians.
|
||||
Returns the angle between the node and the [param point] in radians. See also [method look_at].
|
||||
[url=https://raw.githubusercontent.com/godotengine/godot-docs/master/img/node2d_get_angle_to.png]Illustration of the returned angle.[/url]
|
||||
</description>
|
||||
</method>
|
||||
|
@ -45,7 +45,7 @@
|
|||
<return type="void" />
|
||||
<param index="0" name="point" type="Vector2" />
|
||||
<description>
|
||||
Rotates the node so that its local +X axis points towards the [param point], which is expected to use global coordinates.
|
||||
Rotates the node so that its local +X axis points towards the [param point], which is expected to use global coordinates. This method is a combination of both [method rotate] and [method get_angle_to].
|
||||
[param point] should not be the same as the node's position, otherwise the node always looks to the right.
|
||||
</description>
|
||||
</method>
|
||||
|
@ -69,7 +69,7 @@
|
|||
<return type="void" />
|
||||
<param index="0" name="radians" type="float" />
|
||||
<description>
|
||||
Applies a rotation to the node, in radians, starting from its current rotation.
|
||||
Applies a rotation to the node, in radians, starting from its current rotation. This is equivalent to [code]rotation += radians[/code].
|
||||
</description>
|
||||
</method>
|
||||
<method name="to_global" qualifiers="const">
|
||||
|
@ -90,7 +90,7 @@
|
|||
<return type="void" />
|
||||
<param index="0" name="offset" type="Vector2" />
|
||||
<description>
|
||||
Translates the node by the given [param offset] in local coordinates.
|
||||
Translates the node by the given [param offset] in local coordinates. This is equivalent to [code]position += offset[/code].
|
||||
</description>
|
||||
</method>
|
||||
</methods>
|
||||
|
|
|
@ -65,9 +65,11 @@ EditorDebuggerNode::EditorDebuggerNode() {
|
|||
singleton = this;
|
||||
}
|
||||
|
||||
add_theme_constant_override("margin_left", -EditorNode::get_singleton()->get_editor_theme()->get_stylebox(SNAME("BottomPanelDebuggerOverride"), EditorStringName(EditorStyles))->get_margin(SIDE_LEFT));
|
||||
add_theme_constant_override("margin_right", -EditorNode::get_singleton()->get_editor_theme()->get_stylebox(SNAME("BottomPanelDebuggerOverride"), EditorStringName(EditorStyles))->get_margin(SIDE_RIGHT));
|
||||
add_theme_constant_override("margin_bottom", -EditorNode::get_singleton()->get_editor_theme()->get_stylebox(SNAME("BottomPanelDebuggerOverride"), EditorStringName(EditorStyles))->get_margin(SIDE_BOTTOM));
|
||||
Ref<StyleBox> bottom_panel_margins = EditorNode::get_singleton()->get_editor_theme()->get_stylebox(SNAME("BottomPanel"), EditorStringName(EditorStyles));
|
||||
add_theme_constant_override("margin_top", -bottom_panel_margins->get_margin(SIDE_TOP));
|
||||
add_theme_constant_override("margin_left", -bottom_panel_margins->get_margin(SIDE_LEFT));
|
||||
add_theme_constant_override("margin_right", -bottom_panel_margins->get_margin(SIDE_RIGHT));
|
||||
add_theme_constant_override("margin_bottom", -bottom_panel_margins->get_margin(SIDE_BOTTOM));
|
||||
|
||||
tabs = memnew(TabContainer);
|
||||
tabs->set_tabs_visible(false);
|
||||
|
@ -331,9 +333,11 @@ void EditorDebuggerNode::_notification(int p_what) {
|
|||
tabs->add_theme_style_override(SceneStringName(panel), EditorNode::get_singleton()->get_editor_theme()->get_stylebox(SNAME("DebuggerPanel"), EditorStringName(EditorStyles)));
|
||||
}
|
||||
|
||||
add_theme_constant_override("margin_left", -EditorNode::get_singleton()->get_editor_theme()->get_stylebox(SNAME("BottomPanelDebuggerOverride"), EditorStringName(EditorStyles))->get_margin(SIDE_LEFT));
|
||||
add_theme_constant_override("margin_right", -EditorNode::get_singleton()->get_editor_theme()->get_stylebox(SNAME("BottomPanelDebuggerOverride"), EditorStringName(EditorStyles))->get_margin(SIDE_RIGHT));
|
||||
add_theme_constant_override("margin_bottom", -EditorNode::get_singleton()->get_editor_theme()->get_stylebox(SNAME("BottomPanelDebuggerOverride"), EditorStringName(EditorStyles))->get_margin(SIDE_BOTTOM));
|
||||
Ref<StyleBox> bottom_panel_margins = EditorNode::get_singleton()->get_editor_theme()->get_stylebox(SNAME("BottomPanel"), EditorStringName(EditorStyles));
|
||||
add_theme_constant_override("margin_top", -bottom_panel_margins->get_margin(SIDE_TOP));
|
||||
add_theme_constant_override("margin_left", -bottom_panel_margins->get_margin(SIDE_LEFT));
|
||||
add_theme_constant_override("margin_right", -bottom_panel_margins->get_margin(SIDE_RIGHT));
|
||||
add_theme_constant_override("margin_bottom", -bottom_panel_margins->get_margin(SIDE_BOTTOM));
|
||||
|
||||
remote_scene_tree->update_icon_max_width();
|
||||
} break;
|
||||
|
|
|
@ -415,8 +415,8 @@ void FileSystemDock::_update_tree(const Vector<String> &p_uncollapsed_paths, boo
|
|||
Ref<Texture2D> folder_icon = get_editor_theme_icon(SNAME("Folder"));
|
||||
const Color default_folder_color = get_theme_color(SNAME("folder_icon_color"), SNAME("FileDialog"));
|
||||
|
||||
for (int i = 0; i < favorite_paths.size(); i++) {
|
||||
const String &favorite = favorite_paths[i];
|
||||
const int icon_size = get_theme_constant(SNAME("class_icon_size"), EditorStringName(Editor));
|
||||
for (const String &favorite : favorite_paths) {
|
||||
if (!favorite.begins_with("res://")) {
|
||||
continue;
|
||||
}
|
||||
|
@ -448,6 +448,7 @@ void FileSystemDock::_update_tree(const Vector<String> &p_uncollapsed_paths, boo
|
|||
ti->set_text(0, text);
|
||||
ti->set_icon(0, icon);
|
||||
ti->set_icon_modulate(0, color);
|
||||
ti->set_icon_max_width(0, icon_size);
|
||||
ti->set_tooltip_text(0, favorite);
|
||||
ti->set_selectable(0, true);
|
||||
ti->set_metadata(0, favorite);
|
||||
|
|
|
@ -683,10 +683,6 @@ void EditorNode::_update_theme(bool p_skip_creation) {
|
|||
help_menu->set_item_icon(help_menu->get_item_index(HELP_ABOUT), _get_editor_theme_native_menu_icon(SNAME("Godot"), global_menu, dark_mode));
|
||||
help_menu->set_item_icon(help_menu->get_item_index(HELP_SUPPORT_GODOT_DEVELOPMENT), _get_editor_theme_native_menu_icon(SNAME("Heart"), global_menu, dark_mode));
|
||||
|
||||
if (EditorDebuggerNode::get_singleton()->is_visible()) {
|
||||
bottom_panel->add_theme_style_override(SceneStringName(panel), theme->get_stylebox(SNAME("BottomPanelDebuggerOverride"), EditorStringName(EditorStyles)));
|
||||
}
|
||||
|
||||
_update_renderer_color();
|
||||
}
|
||||
|
||||
|
|
|
@ -125,11 +125,13 @@ bool ShaderBakerExportPlugin::_begin_customize_resources(const Ref<EditorExportP
|
|||
customization_configuration_hash = to_hash.as_string().hash64();
|
||||
|
||||
BitField<RenderingShaderLibrary::FeatureBits> renderer_features = {};
|
||||
#ifndef XR_DISABLED
|
||||
bool xr_enabled = GLOBAL_GET("xr/shaders/enabled");
|
||||
renderer_features.set_flag(RenderingShaderLibrary::FEATURE_ADVANCED_BIT);
|
||||
if (xr_enabled) {
|
||||
renderer_features.set_flag(RenderingShaderLibrary::FEATURE_MULTIVIEW_BIT);
|
||||
}
|
||||
#endif // XR_DISABLED
|
||||
|
||||
int vrs_mode = GLOBAL_GET("rendering/vrs/mode");
|
||||
if (vrs_mode != 0) {
|
||||
|
|
|
@ -128,12 +128,6 @@ void EditorBottomPanel::_switch_to_item(bool p_visible, int p_idx, bool p_ignore
|
|||
items[i].button->set_pressed_no_signal(i == p_idx);
|
||||
items[i].control->set_visible(i == p_idx);
|
||||
}
|
||||
if (EditorDebuggerNode::get_singleton() == items[p_idx].control) {
|
||||
// This is the debug panel which uses tabs, so the top section should be smaller.
|
||||
add_theme_style_override(SceneStringName(panel), get_theme_stylebox(SNAME("BottomPanelDebuggerOverride"), EditorStringName(EditorStyles)));
|
||||
} else {
|
||||
add_theme_style_override(SceneStringName(panel), get_theme_stylebox(SNAME("BottomPanel"), EditorStringName(EditorStyles)));
|
||||
}
|
||||
|
||||
center_split->set_dragger_visibility(SplitContainer::DRAGGER_VISIBLE);
|
||||
center_split->set_collapsed(false);
|
||||
|
@ -145,7 +139,6 @@ void EditorBottomPanel::_switch_to_item(bool p_visible, int p_idx, bool p_ignore
|
|||
}
|
||||
callable_mp(this, &EditorBottomPanel::_ensure_control_visible).call_deferred(items[p_idx].button->get_instance_id());
|
||||
} else {
|
||||
add_theme_style_override(SceneStringName(panel), get_theme_stylebox(SNAME("BottomPanel"), EditorStringName(EditorStyles)));
|
||||
items[p_idx].button->set_pressed_no_signal(false);
|
||||
items[p_idx].control->set_visible(false);
|
||||
center_split->set_dragger_visibility(SplitContainer::DRAGGER_HIDDEN);
|
||||
|
|
|
@ -1699,6 +1699,11 @@ Node *ResourceImporterScene::_post_fix_node(Node *p_node, Node *p_root, HashMap<
|
|||
base = col;
|
||||
} break;
|
||||
case MESH_PHYSICS_RIGID_BODY_AND_MESH: {
|
||||
NodePath skeleton_path = mi->get_skeleton_path();
|
||||
Skeleton3D *skeleton = nullptr;
|
||||
if (!skeleton_path.is_empty()) {
|
||||
skeleton = Object::cast_to<Skeleton3D>(mi->get_node_or_null(skeleton_path));
|
||||
}
|
||||
RigidBody3D *rigid_body = memnew(RigidBody3D);
|
||||
rigid_body->set_name(p_node->get_name());
|
||||
_copy_meta(p_node, rigid_body);
|
||||
|
@ -1714,6 +1719,10 @@ Node *ResourceImporterScene::_post_fix_node(Node *p_node, Node *p_root, HashMap<
|
|||
rigid_body->set_physics_material_override(pmo);
|
||||
}
|
||||
base = rigid_body;
|
||||
if (skeleton) {
|
||||
skeleton_path = mi->get_path_to(skeleton);
|
||||
mi->set_skeleton_path(skeleton_path);
|
||||
}
|
||||
} break;
|
||||
case MESH_PHYSICS_STATIC_COLLIDER_ONLY: {
|
||||
StaticBody3D *col = memnew(StaticBody3D);
|
||||
|
|
|
@ -1476,18 +1476,18 @@ void EditorPropertyInteger::update_property() {
|
|||
#endif
|
||||
}
|
||||
|
||||
void EditorPropertyInteger::setup(int64_t p_min, int64_t p_max, int64_t p_step, bool p_prefer_slider, bool p_hide_control, bool p_allow_greater, bool p_allow_lesser, const String &p_suffix) {
|
||||
spin->set_min(p_min);
|
||||
spin->set_max(p_max);
|
||||
spin->set_step(p_step);
|
||||
if (p_hide_control) {
|
||||
void EditorPropertyInteger::setup(const EditorPropertyRangeHint &p_range_hint) {
|
||||
spin->set_min(p_range_hint.min);
|
||||
spin->set_max(p_range_hint.max);
|
||||
spin->set_step(Math::round(p_range_hint.step));
|
||||
if (p_range_hint.hide_control) {
|
||||
spin->set_control_state(EditorSpinSlider::CONTROL_STATE_HIDE);
|
||||
} else {
|
||||
spin->set_control_state(p_prefer_slider ? EditorSpinSlider::CONTROL_STATE_PREFER_SLIDER : EditorSpinSlider::CONTROL_STATE_DEFAULT);
|
||||
spin->set_control_state(p_range_hint.prefer_slider ? EditorSpinSlider::CONTROL_STATE_PREFER_SLIDER : EditorSpinSlider::CONTROL_STATE_DEFAULT);
|
||||
}
|
||||
spin->set_allow_greater(p_allow_greater);
|
||||
spin->set_allow_lesser(p_allow_lesser);
|
||||
spin->set_suffix(p_suffix);
|
||||
spin->set_allow_greater(p_range_hint.or_greater);
|
||||
spin->set_allow_lesser(p_range_hint.or_less);
|
||||
spin->set_suffix(p_range_hint.suffix);
|
||||
}
|
||||
|
||||
EditorPropertyInteger::EditorPropertyInteger() {
|
||||
|
@ -1607,18 +1607,18 @@ void EditorPropertyFloat::update_property() {
|
|||
spin->set_value_no_signal(val);
|
||||
}
|
||||
|
||||
void EditorPropertyFloat::setup(double p_min, double p_max, double p_step, bool p_hide_control, bool p_exp_range, bool p_greater, bool p_lesser, const String &p_suffix, bool p_radians_as_degrees) {
|
||||
radians_as_degrees = p_radians_as_degrees;
|
||||
spin->set_min(p_min);
|
||||
spin->set_max(p_max);
|
||||
spin->set_step(p_step);
|
||||
if (p_hide_control) {
|
||||
void EditorPropertyFloat::setup(const EditorPropertyRangeHint &p_range_hint) {
|
||||
radians_as_degrees = p_range_hint.radians_as_degrees;
|
||||
spin->set_min(p_range_hint.min);
|
||||
spin->set_max(p_range_hint.max);
|
||||
spin->set_step(p_range_hint.step);
|
||||
if (p_range_hint.hide_control) {
|
||||
spin->set_control_state(EditorSpinSlider::CONTROL_STATE_HIDE);
|
||||
}
|
||||
spin->set_exp_ratio(p_exp_range);
|
||||
spin->set_allow_greater(p_greater);
|
||||
spin->set_allow_lesser(p_lesser);
|
||||
spin->set_suffix(p_suffix);
|
||||
spin->set_exp_ratio(p_range_hint.exp_range);
|
||||
spin->set_allow_greater(p_range_hint.or_greater);
|
||||
spin->set_allow_lesser(p_range_hint.or_less);
|
||||
spin->set_suffix(p_range_hint.suffix);
|
||||
}
|
||||
|
||||
EditorPropertyFloat::EditorPropertyFloat() {
|
||||
|
@ -1897,17 +1897,17 @@ void EditorPropertyRect2::_notification(int p_what) {
|
|||
}
|
||||
}
|
||||
|
||||
void EditorPropertyRect2::setup(double p_min, double p_max, double p_step, bool p_hide_control, const String &p_suffix) {
|
||||
void EditorPropertyRect2::setup(const EditorPropertyRangeHint &p_range_hint) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
spin[i]->set_min(p_min);
|
||||
spin[i]->set_max(p_max);
|
||||
spin[i]->set_step(p_step);
|
||||
if (p_hide_control) {
|
||||
spin[i]->set_min(p_range_hint.min);
|
||||
spin[i]->set_max(p_range_hint.max);
|
||||
spin[i]->set_step(p_range_hint.step);
|
||||
if (p_range_hint.hide_control) {
|
||||
spin[i]->set_control_state(EditorSpinSlider::CONTROL_STATE_HIDE);
|
||||
}
|
||||
spin[i]->set_allow_greater(true);
|
||||
spin[i]->set_allow_lesser(true);
|
||||
spin[i]->set_suffix(p_suffix);
|
||||
spin[i]->set_suffix(p_range_hint.suffix);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1993,14 +1993,14 @@ void EditorPropertyRect2i::_notification(int p_what) {
|
|||
}
|
||||
}
|
||||
|
||||
void EditorPropertyRect2i::setup(int p_min, int p_max, const String &p_suffix) {
|
||||
void EditorPropertyRect2i::setup(const EditorPropertyRangeHint &p_range_hint) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
spin[i]->set_min(p_min);
|
||||
spin[i]->set_max(p_max);
|
||||
spin[i]->set_min(p_range_hint.min);
|
||||
spin[i]->set_max(p_range_hint.max);
|
||||
spin[i]->set_step(1);
|
||||
spin[i]->set_allow_greater(true);
|
||||
spin[i]->set_allow_lesser(true);
|
||||
spin[i]->set_suffix(p_suffix);
|
||||
spin[i]->set_suffix(p_range_hint.suffix);
|
||||
spin[i]->set_editing_integer(true);
|
||||
}
|
||||
}
|
||||
|
@ -2087,18 +2087,18 @@ void EditorPropertyPlane::_notification(int p_what) {
|
|||
}
|
||||
}
|
||||
|
||||
void EditorPropertyPlane::setup(double p_min, double p_max, double p_step, bool p_hide_control, const String &p_suffix) {
|
||||
void EditorPropertyPlane::setup(const EditorPropertyRangeHint &p_range_hint) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
spin[i]->set_min(p_min);
|
||||
spin[i]->set_max(p_max);
|
||||
spin[i]->set_step(p_step);
|
||||
if (p_hide_control) {
|
||||
spin[i]->set_min(p_range_hint.min);
|
||||
spin[i]->set_max(p_range_hint.max);
|
||||
spin[i]->set_step(p_range_hint.step);
|
||||
if (p_range_hint.hide_control) {
|
||||
spin[i]->set_control_state(EditorSpinSlider::CONTROL_STATE_HIDE);
|
||||
}
|
||||
spin[i]->set_allow_greater(true);
|
||||
spin[i]->set_allow_lesser(true);
|
||||
}
|
||||
spin[3]->set_suffix(p_suffix);
|
||||
spin[3]->set_suffix(p_range_hint.suffix);
|
||||
}
|
||||
|
||||
EditorPropertyPlane::EditorPropertyPlane(bool p_force_wide) {
|
||||
|
@ -2238,19 +2238,19 @@ void EditorPropertyQuaternion::_notification(int p_what) {
|
|||
}
|
||||
}
|
||||
|
||||
void EditorPropertyQuaternion::setup(double p_min, double p_max, double p_step, bool p_hide_control, const String &p_suffix, bool p_hide_editor) {
|
||||
void EditorPropertyQuaternion::setup(const EditorPropertyRangeHint &p_range_hint, bool p_hide_editor) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
spin[i]->set_min(p_min);
|
||||
spin[i]->set_max(p_max);
|
||||
spin[i]->set_step(p_step);
|
||||
if (p_hide_control) {
|
||||
spin[i]->set_min(p_range_hint.min);
|
||||
spin[i]->set_max(p_range_hint.max);
|
||||
spin[i]->set_step(p_range_hint.step);
|
||||
if (p_range_hint.hide_control) {
|
||||
spin[i]->set_control_state(EditorSpinSlider::CONTROL_STATE_HIDE);
|
||||
}
|
||||
spin[i]->set_allow_greater(true);
|
||||
spin[i]->set_allow_lesser(true);
|
||||
// Quaternion is inherently unitless, however someone may want to use it as
|
||||
// a generic way to store 4 values, so we'll still respect the suffix.
|
||||
spin[i]->set_suffix(p_suffix);
|
||||
spin[i]->set_suffix(p_range_hint.suffix);
|
||||
}
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
|
@ -2385,17 +2385,17 @@ void EditorPropertyAABB::_notification(int p_what) {
|
|||
}
|
||||
}
|
||||
|
||||
void EditorPropertyAABB::setup(double p_min, double p_max, double p_step, bool p_hide_control, const String &p_suffix) {
|
||||
void EditorPropertyAABB::setup(const EditorPropertyRangeHint &p_range_hint) {
|
||||
for (int i = 0; i < 6; i++) {
|
||||
spin[i]->set_min(p_min);
|
||||
spin[i]->set_max(p_max);
|
||||
spin[i]->set_step(p_step);
|
||||
if (p_hide_control) {
|
||||
spin[i]->set_min(p_range_hint.min);
|
||||
spin[i]->set_max(p_range_hint.max);
|
||||
spin[i]->set_step(p_range_hint.step);
|
||||
if (p_range_hint.hide_control) {
|
||||
spin[i]->set_control_state(EditorSpinSlider::CONTROL_STATE_HIDE);
|
||||
}
|
||||
spin[i]->set_allow_greater(true);
|
||||
spin[i]->set_allow_lesser(true);
|
||||
spin[i]->set_suffix(p_suffix);
|
||||
spin[i]->set_suffix(p_range_hint.suffix);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2465,18 +2465,18 @@ void EditorPropertyTransform2D::_notification(int p_what) {
|
|||
}
|
||||
}
|
||||
|
||||
void EditorPropertyTransform2D::setup(double p_min, double p_max, double p_step, bool p_hide_control, const String &p_suffix) {
|
||||
void EditorPropertyTransform2D::setup(const EditorPropertyRangeHint &p_range_hint) {
|
||||
for (int i = 0; i < 6; i++) {
|
||||
spin[i]->set_min(p_min);
|
||||
spin[i]->set_max(p_max);
|
||||
spin[i]->set_step(p_step);
|
||||
if (p_hide_control) {
|
||||
spin[i]->set_min(p_range_hint.min);
|
||||
spin[i]->set_max(p_range_hint.max);
|
||||
spin[i]->set_step(p_range_hint.step);
|
||||
if (p_range_hint.hide_control) {
|
||||
spin[i]->set_control_state(EditorSpinSlider::CONTROL_STATE_HIDE);
|
||||
}
|
||||
spin[i]->set_allow_greater(true);
|
||||
spin[i]->set_allow_lesser(true);
|
||||
if (i % 3 == 2) {
|
||||
spin[i]->set_suffix(p_suffix);
|
||||
spin[i]->set_suffix(p_range_hint.suffix);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2549,19 +2549,19 @@ void EditorPropertyBasis::_notification(int p_what) {
|
|||
}
|
||||
}
|
||||
|
||||
void EditorPropertyBasis::setup(double p_min, double p_max, double p_step, bool p_hide_control, const String &p_suffix) {
|
||||
void EditorPropertyBasis::setup(const EditorPropertyRangeHint &p_range_hint) {
|
||||
for (int i = 0; i < 9; i++) {
|
||||
spin[i]->set_min(p_min);
|
||||
spin[i]->set_max(p_max);
|
||||
spin[i]->set_step(p_step);
|
||||
if (p_hide_control) {
|
||||
spin[i]->set_min(p_range_hint.min);
|
||||
spin[i]->set_max(p_range_hint.max);
|
||||
spin[i]->set_step(p_range_hint.step);
|
||||
if (p_range_hint.hide_control) {
|
||||
spin[i]->set_control_state(EditorSpinSlider::CONTROL_STATE_HIDE);
|
||||
}
|
||||
spin[i]->set_allow_greater(true);
|
||||
spin[i]->set_allow_lesser(true);
|
||||
// Basis is inherently unitless, however someone may want to use it as
|
||||
// a generic way to store 9 values, so we'll still respect the suffix.
|
||||
spin[i]->set_suffix(p_suffix);
|
||||
spin[i]->set_suffix(p_range_hint.suffix);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2640,18 +2640,18 @@ void EditorPropertyTransform3D::_notification(int p_what) {
|
|||
}
|
||||
}
|
||||
|
||||
void EditorPropertyTransform3D::setup(double p_min, double p_max, double p_step, bool p_hide_control, const String &p_suffix) {
|
||||
void EditorPropertyTransform3D::setup(const EditorPropertyRangeHint &p_range_hint) {
|
||||
for (int i = 0; i < 12; i++) {
|
||||
spin[i]->set_min(p_min);
|
||||
spin[i]->set_max(p_max);
|
||||
spin[i]->set_step(p_step);
|
||||
if (p_hide_control) {
|
||||
spin[i]->set_min(p_range_hint.min);
|
||||
spin[i]->set_max(p_range_hint.max);
|
||||
spin[i]->set_step(p_range_hint.step);
|
||||
if (p_range_hint.hide_control) {
|
||||
spin[i]->set_control_state(EditorSpinSlider::CONTROL_STATE_HIDE);
|
||||
}
|
||||
spin[i]->set_allow_greater(true);
|
||||
spin[i]->set_allow_lesser(true);
|
||||
if (i % 4 == 3) {
|
||||
spin[i]->set_suffix(p_suffix);
|
||||
spin[i]->set_suffix(p_range_hint.suffix);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2739,18 +2739,18 @@ void EditorPropertyProjection::_notification(int p_what) {
|
|||
}
|
||||
}
|
||||
|
||||
void EditorPropertyProjection::setup(double p_min, double p_max, double p_step, bool p_hide_control, const String &p_suffix) {
|
||||
void EditorPropertyProjection::setup(const EditorPropertyRangeHint &p_range_hint) {
|
||||
for (int i = 0; i < 16; i++) {
|
||||
spin[i]->set_min(p_min);
|
||||
spin[i]->set_max(p_max);
|
||||
spin[i]->set_step(p_step);
|
||||
if (p_hide_control) {
|
||||
spin[i]->set_min(p_range_hint.min);
|
||||
spin[i]->set_max(p_range_hint.max);
|
||||
spin[i]->set_step(p_range_hint.step);
|
||||
if (p_range_hint.hide_control) {
|
||||
spin[i]->set_control_state(EditorSpinSlider::CONTROL_STATE_HIDE);
|
||||
}
|
||||
spin[i]->set_allow_greater(true);
|
||||
spin[i]->set_allow_lesser(true);
|
||||
if (i % 4 == 3) {
|
||||
spin[i]->set_suffix(p_suffix);
|
||||
spin[i]->set_suffix(p_range_hint.suffix);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3652,19 +3652,6 @@ bool EditorInspectorDefaultPlugin::parse_property(Object *p_object, const Varian
|
|||
return false;
|
||||
}
|
||||
|
||||
struct EditorPropertyRangeHint {
|
||||
bool or_greater = true;
|
||||
bool or_less = true;
|
||||
double min = 0.0;
|
||||
double max = 0.0;
|
||||
double step = 1.0;
|
||||
String suffix;
|
||||
bool exp_range = false;
|
||||
bool prefer_slider = false;
|
||||
bool hide_control = true;
|
||||
bool radians_as_degrees = false;
|
||||
};
|
||||
|
||||
static EditorPropertyRangeHint _parse_range_hint(PropertyHint p_hint, const String &p_hint_text, double p_default_step, bool is_int = false) {
|
||||
EditorPropertyRangeHint hint;
|
||||
hint.step = p_default_step;
|
||||
|
@ -3836,10 +3823,7 @@ EditorProperty *EditorInspectorDefaultPlugin::get_editor_for_property(Object *p_
|
|||
|
||||
} else {
|
||||
EditorPropertyInteger *editor = memnew(EditorPropertyInteger);
|
||||
|
||||
EditorPropertyRangeHint hint = _parse_range_hint(p_hint, p_hint_text, 1, true);
|
||||
editor->setup(hint.min, hint.max, hint.step, hint.prefer_slider, hint.hide_control, hint.or_greater, hint.or_less, hint.suffix);
|
||||
|
||||
editor->setup(_parse_range_hint(p_hint, p_hint_text, 1, true));
|
||||
return editor;
|
||||
}
|
||||
} break;
|
||||
|
@ -3864,10 +3848,7 @@ EditorProperty *EditorInspectorDefaultPlugin::get_editor_for_property(Object *p_
|
|||
|
||||
} else {
|
||||
EditorPropertyFloat *editor = memnew(EditorPropertyFloat);
|
||||
|
||||
EditorPropertyRangeHint hint = _parse_range_hint(p_hint, p_hint_text, default_float_step);
|
||||
editor->setup(hint.min, hint.max, hint.step, hint.hide_control, hint.exp_range, hint.or_greater, hint.or_less, hint.suffix, hint.radians_as_degrees);
|
||||
|
||||
editor->setup(_parse_range_hint(p_hint, p_hint_text, default_float_step));
|
||||
return editor;
|
||||
}
|
||||
} break;
|
||||
|
@ -3930,101 +3911,91 @@ EditorProperty *EditorInspectorDefaultPlugin::get_editor_for_property(Object *p_
|
|||
|
||||
case Variant::VECTOR2: {
|
||||
EditorPropertyVector2 *editor = memnew(EditorPropertyVector2(p_wide));
|
||||
|
||||
EditorPropertyRangeHint hint = _parse_range_hint(p_hint, p_hint_text, default_float_step);
|
||||
editor->setup(hint.min, hint.max, hint.step, hint.hide_control, p_hint == PROPERTY_HINT_LINK, hint.suffix, hint.radians_as_degrees);
|
||||
editor->setup(_parse_range_hint(p_hint, p_hint_text, default_float_step), p_hint == PROPERTY_HINT_LINK);
|
||||
return editor;
|
||||
|
||||
} break;
|
||||
case Variant::VECTOR2I: {
|
||||
EditorPropertyVector2i *editor = memnew(EditorPropertyVector2i(p_wide));
|
||||
EditorPropertyRangeHint hint = _parse_range_hint(p_hint, p_hint_text, 1, true);
|
||||
editor->setup(hint.min, hint.max, 1, false, p_hint == PROPERTY_HINT_LINK, hint.suffix, false, true);
|
||||
hint.step = Math::round(hint.step);
|
||||
editor->setup(hint, p_hint == PROPERTY_HINT_LINK, true);
|
||||
return editor;
|
||||
|
||||
} break;
|
||||
case Variant::RECT2: {
|
||||
EditorPropertyRect2 *editor = memnew(EditorPropertyRect2(p_wide));
|
||||
EditorPropertyRangeHint hint = _parse_range_hint(p_hint, p_hint_text, default_float_step);
|
||||
editor->setup(hint.min, hint.max, hint.step, hint.hide_control, hint.suffix);
|
||||
editor->setup(_parse_range_hint(p_hint, p_hint_text, default_float_step));
|
||||
return editor;
|
||||
} break;
|
||||
case Variant::RECT2I: {
|
||||
EditorPropertyRect2i *editor = memnew(EditorPropertyRect2i(p_wide));
|
||||
EditorPropertyRangeHint hint = _parse_range_hint(p_hint, p_hint_text, 1, true);
|
||||
editor->setup(hint.min, hint.max, hint.suffix);
|
||||
|
||||
editor->setup(_parse_range_hint(p_hint, p_hint_text, 1, true));
|
||||
return editor;
|
||||
} break;
|
||||
case Variant::VECTOR3: {
|
||||
EditorPropertyVector3 *editor = memnew(EditorPropertyVector3(p_wide));
|
||||
EditorPropertyRangeHint hint = _parse_range_hint(p_hint, p_hint_text, default_float_step);
|
||||
editor->setup(hint.min, hint.max, hint.step, hint.hide_control, p_hint == PROPERTY_HINT_LINK, hint.suffix, hint.radians_as_degrees);
|
||||
editor->setup(_parse_range_hint(p_hint, p_hint_text, default_float_step), p_hint == PROPERTY_HINT_LINK);
|
||||
return editor;
|
||||
|
||||
} break;
|
||||
case Variant::VECTOR3I: {
|
||||
EditorPropertyVector3i *editor = memnew(EditorPropertyVector3i(p_wide));
|
||||
EditorPropertyRangeHint hint = _parse_range_hint(p_hint, p_hint_text, 1, true);
|
||||
editor->setup(hint.min, hint.max, 1, false, p_hint == PROPERTY_HINT_LINK, hint.suffix, false, true);
|
||||
hint.step = Math::round(hint.step);
|
||||
editor->setup(hint, p_hint == PROPERTY_HINT_LINK, true);
|
||||
return editor;
|
||||
|
||||
} break;
|
||||
case Variant::VECTOR4: {
|
||||
EditorPropertyVector4 *editor = memnew(EditorPropertyVector4);
|
||||
EditorPropertyRangeHint hint = _parse_range_hint(p_hint, p_hint_text, default_float_step);
|
||||
editor->setup(hint.min, hint.max, hint.step, hint.hide_control, p_hint == PROPERTY_HINT_LINK, hint.suffix, hint.radians_as_degrees);
|
||||
editor->setup(_parse_range_hint(p_hint, p_hint_text, default_float_step), p_hint == PROPERTY_HINT_LINK);
|
||||
return editor;
|
||||
|
||||
} break;
|
||||
case Variant::VECTOR4I: {
|
||||
EditorPropertyVector4i *editor = memnew(EditorPropertyVector4i);
|
||||
EditorPropertyRangeHint hint = _parse_range_hint(p_hint, p_hint_text, 1, true);
|
||||
editor->setup(hint.min, hint.max, 1, false, p_hint == PROPERTY_HINT_LINK, hint.suffix, false, true);
|
||||
hint.step = Math::round(hint.step);
|
||||
editor->setup(hint, p_hint == PROPERTY_HINT_LINK, true);
|
||||
return editor;
|
||||
|
||||
} break;
|
||||
case Variant::TRANSFORM2D: {
|
||||
EditorPropertyTransform2D *editor = memnew(EditorPropertyTransform2D);
|
||||
EditorPropertyRangeHint hint = _parse_range_hint(p_hint, p_hint_text, default_float_step);
|
||||
editor->setup(hint.min, hint.max, hint.step, hint.hide_control, hint.suffix);
|
||||
editor->setup(_parse_range_hint(p_hint, p_hint_text, default_float_step));
|
||||
return editor;
|
||||
} break;
|
||||
case Variant::PLANE: {
|
||||
EditorPropertyPlane *editor = memnew(EditorPropertyPlane(p_wide));
|
||||
EditorPropertyRangeHint hint = _parse_range_hint(p_hint, p_hint_text, default_float_step);
|
||||
editor->setup(hint.min, hint.max, hint.step, hint.hide_control, hint.suffix);
|
||||
editor->setup(_parse_range_hint(p_hint, p_hint_text, default_float_step));
|
||||
return editor;
|
||||
} break;
|
||||
case Variant::QUATERNION: {
|
||||
EditorPropertyQuaternion *editor = memnew(EditorPropertyQuaternion);
|
||||
EditorPropertyRangeHint hint = _parse_range_hint(p_hint, p_hint_text, default_float_step);
|
||||
editor->setup(hint.min, hint.max, hint.step, hint.hide_control, hint.suffix, p_hint == PROPERTY_HINT_HIDE_QUATERNION_EDIT);
|
||||
editor->setup(_parse_range_hint(p_hint, p_hint_text, default_float_step), p_hint == PROPERTY_HINT_HIDE_QUATERNION_EDIT);
|
||||
return editor;
|
||||
} break;
|
||||
case Variant::AABB: {
|
||||
EditorPropertyAABB *editor = memnew(EditorPropertyAABB);
|
||||
EditorPropertyRangeHint hint = _parse_range_hint(p_hint, p_hint_text, default_float_step);
|
||||
editor->setup(hint.min, hint.max, hint.step, hint.hide_control, hint.suffix);
|
||||
editor->setup(_parse_range_hint(p_hint, p_hint_text, default_float_step));
|
||||
return editor;
|
||||
} break;
|
||||
case Variant::BASIS: {
|
||||
EditorPropertyBasis *editor = memnew(EditorPropertyBasis);
|
||||
EditorPropertyRangeHint hint = _parse_range_hint(p_hint, p_hint_text, default_float_step);
|
||||
editor->setup(hint.min, hint.max, hint.step, hint.hide_control, hint.suffix);
|
||||
editor->setup(_parse_range_hint(p_hint, p_hint_text, default_float_step));
|
||||
return editor;
|
||||
} break;
|
||||
case Variant::TRANSFORM3D: {
|
||||
EditorPropertyTransform3D *editor = memnew(EditorPropertyTransform3D);
|
||||
EditorPropertyRangeHint hint = _parse_range_hint(p_hint, p_hint_text, default_float_step);
|
||||
editor->setup(hint.min, hint.max, hint.step, hint.hide_control, hint.suffix);
|
||||
editor->setup(_parse_range_hint(p_hint, p_hint_text, default_float_step));
|
||||
return editor;
|
||||
|
||||
} break;
|
||||
case Variant::PROJECTION: {
|
||||
EditorPropertyProjection *editor = memnew(EditorPropertyProjection);
|
||||
EditorPropertyRangeHint hint = _parse_range_hint(p_hint, p_hint_text, default_float_step);
|
||||
editor->setup(hint.min, hint.max, hint.step, hint.hide_control, hint.suffix);
|
||||
editor->setup(_parse_range_hint(p_hint, p_hint_text, default_float_step));
|
||||
return editor;
|
||||
|
||||
} break;
|
||||
|
|
|
@ -46,6 +46,19 @@ class SceneTreeDialog;
|
|||
class TextEdit;
|
||||
class TextureButton;
|
||||
|
||||
struct EditorPropertyRangeHint {
|
||||
bool or_greater = true;
|
||||
bool or_less = true;
|
||||
double min = 0.0;
|
||||
double max = 0.0;
|
||||
double step = 1.0;
|
||||
String suffix;
|
||||
bool exp_range = false;
|
||||
bool prefer_slider = false;
|
||||
bool hide_control = true;
|
||||
bool radians_as_degrees = false;
|
||||
};
|
||||
|
||||
class EditorPropertyNil : public EditorProperty {
|
||||
GDCLASS(EditorPropertyNil, EditorProperty);
|
||||
LineEdit *text = nullptr;
|
||||
|
@ -371,7 +384,7 @@ protected:
|
|||
|
||||
public:
|
||||
virtual void update_property() override;
|
||||
void setup(int64_t p_min, int64_t p_max, int64_t p_step, bool p_prefer_slider, bool p_hide_control, bool p_allow_greater, bool p_allow_lesser, const String &p_suffix = String());
|
||||
void setup(const EditorPropertyRangeHint &p_range_hint);
|
||||
EditorPropertyInteger();
|
||||
};
|
||||
|
||||
|
@ -422,7 +435,7 @@ protected:
|
|||
|
||||
public:
|
||||
virtual void update_property() override;
|
||||
void setup(double p_min, double p_max, double p_step, bool p_hide_control, bool p_exp_range, bool p_greater, bool p_lesser, const String &p_suffix = String(), bool p_radians_as_degrees = false);
|
||||
void setup(const EditorPropertyRangeHint &p_range_hint);
|
||||
EditorPropertyFloat();
|
||||
};
|
||||
|
||||
|
@ -478,7 +491,7 @@ protected:
|
|||
|
||||
public:
|
||||
virtual void update_property() override;
|
||||
void setup(double p_min, double p_max, double p_step, bool p_hide_control, const String &p_suffix = String());
|
||||
void setup(const EditorPropertyRangeHint &p_range_hint);
|
||||
EditorPropertyRect2(bool p_force_wide = false);
|
||||
};
|
||||
|
||||
|
@ -493,7 +506,7 @@ protected:
|
|||
|
||||
public:
|
||||
virtual void update_property() override;
|
||||
void setup(int p_min, int p_max, const String &p_suffix = String());
|
||||
void setup(const EditorPropertyRangeHint &p_range_hint);
|
||||
EditorPropertyRect2i(bool p_force_wide = false);
|
||||
};
|
||||
|
||||
|
@ -508,7 +521,7 @@ protected:
|
|||
|
||||
public:
|
||||
virtual void update_property() override;
|
||||
void setup(double p_min, double p_max, double p_step, bool p_hide_control, const String &p_suffix = String());
|
||||
void setup(const EditorPropertyRangeHint &p_range_hint);
|
||||
EditorPropertyPlane(bool p_force_wide = false);
|
||||
};
|
||||
|
||||
|
@ -540,7 +553,7 @@ protected:
|
|||
|
||||
public:
|
||||
virtual void update_property() override;
|
||||
void setup(double p_min, double p_max, double p_step, bool p_hide_control, const String &p_suffix = String(), bool p_hide_editor = false);
|
||||
void setup(const EditorPropertyRangeHint &p_range_hint, bool p_hide_editor = false);
|
||||
EditorPropertyQuaternion();
|
||||
};
|
||||
|
||||
|
@ -555,7 +568,7 @@ protected:
|
|||
|
||||
public:
|
||||
virtual void update_property() override;
|
||||
void setup(double p_min, double p_max, double p_step, bool p_hide_control, const String &p_suffix = String());
|
||||
void setup(const EditorPropertyRangeHint &p_range_hint);
|
||||
EditorPropertyAABB();
|
||||
};
|
||||
|
||||
|
@ -570,7 +583,7 @@ protected:
|
|||
|
||||
public:
|
||||
virtual void update_property() override;
|
||||
void setup(double p_min, double p_max, double p_step, bool p_hide_control, const String &p_suffix = String());
|
||||
void setup(const EditorPropertyRangeHint &p_range_hint);
|
||||
EditorPropertyTransform2D(bool p_include_origin = true);
|
||||
};
|
||||
|
||||
|
@ -585,7 +598,7 @@ protected:
|
|||
|
||||
public:
|
||||
virtual void update_property() override;
|
||||
void setup(double p_min, double p_max, double p_step, bool p_hide_control, const String &p_suffix = String());
|
||||
void setup(const EditorPropertyRangeHint &p_range_hint);
|
||||
EditorPropertyBasis();
|
||||
};
|
||||
|
||||
|
@ -601,7 +614,7 @@ protected:
|
|||
public:
|
||||
virtual void update_property() override;
|
||||
virtual void update_using_transform(Transform3D p_transform);
|
||||
void setup(double p_min, double p_max, double p_step, bool p_hide_control, const String &p_suffix = String());
|
||||
void setup(const EditorPropertyRangeHint &p_range_hint);
|
||||
EditorPropertyTransform3D();
|
||||
};
|
||||
|
||||
|
@ -617,7 +630,7 @@ protected:
|
|||
public:
|
||||
virtual void update_property() override;
|
||||
virtual void update_using_transform(Projection p_transform);
|
||||
void setup(double p_min, double p_max, double p_step, bool p_hide_control, const String &p_suffix = String());
|
||||
void setup(const EditorPropertyRangeHint &p_range_hint);
|
||||
EditorPropertyProjection();
|
||||
};
|
||||
|
||||
|
|
|
@ -153,19 +153,19 @@ void EditorPropertyVectorN::_notification(int p_what) {
|
|||
}
|
||||
}
|
||||
|
||||
void EditorPropertyVectorN::setup(double p_min, double p_max, double p_step, bool p_hide_control, bool p_link, const String &p_suffix, bool p_radians_as_degrees, bool p_is_int) {
|
||||
radians_as_degrees = p_radians_as_degrees;
|
||||
void EditorPropertyVectorN::setup(const EditorPropertyRangeHint &p_range_hint, bool p_link, bool p_is_int) {
|
||||
radians_as_degrees = p_range_hint.radians_as_degrees;
|
||||
|
||||
for (EditorSpinSlider *spin : spin_sliders) {
|
||||
spin->set_min(p_min);
|
||||
spin->set_max(p_max);
|
||||
spin->set_step(p_step);
|
||||
if (p_hide_control) {
|
||||
spin->set_min(p_range_hint.min);
|
||||
spin->set_max(p_range_hint.max);
|
||||
spin->set_step(p_range_hint.step);
|
||||
if (p_range_hint.hide_control) {
|
||||
spin->set_control_state(EditorSpinSlider::CONTROL_STATE_HIDE);
|
||||
}
|
||||
spin->set_allow_greater(true);
|
||||
spin->set_allow_lesser(true);
|
||||
spin->set_suffix(p_suffix);
|
||||
spin->set_suffix(p_range_hint.suffix);
|
||||
spin->set_editing_integer(p_is_int);
|
||||
}
|
||||
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "editor/inspector/editor_inspector.h"
|
||||
#include "editor/inspector/editor_properties.h"
|
||||
|
||||
class EditorSpinSlider;
|
||||
class TextureButton;
|
||||
|
@ -61,7 +62,7 @@ protected:
|
|||
|
||||
public:
|
||||
virtual void update_property() override;
|
||||
void setup(double p_min, double p_max, double p_step = 1.0, bool p_hide_control = true, bool p_link = false, const String &p_suffix = String(), bool p_radians_as_degrees = false, bool p_is_int = false);
|
||||
void setup(const EditorPropertyRangeHint &p_range_hint, bool p_link = false, bool p_is_int = false);
|
||||
EditorPropertyVectorN(Variant::Type p_type, bool p_force_wide, bool p_horizontal);
|
||||
};
|
||||
|
||||
|
|
|
@ -390,6 +390,14 @@ TileProxiesManagerDialog::TileProxiesManagerDialog() {
|
|||
HBoxContainer *hboxcontainer = memnew(HBoxContainer);
|
||||
vbox_container->add_child(hboxcontainer);
|
||||
|
||||
EditorPropertyRangeHint range_hint;
|
||||
range_hint.min = -1;
|
||||
range_hint.hide_control = false;
|
||||
range_hint.or_less = false;
|
||||
|
||||
EditorPropertyRangeHint coords_property_editor_range_hint;
|
||||
coords_property_editor_range_hint.min = -1;
|
||||
|
||||
// From
|
||||
VBoxContainer *vboxcontainer_from = memnew(VBoxContainer);
|
||||
vboxcontainer_from->set_h_size_flags(Control::SIZE_EXPAND_FILL);
|
||||
|
@ -401,7 +409,7 @@ TileProxiesManagerDialog::TileProxiesManagerDialog() {
|
|||
source_from_property_editor->connect("property_changed", callable_mp(this, &TileProxiesManagerDialog::_property_changed));
|
||||
source_from_property_editor->set_selectable(false);
|
||||
source_from_property_editor->set_h_size_flags(Control::SIZE_EXPAND_FILL);
|
||||
source_from_property_editor->setup(-1, 99999, 1, false, false, true, false);
|
||||
source_from_property_editor->setup(range_hint);
|
||||
vboxcontainer_from->add_child(source_from_property_editor);
|
||||
|
||||
coords_from_property_editor = memnew(EditorPropertyVector2i);
|
||||
|
@ -410,7 +418,7 @@ TileProxiesManagerDialog::TileProxiesManagerDialog() {
|
|||
coords_from_property_editor->connect("property_changed", callable_mp(this, &TileProxiesManagerDialog::_property_changed));
|
||||
coords_from_property_editor->set_selectable(false);
|
||||
coords_from_property_editor->set_h_size_flags(Control::SIZE_EXPAND_FILL);
|
||||
coords_from_property_editor->setup(-1, 99999, true);
|
||||
coords_from_property_editor->setup(coords_property_editor_range_hint);
|
||||
coords_from_property_editor->hide();
|
||||
vboxcontainer_from->add_child(coords_from_property_editor);
|
||||
|
||||
|
@ -420,7 +428,7 @@ TileProxiesManagerDialog::TileProxiesManagerDialog() {
|
|||
alternative_from_property_editor->connect("property_changed", callable_mp(this, &TileProxiesManagerDialog::_property_changed));
|
||||
alternative_from_property_editor->set_selectable(false);
|
||||
alternative_from_property_editor->set_h_size_flags(Control::SIZE_EXPAND_FILL);
|
||||
alternative_from_property_editor->setup(-1, 99999, 1, false, false, true, false);
|
||||
alternative_from_property_editor->setup(range_hint);
|
||||
alternative_from_property_editor->hide();
|
||||
vboxcontainer_from->add_child(alternative_from_property_editor);
|
||||
|
||||
|
@ -435,7 +443,7 @@ TileProxiesManagerDialog::TileProxiesManagerDialog() {
|
|||
source_to_property_editor->connect("property_changed", callable_mp(this, &TileProxiesManagerDialog::_property_changed));
|
||||
source_to_property_editor->set_selectable(false);
|
||||
source_to_property_editor->set_h_size_flags(Control::SIZE_EXPAND_FILL);
|
||||
source_to_property_editor->setup(-1, 99999, 1, false, false, true, false);
|
||||
source_to_property_editor->setup(range_hint);
|
||||
vboxcontainer_to->add_child(source_to_property_editor);
|
||||
|
||||
coords_to_property_editor = memnew(EditorPropertyVector2i);
|
||||
|
@ -444,7 +452,7 @@ TileProxiesManagerDialog::TileProxiesManagerDialog() {
|
|||
coords_to_property_editor->connect("property_changed", callable_mp(this, &TileProxiesManagerDialog::_property_changed));
|
||||
coords_to_property_editor->set_selectable(false);
|
||||
coords_to_property_editor->set_h_size_flags(Control::SIZE_EXPAND_FILL);
|
||||
coords_to_property_editor->setup(-1, 99999, true);
|
||||
coords_to_property_editor->setup(coords_property_editor_range_hint);
|
||||
coords_to_property_editor->hide();
|
||||
vboxcontainer_to->add_child(coords_to_property_editor);
|
||||
|
||||
|
@ -454,7 +462,7 @@ TileProxiesManagerDialog::TileProxiesManagerDialog() {
|
|||
alternative_to_property_editor->connect("property_changed", callable_mp(this, &TileProxiesManagerDialog::_property_changed));
|
||||
alternative_to_property_editor->set_selectable(false);
|
||||
alternative_to_property_editor->set_h_size_flags(Control::SIZE_EXPAND_FILL);
|
||||
alternative_to_property_editor->setup(-1, 99999, 1, false, false, true, false);
|
||||
alternative_to_property_editor->setup(range_hint);
|
||||
alternative_to_property_editor->hide();
|
||||
vboxcontainer_to->add_child(alternative_to_property_editor);
|
||||
|
||||
|
|
|
@ -63,8 +63,13 @@ void BonePropertiesEditor::create_editors() {
|
|||
section->get_vbox()->add_child(enabled_checkbox);
|
||||
|
||||
// Position property.
|
||||
EditorPropertyRangeHint large_range_hint;
|
||||
large_range_hint.min = -10000;
|
||||
large_range_hint.max = 10000;
|
||||
large_range_hint.step = 0.001;
|
||||
|
||||
position_property = memnew(EditorPropertyVector3());
|
||||
position_property->setup(-10000, 10000, 0.001, true);
|
||||
position_property->setup(large_range_hint);
|
||||
position_property->set_label("Position");
|
||||
position_property->set_selectable(false);
|
||||
position_property->connect("property_changed", callable_mp(this, &BonePropertiesEditor::_value_changed));
|
||||
|
@ -73,7 +78,7 @@ void BonePropertiesEditor::create_editors() {
|
|||
|
||||
// Rotation property.
|
||||
rotation_property = memnew(EditorPropertyQuaternion());
|
||||
rotation_property->setup(-10000, 10000, 0.001, true);
|
||||
rotation_property->setup(large_range_hint);
|
||||
rotation_property->set_label("Rotation");
|
||||
rotation_property->set_selectable(false);
|
||||
rotation_property->connect("property_changed", callable_mp(this, &BonePropertiesEditor::_value_changed));
|
||||
|
@ -82,7 +87,7 @@ void BonePropertiesEditor::create_editors() {
|
|||
|
||||
// Scale property.
|
||||
scale_property = memnew(EditorPropertyVector3());
|
||||
scale_property->setup(-10000, 10000, 0.001, true, true);
|
||||
scale_property->setup(large_range_hint, true);
|
||||
scale_property->set_label("Scale");
|
||||
scale_property->set_selectable(false);
|
||||
scale_property->connect("property_changed", callable_mp(this, &BonePropertiesEditor::_value_changed));
|
||||
|
@ -96,7 +101,7 @@ void BonePropertiesEditor::create_editors() {
|
|||
|
||||
// Transform/Matrix property.
|
||||
rest_matrix = memnew(EditorPropertyTransform3D());
|
||||
rest_matrix->setup(-10000, 10000, 0.001, true);
|
||||
rest_matrix->setup(large_range_hint);
|
||||
rest_matrix->set_label("Transform");
|
||||
rest_matrix->set_selectable(false);
|
||||
rest_section->get_vbox()->add_child(rest_matrix);
|
||||
|
|
|
@ -465,7 +465,12 @@ void EditorPropertyOTVariation::update_property() {
|
|||
Vector3i range = supported.get_value_at_index(i);
|
||||
|
||||
EditorPropertyInteger *prop = memnew(EditorPropertyInteger);
|
||||
prop->setup(range.x, range.y, 1, false, true, false, false);
|
||||
EditorPropertyRangeHint hint;
|
||||
hint.min = range.x;
|
||||
hint.max = range.y;
|
||||
hint.or_greater = false;
|
||||
hint.or_less = false;
|
||||
prop->setup(hint);
|
||||
prop->set_object_and_property(object.ptr(), "keys/" + itos(name_tag));
|
||||
|
||||
String name = TS->tag_to_name(name_tag);
|
||||
|
@ -746,7 +751,13 @@ void EditorPropertyOTFeatures::update_property() {
|
|||
} break;
|
||||
case Variant::INT: {
|
||||
EditorPropertyInteger *editor = memnew(EditorPropertyInteger);
|
||||
editor->setup(0, 255, 1, false, false, false, false);
|
||||
EditorPropertyRangeHint hint;
|
||||
hint.min = 0;
|
||||
hint.max = 255;
|
||||
hint.hide_control = false;
|
||||
hint.or_greater = false;
|
||||
hint.or_less = false;
|
||||
editor->setup(hint);
|
||||
prop = editor;
|
||||
} break;
|
||||
default: {
|
||||
|
|
|
@ -1147,7 +1147,7 @@ void EditorThemeManager::_populate_standard_styles(const Ref<EditorTheme> &p_the
|
|||
|
||||
Ref<StyleBoxFlat> style_tab_focus = p_config.button_style_focus->duplicate();
|
||||
|
||||
Ref<StyleBoxFlat> style_tabbar_background = make_flat_stylebox(p_config.dark_color_1, 0, 0, 0, 0, p_config.corner_radius * EDSCALE);
|
||||
Ref<StyleBoxFlat> style_tabbar_background = make_flat_stylebox(p_config.dark_color_1, 0, 0, 0, 0, p_config.corner_radius);
|
||||
style_tabbar_background->set_corner_radius(CORNER_BOTTOM_LEFT, 0);
|
||||
style_tabbar_background->set_corner_radius(CORNER_BOTTOM_RIGHT, 0);
|
||||
p_theme->set_stylebox("tabbar_background", "TabContainer", style_tabbar_background);
|
||||
|
@ -2553,18 +2553,6 @@ void EditorThemeManager::_populate_editor_styles(const Ref<EditorTheme> &p_theme
|
|||
Ref<StyleBoxFlat> debugger_panel_style = p_config.content_panel_style->duplicate();
|
||||
debugger_panel_style->set_border_width(SIDE_BOTTOM, 0);
|
||||
p_theme->set_stylebox("DebuggerPanel", EditorStringName(EditorStyles), debugger_panel_style);
|
||||
|
||||
// This pattern of get_font()->get_height(get_font_size()) is used quite a lot and is very verbose.
|
||||
// FIXME: Introduce Theme::get_font_height() / Control::get_theme_font_height() / Window::get_theme_font_height().
|
||||
const int offset_i1 = p_theme->get_font(SNAME("tab_selected"), SNAME("TabContainer"))->get_height(p_theme->get_font_size(SNAME("tab_selected"), SNAME("TabContainer")));
|
||||
const int offset_i2 = p_theme->get_stylebox(SNAME("tab_selected"), SNAME("TabContainer"))->get_minimum_size().height;
|
||||
const int offset_i3 = p_theme->get_stylebox(SceneStringName(panel), SNAME("TabContainer"))->get_content_margin(SIDE_TOP);
|
||||
const int invisible_top_offset = offset_i1 + offset_i2 + offset_i3;
|
||||
|
||||
Ref<StyleBoxFlat> invisible_top_panel_style = p_config.content_panel_style->duplicate();
|
||||
invisible_top_panel_style->set_expand_margin(SIDE_TOP, -invisible_top_offset);
|
||||
invisible_top_panel_style->set_content_margin(SIDE_TOP, 0);
|
||||
p_theme->set_stylebox("BottomPanelDebuggerOverride", EditorStringName(EditorStyles), invisible_top_panel_style);
|
||||
}
|
||||
|
||||
// Resource and node editors.
|
||||
|
|
|
@ -84,7 +84,12 @@ void POTGenerator::generate_pot(const String &p_file) {
|
|||
const String &msgctxt = (translation.size() > 1) ? translation[1] : String();
|
||||
const String &msgid_plural = (translation.size() > 2) ? translation[2] : String();
|
||||
const String &comment = (translation.size() > 3) ? translation[3] : String();
|
||||
_add_new_msgid(translation[0], msgctxt, msgid_plural, file_path, comment);
|
||||
const int source_line = (translation.size() > 4) ? translation[4].to_int() : 0;
|
||||
String location = file_path;
|
||||
if (source_line > 0) {
|
||||
location += vformat(":%d", source_line);
|
||||
}
|
||||
_add_new_msgid(translation[0], msgctxt, msgid_plural, location, comment);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -72,6 +72,12 @@ if env["builtin_freetype"]:
|
|||
if env["builtin_libpng"]:
|
||||
env_freetype.Prepend(CPPPATH=["#thirdparty/libpng"])
|
||||
|
||||
if "text_server_adv" in env.module_list:
|
||||
# HarfBuzz is only available if TextServerAdvanced is enabled
|
||||
env_freetype.Append(CPPDEFINES=["FT_CONFIG_OPTION_USE_HARFBUZZ"])
|
||||
if env["builtin_harfbuzz"]:
|
||||
env_freetype.Prepend(CPPPATH=["#thirdparty/harfbuzz/src/"])
|
||||
|
||||
sfnt = thirdparty_dir + "src/sfnt/sfnt.c"
|
||||
# Must be done after all CPPDEFINES are being set so we can copy them.
|
||||
if env["platform"] == "web":
|
||||
|
|
|
@ -126,7 +126,7 @@ void GDScriptEditorTranslationParserPlugin::_add_id(const String &p_id, int p_li
|
|||
return;
|
||||
}
|
||||
|
||||
translations->push_back({ p_id, String(), String(), comment });
|
||||
translations->push_back({ p_id, String(), String(), comment, itos(p_line) });
|
||||
}
|
||||
|
||||
void GDScriptEditorTranslationParserPlugin::_add_id_ctx_plural(const Vector<String> &p_id_ctx_plural, int p_line) {
|
||||
|
@ -136,7 +136,7 @@ void GDScriptEditorTranslationParserPlugin::_add_id_ctx_plural(const Vector<Stri
|
|||
return;
|
||||
}
|
||||
|
||||
translations->push_back({ p_id_ctx_plural[0], p_id_ctx_plural[1], p_id_ctx_plural[2], comment });
|
||||
translations->push_back({ p_id_ctx_plural[0], p_id_ctx_plural[1], p_id_ctx_plural[2], comment, itos(p_line) });
|
||||
}
|
||||
|
||||
void GDScriptEditorTranslationParserPlugin::_traverse_class(const GDScriptParser::ClassNode *p_class) {
|
||||
|
|
|
@ -135,6 +135,7 @@ static Ref<ImporterMesh> _mesh_to_importer_mesh(Ref<Mesh> p_mesh) {
|
|||
mat_name, p_mesh->surface_get_format(surface_i));
|
||||
}
|
||||
importer_mesh->merge_meta_from(*p_mesh);
|
||||
importer_mesh->set_name(p_mesh->get_name());
|
||||
return importer_mesh;
|
||||
}
|
||||
|
||||
|
@ -565,7 +566,9 @@ String GLTFDocument::_gen_unique_bone_name(Ref<GLTFState> p_state, const GLTFSke
|
|||
|
||||
Error GLTFDocument::_parse_scenes(Ref<GLTFState> p_state) {
|
||||
p_state->unique_names.insert("Skeleton3D"); // Reserve skeleton name.
|
||||
ERR_FAIL_COND_V(!p_state->json.has("scenes"), ERR_FILE_CORRUPT);
|
||||
if (!p_state->json.has("scenes")) {
|
||||
return OK; // No scenes.
|
||||
}
|
||||
const Array &scenes = p_state->json["scenes"];
|
||||
int loaded_scene = 0;
|
||||
if (p_state->json.has("scene")) {
|
||||
|
@ -577,10 +580,11 @@ Error GLTFDocument::_parse_scenes(Ref<GLTFState> p_state) {
|
|||
if (scenes.size()) {
|
||||
ERR_FAIL_COND_V(loaded_scene >= scenes.size(), ERR_FILE_CORRUPT);
|
||||
const Dictionary &scene_dict = scenes[loaded_scene];
|
||||
ERR_FAIL_COND_V(!scene_dict.has("nodes"), ERR_UNAVAILABLE);
|
||||
const Array &nodes = scene_dict["nodes"];
|
||||
for (int j = 0; j < nodes.size(); j++) {
|
||||
p_state->root_nodes.push_back(nodes[j]);
|
||||
if (scene_dict.has("nodes")) {
|
||||
const Array &nodes = scene_dict["nodes"];
|
||||
for (const Variant &node : nodes) {
|
||||
p_state->root_nodes.push_back(node);
|
||||
}
|
||||
}
|
||||
// Determine what to use for the scene name.
|
||||
if (scene_dict.has("name") && !String(scene_dict["name"]).is_empty() && !((String)scene_dict["name"]).begins_with("Scene")) {
|
||||
|
@ -597,7 +601,9 @@ Error GLTFDocument::_parse_scenes(Ref<GLTFState> p_state) {
|
|||
}
|
||||
|
||||
Error GLTFDocument::_parse_nodes(Ref<GLTFState> p_state) {
|
||||
ERR_FAIL_COND_V(!p_state->json.has("nodes"), ERR_FILE_CORRUPT);
|
||||
if (!p_state->json.has("nodes")) {
|
||||
return OK; // No nodes to parse.
|
||||
}
|
||||
const Array &nodes = p_state->json["nodes"];
|
||||
for (int i = 0; i < nodes.size(); i++) {
|
||||
Ref<GLTFNode> node;
|
||||
|
@ -2840,13 +2846,14 @@ Error GLTFDocument::_serialize_meshes(Ref<GLTFState> p_state) {
|
|||
Array meshes;
|
||||
for (GLTFMeshIndex gltf_mesh_i = 0; gltf_mesh_i < p_state->meshes.size(); gltf_mesh_i++) {
|
||||
print_verbose("glTF: Serializing mesh: " + itos(gltf_mesh_i));
|
||||
Ref<ImporterMesh> import_mesh = p_state->meshes.write[gltf_mesh_i]->get_mesh();
|
||||
Ref<GLTFMesh> &gltf_mesh = p_state->meshes.write[gltf_mesh_i];
|
||||
Ref<ImporterMesh> import_mesh = gltf_mesh->get_mesh();
|
||||
if (import_mesh.is_null()) {
|
||||
continue;
|
||||
}
|
||||
Array instance_materials = p_state->meshes.write[gltf_mesh_i]->get_instance_materials();
|
||||
Array instance_materials = gltf_mesh->get_instance_materials();
|
||||
Array primitives;
|
||||
Dictionary gltf_mesh;
|
||||
Dictionary mesh_dict;
|
||||
Array target_names;
|
||||
Array weights;
|
||||
for (int morph_i = 0; morph_i < import_mesh->get_blend_shape_count(); morph_i++) {
|
||||
|
@ -3233,27 +3240,31 @@ Error GLTFDocument::_serialize_meshes(Ref<GLTFState> p_state) {
|
|||
if (!target_names.is_empty()) {
|
||||
Dictionary e;
|
||||
e["targetNames"] = target_names;
|
||||
gltf_mesh["extras"] = e;
|
||||
mesh_dict["extras"] = e;
|
||||
}
|
||||
_attach_meta_to_extras(import_mesh, gltf_mesh);
|
||||
_attach_meta_to_extras(import_mesh, mesh_dict);
|
||||
|
||||
weights.resize(target_names.size());
|
||||
for (int name_i = 0; name_i < target_names.size(); name_i++) {
|
||||
real_t weight = 0.0;
|
||||
if (name_i < p_state->meshes.write[gltf_mesh_i]->get_blend_weights().size()) {
|
||||
weight = p_state->meshes.write[gltf_mesh_i]->get_blend_weights()[name_i];
|
||||
if (name_i < gltf_mesh->get_blend_weights().size()) {
|
||||
weight = gltf_mesh->get_blend_weights()[name_i];
|
||||
}
|
||||
weights[name_i] = weight;
|
||||
}
|
||||
if (weights.size()) {
|
||||
gltf_mesh["weights"] = weights;
|
||||
mesh_dict["weights"] = weights;
|
||||
}
|
||||
|
||||
ERR_FAIL_COND_V(target_names.size() != weights.size(), FAILED);
|
||||
|
||||
gltf_mesh["primitives"] = primitives;
|
||||
mesh_dict["primitives"] = primitives;
|
||||
|
||||
meshes.push_back(gltf_mesh);
|
||||
if (!gltf_mesh->get_name().is_empty()) {
|
||||
mesh_dict["name"] = gltf_mesh->get_name();
|
||||
}
|
||||
|
||||
meshes.push_back(mesh_dict);
|
||||
}
|
||||
|
||||
if (!meshes.size()) {
|
||||
|
@ -4482,19 +4493,19 @@ Error GLTFDocument::_parse_texture_samplers(Ref<GLTFState> p_state) {
|
|||
Error GLTFDocument::_serialize_materials(Ref<GLTFState> p_state) {
|
||||
Array materials;
|
||||
for (int32_t i = 0; i < p_state->materials.size(); i++) {
|
||||
Dictionary d;
|
||||
Dictionary mat_dict;
|
||||
Ref<Material> material = p_state->materials[i];
|
||||
if (material.is_null()) {
|
||||
materials.push_back(d);
|
||||
materials.push_back(mat_dict);
|
||||
continue;
|
||||
}
|
||||
if (!material->get_name().is_empty()) {
|
||||
d["name"] = _gen_unique_name(p_state, material->get_name());
|
||||
mat_dict["name"] = _gen_unique_name(p_state, material->get_name());
|
||||
}
|
||||
|
||||
Ref<BaseMaterial3D> base_material = material;
|
||||
if (base_material.is_null()) {
|
||||
materials.push_back(d);
|
||||
materials.push_back(mat_dict);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -4647,7 +4658,7 @@ Error GLTFDocument::_serialize_materials(Ref<GLTFState> p_state) {
|
|||
if (has_ao) {
|
||||
Dictionary occt;
|
||||
occt["index"] = orm_texture_index;
|
||||
d["occlusionTexture"] = occt;
|
||||
mat_dict["occlusionTexture"] = occt;
|
||||
}
|
||||
if (has_roughness || has_metalness) {
|
||||
mrt["index"] = orm_texture_index;
|
||||
|
@ -4661,7 +4672,7 @@ Error GLTFDocument::_serialize_materials(Ref<GLTFState> p_state) {
|
|||
}
|
||||
}
|
||||
|
||||
d["pbrMetallicRoughness"] = mr;
|
||||
mat_dict["pbrMetallicRoughness"] = mr;
|
||||
if (base_material->get_feature(BaseMaterial3D::FEATURE_NORMAL_MAPPING) && _image_format != "None") {
|
||||
Dictionary nt;
|
||||
Ref<ImageTexture> tex;
|
||||
|
@ -4701,14 +4712,14 @@ Error GLTFDocument::_serialize_materials(Ref<GLTFState> p_state) {
|
|||
nt["scale"] = base_material->get_normal_scale();
|
||||
if (gltf_texture_index != -1) {
|
||||
nt["index"] = gltf_texture_index;
|
||||
d["normalTexture"] = nt;
|
||||
mat_dict["normalTexture"] = nt;
|
||||
}
|
||||
}
|
||||
|
||||
if (base_material->get_feature(BaseMaterial3D::FEATURE_EMISSION)) {
|
||||
const Color c = base_material->get_emission().linear_to_srgb();
|
||||
Array arr = { c.r, c.g, c.b };
|
||||
d["emissiveFactor"] = arr;
|
||||
mat_dict["emissiveFactor"] = arr;
|
||||
}
|
||||
|
||||
if (base_material->get_feature(BaseMaterial3D::FEATURE_EMISSION) && _image_format != "None") {
|
||||
|
@ -4722,20 +4733,20 @@ Error GLTFDocument::_serialize_materials(Ref<GLTFState> p_state) {
|
|||
|
||||
if (gltf_texture_index != -1) {
|
||||
et["index"] = gltf_texture_index;
|
||||
d["emissiveTexture"] = et;
|
||||
mat_dict["emissiveTexture"] = et;
|
||||
}
|
||||
}
|
||||
|
||||
const bool ds = base_material->get_cull_mode() == BaseMaterial3D::CULL_DISABLED;
|
||||
if (ds) {
|
||||
d["doubleSided"] = ds;
|
||||
mat_dict["doubleSided"] = ds;
|
||||
}
|
||||
|
||||
if (base_material->get_transparency() == BaseMaterial3D::TRANSPARENCY_ALPHA_SCISSOR) {
|
||||
d["alphaMode"] = "MASK";
|
||||
d["alphaCutoff"] = base_material->get_alpha_scissor_threshold();
|
||||
mat_dict["alphaMode"] = "MASK";
|
||||
mat_dict["alphaCutoff"] = base_material->get_alpha_scissor_threshold();
|
||||
} else if (base_material->get_transparency() != BaseMaterial3D::TRANSPARENCY_DISABLED) {
|
||||
d["alphaMode"] = "BLEND";
|
||||
mat_dict["alphaMode"] = "BLEND";
|
||||
}
|
||||
|
||||
Dictionary extensions;
|
||||
|
@ -4750,10 +4761,10 @@ Error GLTFDocument::_serialize_materials(Ref<GLTFState> p_state) {
|
|||
extensions["KHR_materials_emissive_strength"] = mat_emissive_strength;
|
||||
p_state->add_used_extension("KHR_materials_emissive_strength");
|
||||
}
|
||||
d["extensions"] = extensions;
|
||||
mat_dict["extensions"] = extensions;
|
||||
|
||||
_attach_meta_to_extras(material, d);
|
||||
materials.push_back(d);
|
||||
_attach_meta_to_extras(material, mat_dict);
|
||||
materials.push_back(mat_dict);
|
||||
}
|
||||
if (!materials.size()) {
|
||||
return OK;
|
||||
|
@ -5858,6 +5869,10 @@ GLTFMeshIndex GLTFDocument::_convert_mesh_to_gltf(Ref<GLTFState> p_state, MeshIn
|
|||
|
||||
Ref<GLTFMesh> gltf_mesh;
|
||||
gltf_mesh.instantiate();
|
||||
if (!mesh_resource->get_name().is_empty()) {
|
||||
gltf_mesh->set_original_name(mesh_resource->get_name());
|
||||
gltf_mesh->set_name(_gen_unique_name(p_state, mesh_resource->get_name()));
|
||||
}
|
||||
gltf_mesh->set_instance_materials(instance_materials);
|
||||
gltf_mesh->set_mesh(current_mesh);
|
||||
gltf_mesh->set_blend_weights(blend_weights);
|
||||
|
@ -8677,6 +8692,7 @@ Node *GLTFDocument::_generate_scene_node_tree(Ref<GLTFState> p_state) {
|
|||
// Generate the node tree.
|
||||
Node *single_root;
|
||||
if (p_state->extensions_used.has("GODOT_single_root")) {
|
||||
ERR_FAIL_COND_V_MSG(p_state->nodes.is_empty(), nullptr, "glTF: Single root file has no nodes. This glTF file is invalid.");
|
||||
if (_naming_version < 2) {
|
||||
_generate_scene_node_compat_4pt4(p_state, 0, nullptr, nullptr);
|
||||
} else {
|
||||
|
@ -8844,50 +8860,53 @@ Error GLTFDocument::write_to_filesystem(Ref<GLTFState> p_state, const String &p_
|
|||
}
|
||||
|
||||
Node *GLTFDocument::generate_scene(Ref<GLTFState> p_state, float p_bake_fps, bool p_trimming, bool p_remove_immutable_tracks) {
|
||||
Ref<GLTFState> state = p_state;
|
||||
ERR_FAIL_COND_V(state.is_null(), nullptr);
|
||||
ERR_FAIL_INDEX_V(0, state->root_nodes.size(), nullptr);
|
||||
ERR_FAIL_COND_V(p_state.is_null(), nullptr);
|
||||
// The glTF file must have nodes, and have some marked as root nodes, in order to generate a scene.
|
||||
if (p_state->nodes.is_empty()) {
|
||||
WARN_PRINT("glTF: This glTF file has no nodes, the generated Godot scene will be empty.");
|
||||
}
|
||||
// Now that we know that we have glTF nodes, we can begin generating a scene from the parsed glTF data.
|
||||
Error err = OK;
|
||||
p_state->set_bake_fps(p_bake_fps);
|
||||
Node *root = _generate_scene_node_tree(state);
|
||||
ERR_FAIL_NULL_V(root, nullptr);
|
||||
_process_mesh_instances(state, root);
|
||||
if (state->get_create_animations() && state->animations.size()) {
|
||||
AnimationPlayer *ap = memnew(AnimationPlayer);
|
||||
root->add_child(ap, true);
|
||||
ap->set_owner(root);
|
||||
for (int i = 0; i < state->animations.size(); i++) {
|
||||
_import_animation(state, ap, i, p_trimming, p_remove_immutable_tracks);
|
||||
Node *godot_root_node = _generate_scene_node_tree(p_state);
|
||||
ERR_FAIL_NULL_V(godot_root_node, nullptr);
|
||||
_process_mesh_instances(p_state, godot_root_node);
|
||||
if (p_state->get_create_animations() && p_state->animations.size()) {
|
||||
AnimationPlayer *anim_player = memnew(AnimationPlayer);
|
||||
godot_root_node->add_child(anim_player, true);
|
||||
anim_player->set_owner(godot_root_node);
|
||||
for (int i = 0; i < p_state->animations.size(); i++) {
|
||||
_import_animation(p_state, anim_player, i, p_trimming, p_remove_immutable_tracks);
|
||||
}
|
||||
}
|
||||
for (KeyValue<GLTFNodeIndex, Node *> E : state->scene_nodes) {
|
||||
for (KeyValue<GLTFNodeIndex, Node *> E : p_state->scene_nodes) {
|
||||
ERR_CONTINUE(!E.value);
|
||||
for (Ref<GLTFDocumentExtension> ext : document_extensions) {
|
||||
ERR_CONTINUE(ext.is_null());
|
||||
Dictionary node_json;
|
||||
if (state->json.has("nodes")) {
|
||||
Array nodes = state->json["nodes"];
|
||||
if (p_state->json.has("nodes")) {
|
||||
Array nodes = p_state->json["nodes"];
|
||||
if (0 <= E.key && E.key < nodes.size()) {
|
||||
node_json = nodes[E.key];
|
||||
}
|
||||
}
|
||||
Ref<GLTFNode> gltf_node = state->nodes[E.key];
|
||||
Ref<GLTFNode> gltf_node = p_state->nodes[E.key];
|
||||
err = ext->import_node(p_state, gltf_node, node_json, E.value);
|
||||
ERR_CONTINUE(err != OK);
|
||||
}
|
||||
}
|
||||
ImporterMeshInstance3D *root_importer_mesh = Object::cast_to<ImporterMeshInstance3D>(root);
|
||||
ImporterMeshInstance3D *root_importer_mesh = Object::cast_to<ImporterMeshInstance3D>(godot_root_node);
|
||||
if (unlikely(root_importer_mesh)) {
|
||||
root = GLTFDocumentExtensionConvertImporterMesh::convert_importer_mesh_instance_3d(root_importer_mesh);
|
||||
godot_root_node = GLTFDocumentExtensionConvertImporterMesh::convert_importer_mesh_instance_3d(root_importer_mesh);
|
||||
memdelete(root_importer_mesh);
|
||||
}
|
||||
for (Ref<GLTFDocumentExtension> ext : document_extensions) {
|
||||
ERR_CONTINUE(ext.is_null());
|
||||
err = ext->import_post(p_state, root);
|
||||
err = ext->import_post(p_state, godot_root_node);
|
||||
ERR_CONTINUE(err != OK);
|
||||
}
|
||||
ERR_FAIL_NULL_V(root, nullptr);
|
||||
return root;
|
||||
ERR_FAIL_NULL_V(godot_root_node, nullptr);
|
||||
return godot_root_node;
|
||||
}
|
||||
|
||||
Error GLTFDocument::append_from_scene(Node *p_node, Ref<GLTFState> p_state, uint32_t p_flags) {
|
||||
|
|
|
@ -55,6 +55,7 @@ if env["builtin_harfbuzz"]:
|
|||
# "src/hb-glib.cc",
|
||||
# "src/hb-gobject-structs.cc",
|
||||
"src/hb-icu.cc",
|
||||
# "src/hb-kbts.cc",
|
||||
"src/hb-map.cc",
|
||||
"src/hb-number.cc",
|
||||
"src/hb-ot-cff1-table.cc",
|
||||
|
@ -95,14 +96,19 @@ if env["builtin_harfbuzz"]:
|
|||
"src/hb-shaper.cc",
|
||||
"src/hb-static.cc",
|
||||
"src/hb-style.cc",
|
||||
"src/hb-subset-cff-common.cc",
|
||||
"src/hb-subset-cff1.cc",
|
||||
"src/hb-subset-cff2.cc",
|
||||
"src/hb-subset-input.cc",
|
||||
"src/hb-subset-instancer-iup.cc",
|
||||
"src/hb-subset-instancer-solver.cc",
|
||||
"src/hb-subset-plan.cc",
|
||||
"src/hb-subset-serialize.cc",
|
||||
# "src/hb-subset-cff-common.cc",
|
||||
# "src/hb-subset-cff1.cc",
|
||||
# "src/hb-subset-cff2.cc",
|
||||
# "src/hb-subset-input.cc",
|
||||
# "src/hb-subset-instancer-iup.cc",
|
||||
# "src/hb-subset-instancer-solver.cc",
|
||||
# "src/hb-subset-plan.cc",
|
||||
# "src/hb-subset-serialize.cc",
|
||||
# "src/hb-subset-table-cff.cc",
|
||||
# "src/hb-subset-table-color.cc",
|
||||
# "src/hb-subset-table-layout.cc",
|
||||
# "src/hb-subset-table-other.cc",
|
||||
# "src/hb-subset-table-var.cc",
|
||||
"src/hb-subset.cc",
|
||||
"src/hb-ucd.cc",
|
||||
"src/hb-unicode.cc",
|
||||
|
|
|
@ -2177,7 +2177,9 @@ void EditorExportPlatformAndroid::get_export_options(List<ExportOption> *r_optio
|
|||
|
||||
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "shader_baker/enabled"), false));
|
||||
|
||||
#ifndef XR_DISABLED
|
||||
r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "xr_features/xr_mode", PROPERTY_HINT_ENUM, "Regular,OpenXR"), XR_MODE_REGULAR, false, true));
|
||||
#endif // XR_DISABLED
|
||||
|
||||
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "gesture/swipe_to_dismiss"), false));
|
||||
|
||||
|
@ -3087,6 +3089,7 @@ void EditorExportPlatformAndroid::get_command_line_flags(const Ref<EditorExportP
|
|||
command_line_strings.push_back(apk_expansion_public_key.strip_edges());
|
||||
}
|
||||
|
||||
#ifndef XR_DISABLED
|
||||
int xr_mode_index = p_preset->get("xr_features/xr_mode");
|
||||
if (xr_mode_index == XR_MODE_OPENXR) {
|
||||
command_line_strings.push_back("--xr_mode_openxr");
|
||||
|
@ -3100,6 +3103,7 @@ void EditorExportPlatformAndroid::get_command_line_flags(const Ref<EditorExportP
|
|||
command_line_strings.push_back("--xr-mode");
|
||||
command_line_strings.push_back("off");
|
||||
}
|
||||
#endif // XR_DISABLED
|
||||
|
||||
bool immersive = p_preset->get("screen/immersive_mode");
|
||||
if (immersive) {
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "scene/2d/node_2d.h"
|
||||
#include "scene/resources/mesh.h"
|
||||
|
||||
class NavigationPolygon;
|
||||
class NavigationMeshSourceGeometryData2D;
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#include "scene/2d/tile_map.h"
|
||||
#include "scene/gui/control.h"
|
||||
#include "scene/resources/2d/navigation_mesh_source_geometry_data_2d.h"
|
||||
#include "scene/resources/material.h"
|
||||
#include "scene/resources/world_2d.h"
|
||||
|
||||
#ifndef PHYSICS_2D_DISABLED
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
|
||||
#include "animation_blend_tree.h"
|
||||
#include "core/math/geometry_2d.h"
|
||||
#include "scene/resources/material.h"
|
||||
|
||||
void AnimationNodeBlendSpace2D::get_parameter_list(List<PropertyInfo> *r_list) const {
|
||||
AnimationNode::get_parameter_list(r_list);
|
||||
|
|
|
@ -36,6 +36,10 @@
|
|||
#include "scene/main/viewport.h"
|
||||
#include "scene/theme/theme_db.h"
|
||||
|
||||
static inline Color _select_color(const Color &p_override_color, const Color &p_default_color) {
|
||||
return p_override_color.a > 0 ? p_override_color : p_default_color;
|
||||
}
|
||||
|
||||
Size2 TabBar::get_minimum_size() const {
|
||||
Size2 ms;
|
||||
|
||||
|
@ -527,15 +531,15 @@ void TabBar::_notification(int p_what) {
|
|||
|
||||
if (tabs[i].disabled) {
|
||||
sb = theme_cache.tab_disabled_style;
|
||||
fnt_col = theme_cache.font_disabled_color;
|
||||
fnt_col = _select_color(tabs[i].font_color_overrides[DrawMode::DRAW_DISABLED], theme_cache.font_disabled_color);
|
||||
icn_col = theme_cache.icon_disabled_color;
|
||||
} else if (i == hover) {
|
||||
sb = theme_cache.tab_hovered_style;
|
||||
fnt_col = theme_cache.font_hovered_color;
|
||||
fnt_col = _select_color(tabs[i].font_color_overrides[DrawMode::DRAW_HOVER], theme_cache.font_hovered_color);
|
||||
icn_col = theme_cache.icon_hovered_color;
|
||||
} else {
|
||||
sb = theme_cache.tab_unselected_style;
|
||||
fnt_col = theme_cache.font_unselected_color;
|
||||
fnt_col = _select_color(tabs[i].font_color_overrides[DrawMode::DRAW_NORMAL], theme_cache.font_unselected_color);
|
||||
icn_col = theme_cache.icon_unselected_color;
|
||||
}
|
||||
|
||||
|
@ -546,8 +550,9 @@ void TabBar::_notification(int p_what) {
|
|||
// Draw selected tab in the front, but only if it's visible.
|
||||
if (current >= offset && current <= max_drawn_tab && !tabs[current].hidden) {
|
||||
Ref<StyleBox> sb = tabs[current].disabled ? theme_cache.tab_disabled_style : theme_cache.tab_selected_style;
|
||||
Color col = _select_color(tabs[current].font_color_overrides[DrawMode::DRAW_PRESSED], theme_cache.font_selected_color);
|
||||
|
||||
_draw_tab(sb, theme_cache.font_selected_color, theme_cache.icon_selected_color, current, rtl ? (size.width - tabs[current].ofs_cache - tabs[current].size_cache) : tabs[current].ofs_cache, has_focus(true));
|
||||
_draw_tab(sb, col, theme_cache.icon_selected_color, current, rtl ? (size.width - tabs[current].ofs_cache - tabs[current].size_cache) : tabs[current].ofs_cache, has_focus(true));
|
||||
}
|
||||
|
||||
if (buttons_visible) {
|
||||
|
@ -1009,6 +1014,37 @@ int TabBar::get_tab_icon_max_width(int p_tab) const {
|
|||
return tabs[p_tab].icon_max_width;
|
||||
}
|
||||
|
||||
void TabBar::set_font_color_override_all(int p_tab, const Color &p_color) {
|
||||
ERR_FAIL_INDEX(p_tab, tabs.size());
|
||||
|
||||
Tab &tab = tabs.write[p_tab];
|
||||
for (int i = 0; i < DrawMode::DRAW_MAX; i++) {
|
||||
tab.font_color_overrides[i] = p_color;
|
||||
}
|
||||
|
||||
queue_redraw();
|
||||
}
|
||||
|
||||
void TabBar::set_font_color_override(int p_tab, DrawMode p_draw_mode, const Color &p_color) {
|
||||
ERR_FAIL_INDEX(p_tab, tabs.size());
|
||||
ERR_FAIL_INDEX(p_draw_mode, DrawMode::DRAW_MAX);
|
||||
|
||||
if (tabs[p_tab].font_color_overrides[p_draw_mode] == p_color) {
|
||||
return;
|
||||
}
|
||||
|
||||
tabs.write[p_tab].font_color_overrides[p_draw_mode] = p_color;
|
||||
|
||||
queue_redraw();
|
||||
}
|
||||
|
||||
Color TabBar::get_font_color_override(int p_tab, DrawMode p_draw_mode) const {
|
||||
ERR_FAIL_INDEX_V(p_tab, tabs.size(), Color());
|
||||
ERR_FAIL_INDEX_V(p_draw_mode, DrawMode::DRAW_MAX, Color());
|
||||
|
||||
return tabs[p_tab].font_color_overrides[p_draw_mode];
|
||||
}
|
||||
|
||||
void TabBar::set_tab_disabled(int p_tab, bool p_disabled) {
|
||||
ERR_FAIL_INDEX(p_tab, tabs.size());
|
||||
|
||||
|
|
|
@ -52,11 +52,22 @@ public:
|
|||
CLOSE_BUTTON_MAX
|
||||
};
|
||||
|
||||
enum DrawMode {
|
||||
DRAW_NORMAL,
|
||||
DRAW_PRESSED,
|
||||
DRAW_HOVER,
|
||||
DRAW_DISABLED,
|
||||
DRAW_MAX,
|
||||
};
|
||||
|
||||
private:
|
||||
struct Tab {
|
||||
mutable RID accessibility_item_element;
|
||||
mutable bool accessibility_item_dirty = true;
|
||||
|
||||
// Corresponds to color overrides for the DrawMode enum
|
||||
Color font_color_overrides[DrawMode::DRAW_MAX] = { Color(0, 0, 0, 0), Color(0, 0, 0, 0), Color(0, 0, 0, 0), Color(0, 0, 0, 0) };
|
||||
|
||||
String text;
|
||||
String tooltip;
|
||||
|
||||
|
@ -228,6 +239,10 @@ public:
|
|||
void set_tab_icon_max_width(int p_tab, int p_width);
|
||||
int get_tab_icon_max_width(int p_tab) const;
|
||||
|
||||
void set_font_color_override_all(int p_tab, const Color &p_color);
|
||||
void set_font_color_override(int p_tab, DrawMode p_draw_mode, const Color &p_color);
|
||||
Color get_font_color_override(int p_tab, DrawMode p_draw_mode) const;
|
||||
|
||||
void set_tab_disabled(int p_tab, bool p_disabled);
|
||||
bool is_tab_disabled(int p_tab) const;
|
||||
|
||||
|
|
|
@ -947,8 +947,7 @@ void CanvasItem::draw_set_transform(const Point2 &p_offset, real_t p_rot, const
|
|||
ERR_THREAD_GUARD;
|
||||
ERR_DRAW_GUARD;
|
||||
|
||||
Transform2D xform(p_rot, p_offset);
|
||||
xform.scale_basis(p_scale);
|
||||
Transform2D xform(p_rot, p_scale, 0.0, p_offset);
|
||||
RenderingServer::get_singleton()->canvas_item_add_set_transform(canvas_item, xform);
|
||||
}
|
||||
|
||||
|
|
|
@ -4768,6 +4768,7 @@ void Viewport::_propagate_exit_world_3d(Node *p_node) {
|
|||
}
|
||||
}
|
||||
|
||||
#ifndef XR_DISABLED
|
||||
void Viewport::set_use_xr(bool p_use_xr) {
|
||||
ERR_MAIN_THREAD_GUARD;
|
||||
if (use_xr != p_use_xr) {
|
||||
|
@ -4794,6 +4795,7 @@ bool Viewport::is_using_xr() {
|
|||
ERR_READ_THREAD_GUARD_V(false);
|
||||
return use_xr;
|
||||
}
|
||||
#endif // XR_DISABLED
|
||||
|
||||
void Viewport::set_scaling_3d_mode(Scaling3DMode p_scaling_3d_mode) {
|
||||
ERR_MAIN_THREAD_GUARD;
|
||||
|
@ -5060,8 +5062,10 @@ void Viewport::_bind_methods() {
|
|||
ClassDB::bind_method(D_METHOD("set_disable_3d", "disable"), &Viewport::set_disable_3d);
|
||||
ClassDB::bind_method(D_METHOD("is_3d_disabled"), &Viewport::is_3d_disabled);
|
||||
|
||||
#ifndef XR_DISABLED
|
||||
ClassDB::bind_method(D_METHOD("set_use_xr", "use"), &Viewport::set_use_xr);
|
||||
ClassDB::bind_method(D_METHOD("is_using_xr"), &Viewport::is_using_xr);
|
||||
#endif // XR_DISABLED
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_scaling_3d_mode", "scaling_3d_mode"), &Viewport::set_scaling_3d_mode);
|
||||
ClassDB::bind_method(D_METHOD("get_scaling_3d_mode"), &Viewport::get_scaling_3d_mode);
|
||||
|
@ -5088,7 +5092,9 @@ void Viewport::_bind_methods() {
|
|||
ClassDB::bind_method(D_METHOD("get_vrs_texture"), &Viewport::get_vrs_texture);
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "disable_3d"), "set_disable_3d", "is_3d_disabled");
|
||||
#ifndef XR_DISABLED
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_xr"), "set_use_xr", "is_using_xr");
|
||||
#endif // XR_DISABLED
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "own_world_3d"), "set_use_own_world_3d", "is_using_own_world_3d");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "world_3d", PROPERTY_HINT_RESOURCE_TYPE, "World3D"), "set_world_3d", "get_world_3d");
|
||||
#endif // _3D_DISABLED
|
||||
|
|
|
@ -788,7 +788,9 @@ public:
|
|||
#ifndef _3D_DISABLED
|
||||
private:
|
||||
// 3D audio, camera, physics, and world.
|
||||
#ifndef XR_DISABLED
|
||||
bool use_xr = false;
|
||||
#endif // XR_DISABLED
|
||||
friend class AudioListener3D;
|
||||
AudioListener3D *audio_listener_3d = nullptr;
|
||||
HashSet<AudioListener3D *> audio_listener_3d_set;
|
||||
|
@ -846,8 +848,10 @@ public:
|
|||
void set_use_own_world_3d(bool p_use_own_world_3d);
|
||||
bool is_using_own_world_3d() const;
|
||||
|
||||
#ifndef XR_DISABLED
|
||||
void set_use_xr(bool p_use_xr);
|
||||
bool is_using_xr();
|
||||
#endif // XR_DISABLED
|
||||
#endif // _3D_DISABLED
|
||||
|
||||
Viewport();
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#include "core/templates/rb_set.h"
|
||||
#include "scene/gui/control.h"
|
||||
#include "scene/resources/image_texture.h"
|
||||
#include "scene/resources/mesh.h"
|
||||
|
||||
#ifndef NAVIGATION_2D_DISABLED
|
||||
#include "servers/navigation_2d/navigation_server_2d.h"
|
||||
|
|
|
@ -188,6 +188,14 @@ void CameraFeed::set_rgb_image(const Ref<Image> &p_rgb_img) {
|
|||
int new_width = p_rgb_img->get_width();
|
||||
int new_height = p_rgb_img->get_height();
|
||||
|
||||
// Emit `format_changed` signal if feed datatype or frame size is changed.
|
||||
// The signal is deferred to ensure:
|
||||
// - They are emitted on Godot's main thread.
|
||||
// - Both datatype and frame size are updated before the emission.
|
||||
if (datatype != CameraFeed::FEED_RGB || (base_width != new_width) || (base_height != new_height)) {
|
||||
call_deferred("emit_signal", format_changed_signal_name);
|
||||
}
|
||||
|
||||
if ((base_width != new_width) || (base_height != new_height)) {
|
||||
// We're assuming here that our camera image doesn't change around formats etc, allocate the whole lot...
|
||||
base_width = new_width;
|
||||
|
@ -195,10 +203,6 @@ void CameraFeed::set_rgb_image(const Ref<Image> &p_rgb_img) {
|
|||
|
||||
RID new_texture = RenderingServer::get_singleton()->texture_2d_create(p_rgb_img);
|
||||
RenderingServer::get_singleton()->texture_replace(texture[CameraServer::FEED_RGBA_IMAGE], new_texture);
|
||||
|
||||
// Defer `format_changed` signals to ensure they are emitted on Godot's main thread.
|
||||
// This also makes sure the datatype of the feed is updated before the emission.
|
||||
call_deferred("emit_signal", format_changed_signal_name);
|
||||
} else {
|
||||
RenderingServer::get_singleton()->texture_2d_update(texture[CameraServer::FEED_RGBA_IMAGE], p_rgb_img);
|
||||
}
|
||||
|
@ -216,6 +220,14 @@ void CameraFeed::set_ycbcr_image(const Ref<Image> &p_ycbcr_img) {
|
|||
int new_width = p_ycbcr_img->get_width();
|
||||
int new_height = p_ycbcr_img->get_height();
|
||||
|
||||
// Emit `format_changed` signal if feed datatype or frame size is changed.
|
||||
// The signal is deferred to ensure:
|
||||
// - They are emitted on Godot's main thread.
|
||||
// - Both datatype and frame size are updated before the emission.
|
||||
if (datatype != CameraFeed::FEED_YCBCR || (base_width != new_width) || (base_height != new_height)) {
|
||||
call_deferred("emit_signal", format_changed_signal_name);
|
||||
}
|
||||
|
||||
if ((base_width != new_width) || (base_height != new_height)) {
|
||||
// We're assuming here that our camera image doesn't change around formats etc, allocate the whole lot...
|
||||
base_width = new_width;
|
||||
|
@ -223,10 +235,6 @@ void CameraFeed::set_ycbcr_image(const Ref<Image> &p_ycbcr_img) {
|
|||
|
||||
RID new_texture = RenderingServer::get_singleton()->texture_2d_create(p_ycbcr_img);
|
||||
RenderingServer::get_singleton()->texture_replace(texture[CameraServer::FEED_RGBA_IMAGE], new_texture);
|
||||
|
||||
// Defer `format_changed` signals to ensure they are emitted on Godot's main thread.
|
||||
// This also makes sure the datatype of the feed is updated before the emission.
|
||||
call_deferred("emit_signal", format_changed_signal_name);
|
||||
} else {
|
||||
RenderingServer::get_singleton()->texture_2d_update(texture[CameraServer::FEED_RGBA_IMAGE], p_ycbcr_img);
|
||||
}
|
||||
|
@ -249,6 +257,14 @@ void CameraFeed::set_ycbcr_images(const Ref<Image> &p_y_img, const Ref<Image> &p
|
|||
int new_y_width = p_y_img->get_width();
|
||||
int new_y_height = p_y_img->get_height();
|
||||
|
||||
// Emit `format_changed` signal if feed datatype or frame size is changed.
|
||||
// The signal is deferred to ensure:
|
||||
// - They are emitted on Godot's main thread.
|
||||
// - Both datatype and frame size are updated before the emission.
|
||||
if (datatype != CameraFeed::FEED_YCBCR_SEP || (base_width != new_y_width) || (base_height != new_y_height)) {
|
||||
call_deferred("emit_signal", format_changed_signal_name);
|
||||
}
|
||||
|
||||
if ((base_width != new_y_width) || (base_height != new_y_height)) {
|
||||
// We're assuming here that our camera image doesn't change around formats etc, allocate the whole lot...
|
||||
base_width = new_y_width;
|
||||
|
@ -261,10 +277,6 @@ void CameraFeed::set_ycbcr_images(const Ref<Image> &p_y_img, const Ref<Image> &p
|
|||
RID new_texture = RenderingServer::get_singleton()->texture_2d_create(p_cbcr_img);
|
||||
RenderingServer::get_singleton()->texture_replace(texture[CameraServer::FEED_CBCR_IMAGE], new_texture);
|
||||
}
|
||||
|
||||
// Defer `format_changed` signals to ensure they are emitted on Godot's main thread.
|
||||
// This also makes sure the datatype of the feed is updated before the emission.
|
||||
call_deferred("emit_signal", format_changed_signal_name);
|
||||
} else {
|
||||
RenderingServer::get_singleton()->texture_2d_update(texture[CameraServer::FEED_Y_IMAGE], p_y_img);
|
||||
RenderingServer::get_singleton()->texture_2d_update(texture[CameraServer::FEED_CBCR_IMAGE], p_cbcr_img);
|
||||
|
@ -278,6 +290,14 @@ void CameraFeed::set_ycbcr_images(const Ref<Image> &p_y_img, const Ref<Image> &p
|
|||
}
|
||||
|
||||
void CameraFeed::set_external(int p_width, int p_height) {
|
||||
// Emit `format_changed` signal if feed datatype or frame size is changed.
|
||||
// The signal is deferred to ensure:
|
||||
// - They are emitted on Godot's main thread.
|
||||
// - Both datatype and frame size are updated before the emission.
|
||||
if (datatype != CameraFeed::FEED_EXTERNAL || (base_width != p_width) || (base_height != p_height)) {
|
||||
call_deferred("emit_signal", format_changed_signal_name);
|
||||
}
|
||||
|
||||
if ((base_width != p_width) || (base_height != p_height)) {
|
||||
// We're assuming here that our camera image doesn't change around formats etc, allocate the whole lot...
|
||||
base_width = p_width;
|
||||
|
|
|
@ -66,7 +66,7 @@ BokehDOF::BokehDOF(bool p_prefer_raster_effects) {
|
|||
|
||||
for (int i = 0; i < BOKEH_MAX; i++) {
|
||||
if (bokeh.compute_shader.is_variant_enabled(i)) {
|
||||
bokeh.compute_pipelines[i] = RD::get_singleton()->compute_pipeline_create(bokeh.compute_shader.version_get_shader(bokeh.shader_version, i));
|
||||
bokeh.compute_pipelines[i].create_compute_pipeline(bokeh.compute_shader.version_get_shader(bokeh.shader_version, i));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -77,6 +77,10 @@ BokehDOF::BokehDOF(bool p_prefer_raster_effects) {
|
|||
}
|
||||
|
||||
BokehDOF::~BokehDOF() {
|
||||
for (int i = 0; i < BOKEH_MAX; i++) {
|
||||
bokeh.compute_pipelines[i].free();
|
||||
}
|
||||
|
||||
if (prefer_raster_effects) {
|
||||
bokeh.raster_shader.version_free(bokeh.shader_version);
|
||||
} else {
|
||||
|
@ -154,7 +158,7 @@ void BokehDOF::bokeh_dof_compute(const BokehBuffers &p_buffers, RID p_camera_att
|
|||
RID shader = bokeh.compute_shader.version_get_shader(bokeh.shader_version, BOKEH_GEN_BLUR_SIZE);
|
||||
ERR_FAIL_COND(shader.is_null());
|
||||
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, bokeh.compute_pipelines[BOKEH_GEN_BLUR_SIZE]);
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, bokeh.compute_pipelines[BOKEH_GEN_BLUR_SIZE].get_rid());
|
||||
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_base_image), 0);
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_depth_texture), 1);
|
||||
|
@ -173,7 +177,7 @@ void BokehDOF::bokeh_dof_compute(const BokehBuffers &p_buffers, RID p_camera_att
|
|||
shader = bokeh.compute_shader.version_get_shader(bokeh.shader_version, mode);
|
||||
ERR_FAIL_COND(shader.is_null());
|
||||
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, bokeh.compute_pipelines[mode]);
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, bokeh.compute_pipelines[mode].get_rid());
|
||||
|
||||
static const int quality_samples[4] = { 6, 12, 12, 24 };
|
||||
|
||||
|
@ -223,7 +227,7 @@ void BokehDOF::bokeh_dof_compute(const BokehBuffers &p_buffers, RID p_camera_att
|
|||
shader = bokeh.compute_shader.version_get_shader(bokeh.shader_version, BOKEH_COMPOSITE);
|
||||
ERR_FAIL_COND(shader.is_null());
|
||||
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, bokeh.compute_pipelines[BOKEH_COMPOSITE]);
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, bokeh.compute_pipelines[BOKEH_COMPOSITE].get_rid());
|
||||
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_base_image), 0);
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_half_texture1), 1);
|
||||
|
@ -244,7 +248,7 @@ void BokehDOF::bokeh_dof_compute(const BokehBuffers &p_buffers, RID p_camera_att
|
|||
ERR_FAIL_COND(shader.is_null());
|
||||
|
||||
//second pass
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, bokeh.compute_pipelines[BOKEH_GEN_BOKEH_CIRCULAR]);
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, bokeh.compute_pipelines[BOKEH_GEN_BOKEH_CIRCULAR].get_rid());
|
||||
|
||||
static const float quality_scale[4] = { 8.0, 4.0, 1.0, 0.5 };
|
||||
|
||||
|
@ -272,7 +276,7 @@ void BokehDOF::bokeh_dof_compute(const BokehBuffers &p_buffers, RID p_camera_att
|
|||
shader = bokeh.compute_shader.version_get_shader(bokeh.shader_version, BOKEH_COMPOSITE);
|
||||
ERR_FAIL_COND(shader.is_null());
|
||||
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, bokeh.compute_pipelines[BOKEH_COMPOSITE]);
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, bokeh.compute_pipelines[BOKEH_COMPOSITE].get_rid());
|
||||
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_base_image), 0);
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_half_texture0), 1);
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "servers/rendering/renderer_rd/pipeline_cache_rd.h"
|
||||
#include "servers/rendering/renderer_rd/pipeline_deferred_rd.h"
|
||||
#include "servers/rendering/renderer_rd/shaders/effects/bokeh_dof.glsl.gen.h"
|
||||
#include "servers/rendering/renderer_rd/shaders/effects/bokeh_dof_raster.glsl.gen.h"
|
||||
|
||||
|
@ -86,7 +87,7 @@ private:
|
|||
BokehDofShaderRD compute_shader;
|
||||
BokehDofRasterShaderRD raster_shader;
|
||||
RID shader_version;
|
||||
RID compute_pipelines[BOKEH_MAX];
|
||||
PipelineDeferredRD compute_pipelines[BOKEH_MAX];
|
||||
PipelineCacheRD raster_pipelines[BOKEH_MAX];
|
||||
} bokeh;
|
||||
|
||||
|
|
|
@ -96,7 +96,7 @@ CopyEffects::CopyEffects(bool p_prefer_raster_effects) {
|
|||
|
||||
for (int i = 0; i < COPY_MODE_MAX; i++) {
|
||||
if (copy.shader.is_variant_enabled(i)) {
|
||||
copy.pipelines[i] = RD::get_singleton()->compute_pipeline_create(copy.shader.version_get_shader(copy.shader_version, i));
|
||||
copy.pipelines[i].create_compute_pipeline(copy.shader.version_get_shader(copy.shader_version, i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -162,7 +162,7 @@ CopyEffects::CopyEffects(bool p_prefer_raster_effects) {
|
|||
|
||||
cubemap_downsampler.shader_version = cubemap_downsampler.compute_shader.version_create();
|
||||
|
||||
cubemap_downsampler.compute_pipeline = RD::get_singleton()->compute_pipeline_create(cubemap_downsampler.compute_shader.version_get_shader(cubemap_downsampler.shader_version, 0));
|
||||
cubemap_downsampler.compute_pipeline.create_compute_pipeline(cubemap_downsampler.compute_shader.version_get_shader(cubemap_downsampler.shader_version, 0));
|
||||
cubemap_downsampler.raster_pipeline.clear();
|
||||
}
|
||||
}
|
||||
|
@ -216,7 +216,7 @@ CopyEffects::CopyEffects(bool p_prefer_raster_effects) {
|
|||
filter.shader_version = filter.compute_shader.version_create();
|
||||
|
||||
for (int i = 0; i < FILTER_MODE_MAX; i++) {
|
||||
filter.compute_pipelines[i] = RD::get_singleton()->compute_pipeline_create(filter.compute_shader.version_get_shader(filter.shader_version, i));
|
||||
filter.compute_pipelines[i].create_compute_pipeline(filter.compute_shader.version_get_shader(filter.shader_version, i));
|
||||
filter.raster_pipelines[i].clear();
|
||||
}
|
||||
|
||||
|
@ -249,7 +249,7 @@ CopyEffects::CopyEffects(bool p_prefer_raster_effects) {
|
|||
|
||||
roughness.shader_version = roughness.compute_shader.version_create();
|
||||
|
||||
roughness.compute_pipeline = RD::get_singleton()->compute_pipeline_create(roughness.compute_shader.version_get_shader(roughness.shader_version, 0));
|
||||
roughness.compute_pipeline.create_compute_pipeline(roughness.compute_shader.version_get_shader(roughness.shader_version, 0));
|
||||
roughness.raster_pipeline.clear();
|
||||
}
|
||||
}
|
||||
|
@ -306,6 +306,17 @@ CopyEffects::CopyEffects(bool p_prefer_raster_effects) {
|
|||
}
|
||||
|
||||
CopyEffects::~CopyEffects() {
|
||||
for (int i = 0; i < COPY_MODE_MAX; i++) {
|
||||
copy.pipelines[i].free();
|
||||
}
|
||||
|
||||
for (int i = 0; i < FILTER_MODE_MAX; i++) {
|
||||
filter.compute_pipelines[i].free();
|
||||
}
|
||||
|
||||
cubemap_downsampler.compute_pipeline.free();
|
||||
roughness.compute_pipeline.free();
|
||||
|
||||
if (prefer_raster_effects) {
|
||||
blur_raster.shader.version_free(blur_raster.shader_version);
|
||||
cubemap_downsampler.raster_shader.version_free(cubemap_downsampler.shader_version);
|
||||
|
@ -377,7 +388,7 @@ void CopyEffects::copy_to_rect(RID p_source_rd_texture, RID p_dest_texture, cons
|
|||
ERR_FAIL_COND(shader.is_null());
|
||||
|
||||
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[mode]);
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[mode].get_rid());
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0);
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 3, u_dest_texture), 3);
|
||||
RD::get_singleton()->compute_list_set_push_constant(compute_list, ©.push_constant, sizeof(CopyPushConstant));
|
||||
|
@ -412,7 +423,7 @@ void CopyEffects::copy_cubemap_to_panorama(RID p_source_cube, RID p_dest_panoram
|
|||
ERR_FAIL_COND(shader.is_null());
|
||||
|
||||
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[mode]);
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[mode].get_rid());
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_source_cube), 0);
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 3, u_dest_panorama), 3);
|
||||
RD::get_singleton()->compute_list_set_push_constant(compute_list, ©.push_constant, sizeof(CopyPushConstant));
|
||||
|
@ -449,7 +460,7 @@ void CopyEffects::copy_depth_to_rect(RID p_source_rd_texture, RID p_dest_texture
|
|||
ERR_FAIL_COND(shader.is_null());
|
||||
|
||||
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[mode]);
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[mode].get_rid());
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0);
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 3, u_dest_texture), 3);
|
||||
RD::get_singleton()->compute_list_set_push_constant(compute_list, ©.push_constant, sizeof(CopyPushConstant));
|
||||
|
@ -488,7 +499,7 @@ void CopyEffects::copy_depth_to_rect_and_linearize(RID p_source_rd_texture, RID
|
|||
ERR_FAIL_COND(shader.is_null());
|
||||
|
||||
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[mode]);
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[mode].get_rid());
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0);
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 3, u_dest_texture), 3);
|
||||
RD::get_singleton()->compute_list_set_push_constant(compute_list, ©.push_constant, sizeof(CopyPushConstant));
|
||||
|
@ -695,7 +706,7 @@ void CopyEffects::gaussian_blur(RID p_source_rd_texture, RID p_texture, const Re
|
|||
ERR_FAIL_COND(shader.is_null());
|
||||
|
||||
RD::DrawListID compute_list = RD::get_singleton()->compute_list_begin();
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[mode]);
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[mode].get_rid());
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0);
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 3, u_texture), 3);
|
||||
|
||||
|
@ -777,7 +788,7 @@ void CopyEffects::gaussian_glow(RID p_source_rd_texture, RID p_back_texture, con
|
|||
ERR_FAIL_COND(shader.is_null());
|
||||
|
||||
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[copy_mode]);
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[copy_mode].get_rid());
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0);
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 3, u_back_texture), 3);
|
||||
if (p_auto_exposure.is_valid() && p_first_pass) {
|
||||
|
@ -890,7 +901,7 @@ void CopyEffects::make_mipmap(RID p_source_rd_texture, RID p_dest_texture, const
|
|||
ERR_FAIL_COND(shader.is_null());
|
||||
|
||||
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[mode]);
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[mode].get_rid());
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0);
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 3, u_dest_texture), 3);
|
||||
RD::get_singleton()->compute_list_set_push_constant(compute_list, ©.push_constant, sizeof(CopyPushConstant));
|
||||
|
@ -959,7 +970,7 @@ void CopyEffects::set_color(RID p_dest_texture, const Color &p_color, const Rect
|
|||
ERR_FAIL_COND(shader.is_null());
|
||||
|
||||
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[mode]);
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[mode].get_rid());
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 3, u_dest_texture), 3);
|
||||
RD::get_singleton()->compute_list_set_push_constant(compute_list, ©.push_constant, sizeof(CopyPushConstant));
|
||||
RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_region.size.width, p_region.size.height, 1);
|
||||
|
@ -1056,7 +1067,7 @@ void CopyEffects::cubemap_downsample(RID p_source_cubemap, RID p_dest_cubemap, c
|
|||
ERR_FAIL_COND(shader.is_null());
|
||||
|
||||
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, cubemap_downsampler.compute_pipeline);
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, cubemap_downsampler.compute_pipeline.get_rid());
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_source_cubemap), 0);
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_dest_cubemap), 1);
|
||||
|
||||
|
@ -1133,7 +1144,7 @@ void CopyEffects::cubemap_filter(RID p_source_cubemap, Vector<RID> p_dest_cubema
|
|||
ERR_FAIL_COND(shader.is_null());
|
||||
|
||||
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, filter.compute_pipelines[mode]);
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, filter.compute_pipelines[mode].get_rid());
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_source_cubemap), 0);
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, filter.uniform_set, 1);
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, filter.image_uniform_set, 2);
|
||||
|
@ -1207,7 +1218,7 @@ void CopyEffects::cubemap_roughness(RID p_source_rd_texture, RID p_dest_texture,
|
|||
ERR_FAIL_COND(shader.is_null());
|
||||
|
||||
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, roughness.compute_pipeline);
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, roughness.compute_pipeline.get_rid());
|
||||
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0);
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_dest_texture), 1);
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "servers/rendering/renderer_rd/pipeline_cache_rd.h"
|
||||
#include "servers/rendering/renderer_rd/pipeline_deferred_rd.h"
|
||||
#include "servers/rendering/renderer_rd/shaders/effects/blur_raster.glsl.gen.h"
|
||||
#include "servers/rendering/renderer_rd/shaders/effects/copy.glsl.gen.h"
|
||||
#include "servers/rendering/renderer_rd/shaders/effects/copy_to_fb.glsl.gen.h"
|
||||
|
@ -161,7 +162,7 @@ private:
|
|||
CopyPushConstant push_constant;
|
||||
CopyShaderRD shader;
|
||||
RID shader_version;
|
||||
RID pipelines[COPY_MODE_MAX];
|
||||
PipelineDeferredRD pipelines[COPY_MODE_MAX];
|
||||
|
||||
} copy;
|
||||
|
||||
|
@ -237,7 +238,7 @@ private:
|
|||
CubemapDownsamplerShaderRD compute_shader;
|
||||
CubemapDownsamplerRasterShaderRD raster_shader;
|
||||
RID shader_version;
|
||||
RID compute_pipeline;
|
||||
PipelineDeferredRD compute_pipeline;
|
||||
PipelineCacheRD raster_pipeline;
|
||||
} cubemap_downsampler;
|
||||
|
||||
|
@ -259,7 +260,7 @@ private:
|
|||
CubemapFilterShaderRD compute_shader;
|
||||
CubemapFilterRasterShaderRD raster_shader;
|
||||
RID shader_version;
|
||||
RID compute_pipelines[FILTER_MODE_MAX];
|
||||
PipelineDeferredRD compute_pipelines[FILTER_MODE_MAX];
|
||||
PipelineCacheRD raster_pipelines[FILTER_MODE_MAX];
|
||||
|
||||
RID uniform_set;
|
||||
|
@ -283,7 +284,7 @@ private:
|
|||
CubemapRoughnessShaderRD compute_shader;
|
||||
CubemapRoughnessRasterShaderRD raster_shader;
|
||||
RID shader_version;
|
||||
RID compute_pipeline;
|
||||
PipelineDeferredRD compute_pipeline;
|
||||
PipelineCacheRD raster_pipeline;
|
||||
} roughness;
|
||||
|
||||
|
|
|
@ -48,10 +48,11 @@ FSR::FSR() {
|
|||
}
|
||||
|
||||
shader_version = fsr_shader.version_create();
|
||||
pipeline = RD::get_singleton()->compute_pipeline_create(fsr_shader.version_get_shader(shader_version, variant));
|
||||
pipeline.create_compute_pipeline(fsr_shader.version_get_shader(shader_version, variant));
|
||||
}
|
||||
|
||||
FSR::~FSR() {
|
||||
pipeline.free();
|
||||
fsr_shader.version_free(shader_version);
|
||||
}
|
||||
|
||||
|
@ -82,7 +83,7 @@ void FSR::process(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_source_rd_te
|
|||
int dispatch_y = (target_size.y + 15) / 16;
|
||||
|
||||
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, pipeline);
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, pipeline.get_rid());
|
||||
|
||||
push_constant.resolution_width = internal_size.width;
|
||||
push_constant.resolution_height = internal_size.height;
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include "spatial_upscaler.h"
|
||||
|
||||
#include "../storage_rd/render_scene_buffers_rd.h"
|
||||
#include "servers/rendering/renderer_rd/pipeline_deferred_rd.h"
|
||||
#include "servers/rendering/renderer_rd/shaders/effects/fsr_upscale.glsl.gen.h"
|
||||
|
||||
namespace RendererRD {
|
||||
|
@ -69,7 +70,7 @@ private:
|
|||
|
||||
FsrUpscaleShaderRD fsr_shader;
|
||||
RID shader_version;
|
||||
RID pipeline;
|
||||
PipelineDeferredRD pipeline;
|
||||
};
|
||||
|
||||
} // namespace RendererRD
|
||||
|
|
|
@ -66,7 +66,7 @@ SSEffects::SSEffects() {
|
|||
ss_effects.downsample_shader_version = ss_effects.downsample_shader.version_create();
|
||||
|
||||
for (int i = 0; i < SS_EFFECTS_MAX; i++) {
|
||||
ss_effects.pipelines[i] = RD::get_singleton()->compute_pipeline_create(ss_effects.downsample_shader.version_get_shader(ss_effects.downsample_shader_version, i));
|
||||
ss_effects.pipelines[i].create_compute_pipeline(ss_effects.downsample_shader.version_get_shader(ss_effects.downsample_shader_version, i));
|
||||
}
|
||||
|
||||
ss_effects.gather_constants_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(SSEffectsGatherConstants));
|
||||
|
@ -112,7 +112,7 @@ SSEffects::SSEffects() {
|
|||
ssil.gather_shader_version = ssil.gather_shader.version_create();
|
||||
|
||||
for (int i = SSIL_GATHER; i <= SSIL_GATHER_ADAPTIVE; i++) {
|
||||
ssil.pipelines[i] = RD::get_singleton()->compute_pipeline_create(ssil.gather_shader.version_get_shader(ssil.gather_shader_version, i));
|
||||
ssil.pipelines[i].create_compute_pipeline(ssil.gather_shader.version_get_shader(ssil.gather_shader_version, i));
|
||||
}
|
||||
ssil.projection_uniform_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(SSILProjectionUniforms));
|
||||
}
|
||||
|
@ -128,7 +128,7 @@ SSEffects::SSEffects() {
|
|||
ssil.importance_map_shader_version = ssil.importance_map_shader.version_create();
|
||||
|
||||
for (int i = SSIL_GENERATE_IMPORTANCE_MAP; i <= SSIL_PROCESS_IMPORTANCE_MAPB; i++) {
|
||||
ssil.pipelines[i] = RD::get_singleton()->compute_pipeline_create(ssil.importance_map_shader.version_get_shader(ssil.importance_map_shader_version, i - SSIL_GENERATE_IMPORTANCE_MAP));
|
||||
ssil.pipelines[i].create_compute_pipeline(ssil.importance_map_shader.version_get_shader(ssil.importance_map_shader_version, i - SSIL_GENERATE_IMPORTANCE_MAP));
|
||||
}
|
||||
ssil.importance_map_load_counter = RD::get_singleton()->storage_buffer_create(sizeof(uint32_t));
|
||||
int zero[1] = { 0 };
|
||||
|
@ -157,7 +157,7 @@ SSEffects::SSEffects() {
|
|||
|
||||
ssil.blur_shader_version = ssil.blur_shader.version_create();
|
||||
for (int i = SSIL_BLUR_PASS; i <= SSIL_BLUR_PASS_WIDE; i++) {
|
||||
ssil.pipelines[i] = RD::get_singleton()->compute_pipeline_create(ssil.blur_shader.version_get_shader(ssil.blur_shader_version, i - SSIL_BLUR_PASS));
|
||||
ssil.pipelines[i].create_compute_pipeline(ssil.blur_shader.version_get_shader(ssil.blur_shader_version, i - SSIL_BLUR_PASS));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -171,7 +171,7 @@ SSEffects::SSEffects() {
|
|||
|
||||
ssil.interleave_shader_version = ssil.interleave_shader.version_create();
|
||||
for (int i = SSIL_INTERLEAVE; i <= SSIL_INTERLEAVE_HALF; i++) {
|
||||
ssil.pipelines[i] = RD::get_singleton()->compute_pipeline_create(ssil.interleave_shader.version_get_shader(ssil.interleave_shader_version, i - SSIL_INTERLEAVE));
|
||||
ssil.pipelines[i].create_compute_pipeline(ssil.interleave_shader.version_get_shader(ssil.interleave_shader_version, i - SSIL_INTERLEAVE));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -201,7 +201,7 @@ SSEffects::SSEffects() {
|
|||
ssao.gather_shader_version = ssao.gather_shader.version_create();
|
||||
|
||||
for (int i = 0; i <= SSAO_GATHER_ADAPTIVE; i++) {
|
||||
ssao.pipelines[pipeline] = RD::get_singleton()->compute_pipeline_create(ssao.gather_shader.version_get_shader(ssao.gather_shader_version, i));
|
||||
ssao.pipelines[pipeline].create_compute_pipeline(ssao.gather_shader.version_get_shader(ssao.gather_shader_version, i));
|
||||
pipeline++;
|
||||
}
|
||||
}
|
||||
|
@ -217,7 +217,7 @@ SSEffects::SSEffects() {
|
|||
ssao.importance_map_shader_version = ssao.importance_map_shader.version_create();
|
||||
|
||||
for (int i = SSAO_GENERATE_IMPORTANCE_MAP; i <= SSAO_PROCESS_IMPORTANCE_MAPB; i++) {
|
||||
ssao.pipelines[pipeline] = RD::get_singleton()->compute_pipeline_create(ssao.importance_map_shader.version_get_shader(ssao.importance_map_shader_version, i - SSAO_GENERATE_IMPORTANCE_MAP));
|
||||
ssao.pipelines[pipeline].create_compute_pipeline(ssao.importance_map_shader.version_get_shader(ssao.importance_map_shader_version, i - SSAO_GENERATE_IMPORTANCE_MAP));
|
||||
|
||||
pipeline++;
|
||||
}
|
||||
|
@ -250,7 +250,7 @@ SSEffects::SSEffects() {
|
|||
ssao.blur_shader_version = ssao.blur_shader.version_create();
|
||||
|
||||
for (int i = SSAO_BLUR_PASS; i <= SSAO_BLUR_PASS_WIDE; i++) {
|
||||
ssao.pipelines[pipeline] = RD::get_singleton()->compute_pipeline_create(ssao.blur_shader.version_get_shader(ssao.blur_shader_version, i - SSAO_BLUR_PASS));
|
||||
ssao.pipelines[pipeline].create_compute_pipeline(ssao.blur_shader.version_get_shader(ssao.blur_shader_version, i - SSAO_BLUR_PASS));
|
||||
|
||||
pipeline++;
|
||||
}
|
||||
|
@ -266,8 +266,7 @@ SSEffects::SSEffects() {
|
|||
|
||||
ssao.interleave_shader_version = ssao.interleave_shader.version_create();
|
||||
for (int i = SSAO_INTERLEAVE; i <= SSAO_INTERLEAVE_HALF; i++) {
|
||||
ssao.pipelines[pipeline] = RD::get_singleton()->compute_pipeline_create(ssao.interleave_shader.version_get_shader(ssao.interleave_shader_version, i - SSAO_INTERLEAVE));
|
||||
RD::get_singleton()->set_resource_name(ssao.pipelines[pipeline], "Interleave Pipeline " + itos(i));
|
||||
ssao.pipelines[pipeline].create_compute_pipeline(ssao.interleave_shader.version_get_shader(ssao.interleave_shader_version, i - SSAO_INTERLEAVE));
|
||||
pipeline++;
|
||||
}
|
||||
}
|
||||
|
@ -300,7 +299,7 @@ SSEffects::SSEffects() {
|
|||
|
||||
for (int v = 0; v < SSR_VARIATIONS; v++) {
|
||||
specialization_constants.ptrw()[0].bool_value = (v & SSR_MULTIVIEW) ? true : false;
|
||||
ssr_scale.pipelines[v] = RD::get_singleton()->compute_pipeline_create(ssr_scale.shader.version_get_shader(ssr_scale.shader_version, 0), specialization_constants);
|
||||
ssr_scale.pipelines[v].create_compute_pipeline(ssr_scale.shader.version_get_shader(ssr_scale.shader_version, 0), specialization_constants);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -315,7 +314,7 @@ SSEffects::SSEffects() {
|
|||
for (int v = 0; v < SSR_VARIATIONS; v++) {
|
||||
specialization_constants.ptrw()[0].bool_value = (v & SSR_MULTIVIEW) ? true : false;
|
||||
for (int i = 0; i < SCREEN_SPACE_REFLECTION_MAX; i++) {
|
||||
ssr.pipelines[v][i] = RD::get_singleton()->compute_pipeline_create(ssr.shader.version_get_shader(ssr.shader_version, i), specialization_constants);
|
||||
ssr.pipelines[v][i].create_compute_pipeline(ssr.shader.version_get_shader(ssr.shader_version, i), specialization_constants);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -331,7 +330,7 @@ SSEffects::SSEffects() {
|
|||
for (int v = 0; v < SSR_VARIATIONS; v++) {
|
||||
specialization_constants.ptrw()[0].bool_value = (v & SSR_MULTIVIEW) ? true : false;
|
||||
for (int i = 0; i < SCREEN_SPACE_REFLECTION_FILTER_MAX; i++) {
|
||||
ssr_filter.pipelines[v][i] = RD::get_singleton()->compute_pipeline_create(ssr_filter.shader.version_get_shader(ssr_filter.shader_version, i), specialization_constants);
|
||||
ssr_filter.pipelines[v][i].create_compute_pipeline(ssr_filter.shader.version_get_shader(ssr_filter.shader_version, i), specialization_constants);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -352,8 +351,8 @@ SSEffects::SSEffects() {
|
|||
|
||||
sss.shader_version = sss.shader.version_create();
|
||||
|
||||
for (int i = 0; i < sss_modes.size(); i++) {
|
||||
sss.pipelines[i] = RD::get_singleton()->compute_pipeline_create(sss.shader.version_get_shader(sss.shader_version, i));
|
||||
for (int i = 0; i < SUBSURFACE_SCATTERING_MODE_MAX; i++) {
|
||||
sss.pipelines[i].create_compute_pipeline(sss.shader.version_get_shader(sss.shader_version, i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -361,6 +360,15 @@ SSEffects::SSEffects() {
|
|||
SSEffects::~SSEffects() {
|
||||
{
|
||||
// Cleanup SS Reflections
|
||||
for (int v = 0; v < SSR_VARIATIONS; v++) {
|
||||
for (int i = 0; i < SCREEN_SPACE_REFLECTION_FILTER_MAX; i++) {
|
||||
ssr.pipelines[v][i].free();
|
||||
ssr_filter.pipelines[v][i].free();
|
||||
}
|
||||
|
||||
ssr_scale.pipelines[v].free();
|
||||
}
|
||||
|
||||
ssr.shader.version_free(ssr.shader_version);
|
||||
ssr_filter.shader.version_free(ssr_filter.shader_version);
|
||||
ssr_scale.shader.version_free(ssr_scale.shader_version);
|
||||
|
@ -372,6 +380,10 @@ SSEffects::~SSEffects() {
|
|||
|
||||
{
|
||||
// Cleanup SS downsampler
|
||||
for (int i = 0; i < SS_EFFECTS_MAX; i++) {
|
||||
ss_effects.pipelines[i].free();
|
||||
}
|
||||
|
||||
ss_effects.downsample_shader.version_free(ss_effects.downsample_shader_version);
|
||||
|
||||
RD::get_singleton()->free_rid(ss_effects.mirror_sampler);
|
||||
|
@ -380,6 +392,10 @@ SSEffects::~SSEffects() {
|
|||
|
||||
{
|
||||
// Cleanup SSIL
|
||||
for (int i = 0; i < SSIL_MAX; i++) {
|
||||
ssil.pipelines[i].free();
|
||||
}
|
||||
|
||||
ssil.blur_shader.version_free(ssil.blur_shader_version);
|
||||
ssil.gather_shader.version_free(ssil.gather_shader_version);
|
||||
ssil.interleave_shader.version_free(ssil.interleave_shader_version);
|
||||
|
@ -391,6 +407,10 @@ SSEffects::~SSEffects() {
|
|||
|
||||
{
|
||||
// Cleanup SSAO
|
||||
for (int i = 0; i < SSAO_MAX; i++) {
|
||||
ssao.pipelines[i].free();
|
||||
}
|
||||
|
||||
ssao.blur_shader.version_free(ssao.blur_shader_version);
|
||||
ssao.gather_shader.version_free(ssao.gather_shader_version);
|
||||
ssao.interleave_shader.version_free(ssao.interleave_shader_version);
|
||||
|
@ -401,6 +421,10 @@ SSEffects::~SSEffects() {
|
|||
|
||||
{
|
||||
// Cleanup Subsurface scattering
|
||||
for (int i = 0; i < SUBSURFACE_SCATTERING_MODE_MAX; i++) {
|
||||
sss.pipelines[i].free();
|
||||
}
|
||||
|
||||
sss.shader.version_free(sss.shader_version);
|
||||
}
|
||||
|
||||
|
@ -512,7 +536,7 @@ void SSEffects::downsample_depth(Ref<RenderSceneBuffersRD> p_render_buffers, uin
|
|||
RD::Uniform u_depth_buffer(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, depth_texture }));
|
||||
RD::Uniform u_depth_mipmap(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ depth_mipmap }));
|
||||
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ss_effects.pipelines[downsample_mode]);
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ss_effects.pipelines[downsample_mode].get_rid());
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_depth_buffer), 0);
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_depth_mipmap), 1);
|
||||
if (use_mips) {
|
||||
|
@ -791,7 +815,7 @@ void SSEffects::screen_space_indirect_lighting(Ref<RenderSceneBuffersRD> p_rende
|
|||
ssil.importance_map_push_constant.intensity = p_settings.intensity * Math::PI;
|
||||
|
||||
//base pass
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[SSIL_GATHER_BASE]);
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[SSIL_GATHER_BASE].get_rid());
|
||||
gather_ssil(compute_list, deinterleaved_pong_slices, edges_slices, p_settings, true, gather_uniform_set, importance_map_uniform_set, projection_uniform_set);
|
||||
|
||||
//generate importance map
|
||||
|
@ -799,7 +823,7 @@ void SSEffects::screen_space_indirect_lighting(Ref<RenderSceneBuffersRD> p_rende
|
|||
RD::Uniform u_ssil_pong_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, deinterleaved_pong }));
|
||||
RD::Uniform u_importance_map(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ importance_map }));
|
||||
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[SSIL_GENERATE_IMPORTANCE_MAP]);
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[SSIL_GENERATE_IMPORTANCE_MAP].get_rid());
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(gen_imp_shader, 0, u_ssil_pong_with_sampler), 0);
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(gen_imp_shader, 1, u_importance_map), 1);
|
||||
RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssil.importance_map_push_constant, sizeof(SSILImportanceMapPushConstant));
|
||||
|
@ -811,7 +835,7 @@ void SSEffects::screen_space_indirect_lighting(Ref<RenderSceneBuffersRD> p_rende
|
|||
RD::Uniform u_importance_map_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, importance_map }));
|
||||
RD::Uniform u_importance_map_pong(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ importance_pong }));
|
||||
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[SSIL_PROCESS_IMPORTANCE_MAPA]);
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[SSIL_PROCESS_IMPORTANCE_MAPA].get_rid());
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(proc_imp_shader_a, 0, u_importance_map_with_sampler), 0);
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(proc_imp_shader_a, 1, u_importance_map_pong), 1);
|
||||
RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssil.importance_map_push_constant, sizeof(SSILImportanceMapPushConstant));
|
||||
|
@ -822,7 +846,7 @@ void SSEffects::screen_space_indirect_lighting(Ref<RenderSceneBuffersRD> p_rende
|
|||
RID proc_imp_shader_b = ssil.importance_map_shader.version_get_shader(ssil.importance_map_shader_version, 2);
|
||||
RD::Uniform u_importance_map_pong_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, importance_pong }));
|
||||
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[SSIL_PROCESS_IMPORTANCE_MAPB]);
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[SSIL_PROCESS_IMPORTANCE_MAPB].get_rid());
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(proc_imp_shader_b, 0, u_importance_map_pong_with_sampler), 0);
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(proc_imp_shader_b, 1, u_importance_map), 1);
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, ssil.counter_uniform_set, 2);
|
||||
|
@ -832,9 +856,9 @@ void SSEffects::screen_space_indirect_lighting(Ref<RenderSceneBuffersRD> p_rende
|
|||
|
||||
RD::get_singleton()->draw_command_end_label(); // Importance Map
|
||||
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[SSIL_GATHER_ADAPTIVE]);
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[SSIL_GATHER_ADAPTIVE].get_rid());
|
||||
} else {
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[SSIL_GATHER]);
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[SSIL_GATHER].get_rid());
|
||||
}
|
||||
|
||||
gather_ssil(compute_list, deinterleaved_slices, edges_slices, p_settings, false, gather_uniform_set, importance_map_uniform_set, projection_uniform_set);
|
||||
|
@ -867,7 +891,7 @@ void SSEffects::screen_space_indirect_lighting(Ref<RenderSceneBuffersRD> p_rende
|
|||
continue;
|
||||
}
|
||||
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[blur_pipeline]);
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[blur_pipeline].get_rid());
|
||||
if (pass % 2 == 0) {
|
||||
if (ssil_quality == RS::ENV_SSIL_QUALITY_VERY_LOW) {
|
||||
RD::Uniform u_ssil_slice(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, deinterleaved_slices[i] }));
|
||||
|
@ -926,7 +950,7 @@ void SSEffects::screen_space_indirect_lighting(Ref<RenderSceneBuffersRD> p_rende
|
|||
|
||||
shader = ssil.interleave_shader.version_get_shader(ssil.interleave_shader_version, 0);
|
||||
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[interleave_pipeline]);
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[interleave_pipeline].get_rid());
|
||||
|
||||
RID final = p_render_buffers->get_texture_slice(RB_SCOPE_SSIL, RB_FINAL, p_view, 0);
|
||||
RD::Uniform u_destination(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ final }));
|
||||
|
@ -1175,12 +1199,12 @@ void SSEffects::generate_ssao(Ref<RenderSceneBuffersRD> p_render_buffers, SSAORe
|
|||
ssao.importance_map_push_constant.power = p_settings.power;
|
||||
|
||||
//base pass
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_GATHER_BASE]);
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_GATHER_BASE].get_rid());
|
||||
gather_ssao(compute_list, ao_pong_slices, p_settings, true, gather_uniform_set, RID());
|
||||
|
||||
//generate importance map
|
||||
RID gen_imp_shader = ssao.importance_map_shader.version_get_shader(ssao.importance_map_shader_version, 0);
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_GENERATE_IMPORTANCE_MAP]);
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_GENERATE_IMPORTANCE_MAP].get_rid());
|
||||
|
||||
RD::Uniform u_ao_pong_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, ao_pong }));
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(gen_imp_shader, 0, u_ao_pong_with_sampler), 0);
|
||||
|
@ -1194,7 +1218,7 @@ void SSEffects::generate_ssao(Ref<RenderSceneBuffersRD> p_render_buffers, SSAORe
|
|||
|
||||
//process importance map A
|
||||
RID proc_imp_shader_a = ssao.importance_map_shader.version_get_shader(ssao.importance_map_shader_version, 1);
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_PROCESS_IMPORTANCE_MAPA]);
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_PROCESS_IMPORTANCE_MAPA].get_rid());
|
||||
|
||||
RD::Uniform u_importance_map_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, importance_map }));
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(proc_imp_shader_a, 0, u_importance_map_with_sampler), 0);
|
||||
|
@ -1208,7 +1232,7 @@ void SSEffects::generate_ssao(Ref<RenderSceneBuffersRD> p_render_buffers, SSAORe
|
|||
|
||||
//process Importance Map B
|
||||
RID proc_imp_shader_b = ssao.importance_map_shader.version_get_shader(ssao.importance_map_shader_version, 2);
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_PROCESS_IMPORTANCE_MAPB]);
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_PROCESS_IMPORTANCE_MAPB].get_rid());
|
||||
|
||||
RD::Uniform u_importance_map_pong_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, importance_pong }));
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(proc_imp_shader_b, 0, u_importance_map_pong_with_sampler), 0);
|
||||
|
@ -1219,10 +1243,10 @@ void SSEffects::generate_ssao(Ref<RenderSceneBuffersRD> p_render_buffers, SSAORe
|
|||
RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_ssao_buffers.half_buffer_width, p_ssao_buffers.half_buffer_height, 1);
|
||||
RD::get_singleton()->compute_list_add_barrier(compute_list);
|
||||
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_GATHER_ADAPTIVE]);
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_GATHER_ADAPTIVE].get_rid());
|
||||
RD::get_singleton()->draw_command_end_label(); // Importance Map
|
||||
} else {
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_GATHER]);
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_GATHER].get_rid());
|
||||
}
|
||||
|
||||
gather_ssao(compute_list, ao_deinterleaved_slices, p_settings, false, gather_uniform_set, importance_map_uniform_set);
|
||||
|
@ -1258,7 +1282,7 @@ void SSEffects::generate_ssao(Ref<RenderSceneBuffersRD> p_render_buffers, SSAORe
|
|||
}
|
||||
|
||||
RID blur_shader = ssao.blur_shader.version_get_shader(ssao.blur_shader_version, blur_pipeline - SSAO_BLUR_PASS);
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[blur_pipeline]);
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[blur_pipeline].get_rid());
|
||||
if (pass % 2 == 0) {
|
||||
if (ssao_quality == RS::ENV_SSAO_QUALITY_VERY_LOW) {
|
||||
RD::Uniform u_ao_slices_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, ao_deinterleaved_slices[i] }));
|
||||
|
@ -1312,7 +1336,7 @@ void SSEffects::generate_ssao(Ref<RenderSceneBuffersRD> p_render_buffers, SSAORe
|
|||
}
|
||||
|
||||
RID interleave_shader = ssao.interleave_shader.version_get_shader(ssao.interleave_shader_version, interleave_pipeline - SSAO_INTERLEAVE);
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[interleave_pipeline]);
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[interleave_pipeline].get_rid());
|
||||
|
||||
RD::Uniform u_upscale_buffer(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ ao_final }));
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(interleave_shader, 0, u_upscale_buffer), 0);
|
||||
|
@ -1439,7 +1463,7 @@ void SSEffects::screen_space_reflection(Ref<RenderSceneBuffersRD> p_render_buffe
|
|||
|
||||
RID shader = ssr_scale.shader.version_get_shader(ssr_scale.shader_version, 0);
|
||||
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssr_scale.pipelines[pipeline_specialization]);
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssr_scale.pipelines[pipeline_specialization].get_rid());
|
||||
|
||||
RD::Uniform u_diffuse(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, diffuse_slice }));
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_diffuse), 0);
|
||||
|
@ -1486,7 +1510,7 @@ void SSEffects::screen_space_reflection(Ref<RenderSceneBuffersRD> p_render_buffe
|
|||
ScreenSpaceReflectionMode mode = (ssr_roughness_quality != RS::ENV_SSR_ROUGHNESS_QUALITY_DISABLED) ? SCREEN_SPACE_REFLECTION_ROUGH : SCREEN_SPACE_REFLECTION_NORMAL;
|
||||
RID shader = ssr.shader.version_get_shader(ssr.shader_version, mode);
|
||||
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssr.pipelines[pipeline_specialization][mode]);
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssr.pipelines[pipeline_specialization][mode].get_rid());
|
||||
|
||||
RD::Uniform u_scene_data(RD::UNIFORM_TYPE_UNIFORM_BUFFER, 0, ssr.ubo);
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 4, u_scene_data), 4);
|
||||
|
@ -1554,7 +1578,7 @@ void SSEffects::screen_space_reflection(Ref<RenderSceneBuffersRD> p_render_buffe
|
|||
|
||||
RID shader = ssr_filter.shader.version_get_shader(ssr_filter.shader_version, mode);
|
||||
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssr_filter.pipelines[pipeline_specialization][mode]);
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssr_filter.pipelines[pipeline_specialization][mode].get_rid());
|
||||
|
||||
RD::Uniform u_output(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ output }));
|
||||
RD::Uniform u_blur_radius(RD::UNIFORM_TYPE_IMAGE, 1, Vector<RID>({ blur_radius[0] }));
|
||||
|
@ -1582,7 +1606,7 @@ void SSEffects::screen_space_reflection(Ref<RenderSceneBuffersRD> p_render_buffe
|
|||
mode = SCREEN_SPACE_REFLECTION_FILTER_VERTICAL;
|
||||
shader = ssr_filter.shader.version_get_shader(ssr_filter.shader_version, mode);
|
||||
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssr_filter.pipelines[pipeline_specialization][mode]);
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssr_filter.pipelines[pipeline_specialization][mode].get_rid());
|
||||
|
||||
push_constant.vertical = 1;
|
||||
|
||||
|
@ -1656,7 +1680,7 @@ void SSEffects::sub_surface_scattering(Ref<RenderSceneBuffersRD> p_render_buffer
|
|||
sss.push_constant.depth_scale = sss_depth_scale;
|
||||
|
||||
RID shader = sss.shader.version_get_shader(sss.shader_version, sss_quality - 1);
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, sss.pipelines[sss_quality - 1]);
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, sss.pipelines[sss_quality - 1].get_rid());
|
||||
|
||||
RD::Uniform u_diffuse_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_diffuse }));
|
||||
RD::Uniform u_diffuse(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_diffuse }));
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "servers/rendering/renderer_rd/pipeline_deferred_rd.h"
|
||||
#include "servers/rendering/renderer_rd/shaders/effects/screen_space_reflection.glsl.gen.h"
|
||||
#include "servers/rendering/renderer_rd/shaders/effects/screen_space_reflection_filter.glsl.gen.h"
|
||||
#include "servers/rendering/renderer_rd/shaders/effects/screen_space_reflection_scale.glsl.gen.h"
|
||||
|
@ -210,7 +211,7 @@ private:
|
|||
|
||||
RID mirror_sampler;
|
||||
|
||||
RID pipelines[SS_EFFECTS_MAX];
|
||||
PipelineDeferredRD pipelines[SS_EFFECTS_MAX];
|
||||
} ss_effects;
|
||||
|
||||
/* SSIL */
|
||||
|
@ -307,7 +308,7 @@ private:
|
|||
SsilInterleaveShaderRD interleave_shader;
|
||||
RID interleave_shader_version;
|
||||
|
||||
RID pipelines[SSIL_MAX];
|
||||
PipelineDeferredRD pipelines[SSIL_MAX];
|
||||
} ssil;
|
||||
|
||||
void gather_ssil(RD::ComputeListID p_compute_list, const RID *p_ssil_slices, const RID *p_edges_slices, const SSILSettings &p_settings, bool p_adaptive_base_pass, RID p_gather_uniform_set, RID p_importance_map_uniform_set, RID p_projection_uniform_set);
|
||||
|
@ -401,7 +402,7 @@ private:
|
|||
SsaoInterleaveShaderRD interleave_shader;
|
||||
RID interleave_shader_version;
|
||||
|
||||
RID pipelines[SSAO_MAX];
|
||||
PipelineDeferredRD pipelines[SSAO_MAX];
|
||||
} ssao;
|
||||
|
||||
void gather_ssao(RD::ComputeListID p_compute_list, const RID *p_ao_slices, const SSAOSettings &p_settings, bool p_adaptive_base_pass, RID p_gather_uniform_set, RID p_importance_map_uniform_set);
|
||||
|
@ -435,7 +436,7 @@ private:
|
|||
struct ScreenSpaceReflectionScale {
|
||||
ScreenSpaceReflectionScaleShaderRD shader;
|
||||
RID shader_version;
|
||||
RID pipelines[SSR_VARIATIONS];
|
||||
PipelineDeferredRD pipelines[SSR_VARIATIONS];
|
||||
} ssr_scale;
|
||||
|
||||
// SSR main
|
||||
|
@ -469,7 +470,7 @@ private:
|
|||
struct ScreenSpaceReflection {
|
||||
ScreenSpaceReflectionShaderRD shader;
|
||||
RID shader_version;
|
||||
RID pipelines[SSR_VARIATIONS][SCREEN_SPACE_REFLECTION_MAX];
|
||||
PipelineDeferredRD pipelines[SSR_VARIATIONS][SCREEN_SPACE_REFLECTION_MAX];
|
||||
|
||||
RID ubo;
|
||||
} ssr;
|
||||
|
@ -498,11 +499,18 @@ private:
|
|||
struct ScreenSpaceReflectionFilter {
|
||||
ScreenSpaceReflectionFilterShaderRD shader;
|
||||
RID shader_version;
|
||||
RID pipelines[SSR_VARIATIONS][SCREEN_SPACE_REFLECTION_FILTER_MAX];
|
||||
PipelineDeferredRD pipelines[SSR_VARIATIONS][SCREEN_SPACE_REFLECTION_FILTER_MAX];
|
||||
} ssr_filter;
|
||||
|
||||
/* Subsurface scattering */
|
||||
|
||||
enum SSSMode {
|
||||
SUBSURFACE_SCATTERING_MODE_LOW_QUALITY,
|
||||
SUBSURFACE_SCATTERING_MODE_MEDIUM_QUALITY,
|
||||
SUBSURFACE_SCATTERING_MODE_HIGH_QUALITY,
|
||||
SUBSURFACE_SCATTERING_MODE_MAX
|
||||
};
|
||||
|
||||
struct SubSurfaceScatteringPushConstant {
|
||||
int32_t screen_size[2];
|
||||
float camera_z_far;
|
||||
|
@ -521,7 +529,7 @@ private:
|
|||
SubSurfaceScatteringPushConstant push_constant;
|
||||
SubsurfaceScatteringShaderRD shader;
|
||||
RID shader_version;
|
||||
RID pipelines[3]; //3 quality levels
|
||||
PipelineDeferredRD pipelines[SUBSURFACE_SCATTERING_MODE_MAX];
|
||||
} sss;
|
||||
};
|
||||
|
||||
|
|
|
@ -325,7 +325,7 @@ ALBEDO = vec3(1.0);
|
|||
|
||||
volumetric_fog.process_shader_version = volumetric_fog.process_shader.version_create();
|
||||
for (int i = 0; i < VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_MAX; i++) {
|
||||
volumetric_fog.process_pipelines[i] = RD::get_singleton()->compute_pipeline_create(volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, _get_fog_process_variant(i)));
|
||||
volumetric_fog.process_pipelines[i].create_compute_pipeline(volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, _get_fog_process_variant(i)));
|
||||
}
|
||||
volumetric_fog.params_ubo = RD::get_singleton()->uniform_buffer_create(sizeof(VolumetricFogShader::ParamsUBO));
|
||||
}
|
||||
|
@ -333,7 +333,9 @@ ALBEDO = vec3(1.0);
|
|||
|
||||
void Fog::free_fog_shader() {
|
||||
MaterialStorage *material_storage = MaterialStorage::get_singleton();
|
||||
|
||||
for (int i = 0; i < VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_MAX; i++) {
|
||||
volumetric_fog.process_pipelines[i].free();
|
||||
}
|
||||
if (volumetric_fog.process_shader_version.is_valid()) {
|
||||
volumetric_fog.process_shader.version_free(volumetric_fog.process_shader_version);
|
||||
}
|
||||
|
@ -380,6 +382,8 @@ void Fog::FogShaderData::set_code(const String &p_code) {
|
|||
|
||||
if (version.is_null()) {
|
||||
version = fog_singleton->volumetric_fog.shader.version_create();
|
||||
} else {
|
||||
pipeline.free();
|
||||
}
|
||||
|
||||
fog_singleton->volumetric_fog.shader.version_set_compute_code(version, gen_code.code, gen_code.uniforms, gen_code.stage_globals[ShaderCompiler::STAGE_COMPUTE], gen_code.defines);
|
||||
|
@ -389,7 +393,7 @@ void Fog::FogShaderData::set_code(const String &p_code) {
|
|||
ubo_offsets = gen_code.uniform_offsets;
|
||||
texture_uniforms = gen_code.texture_uniforms;
|
||||
|
||||
pipeline = RD::get_singleton()->compute_pipeline_create(fog_singleton->volumetric_fog.shader.version_get_shader(version, _get_fog_variant()));
|
||||
pipeline.create_compute_pipeline(fog_singleton->volumetric_fog.shader.version_get_shader(version, _get_fog_variant()));
|
||||
|
||||
valid = true;
|
||||
}
|
||||
|
@ -414,9 +418,10 @@ Pair<ShaderRD *, RID> Fog::FogShaderData::get_native_shader_and_version() const
|
|||
}
|
||||
|
||||
Fog::FogShaderData::~FogShaderData() {
|
||||
pipeline.free();
|
||||
|
||||
Fog *fog_singleton = Fog::get_singleton();
|
||||
ERR_FAIL_NULL(fog_singleton);
|
||||
//pipeline variants will clear themselves if shader is gone
|
||||
if (version.is_valid()) {
|
||||
fog_singleton->volumetric_fog.shader.version_free(version);
|
||||
}
|
||||
|
@ -768,7 +773,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P
|
|||
push_constant.shape = uint32_t(RendererRD::Fog::get_singleton()->fog_volume_get_shape(fog_volume));
|
||||
RendererRD::MaterialStorage::store_transform(fog_volume_instance->transform.affine_inverse(), push_constant.transform);
|
||||
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, shader_data->pipeline);
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, shader_data->pipeline.get_rid());
|
||||
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, fog->fog_uniform_set, VolumetricFogShader::FogSet::FOG_SET_UNIFORMS);
|
||||
RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(VolumetricFogShader::FogPushConstant));
|
||||
|
@ -1138,7 +1143,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P
|
|||
|
||||
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
|
||||
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.process_pipelines[using_sdfgi ? VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY_WITH_SDFGI : VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY]);
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.process_pipelines[using_sdfgi ? VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY_WITH_SDFGI : VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY].get_rid());
|
||||
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, fog->gi_dependent_sets.process_uniform_set_density, 0);
|
||||
|
||||
|
@ -1150,7 +1155,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P
|
|||
|
||||
// Copy fog to history buffer
|
||||
if (RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_temporal_reprojection(p_settings.env)) {
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.process_pipelines[VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_COPY]);
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.process_pipelines[VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_COPY].get_rid());
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, fog->copy_uniform_set, 0);
|
||||
RD::get_singleton()->compute_list_dispatch_threads(compute_list, fog->width, fog->height, fog->depth);
|
||||
RD::get_singleton()->compute_list_add_barrier(compute_list);
|
||||
|
@ -1162,7 +1167,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P
|
|||
|
||||
RENDER_TIMESTAMP("Filter Fog");
|
||||
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.process_pipelines[VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_FILTER]);
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.process_pipelines[VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_FILTER].get_rid());
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, fog->gi_dependent_sets.process_uniform_set, 0);
|
||||
RD::get_singleton()->compute_list_dispatch_threads(compute_list, fog->width, fog->height, fog->depth);
|
||||
|
||||
|
@ -1173,7 +1178,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P
|
|||
RD::get_singleton()->buffer_update(volumetric_fog.params_ubo, 0, sizeof(VolumetricFogShader::ParamsUBO), ¶ms);
|
||||
|
||||
compute_list = RD::get_singleton()->compute_list_begin();
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.process_pipelines[VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_FILTER]);
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.process_pipelines[VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_FILTER].get_rid());
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, fog->gi_dependent_sets.process_uniform_set2, 0);
|
||||
RD::get_singleton()->compute_list_dispatch_threads(compute_list, fog->width, fog->height, fog->depth);
|
||||
|
||||
|
@ -1184,7 +1189,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P
|
|||
RENDER_TIMESTAMP("Integrate Fog");
|
||||
RD::get_singleton()->draw_command_begin_label("Integrate Fog");
|
||||
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.process_pipelines[VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_FOG]);
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.process_pipelines[VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_FOG].get_rid());
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, fog->gi_dependent_sets.process_uniform_set, 0);
|
||||
RD::get_singleton()->compute_list_dispatch_threads(compute_list, fog->width, fog->height, 1);
|
||||
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#include "servers/rendering/environment/renderer_fog.h"
|
||||
#include "servers/rendering/renderer_rd/cluster_builder_rd.h"
|
||||
#include "servers/rendering/renderer_rd/environment/gi.h"
|
||||
#include "servers/rendering/renderer_rd/pipeline_deferred_rd.h"
|
||||
#include "servers/rendering/renderer_rd/shaders/environment/volumetric_fog.glsl.gen.h"
|
||||
#include "servers/rendering/renderer_rd/shaders/environment/volumetric_fog_process.glsl.gen.h"
|
||||
#include "servers/rendering/renderer_rd/storage_rd/render_buffer_custom_data_rd.h"
|
||||
|
@ -189,7 +190,7 @@ private:
|
|||
VolumetricFogProcessShaderRD process_shader;
|
||||
|
||||
RID process_shader_version;
|
||||
RID process_pipelines[VOLUMETRIC_FOG_PROCESS_SHADER_MAX];
|
||||
PipelineDeferredRD process_pipelines[VOLUMETRIC_FOG_PROCESS_SHADER_MAX];
|
||||
|
||||
} volumetric_fog;
|
||||
|
||||
|
@ -199,7 +200,7 @@ private:
|
|||
bool valid = false;
|
||||
RID version;
|
||||
|
||||
RID pipeline;
|
||||
PipelineDeferredRD pipeline;
|
||||
Vector<ShaderCompiler::GeneratedCode::Texture> texture_uniforms;
|
||||
|
||||
Vector<uint32_t> ubo_offsets;
|
||||
|
|
|
@ -1247,7 +1247,7 @@ void GI::SDFGI::update_light() {
|
|||
/* Update dynamic light */
|
||||
|
||||
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->sdfgi_shader.direct_light_pipeline[SDFGIShader::DIRECT_LIGHT_MODE_DYNAMIC]);
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->sdfgi_shader.direct_light_pipeline[SDFGIShader::DIRECT_LIGHT_MODE_DYNAMIC].get_rid());
|
||||
|
||||
SDFGIShader::DirectLightPushConstant push_constant;
|
||||
|
||||
|
@ -1367,7 +1367,7 @@ void GI::SDFGI::update_probes(RID p_env, SkyRD::Sky *p_sky) {
|
|||
render_pass++;
|
||||
|
||||
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->sdfgi_shader.integrate_pipeline[SDFGIShader::INTEGRATE_MODE_PROCESS]);
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->sdfgi_shader.integrate_pipeline[SDFGIShader::INTEGRATE_MODE_PROCESS].get_rid());
|
||||
|
||||
int32_t probe_divisor = cascade_size / SDFGI::PROBE_DIVISOR;
|
||||
for (uint32_t i = 0; i < cascades.size(); i++) {
|
||||
|
@ -1412,7 +1412,7 @@ void GI::SDFGI::store_probes() {
|
|||
RENDER_TIMESTAMP("Average SDFGI Probes");
|
||||
|
||||
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->sdfgi_shader.integrate_pipeline[SDFGIShader::INTEGRATE_MODE_STORE]);
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->sdfgi_shader.integrate_pipeline[SDFGIShader::INTEGRATE_MODE_STORE].get_rid());
|
||||
|
||||
//convert to octahedral to store
|
||||
push_constant.image_size[0] *= SDFGI::LIGHTPROBE_OCT_SIZE;
|
||||
|
@ -1607,7 +1607,7 @@ void GI::SDFGI::debug_draw(uint32_t p_view_count, const Projection *p_projection
|
|||
}
|
||||
|
||||
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->sdfgi_shader.debug_pipeline);
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->sdfgi_shader.debug_pipeline.get_rid());
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, debug_uniform_set[v], 0);
|
||||
|
||||
SDFGIShader::DebugPushConstant push_constant;
|
||||
|
@ -2067,14 +2067,14 @@ void GI::SDFGI::render_region(Ref<RenderSceneBuffersRD> p_render_buffers, int p_
|
|||
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
|
||||
|
||||
//must pre scroll existing data because not all is dirty
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->sdfgi_shader.preprocess_pipeline[SDFGIShader::PRE_PROCESS_SCROLL]);
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->sdfgi_shader.preprocess_pipeline[SDFGIShader::PRE_PROCESS_SCROLL].get_rid());
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, cascades[cascade].scroll_uniform_set, 0);
|
||||
|
||||
RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(SDFGIShader::PreprocessPushConstant));
|
||||
RD::get_singleton()->compute_list_dispatch_indirect(compute_list, cascades[cascade].solid_cell_dispatch_buffer_call, 0);
|
||||
// no barrier do all together
|
||||
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->sdfgi_shader.preprocess_pipeline[SDFGIShader::PRE_PROCESS_SCROLL_OCCLUSION]);
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->sdfgi_shader.preprocess_pipeline[SDFGIShader::PRE_PROCESS_SCROLL_OCCLUSION].get_rid());
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, cascades[cascade].scroll_occlusion_uniform_set, 0);
|
||||
|
||||
Vector3i dirty = cascades[cascade].dirty_regions;
|
||||
|
@ -2122,7 +2122,7 @@ void GI::SDFGI::render_region(Ref<RenderSceneBuffersRD> p_render_buffers, int p_
|
|||
ipush_constant.scroll[1] = dirty.y / probe_divisor;
|
||||
ipush_constant.scroll[2] = dirty.z / probe_divisor;
|
||||
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->sdfgi_shader.integrate_pipeline[SDFGIShader::INTEGRATE_MODE_SCROLL]);
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->sdfgi_shader.integrate_pipeline[SDFGIShader::INTEGRATE_MODE_SCROLL].get_rid());
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, cascades[cascade].integrate_uniform_set, 0);
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, gi->sdfgi_shader.integrate_default_sky_uniform_set, 1);
|
||||
RD::get_singleton()->compute_list_set_push_constant(compute_list, &ipush_constant, sizeof(SDFGIShader::IntegratePushConstant));
|
||||
|
@ -2130,7 +2130,7 @@ void GI::SDFGI::render_region(Ref<RenderSceneBuffersRD> p_render_buffers, int p_
|
|||
|
||||
RD::get_singleton()->compute_list_add_barrier(compute_list);
|
||||
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->sdfgi_shader.integrate_pipeline[SDFGIShader::INTEGRATE_MODE_SCROLL_STORE]);
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->sdfgi_shader.integrate_pipeline[SDFGIShader::INTEGRATE_MODE_SCROLL_STORE].get_rid());
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, cascades[cascade].integrate_uniform_set, 0);
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, gi->sdfgi_shader.integrate_default_sky_uniform_set, 1);
|
||||
RD::get_singleton()->compute_list_set_push_constant(compute_list, &ipush_constant, sizeof(SDFGIShader::IntegratePushConstant));
|
||||
|
@ -2141,7 +2141,7 @@ void GI::SDFGI::render_region(Ref<RenderSceneBuffersRD> p_render_buffers, int p_
|
|||
if (bounce_feedback > 0.0) {
|
||||
//multibounce requires this to be stored so direct light can read from it
|
||||
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->sdfgi_shader.integrate_pipeline[SDFGIShader::INTEGRATE_MODE_STORE]);
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->sdfgi_shader.integrate_pipeline[SDFGIShader::INTEGRATE_MODE_STORE].get_rid());
|
||||
|
||||
//convert to octahedral to store
|
||||
ipush_constant.image_size[0] *= SDFGI::LIGHTPROBE_OCT_SIZE;
|
||||
|
@ -2171,7 +2171,7 @@ void GI::SDFGI::render_region(Ref<RenderSceneBuffersRD> p_render_buffers, int p_
|
|||
push_constant.grid_size >>= 1;
|
||||
|
||||
uint32_t cascade_half_size = cascade_size >> 1;
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->sdfgi_shader.preprocess_pipeline[SDFGIShader::PRE_PROCESS_JUMP_FLOOD_INITIALIZE_HALF]);
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->sdfgi_shader.preprocess_pipeline[SDFGIShader::PRE_PROCESS_JUMP_FLOOD_INITIALIZE_HALF].get_rid());
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, sdf_initialize_half_uniform_set, 0);
|
||||
RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(SDFGIShader::PreprocessPushConstant));
|
||||
RD::get_singleton()->compute_list_dispatch_threads(compute_list, cascade_half_size, cascade_half_size, cascade_half_size);
|
||||
|
@ -2185,7 +2185,7 @@ void GI::SDFGI::render_region(Ref<RenderSceneBuffersRD> p_render_buffers, int p_
|
|||
|
||||
uint32_t s = cascade_half_size;
|
||||
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->sdfgi_shader.preprocess_pipeline[SDFGIShader::PRE_PROCESS_JUMP_FLOOD]);
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->sdfgi_shader.preprocess_pipeline[SDFGIShader::PRE_PROCESS_JUMP_FLOOD].get_rid());
|
||||
|
||||
int jf_us = 0;
|
||||
//start with regular jump flood for very coarse reads, as this is impossible to optimize
|
||||
|
@ -2206,7 +2206,7 @@ void GI::SDFGI::render_region(Ref<RenderSceneBuffersRD> p_render_buffers, int p_
|
|||
RENDER_TIMESTAMP("SDFGI Jump Flood Optimized (Half-Size)");
|
||||
|
||||
//continue with optimized jump flood for smaller reads
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->sdfgi_shader.preprocess_pipeline[SDFGIShader::PRE_PROCESS_JUMP_FLOOD_OPTIMIZED]);
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->sdfgi_shader.preprocess_pipeline[SDFGIShader::PRE_PROCESS_JUMP_FLOOD_OPTIMIZED].get_rid());
|
||||
while (s > 1) {
|
||||
s /= 2;
|
||||
push_constant.step_size = s;
|
||||
|
@ -2221,7 +2221,7 @@ void GI::SDFGI::render_region(Ref<RenderSceneBuffersRD> p_render_buffers, int p_
|
|||
// restore grid size for last passes
|
||||
push_constant.grid_size = cascade_size;
|
||||
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->sdfgi_shader.preprocess_pipeline[SDFGIShader::PRE_PROCESS_JUMP_FLOOD_UPSCALE]);
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->sdfgi_shader.preprocess_pipeline[SDFGIShader::PRE_PROCESS_JUMP_FLOOD_UPSCALE].get_rid());
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, sdf_upscale_uniform_set, 0);
|
||||
RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(SDFGIShader::PreprocessPushConstant));
|
||||
RD::get_singleton()->compute_list_dispatch_threads(compute_list, cascade_size, cascade_size, cascade_size);
|
||||
|
@ -2231,7 +2231,7 @@ void GI::SDFGI::render_region(Ref<RenderSceneBuffersRD> p_render_buffers, int p_
|
|||
|
||||
push_constant.half_size = false;
|
||||
push_constant.step_size = 1;
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->sdfgi_shader.preprocess_pipeline[SDFGIShader::PRE_PROCESS_JUMP_FLOOD_OPTIMIZED]);
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->sdfgi_shader.preprocess_pipeline[SDFGIShader::PRE_PROCESS_JUMP_FLOOD_OPTIMIZED].get_rid());
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, jump_flood_uniform_set[upscale_jfa_uniform_set_index], 0);
|
||||
RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(SDFGIShader::PreprocessPushConstant));
|
||||
RD::get_singleton()->compute_list_dispatch_threads(compute_list, cascade_size, cascade_size, cascade_size);
|
||||
|
@ -2241,7 +2241,7 @@ void GI::SDFGI::render_region(Ref<RenderSceneBuffersRD> p_render_buffers, int p_
|
|||
//full size jumpflood
|
||||
RENDER_TIMESTAMP("SDFGI Jump Flood (Full-Size)");
|
||||
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->sdfgi_shader.preprocess_pipeline[SDFGIShader::PRE_PROCESS_JUMP_FLOOD_INITIALIZE]);
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->sdfgi_shader.preprocess_pipeline[SDFGIShader::PRE_PROCESS_JUMP_FLOOD_INITIALIZE].get_rid());
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, sdf_initialize_uniform_set, 0);
|
||||
RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(SDFGIShader::PreprocessPushConstant));
|
||||
RD::get_singleton()->compute_list_dispatch_threads(compute_list, cascade_size, cascade_size, cascade_size);
|
||||
|
@ -2252,7 +2252,7 @@ void GI::SDFGI::render_region(Ref<RenderSceneBuffersRD> p_render_buffers, int p_
|
|||
{
|
||||
uint32_t s = cascade_size;
|
||||
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->sdfgi_shader.preprocess_pipeline[SDFGIShader::PRE_PROCESS_JUMP_FLOOD]);
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->sdfgi_shader.preprocess_pipeline[SDFGIShader::PRE_PROCESS_JUMP_FLOOD].get_rid());
|
||||
|
||||
int jf_us = 0;
|
||||
//start with regular jump flood for very coarse reads, as this is impossible to optimize
|
||||
|
@ -2273,7 +2273,7 @@ void GI::SDFGI::render_region(Ref<RenderSceneBuffersRD> p_render_buffers, int p_
|
|||
RENDER_TIMESTAMP("SDFGI Jump Flood Optimized (Full-Size)");
|
||||
|
||||
//continue with optimized jump flood for smaller reads
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->sdfgi_shader.preprocess_pipeline[SDFGIShader::PRE_PROCESS_JUMP_FLOOD_OPTIMIZED]);
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->sdfgi_shader.preprocess_pipeline[SDFGIShader::PRE_PROCESS_JUMP_FLOOD_OPTIMIZED].get_rid());
|
||||
while (s > 1) {
|
||||
s /= 2;
|
||||
push_constant.step_size = s;
|
||||
|
@ -2293,7 +2293,7 @@ void GI::SDFGI::render_region(Ref<RenderSceneBuffersRD> p_render_buffers, int p_
|
|||
uint32_t probe_size = cascade_size / SDFGI::PROBE_DIVISOR;
|
||||
Vector3i probe_global_pos = cascades[cascade].position / probe_size;
|
||||
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->sdfgi_shader.preprocess_pipeline[SDFGIShader::PRE_PROCESS_OCCLUSION]);
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->sdfgi_shader.preprocess_pipeline[SDFGIShader::PRE_PROCESS_OCCLUSION].get_rid());
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, occlusion_uniform_set, 0);
|
||||
for (int i = 0; i < 8; i++) {
|
||||
//dispatch all at once for performance
|
||||
|
@ -2323,7 +2323,7 @@ void GI::SDFGI::render_region(Ref<RenderSceneBuffersRD> p_render_buffers, int p_
|
|||
RENDER_TIMESTAMP("SDFGI Store");
|
||||
|
||||
// store
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->sdfgi_shader.preprocess_pipeline[SDFGIShader::PRE_PROCESS_STORE]);
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->sdfgi_shader.preprocess_pipeline[SDFGIShader::PRE_PROCESS_STORE].get_rid());
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, cascades[cascade].sdf_store_uniform_set, 0);
|
||||
RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(SDFGIShader::PreprocessPushConstant));
|
||||
RD::get_singleton()->compute_list_dispatch_threads(compute_list, cascade_size, cascade_size, cascade_size);
|
||||
|
@ -2481,7 +2481,7 @@ void GI::SDFGI::render_static_lights(RenderDataRD *p_render_data, Ref<RenderScen
|
|||
/* Static Lights */
|
||||
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
|
||||
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->sdfgi_shader.direct_light_pipeline[SDFGIShader::DIRECT_LIGHT_MODE_STATIC]);
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->sdfgi_shader.direct_light_pipeline[SDFGIShader::DIRECT_LIGHT_MODE_STATIC].get_rid());
|
||||
|
||||
SDFGIShader::DirectLightPushConstant dl_push_constant;
|
||||
|
||||
|
@ -2985,9 +2985,9 @@ void GI::VoxelGIInstance::update(bool p_update_light_instances, const Vector<RID
|
|||
if (p_update_light_instances) {
|
||||
for (int i = 0; i < mipmaps.size(); i++) {
|
||||
if (i == 0) {
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->voxel_gi_lighting_shader_version_pipelines[pass == 0 ? VOXEL_GI_SHADER_VERSION_COMPUTE_LIGHT : VOXEL_GI_SHADER_VERSION_COMPUTE_SECOND_BOUNCE]);
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->voxel_gi_lighting_shader_version_pipelines[pass == 0 ? VOXEL_GI_SHADER_VERSION_COMPUTE_LIGHT : VOXEL_GI_SHADER_VERSION_COMPUTE_SECOND_BOUNCE].get_rid());
|
||||
} else if (i == 1) {
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->voxel_gi_lighting_shader_version_pipelines[VOXEL_GI_SHADER_VERSION_COMPUTE_MIPMAP]);
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->voxel_gi_lighting_shader_version_pipelines[VOXEL_GI_SHADER_VERSION_COMPUTE_MIPMAP].get_rid());
|
||||
}
|
||||
|
||||
if (pass == 1 || i > 0) {
|
||||
|
@ -3015,7 +3015,7 @@ void GI::VoxelGIInstance::update(bool p_update_light_instances, const Vector<RID
|
|||
RD::get_singleton()->compute_list_add_barrier(compute_list); //wait til previous step is done
|
||||
}
|
||||
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->voxel_gi_lighting_shader_version_pipelines[VOXEL_GI_SHADER_VERSION_WRITE_TEXTURE]);
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->voxel_gi_lighting_shader_version_pipelines[VOXEL_GI_SHADER_VERSION_WRITE_TEXTURE].get_rid());
|
||||
|
||||
for (int i = 0; i < mipmaps.size(); i++) {
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, mipmaps[i].write_uniform_set, 0);
|
||||
|
@ -3174,7 +3174,7 @@ void GI::VoxelGIInstance::update(bool p_update_light_instances, const Vector<RID
|
|||
|
||||
//process lighting
|
||||
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->voxel_gi_lighting_shader_version_pipelines[VOXEL_GI_SHADER_VERSION_DYNAMIC_OBJECT_LIGHTING]);
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->voxel_gi_lighting_shader_version_pipelines[VOXEL_GI_SHADER_VERSION_DYNAMIC_OBJECT_LIGHTING].get_rid());
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, dynamic_maps[0].uniform_set, 0);
|
||||
RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(VoxelGIDynamicPushConstant));
|
||||
RD::get_singleton()->compute_list_dispatch(compute_list, Math::division_round_up(rect.size.x, 8), Math::division_round_up(rect.size.y, 8), 1);
|
||||
|
@ -3231,11 +3231,11 @@ void GI::VoxelGIInstance::update(bool p_update_light_instances, const Vector<RID
|
|||
RD::get_singleton()->compute_list_add_barrier(compute_list);
|
||||
|
||||
if (dynamic_maps[k].mipmap < 0) {
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->voxel_gi_lighting_shader_version_pipelines[VOXEL_GI_SHADER_VERSION_DYNAMIC_SHRINK_WRITE]);
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->voxel_gi_lighting_shader_version_pipelines[VOXEL_GI_SHADER_VERSION_DYNAMIC_SHRINK_WRITE].get_rid());
|
||||
} else if (k < dynamic_maps.size() - 1) {
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->voxel_gi_lighting_shader_version_pipelines[VOXEL_GI_SHADER_VERSION_DYNAMIC_SHRINK_WRITE_PLOT]);
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->voxel_gi_lighting_shader_version_pipelines[VOXEL_GI_SHADER_VERSION_DYNAMIC_SHRINK_WRITE_PLOT].get_rid());
|
||||
} else {
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->voxel_gi_lighting_shader_version_pipelines[VOXEL_GI_SHADER_VERSION_DYNAMIC_SHRINK_PLOT]);
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->voxel_gi_lighting_shader_version_pipelines[VOXEL_GI_SHADER_VERSION_DYNAMIC_SHRINK_PLOT].get_rid());
|
||||
}
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, dynamic_maps[k].uniform_set, 0);
|
||||
RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(VoxelGIDynamicPushConstant));
|
||||
|
@ -3373,6 +3373,30 @@ GI::GI() {
|
|||
}
|
||||
|
||||
GI::~GI() {
|
||||
for (int v = 0; v < SHADER_SPECIALIZATION_VARIATIONS; v++) {
|
||||
for (int i = 0; i < MODE_MAX; i++) {
|
||||
pipelines[v][i].free();
|
||||
}
|
||||
}
|
||||
|
||||
sdfgi_shader.debug_pipeline.free();
|
||||
|
||||
for (int i = 0; i < SDFGIShader::DIRECT_LIGHT_MODE_MAX; i++) {
|
||||
sdfgi_shader.direct_light_pipeline[i].free();
|
||||
}
|
||||
|
||||
for (int i = 0; i < SDFGIShader::INTEGRATE_MODE_MAX; i++) {
|
||||
sdfgi_shader.integrate_pipeline[i].free();
|
||||
}
|
||||
|
||||
for (int i = 0; i < SDFGIShader::PRE_PROCESS_MAX; i++) {
|
||||
sdfgi_shader.preprocess_pipeline[i].free();
|
||||
}
|
||||
|
||||
for (int i = 0; i < VOXEL_GI_SHADER_VERSION_MAX; i++) {
|
||||
voxel_gi_lighting_shader_version_pipelines[i].free();
|
||||
}
|
||||
|
||||
if (voxel_gi_debug_shader_version.is_valid()) {
|
||||
voxel_gi_debug_shader.version_free(voxel_gi_debug_shader_version);
|
||||
}
|
||||
|
@ -3430,7 +3454,7 @@ void GI::init(SkyRD *p_sky) {
|
|||
voxel_gi_lighting_shader_version = voxel_gi_shader.version_create();
|
||||
for (int i = 0; i < VOXEL_GI_SHADER_VERSION_MAX; i++) {
|
||||
voxel_gi_lighting_shader_version_shaders[i] = voxel_gi_shader.version_get_shader(voxel_gi_lighting_shader_version, i);
|
||||
voxel_gi_lighting_shader_version_pipelines[i] = RD::get_singleton()->compute_pipeline_create(voxel_gi_lighting_shader_version_shaders[i]);
|
||||
voxel_gi_lighting_shader_version_pipelines[i].create_compute_pipeline(voxel_gi_lighting_shader_version_shaders[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3475,7 +3499,7 @@ void GI::init(SkyRD *p_sky) {
|
|||
sdfgi_shader.preprocess.initialize(preprocess_modes, defines);
|
||||
sdfgi_shader.preprocess_shader = sdfgi_shader.preprocess.version_create();
|
||||
for (int i = 0; i < SDFGIShader::PRE_PROCESS_MAX; i++) {
|
||||
sdfgi_shader.preprocess_pipeline[i] = RD::get_singleton()->compute_pipeline_create(sdfgi_shader.preprocess.version_get_shader(sdfgi_shader.preprocess_shader, i));
|
||||
sdfgi_shader.preprocess_pipeline[i].create_compute_pipeline(sdfgi_shader.preprocess.version_get_shader(sdfgi_shader.preprocess_shader, i));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3489,7 +3513,7 @@ void GI::init(SkyRD *p_sky) {
|
|||
sdfgi_shader.direct_light.initialize(direct_light_modes, defines);
|
||||
sdfgi_shader.direct_light_shader = sdfgi_shader.direct_light.version_create();
|
||||
for (int i = 0; i < SDFGIShader::DIRECT_LIGHT_MODE_MAX; i++) {
|
||||
sdfgi_shader.direct_light_pipeline[i] = RD::get_singleton()->compute_pipeline_create(sdfgi_shader.direct_light.version_get_shader(sdfgi_shader.direct_light_shader, i));
|
||||
sdfgi_shader.direct_light_pipeline[i].create_compute_pipeline(sdfgi_shader.direct_light.version_get_shader(sdfgi_shader.direct_light_shader, i));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3510,7 +3534,7 @@ void GI::init(SkyRD *p_sky) {
|
|||
sdfgi_shader.integrate_shader = sdfgi_shader.integrate.version_create();
|
||||
|
||||
for (int i = 0; i < SDFGIShader::INTEGRATE_MODE_MAX; i++) {
|
||||
sdfgi_shader.integrate_pipeline[i] = RD::get_singleton()->compute_pipeline_create(sdfgi_shader.integrate.version_get_shader(sdfgi_shader.integrate_shader, i));
|
||||
sdfgi_shader.integrate_pipeline[i].create_compute_pipeline(sdfgi_shader.integrate.version_get_shader(sdfgi_shader.integrate_shader, i));
|
||||
}
|
||||
|
||||
{
|
||||
|
@ -3592,7 +3616,7 @@ void GI::init(SkyRD *p_sky) {
|
|||
|
||||
int variant_base = vrs_supported ? MODE_MAX : 0;
|
||||
for (int i = 0; i < MODE_MAX; i++) {
|
||||
pipelines[v][i] = RD::get_singleton()->compute_pipeline_create(shader.version_get_shader(shader_version, variant_base + i), specialization_constants);
|
||||
pipelines[v][i].create_compute_pipeline(shader.version_get_shader(shader_version, variant_base + i), specialization_constants);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3605,7 +3629,7 @@ void GI::init(SkyRD *p_sky) {
|
|||
sdfgi_shader.debug.initialize(debug_modes, defines);
|
||||
sdfgi_shader.debug_shader = sdfgi_shader.debug.version_create();
|
||||
sdfgi_shader.debug_shader_version = sdfgi_shader.debug.version_get_shader(sdfgi_shader.debug_shader, 0);
|
||||
sdfgi_shader.debug_pipeline = RD::get_singleton()->compute_pipeline_create(sdfgi_shader.debug_shader_version);
|
||||
sdfgi_shader.debug_pipeline.create_compute_pipeline(sdfgi_shader.debug_shader_version);
|
||||
}
|
||||
{
|
||||
String defines = "\n#define OCT_SIZE " + itos(SDFGI::LIGHTPROBE_OCT_SIZE) + "\n";
|
||||
|
@ -4090,7 +4114,7 @@ void GI::process_gi(Ref<RenderSceneBuffersRD> p_render_buffers, const RID *p_nor
|
|||
rbgi->uniform_set[v] = RD::get_singleton()->uniform_set_create(uniforms, shader.version_get_shader(shader_version, variant_base), 0);
|
||||
}
|
||||
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, pipelines[pipeline_specialization][mode]);
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, pipelines[pipeline_specialization][mode].get_rid());
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rbgi->uniform_set[v], 0);
|
||||
RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(PushConstant));
|
||||
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#include "servers/rendering/environment/renderer_gi.h"
|
||||
#include "servers/rendering/renderer_compositor.h"
|
||||
#include "servers/rendering/renderer_rd/environment/sky.h"
|
||||
#include "servers/rendering/renderer_rd/pipeline_deferred_rd.h"
|
||||
#include "servers/rendering/renderer_rd/shaders/environment/gi.glsl.gen.h"
|
||||
#include "servers/rendering/renderer_rd/shaders/environment/sdfgi_debug.glsl.gen.h"
|
||||
#include "servers/rendering/renderer_rd/shaders/environment/sdfgi_debug_probes.glsl.gen.h"
|
||||
|
@ -232,7 +233,7 @@ private:
|
|||
VoxelGiShaderRD voxel_gi_shader;
|
||||
RID voxel_gi_lighting_shader_version;
|
||||
RID voxel_gi_lighting_shader_version_shaders[VOXEL_GI_SHADER_VERSION_MAX];
|
||||
RID voxel_gi_lighting_shader_version_pipelines[VOXEL_GI_SHADER_VERSION_MAX];
|
||||
PipelineDeferredRD voxel_gi_lighting_shader_version_pipelines[VOXEL_GI_SHADER_VERSION_MAX];
|
||||
|
||||
enum {
|
||||
VOXEL_GI_DEBUG_COLOR,
|
||||
|
@ -289,7 +290,7 @@ private:
|
|||
|
||||
SdfgiPreprocessShaderRD preprocess;
|
||||
RID preprocess_shader;
|
||||
RID preprocess_pipeline[PRE_PROCESS_MAX];
|
||||
PipelineDeferredRD preprocess_pipeline[PRE_PROCESS_MAX];
|
||||
|
||||
struct DebugPushConstant {
|
||||
float grid_size[3];
|
||||
|
@ -308,7 +309,7 @@ private:
|
|||
SdfgiDebugShaderRD debug;
|
||||
RID debug_shader;
|
||||
RID debug_shader_version;
|
||||
RID debug_pipeline;
|
||||
PipelineDeferredRD debug_pipeline;
|
||||
|
||||
enum ProbeDebugMode {
|
||||
PROBE_DEBUG_PROBES,
|
||||
|
@ -381,7 +382,7 @@ private:
|
|||
};
|
||||
SdfgiDirectLightShaderRD direct_light;
|
||||
RID direct_light_shader;
|
||||
RID direct_light_pipeline[DIRECT_LIGHT_MODE_MAX];
|
||||
PipelineDeferredRD direct_light_pipeline[DIRECT_LIGHT_MODE_MAX];
|
||||
|
||||
enum {
|
||||
INTEGRATE_MODE_PROCESS,
|
||||
|
@ -424,7 +425,7 @@ private:
|
|||
|
||||
SdfgiIntegrateShaderRD integrate;
|
||||
RID integrate_shader;
|
||||
RID integrate_pipeline[INTEGRATE_MODE_MAX];
|
||||
PipelineDeferredRD integrate_pipeline[INTEGRATE_MODE_MAX];
|
||||
|
||||
RID integrate_default_sky_uniform_set;
|
||||
|
||||
|
@ -815,7 +816,7 @@ public:
|
|||
bool half_resolution = false;
|
||||
GiShaderRD shader;
|
||||
RID shader_version;
|
||||
RID pipelines[SHADER_SPECIALIZATION_VARIATIONS][MODE_MAX];
|
||||
PipelineDeferredRD pipelines[SHADER_SPECIALIZATION_VARIATIONS][MODE_MAX];
|
||||
|
||||
GI();
|
||||
~GI();
|
||||
|
|
126
servers/rendering/renderer_rd/pipeline_deferred_rd.h
Normal file
126
servers/rendering/renderer_rd/pipeline_deferred_rd.h
Normal file
|
@ -0,0 +1,126 @@
|
|||
/**************************************************************************/
|
||||
/* pipeline_deferred_rd.h */
|
||||
/**************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/**************************************************************************/
|
||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "servers/rendering/rendering_device.h"
|
||||
|
||||
// Helper class for automatically deferring compilation of a pipeline to a background task.
|
||||
// When attempting to retrieve the pipeline with the getter, the caller will automatically
|
||||
// wait for it to be ready.
|
||||
|
||||
class PipelineDeferredRD {
|
||||
protected:
|
||||
struct CreationParameters {
|
||||
RID shader;
|
||||
RD::FramebufferFormatID framebuffer_format;
|
||||
RD::VertexFormatID vertex_format;
|
||||
RD::RenderPrimitive render_primitive;
|
||||
RD::PipelineRasterizationState rasterization_state;
|
||||
RD::PipelineMultisampleState multisample_state;
|
||||
RD::PipelineDepthStencilState depth_stencil_state;
|
||||
RD::PipelineColorBlendState blend_state;
|
||||
BitField<RD::PipelineDynamicStateFlags> dynamic_state_flags;
|
||||
uint32_t for_render_pass;
|
||||
Vector<RD::PipelineSpecializationConstant> specialization_constants;
|
||||
bool is_compute;
|
||||
};
|
||||
|
||||
RID pipeline;
|
||||
WorkerThreadPool::TaskID task = WorkerThreadPool::INVALID_TASK_ID;
|
||||
|
||||
void _create(const CreationParameters &c) {
|
||||
if (c.is_compute) {
|
||||
pipeline = RD::get_singleton()->compute_pipeline_create(c.shader, c.specialization_constants);
|
||||
} else {
|
||||
pipeline = RD::get_singleton()->render_pipeline_create(c.shader, c.framebuffer_format, c.vertex_format, c.render_primitive, c.rasterization_state, c.multisample_state, c.depth_stencil_state, c.blend_state, c.dynamic_state_flags, c.for_render_pass, c.specialization_constants);
|
||||
}
|
||||
}
|
||||
|
||||
void _start(const CreationParameters &c) {
|
||||
free();
|
||||
task = WorkerThreadPool::get_singleton()->add_template_task(this, &PipelineDeferredRD::_create, c, true, "PipelineCompilation");
|
||||
}
|
||||
|
||||
void _wait() {
|
||||
if (task != WorkerThreadPool::INVALID_TASK_ID) {
|
||||
WorkerThreadPool::get_singleton()->wait_for_task_completion(task);
|
||||
task = WorkerThreadPool::INVALID_TASK_ID;
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
PipelineDeferredRD() {
|
||||
// Default constructor.
|
||||
}
|
||||
|
||||
~PipelineDeferredRD() {
|
||||
free();
|
||||
}
|
||||
|
||||
void create_render_pipeline(RID p_shader, RD::FramebufferFormatID p_framebuffer_format, RD::VertexFormatID p_vertex_format, RD::RenderPrimitive p_render_primitive, const RD::PipelineRasterizationState &p_rasterization_state, const RD::PipelineMultisampleState &p_multisample_state, const RD::PipelineDepthStencilState &p_depth_stencil_state, const RD::PipelineColorBlendState &p_blend_state, BitField<RD::PipelineDynamicStateFlags> p_dynamic_state_flags = 0, uint32_t p_for_render_pass = 0, const Vector<RD::PipelineSpecializationConstant> &p_specialization_constants = Vector<RD::PipelineSpecializationConstant>()) {
|
||||
CreationParameters c;
|
||||
c.shader = p_shader;
|
||||
c.framebuffer_format = p_framebuffer_format;
|
||||
c.vertex_format = p_vertex_format;
|
||||
c.render_primitive = p_render_primitive;
|
||||
c.rasterization_state = p_rasterization_state;
|
||||
c.multisample_state = p_multisample_state;
|
||||
c.depth_stencil_state = p_depth_stencil_state;
|
||||
c.blend_state = p_blend_state;
|
||||
c.dynamic_state_flags = p_dynamic_state_flags;
|
||||
c.for_render_pass = p_for_render_pass;
|
||||
c.specialization_constants = p_specialization_constants;
|
||||
c.is_compute = false;
|
||||
_start(c);
|
||||
}
|
||||
|
||||
void create_compute_pipeline(RID p_shader, const Vector<RD::PipelineSpecializationConstant> &p_specialization_constants = Vector<RD::PipelineSpecializationConstant>()) {
|
||||
CreationParameters c = {};
|
||||
c.shader = p_shader;
|
||||
c.specialization_constants = p_specialization_constants;
|
||||
c.is_compute = true;
|
||||
_start(c);
|
||||
}
|
||||
|
||||
RID get_rid() {
|
||||
_wait();
|
||||
return pipeline;
|
||||
}
|
||||
|
||||
void free() {
|
||||
_wait();
|
||||
|
||||
if (pipeline.is_valid()) {
|
||||
RD::get_singleton()->free_rid(pipeline);
|
||||
pipeline = RID();
|
||||
}
|
||||
}
|
||||
};
|
|
@ -180,17 +180,22 @@ void process() {
|
|||
|
||||
for (int i = 0; i <= ParticlesShader::MAX_USERDATAS; i++) {
|
||||
for (int j = 0; j < ParticlesShader::COPY_MODE_MAX; j++) {
|
||||
particles_shader.copy_pipelines[i * ParticlesShader::COPY_MODE_MAX + j] = RD::get_singleton()->compute_pipeline_create(particles_shader.copy_shader.version_get_shader(particles_shader.copy_shader_version, i * ParticlesShader::COPY_MODE_MAX + j));
|
||||
particles_shader.copy_pipelines[i][j].create_compute_pipeline(particles_shader.copy_shader.version_get_shader(particles_shader.copy_shader_version, i * ParticlesShader::COPY_MODE_MAX + j));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ParticlesStorage::~ParticlesStorage() {
|
||||
MaterialStorage *material_storage = MaterialStorage::get_singleton();
|
||||
for (int i = 0; i <= ParticlesShader::MAX_USERDATAS; i++) {
|
||||
for (int j = 0; j < ParticlesShader::COPY_MODE_MAX; j++) {
|
||||
particles_shader.copy_pipelines[i][j].free();
|
||||
}
|
||||
}
|
||||
|
||||
particles_shader.copy_shader.version_free(particles_shader.copy_shader_version);
|
||||
|
||||
MaterialStorage *material_storage = MaterialStorage::get_singleton();
|
||||
material_storage->material_free(particles_shader.default_material);
|
||||
material_storage->shader_free(particles_shader.default_shader);
|
||||
|
||||
|
@ -1183,7 +1188,7 @@ void ParticlesStorage::_particles_process(Particles *p_particles, double p_delta
|
|||
|
||||
//todo should maybe compute all particle systems together?
|
||||
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, m->shader_data->pipeline);
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, m->shader_data->pipeline.get_rid());
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, particles_shader.base_uniform_set, BASE_UNIFORM_SET);
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, p_particles->particles_material_uniform_set, MATERIAL_UNIFORM_SET);
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, p_particles->collision_textures_uniform_set, COLLISION_TEXTURTES_UNIFORM_SET);
|
||||
|
@ -1294,7 +1299,7 @@ void ParticlesStorage::particles_set_view_axis(RID p_particles, const Vector3 &p
|
|||
if (do_sort) {
|
||||
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
|
||||
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, particles_shader.copy_pipelines[ParticlesShader::COPY_MODE_FILL_SORT_BUFFER + particles->userdata_count * ParticlesShader::COPY_MODE_MAX]);
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, particles_shader.copy_pipelines[particles->userdata_count][ParticlesShader::COPY_MODE_FILL_SORT_BUFFER].get_rid());
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, particles->particles_copy_uniform_set, 0);
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, particles->particles_sort_uniform_set, 1);
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, particles->trail_bind_pose_uniform_set, 2);
|
||||
|
@ -1311,10 +1316,9 @@ void ParticlesStorage::particles_set_view_axis(RID p_particles, const Vector3 &p
|
|||
}
|
||||
|
||||
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
|
||||
uint32_t copy_pipeline = do_sort ? ParticlesShader::COPY_MODE_FILL_INSTANCES_WITH_SORT_BUFFER : ParticlesShader::COPY_MODE_FILL_INSTANCES;
|
||||
copy_pipeline += particles->userdata_count * ParticlesShader::COPY_MODE_MAX;
|
||||
uint32_t copy_mode = do_sort ? ParticlesShader::COPY_MODE_FILL_INSTANCES_WITH_SORT_BUFFER : ParticlesShader::COPY_MODE_FILL_INSTANCES;
|
||||
copy_push_constant.copy_mode_2d = particles->mode == RS::PARTICLES_MODE_2D ? 1 : 0;
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, particles_shader.copy_pipelines[copy_pipeline]);
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, particles_shader.copy_pipelines[particles->userdata_count][copy_mode].get_rid());
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, particles->particles_copy_uniform_set, 0);
|
||||
if (do_sort) {
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, particles->particles_sort_uniform_set, 1);
|
||||
|
@ -1642,7 +1646,7 @@ void ParticlesStorage::update_particles() {
|
|||
|
||||
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
|
||||
copy_push_constant.copy_mode_2d = particles->mode == RS::PARTICLES_MODE_2D ? 1 : 0;
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, particles_shader.copy_pipelines[ParticlesShader::COPY_MODE_FILL_INSTANCES + particles->userdata_count * ParticlesShader::COPY_MODE_MAX]);
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, particles_shader.copy_pipelines[particles->userdata_count][ParticlesShader::COPY_MODE_FILL_INSTANCES].get_rid());
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, particles->particles_copy_uniform_set, 0);
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, particles->trail_bind_pose_uniform_set, 2);
|
||||
RD::get_singleton()->compute_list_set_push_constant(compute_list, ©_push_constant, sizeof(ParticlesShader::CopyPushConstant));
|
||||
|
@ -1714,6 +1718,8 @@ void ParticlesStorage::ParticlesShaderData::set_code(const String &p_code) {
|
|||
|
||||
if (version.is_null()) {
|
||||
version = particles_storage->particles_shader.shader.version_create();
|
||||
} else {
|
||||
pipeline.free();
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < ParticlesShader::MAX_USERDATAS; i++) {
|
||||
|
@ -1731,7 +1737,7 @@ void ParticlesStorage::ParticlesShaderData::set_code(const String &p_code) {
|
|||
|
||||
//update pipelines
|
||||
|
||||
pipeline = RD::get_singleton()->compute_pipeline_create(particles_storage->particles_shader.shader.version_get_shader(version, 0));
|
||||
pipeline.create_compute_pipeline(particles_storage->particles_shader.shader.version_get_shader(version, 0));
|
||||
|
||||
valid = true;
|
||||
}
|
||||
|
@ -1753,7 +1759,8 @@ Pair<ShaderRD *, RID> ParticlesStorage::ParticlesShaderData::get_native_shader_a
|
|||
}
|
||||
|
||||
ParticlesStorage::ParticlesShaderData::~ParticlesShaderData() {
|
||||
//pipeline variants will clear themselves if shader is gone
|
||||
pipeline.free();
|
||||
|
||||
if (version.is_valid()) {
|
||||
ParticlesStorage::get_singleton()->particles_shader.shader.version_free(version);
|
||||
}
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#include "core/templates/rid_owner.h"
|
||||
#include "core/templates/self_list.h"
|
||||
#include "servers/rendering/renderer_rd/effects/sort_effects.h"
|
||||
#include "servers/rendering/renderer_rd/pipeline_deferred_rd.h"
|
||||
#include "servers/rendering/renderer_rd/shaders/particles.glsl.gen.h"
|
||||
#include "servers/rendering/renderer_rd/shaders/particles_copy.glsl.gen.h"
|
||||
#include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
|
||||
|
@ -329,7 +330,7 @@ private:
|
|||
|
||||
ParticlesCopyShaderRD copy_shader;
|
||||
RID copy_shader_version;
|
||||
RID copy_pipelines[COPY_MODE_MAX * (MAX_USERDATAS + 1)];
|
||||
PipelineDeferredRD copy_pipelines[MAX_USERDATAS + 1][COPY_MODE_MAX];
|
||||
|
||||
LocalVector<float> pose_update_buffer;
|
||||
|
||||
|
@ -353,7 +354,7 @@ private:
|
|||
|
||||
String code;
|
||||
|
||||
RID pipeline;
|
||||
PipelineDeferredRD pipeline;
|
||||
|
||||
bool uses_time = false;
|
||||
|
||||
|
|
|
@ -955,6 +955,7 @@ void RendererViewport::viewport_initialize(RID p_rid) {
|
|||
viewport->fsr_enabled = !RSG::rasterizer->is_low_end() && !viewport->disable_3d;
|
||||
}
|
||||
|
||||
#ifndef XR_DISABLED
|
||||
void RendererViewport::viewport_set_use_xr(RID p_viewport, bool p_use_xr) {
|
||||
Viewport *viewport = viewport_owner.get_or_null(p_viewport);
|
||||
ERR_FAIL_NULL(viewport);
|
||||
|
@ -972,6 +973,7 @@ void RendererViewport::viewport_set_use_xr(RID p_viewport, bool p_use_xr) {
|
|||
_configure_3d_render_buffers(viewport);
|
||||
}
|
||||
}
|
||||
#endif // !XR_DISABLED
|
||||
|
||||
void RendererViewport::viewport_set_scaling_3d_mode(RID p_viewport, RS::ViewportScaling3DMode p_mode) {
|
||||
Viewport *viewport = viewport_owner.get_or_null(p_viewport);
|
||||
|
|
|
@ -216,7 +216,9 @@ public:
|
|||
RID viewport_allocate();
|
||||
void viewport_initialize(RID p_rid);
|
||||
|
||||
#ifndef XR_DISABLED
|
||||
void viewport_set_use_xr(RID p_viewport, bool p_use_xr);
|
||||
#endif // XR_DISABLED
|
||||
|
||||
void viewport_set_size(RID p_viewport, int p_width, int p_height);
|
||||
|
||||
|
|
|
@ -2823,7 +2823,9 @@ void RenderingServer::_bind_methods() {
|
|||
/* VIEWPORT */
|
||||
|
||||
ClassDB::bind_method(D_METHOD("viewport_create"), &RenderingServer::viewport_create);
|
||||
#ifndef XR_DISABLED
|
||||
ClassDB::bind_method(D_METHOD("viewport_set_use_xr", "viewport", "use_xr"), &RenderingServer::viewport_set_use_xr);
|
||||
#endif // XR_DISABLED
|
||||
ClassDB::bind_method(D_METHOD("viewport_set_size", "viewport", "width", "height"), &RenderingServer::viewport_set_size);
|
||||
ClassDB::bind_method(D_METHOD("viewport_set_active", "viewport", "active"), &RenderingServer::viewport_set_active);
|
||||
ClassDB::bind_method(D_METHOD("viewport_set_parent_viewport", "viewport", "parent_viewport"), &RenderingServer::viewport_set_parent_viewport);
|
||||
|
@ -3760,7 +3762,9 @@ void RenderingServer::init() {
|
|||
GLOBAL_DEF_RST(PropertyInfo(Variant::INT, "rendering/limits/opengl/max_renderable_lights", PROPERTY_HINT_RANGE, "2,256,1"), 32);
|
||||
GLOBAL_DEF_RST(PropertyInfo(Variant::INT, "rendering/limits/opengl/max_lights_per_object", PROPERTY_HINT_RANGE, "2,1024,1"), 8);
|
||||
|
||||
#ifndef XR_DISABLED
|
||||
GLOBAL_DEF_RST_BASIC("xr/shaders/enabled", false);
|
||||
#endif // XR_DISABLED
|
||||
|
||||
GLOBAL_DEF("debug/shader_language/warnings/enable", true);
|
||||
GLOBAL_DEF("debug/shader_language/warnings/treat_warnings_as_errors", false);
|
||||
|
|
|
@ -980,7 +980,10 @@ public:
|
|||
return VIEWPORT_SCALING_3D_TYPE_NONE;
|
||||
}
|
||||
|
||||
#ifndef XR_DISABLED
|
||||
virtual void viewport_set_use_xr(RID p_viewport, bool p_use_xr) = 0;
|
||||
#endif // !XR_DISABLED
|
||||
|
||||
virtual void viewport_set_size(RID p_viewport, int p_width, int p_height) = 0;
|
||||
virtual void viewport_set_active(RID p_viewport, bool p_active) = 0;
|
||||
virtual void viewport_set_parent_viewport(RID p_viewport, RID p_parent_viewport) = 0;
|
||||
|
|
|
@ -693,7 +693,10 @@ public:
|
|||
|
||||
FUNCRIDSPLIT(viewport)
|
||||
|
||||
#ifndef XR_DISABLED
|
||||
FUNC2(viewport_set_use_xr, RID, bool)
|
||||
#endif // XR_DISABLED
|
||||
|
||||
FUNC3(viewport_set_size, RID, int, int)
|
||||
|
||||
FUNC2(viewport_set_active, RID, bool)
|
||||
|
|
|
@ -115,10 +115,10 @@ void XRPositionalTracker::set_pose(const StringName &p_action_name, const Transf
|
|||
new_pose = poses[p_action_name];
|
||||
} else {
|
||||
new_pose.instantiate();
|
||||
new_pose->set_name(p_action_name);
|
||||
poses[p_action_name] = new_pose;
|
||||
}
|
||||
|
||||
new_pose->set_name(p_action_name);
|
||||
new_pose->set_has_tracking_data(true);
|
||||
new_pose->set_transform(p_transform);
|
||||
new_pose->set_linear_velocity(p_linear_velocity);
|
||||
|
|
2
thirdparty/README.md
vendored
2
thirdparty/README.md
vendored
|
@ -436,7 +436,7 @@ Patches:
|
|||
## harfbuzz
|
||||
|
||||
- Upstream: https://github.com/harfbuzz/harfbuzz
|
||||
- Version: 11.3.2 (4e3df1c1383481ed5717603d5dd3453a04fb16ba, 2025)
|
||||
- Version: 12.1.0 (a790c38b782f9d8e6f0299d2837229e5726fc669, 2025)
|
||||
- License: MIT
|
||||
|
||||
Files extracted from upstream source:
|
||||
|
|
13
thirdparty/harfbuzz/src/OT/Color/COLR/COLR.hh
vendored
13
thirdparty/harfbuzz/src/OT/Color/COLR/COLR.hh
vendored
|
@ -178,7 +178,10 @@ struct hb_colrv1_closure_context_t :
|
|||
{ glyphs->add (glyph_id); }
|
||||
|
||||
void add_layer_indices (unsigned first_layer_index, unsigned num_of_layers)
|
||||
{ layer_indices->add_range (first_layer_index, first_layer_index + num_of_layers - 1); }
|
||||
{
|
||||
if (num_of_layers == 0) return;
|
||||
layer_indices->add_range (first_layer_index, first_layer_index + num_of_layers - 1);
|
||||
}
|
||||
|
||||
void add_palette_index (unsigned palette_index)
|
||||
{ palette_indices->add (palette_index); }
|
||||
|
@ -650,10 +653,10 @@ struct PaintColrLayers
|
|||
TRACE_SUBSET (this);
|
||||
auto *out = c->serializer->embed (this);
|
||||
if (unlikely (!out)) return_trace (false);
|
||||
return_trace (c->serializer->check_assign (out->firstLayerIndex, c->plan->colrv1_layers.get (firstLayerIndex),
|
||||
HB_SERIALIZE_ERROR_INT_OVERFLOW));
|
||||
|
||||
return_trace (true);
|
||||
uint32_t first_layer_index = numLayers ? c->plan->colrv1_layers.get (firstLayerIndex) : 0;
|
||||
return_trace (c->serializer->check_assign (out->firstLayerIndex, first_layer_index,
|
||||
HB_SERIALIZE_ERROR_INT_OVERFLOW));
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
|
@ -2057,7 +2060,7 @@ struct delta_set_index_map_subset_plan_t
|
|||
outer_bit_count = 1;
|
||||
inner_bit_count = 1;
|
||||
|
||||
if (unlikely (!output_map.resize (map_count, false))) return false;
|
||||
if (unlikely (!output_map.resize_dirty (map_count))) return false;
|
||||
|
||||
for (unsigned idx = 0; idx < map_count; idx++)
|
||||
{
|
||||
|
|
|
@ -307,6 +307,7 @@ struct CPAL
|
|||
if (first_color_to_layer_index.has (first_color_record_idx)) continue;
|
||||
|
||||
first_color_index_for_layer.push (first_color_record_idx);
|
||||
if (unlikely (!c->serializer->propagate_error (first_color_index_for_layer))) return_trace (false);
|
||||
first_color_to_layer_index.set (first_color_record_idx,
|
||||
first_color_index_for_layer.length - 1);
|
||||
}
|
||||
|
|
|
@ -97,12 +97,17 @@ struct Coverage
|
|||
}
|
||||
}
|
||||
unsigned int get_coverage (hb_codepoint_t glyph_id,
|
||||
hb_ot_lookup_cache_t *cache) const
|
||||
hb_ot_layout_mapping_cache_t *cache) const
|
||||
{
|
||||
unsigned coverage;
|
||||
if (cache && cache->get (glyph_id, &coverage)) return coverage;
|
||||
if (cache && cache->get (glyph_id, &coverage)) return coverage < cache->MAX_VALUE ? coverage : NOT_COVERED;
|
||||
coverage = get_coverage (glyph_id);
|
||||
if (cache) cache->set (glyph_id, coverage);
|
||||
if (cache) {
|
||||
if (coverage == NOT_COVERED)
|
||||
cache->set_unchecked (glyph_id, cache->MAX_VALUE);
|
||||
else if (likely (coverage < cache->MAX_VALUE))
|
||||
cache->set_unchecked (glyph_id, coverage);
|
||||
}
|
||||
return coverage;
|
||||
}
|
||||
|
||||
|
@ -332,7 +337,7 @@ struct Coverage
|
|||
}
|
||||
iter_t __end__ () const
|
||||
{
|
||||
iter_t it = {};
|
||||
iter_t it;
|
||||
it.format = format;
|
||||
switch (format)
|
||||
{
|
||||
|
|
10
thirdparty/harfbuzz/src/OT/Layout/GDEF/GDEF.hh
vendored
10
thirdparty/harfbuzz/src/OT/Layout/GDEF/GDEF.hh
vendored
|
@ -977,7 +977,7 @@ struct GDEF
|
|||
}
|
||||
|
||||
#ifndef HB_NO_GDEF_CACHE
|
||||
table->get_mark_glyph_sets ().collect_coverage (mark_glyph_set_digests);
|
||||
table->get_mark_glyph_sets ().collect_coverage (mark_glyph_sets);
|
||||
#endif
|
||||
}
|
||||
~accelerator_t () { table.destroy (); }
|
||||
|
@ -1006,14 +1006,16 @@ struct GDEF
|
|||
{
|
||||
return
|
||||
#ifndef HB_NO_GDEF_CACHE
|
||||
mark_glyph_set_digests[set_index].may_have (glyph_id) &&
|
||||
mark_glyph_sets[set_index].may_have (glyph_id)
|
||||
#else
|
||||
table->mark_set_covers (set_index, glyph_id)
|
||||
#endif
|
||||
table->mark_set_covers (set_index, glyph_id);
|
||||
;
|
||||
}
|
||||
|
||||
hb_blob_ptr_t<GDEF> table;
|
||||
#ifndef HB_NO_GDEF_CACHE
|
||||
hb_vector_t<hb_set_digest_t> mark_glyph_set_digests;
|
||||
hb_vector_t<hb_bit_set_t> mark_glyph_sets;
|
||||
mutable hb_cache_t<21, 3> glyph_props_cache;
|
||||
static_assert (sizeof (glyph_props_cache) == 512, "");
|
||||
#endif
|
||||
|
|
|
@ -77,6 +77,13 @@ struct AnchorMatrix
|
|||
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
bool offset_is_null (unsigned row, unsigned col, unsigned num_cols) const
|
||||
{
|
||||
if (unlikely (row >= rows || col >= num_cols)) return true;
|
||||
auto &offset = matrixZ[row * num_cols + col];
|
||||
return offset.is_null ();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
|
66
thirdparty/harfbuzz/src/OT/Layout/GPOS/GPOS.hh
vendored
66
thirdparty/harfbuzz/src/OT/Layout/GPOS/GPOS.hh
vendored
|
@ -80,9 +80,8 @@ propagate_attachment_offsets (hb_glyph_position_t *pos,
|
|||
{
|
||||
/* Adjusts offsets of attached glyphs (both cursive and mark) to accumulate
|
||||
* offset of glyph they are attached to. */
|
||||
int chain = pos[i].attach_chain(), type = pos[i].attach_type();
|
||||
if (likely (!chain))
|
||||
return;
|
||||
int chain = pos[i].attach_chain();
|
||||
int type = pos[i].attach_type();
|
||||
|
||||
pos[i].attach_chain() = 0;
|
||||
|
||||
|
@ -94,7 +93,8 @@ propagate_attachment_offsets (hb_glyph_position_t *pos,
|
|||
if (unlikely (!nesting_level))
|
||||
return;
|
||||
|
||||
propagate_attachment_offsets (pos, len, j, direction, nesting_level - 1);
|
||||
if (pos[j].attach_chain())
|
||||
propagate_attachment_offsets (pos, len, j, direction, nesting_level - 1);
|
||||
|
||||
assert (!!(type & GPOS_impl::ATTACH_TYPE_MARK) ^ !!(type & GPOS_impl::ATTACH_TYPE_CURSIVE));
|
||||
|
||||
|
@ -110,17 +110,37 @@ propagate_attachment_offsets (hb_glyph_position_t *pos,
|
|||
pos[i].x_offset += pos[j].x_offset;
|
||||
pos[i].y_offset += pos[j].y_offset;
|
||||
|
||||
assert (j < i);
|
||||
if (HB_DIRECTION_IS_FORWARD (direction))
|
||||
for (unsigned int k = j; k < i; k++) {
|
||||
pos[i].x_offset -= pos[k].x_advance;
|
||||
pos[i].y_offset -= pos[k].y_advance;
|
||||
}
|
||||
else
|
||||
for (unsigned int k = j + 1; k < i + 1; k++) {
|
||||
pos[i].x_offset += pos[k].x_advance;
|
||||
pos[i].y_offset += pos[k].y_advance;
|
||||
}
|
||||
// i is the position of the mark; j is the base.
|
||||
if (j < i)
|
||||
{
|
||||
/* This is the common case: mark follows base.
|
||||
* And currently the only way in OpenType. */
|
||||
if (HB_DIRECTION_IS_FORWARD (direction))
|
||||
for (unsigned int k = j; k < i; k++) {
|
||||
pos[i].x_offset -= pos[k].x_advance;
|
||||
pos[i].y_offset -= pos[k].y_advance;
|
||||
}
|
||||
else
|
||||
for (unsigned int k = j + 1; k < i + 1; k++) {
|
||||
pos[i].x_offset += pos[k].x_advance;
|
||||
pos[i].y_offset += pos[k].y_advance;
|
||||
}
|
||||
}
|
||||
else // j > i
|
||||
{
|
||||
/* This can happen with `kerx`: a mark attaching
|
||||
* to a base after it in the logical order. */
|
||||
if (HB_DIRECTION_IS_FORWARD (direction))
|
||||
for (unsigned int k = i; k < j; k++) {
|
||||
pos[i].x_offset += pos[k].x_advance;
|
||||
pos[i].y_offset += pos[k].y_advance;
|
||||
}
|
||||
else
|
||||
for (unsigned int k = i + 1; k < j + 1; k++) {
|
||||
pos[i].x_offset -= pos[k].x_advance;
|
||||
pos[i].y_offset -= pos[k].y_advance;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -149,8 +169,20 @@ GPOS::position_finish_offsets (hb_font_t *font, hb_buffer_t *buffer)
|
|||
|
||||
/* Handle attachments */
|
||||
if (buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT)
|
||||
for (unsigned i = 0; i < len; i++)
|
||||
propagate_attachment_offsets (pos, len, i, direction);
|
||||
{
|
||||
auto *pos = buffer->pos;
|
||||
// https://github.com/harfbuzz/harfbuzz/issues/5514
|
||||
if (HB_DIRECTION_IS_FORWARD (direction))
|
||||
{
|
||||
for (unsigned i = 0; i < len; i++)
|
||||
if (pos[i].attach_chain())
|
||||
propagate_attachment_offsets (pos, len, i, direction);
|
||||
} else {
|
||||
for (unsigned i = len; i-- > 0; )
|
||||
if (pos[i].attach_chain())
|
||||
propagate_attachment_offsets (pos, len, i, direction);
|
||||
}
|
||||
}
|
||||
|
||||
if (unlikely (font->slant_xy) &&
|
||||
HB_DIRECTION_IS_HORIZONTAL (direction))
|
||||
|
|
|
@ -19,22 +19,30 @@ struct LigatureArray : List16OfOffset16To<LigatureAttach>
|
|||
bool subset (hb_subset_context_t *c,
|
||||
Iterator coverage,
|
||||
unsigned class_count,
|
||||
const hb_map_t *klass_mapping) const
|
||||
const hb_map_t *klass_mapping,
|
||||
hb_sorted_vector_t<hb_codepoint_t> &new_coverage /* OUT */) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
|
||||
const hb_map_t &glyph_map = c->plan->glyph_map_gsub;
|
||||
|
||||
auto *out = c->serializer->start_embed (this);
|
||||
if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
|
||||
|
||||
bool ret = false;
|
||||
for (const auto _ : + hb_zip (coverage, *this)
|
||||
| hb_filter (glyphset, hb_first))
|
||||
| hb_filter (glyph_map, hb_first))
|
||||
{
|
||||
const LigatureAttach& src = (this + _.second);
|
||||
bool non_empty = + hb_range (src.rows * class_count)
|
||||
| hb_filter ([=] (unsigned index) { return klass_mapping->has (index % class_count); })
|
||||
| hb_map ([&] (const unsigned index) { return !src.offset_is_null (index / class_count, index % class_count, class_count); })
|
||||
| hb_any;
|
||||
|
||||
if (!non_empty) continue;
|
||||
|
||||
auto *matrix = out->serialize_append (c->serializer);
|
||||
if (unlikely (!matrix)) return_trace (false);
|
||||
|
||||
const LigatureAttach& src = (this + _.second);
|
||||
auto indexes =
|
||||
+ hb_range (src.rows * class_count)
|
||||
| hb_filter ([=] (unsigned index) { return klass_mapping->has (index % class_count); })
|
||||
|
@ -44,6 +52,9 @@ struct LigatureArray : List16OfOffset16To<LigatureAttach>
|
|||
this,
|
||||
src.rows,
|
||||
indexes);
|
||||
|
||||
hb_codepoint_t new_gid = glyph_map.get (_.first);
|
||||
new_coverage.push (new_gid);
|
||||
}
|
||||
return_trace (ret);
|
||||
}
|
||||
|
|
|
@ -209,19 +209,22 @@ struct MarkBasePosFormat1_2
|
|||
;
|
||||
|
||||
new_coverage.reset ();
|
||||
+ base_iter
|
||||
| hb_map (hb_first)
|
||||
| hb_map (glyph_map)
|
||||
| hb_sink (new_coverage)
|
||||
;
|
||||
|
||||
if (!out->baseCoverage.serialize_serialize (c->serializer, new_coverage.iter ()))
|
||||
return_trace (false);
|
||||
|
||||
hb_sorted_vector_t<unsigned> base_indexes;
|
||||
for (const unsigned row : + base_iter
|
||||
| hb_map (hb_second))
|
||||
auto &base_array = (this+baseArray);
|
||||
for (const auto _ : + base_iter)
|
||||
{
|
||||
unsigned row = _.second;
|
||||
bool non_empty = + hb_range ((unsigned) classCount)
|
||||
| hb_filter (klass_mapping)
|
||||
| hb_map ([&] (const unsigned col) { return !base_array.offset_is_null (row, col, (unsigned) classCount); })
|
||||
| hb_any
|
||||
;
|
||||
|
||||
if (!non_empty) continue;
|
||||
|
||||
hb_codepoint_t new_g = glyph_map.get ( _.first);
|
||||
new_coverage.push (new_g);
|
||||
|
||||
+ hb_range ((unsigned) classCount)
|
||||
| hb_filter (klass_mapping)
|
||||
| hb_map ([&] (const unsigned col) { return row * (unsigned) classCount + col; })
|
||||
|
@ -229,8 +232,12 @@ struct MarkBasePosFormat1_2
|
|||
;
|
||||
}
|
||||
|
||||
if (!new_coverage) return_trace (false);
|
||||
if (!out->baseCoverage.serialize_serialize (c->serializer, new_coverage.iter ()))
|
||||
return_trace (false);
|
||||
|
||||
return_trace (out->baseArray.serialize_subset (c, baseArray, this,
|
||||
base_iter.len (),
|
||||
new_coverage.length,
|
||||
base_indexes.iter ()));
|
||||
}
|
||||
};
|
||||
|
|
|
@ -200,19 +200,13 @@ struct MarkLigPosFormat1_2
|
|||
&klass_mapping)))
|
||||
return_trace (false);
|
||||
|
||||
auto new_ligature_coverage =
|
||||
+ hb_iter (this + ligatureCoverage)
|
||||
| hb_take ((this + ligatureArray).len)
|
||||
| hb_map_retains_sorting (glyph_map)
|
||||
| hb_filter ([] (hb_codepoint_t glyph) { return glyph != HB_MAP_VALUE_INVALID; })
|
||||
;
|
||||
|
||||
if (!out->ligatureCoverage.serialize_serialize (c->serializer, new_ligature_coverage))
|
||||
hb_sorted_vector_t<hb_codepoint_t> new_lig_coverage;
|
||||
if (!out->ligatureArray.serialize_subset (c, ligatureArray, this,
|
||||
hb_iter (this+ligatureCoverage),
|
||||
classCount, &klass_mapping, new_lig_coverage))
|
||||
return_trace (false);
|
||||
|
||||
return_trace (out->ligatureArray.serialize_subset (c, ligatureArray, this,
|
||||
hb_iter (this+ligatureCoverage),
|
||||
classCount, &klass_mapping));
|
||||
return_trace (out->ligatureCoverage.serialize_serialize (c->serializer, new_lig_coverage.iter ()));
|
||||
}
|
||||
|
||||
};
|
||||
|
|
|
@ -196,19 +196,23 @@ struct MarkMarkPosFormat1_2
|
|||
;
|
||||
|
||||
new_coverage.reset ();
|
||||
+ mark2_iter
|
||||
| hb_map (hb_first)
|
||||
| hb_map (glyph_map)
|
||||
| hb_sink (new_coverage)
|
||||
;
|
||||
|
||||
if (!out->mark2Coverage.serialize_serialize (c->serializer, new_coverage.iter ()))
|
||||
return_trace (false);
|
||||
|
||||
hb_sorted_vector_t<unsigned> mark2_indexes;
|
||||
for (const unsigned row : + mark2_iter
|
||||
| hb_map (hb_second))
|
||||
auto &mark2_array = (this+mark2Array);
|
||||
for (const auto _ : + mark2_iter)
|
||||
{
|
||||
unsigned row = _.second;
|
||||
|
||||
bool non_empty = + hb_range ((unsigned) classCount)
|
||||
| hb_filter (klass_mapping)
|
||||
| hb_map ([&] (const unsigned col) { return !mark2_array.offset_is_null (row, col, (unsigned) classCount); })
|
||||
| hb_any
|
||||
;
|
||||
|
||||
if (!non_empty) continue;
|
||||
|
||||
hb_codepoint_t new_g = glyph_map.get ( _.first);
|
||||
new_coverage.push (new_g);
|
||||
|
||||
+ hb_range ((unsigned) classCount)
|
||||
| hb_filter (klass_mapping)
|
||||
| hb_map ([&] (const unsigned col) { return row * (unsigned) classCount + col; })
|
||||
|
@ -216,6 +220,10 @@ struct MarkMarkPosFormat1_2
|
|||
;
|
||||
}
|
||||
|
||||
if (!new_coverage) return_trace (false);
|
||||
if (!out->mark2Coverage.serialize_serialize (c->serializer, new_coverage.iter ()))
|
||||
return_trace (false);
|
||||
|
||||
return_trace (out->mark2Array.serialize_subset (c, mark2Array, this,
|
||||
mark2_iter.len (),
|
||||
mark2_indexes.iter ()));
|
||||
|
|
|
@ -103,46 +103,29 @@ struct PairPosFormat1_3
|
|||
|
||||
const Coverage &get_coverage () const { return this+coverage; }
|
||||
|
||||
unsigned cache_cost () const
|
||||
struct external_cache_t
|
||||
{
|
||||
return (this+coverage).cost ();
|
||||
}
|
||||
static void * cache_func (void *p, hb_ot_lookup_cache_op_t op)
|
||||
hb_ot_layout_mapping_cache_t coverage;
|
||||
};
|
||||
void *external_cache_create () const
|
||||
{
|
||||
switch (op)
|
||||
external_cache_t *cache = (external_cache_t *) hb_malloc (sizeof (external_cache_t));
|
||||
if (likely (cache))
|
||||
{
|
||||
case hb_ot_lookup_cache_op_t::CREATE:
|
||||
{
|
||||
hb_ot_lookup_cache_t *cache = (hb_ot_lookup_cache_t *) hb_malloc (sizeof (hb_ot_lookup_cache_t));
|
||||
if (likely (cache))
|
||||
cache->clear ();
|
||||
return cache;
|
||||
}
|
||||
case hb_ot_lookup_cache_op_t::ENTER:
|
||||
return (void *) true;
|
||||
case hb_ot_lookup_cache_op_t::LEAVE:
|
||||
return nullptr;
|
||||
case hb_ot_lookup_cache_op_t::DESTROY:
|
||||
{
|
||||
hb_ot_lookup_cache_t *cache = (hb_ot_lookup_cache_t *) p;
|
||||
hb_free (cache);
|
||||
return nullptr;
|
||||
}
|
||||
cache->coverage.clear ();
|
||||
}
|
||||
return nullptr;
|
||||
return cache;
|
||||
}
|
||||
|
||||
bool apply_cached (hb_ot_apply_context_t *c) const { return _apply (c, true); }
|
||||
bool apply (hb_ot_apply_context_t *c) const { return _apply (c, false); }
|
||||
bool _apply (hb_ot_apply_context_t *c, bool cached) const
|
||||
bool apply (hb_ot_apply_context_t *c, void *external_cache) const
|
||||
{
|
||||
TRACE_APPLY (this);
|
||||
|
||||
hb_buffer_t *buffer = c->buffer;
|
||||
|
||||
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
|
||||
hb_ot_lookup_cache_t *cache = cached ? (hb_ot_lookup_cache_t *) c->lookup_accel->cache : nullptr;
|
||||
unsigned int index = (this+coverage).get_coverage (buffer->cur().codepoint, cache);
|
||||
external_cache_t *cache = (external_cache_t *) external_cache;
|
||||
unsigned int index = (this+coverage).get_coverage (buffer->cur().codepoint, cache ? &cache->coverage : nullptr);
|
||||
#else
|
||||
unsigned int index = (this+coverage).get_coverage (buffer->cur().codepoint);
|
||||
#endif
|
||||
|
|
|
@ -123,56 +123,32 @@ struct PairPosFormat2_4 : ValueBase
|
|||
|
||||
const Coverage &get_coverage () const { return this+coverage; }
|
||||
|
||||
struct pair_pos_cache_t
|
||||
struct external_cache_t
|
||||
{
|
||||
hb_ot_lookup_cache_t coverage;
|
||||
hb_ot_lookup_cache_t first;
|
||||
hb_ot_lookup_cache_t second;
|
||||
hb_ot_layout_mapping_cache_t coverage;
|
||||
hb_ot_layout_mapping_cache_t first;
|
||||
hb_ot_layout_mapping_cache_t second;
|
||||
};
|
||||
|
||||
unsigned cache_cost () const
|
||||
void *external_cache_create () const
|
||||
{
|
||||
return (this+coverage).cost () + (this+classDef1).cost () + (this+classDef2).cost ();
|
||||
}
|
||||
static void * cache_func (void *p, hb_ot_lookup_cache_op_t op)
|
||||
{
|
||||
switch (op)
|
||||
external_cache_t *cache = (external_cache_t *) hb_malloc (sizeof (external_cache_t));
|
||||
if (likely (cache))
|
||||
{
|
||||
case hb_ot_lookup_cache_op_t::CREATE:
|
||||
{
|
||||
pair_pos_cache_t *cache = (pair_pos_cache_t *) hb_malloc (sizeof (pair_pos_cache_t));
|
||||
if (likely (cache))
|
||||
{
|
||||
cache->coverage.clear ();
|
||||
cache->first.clear ();
|
||||
cache->second.clear ();
|
||||
}
|
||||
return cache;
|
||||
}
|
||||
case hb_ot_lookup_cache_op_t::ENTER:
|
||||
return (void *) true;
|
||||
case hb_ot_lookup_cache_op_t::LEAVE:
|
||||
return nullptr;
|
||||
case hb_ot_lookup_cache_op_t::DESTROY:
|
||||
{
|
||||
pair_pos_cache_t *cache = (pair_pos_cache_t *) p;
|
||||
hb_free (cache);
|
||||
return nullptr;
|
||||
}
|
||||
cache->coverage.clear ();
|
||||
cache->first.clear ();
|
||||
cache->second.clear ();
|
||||
}
|
||||
return nullptr;
|
||||
return cache;
|
||||
}
|
||||
|
||||
bool apply_cached (hb_ot_apply_context_t *c) const { return _apply (c, true); }
|
||||
bool apply (hb_ot_apply_context_t *c) const { return _apply (c, false); }
|
||||
bool _apply (hb_ot_apply_context_t *c, bool cached) const
|
||||
bool apply (hb_ot_apply_context_t *c, void *external_cache) const
|
||||
{
|
||||
TRACE_APPLY (this);
|
||||
|
||||
hb_buffer_t *buffer = c->buffer;
|
||||
|
||||
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
|
||||
pair_pos_cache_t *cache = cached ? (pair_pos_cache_t *) c->lookup_accel->cache : nullptr;
|
||||
external_cache_t *cache = (external_cache_t *) external_cache;
|
||||
unsigned int index = (this+coverage).get_coverage (buffer->cur().codepoint, cache ? &cache->coverage : nullptr);
|
||||
#else
|
||||
unsigned int index = (this+coverage).get_coverage (buffer->cur().codepoint);
|
||||
|
|
|
@ -58,7 +58,12 @@ struct ValueFormat : HBUINT16
|
|||
|
||||
NumType& operator = (uint16_t i) { v = i; return *this; }
|
||||
|
||||
unsigned int get_len () const { return hb_popcount ((unsigned int) *this); }
|
||||
// Note: spec says skip 2 bytes per bit in the valueformat. But reports
|
||||
// from Microsoft developers indicate that only the fields that are
|
||||
// currently defined are counted. We don't expect any new fields to
|
||||
// be added to ValueFormat. As such, we use the faster hb_popcount8
|
||||
// that only processes the lowest 8 bits.
|
||||
unsigned int get_len () const { return hb_popcount8 ((uint8_t) *this); }
|
||||
unsigned int get_size () const { return get_len () * Value::static_size; }
|
||||
|
||||
hb_vector_t<unsigned> get_device_table_indices () const {
|
||||
|
|
|
@ -91,6 +91,19 @@ struct AlternateSet
|
|||
return alternates.len;
|
||||
}
|
||||
|
||||
void
|
||||
collect_alternates (hb_codepoint_t gid,
|
||||
hb_map_t *alternate_count /* IN/OUT */,
|
||||
hb_map_t *alternate_glyphs /* IN/OUT */) const
|
||||
{
|
||||
+ hb_enumerate (alternates)
|
||||
| hb_map ([gid] (hb_pair_t<unsigned, hb_codepoint_t> _) { return hb_pair (gid + (_.first << 24), _.second); })
|
||||
| hb_apply ([&] (const hb_pair_t<hb_codepoint_t, hb_codepoint_t> &p) -> void
|
||||
{ _hb_collect_glyph_alternates_add (p.first, p.second,
|
||||
alternate_count, alternate_glyphs); })
|
||||
;
|
||||
}
|
||||
|
||||
template <typename Iterator,
|
||||
hb_requires (hb_is_source_of (Iterator, hb_codepoint_t))>
|
||||
bool serialize (hb_serialize_context_t *c,
|
||||
|
|
|
@ -69,6 +69,19 @@ struct AlternateSubstFormat1_2
|
|||
{ return (this+alternateSet[(this+coverage).get_coverage (gid)])
|
||||
.get_alternates (start_offset, alternate_count, alternate_glyphs); }
|
||||
|
||||
void
|
||||
collect_glyph_alternates (hb_map_t *alternate_count /* IN/OUT */,
|
||||
hb_map_t *alternate_glyphs /* IN/OUT */) const
|
||||
{
|
||||
+ hb_iter (alternateSet)
|
||||
| hb_map (hb_add (this))
|
||||
| hb_zip (this+coverage)
|
||||
| hb_apply ([&] (const hb_pair_t<const AlternateSet<Types> &, hb_codepoint_t> _) {
|
||||
_.first.collect_alternates (_.second, alternate_count, alternate_glyphs);
|
||||
})
|
||||
;
|
||||
}
|
||||
|
||||
bool apply (hb_ot_apply_context_t *c) const
|
||||
{
|
||||
TRACE_APPLY (this);
|
||||
|
|
|
@ -44,6 +44,18 @@ struct Ligature
|
|||
c->output->add (ligGlyph);
|
||||
}
|
||||
|
||||
template <typename set_t>
|
||||
void collect_second (set_t &s) const
|
||||
{
|
||||
if (unlikely (!component.get_length ()))
|
||||
{
|
||||
// A ligature without any components. Anything matches.
|
||||
s = set_t::full ();
|
||||
return;
|
||||
}
|
||||
s.add (component.arrayZ[0]);
|
||||
}
|
||||
|
||||
bool would_apply (hb_would_apply_context_t *c) const
|
||||
{
|
||||
if (c->len != component.lenP1)
|
||||
|
@ -91,15 +103,6 @@ struct Ligature
|
|||
unsigned int total_component_count = 0;
|
||||
|
||||
if (unlikely (count > HB_MAX_CONTEXT_LENGTH)) return false;
|
||||
unsigned match_positions_stack[4];
|
||||
unsigned *match_positions = match_positions_stack;
|
||||
if (unlikely (count > ARRAY_LENGTH (match_positions_stack)))
|
||||
{
|
||||
match_positions = (unsigned *) hb_malloc (hb_max (count, 1u) * sizeof (unsigned));
|
||||
if (unlikely (!match_positions))
|
||||
return_trace (false);
|
||||
}
|
||||
|
||||
unsigned int match_end = 0;
|
||||
|
||||
if (likely (!match_input (c, count,
|
||||
|
@ -107,12 +110,9 @@ struct Ligature
|
|||
match_glyph,
|
||||
nullptr,
|
||||
&match_end,
|
||||
match_positions,
|
||||
&total_component_count)))
|
||||
{
|
||||
c->buffer->unsafe_to_concat (c->buffer->idx, match_end);
|
||||
if (match_positions != match_positions_stack)
|
||||
hb_free (match_positions);
|
||||
return_trace (false);
|
||||
}
|
||||
|
||||
|
@ -129,10 +129,10 @@ struct Ligature
|
|||
match_end += delta;
|
||||
for (unsigned i = 0; i < count; i++)
|
||||
{
|
||||
match_positions[i] += delta;
|
||||
c->match_positions[i] += delta;
|
||||
if (i)
|
||||
*p++ = ',';
|
||||
snprintf (p, sizeof(buf) - (p - buf), "%u", match_positions[i]);
|
||||
snprintf (p, sizeof(buf) - (p - buf), "%u", c->match_positions[i]);
|
||||
p += strlen(p);
|
||||
}
|
||||
|
||||
|
@ -143,7 +143,6 @@ struct Ligature
|
|||
|
||||
ligate_input (c,
|
||||
count,
|
||||
match_positions,
|
||||
match_end,
|
||||
ligGlyph,
|
||||
total_component_count);
|
||||
|
@ -156,8 +155,6 @@ struct Ligature
|
|||
pos);
|
||||
}
|
||||
|
||||
if (match_positions != match_positions_stack)
|
||||
hb_free (match_positions);
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
|
|
|
@ -62,6 +62,15 @@ struct LigatureSet
|
|||
;
|
||||
}
|
||||
|
||||
template <typename set_t>
|
||||
void collect_seconds (set_t &s) const
|
||||
{
|
||||
+ hb_iter (ligature)
|
||||
| hb_map (hb_add (this))
|
||||
| hb_apply ([&s] (const Ligature<Types> &_) { _.collect_second (s); })
|
||||
;
|
||||
}
|
||||
|
||||
bool would_apply (hb_would_apply_context_t *c) const
|
||||
{
|
||||
return
|
||||
|
@ -72,14 +81,14 @@ struct LigatureSet
|
|||
;
|
||||
}
|
||||
|
||||
bool apply (hb_ot_apply_context_t *c) const
|
||||
bool apply (hb_ot_apply_context_t *c, const hb_set_digest_t *seconds = nullptr) const
|
||||
{
|
||||
TRACE_APPLY (this);
|
||||
|
||||
unsigned int num_ligs = ligature.len;
|
||||
|
||||
#ifndef HB_NO_OT_RULESETS_FAST_PATH
|
||||
if (HB_OPTIMIZE_SIZE_VAL || num_ligs <= 4)
|
||||
if (HB_OPTIMIZE_SIZE_VAL || num_ligs <= 1)
|
||||
#endif
|
||||
{
|
||||
slow:
|
||||
|
@ -91,7 +100,7 @@ struct LigatureSet
|
|||
return_trace (false);
|
||||
}
|
||||
|
||||
/* This version is optimized for speed by matching the first component
|
||||
/* This version is optimized for speed by matching the second component
|
||||
* of the ligature here, instead of calling into the ligation code.
|
||||
*
|
||||
* This is replicated in ChainRuleSet and RuleSet. */
|
||||
|
@ -101,11 +110,11 @@ struct LigatureSet
|
|||
skippy_iter.set_match_func (match_always, nullptr);
|
||||
skippy_iter.set_glyph_data ((HBUINT16 *) nullptr);
|
||||
unsigned unsafe_to;
|
||||
hb_codepoint_t first = (unsigned) -1;
|
||||
hb_codepoint_t second = (unsigned) -1;
|
||||
bool matched = skippy_iter.next (&unsafe_to);
|
||||
if (likely (matched))
|
||||
{
|
||||
first = c->buffer->info[skippy_iter.idx].codepoint;
|
||||
second = c->buffer->info[skippy_iter.idx].codepoint;
|
||||
unsafe_to = skippy_iter.idx + 1;
|
||||
|
||||
if (skippy_iter.may_skip (c->buffer->info[skippy_iter.idx]))
|
||||
|
@ -118,13 +127,14 @@ struct LigatureSet
|
|||
else
|
||||
goto slow;
|
||||
|
||||
if (seconds && !seconds->may_have (second))
|
||||
return_trace (false);
|
||||
bool unsafe_to_concat = false;
|
||||
|
||||
for (unsigned int i = 0; i < num_ligs; i++)
|
||||
{
|
||||
const auto &lig = this+ligature.arrayZ[i];
|
||||
if (unlikely (lig.component.lenP1 <= 1) ||
|
||||
lig.component.arrayZ[0] == first)
|
||||
lig.component.arrayZ[0] == second)
|
||||
{
|
||||
if (lig.apply (c))
|
||||
{
|
||||
|
|
|
@ -78,52 +78,44 @@ struct LigatureSubstFormat1_2
|
|||
return lig_set.would_apply (c);
|
||||
}
|
||||
|
||||
unsigned cache_cost () const
|
||||
struct external_cache_t
|
||||
{
|
||||
return (this+coverage).cost ();
|
||||
}
|
||||
static void * cache_func (void *p, hb_ot_lookup_cache_op_t op)
|
||||
hb_ot_layout_mapping_cache_t coverage;
|
||||
hb_set_digest_t seconds;
|
||||
};
|
||||
void *external_cache_create () const
|
||||
{
|
||||
switch (op)
|
||||
external_cache_t *cache = (external_cache_t *) hb_malloc (sizeof (external_cache_t));
|
||||
if (likely (cache))
|
||||
{
|
||||
case hb_ot_lookup_cache_op_t::CREATE:
|
||||
{
|
||||
hb_ot_lookup_cache_t *cache = (hb_ot_lookup_cache_t *) hb_malloc (sizeof (hb_ot_lookup_cache_t));
|
||||
if (likely (cache))
|
||||
cache->clear ();
|
||||
return cache;
|
||||
}
|
||||
case hb_ot_lookup_cache_op_t::ENTER:
|
||||
return (void *) true;
|
||||
case hb_ot_lookup_cache_op_t::LEAVE:
|
||||
return nullptr;
|
||||
case hb_ot_lookup_cache_op_t::DESTROY:
|
||||
{
|
||||
hb_ot_lookup_cache_t *cache = (hb_ot_lookup_cache_t *) p;
|
||||
hb_free (cache);
|
||||
return nullptr;
|
||||
}
|
||||
cache->coverage.clear ();
|
||||
|
||||
cache->seconds.init ();
|
||||
+ hb_iter (ligatureSet)
|
||||
| hb_map (hb_add (this))
|
||||
| hb_apply ([cache] (const LigatureSet<Types> &_) { _.collect_seconds (cache->seconds); })
|
||||
;
|
||||
}
|
||||
return nullptr;
|
||||
return cache;
|
||||
}
|
||||
|
||||
bool apply_cached (hb_ot_apply_context_t *c) const { return _apply (c, true); }
|
||||
bool apply (hb_ot_apply_context_t *c) const { return _apply (c, false); }
|
||||
bool _apply (hb_ot_apply_context_t *c, bool cached) const
|
||||
bool apply (hb_ot_apply_context_t *c, void *external_cache) const
|
||||
{
|
||||
TRACE_APPLY (this);
|
||||
hb_buffer_t *buffer = c->buffer;
|
||||
|
||||
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
|
||||
hb_ot_lookup_cache_t *cache = cached ? (hb_ot_lookup_cache_t *) c->lookup_accel->cache : nullptr;
|
||||
unsigned int index = (this+coverage).get_coverage (buffer->cur().codepoint, cache);
|
||||
external_cache_t *cache = (external_cache_t *) external_cache;
|
||||
const hb_set_digest_t *seconds = cache ? &cache->seconds : nullptr;
|
||||
unsigned int index = (this+coverage).get_coverage (buffer->cur().codepoint, cache ? &cache->coverage : nullptr);
|
||||
#else
|
||||
const hb_set_digest_t *seconds = nullptr;
|
||||
unsigned int index = (this+coverage).get_coverage (buffer->cur().codepoint);
|
||||
#endif
|
||||
if (index == NOT_COVERED) return_trace (false);
|
||||
|
||||
const auto &lig_set = this+ligatureSet[index];
|
||||
return_trace (lig_set.apply (c));
|
||||
return_trace (lig_set.apply (c, seconds));
|
||||
}
|
||||
|
||||
bool serialize (hb_serialize_context_t *c,
|
||||
|
|
|
@ -123,6 +123,21 @@ struct SingleSubstFormat1_3
|
|||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
collect_glyph_alternates (hb_map_t *alternate_count /* IN/OUT */,
|
||||
hb_map_t *alternate_glyphs /* IN/OUT */) const
|
||||
{
|
||||
hb_codepoint_t d = deltaGlyphID;
|
||||
hb_codepoint_t mask = get_mask ();
|
||||
|
||||
+ hb_iter (this+coverage)
|
||||
| hb_map ([d, mask] (hb_codepoint_t g) { return hb_pair (g, (g + d) & mask); })
|
||||
| hb_apply ([&] (const hb_pair_t<hb_codepoint_t, hb_codepoint_t> &p) -> void
|
||||
{ _hb_collect_glyph_alternates_add (p.first, p.second,
|
||||
alternate_count, alternate_glyphs); })
|
||||
;
|
||||
}
|
||||
|
||||
bool apply (hb_ot_apply_context_t *c) const
|
||||
{
|
||||
TRACE_APPLY (this);
|
||||
|
|
|
@ -100,6 +100,17 @@ struct SingleSubstFormat2_4
|
|||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
collect_glyph_alternates (hb_map_t *alternate_count /* IN/OUT */,
|
||||
hb_map_t *alternate_glyphs /* IN/OUT */) const
|
||||
{
|
||||
+ hb_zip (this+coverage, substitute)
|
||||
| hb_apply ([&] (const hb_pair_t<hb_codepoint_t, hb_codepoint_t> &p) -> void
|
||||
{ _hb_collect_glyph_alternates_add (p.first, p.second,
|
||||
alternate_count, alternate_glyphs); })
|
||||
;
|
||||
}
|
||||
|
||||
bool apply (hb_ot_apply_context_t *c) const
|
||||
{
|
||||
TRACE_APPLY (this);
|
||||
|
|
4
thirdparty/harfbuzz/src/OT/Layout/types.hh
vendored
4
thirdparty/harfbuzz/src/OT/Layout/types.hh
vendored
|
@ -29,8 +29,8 @@
|
|||
#ifndef OT_LAYOUT_TYPES_HH
|
||||
#define OT_LAYOUT_TYPES_HH
|
||||
|
||||
using hb_ot_lookup_cache_t = hb_cache_t<15, 8, 7>;
|
||||
static_assert (sizeof (hb_ot_lookup_cache_t) == 256, "");
|
||||
using hb_ot_layout_mapping_cache_t = hb_cache_t<15, 8, 7>;
|
||||
static_assert (sizeof (hb_ot_layout_mapping_cache_t) == 256, "");
|
||||
|
||||
namespace OT {
|
||||
namespace Layout {
|
||||
|
|
4
thirdparty/harfbuzz/src/OT/Var/VARC/VARC.cc
vendored
4
thirdparty/harfbuzz/src/OT/Var/VARC/VARC.cc
vendored
|
@ -11,6 +11,8 @@ namespace OT {
|
|||
//namespace Var {
|
||||
|
||||
|
||||
#ifndef HB_NO_DRAW
|
||||
|
||||
struct hb_transforming_pen_context_t
|
||||
{
|
||||
hb_transform_t<> transform;
|
||||
|
@ -411,6 +413,8 @@ VARC::get_path_at (const hb_varc_context_t &c,
|
|||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//} // namespace Var
|
||||
} // namespace OT
|
||||
|
||||
|
|
4
thirdparty/harfbuzz/src/OT/Var/VARC/VARC.hh
vendored
4
thirdparty/harfbuzz/src/OT/Var/VARC/VARC.hh
vendored
|
@ -194,6 +194,7 @@ struct VARC
|
|||
hb_codepoint_t gid,
|
||||
hb_glyph_extents_t *extents) const
|
||||
{
|
||||
#ifndef HB_NO_DRAW
|
||||
if (!table->has_data ()) return false;
|
||||
|
||||
hb_extents_t<> f_extents;
|
||||
|
@ -207,6 +208,9 @@ struct VARC
|
|||
*extents = f_extents.to_glyph_extents (font->x_scale < 0, font->y_scale < 0);
|
||||
|
||||
return ret;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
|
|
6
thirdparty/harfbuzz/src/OT/glyf/Glyph.hh
vendored
6
thirdparty/harfbuzz/src/OT/glyf/Glyph.hh
vendored
|
@ -533,7 +533,11 @@ struct Glyph
|
|||
bool get_extents_without_var_scaled (hb_font_t *font, const glyf_accelerator_t &glyf_accelerator,
|
||||
hb_glyph_extents_t *extents) const
|
||||
{
|
||||
if (type == EMPTY) return true; /* Empty glyph; zero extents. */
|
||||
if (type == EMPTY)
|
||||
{
|
||||
*extents = {0, 0, 0, 0};
|
||||
return true; /* Empty glyph; zero extents. */
|
||||
}
|
||||
return header->get_extents_without_var_scaled (font, glyf_accelerator, gid, extents);
|
||||
}
|
||||
|
||||
|
|
|
@ -189,7 +189,7 @@ struct SimpleGlyph
|
|||
|
||||
unsigned old_length = points.length;
|
||||
points.alloc (points.length + num_points + 4); // Allocate for phantom points, to avoid a possible copy
|
||||
if (unlikely (!points.resize (points.length + num_points, false))) return false;
|
||||
if (unlikely (!points.resize_dirty (points.length + num_points))) return false;
|
||||
auto points_ = points.as_array ().sub_array (old_length);
|
||||
if (!phantom_only)
|
||||
hb_memset (points_.arrayZ, 0, sizeof (contour_point_t) * num_points);
|
||||
|
|
9
thirdparty/harfbuzz/src/OT/glyf/glyf.hh
vendored
9
thirdparty/harfbuzz/src/OT/glyf/glyf.hh
vendored
|
@ -445,8 +445,7 @@ struct glyf_accelerator_t
|
|||
if (coords)
|
||||
{
|
||||
hb_glyf_scratch_t *scratch = acquire_scratch ();
|
||||
if (unlikely (!scratch))
|
||||
return false;
|
||||
if (unlikely (!scratch)) return false;
|
||||
bool ret = get_points (font,
|
||||
gid,
|
||||
points_aggregator_t (font, extents, nullptr, true),
|
||||
|
@ -493,8 +492,7 @@ struct glyf_accelerator_t
|
|||
if (!has_data ()) return false;
|
||||
|
||||
hb_glyf_scratch_t *scratch = acquire_scratch ();
|
||||
if (unlikely (!scratch))
|
||||
return true;
|
||||
if (unlikely (!scratch)) return true;
|
||||
|
||||
bool ret = get_points (font, gid, glyf_impl::path_builder_t (font, draw_session),
|
||||
hb_array (font->coords,
|
||||
|
@ -523,6 +521,7 @@ struct glyf_accelerator_t
|
|||
|
||||
hb_glyf_scratch_t *acquire_scratch () const
|
||||
{
|
||||
if (!has_data ()) return nullptr;
|
||||
hb_glyf_scratch_t *scratch = cached_scratch.get_acquire ();
|
||||
if (!scratch || unlikely (!cached_scratch.cmpexch (scratch, nullptr)))
|
||||
{
|
||||
|
@ -534,6 +533,8 @@ struct glyf_accelerator_t
|
|||
}
|
||||
void release_scratch (hb_glyf_scratch_t *scratch) const
|
||||
{
|
||||
if (!scratch)
|
||||
return;
|
||||
if (!cached_scratch.cmpexch (nullptr, scratch))
|
||||
{
|
||||
scratch->~hb_glyf_scratch_t ();
|
||||
|
|
207
thirdparty/harfbuzz/src/graph/graph.hh
vendored
207
thirdparty/harfbuzz/src/graph/graph.hh
vendored
|
@ -470,8 +470,12 @@ struct graph_t
|
|||
num_roots_for_space_.push (1);
|
||||
bool removed_nil = false;
|
||||
vertices_.alloc (objects.length);
|
||||
vertices_scratch_.alloc (objects.length);
|
||||
ordering_.resize (objects.length);
|
||||
ordering_scratch_.alloc (objects.length);
|
||||
|
||||
unsigned count = objects.length;
|
||||
unsigned order = objects.length;
|
||||
unsigned skip = 0;
|
||||
for (unsigned i = 0; i < count; i++)
|
||||
{
|
||||
// If this graph came from a serialization buffer object 0 is the
|
||||
|
@ -479,6 +483,9 @@ struct graph_t
|
|||
if (i == 0 && !objects.arrayZ[i])
|
||||
{
|
||||
removed_nil = true;
|
||||
order--;
|
||||
ordering_.resize(objects.length - 1);
|
||||
skip++;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -488,6 +495,12 @@ struct graph_t
|
|||
|
||||
check_success (v->link_positions_valid (count, removed_nil));
|
||||
|
||||
// To start we set the ordering to match the provided objects
|
||||
// list. Note: objects are provided to us in reverse order (ie.
|
||||
// the last object is the root).
|
||||
unsigned obj_idx = i - skip;
|
||||
ordering_[--order] = obj_idx;
|
||||
|
||||
if (!removed_nil) continue;
|
||||
// Fix indices to account for removed nil object.
|
||||
for (auto& l : v->obj.all_links_writer ()) {
|
||||
|
@ -508,10 +521,10 @@ struct graph_t
|
|||
}
|
||||
|
||||
void print () const {
|
||||
for (int i = vertices_.length - 1; i >= 0; i--)
|
||||
for (unsigned id : ordering_)
|
||||
{
|
||||
const auto& v = vertices_[i];
|
||||
printf("%d: %u [", i, (unsigned int)v.table_size());
|
||||
const auto& v = vertices_[id];
|
||||
printf("%u: %u [", id, (unsigned int)v.table_size());
|
||||
for (const auto &l : v.obj.real_links) {
|
||||
printf("%u, ", l.objidx);
|
||||
}
|
||||
|
@ -533,6 +546,7 @@ struct graph_t
|
|||
{
|
||||
return !successful ||
|
||||
vertices_.in_error () ||
|
||||
ordering_.in_error() ||
|
||||
num_roots_for_space_.in_error ();
|
||||
}
|
||||
|
||||
|
@ -543,10 +557,10 @@ struct graph_t
|
|||
|
||||
unsigned root_idx () const
|
||||
{
|
||||
// Object graphs are in reverse order, the first object is at the end
|
||||
// of the vector. Since the graph is topologically sorted it's safe to
|
||||
// First element of ordering_ is the root.
|
||||
// Since the graph is topologically sorted it's safe to
|
||||
// assume the first object has no incoming edges.
|
||||
return vertices_.length - 1;
|
||||
return ordering_[0];
|
||||
}
|
||||
|
||||
const hb_serialize_context_t::object_t& object (unsigned i) const
|
||||
|
@ -604,55 +618,51 @@ struct graph_t
|
|||
|
||||
hb_priority_queue_t<int64_t> queue;
|
||||
queue.alloc (vertices_.length);
|
||||
hb_vector_t<vertex_t> &sorted_graph = vertices_scratch_;
|
||||
if (unlikely (!check_success (sorted_graph.resize (vertices_.length)))) return;
|
||||
hb_vector_t<unsigned> id_map;
|
||||
if (unlikely (!check_success (id_map.resize (vertices_.length)))) return;
|
||||
hb_vector_t<unsigned> &new_ordering = ordering_scratch_;
|
||||
if (unlikely (!check_success (new_ordering.resize (vertices_.length)))) return;
|
||||
|
||||
hb_vector_t<unsigned> removed_edges;
|
||||
if (unlikely (!check_success (removed_edges.resize (vertices_.length)))) return;
|
||||
update_parents ();
|
||||
|
||||
queue.insert (root ().modified_distance (0), root_idx ());
|
||||
int new_id = root_idx ();
|
||||
unsigned order = 1;
|
||||
unsigned pos = 0;
|
||||
while (!queue.in_error () && !queue.is_empty ())
|
||||
{
|
||||
unsigned next_id = queue.pop_minimum().second;
|
||||
|
||||
sorted_graph[new_id] = std::move (vertices_[next_id]);
|
||||
const vertex_t& next = sorted_graph[new_id];
|
||||
|
||||
if (unlikely (!check_success(new_id >= 0))) {
|
||||
if (unlikely (!check_success(pos < new_ordering.length))) {
|
||||
// We are out of ids. Which means we've visited a node more than once.
|
||||
// This graph contains a cycle which is not allowed.
|
||||
DEBUG_MSG (SUBSET_REPACK, nullptr, "Invalid graph. Contains cycle.");
|
||||
return;
|
||||
}
|
||||
|
||||
id_map[next_id] = new_id--;
|
||||
new_ordering[pos++] = next_id;
|
||||
const vertex_t& next = vertices_[next_id];
|
||||
|
||||
for (const auto& link : next.obj.all_links ()) {
|
||||
removed_edges[link.objidx]++;
|
||||
if (!(vertices_[link.objidx].incoming_edges () - removed_edges[link.objidx]))
|
||||
const auto& v = vertices_[link.objidx];
|
||||
if (!(v.incoming_edges () - removed_edges[link.objidx]))
|
||||
// Add the order that the links were encountered to the priority.
|
||||
// This ensures that ties between priorities objects are broken in a consistent
|
||||
// way. More specifically this is set up so that if a set of objects have the same
|
||||
// distance they'll be added to the topological order in the order that they are
|
||||
// referenced from the parent object.
|
||||
queue.insert (vertices_[link.objidx].modified_distance (order++),
|
||||
queue.insert (v.modified_distance (order++),
|
||||
link.objidx);
|
||||
}
|
||||
}
|
||||
|
||||
check_success (!queue.in_error ());
|
||||
check_success (!sorted_graph.in_error ());
|
||||
check_success (!new_ordering.in_error ());
|
||||
|
||||
check_success (remap_all_obj_indices (id_map, &sorted_graph));
|
||||
vertices_ = std::move (sorted_graph);
|
||||
hb_swap (ordering_, new_ordering);
|
||||
|
||||
if (!check_success (new_id == -1))
|
||||
if (!check_success (pos == vertices_.length)) {
|
||||
print_orphaned_nodes ();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -662,8 +672,8 @@ struct graph_t
|
|||
*/
|
||||
void find_space_roots (hb_set_t& visited, hb_set_t& roots)
|
||||
{
|
||||
int root_index = (int) root_idx ();
|
||||
for (int i = root_index; i >= 0; i--)
|
||||
unsigned root_index = root_idx ();
|
||||
for (unsigned i : ordering_)
|
||||
{
|
||||
if (visited.has (i)) continue;
|
||||
|
||||
|
@ -846,7 +856,6 @@ struct graph_t
|
|||
if (subgraph.in_error ())
|
||||
return false;
|
||||
|
||||
unsigned original_root_idx = root_idx ();
|
||||
hb_map_t index_map;
|
||||
bool made_changes = false;
|
||||
for (auto entry : subgraph.iter ())
|
||||
|
@ -869,14 +878,6 @@ struct graph_t
|
|||
if (!made_changes)
|
||||
return false;
|
||||
|
||||
if (original_root_idx != root_idx ()
|
||||
&& parents.has (original_root_idx))
|
||||
{
|
||||
// If the root idx has changed since parents was determined, update root idx in parents
|
||||
parents.add (root_idx ());
|
||||
parents.del (original_root_idx);
|
||||
}
|
||||
|
||||
auto new_subgraph =
|
||||
+ subgraph.keys ()
|
||||
| hb_map([&] (uint32_t node_idx) {
|
||||
|
@ -965,9 +966,9 @@ struct graph_t
|
|||
*/
|
||||
template<typename O>
|
||||
unsigned move_child (unsigned old_parent_idx,
|
||||
const O* old_offset,
|
||||
unsigned new_parent_idx,
|
||||
const O* new_offset)
|
||||
const O* old_offset,
|
||||
unsigned new_parent_idx,
|
||||
const O* new_offset)
|
||||
{
|
||||
distance_invalid = true;
|
||||
positions_invalid = true;
|
||||
|
@ -992,6 +993,50 @@ struct graph_t
|
|||
return child_id;
|
||||
}
|
||||
|
||||
/*
|
||||
* Moves all outgoing links in old parent that have
|
||||
* a link position between [old_post_start, old_pos_end)
|
||||
* to the new parent. Links are placed serially in the new
|
||||
* parent starting at new_pos_start.
|
||||
*/
|
||||
template<typename O>
|
||||
void move_children (unsigned old_parent_idx,
|
||||
unsigned old_pos_start,
|
||||
unsigned old_pos_end,
|
||||
unsigned new_parent_idx,
|
||||
unsigned new_pos_start)
|
||||
{
|
||||
distance_invalid = true;
|
||||
positions_invalid = true;
|
||||
|
||||
auto& old_v = vertices_[old_parent_idx];
|
||||
auto& new_v = vertices_[new_parent_idx];
|
||||
|
||||
hb_vector_t<hb_serialize_context_t::object_t::link_t> old_links;
|
||||
for (const auto& l : old_v.obj.real_links)
|
||||
{
|
||||
if (l.position < old_pos_start || l.position >= old_pos_end)
|
||||
{
|
||||
old_links.push(l);
|
||||
continue;
|
||||
}
|
||||
|
||||
unsigned array_pos = l.position - old_pos_start;
|
||||
|
||||
unsigned child_id = l.objidx;
|
||||
auto* new_link = new_v.obj.real_links.push ();
|
||||
new_link->width = O::static_size;
|
||||
new_link->objidx = child_id;
|
||||
new_link->position = new_pos_start + array_pos;
|
||||
|
||||
auto& child = vertices_[child_id];
|
||||
child.add_parent (new_parent_idx, false);
|
||||
child.remove_parent (old_parent_idx);
|
||||
}
|
||||
|
||||
old_v.obj.real_links = std::move (old_links);
|
||||
}
|
||||
|
||||
/*
|
||||
* duplicates all nodes in the subgraph reachable from node_idx. Does not re-assign
|
||||
* links. index_map is updated with mappings from old id to new id. If a duplication has already
|
||||
|
@ -1021,8 +1066,11 @@ struct graph_t
|
|||
distance_invalid = true;
|
||||
|
||||
auto* clone = vertices_.push ();
|
||||
unsigned clone_idx = vertices_.length - 1;
|
||||
ordering_.push(clone_idx);
|
||||
|
||||
auto& child = vertices_[node_idx];
|
||||
if (vertices_.in_error ()) {
|
||||
if (vertices_.in_error () || ordering_.in_error()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -1032,7 +1080,6 @@ struct graph_t
|
|||
clone->space = child.space;
|
||||
clone->reset_parents ();
|
||||
|
||||
unsigned clone_idx = vertices_.length - 2;
|
||||
for (const auto& l : child.obj.real_links)
|
||||
{
|
||||
clone->obj.real_links.push (l);
|
||||
|
@ -1047,15 +1094,6 @@ struct graph_t
|
|||
check_success (!clone->obj.real_links.in_error ());
|
||||
check_success (!clone->obj.virtual_links.in_error ());
|
||||
|
||||
// The last object is the root of the graph, so swap back the root to the end.
|
||||
// The root's obj idx does change, however since it's root nothing else refers to it.
|
||||
// all other obj idx's will be unaffected.
|
||||
hb_swap (vertices_[vertices_.length - 2], *clone);
|
||||
|
||||
// Since the root moved, update the parents arrays of all children on the root.
|
||||
for (const auto& l : root ().obj.all_links ())
|
||||
vertices_[l.objidx].remap_parent (root_idx () - 1, root_idx ());
|
||||
|
||||
return clone_idx;
|
||||
}
|
||||
|
||||
|
@ -1205,7 +1243,10 @@ struct graph_t
|
|||
distance_invalid = true;
|
||||
|
||||
auto* clone = vertices_.push ();
|
||||
if (vertices_.in_error ()) {
|
||||
unsigned clone_idx = vertices_.length - 1;
|
||||
ordering_.push(clone_idx);
|
||||
|
||||
if (vertices_.in_error () || ordering_.in_error()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -1214,17 +1255,6 @@ struct graph_t
|
|||
clone->distance = 0;
|
||||
clone->space = 0;
|
||||
|
||||
unsigned clone_idx = vertices_.length - 2;
|
||||
|
||||
// The last object is the root of the graph, so swap back the root to the end.
|
||||
// The root's obj idx does change, however since it's root nothing else refers to it.
|
||||
// all other obj idx's will be unaffected.
|
||||
hb_swap (vertices_[vertices_.length - 2], *clone);
|
||||
|
||||
// Since the root moved, update the parents arrays of all children on the root.
|
||||
for (const auto& l : root ().obj.all_links ())
|
||||
vertices_[l.objidx].remap_parent (root_idx () - 1, root_idx ());
|
||||
|
||||
return clone_idx;
|
||||
}
|
||||
|
||||
|
@ -1386,7 +1416,8 @@ struct graph_t
|
|||
size_t total_size = 0;
|
||||
unsigned count = vertices_.length;
|
||||
for (unsigned i = 0; i < count; i++) {
|
||||
size_t size = vertices_.arrayZ[i].obj.tail - vertices_.arrayZ[i].obj.head;
|
||||
const auto& obj = vertices_.arrayZ[i].obj;
|
||||
size_t size = obj.tail - obj.head;
|
||||
total_size += size;
|
||||
}
|
||||
return total_size;
|
||||
|
@ -1459,7 +1490,7 @@ struct graph_t
|
|||
if (!positions_invalid) return;
|
||||
|
||||
unsigned current_pos = 0;
|
||||
for (int i = root_idx (); i >= 0; i--)
|
||||
for (unsigned i : ordering_)
|
||||
{
|
||||
auto& v = vertices_[i];
|
||||
v.start = current_pos;
|
||||
|
@ -1491,11 +1522,11 @@ struct graph_t
|
|||
unsigned count = vertices_.length;
|
||||
for (unsigned i = 0; i < count; i++)
|
||||
vertices_.arrayZ[i].distance = hb_int_max (int64_t);
|
||||
vertices_.tail ().distance = 0;
|
||||
vertices_[root_idx ()].distance = 0;
|
||||
|
||||
hb_priority_queue_t<int64_t> queue;
|
||||
queue.alloc (count);
|
||||
queue.insert (0, vertices_.length - 1);
|
||||
queue.insert (0, root_idx ());
|
||||
|
||||
hb_vector_t<bool> visited;
|
||||
visited.resize (vertices_.length);
|
||||
|
@ -1505,22 +1536,23 @@ struct graph_t
|
|||
unsigned next_idx = queue.pop_minimum ().second;
|
||||
if (visited[next_idx]) continue;
|
||||
const auto& next = vertices_[next_idx];
|
||||
int64_t next_distance = vertices_[next_idx].distance;
|
||||
int64_t next_distance = next.distance;
|
||||
visited[next_idx] = true;
|
||||
|
||||
for (const auto& link : next.obj.all_links ())
|
||||
{
|
||||
if (visited[link.objidx]) continue;
|
||||
|
||||
const auto& child = vertices_.arrayZ[link.objidx].obj;
|
||||
auto& child_v = vertices_.arrayZ[link.objidx];
|
||||
const auto& child = child_v.obj;
|
||||
unsigned link_width = link.width ? link.width : 4; // treat virtual offsets as 32 bits wide
|
||||
int64_t child_weight = (child.tail - child.head) +
|
||||
((int64_t) 1 << (link_width * 8)) * (vertices_.arrayZ[link.objidx].space + 1);
|
||||
((int64_t) 1 << (link_width * 8)) * (child_v.space + 1);
|
||||
int64_t child_distance = next_distance + child_weight;
|
||||
|
||||
if (child_distance < vertices_.arrayZ[link.objidx].distance)
|
||||
if (child_distance < child_v.distance)
|
||||
{
|
||||
vertices_.arrayZ[link.objidx].distance = child_distance;
|
||||
child_v.distance = child_distance;
|
||||
queue.insert (child_distance, link.objidx);
|
||||
}
|
||||
}
|
||||
|
@ -1563,9 +1595,10 @@ struct graph_t
|
|||
if (!id_map) return;
|
||||
for (unsigned i : subgraph)
|
||||
{
|
||||
unsigned num_real = vertices_[i].obj.real_links.length;
|
||||
auto& obj = vertices_[i].obj;
|
||||
unsigned num_real = obj.real_links.length;
|
||||
unsigned count = 0;
|
||||
for (auto& link : vertices_[i].obj.all_links_writer ())
|
||||
for (auto& link : obj.all_links_writer ())
|
||||
{
|
||||
count++;
|
||||
const uint32_t *v;
|
||||
|
@ -1577,25 +1610,6 @@ struct graph_t
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Updates all objidx's in all links using the provided mapping.
|
||||
*/
|
||||
bool remap_all_obj_indices (const hb_vector_t<unsigned>& id_map,
|
||||
hb_vector_t<vertex_t>* sorted_graph) const
|
||||
{
|
||||
unsigned count = sorted_graph->length;
|
||||
for (unsigned i = 0; i < count; i++)
|
||||
{
|
||||
if (!(*sorted_graph)[i].remap_parents (id_map))
|
||||
return false;
|
||||
for (auto& link : sorted_graph->arrayZ[i].obj.all_links_writer ())
|
||||
{
|
||||
link.objidx = id_map[link.objidx];
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Finds all nodes in targets that are reachable from start_idx, nodes in visited will be skipped.
|
||||
* For this search the graph is treated as being undirected.
|
||||
|
@ -1631,7 +1645,16 @@ struct graph_t
|
|||
public:
|
||||
// TODO(garretrieger): make private, will need to move most of offset overflow code into graph.
|
||||
hb_vector_t<vertex_t> vertices_;
|
||||
hb_vector_t<vertex_t> vertices_scratch_;
|
||||
|
||||
// Specifies the current topological ordering of this graph
|
||||
//
|
||||
// ordering_[pos] = obj index
|
||||
//
|
||||
// specifies that the 'pos'th spot is filled by the object
|
||||
// given by obj index.
|
||||
hb_vector_t<unsigned> ordering_;
|
||||
hb_vector_t<unsigned> ordering_scratch_;
|
||||
|
||||
private:
|
||||
bool parents_invalid;
|
||||
bool distance_invalid;
|
||||
|
|
|
@ -87,6 +87,12 @@ struct Lookup : public OT::Lookup
|
|||
return lookupType == extension_type (table_tag);
|
||||
}
|
||||
|
||||
bool use_mark_filtering_set () const
|
||||
{
|
||||
unsigned flag = lookupFlag;
|
||||
return flag & 0x0010u;
|
||||
}
|
||||
|
||||
bool make_extension (gsubgpos_graph_context_t& c,
|
||||
unsigned this_index)
|
||||
{
|
||||
|
@ -220,6 +226,9 @@ struct Lookup : public OT::Lookup
|
|||
}
|
||||
hb_memcpy (buffer, v->obj.head, v->table_size());
|
||||
|
||||
if (use_mark_filtering_set ())
|
||||
hb_memcpy (buffer + new_size - 2, v->obj.tail - 2, 2);
|
||||
|
||||
v->obj.head = buffer;
|
||||
v->obj.tail = buffer + new_size;
|
||||
|
||||
|
|
53
thirdparty/harfbuzz/src/graph/ligature-graph.hh
vendored
53
thirdparty/harfbuzz/src/graph/ligature-graph.hh
vendored
|
@ -105,6 +105,23 @@ struct LigatureSubstFormat1 : public OT::Layout::GSUB_impl::LigatureSubstFormat1
|
|||
return result;
|
||||
}
|
||||
|
||||
hb_vector_t<unsigned> ligature_index_to_object_id(const graph_t::vertex_and_table_t<LigatureSet>& liga_set) const {
|
||||
hb_vector_t<unsigned> map;
|
||||
map.resize_exact(liga_set.table->ligature.len);
|
||||
if (map.in_error()) return map;
|
||||
|
||||
for (unsigned i = 0; i < map.length; i++) {
|
||||
map[i] = (unsigned) -1;
|
||||
}
|
||||
|
||||
for (const auto& l : liga_set.vertex->obj.real_links) {
|
||||
if (l.position < 2) continue;
|
||||
unsigned array_index = (l.position - 2) / 2;
|
||||
map[array_index] = l.objidx;
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
hb_vector_t<unsigned> compute_split_points(gsubgpos_graph_context_t& c,
|
||||
unsigned parent_index,
|
||||
unsigned this_index) const
|
||||
|
@ -128,9 +145,16 @@ struct LigatureSubstFormat1 : public OT::Layout::GSUB_impl::LigatureSubstFormat1
|
|||
return hb_vector_t<unsigned> {};
|
||||
}
|
||||
|
||||
// Finding the object id associated with an array index is O(n)
|
||||
// so to avoid O(n^2), precompute the mapping by scanning through
|
||||
// all links
|
||||
auto index_to_id = ligature_index_to_object_id(liga_set);
|
||||
if (index_to_id.in_error()) return hb_vector_t<unsigned>();
|
||||
|
||||
for (unsigned j = 0; j < liga_set.table->ligature.len; j++)
|
||||
{
|
||||
const unsigned liga_id = c.graph.index_for_offset (liga_set.index, &liga_set.table->ligature[j]);
|
||||
const unsigned liga_id = index_to_id[j];
|
||||
if (liga_id == (unsigned) -1) continue; // no outgoing link, ignore
|
||||
const unsigned liga_size = c.graph.vertices_[liga_id].table_size ();
|
||||
|
||||
accumulated += OT::HBUINT16::static_size; // for ligature offset
|
||||
|
@ -154,7 +178,6 @@ struct LigatureSubstFormat1 : public OT::Layout::GSUB_impl::LigatureSubstFormat1
|
|||
return split_points;
|
||||
}
|
||||
|
||||
|
||||
struct split_context_t
|
||||
{
|
||||
gsubgpos_graph_context_t& c;
|
||||
|
@ -323,19 +346,19 @@ struct LigatureSubstFormat1 : public OT::Layout::GSUB_impl::LigatureSubstFormat1
|
|||
{
|
||||
// This liga set partially overlaps [start, end). We'll need to create
|
||||
// a new liga set sub table and move the intersecting ligas to it.
|
||||
unsigned liga_count = hb_min(end, current_end) - hb_max(start, current_start);
|
||||
unsigned start_index = hb_max(start, current_start) - count;
|
||||
unsigned end_index = hb_min(end, current_end) - count;
|
||||
unsigned liga_count = end_index - start_index;
|
||||
auto result = new_liga_set(c, liga_count);
|
||||
liga_set_prime_id = result.first;
|
||||
LigatureSet* prime = result.second;
|
||||
if (liga_set_prime_id == (unsigned) -1) return -1;
|
||||
|
||||
unsigned new_index = 0;
|
||||
for (unsigned j = hb_max(start, current_start) - count; j < hb_min(end, current_end) - count; j++) {
|
||||
c.graph.move_child<> (liga_set_index,
|
||||
&liga_set.table->ligature[j],
|
||||
liga_set_prime_id,
|
||||
&prime->ligature[new_index++]);
|
||||
}
|
||||
c.graph.move_children<OT::Offset16>(
|
||||
liga_set_index,
|
||||
2 + start_index * 2,
|
||||
2 + end_index * 2,
|
||||
liga_set_prime_id,
|
||||
2);
|
||||
|
||||
liga_set_end = i;
|
||||
if (i < liga_set_start) liga_set_start = i;
|
||||
|
@ -392,8 +415,12 @@ struct LigatureSubstFormat1 : public OT::Layout::GSUB_impl::LigatureSubstFormat1
|
|||
// duplicated. Code later on will re-add the virtual links as needed (via retained_indices).
|
||||
clear_virtual_links(c, liga_set.index);
|
||||
retained_indices.add(liga_set.index);
|
||||
for (const auto& liga_offset : liga_set.table->ligature) {
|
||||
unsigned liga_index = c.graph.index_for_offset(liga_set.index, &liga_offset);
|
||||
|
||||
auto index_to_id = ligature_index_to_object_id(liga_set);
|
||||
if (index_to_id.in_error()) return false;
|
||||
|
||||
for (unsigned i = 0; i < liga_set.table->ligature.len; i++) {
|
||||
unsigned liga_index = index_to_id[i];
|
||||
if (liga_index != (unsigned) -1) {
|
||||
clear_virtual_links(c, liga_index);
|
||||
retained_indices.add(liga_index);
|
||||
|
|
41
thirdparty/harfbuzz/src/graph/serialize.hh
vendored
41
thirdparty/harfbuzz/src/graph/serialize.hh
vendored
|
@ -113,7 +113,7 @@ will_overflow (graph_t& graph,
|
|||
|
||||
hb_hashmap_t<overflow_record_t*, bool> record_set;
|
||||
const auto& vertices = graph.vertices_;
|
||||
for (int parent_idx = vertices.length - 1; parent_idx >= 0; parent_idx--)
|
||||
for (unsigned parent_idx : graph.ordering_)
|
||||
{
|
||||
// Don't need to check virtual links for overflow
|
||||
for (const auto& link : vertices.arrayZ[parent_idx].obj.real_links)
|
||||
|
@ -173,6 +173,7 @@ template <typename O> inline void
|
|||
serialize_link_of_type (const hb_serialize_context_t::object_t::link_t& link,
|
||||
char* head,
|
||||
unsigned size,
|
||||
const hb_vector_t<unsigned>& id_map,
|
||||
hb_serialize_context_t* c)
|
||||
{
|
||||
assert(link.position + link.width <= size);
|
||||
|
@ -180,9 +181,7 @@ serialize_link_of_type (const hb_serialize_context_t::object_t::link_t& link,
|
|||
OT::Offset<O>* offset = reinterpret_cast<OT::Offset<O>*> (head + link.position);
|
||||
*offset = 0;
|
||||
c->add_link (*offset,
|
||||
// serializer has an extra nil object at the start of the
|
||||
// object array. So all id's are +1 of what our id's are.
|
||||
link.objidx + 1,
|
||||
id_map[link.objidx],
|
||||
(hb_serialize_context_t::whence_t) link.whence,
|
||||
link.bias);
|
||||
}
|
||||
|
@ -191,6 +190,7 @@ inline
|
|||
void serialize_link (const hb_serialize_context_t::object_t::link_t& link,
|
||||
char* head,
|
||||
unsigned size,
|
||||
const hb_vector_t<unsigned>& id_map,
|
||||
hb_serialize_context_t* c)
|
||||
{
|
||||
switch (link.width)
|
||||
|
@ -201,21 +201,21 @@ void serialize_link (const hb_serialize_context_t::object_t::link_t& link,
|
|||
case 4:
|
||||
if (link.is_signed)
|
||||
{
|
||||
serialize_link_of_type<OT::HBINT32> (link, head, size, c);
|
||||
serialize_link_of_type<OT::HBINT32> (link, head, size, id_map, c);
|
||||
} else {
|
||||
serialize_link_of_type<OT::HBUINT32> (link, head, size, c);
|
||||
serialize_link_of_type<OT::HBUINT32> (link, head, size, id_map, c);
|
||||
}
|
||||
return;
|
||||
case 2:
|
||||
if (link.is_signed)
|
||||
{
|
||||
serialize_link_of_type<OT::HBINT16> (link, head, size, c);
|
||||
serialize_link_of_type<OT::HBINT16> (link, head, size, id_map, c);
|
||||
} else {
|
||||
serialize_link_of_type<OT::HBUINT16> (link, head, size, c);
|
||||
serialize_link_of_type<OT::HBUINT16> (link, head, size, id_map, c);
|
||||
}
|
||||
return;
|
||||
case 3:
|
||||
serialize_link_of_type<OT::HBUINT24> (link, head, size, c);
|
||||
serialize_link_of_type<OT::HBUINT24> (link, head, size, id_map, c);
|
||||
return;
|
||||
default:
|
||||
// Unexpected link width.
|
||||
|
@ -241,25 +241,36 @@ inline hb_blob_t* serialize (const graph_t& graph)
|
|||
|
||||
c.start_serialize<void> ();
|
||||
const auto& vertices = graph.vertices_;
|
||||
for (unsigned i = 0; i < vertices.length; i++) {
|
||||
|
||||
// Objects are placed in the serializer in reverse order since children need
|
||||
// to be inserted before their parents.
|
||||
|
||||
// Maps from our obj id's to the id's used during this serialization.
|
||||
hb_vector_t<unsigned> id_map;
|
||||
id_map.resize(graph.ordering_.length);
|
||||
for (int pos = graph.ordering_.length - 1; pos >= 0; pos--) {
|
||||
unsigned i = graph.ordering_[pos];
|
||||
c.push ();
|
||||
|
||||
size_t size = vertices[i].obj.tail - vertices[i].obj.head;
|
||||
auto& v = vertices[i];
|
||||
|
||||
size_t size = v.obj.tail - v.obj.head;
|
||||
|
||||
char* start = c.allocate_size <char> (size);
|
||||
if (!start) {
|
||||
DEBUG_MSG (SUBSET_REPACK, nullptr, "Buffer out of space.");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
hb_memcpy (start, vertices[i].obj.head, size);
|
||||
hb_memcpy (start, v.obj.head, size);
|
||||
|
||||
// Only real links needs to be serialized.
|
||||
for (const auto& link : vertices[i].obj.real_links)
|
||||
serialize_link (link, start, size, &c);
|
||||
for (const auto& link : v.obj.real_links)
|
||||
serialize_link (link, start, size, id_map, &c);
|
||||
|
||||
// All duplications are already encoded in the graph, so don't
|
||||
// enable sharing during packing.
|
||||
c.pop_pack (false);
|
||||
id_map[i] = c.pop_pack (false);
|
||||
}
|
||||
c.end_serialize ();
|
||||
|
||||
|
|
50
thirdparty/harfbuzz/src/hb-aat-layout-common.hh
vendored
50
thirdparty/harfbuzz/src/hb-aat-layout-common.hh
vendored
|
@ -47,8 +47,7 @@ using namespace OT;
|
|||
|
||||
struct ankr;
|
||||
|
||||
using hb_aat_class_cache_t = hb_cache_t<15, 8, 7>;
|
||||
static_assert (sizeof (hb_aat_class_cache_t) == 256, "");
|
||||
using hb_aat_class_cache_t = hb_ot_layout_mapping_cache_t;
|
||||
|
||||
struct hb_aat_scratch_t
|
||||
{
|
||||
|
@ -79,7 +78,10 @@ struct hb_aat_scratch_t
|
|||
{
|
||||
hb_bit_set_t *s = buffer_glyph_set.get_acquire ();
|
||||
if (s && buffer_glyph_set.cmpexch (s, nullptr))
|
||||
{
|
||||
s->clear ();
|
||||
return s;
|
||||
}
|
||||
|
||||
s = (hb_bit_set_t *) hb_calloc (1, sizeof (hb_bit_set_t));
|
||||
if (unlikely (!s))
|
||||
|
@ -124,13 +126,14 @@ struct hb_aat_apply_context_t :
|
|||
const OT::GDEF &gdef;
|
||||
bool has_glyph_classes;
|
||||
const hb_sorted_vector_t<hb_aat_map_t::range_flags_t> *range_flags = nullptr;
|
||||
hb_mask_t subtable_flags = 0;
|
||||
bool buffer_is_reversed = false;
|
||||
// Caches
|
||||
bool using_buffer_glyph_set = false;
|
||||
hb_bit_set_t *buffer_glyph_set = nullptr;
|
||||
const hb_bit_set_t *left_set = nullptr;
|
||||
const hb_bit_set_t *right_set = nullptr;
|
||||
const hb_bit_set_t *machine_glyph_set = nullptr;
|
||||
const hb_bit_set_t *first_set = nullptr;
|
||||
const hb_bit_set_t *second_set = nullptr;
|
||||
hb_aat_class_cache_t *machine_class_cache = nullptr;
|
||||
hb_mask_t subtable_flags = 0;
|
||||
|
||||
/* Unused. For debug tracing only. */
|
||||
unsigned int lookup_index;
|
||||
|
@ -146,6 +149,12 @@ struct hb_aat_apply_context_t :
|
|||
|
||||
void set_lookup_index (unsigned int i) { lookup_index = i; }
|
||||
|
||||
void reverse_buffer ()
|
||||
{
|
||||
buffer->reverse ();
|
||||
buffer_is_reversed = !buffer_is_reversed;
|
||||
}
|
||||
|
||||
void setup_buffer_glyph_set ()
|
||||
{
|
||||
using_buffer_glyph_set = buffer->len >= 4 && buffer_glyph_set;
|
||||
|
@ -156,11 +165,11 @@ struct hb_aat_apply_context_t :
|
|||
bool buffer_intersects_machine () const
|
||||
{
|
||||
if (likely (using_buffer_glyph_set))
|
||||
return buffer_glyph_set->intersects (*machine_glyph_set);
|
||||
return buffer_glyph_set->intersects (*first_set);
|
||||
|
||||
// Faster for shorter buffers.
|
||||
for (unsigned i = 0; i < buffer->len; i++)
|
||||
if (machine_glyph_set->has (buffer->info[i].codepoint))
|
||||
if (first_set->has (buffer->info[i].codepoint))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
@ -639,6 +648,23 @@ struct LookupFormat10
|
|||
glyphs.add_range (firstGlyph, firstGlyph + glyphCount - 1);
|
||||
}
|
||||
|
||||
template <typename set_t, typename filter_t>
|
||||
void collect_glyphs_filtered (set_t &glyphs, const filter_t &filter) const
|
||||
{
|
||||
if (unlikely (!glyphCount)) return;
|
||||
if (firstGlyph == DELETED_GLYPH) return;
|
||||
const HBUINT8 *p = valueArrayZ.arrayZ;
|
||||
for (unsigned i = 0; i < glyphCount; i++)
|
||||
{
|
||||
unsigned int v = 0;
|
||||
unsigned int count = valueSize;
|
||||
for (unsigned int j = 0; j < count; j++)
|
||||
v = (v << 8) | *p++;
|
||||
if (filter (v))
|
||||
glyphs.add (firstGlyph + i);
|
||||
}
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
|
@ -709,6 +735,7 @@ struct Lookup
|
|||
case 4: hb_barrier (); u.format4.collect_glyphs_filtered (glyphs, filter); return;
|
||||
case 6: hb_barrier (); u.format6.collect_glyphs_filtered (glyphs, filter); return;
|
||||
case 8: hb_barrier (); u.format8.collect_glyphs_filtered (glyphs, filter); return;
|
||||
case 10: hb_barrier (); u.format10.collect_glyphs_filtered (glyphs, filter); return;
|
||||
default:return;
|
||||
}
|
||||
}
|
||||
|
@ -838,11 +865,6 @@ struct StateTable
|
|||
STATE_START_OF_LINE = 1,
|
||||
};
|
||||
|
||||
template <typename set_t>
|
||||
void collect_glyphs (set_t &glyphs, unsigned num_glyphs) const
|
||||
{
|
||||
(this+classTable).collect_glyphs (glyphs, num_glyphs);
|
||||
}
|
||||
template <typename set_t, typename table_t>
|
||||
void collect_initial_glyphs (set_t &glyphs, unsigned num_glyphs, const table_t &table) const
|
||||
{
|
||||
|
@ -1082,6 +1104,8 @@ struct SubtableGlyphCoverage
|
|||
for (unsigned i = 0; i < subtable_count; i++)
|
||||
{
|
||||
uint32_t offset = (uint32_t) subtableOffsets[i];
|
||||
// A font file called SFNSDisplay.ttf has value 0xFFFFFFFF in the offsets.
|
||||
// Just ignore it.
|
||||
if (offset == 0 || offset == 0xFFFFFFFF)
|
||||
continue;
|
||||
if (unlikely (!subtableOffsets[i].sanitize (c, this, bytes)))
|
||||
|
|
|
@ -120,12 +120,12 @@ struct KerxSubTableFormat0
|
|||
}
|
||||
|
||||
template <typename set_t>
|
||||
void collect_glyphs (set_t &left_set, set_t &right_set, unsigned num_glyphs) const
|
||||
void collect_glyphs (set_t &first_set, set_t &second_set, unsigned num_glyphs) const
|
||||
{
|
||||
for (const KernPair& pair : pairs)
|
||||
{
|
||||
left_set.add (pair.left);
|
||||
right_set.add (pair.right);
|
||||
first_set.add (pair.left);
|
||||
second_set.add (pair.right);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -140,7 +140,7 @@ struct KerxSubTableFormat0
|
|||
|
||||
int get_kerning (hb_codepoint_t left, hb_codepoint_t right) const
|
||||
{
|
||||
if (!(*c->left_set)[left] || !(*c->right_set)[right]) return 0;
|
||||
if (!(*c->first_set)[left] || !(*c->second_set)[right]) return 0;
|
||||
return table.get_kerning (left, right, c);
|
||||
}
|
||||
};
|
||||
|
@ -396,10 +396,10 @@ struct KerxSubTableFormat1
|
|||
}
|
||||
|
||||
template <typename set_t>
|
||||
void collect_glyphs (set_t &left_set, set_t &right_set, unsigned num_glyphs) const
|
||||
void collect_glyphs (set_t &first_set, set_t &second_set, unsigned num_glyphs) const
|
||||
{
|
||||
machine.collect_initial_glyphs (left_set, num_glyphs, *this);
|
||||
//machine.collect_glyphs (right_set, num_glyphs); // right_set is unused for machine kerning
|
||||
machine.collect_initial_glyphs (first_set, num_glyphs, *this);
|
||||
//machine.collect_glyphs (second_set, num_glyphs); // second_set is unused for machine kerning
|
||||
}
|
||||
|
||||
protected:
|
||||
|
@ -451,10 +451,10 @@ struct KerxSubTableFormat2
|
|||
}
|
||||
|
||||
template <typename set_t>
|
||||
void collect_glyphs (set_t &left_set, set_t &right_set, unsigned num_glyphs) const
|
||||
void collect_glyphs (set_t &first_set, set_t &second_set, unsigned num_glyphs) const
|
||||
{
|
||||
(this+leftClassTable).collect_glyphs (left_set, num_glyphs);
|
||||
(this+rightClassTable).collect_glyphs (right_set, num_glyphs);
|
||||
(this+leftClassTable).collect_glyphs (first_set, num_glyphs);
|
||||
(this+rightClassTable).collect_glyphs (second_set, num_glyphs);
|
||||
}
|
||||
|
||||
struct accelerator_t
|
||||
|
@ -468,7 +468,7 @@ struct KerxSubTableFormat2
|
|||
|
||||
int get_kerning (hb_codepoint_t left, hb_codepoint_t right) const
|
||||
{
|
||||
if (!(*c->left_set)[left] || !(*c->right_set)[right]) return 0;
|
||||
if (!(*c->first_set)[left] || !(*c->second_set)[right]) return 0;
|
||||
return table.get_kerning (left, right, c);
|
||||
}
|
||||
};
|
||||
|
@ -629,6 +629,8 @@ struct KerxSubTableFormat4
|
|||
}
|
||||
o.attach_type() = OT::Layout::GPOS_impl::ATTACH_TYPE_MARK;
|
||||
o.attach_chain() = (int) mark - (int) buffer->idx;
|
||||
if (c->buffer_is_reversed)
|
||||
o.attach_chain() = -o.attach_chain();
|
||||
buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT;
|
||||
}
|
||||
|
||||
|
@ -671,10 +673,10 @@ struct KerxSubTableFormat4
|
|||
}
|
||||
|
||||
template <typename set_t>
|
||||
void collect_glyphs (set_t &left_set, set_t &right_set, unsigned num_glyphs) const
|
||||
void collect_glyphs (set_t &first_set, set_t &second_set, unsigned num_glyphs) const
|
||||
{
|
||||
machine.collect_initial_glyphs (left_set, num_glyphs, *this);
|
||||
//machine.collect_glyphs (right_set, num_glyphs); // right_set is unused for machine kerning
|
||||
machine.collect_initial_glyphs (first_set, num_glyphs, *this);
|
||||
//machine.collect_glyphs (second_set, num_glyphs); // second_set is unused for machine kerning
|
||||
}
|
||||
|
||||
protected:
|
||||
|
@ -762,19 +764,19 @@ struct KerxSubTableFormat6
|
|||
}
|
||||
|
||||
template <typename set_t>
|
||||
void collect_glyphs (set_t &left_set, set_t &right_set, unsigned num_glyphs) const
|
||||
void collect_glyphs (set_t &first_set, set_t &second_set, unsigned num_glyphs) const
|
||||
{
|
||||
if (is_long ())
|
||||
{
|
||||
const auto &t = u.l;
|
||||
(this+t.rowIndexTable).collect_glyphs (left_set, num_glyphs);
|
||||
(this+t.columnIndexTable).collect_glyphs (right_set, num_glyphs);
|
||||
(this+t.rowIndexTable).collect_glyphs (first_set, num_glyphs);
|
||||
(this+t.columnIndexTable).collect_glyphs (second_set, num_glyphs);
|
||||
}
|
||||
else
|
||||
{
|
||||
const auto &t = u.s;
|
||||
(this+t.rowIndexTable).collect_glyphs (left_set, num_glyphs);
|
||||
(this+t.columnIndexTable).collect_glyphs (right_set, num_glyphs);
|
||||
(this+t.rowIndexTable).collect_glyphs (first_set, num_glyphs);
|
||||
(this+t.columnIndexTable).collect_glyphs (second_set, num_glyphs);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -789,7 +791,7 @@ struct KerxSubTableFormat6
|
|||
|
||||
int get_kerning (hb_codepoint_t left, hb_codepoint_t right) const
|
||||
{
|
||||
if (!(*c->left_set)[left] || !(*c->right_set)[right]) return 0;
|
||||
if (!(*c->first_set)[left] || !(*c->second_set)[right]) return 0;
|
||||
return table.get_kerning (left, right, c);
|
||||
}
|
||||
};
|
||||
|
@ -878,15 +880,15 @@ struct KerxSubTable
|
|||
}
|
||||
|
||||
template <typename set_t>
|
||||
void collect_glyphs (set_t &left_set, set_t &right_set, unsigned num_glyphs) const
|
||||
void collect_glyphs (set_t &first_set, set_t &second_set, unsigned num_glyphs) const
|
||||
{
|
||||
unsigned int subtable_type = get_type ();
|
||||
switch (subtable_type) {
|
||||
case 0: u.format0.collect_glyphs (left_set, right_set, num_glyphs); return;
|
||||
case 1: u.format1.collect_glyphs (left_set, right_set, num_glyphs); return;
|
||||
case 2: u.format2.collect_glyphs (left_set, right_set, num_glyphs); return;
|
||||
case 4: u.format4.collect_glyphs (left_set, right_set, num_glyphs); return;
|
||||
case 6: u.format6.collect_glyphs (left_set, right_set, num_glyphs); return;
|
||||
case 0: u.format0.collect_glyphs (first_set, second_set, num_glyphs); return;
|
||||
case 1: u.format1.collect_glyphs (first_set, second_set, num_glyphs); return;
|
||||
case 2: u.format2.collect_glyphs (first_set, second_set, num_glyphs); return;
|
||||
case 4: u.format4.collect_glyphs (first_set, second_set, num_glyphs); return;
|
||||
case 6: u.format6.collect_glyphs (first_set, second_set, num_glyphs); return;
|
||||
default: return;
|
||||
}
|
||||
}
|
||||
|
@ -923,8 +925,8 @@ struct KerxSubTable
|
|||
|
||||
struct kern_subtable_accelerator_data_t
|
||||
{
|
||||
hb_bit_set_t left_set;
|
||||
hb_bit_set_t right_set;
|
||||
hb_bit_set_t first_set;
|
||||
hb_bit_set_t second_set;
|
||||
mutable hb_aat_class_cache_t class_cache;
|
||||
};
|
||||
|
||||
|
@ -1017,9 +1019,8 @@ struct KerxTable
|
|||
if (HB_DIRECTION_IS_HORIZONTAL (c->buffer->props.direction) != st->u.header.is_horizontal ())
|
||||
goto skip;
|
||||
|
||||
c->left_set = &subtable_accel.left_set;
|
||||
c->right_set = &subtable_accel.right_set;
|
||||
c->machine_glyph_set = &subtable_accel.left_set;
|
||||
c->first_set = &subtable_accel.first_set;
|
||||
c->second_set = &subtable_accel.second_set;
|
||||
c->machine_class_cache = &subtable_accel.class_cache;
|
||||
|
||||
if (!c->buffer_intersects_machine ())
|
||||
|
@ -1051,8 +1052,8 @@ struct KerxTable
|
|||
}
|
||||
}
|
||||
|
||||
if (reverse)
|
||||
c->buffer->reverse ();
|
||||
if (reverse != c->buffer_is_reversed)
|
||||
c->reverse_buffer ();
|
||||
|
||||
{
|
||||
/* See comment in sanitize() for conditional here. */
|
||||
|
@ -1060,15 +1061,14 @@ struct KerxTable
|
|||
ret |= st->dispatch (c);
|
||||
}
|
||||
|
||||
if (reverse)
|
||||
c->buffer->reverse ();
|
||||
|
||||
(void) c->buffer->message (c->font, "end subtable %u", c->lookup_index);
|
||||
|
||||
skip:
|
||||
st = &StructAfter<SubTable> (*st);
|
||||
c->set_lookup_index (c->lookup_index + 1);
|
||||
}
|
||||
if (c->buffer_is_reversed)
|
||||
c->reverse_buffer ();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -1133,7 +1133,7 @@ struct KerxTable
|
|||
if (unlikely (accel_data.subtable_accels.in_error ()))
|
||||
return accel_data;
|
||||
|
||||
st->collect_glyphs (subtable_accel.left_set, subtable_accel.right_set, num_glyphs);
|
||||
st->collect_glyphs (subtable_accel.first_set, subtable_accel.second_set, num_glyphs);
|
||||
subtable_accel.class_cache.clear ();
|
||||
|
||||
st = &StructAfter<SubTable> (*st);
|
||||
|
|
|
@ -1169,15 +1169,15 @@ struct Chain
|
|||
hb_map ([subtable_flags] (const hb_aat_map_t::range_flags_t _) -> bool { return subtable_flags & (_.flags); })))
|
||||
goto skip;
|
||||
|
||||
c->subtable_flags = subtable_flags;
|
||||
c->machine_glyph_set = accel ? &accel->subtables[i].glyph_set : &Null(hb_bit_set_t);
|
||||
c->machine_class_cache = accel ? &accel->subtables[i].class_cache : nullptr;
|
||||
|
||||
if (!(coverage & ChainSubtable<Types>::AllDirections) &&
|
||||
HB_DIRECTION_IS_VERTICAL (c->buffer->props.direction) !=
|
||||
bool (coverage & ChainSubtable<Types>::Vertical))
|
||||
goto skip;
|
||||
|
||||
c->subtable_flags = subtable_flags;
|
||||
c->first_set = accel ? &accel->subtables[i].glyph_set : &Null(hb_bit_set_t);
|
||||
c->machine_class_cache = accel ? &accel->subtables[i].class_cache : nullptr;
|
||||
|
||||
if (!c->buffer_intersects_machine ())
|
||||
{
|
||||
(void) c->buffer->message (c->font, "skipped chainsubtable %u because no glyph matches", c->lookup_index);
|
||||
|
@ -1219,22 +1219,21 @@ struct Chain
|
|||
if (!c->buffer->message (c->font, "start chainsubtable %u", c->lookup_index))
|
||||
goto skip;
|
||||
|
||||
if (reverse)
|
||||
c->buffer->reverse ();
|
||||
if (reverse != c->buffer_is_reversed)
|
||||
c->reverse_buffer ();
|
||||
|
||||
subtable->apply (c);
|
||||
|
||||
if (reverse)
|
||||
c->buffer->reverse ();
|
||||
|
||||
(void) c->buffer->message (c->font, "end chainsubtable %u", c->lookup_index);
|
||||
|
||||
if (unlikely (!c->buffer->successful)) return;
|
||||
if (unlikely (!c->buffer->successful)) break;
|
||||
|
||||
skip:
|
||||
subtable = &StructAfter<ChainSubtable<Types>> (*subtable);
|
||||
c->set_lookup_index (c->lookup_index + 1);
|
||||
}
|
||||
if (c->buffer_is_reversed)
|
||||
c->reverse_buffer ();
|
||||
}
|
||||
|
||||
unsigned int get_size () const { return length; }
|
||||
|
|
19
thirdparty/harfbuzz/src/hb-algs.hh
vendored
19
thirdparty/harfbuzz/src/hb-algs.hh
vendored
|
@ -92,6 +92,7 @@ template <typename Type>
|
|||
struct __attribute__((packed)) hb_packed_t { Type v; };
|
||||
|
||||
#ifndef HB_FAST_NUM_ACCESS
|
||||
|
||||
#if defined(__OPTIMIZE__) && \
|
||||
defined(__BYTE_ORDER) && \
|
||||
(__BYTE_ORDER == __BIG_ENDIAN || \
|
||||
|
@ -102,6 +103,13 @@ struct __attribute__((packed)) hb_packed_t { Type v; };
|
|||
#else
|
||||
#define HB_FAST_NUM_ACCESS 0
|
||||
#endif
|
||||
|
||||
// https://github.com/harfbuzz/harfbuzz/issues/5456
|
||||
#if defined(__GNUC__) && !defined(__clang__) && (__GNUC__ <= 12)
|
||||
#undef HB_FAST_NUM_ACCESS
|
||||
#define HB_FAST_NUM_ACCESS 0
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
template <bool BE, typename Type, int Bytes = sizeof (Type)>
|
||||
|
@ -846,6 +854,17 @@ HB_FUNCOBJ (hb_clamp);
|
|||
* Bithacks.
|
||||
*/
|
||||
|
||||
/* Return the number of 1 bits in a uint8_t; faster than hb_popcount() */
|
||||
static inline unsigned
|
||||
hb_popcount8 (uint8_t v)
|
||||
{
|
||||
static const uint8_t popcount4[16] = {
|
||||
0, 1, 1, 2, 1, 2, 2, 3,
|
||||
1, 2, 2, 3, 2, 3, 3, 4
|
||||
};
|
||||
return popcount4[v & 0xF] + popcount4[v >> 4];
|
||||
}
|
||||
|
||||
/* Return the number of 1 bits in v. */
|
||||
template <typename T>
|
||||
static inline unsigned int
|
||||
|
|
105
thirdparty/harfbuzz/src/hb-alloc-pool.hh
vendored
Normal file
105
thirdparty/harfbuzz/src/hb-alloc-pool.hh
vendored
Normal file
|
@ -0,0 +1,105 @@
|
|||
/*
|
||||
* This is part of HarfBuzz, a text shaping library.
|
||||
*
|
||||
* Permission is hereby granted, without written agreement and without
|
||||
* license or royalty fees, to use, copy, modify, and distribute this
|
||||
* software and its documentation for any purpose, provided that the
|
||||
* above copyright notice and the following two paragraphs appear in
|
||||
* all copies of this software.
|
||||
*
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
|
||||
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
|
||||
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
|
||||
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
|
||||
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
|
||||
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
*
|
||||
* Author(s): Behdad Esfahbod
|
||||
*/
|
||||
|
||||
#ifndef HB_ALLOC_POOL_HH
|
||||
#define HB_ALLOC_POOL_HH
|
||||
|
||||
#include "hb-vector.hh"
|
||||
|
||||
/* Memory pool for persistent small- to medium-sized allocations.
|
||||
*
|
||||
* Some AI musings on this, not necessarily true:
|
||||
*
|
||||
* This is a very simple implementation, but it's good enough for our
|
||||
* purposes. It's not thread-safe. It's not very fast. It's not
|
||||
* very memory efficient. It's not very cache efficient. It's not
|
||||
* very anything efficient. But it's simple and it works. And it's
|
||||
* good enough for our purposes. If you need something more
|
||||
* sophisticated, use a real allocator. Or use a real language. */
|
||||
|
||||
struct hb_alloc_pool_t
|
||||
{
|
||||
unsigned ChunkSize = 65536 - 2 * sizeof (void *);
|
||||
|
||||
void *alloc (size_t size, unsigned alignment = 2 * sizeof (void *))
|
||||
{
|
||||
if (unlikely (chunks.in_error ())) return nullptr;
|
||||
|
||||
assert (alignment > 0);
|
||||
assert (alignment <= 2 * sizeof (void *));
|
||||
assert ((alignment & (alignment - 1)) == 0); /* power of two */
|
||||
|
||||
if (size > (ChunkSize) / 4)
|
||||
{
|
||||
/* Big chunk, allocate separately. */
|
||||
hb_vector_t<char> chunk;
|
||||
if (unlikely (!chunk.resize (size))) return nullptr;
|
||||
void *ret = chunk.arrayZ;
|
||||
chunks.push (std::move (chunk));
|
||||
if (chunks.in_error ()) return nullptr;
|
||||
if (chunks.length > 1)
|
||||
{
|
||||
// Bring back the previous last chunk to the end, so that
|
||||
// we can continue to allocate from it.
|
||||
hb_swap (chunks.arrayZ[chunks.length - 1], chunks.arrayZ[chunks.length - 2]);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
unsigned pad = (unsigned)(-(uintptr_t) current_chunk.arrayZ) & (alignment - 1);
|
||||
|
||||
// Small chunk, allocate from the last chunk.
|
||||
if (current_chunk.length < pad + size)
|
||||
{
|
||||
chunks.push ();
|
||||
if (unlikely (chunks.in_error ())) return nullptr;
|
||||
hb_vector_t<char> &chunk = chunks.arrayZ[chunks.length - 1];
|
||||
if (unlikely (!chunk.resize (ChunkSize))) return nullptr;
|
||||
current_chunk = chunk;
|
||||
pad = (unsigned)(-(uintptr_t) current_chunk.arrayZ) & (alignment - 1);
|
||||
}
|
||||
|
||||
current_chunk += pad;
|
||||
|
||||
assert (current_chunk.length >= size);
|
||||
void *ret = current_chunk.arrayZ;
|
||||
current_chunk += size;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void discard (void *p_, size_t size)
|
||||
{
|
||||
// Reclaim memory if we can.
|
||||
char *p = (char *) p_;
|
||||
if (current_chunk.arrayZ == p + size && current_chunk.backwards_length >= size)
|
||||
current_chunk -= size;
|
||||
}
|
||||
|
||||
private:
|
||||
hb_vector_t<hb_vector_t<char>> chunks;
|
||||
hb_array_t<char> current_chunk;
|
||||
};
|
||||
|
||||
|
||||
#endif /* HB_ALLOC_POOL_HH */
|
100
thirdparty/harfbuzz/src/hb-atomic.hh
vendored
100
thirdparty/harfbuzz/src/hb-atomic.hh
vendored
|
@ -40,7 +40,6 @@
|
|||
* Atomic integers and pointers.
|
||||
*/
|
||||
|
||||
|
||||
/* We need external help for these */
|
||||
|
||||
#if defined(hb_atomic_int_impl_add) \
|
||||
|
@ -80,27 +79,11 @@ _hb_atomic_ptr_impl_cmplexch (const void **P, const void *O_, const void *N)
|
|||
|
||||
#include <atomic>
|
||||
|
||||
#define HB_STL_ATOMIC_IMPL
|
||||
|
||||
#define _hb_memory_r_barrier() std::atomic_thread_fence(std::memory_order_acquire)
|
||||
#define _hb_memory_w_barrier() std::atomic_thread_fence(std::memory_order_release)
|
||||
|
||||
#define hb_atomic_int_impl_add(AI, V) (reinterpret_cast<std::atomic<typename std::decay<decltype (*(AI))>::type> *> (AI)->fetch_add ((V), std::memory_order_acq_rel))
|
||||
#define hb_atomic_int_impl_set_relaxed(AI, V) (reinterpret_cast<std::atomic<typename std::decay<decltype (*(AI))>::type> *> (AI)->store ((V), std::memory_order_relaxed))
|
||||
#define hb_atomic_int_impl_set(AI, V) (reinterpret_cast<std::atomic<typename std::decay<decltype (*(AI))>::type> *> (AI)->store ((V), std::memory_order_release))
|
||||
#define hb_atomic_int_impl_get_relaxed(AI) (reinterpret_cast<std::atomic<typename std::decay<decltype (*(AI))>::type> const *> (AI)->load (std::memory_order_relaxed))
|
||||
#define hb_atomic_int_impl_get(AI) (reinterpret_cast<std::atomic<typename std::decay<decltype (*(AI))>::type> const *> (AI)->load (std::memory_order_acquire))
|
||||
|
||||
#define hb_atomic_ptr_impl_set_relaxed(P, V) (reinterpret_cast<std::atomic<void*> *> (P)->store ((V), std::memory_order_relaxed))
|
||||
#define hb_atomic_ptr_impl_get_relaxed(P) (reinterpret_cast<std::atomic<void*> const *> (P)->load (std::memory_order_relaxed))
|
||||
#define hb_atomic_ptr_impl_get(P) (reinterpret_cast<std::atomic<void*> *> (P)->load (std::memory_order_acquire))
|
||||
static inline bool
|
||||
_hb_atomic_ptr_impl_cmplexch (const void **P, const void *O_, const void *N)
|
||||
{
|
||||
const void *O = O_; // Need lvalue
|
||||
return reinterpret_cast<std::atomic<const void*> *> (P)->compare_exchange_weak (O, N, std::memory_order_acq_rel, std::memory_order_relaxed);
|
||||
}
|
||||
#define hb_atomic_ptr_impl_cmpexch(P,O,N) _hb_atomic_ptr_impl_cmplexch ((const void **) (P), (O), (N))
|
||||
|
||||
|
||||
#else /* defined(HB_NO_MT) */
|
||||
|
||||
#define hb_atomic_int_impl_add(AI, V) ((*(AI) += (V)) - (V))
|
||||
|
@ -159,6 +142,81 @@ inline T hb_atomic_int_impl_get (const T *AI) { T v = *AI; _hb_memory_r_barrier
|
|||
inline void *hb_atomic_ptr_impl_get (void ** const P) { void *v = *P; _hb_memory_r_barrier (); return v; }
|
||||
#endif
|
||||
|
||||
#ifdef HB_STL_ATOMIC_IMPL
|
||||
template <typename T>
|
||||
struct hb_atomic_t
|
||||
{
|
||||
hb_atomic_t () = default;
|
||||
constexpr hb_atomic_t (T v) : v (v) {}
|
||||
constexpr hb_atomic_t (const hb_atomic_t& o) : v (o.get_relaxed ()) {}
|
||||
constexpr hb_atomic_t (hb_atomic_t&& o) : v (o.get_relaxed ()) { o.set_relaxed ({}); }
|
||||
|
||||
hb_atomic_t &operator= (const hb_atomic_t& o) { set_relaxed (o.get_relaxed ()); return *this; }
|
||||
hb_atomic_t &operator= (hb_atomic_t&& o){ set_relaxed (o.get_relaxed ()); o.set_relaxed ({}); return *this; }
|
||||
hb_atomic_t &operator= (T v_)
|
||||
{
|
||||
set_relaxed (v_);
|
||||
return *this;
|
||||
}
|
||||
operator T () const { return get_relaxed (); }
|
||||
|
||||
void set_relaxed (T v_) { v.store (v_, std::memory_order_relaxed); }
|
||||
void set_release (T v_) { v.store (v_, std::memory_order_release); }
|
||||
T get_relaxed () const { return v.load (std::memory_order_relaxed); }
|
||||
T get_acquire () const { return v.load (std::memory_order_acquire); }
|
||||
T inc () { return v.fetch_add (1, std::memory_order_acq_rel); }
|
||||
T dec () { return v.fetch_add (-1, std::memory_order_acq_rel); }
|
||||
|
||||
int operator++ (int) { return inc (); }
|
||||
int operator-- (int) { return dec (); }
|
||||
long operator|= (long v_)
|
||||
{
|
||||
set_relaxed (get_relaxed () | v_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
friend void swap (hb_atomic_t &a, hb_atomic_t &b) noexcept
|
||||
{
|
||||
T v = a.get_acquire ();
|
||||
a.set_relaxed (b.get_acquire ());
|
||||
b.set_relaxed (v);
|
||||
}
|
||||
|
||||
std::atomic<T> v = 0;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct hb_atomic_t<T *>
|
||||
{
|
||||
hb_atomic_t () = default;
|
||||
constexpr hb_atomic_t (T *v) : v (v) {}
|
||||
hb_atomic_t (const hb_atomic_t &other) = delete;
|
||||
|
||||
void init (T *v_ = nullptr) { set_relaxed (v_); }
|
||||
void set_relaxed (T *v_) { v.store (v_, std::memory_order_relaxed); }
|
||||
T *get_relaxed () const { return v.load (std::memory_order_relaxed); }
|
||||
T *get_acquire () const { return v.load (std::memory_order_acquire); }
|
||||
bool cmpexch (T *old, T *new_) { return v.compare_exchange_weak (old, new_, std::memory_order_acq_rel, std::memory_order_relaxed); }
|
||||
|
||||
operator bool () const { return get_acquire () != nullptr; }
|
||||
T *operator->() const { return get_acquire (); }
|
||||
template <typename C>
|
||||
operator C * () const
|
||||
{
|
||||
return get_acquire ();
|
||||
}
|
||||
|
||||
friend void swap (hb_atomic_t &a, hb_atomic_t &b) noexcept
|
||||
{
|
||||
T *p = a.get_acquire ();
|
||||
a.set_relaxed (b.get_acquire ());
|
||||
b.set_relaxed (p);
|
||||
}
|
||||
|
||||
std::atomic<T *> v = nullptr;
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
template <typename T>
|
||||
struct hb_atomic_t
|
||||
|
@ -194,7 +252,7 @@ struct hb_atomic_t<T*>
|
|||
void set_relaxed (T* v_) { hb_atomic_ptr_impl_set_relaxed (&v, v_); }
|
||||
T *get_relaxed () const { return (T *) hb_atomic_ptr_impl_get_relaxed (&v); }
|
||||
T *get_acquire () const { return (T *) hb_atomic_ptr_impl_get ((void **) &v); }
|
||||
bool cmpexch (const T *old, T *new_) { return hb_atomic_ptr_impl_cmpexch ((void **) &v, (void *) old, (void *) new_); }
|
||||
bool cmpexch (T *old, T *new_) { return hb_atomic_ptr_impl_cmpexch ((void **) &v, (void *) old, (void *) new_); }
|
||||
|
||||
operator bool () const { return get_acquire () != nullptr; }
|
||||
T * operator -> () const { return get_acquire (); }
|
||||
|
@ -203,6 +261,8 @@ struct hb_atomic_t<T*>
|
|||
T *v = nullptr;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
static inline bool hb_barrier ()
|
||||
{
|
||||
_hb_compiler_memory_r_barrier ();
|
||||
|
|
2
thirdparty/harfbuzz/src/hb-bimap.hh
vendored
2
thirdparty/harfbuzz/src/hb-bimap.hh
vendored
|
@ -176,7 +176,7 @@ struct hb_inc_bimap_t
|
|||
{
|
||||
hb_codepoint_t count = get_population ();
|
||||
hb_vector_t <hb_codepoint_t> work;
|
||||
if (unlikely (!work.resize (count, false))) return;
|
||||
if (unlikely (!work.resize_dirty (count))) return;
|
||||
|
||||
for (hb_codepoint_t rhs = 0; rhs < count; rhs++)
|
||||
work.arrayZ[rhs] = back_map[rhs];
|
||||
|
|
33
thirdparty/harfbuzz/src/hb-bit-page.hh
vendored
33
thirdparty/harfbuzz/src/hb-bit-page.hh
vendored
|
@ -142,6 +142,7 @@ struct hb_bit_page_t
|
|||
|
||||
bool operator [] (hb_codepoint_t g) const { return get (g); }
|
||||
bool operator () (hb_codepoint_t g) const { return get (g); }
|
||||
bool has (hb_codepoint_t g) const { return get (g); }
|
||||
|
||||
void add_range (hb_codepoint_t a, hb_codepoint_t b)
|
||||
{
|
||||
|
@ -290,7 +291,7 @@ struct hb_bit_page_t
|
|||
unsigned int j = m & ELT_MASK;
|
||||
|
||||
const elt_t vv = v[i] & ~((elt_t (1) << j) - 1);
|
||||
for (const elt_t *p = &vv; i < len (); p = &v[++i])
|
||||
for (const elt_t *p = &vv; i < len (); p = ((const elt_t *) &v[0]) + (++i))
|
||||
if (*p)
|
||||
{
|
||||
*codepoint = i * ELT_BITS + elt_get_min (*p);
|
||||
|
@ -346,6 +347,36 @@ struct hb_bit_page_t
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Iterator implementation.
|
||||
*/
|
||||
struct iter_t : hb_iter_with_fallback_t<iter_t, hb_codepoint_t>
|
||||
{
|
||||
static constexpr bool is_sorted_iterator = true;
|
||||
iter_t (const hb_bit_page_t &s_ = Null (hb_bit_page_t), bool init = true) : s (&s_), v (INVALID)
|
||||
{
|
||||
if (init)
|
||||
v = s->get_min ();
|
||||
}
|
||||
|
||||
typedef hb_codepoint_t __item_t__;
|
||||
hb_codepoint_t __item__ () const { return v; }
|
||||
bool __more__ () const { return v != INVALID; }
|
||||
void __next__ () {
|
||||
s->next (&v);
|
||||
}
|
||||
void __prev__ () { s->previous (&v); }
|
||||
iter_t end () const { return iter_t (*s, false); }
|
||||
bool operator != (const iter_t& o) const
|
||||
{ return v != o.v; }
|
||||
|
||||
protected:
|
||||
const hb_bit_page_t *s;
|
||||
hb_codepoint_t v;
|
||||
};
|
||||
iter_t iter () const { return iter_t (*this); }
|
||||
operator iter_t () const { return iter (); }
|
||||
|
||||
static constexpr hb_codepoint_t INVALID = HB_SET_VALUE_INVALID;
|
||||
|
||||
typedef unsigned long long elt_t;
|
||||
|
|
|
@ -368,7 +368,7 @@ struct hb_bit_set_invertible_t
|
|||
unsigned __len__ () const { return l; }
|
||||
iter_t end () const { return iter_t (*s, false); }
|
||||
bool operator != (const iter_t& o) const
|
||||
{ return v != o.v || s != o.s; }
|
||||
{ return v != o.v; }
|
||||
|
||||
protected:
|
||||
const hb_bit_set_invertible_t *s;
|
||||
|
|
13
thirdparty/harfbuzz/src/hb-bit-set.hh
vendored
13
thirdparty/harfbuzz/src/hb-bit-set.hh
vendored
|
@ -91,10 +91,10 @@ struct hb_bit_set_t
|
|||
if (pages.length < count && (unsigned) pages.allocated < count && count <= 2)
|
||||
exact_size = true; // Most sets are small and local
|
||||
|
||||
if (unlikely (!pages.resize (count, clear, exact_size) ||
|
||||
!page_map.resize (count, clear)))
|
||||
if (unlikely (!pages.resize_full (count, clear, exact_size) ||
|
||||
!page_map.resize_full (count, clear, false)))
|
||||
{
|
||||
pages.resize (page_map.length, clear, exact_size);
|
||||
pages.resize_full (page_map.length, clear, exact_size);
|
||||
successful = false;
|
||||
return false;
|
||||
}
|
||||
|
@ -108,10 +108,11 @@ struct hb_bit_set_t
|
|||
page_map.alloc (sz);
|
||||
}
|
||||
|
||||
void reset ()
|
||||
hb_bit_set_t& reset ()
|
||||
{
|
||||
successful = true;
|
||||
clear ();
|
||||
return *this;
|
||||
}
|
||||
|
||||
void clear ()
|
||||
|
@ -394,7 +395,7 @@ struct hb_bit_set_t
|
|||
{
|
||||
if (unlikely (!successful)) return;
|
||||
unsigned int count = other.pages.length;
|
||||
if (unlikely (!resize (count, false, exact_size)))
|
||||
if (unlikely (!resize (count, false, exact_size)))
|
||||
return;
|
||||
population = other.population;
|
||||
|
||||
|
@ -922,7 +923,7 @@ struct hb_bit_set_t
|
|||
unsigned __len__ () const { return l; }
|
||||
iter_t end () const { return iter_t (*s, false); }
|
||||
bool operator != (const iter_t& o) const
|
||||
{ return s != o.s || v != o.v; }
|
||||
{ return v != o.v; }
|
||||
|
||||
protected:
|
||||
const hb_bit_set_t *s;
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
#include "hb.hh"
|
||||
|
||||
|
||||
#line 36 "hb-buffer-deserialize-text-unicode.hh"
|
||||
#line 33 "hb-buffer-deserialize-text-unicode.hh"
|
||||
static const unsigned char _deserialize_text_unicode_trans_keys[] = {
|
||||
0u, 0u, 43u, 102u, 48u, 102u, 48u, 124u, 48u, 57u, 62u, 124u, 48u, 124u, 60u, 117u,
|
||||
85u, 117u, 85u, 117u, 0
|
||||
|
@ -150,12 +150,12 @@ _hb_buffer_deserialize_text_unicode (hb_buffer_t *buffer,
|
|||
hb_glyph_info_t info = {0};
|
||||
const hb_glyph_position_t pos = {0};
|
||||
|
||||
#line 154 "hb-buffer-deserialize-text-unicode.hh"
|
||||
#line 147 "hb-buffer-deserialize-text-unicode.hh"
|
||||
{
|
||||
cs = deserialize_text_unicode_start;
|
||||
}
|
||||
|
||||
#line 159 "hb-buffer-deserialize-text-unicode.hh"
|
||||
#line 150 "hb-buffer-deserialize-text-unicode.hh"
|
||||
{
|
||||
int _slen;
|
||||
int _trans;
|
||||
|
@ -215,7 +215,7 @@ _resume:
|
|||
hb_memset (&info, 0, sizeof (info));
|
||||
}
|
||||
break;
|
||||
#line 219 "hb-buffer-deserialize-text-unicode.hh"
|
||||
#line 203 "hb-buffer-deserialize-text-unicode.hh"
|
||||
}
|
||||
|
||||
_again:
|
||||
|
@ -238,7 +238,7 @@ _again:
|
|||
*end_ptr = p;
|
||||
}
|
||||
break;
|
||||
#line 242 "hb-buffer-deserialize-text-unicode.hh"
|
||||
#line 224 "hb-buffer-deserialize-text-unicode.hh"
|
||||
}
|
||||
}
|
||||
|
||||
|
|
6
thirdparty/harfbuzz/src/hb-buffer-verify.cc
vendored
6
thirdparty/harfbuzz/src/hb-buffer-verify.cc
vendored
|
@ -163,7 +163,7 @@ buffer_verify_unsafe_to_break (hb_buffer_t *buffer,
|
|||
|
||||
hb_buffer_append (fragment, text_buffer, text_start, text_end);
|
||||
if (!hb_shape_full (font, fragment, features, num_features, shapers) ||
|
||||
fragment->successful || fragment->shaping_failed)
|
||||
fragment->successful)
|
||||
{
|
||||
hb_buffer_destroy (reconstruction);
|
||||
hb_buffer_destroy (fragment);
|
||||
|
@ -313,11 +313,11 @@ buffer_verify_unsafe_to_concat (hb_buffer_t *buffer,
|
|||
* Shape the two fragment streams.
|
||||
*/
|
||||
if (!hb_shape_full (font, fragments[0], features, num_features, shapers) ||
|
||||
!fragments[0]->successful || fragments[0]->shaping_failed)
|
||||
!fragments[0]->successful)
|
||||
goto out;
|
||||
|
||||
if (!hb_shape_full (font, fragments[1], features, num_features, shapers) ||
|
||||
!fragments[1]->successful || fragments[1]->shaping_failed)
|
||||
!fragments[1]->successful)
|
||||
goto out;
|
||||
|
||||
if (!forward)
|
||||
|
|
36
thirdparty/harfbuzz/src/hb-buffer.cc
vendored
36
thirdparty/harfbuzz/src/hb-buffer.cc
vendored
|
@ -158,14 +158,15 @@ hb_segment_properties_overlay (hb_segment_properties_t *p,
|
|||
bool
|
||||
hb_buffer_t::enlarge (unsigned int size)
|
||||
{
|
||||
if (unlikely (!successful))
|
||||
return false;
|
||||
if (unlikely (size > max_len))
|
||||
{
|
||||
successful = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (unlikely (!successful))
|
||||
return false;
|
||||
|
||||
unsigned int new_allocated = allocated;
|
||||
hb_glyph_position_t *new_pos = nullptr;
|
||||
hb_glyph_info_t *new_info = nullptr;
|
||||
|
@ -226,6 +227,13 @@ hb_buffer_t::shift_forward (unsigned int count)
|
|||
assert (have_output);
|
||||
if (unlikely (!ensure (len + count))) return false;
|
||||
|
||||
max_ops -= len - idx;
|
||||
if (unlikely (max_ops < 0))
|
||||
{
|
||||
successful = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
memmove (info + idx + count, info + idx, (len - idx) * sizeof (info[0]));
|
||||
if (idx + count > len)
|
||||
{
|
||||
|
@ -297,7 +305,6 @@ hb_buffer_t::clear ()
|
|||
props = default_props;
|
||||
|
||||
successful = true;
|
||||
shaping_failed = false;
|
||||
have_output = false;
|
||||
have_positions = false;
|
||||
|
||||
|
@ -320,7 +327,6 @@ hb_buffer_t::enter ()
|
|||
{
|
||||
deallocate_var_all ();
|
||||
serial = 0;
|
||||
shaping_failed = false;
|
||||
scratch_flags = HB_BUFFER_SCRATCH_FLAG_DEFAULT;
|
||||
unsigned mul;
|
||||
if (likely (!hb_unsigned_mul_overflows (len, HB_BUFFER_MAX_LEN_FACTOR, &mul)))
|
||||
|
@ -339,7 +345,6 @@ hb_buffer_t::leave ()
|
|||
max_ops = HB_BUFFER_MAX_OPS_DEFAULT;
|
||||
deallocate_var_all ();
|
||||
serial = 0;
|
||||
// Intentionally not reseting shaping_failed, such that it can be inspected.
|
||||
}
|
||||
|
||||
|
||||
|
@ -520,7 +525,19 @@ hb_buffer_t::set_masks (hb_mask_t value,
|
|||
hb_mask_t not_mask = ~mask;
|
||||
value &= mask;
|
||||
|
||||
max_ops -= len;
|
||||
if (unlikely (max_ops < 0))
|
||||
successful = false;
|
||||
|
||||
unsigned int count = len;
|
||||
|
||||
if (cluster_start == 0 && cluster_end == (unsigned int) -1)
|
||||
{
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
info[i].mask = (info[i].mask & not_mask) | value;
|
||||
return;
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
if (cluster_start <= info[i].cluster && info[i].cluster < cluster_end)
|
||||
info[i].mask = (info[i].mask & not_mask) | value;
|
||||
|
@ -536,6 +553,10 @@ hb_buffer_t::merge_clusters_impl (unsigned int start,
|
|||
return;
|
||||
}
|
||||
|
||||
max_ops -= end - start;
|
||||
if (unlikely (max_ops < 0))
|
||||
successful = false;
|
||||
|
||||
unsigned int cluster = info[start].cluster;
|
||||
|
||||
for (unsigned int i = start + 1; i < end; i++)
|
||||
|
@ -569,6 +590,10 @@ hb_buffer_t::merge_out_clusters (unsigned int start,
|
|||
if (unlikely (end - start < 2))
|
||||
return;
|
||||
|
||||
max_ops -= end - start;
|
||||
if (unlikely (max_ops < 0))
|
||||
successful = false;
|
||||
|
||||
unsigned int cluster = out_info[start].cluster;
|
||||
|
||||
for (unsigned int i = start + 1; i < end; i++)
|
||||
|
@ -726,7 +751,6 @@ DEFINE_NULL_INSTANCE (hb_buffer_t) =
|
|||
HB_SEGMENT_PROPERTIES_DEFAULT,
|
||||
|
||||
false, /* successful */
|
||||
true, /* shaping_failed */
|
||||
false, /* have_output */
|
||||
true /* have_positions */
|
||||
|
||||
|
|
73
thirdparty/harfbuzz/src/hb-buffer.hh
vendored
73
thirdparty/harfbuzz/src/hb-buffer.hh
vendored
|
@ -32,6 +32,7 @@
|
|||
|
||||
#include "hb.hh"
|
||||
#include "hb-unicode.hh"
|
||||
#include "hb-set-digest.hh"
|
||||
|
||||
|
||||
static_assert ((sizeof (hb_glyph_info_t) == 20), "");
|
||||
|
@ -44,14 +45,14 @@ HB_MARK_AS_FLAG_T (hb_buffer_diff_flags_t);
|
|||
|
||||
enum hb_buffer_scratch_flags_t {
|
||||
HB_BUFFER_SCRATCH_FLAG_DEFAULT = 0x00000000u,
|
||||
HB_BUFFER_SCRATCH_FLAG_HAS_NON_ASCII = 0x00000001u,
|
||||
HB_BUFFER_SCRATCH_FLAG_HAS_FRACTION_SLASH = 0x00000001u,
|
||||
HB_BUFFER_SCRATCH_FLAG_HAS_DEFAULT_IGNORABLES = 0x00000002u,
|
||||
HB_BUFFER_SCRATCH_FLAG_HAS_SPACE_FALLBACK = 0x00000004u,
|
||||
HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT = 0x00000008u,
|
||||
HB_BUFFER_SCRATCH_FLAG_HAS_CGJ = 0x00000010u,
|
||||
HB_BUFFER_SCRATCH_FLAG_HAS_GLYPH_FLAGS = 0x00000020u,
|
||||
HB_BUFFER_SCRATCH_FLAG_HAS_BROKEN_SYLLABLE = 0x00000040u,
|
||||
HB_BUFFER_SCRATCH_FLAG_HAS_VARIATION_SELECTOR_FALLBACK= 0x00000080u,
|
||||
HB_BUFFER_SCRATCH_FLAG_HAS_BROKEN_SYLLABLE = 0x00000020u,
|
||||
HB_BUFFER_SCRATCH_FLAG_HAS_VARIATION_SELECTOR_FALLBACK= 0x00000040u,
|
||||
HB_BUFFER_SCRATCH_FLAG_HAS_CONTINUATIONS = 0x00000080u,
|
||||
|
||||
/* Reserved for shapers' internal use. */
|
||||
HB_BUFFER_SCRATCH_FLAG_SHAPER0 = 0x01000000u,
|
||||
|
@ -90,7 +91,6 @@ struct hb_buffer_t
|
|||
hb_segment_properties_t props; /* Script, language, direction */
|
||||
|
||||
bool successful; /* Allocations successful */
|
||||
bool shaping_failed; /* Shaping failure */
|
||||
bool have_output; /* Whether we have an output buffer going on */
|
||||
bool have_positions; /* Whether we have positions */
|
||||
|
||||
|
@ -110,6 +110,7 @@ struct hb_buffer_t
|
|||
hb_codepoint_t context[2][CONTEXT_LENGTH];
|
||||
unsigned int context_len[2];
|
||||
|
||||
hb_set_digest_t digest; /* Manually updated sometimes */
|
||||
|
||||
/*
|
||||
* Managed by enter / leave
|
||||
|
@ -200,6 +201,12 @@ struct hb_buffer_t
|
|||
void collect_codepoints (set_t &d) const
|
||||
{ d.clear (); d.add_array (&info[0].codepoint, len, sizeof (info[0])); }
|
||||
|
||||
void update_digest ()
|
||||
{
|
||||
digest = hb_set_digest_t ();
|
||||
collect_codepoints (digest);
|
||||
}
|
||||
|
||||
HB_INTERNAL void similar (const hb_buffer_t &src);
|
||||
HB_INTERNAL void reset ();
|
||||
HB_INTERNAL void clear ();
|
||||
|
@ -346,7 +353,7 @@ struct hb_buffer_t
|
|||
{
|
||||
if (out_info != info || out_len != idx)
|
||||
{
|
||||
if (unlikely (!make_room_for (1, 1))) return false;
|
||||
if (unlikely (!ensure (out_len + 1))) return false;
|
||||
out_info[out_len] = info[idx];
|
||||
}
|
||||
out_len++;
|
||||
|
@ -363,7 +370,7 @@ struct hb_buffer_t
|
|||
{
|
||||
if (out_info != info || out_len != idx)
|
||||
{
|
||||
if (unlikely (!make_room_for (n, n))) return false;
|
||||
if (unlikely (!ensure (out_len + n))) return false;
|
||||
memmove (out_info + out_len, info + idx, n * sizeof (out_info[0]));
|
||||
}
|
||||
out_len += n;
|
||||
|
@ -404,22 +411,12 @@ struct hb_buffer_t
|
|||
/* Adds glyph flags in mask to infos with clusters between start and end.
|
||||
* The start index will be from out-buffer if from_out_buffer is true.
|
||||
* If interior is true, then the cluster having the minimum value is skipped. */
|
||||
void _set_glyph_flags (hb_mask_t mask,
|
||||
unsigned start = 0,
|
||||
unsigned end = (unsigned) -1,
|
||||
bool interior = false,
|
||||
bool from_out_buffer = false)
|
||||
void _set_glyph_flags_impl (hb_mask_t mask,
|
||||
unsigned start,
|
||||
unsigned end,
|
||||
bool interior,
|
||||
bool from_out_buffer)
|
||||
{
|
||||
if (unlikely (end != (unsigned) -1 && end - start > 255))
|
||||
return;
|
||||
|
||||
end = hb_min (end, len);
|
||||
|
||||
if (interior && !from_out_buffer && end - start < 2)
|
||||
return;
|
||||
|
||||
scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GLYPH_FLAGS;
|
||||
|
||||
if (!from_out_buffer || !have_output)
|
||||
{
|
||||
if (!interior)
|
||||
|
@ -456,6 +453,25 @@ struct hb_buffer_t
|
|||
}
|
||||
}
|
||||
|
||||
HB_ALWAYS_INLINE
|
||||
void _set_glyph_flags (hb_mask_t mask,
|
||||
unsigned start = 0,
|
||||
unsigned end = (unsigned) -1,
|
||||
bool interior = false,
|
||||
bool from_out_buffer = false)
|
||||
{
|
||||
if (unlikely (end != (unsigned) -1 && end - start > 255))
|
||||
return;
|
||||
|
||||
end = hb_min (end, len);
|
||||
|
||||
if (interior && !from_out_buffer && end - start < 2)
|
||||
return;
|
||||
|
||||
_set_glyph_flags_impl (mask, start, end, interior, from_out_buffer);
|
||||
}
|
||||
|
||||
|
||||
void unsafe_to_break (unsigned int start = 0, unsigned int end = -1)
|
||||
{
|
||||
_set_glyph_flags (HB_GLYPH_FLAG_UNSAFE_TO_BREAK | HB_GLYPH_FLAG_UNSAFE_TO_CONCAT,
|
||||
|
@ -606,6 +622,10 @@ struct hb_buffer_t
|
|||
if (unlikely (start == end))
|
||||
return;
|
||||
|
||||
max_ops -= end - start;
|
||||
if (unlikely (max_ops < 0))
|
||||
successful = false;
|
||||
|
||||
unsigned cluster_first = infos[start].cluster;
|
||||
unsigned cluster_last = infos[end - 1].cluster;
|
||||
|
||||
|
@ -614,10 +634,7 @@ struct hb_buffer_t
|
|||
{
|
||||
for (unsigned int i = start; i < end; i++)
|
||||
if (cluster != infos[i].cluster)
|
||||
{
|
||||
scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GLYPH_FLAGS;
|
||||
infos[i].mask |= mask;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -626,18 +643,12 @@ struct hb_buffer_t
|
|||
if (cluster == cluster_first)
|
||||
{
|
||||
for (unsigned int i = end; start < i && infos[i - 1].cluster != cluster_first; i--)
|
||||
{
|
||||
scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GLYPH_FLAGS;
|
||||
infos[i - 1].mask |= mask;
|
||||
}
|
||||
}
|
||||
else /* cluster == cluster_last */
|
||||
{
|
||||
for (unsigned int i = start; i < end && infos[i].cluster != cluster_last; i++)
|
||||
{
|
||||
scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GLYPH_FLAGS;
|
||||
infos[i].mask |= mask;
|
||||
}
|
||||
}
|
||||
}
|
||||
unsigned
|
||||
|
|
8
thirdparty/harfbuzz/src/hb-cache.hh
vendored
8
thirdparty/harfbuzz/src/hb-cache.hh
vendored
|
@ -75,6 +75,8 @@ struct hb_cache_t
|
|||
static_assert ((key_bits >= cache_bits), "");
|
||||
static_assert ((key_bits + value_bits <= cache_bits + 8 * sizeof (item_t)), "");
|
||||
|
||||
static constexpr unsigned MAX_VALUE = (1u << value_bits) - 1;
|
||||
|
||||
hb_cache_t () { clear (); }
|
||||
|
||||
void clear ()
|
||||
|
@ -100,6 +102,12 @@ struct hb_cache_t
|
|||
{
|
||||
if (unlikely ((key >> key_bits) || (value >> value_bits)))
|
||||
return; /* Overflows */
|
||||
set_unchecked (key, value);
|
||||
}
|
||||
|
||||
HB_HOT
|
||||
void set_unchecked (unsigned int key, unsigned int value)
|
||||
{
|
||||
unsigned int k = key & ((1u<<cache_bits)-1);
|
||||
unsigned int v = ((key>>cache_bits)<<value_bits) | value;
|
||||
values[k] = v;
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue