summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/extension/gdnative_interface.cpp69
-rw-r--r--core/extension/gdnative_interface.h76
-rw-r--r--core/extension/native_extension.cpp109
-rw-r--r--core/extension/native_extension.h16
-rw-r--r--core/object/class_db.cpp2
-rw-r--r--core/object/make_virtuals.py6
-rw-r--r--core/object/object.cpp3
-rw-r--r--core/object/object.h20
-rw-r--r--core/object/script_language_extension.h38
-rw-r--r--doc/classes/AnimatedTexture.xml1
-rw-r--r--doc/classes/AtlasTexture.xml1
-rw-r--r--doc/classes/CameraTexture.xml1
-rw-r--r--doc/classes/CanvasTexture.xml1
-rw-r--r--doc/classes/CompressedTexture2D.xml1
-rw-r--r--doc/classes/CurveTexture.xml1
-rw-r--r--doc/classes/CurveXYZTexture.xml1
-rw-r--r--doc/classes/DisplayServer.xml8
-rw-r--r--doc/classes/EditorSpinSlider.xml2
-rw-r--r--doc/classes/GradientTexture1D.xml1
-rw-r--r--doc/classes/GradientTexture2D.xml1
-rw-r--r--doc/classes/ImageTexture.xml3
-rw-r--r--doc/classes/MeshTexture.xml1
-rw-r--r--doc/classes/PhysicsDirectBodyState2D.xml24
-rw-r--r--doc/classes/PhysicsDirectBodyState3D.xml28
-rw-r--r--doc/classes/PlaceholderTexture2D.xml1
-rw-r--r--doc/classes/PortableCompressedTexture2D.xml1
-rw-r--r--doc/classes/ProgressBar.xml2
-rw-r--r--doc/classes/Range.xml3
-rw-r--r--doc/classes/ScrollBar.xml1
-rw-r--r--doc/classes/Slider.xml2
-rw-r--r--doc/classes/SpinBox.xml2
-rw-r--r--doc/classes/TextureProgressBar.xml2
-rw-r--r--doc/classes/ViewportTexture.xml1
-rw-r--r--drivers/gles3/rasterizer_scene_gles3.cpp36
-rw-r--r--drivers/gles3/storage/render_scene_buffers_gles3.cpp62
-rw-r--r--drivers/gles3/storage/render_scene_buffers_gles3.h3
-rw-r--r--drivers/gles3/storage/texture_storage.cpp293
-rw-r--r--drivers/gles3/storage/texture_storage.h28
-rw-r--r--editor/doc_tools.cpp2
-rw-r--r--modules/noise/doc_classes/NoiseTexture2D.xml1
-rw-r--r--modules/openxr/SCsub2
-rw-r--r--modules/openxr/extensions/openxr_opengl_extension.cpp479
-rw-r--r--modules/openxr/extensions/openxr_opengl_extension.h120
-rw-r--r--modules/openxr/openxr_api.cpp35
-rw-r--r--platform/android/display_server_android.cpp5
-rw-r--r--platform/linuxbsd/x11/detect_prime_x11.cpp5
-rw-r--r--platform/linuxbsd/x11/display_server_x11.cpp5
-rw-r--r--platform/linuxbsd/x11/gl_manager_x11.cpp11
-rw-r--r--platform/linuxbsd/x11/gl_manager_x11.h2
-rw-r--r--platform/macos/display_server_macos.mm5
-rw-r--r--platform/macos/gl_manager_macos_legacy.h2
-rw-r--r--platform/macos/gl_manager_macos_legacy.mm9
-rw-r--r--platform/web/display_server_web.cpp12
-rw-r--r--platform/web/display_server_web.h1
-rw-r--r--platform/windows/display_server_windows.cpp7
-rw-r--r--platform/windows/gl_manager_windows.cpp10
-rw-r--r--platform/windows/gl_manager_windows.h3
-rw-r--r--scene/resources/animation.cpp84
-rw-r--r--servers/display_server.cpp1
-rw-r--r--servers/display_server.h1
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp11
61 files changed, 1309 insertions, 355 deletions
diff --git a/core/extension/gdnative_interface.cpp b/core/extension/gdnative_interface.cpp
index 193fcb8916..864f2fa86b 100644
--- a/core/extension/gdnative_interface.cpp
+++ b/core/extension/gdnative_interface.cpp
@@ -61,8 +61,9 @@ static void gdnative_print_script_error(const char *p_description, const char *p
_err_print_error(p_function, p_file, p_line, p_description, false, ERR_HANDLER_SCRIPT);
}
-uint64_t gdnative_get_native_struct_size(const char *p_name) {
- return ClassDB::get_native_struct_size(p_name);
+uint64_t gdnative_get_native_struct_size(const GDNativeStringNamePtr p_name) {
+ const StringName name = *reinterpret_cast<const StringName *>(p_name);
+ return ClassDB::get_native_struct_size(name);
}
// Variant functions
@@ -81,11 +82,11 @@ static void gdnative_variant_destroy(GDNativeVariantPtr p_self) {
static void gdnative_variant_call(GDNativeVariantPtr p_self, const GDNativeStringNamePtr p_method, const GDNativeVariantPtr *p_args, const GDNativeInt p_argcount, GDNativeVariantPtr r_return, GDNativeCallError *r_error) {
Variant *self = (Variant *)p_self;
- const StringName *method = (const StringName *)p_method;
+ const StringName method = *reinterpret_cast<const StringName *>(p_method);
const Variant **args = (const Variant **)p_args;
Variant ret;
Callable::CallError error;
- self->callp(*method, args, p_argcount, ret, error);
+ self->callp(method, args, p_argcount, ret, error);
memnew_placement(r_return, Variant(ret));
if (r_error) {
@@ -97,11 +98,11 @@ static void gdnative_variant_call(GDNativeVariantPtr p_self, const GDNativeStrin
static void gdnative_variant_call_static(GDNativeVariantType p_type, const GDNativeStringNamePtr p_method, const GDNativeVariantPtr *p_args, const GDNativeInt p_argcount, GDNativeVariantPtr r_return, GDNativeCallError *r_error) {
Variant::Type type = (Variant::Type)p_type;
- const StringName *method = (const StringName *)p_method;
+ const StringName method = *reinterpret_cast<const StringName *>(p_method);
const Variant **args = (const Variant **)p_args;
Variant ret;
Callable::CallError error;
- Variant::call_static(type, *method, args, p_argcount, ret, error);
+ Variant::call_static(type, method, args, p_argcount, ret, error);
memnew_placement(r_return, Variant(ret));
if (r_error) {
@@ -469,11 +470,11 @@ static GDNativeTypeFromVariantConstructorFunc gdnative_get_type_from_variant_con
static GDNativePtrOperatorEvaluator gdnative_variant_get_ptr_operator_evaluator(GDNativeVariantOperator p_operator, GDNativeVariantType p_type_a, GDNativeVariantType p_type_b) {
return (GDNativePtrOperatorEvaluator)Variant::get_ptr_operator_evaluator(Variant::Operator(p_operator), Variant::Type(p_type_a), Variant::Type(p_type_b));
}
-static GDNativePtrBuiltInMethod gdnative_variant_get_ptr_builtin_method(GDNativeVariantType p_type, const char *p_method, GDNativeInt p_hash) {
- StringName method = p_method;
+static GDNativePtrBuiltInMethod gdnative_variant_get_ptr_builtin_method(GDNativeVariantType p_type, const GDNativeStringNamePtr p_method, GDNativeInt p_hash) {
+ const StringName method = *reinterpret_cast<const StringName *>(p_method);
uint32_t hash = Variant::get_builtin_method_hash(Variant::Type(p_type), method);
if (hash != p_hash) {
- ERR_PRINT_ONCE("Error getting method " + String(method) + ", hash mismatch.");
+ ERR_PRINT_ONCE("Error getting method " + method + ", hash mismatch.");
return nullptr;
}
@@ -497,11 +498,13 @@ static void gdnative_variant_construct(GDNativeVariantType p_type, GDNativeVaria
r_error->expected = error.expected;
}
}
-static GDNativePtrSetter gdnative_variant_get_ptr_setter(GDNativeVariantType p_type, const char *p_member) {
- return (GDNativePtrSetter)Variant::get_member_ptr_setter(Variant::Type(p_type), p_member);
+static GDNativePtrSetter gdnative_variant_get_ptr_setter(GDNativeVariantType p_type, const GDNativeStringNamePtr p_member) {
+ const StringName member = *reinterpret_cast<const StringName *>(p_member);
+ return (GDNativePtrSetter)Variant::get_member_ptr_setter(Variant::Type(p_type), member);
}
-static GDNativePtrGetter gdnative_variant_get_ptr_getter(GDNativeVariantType p_type, const char *p_member) {
- return (GDNativePtrGetter)Variant::get_member_ptr_getter(Variant::Type(p_type), p_member);
+static GDNativePtrGetter gdnative_variant_get_ptr_getter(GDNativeVariantType p_type, const GDNativeStringNamePtr p_member) {
+ const StringName member = *reinterpret_cast<const StringName *>(p_member);
+ return (GDNativePtrGetter)Variant::get_member_ptr_getter(Variant::Type(p_type), member);
}
static GDNativePtrIndexedSetter gdnative_variant_get_ptr_indexed_setter(GDNativeVariantType p_type) {
return (GDNativePtrIndexedSetter)Variant::get_member_ptr_indexed_setter(Variant::Type(p_type));
@@ -518,14 +521,15 @@ static GDNativePtrKeyedGetter gdnative_variant_get_ptr_keyed_getter(GDNativeVari
static GDNativePtrKeyedChecker gdnative_variant_get_ptr_keyed_checker(GDNativeVariantType p_type) {
return (GDNativePtrKeyedChecker)Variant::get_member_ptr_keyed_checker(Variant::Type(p_type));
}
-static void gdnative_variant_get_constant_value(GDNativeVariantType p_type, const char *p_constant, GDNativeVariantPtr r_ret) {
- memnew_placement(r_ret, Variant(Variant::get_constant_value(Variant::Type(p_type), p_constant)));
+static void gdnative_variant_get_constant_value(GDNativeVariantType p_type, const GDNativeStringNamePtr p_constant, GDNativeVariantPtr r_ret) {
+ StringName constant = *reinterpret_cast<const StringName *>(p_constant);
+ memnew_placement(r_ret, Variant(Variant::get_constant_value(Variant::Type(p_type), constant)));
}
-static GDNativePtrUtilityFunction gdnative_variant_get_ptr_utility_function(const char *p_function, GDNativeInt p_hash) {
- StringName function = p_function;
+static GDNativePtrUtilityFunction gdnative_variant_get_ptr_utility_function(const GDNativeStringNamePtr p_function, GDNativeInt p_hash) {
+ StringName function = *reinterpret_cast<const StringName *>(p_function);
uint32_t hash = Variant::get_utility_function_hash(function);
if (hash != p_hash) {
- ERR_PRINT_ONCE("Error getting utility function " + String(function) + ", hash mismatch.");
+ ERR_PRINT_ONCE("Error getting utility function " + function + ", hash mismatch.");
return nullptr;
}
return (GDNativePtrUtilityFunction)Variant::get_ptr_utility_function(function);
@@ -836,8 +840,9 @@ static void gdnative_object_destroy(GDNativeObjectPtr p_o) {
memdelete((Object *)p_o);
}
-static GDNativeObjectPtr gdnative_global_get_singleton(const char *p_name) {
- return (GDNativeObjectPtr)Engine::get_singleton()->get_singleton_object(String(p_name));
+static GDNativeObjectPtr gdnative_global_get_singleton(const GDNativeStringNamePtr p_name) {
+ const StringName name = *reinterpret_cast<const StringName *>(p_name);
+ return (GDNativeObjectPtr)Engine::get_singleton()->get_singleton_object(name);
}
static void *gdnative_object_get_instance_binding(GDNativeObjectPtr p_object, void *p_token, const GDNativeInstanceBindingCallbacks *p_callbacks) {
@@ -850,9 +855,10 @@ static void gdnative_object_set_instance_binding(GDNativeObjectPtr p_object, voi
o->set_instance_binding(p_token, p_binding, p_callbacks);
}
-static void gdnative_object_set_instance(GDNativeObjectPtr p_object, const char *p_classname, GDExtensionClassInstancePtr p_instance) {
+static void gdnative_object_set_instance(GDNativeObjectPtr p_object, const GDNativeStringNamePtr p_classname, GDExtensionClassInstancePtr p_instance) {
+ const StringName classname = *reinterpret_cast<const StringName *>(p_classname);
Object *o = (Object *)p_object;
- ClassDB::set_object_extension_instance(o, p_classname, p_instance);
+ ClassDB::set_object_extension_instance(o, classname, p_instance);
}
static GDNativeObjectPtr gdnative_object_get_instance_from_id(GDObjectInstanceID p_instance_id) {
@@ -880,23 +886,26 @@ static GDNativeScriptInstancePtr gdnative_script_instance_create(const GDNativeE
return reinterpret_cast<GDNativeScriptInstancePtr>(script_instance_extension);
}
-static GDNativeMethodBindPtr gdnative_classdb_get_method_bind(const char *p_classname, const char *p_methodname, GDNativeInt p_hash) {
- MethodBind *mb = ClassDB::get_method(StringName(p_classname), StringName(p_methodname));
+static GDNativeMethodBindPtr gdnative_classdb_get_method_bind(const GDNativeStringNamePtr p_classname, const GDNativeStringNamePtr p_methodname, GDNativeInt p_hash) {
+ const StringName classname = *reinterpret_cast<const StringName *>(p_classname);
+ const StringName methodname = *reinterpret_cast<const StringName *>(p_methodname);
+ MethodBind *mb = ClassDB::get_method(classname, methodname);
ERR_FAIL_COND_V(!mb, nullptr);
if (mb->get_hash() != p_hash) {
- ERR_PRINT("Hash mismatch for method '" + String(p_classname) + "." + String(p_methodname) + "'.");
+ ERR_PRINT("Hash mismatch for method '" + classname + "." + methodname + "'.");
return nullptr;
}
- // MethodBind *mb = ClassDB::get_method("Node", "get_name");
return (GDNativeMethodBindPtr)mb;
}
-static GDNativeObjectPtr gdnative_classdb_construct_object(const char *p_classname) {
- return (GDNativeObjectPtr)ClassDB::instantiate(p_classname);
+static GDNativeObjectPtr gdnative_classdb_construct_object(const GDNativeStringNamePtr p_classname) {
+ const StringName classname = *reinterpret_cast<const StringName *>(p_classname);
+ return (GDNativeObjectPtr)ClassDB::instantiate(classname);
}
-static void *gdnative_classdb_get_class_tag(const char *p_classname) {
- ClassDB::ClassInfo *class_info = ClassDB::classes.getptr(p_classname);
+static void *gdnative_classdb_get_class_tag(const GDNativeStringNamePtr p_classname) {
+ const StringName classname = *reinterpret_cast<const StringName *>(p_classname);
+ ClassDB::ClassInfo *class_info = ClassDB::classes.getptr(classname);
return class_info ? class_info->class_ptr : nullptr;
}
diff --git a/core/extension/gdnative_interface.h b/core/extension/gdnative_interface.h
index 1ce50bc186..68eed5a161 100644
--- a/core/extension/gdnative_interface.h
+++ b/core/extension/gdnative_interface.h
@@ -202,21 +202,21 @@ typedef uint64_t (*GDNativeExtensionClassGetRID)(GDExtensionClassInstancePtr p_i
typedef struct {
GDNativeVariantType type;
- const char *name;
- const char *class_name;
+ GDNativeStringNamePtr name;
+ GDNativeStringNamePtr class_name;
uint32_t hint; // Bitfield of `PropertyHint` (defined in `extension_api.json`)
- const char *hint_string;
+ GDNativeStringPtr hint_string;
uint32_t usage; // Bitfield of `PropertyUsageFlags` (defined in `extension_api.json`)
} GDNativePropertyInfo;
typedef struct {
- const char *name;
+ GDNativeStringNamePtr name;
GDNativePropertyInfo return_value;
uint32_t flags; // Bitfield of `GDNativeExtensionClassMethodFlags`
int32_t id;
- GDNativePropertyInfo *arguments;
+ GDNativePropertyInfo *arguments; // array of `argument_count` size
uint32_t argument_count;
- GDNativeVariantPtr default_arguments;
+ GDNativeVariantPtr *default_arguments; // array of `default_argument_count` size
uint32_t default_argument_count;
} GDNativeMethodInfo;
@@ -225,13 +225,13 @@ typedef void (*GDNativeExtensionClassFreePropertyList)(GDExtensionClassInstanceP
typedef GDNativeBool (*GDNativeExtensionClassPropertyCanRevert)(GDExtensionClassInstancePtr p_instance, const GDNativeStringNamePtr p_name);
typedef GDNativeBool (*GDNativeExtensionClassPropertyGetRevert)(GDExtensionClassInstancePtr p_instance, const GDNativeStringNamePtr p_name, GDNativeVariantPtr r_ret);
typedef void (*GDNativeExtensionClassNotification)(GDExtensionClassInstancePtr p_instance, int32_t p_what);
-typedef void (*GDNativeExtensionClassToString)(GDExtensionClassInstancePtr p_instance, GDNativeStringPtr p_out);
+typedef void (*GDNativeExtensionClassToString)(GDExtensionClassInstancePtr p_instance, GDNativeBool *r_is_valid, GDNativeStringPtr p_out);
typedef void (*GDNativeExtensionClassReference)(GDExtensionClassInstancePtr p_instance);
typedef void (*GDNativeExtensionClassUnreference)(GDExtensionClassInstancePtr p_instance);
typedef void (*GDNativeExtensionClassCallVirtual)(GDExtensionClassInstancePtr p_instance, const GDNativeTypePtr *p_args, GDNativeTypePtr r_ret);
typedef GDNativeObjectPtr (*GDNativeExtensionClassCreateInstance)(void *p_userdata);
typedef void (*GDNativeExtensionClassFreeInstance)(void *p_userdata, GDExtensionClassInstancePtr p_instance);
-typedef GDNativeExtensionClassCallVirtual (*GDNativeExtensionClassGetVirtual)(void *p_userdata, const char *p_name);
+typedef GDNativeExtensionClassCallVirtual (*GDNativeExtensionClassGetVirtual)(void *p_userdata, const GDNativeStringNamePtr p_name);
typedef struct {
GDNativeBool is_virtual;
@@ -284,24 +284,21 @@ typedef enum {
typedef void (*GDNativeExtensionClassMethodCall)(void *method_userdata, GDExtensionClassInstancePtr p_instance, const GDNativeVariantPtr *p_args, const GDNativeInt p_argument_count, GDNativeVariantPtr r_return, GDNativeCallError *r_error);
typedef void (*GDNativeExtensionClassMethodPtrCall)(void *method_userdata, GDExtensionClassInstancePtr p_instance, const GDNativeTypePtr *p_args, GDNativeTypePtr r_ret);
-/* passing -1 as argument in the following functions refers to the return type */
-typedef GDNativeVariantType (*GDNativeExtensionClassMethodGetArgumentType)(void *p_method_userdata, int32_t p_argument);
-typedef void (*GDNativeExtensionClassMethodGetArgumentInfo)(void *p_method_userdata, int32_t p_argument, GDNativePropertyInfo *r_info);
-typedef GDNativeExtensionClassMethodArgumentMetadata (*GDNativeExtensionClassMethodGetArgumentMetadata)(void *p_method_userdata, int32_t p_argument);
-
typedef struct {
- const char *name;
+ GDNativeStringNamePtr name;
void *method_userdata;
GDNativeExtensionClassMethodCall call_func;
GDNativeExtensionClassMethodPtrCall ptrcall_func;
uint32_t method_flags; // Bitfield of `GDNativeExtensionClassMethodFlags`
uint32_t argument_count;
GDNativeBool has_return_value;
- GDNativeExtensionClassMethodGetArgumentType get_argument_type_func;
- GDNativeExtensionClassMethodGetArgumentInfo get_argument_info_func; /* name and hint information for the argument can be omitted in release builds. Class name should always be present if it applies. */
- GDNativeExtensionClassMethodGetArgumentMetadata get_argument_metadata_func;
+ GDNativePropertyInfo *return_value_info; // Ignored if `has_return_value` is false
+ GDNativeExtensionClassMethodArgumentMetadata return_value_metadata; // Ignored if `has_return_value` is false
+ /* name and hint information for the argument can be omitted in release builds. Class name should always be present if it applies. */
+ GDNativePropertyInfo *aguments_info; // array of `argument_count` size
+ GDNativeExtensionClassMethodArgumentMetadata *aguments_metadata; // array of `argument_count` size
uint32_t default_argument_count;
- GDNativeVariantPtr *default_arguments;
+ GDNativeVariantPtr *default_arguments; // array of `default_argument_count` size
} GDNativeExtensionClassMethodInfo;
/* SCRIPT INSTANCE EXTENSION */
@@ -312,7 +309,6 @@ typedef GDNativeBool (*GDNativeExtensionScriptInstanceSet)(GDNativeExtensionScri
typedef GDNativeBool (*GDNativeExtensionScriptInstanceGet)(GDNativeExtensionScriptInstanceDataPtr p_instance, const GDNativeStringNamePtr p_name, GDNativeVariantPtr r_ret);
typedef const GDNativePropertyInfo *(*GDNativeExtensionScriptInstanceGetPropertyList)(GDNativeExtensionScriptInstanceDataPtr p_instance, uint32_t *r_count);
typedef void (*GDNativeExtensionScriptInstanceFreePropertyList)(GDNativeExtensionScriptInstanceDataPtr p_instance, const GDNativePropertyInfo *p_list);
-typedef GDNativeVariantType (*GDNativeExtensionScriptInstanceGetPropertyType)(GDNativeExtensionScriptInstanceDataPtr p_instance, const GDNativeStringNamePtr p_name, GDNativeBool *r_is_valid);
typedef GDNativeBool (*GDNativeExtensionScriptInstancePropertyCanRevert)(GDNativeExtensionScriptInstanceDataPtr p_instance, const GDNativeStringNamePtr p_name);
typedef GDNativeBool (*GDNativeExtensionScriptInstancePropertyGetRevert)(GDNativeExtensionScriptInstanceDataPtr p_instance, const GDNativeStringNamePtr p_name, GDNativeVariantPtr r_ret);
@@ -328,7 +324,7 @@ typedef GDNativeBool (*GDNativeExtensionScriptInstanceHasMethod)(GDNativeExtensi
typedef void (*GDNativeExtensionScriptInstanceCall)(GDNativeExtensionScriptInstanceDataPtr p_self, const GDNativeStringNamePtr p_method, const GDNativeVariantPtr *p_args, const GDNativeInt p_argument_count, GDNativeVariantPtr r_return, GDNativeCallError *r_error);
typedef void (*GDNativeExtensionScriptInstanceNotification)(GDNativeExtensionScriptInstanceDataPtr p_instance, int32_t p_what);
-typedef const char *(*GDNativeExtensionScriptInstanceToString)(GDNativeExtensionScriptInstanceDataPtr p_instance, GDNativeBool *r_is_valid);
+typedef void (*GDNativeExtensionScriptInstanceToString)(GDNativeExtensionScriptInstanceDataPtr p_instance, GDNativeBool *r_is_valid, GDNativeStringPtr r_out);
typedef void (*GDNativeExtensionScriptInstanceRefCountIncremented)(GDNativeExtensionScriptInstanceDataPtr p_instance);
typedef GDNativeBool (*GDNativeExtensionScriptInstanceRefCountDecremented)(GDNativeExtensionScriptInstanceDataPtr p_instance);
@@ -349,7 +345,6 @@ typedef struct {
GDNativeExtensionScriptInstanceGet get_func;
GDNativeExtensionScriptInstanceGetPropertyList get_property_list_func;
GDNativeExtensionScriptInstanceFreePropertyList free_property_list_func;
- GDNativeExtensionScriptInstanceGetPropertyType get_property_type_func;
GDNativeExtensionScriptInstancePropertyCanRevert property_can_revert_func;
GDNativeExtensionScriptInstancePropertyGetRevert property_get_revert_func;
@@ -400,7 +395,7 @@ typedef struct {
void (*print_warning)(const char *p_description, const char *p_function, const char *p_file, int32_t p_line);
void (*print_script_error)(const char *p_description, const char *p_function, const char *p_file, int32_t p_line);
- uint64_t (*get_native_struct_size)(const char *p_name);
+ uint64_t (*get_native_struct_size)(const GDNativeStringNamePtr p_name);
/* GODOT VARIANT */
@@ -443,19 +438,19 @@ typedef struct {
GDNativeVariantFromTypeConstructorFunc (*get_variant_from_type_constructor)(GDNativeVariantType p_type);
GDNativeTypeFromVariantConstructorFunc (*get_variant_to_type_constructor)(GDNativeVariantType p_type);
GDNativePtrOperatorEvaluator (*variant_get_ptr_operator_evaluator)(GDNativeVariantOperator p_operator, GDNativeVariantType p_type_a, GDNativeVariantType p_type_b);
- GDNativePtrBuiltInMethod (*variant_get_ptr_builtin_method)(GDNativeVariantType p_type, const char *p_method, GDNativeInt p_hash);
+ GDNativePtrBuiltInMethod (*variant_get_ptr_builtin_method)(GDNativeVariantType p_type, const GDNativeStringNamePtr p_method, GDNativeInt p_hash);
GDNativePtrConstructor (*variant_get_ptr_constructor)(GDNativeVariantType p_type, int32_t p_constructor);
GDNativePtrDestructor (*variant_get_ptr_destructor)(GDNativeVariantType p_type);
void (*variant_construct)(GDNativeVariantType p_type, GDNativeVariantPtr p_base, const GDNativeVariantPtr *p_args, int32_t p_argument_count, GDNativeCallError *r_error);
- GDNativePtrSetter (*variant_get_ptr_setter)(GDNativeVariantType p_type, const char *p_member);
- GDNativePtrGetter (*variant_get_ptr_getter)(GDNativeVariantType p_type, const char *p_member);
+ GDNativePtrSetter (*variant_get_ptr_setter)(GDNativeVariantType p_type, const GDNativeStringNamePtr p_member);
+ GDNativePtrGetter (*variant_get_ptr_getter)(GDNativeVariantType p_type, const GDNativeStringNamePtr p_member);
GDNativePtrIndexedSetter (*variant_get_ptr_indexed_setter)(GDNativeVariantType p_type);
GDNativePtrIndexedGetter (*variant_get_ptr_indexed_getter)(GDNativeVariantType p_type);
GDNativePtrKeyedSetter (*variant_get_ptr_keyed_setter)(GDNativeVariantType p_type);
GDNativePtrKeyedGetter (*variant_get_ptr_keyed_getter)(GDNativeVariantType p_type);
GDNativePtrKeyedChecker (*variant_get_ptr_keyed_checker)(GDNativeVariantType p_type);
- void (*variant_get_constant_value)(GDNativeVariantType p_type, const char *p_constant, GDNativeVariantPtr r_ret);
- GDNativePtrUtilityFunction (*variant_get_ptr_utility_function)(const char *p_function, GDNativeInt p_hash);
+ void (*variant_get_constant_value)(GDNativeVariantType p_type, const GDNativeStringNamePtr p_constant, GDNativeVariantPtr r_ret);
+ GDNativePtrUtilityFunction (*variant_get_ptr_utility_function)(const GDNativeStringNamePtr p_function, GDNativeInt p_hash);
/* extra utilities */
@@ -524,12 +519,12 @@ typedef struct {
void (*object_method_bind_call)(const GDNativeMethodBindPtr p_method_bind, GDNativeObjectPtr p_instance, const GDNativeVariantPtr *p_args, GDNativeInt p_arg_count, GDNativeVariantPtr r_ret, GDNativeCallError *r_error);
void (*object_method_bind_ptrcall)(const GDNativeMethodBindPtr p_method_bind, GDNativeObjectPtr p_instance, const GDNativeTypePtr *p_args, GDNativeTypePtr r_ret);
void (*object_destroy)(GDNativeObjectPtr p_o);
- GDNativeObjectPtr (*global_get_singleton)(const char *p_name);
+ GDNativeObjectPtr (*global_get_singleton)(const GDNativeStringNamePtr p_name);
void *(*object_get_instance_binding)(GDNativeObjectPtr p_o, void *p_token, const GDNativeInstanceBindingCallbacks *p_callbacks);
void (*object_set_instance_binding)(GDNativeObjectPtr p_o, void *p_token, void *p_binding, const GDNativeInstanceBindingCallbacks *p_callbacks);
- void (*object_set_instance)(GDNativeObjectPtr p_o, const char *p_classname, GDExtensionClassInstancePtr p_instance); /* p_classname should be a registered extension class and should extend the p_o object's class. */
+ void (*object_set_instance)(GDNativeObjectPtr p_o, const GDNativeStringNamePtr p_classname, GDExtensionClassInstancePtr p_instance); /* p_classname should be a registered extension class and should extend the p_o object's class. */
GDNativeObjectPtr (*object_cast_to)(const GDNativeObjectPtr p_object, void *p_class_tag);
GDNativeObjectPtr (*object_get_instance_from_id)(GDObjectInstanceID p_instance_id);
@@ -540,20 +535,21 @@ typedef struct {
GDNativeScriptInstancePtr (*script_instance_create)(const GDNativeExtensionScriptInstanceInfo *p_info, GDNativeExtensionScriptInstanceDataPtr p_instance_data);
/* CLASSDB */
- GDNativeObjectPtr (*classdb_construct_object)(const char *p_classname); /* The passed class must be a built-in godot class, or an already-registered extension class. In both case, object_set_instance should be called to fully initialize the object. */
- GDNativeMethodBindPtr (*classdb_get_method_bind)(const char *p_classname, const char *p_methodname, GDNativeInt p_hash);
- void *(*classdb_get_class_tag)(const char *p_classname);
+ GDNativeObjectPtr (*classdb_construct_object)(const GDNativeStringNamePtr p_classname); /* The passed class must be a built-in godot class, or an already-registered extension class. In both case, object_set_instance should be called to fully initialize the object. */
+ GDNativeMethodBindPtr (*classdb_get_method_bind)(const GDNativeStringNamePtr p_classname, const GDNativeStringNamePtr p_methodname, GDNativeInt p_hash);
+ void *(*classdb_get_class_tag)(const GDNativeStringNamePtr p_classname);
/* CLASSDB EXTENSION */
- void (*classdb_register_extension_class)(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_parent_class_name, const GDNativeExtensionClassCreationInfo *p_extension_funcs);
- void (*classdb_register_extension_class_method)(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const GDNativeExtensionClassMethodInfo *p_method_info);
- void (*classdb_register_extension_class_integer_constant)(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_enum_name, const char *p_constant_name, GDNativeInt p_constant_value, GDNativeBool p_is_bitfield);
- void (*classdb_register_extension_class_property)(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const GDNativePropertyInfo *p_info, const char *p_setter, const char *p_getter);
- void (*classdb_register_extension_class_property_group)(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_group_name, const char *p_prefix);
- void (*classdb_register_extension_class_property_subgroup)(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_subgroup_name, const char *p_prefix);
- void (*classdb_register_extension_class_signal)(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_signal_name, const GDNativePropertyInfo *p_argument_info, GDNativeInt p_argument_count);
- void (*classdb_unregister_extension_class)(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name); /* Unregistering a parent class before a class that inherits it will result in failure. Inheritors must be unregistered first. */
+ // Provided parameters for `classdb_register_extension_*` can be safely freed once the function returns
+ void (*classdb_register_extension_class)(const GDNativeExtensionClassLibraryPtr p_library, const GDNativeStringNamePtr p_class_name, const GDNativeStringNamePtr p_parent_class_name, const GDNativeExtensionClassCreationInfo *p_extension_funcs);
+ void (*classdb_register_extension_class_method)(const GDNativeExtensionClassLibraryPtr p_library, const GDNativeStringNamePtr p_class_name, const GDNativeExtensionClassMethodInfo *p_method_info);
+ void (*classdb_register_extension_class_integer_constant)(const GDNativeExtensionClassLibraryPtr p_library, const GDNativeStringNamePtr p_class_name, const GDNativeStringNamePtr p_enum_name, const GDNativeStringNamePtr p_constant_name, GDNativeInt p_constant_value, GDNativeBool p_is_bitfield);
+ void (*classdb_register_extension_class_property)(const GDNativeExtensionClassLibraryPtr p_library, const GDNativeStringNamePtr p_class_name, const GDNativePropertyInfo *p_info, const GDNativeStringNamePtr p_setter, const GDNativeStringNamePtr p_getter);
+ void (*classdb_register_extension_class_property_group)(const GDNativeExtensionClassLibraryPtr p_library, const GDNativeStringNamePtr p_class_name, const GDNativeStringPtr p_group_name, const GDNativeStringPtr p_prefix);
+ void (*classdb_register_extension_class_property_subgroup)(const GDNativeExtensionClassLibraryPtr p_library, const GDNativeStringNamePtr p_class_name, const GDNativeStringPtr p_subgroup_name, const GDNativeStringPtr p_prefix);
+ void (*classdb_register_extension_class_signal)(const GDNativeExtensionClassLibraryPtr p_library, const GDNativeStringNamePtr p_class_name, const GDNativeStringNamePtr p_signal_name, const GDNativePropertyInfo *p_argument_info, GDNativeInt p_argument_count);
+ void (*classdb_unregister_extension_class)(const GDNativeExtensionClassLibraryPtr p_library, const GDNativeStringNamePtr p_class_name); /* Unregistering a parent class before a class that inherits it will result in failure. Inheritors must be unregistered first. */
void (*get_library_path)(const GDNativeExtensionClassLibraryPtr p_library, GDNativeStringPtr r_path);
diff --git a/core/extension/native_extension.cpp b/core/extension/native_extension.cpp
index cc019584a5..8bbb72fd82 100644
--- a/core/extension/native_extension.cpp
+++ b/core/extension/native_extension.cpp
@@ -42,26 +42,37 @@ String NativeExtension::get_extension_list_config_file() {
class NativeExtensionMethodBind : public MethodBind {
GDNativeExtensionClassMethodCall call_func;
GDNativeExtensionClassMethodPtrCall ptrcall_func;
- GDNativeExtensionClassMethodGetArgumentType get_argument_type_func;
- GDNativeExtensionClassMethodGetArgumentInfo get_argument_info_func;
- GDNativeExtensionClassMethodGetArgumentMetadata get_argument_metadata_func;
void *method_userdata;
bool vararg;
+ PropertyInfo return_value_info;
+ GodotTypeInfo::Metadata return_value_metadata;
+ List<PropertyInfo> arguments_info;
+ List<GodotTypeInfo::Metadata> arguments_metadata;
protected:
virtual Variant::Type _gen_argument_type(int p_arg) const override {
- return Variant::Type(get_argument_type_func(method_userdata, p_arg));
+ if (p_arg < 0) {
+ return return_value_info.type;
+ } else {
+ return arguments_info[p_arg].type;
+ }
}
virtual PropertyInfo _gen_argument_type_info(int p_arg) const override {
- GDNativePropertyInfo pinfo;
- get_argument_info_func(method_userdata, p_arg, &pinfo);
- return PropertyInfo(pinfo);
+ if (p_arg < 0) {
+ return return_value_info;
+ } else {
+ return arguments_info[p_arg];
+ }
}
public:
#ifdef DEBUG_METHODS_ENABLED
virtual GodotTypeInfo::Metadata get_argument_meta(int p_arg) const override {
- return GodotTypeInfo::Metadata(get_argument_metadata_func(method_userdata, p_arg));
+ if (p_arg < 0) {
+ return return_value_metadata;
+ } else {
+ return arguments_metadata[p_arg];
+ }
}
#endif
@@ -89,10 +100,17 @@ public:
method_userdata = p_method_info->method_userdata;
call_func = p_method_info->call_func;
ptrcall_func = p_method_info->ptrcall_func;
- get_argument_type_func = p_method_info->get_argument_type_func;
- get_argument_info_func = p_method_info->get_argument_info_func;
- get_argument_metadata_func = p_method_info->get_argument_metadata_func;
- set_name(p_method_info->name);
+ set_name(*reinterpret_cast<StringName *>(p_method_info->name));
+
+ if (p_method_info->has_return_value) {
+ return_value_info = PropertyInfo(*p_method_info->return_value_info);
+ return_value_metadata = GodotTypeInfo::Metadata(p_method_info->return_value_metadata);
+ }
+
+ for (uint32_t i = 0; i < p_method_info->argument_count; i++) {
+ arguments_info.push_back(PropertyInfo(p_method_info->aguments_info[i]));
+ arguments_metadata.push_back(GodotTypeInfo::Metadata(p_method_info->aguments_metadata[i]));
+ }
set_hint_flags(p_method_info->method_flags);
@@ -117,15 +135,15 @@ public:
static GDNativeInterface gdnative_interface;
-void NativeExtension::_register_extension_class(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_parent_class_name, const GDNativeExtensionClassCreationInfo *p_extension_funcs) {
+void NativeExtension::_register_extension_class(const GDNativeExtensionClassLibraryPtr p_library, const GDNativeStringNamePtr p_class_name, const GDNativeStringNamePtr p_parent_class_name, const GDNativeExtensionClassCreationInfo *p_extension_funcs) {
NativeExtension *self = static_cast<NativeExtension *>(p_library);
- StringName class_name = p_class_name;
+ StringName class_name = *reinterpret_cast<StringName *>(p_class_name);
+ StringName parent_class_name = *reinterpret_cast<StringName *>(p_parent_class_name);
ERR_FAIL_COND_MSG(!String(class_name).is_valid_identifier(), "Attempt to register extension class '" + class_name + "', which is not a valid class identifier.");
ERR_FAIL_COND_MSG(ClassDB::class_exists(class_name), "Attempt to register extension class '" + class_name + "', which appears to be already registered.");
Extension *parent_extension = nullptr;
- StringName parent_class_name = p_parent_class_name;
if (self->extension_classes.has(parent_class_name)) {
parent_extension = &self->extension_classes[parent_class_name];
@@ -172,11 +190,11 @@ void NativeExtension::_register_extension_class(const GDNativeExtensionClassLibr
ClassDB::register_extension_class(&extension->native_extension);
}
-void NativeExtension::_register_extension_class_method(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const GDNativeExtensionClassMethodInfo *p_method_info) {
+void NativeExtension::_register_extension_class_method(const GDNativeExtensionClassLibraryPtr p_library, const GDNativeStringNamePtr p_class_name, const GDNativeExtensionClassMethodInfo *p_method_info) {
NativeExtension *self = static_cast<NativeExtension *>(p_library);
- StringName class_name = p_class_name;
- StringName method_name = p_method_info->name;
+ StringName class_name = *reinterpret_cast<const StringName *>(p_class_name);
+ StringName method_name = *reinterpret_cast<const StringName *>(p_method_info->name);
ERR_FAIL_COND_MSG(!self->extension_classes.has(class_name), "Attempt to register extension method '" + String(method_name) + "' for unexisting class '" + class_name + "'.");
//Extension *extension = &self->extension_classes[class_name];
@@ -186,56 +204,63 @@ void NativeExtension::_register_extension_class_method(const GDNativeExtensionCl
ClassDB::bind_method_custom(class_name, method);
}
-void NativeExtension::_register_extension_class_integer_constant(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_enum_name, const char *p_constant_name, GDNativeInt p_constant_value, GDNativeBool p_is_bitfield) {
+void NativeExtension::_register_extension_class_integer_constant(const GDNativeExtensionClassLibraryPtr p_library, const GDNativeStringNamePtr p_class_name, const GDNativeStringNamePtr p_enum_name, const GDNativeStringNamePtr p_constant_name, GDNativeInt p_constant_value, GDNativeBool p_is_bitfield) {
NativeExtension *self = static_cast<NativeExtension *>(p_library);
- StringName class_name = p_class_name;
- ERR_FAIL_COND_MSG(!self->extension_classes.has(class_name), "Attempt to register extension constant '" + String(p_constant_name) + "' for unexisting class '" + class_name + "'.");
-
- //Extension *extension = &self->extension_classes[class_name];
+ StringName class_name = *reinterpret_cast<const StringName *>(p_class_name);
+ StringName enum_name = *reinterpret_cast<const StringName *>(p_enum_name);
+ StringName constant_name = *reinterpret_cast<const StringName *>(p_constant_name);
+ ERR_FAIL_COND_MSG(!self->extension_classes.has(class_name), "Attempt to register extension constant '" + constant_name + "' for unexisting class '" + class_name + "'.");
- ClassDB::bind_integer_constant(class_name, p_enum_name, p_constant_name, p_constant_value, p_is_bitfield);
+ ClassDB::bind_integer_constant(class_name, enum_name, constant_name, p_constant_value, p_is_bitfield);
}
-void NativeExtension::_register_extension_class_property(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const GDNativePropertyInfo *p_info, const char *p_setter, const char *p_getter) {
+void NativeExtension::_register_extension_class_property(const GDNativeExtensionClassLibraryPtr p_library, const GDNativeStringNamePtr p_class_name, const GDNativePropertyInfo *p_info, const GDNativeStringNamePtr p_setter, const GDNativeStringNamePtr p_getter) {
NativeExtension *self = static_cast<NativeExtension *>(p_library);
- StringName class_name = p_class_name;
- String property_name = p_info->name;
+ StringName class_name = *reinterpret_cast<const StringName *>(p_class_name);
+ StringName setter = *reinterpret_cast<const StringName *>(p_setter);
+ StringName getter = *reinterpret_cast<const StringName *>(p_getter);
+ String property_name = *reinterpret_cast<const StringName *>(p_info->name);
ERR_FAIL_COND_MSG(!self->extension_classes.has(class_name), "Attempt to register extension class property '" + property_name + "' for unexisting class '" + class_name + "'.");
//Extension *extension = &self->extension_classes[class_name];
PropertyInfo pinfo(*p_info);
- ClassDB::add_property(class_name, pinfo, p_setter, p_getter);
+ ClassDB::add_property(class_name, pinfo, setter, getter);
}
-void NativeExtension::_register_extension_class_property_group(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_group_name, const char *p_prefix) {
+void NativeExtension::_register_extension_class_property_group(const GDNativeExtensionClassLibraryPtr p_library, const GDNativeStringNamePtr p_class_name, const GDNativeStringPtr p_group_name, const GDNativeStringPtr p_prefix) {
NativeExtension *self = static_cast<NativeExtension *>(p_library);
- StringName class_name = p_class_name;
- ERR_FAIL_COND_MSG(!self->extension_classes.has(class_name), "Attempt to register extension class property group '" + String(p_group_name) + "' for unexisting class '" + class_name + "'.");
+ StringName class_name = *reinterpret_cast<const StringName *>(p_class_name);
+ String group_name = *reinterpret_cast<const String *>(p_group_name);
+ String prefix = *reinterpret_cast<const String *>(p_prefix);
+ ERR_FAIL_COND_MSG(!self->extension_classes.has(class_name), "Attempt to register extension class property group '" + group_name + "' for unexisting class '" + class_name + "'.");
- ClassDB::add_property_group(class_name, p_group_name, p_prefix);
+ ClassDB::add_property_group(class_name, group_name, prefix);
}
-void NativeExtension::_register_extension_class_property_subgroup(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_subgroup_name, const char *p_prefix) {
+void NativeExtension::_register_extension_class_property_subgroup(const GDNativeExtensionClassLibraryPtr p_library, const GDNativeStringNamePtr p_class_name, const GDNativeStringPtr p_subgroup_name, const GDNativeStringPtr p_prefix) {
NativeExtension *self = static_cast<NativeExtension *>(p_library);
- StringName class_name = p_class_name;
- ERR_FAIL_COND_MSG(!self->extension_classes.has(class_name), "Attempt to register extension class property subgroup '" + String(p_subgroup_name) + "' for unexisting class '" + class_name + "'.");
+ StringName class_name = *reinterpret_cast<const StringName *>(p_class_name);
+ String subgroup_name = *reinterpret_cast<const String *>(p_subgroup_name);
+ String prefix = *reinterpret_cast<const String *>(p_prefix);
+ ERR_FAIL_COND_MSG(!self->extension_classes.has(class_name), "Attempt to register extension class property subgroup '" + subgroup_name + "' for unexisting class '" + class_name + "'.");
- ClassDB::add_property_subgroup(class_name, p_subgroup_name, p_prefix);
+ ClassDB::add_property_subgroup(class_name, subgroup_name, prefix);
}
-void NativeExtension::_register_extension_class_signal(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_signal_name, const GDNativePropertyInfo *p_argument_info, GDNativeInt p_argument_count) {
+void NativeExtension::_register_extension_class_signal(const GDNativeExtensionClassLibraryPtr p_library, const GDNativeStringNamePtr p_class_name, const GDNativeStringNamePtr p_signal_name, const GDNativePropertyInfo *p_argument_info, GDNativeInt p_argument_count) {
NativeExtension *self = static_cast<NativeExtension *>(p_library);
- StringName class_name = p_class_name;
- ERR_FAIL_COND_MSG(!self->extension_classes.has(class_name), "Attempt to register extension class signal '" + String(p_signal_name) + "' for unexisting class '" + class_name + "'.");
+ StringName class_name = *reinterpret_cast<const StringName *>(p_class_name);
+ StringName signal_name = *reinterpret_cast<const StringName *>(p_signal_name);
+ ERR_FAIL_COND_MSG(!self->extension_classes.has(class_name), "Attempt to register extension class signal '" + signal_name + "' for unexisting class '" + class_name + "'.");
MethodInfo s;
- s.name = p_signal_name;
+ s.name = signal_name;
for (int i = 0; i < p_argument_count; i++) {
PropertyInfo arg(p_argument_info[i]);
s.arguments.push_back(arg);
@@ -243,10 +268,10 @@ void NativeExtension::_register_extension_class_signal(const GDNativeExtensionCl
ClassDB::add_signal(class_name, s);
}
-void NativeExtension::_unregister_extension_class(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name) {
+void NativeExtension::_unregister_extension_class(const GDNativeExtensionClassLibraryPtr p_library, const GDNativeStringNamePtr p_class_name) {
NativeExtension *self = static_cast<NativeExtension *>(p_library);
- StringName class_name = p_class_name;
+ StringName class_name = *reinterpret_cast<const StringName *>(p_class_name);
ERR_FAIL_COND_MSG(!self->extension_classes.has(class_name), "Attempt to unregister unexisting extension class '" + class_name + "'.");
Extension *ext = &self->extension_classes[class_name];
ERR_FAIL_COND_MSG(ext->native_extension.children.size(), "Attempt to unregister class '" + class_name + "' while other extension classes inherit from it.");
diff --git a/core/extension/native_extension.h b/core/extension/native_extension.h
index b7238d2899..70f6f9f039 100644
--- a/core/extension/native_extension.h
+++ b/core/extension/native_extension.h
@@ -47,14 +47,14 @@ class NativeExtension : public Resource {
HashMap<StringName, Extension> extension_classes;
- static void _register_extension_class(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_parent_class_name, const GDNativeExtensionClassCreationInfo *p_extension_funcs);
- static void _register_extension_class_method(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const GDNativeExtensionClassMethodInfo *p_method_info);
- static void _register_extension_class_integer_constant(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_enum_name, const char *p_constant_name, GDNativeInt p_constant_value, GDNativeBool p_is_bitfield);
- static void _register_extension_class_property(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const GDNativePropertyInfo *p_info, const char *p_setter, const char *p_getter);
- static void _register_extension_class_property_group(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_group_name, const char *p_prefix);
- static void _register_extension_class_property_subgroup(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_subgroup_name, const char *p_prefix);
- static void _register_extension_class_signal(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_signal_name, const GDNativePropertyInfo *p_argument_info, GDNativeInt p_argument_count);
- static void _unregister_extension_class(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name);
+ static void _register_extension_class(const GDNativeExtensionClassLibraryPtr p_library, const GDNativeStringNamePtr p_class_name, const GDNativeStringNamePtr p_parent_class_name, const GDNativeExtensionClassCreationInfo *p_extension_funcs);
+ static void _register_extension_class_method(const GDNativeExtensionClassLibraryPtr p_library, const GDNativeStringNamePtr p_class_name, const GDNativeExtensionClassMethodInfo *p_method_info);
+ static void _register_extension_class_integer_constant(const GDNativeExtensionClassLibraryPtr p_library, const GDNativeStringNamePtr p_class_name, const GDNativeStringNamePtr p_enum_name, const GDNativeStringNamePtr p_constant_name, GDNativeInt p_constant_value, GDNativeBool p_is_bitfield);
+ static void _register_extension_class_property(const GDNativeExtensionClassLibraryPtr p_library, const GDNativeStringNamePtr p_class_name, const GDNativePropertyInfo *p_info, const GDNativeStringNamePtr p_setter, const GDNativeStringNamePtr p_getter);
+ static void _register_extension_class_property_group(const GDNativeExtensionClassLibraryPtr p_library, const GDNativeStringNamePtr p_class_name, const GDNativeStringNamePtr p_group_name, const GDNativeStringNamePtr p_prefix);
+ static void _register_extension_class_property_subgroup(const GDNativeExtensionClassLibraryPtr p_library, const GDNativeStringNamePtr p_class_name, const GDNativeStringNamePtr p_subgroup_name, const GDNativeStringNamePtr p_prefix);
+ static void _register_extension_class_signal(const GDNativeExtensionClassLibraryPtr p_library, const GDNativeStringNamePtr p_class_name, const GDNativeStringNamePtr p_signal_name, const GDNativePropertyInfo *p_argument_info, GDNativeInt p_argument_count);
+ static void _unregister_extension_class(const GDNativeExtensionClassLibraryPtr p_library, const GDNativeStringNamePtr p_class_name);
static void _get_library_path(const GDNativeExtensionClassLibraryPtr p_library, GDNativeStringPtr r_path);
GDNativeInitialization initialization;
diff --git a/core/object/class_db.cpp b/core/object/class_db.cpp
index afde6863a3..ac6ad0fdd2 100644
--- a/core/object/class_db.cpp
+++ b/core/object/class_db.cpp
@@ -1460,7 +1460,7 @@ Variant ClassDB::class_get_default_property_value(const StringName &p_class, con
if (Engine::get_singleton()->has_singleton(p_class)) {
c = Engine::get_singleton()->get_singleton_object(p_class);
cleanup_c = false;
- } else if (ClassDB::can_instantiate(p_class)) { // Keep this condition in sync with doc_tools.cpp get_documentation_default_value.
+ } else if (ClassDB::can_instantiate(p_class) && !ClassDB::is_virtual(p_class)) { // Keep this condition in sync with doc_tools.cpp get_documentation_default_value.
c = ClassDB::instantiate(p_class);
cleanup_c = true;
}
diff --git a/core/object/make_virtuals.py b/core/object/make_virtuals.py
index 326a9277ff..61bf6d900a 100644
--- a/core/object/make_virtuals.py
+++ b/core/object/make_virtuals.py
@@ -16,7 +16,8 @@ _FORCE_INLINE_ bool _gdvirtual_##m_name##_call($CALLARGS) $CONST { \\
} \\
}\\
if (unlikely(_get_extension() && !_gdvirtual_##m_name##_initialized)) {\\
- _gdvirtual_##m_name = (_get_extension() && _get_extension()->get_virtual) ? _get_extension()->get_virtual(_get_extension()->class_userdata, #m_name) : (GDNativeExtensionClassCallVirtual) nullptr;\\
+ /* TODO: C-style cast because GDNativeStringNamePtr's const qualifier is broken (see https://github.com/godotengine/godot/pull/67751) */\\
+ _gdvirtual_##m_name = (_get_extension() && _get_extension()->get_virtual) ? _get_extension()->get_virtual(_get_extension()->class_userdata, (GDNativeStringNamePtr)&_gdvirtual_##m_name##_sn) : (GDNativeExtensionClassCallVirtual) nullptr;\\
_gdvirtual_##m_name##_initialized = true;\\
}\\
if (_gdvirtual_##m_name) {\\
@@ -40,7 +41,8 @@ _FORCE_INLINE_ bool _gdvirtual_##m_name##_overridden() const { \\
return _script_instance->has_method(_gdvirtual_##m_name##_sn);\\
}\\
if (unlikely(_get_extension() && !_gdvirtual_##m_name##_initialized)) {\\
- _gdvirtual_##m_name = (_get_extension() && _get_extension()->get_virtual) ? _get_extension()->get_virtual(_get_extension()->class_userdata, #m_name) : (GDNativeExtensionClassCallVirtual) nullptr;\\
+ /* TODO: C-style cast because GDNativeStringNamePtr's const qualifier is broken (see https://github.com/godotengine/godot/pull/67751) */\\
+ _gdvirtual_##m_name = (_get_extension() && _get_extension()->get_virtual) ? _get_extension()->get_virtual(_get_extension()->class_userdata, (GDNativeStringNamePtr)&_gdvirtual_##m_name##_sn) : (GDNativeExtensionClassCallVirtual) nullptr;\\
_gdvirtual_##m_name##_initialized = true;\\
}\\
if (_gdvirtual_##m_name) {\\
diff --git a/core/object/object.cpp b/core/object/object.cpp
index 540b9a8f19..d27e0d7621 100644
--- a/core/object/object.cpp
+++ b/core/object/object.cpp
@@ -808,7 +808,8 @@ String Object::to_string() {
}
if (_extension && _extension->to_string) {
String ret;
- _extension->to_string(_extension_instance, &ret);
+ GDNativeBool is_valid;
+ _extension->to_string(_extension_instance, &is_valid, &ret);
return ret;
}
return "<" + get_class() + "#" + itos(get_instance_id()) + ">";
diff --git a/core/object/object.h b/core/object/object.h
index 8c647cda40..7bb88998a2 100644
--- a/core/object/object.h
+++ b/core/object/object.h
@@ -192,10 +192,10 @@ struct PropertyInfo {
explicit PropertyInfo(const GDNativePropertyInfo &pinfo) :
type((Variant::Type)pinfo.type),
- name(pinfo.name),
- class_name(pinfo.class_name), // can be null
+ name(*reinterpret_cast<StringName *>(pinfo.name)),
+ class_name(*reinterpret_cast<StringName *>(pinfo.class_name)),
hint((PropertyHint)pinfo.hint),
- hint_string(pinfo.hint_string), // can be null
+ hint_string(*reinterpret_cast<String *>(pinfo.hint_string)),
usage(pinfo.usage) {}
bool operator==(const PropertyInfo &p_info) const {
@@ -242,6 +242,20 @@ struct MethodInfo {
MethodInfo() {}
+ explicit MethodInfo(const GDNativeMethodInfo &pinfo) :
+ name(*reinterpret_cast<StringName *>(pinfo.name)),
+ return_val(PropertyInfo(pinfo.return_value)),
+ flags(pinfo.flags),
+ id(pinfo.id) {
+ for (uint32_t j = 0; j < pinfo.argument_count; j++) {
+ arguments.push_back(PropertyInfo(pinfo.arguments[j]));
+ }
+ const Variant *def_values = (const Variant *)pinfo.default_arguments;
+ for (uint32_t j = 0; j < pinfo.default_argument_count; j++) {
+ default_arguments.push_back(def_values[j]);
+ }
+ }
+
void _push_params(const PropertyInfo &p_param) {
arguments.push_back(p_param);
}
diff --git a/core/object/script_language_extension.h b/core/object/script_language_extension.h
index c32fb9d85b..c287a6f71a 100644
--- a/core/object/script_language_extension.h
+++ b/core/object/script_language_extension.h
@@ -681,16 +681,21 @@ public:
}
}
virtual Variant::Type get_property_type(const StringName &p_name, bool *r_is_valid = nullptr) const override {
- if (native_info->get_property_type_func) {
- GDNativeBool is_valid = 0;
- GDNativeVariantType type = native_info->get_property_type_func(instance, (const GDNativeStringNamePtr)&p_name, &is_valid);
- if (r_is_valid) {
- *r_is_valid = is_valid != 0;
+ Variant::Type type = Variant::Type::NIL;
+ if (native_info->get_property_list_func) {
+ uint32_t pcount;
+ const GDNativePropertyInfo *pinfo = native_info->get_property_list_func(instance, &pcount);
+ for (uint32_t i = 0; i < pcount; i++) {
+ if (p_name == *reinterpret_cast<StringName *>(pinfo->name)) {
+ type = Variant::Type(pinfo->type);
+ break;
+ }
+ }
+ if (native_info->free_property_list_func) {
+ native_info->free_property_list_func(instance, pinfo);
}
-
- return Variant::Type(type);
}
- return Variant::NIL;
+ return type;
}
virtual bool property_can_revert(const StringName &p_name) const override {
@@ -727,19 +732,7 @@ public:
uint32_t mcount;
const GDNativeMethodInfo *minfo = native_info->get_method_list_func(instance, &mcount);
for (uint32_t i = 0; i < mcount; i++) {
- MethodInfo m;
- m.name = minfo[i].name;
- m.flags = minfo[i].flags;
- m.id = minfo[i].id;
- m.return_val = PropertyInfo(minfo[i].return_value);
- for (uint32_t j = 0; j < minfo[i].argument_count; j++) {
- m.arguments.push_back(PropertyInfo(minfo[i].arguments[j]));
- }
- const Variant *def_values = (const Variant *)minfo[i].default_arguments;
- for (uint32_t j = 0; j < minfo[i].default_argument_count; j++) {
- m.default_arguments.push_back(def_values[j]);
- }
- p_list->push_back(m);
+ p_list->push_back(MethodInfo(minfo[i]));
}
if (native_info->free_method_list_func) {
native_info->free_method_list_func(instance, minfo);
@@ -773,7 +766,8 @@ public:
virtual String to_string(bool *r_valid) override {
if (native_info->to_string_func) {
GDNativeBool valid;
- String ret = native_info->to_string_func(instance, &valid);
+ String ret;
+ native_info->to_string_func(instance, &valid, reinterpret_cast<GDNativeStringPtr>(&ret));
if (r_valid) {
*r_valid = valid != 0;
}
diff --git a/doc/classes/AnimatedTexture.xml b/doc/classes/AnimatedTexture.xml
index f0c86ba47b..57a7f86901 100644
--- a/doc/classes/AnimatedTexture.xml
+++ b/doc/classes/AnimatedTexture.xml
@@ -57,6 +57,7 @@
<member name="pause" type="bool" setter="set_pause" getter="get_pause" default="false">
If [code]true[/code], the animation will pause where it currently is (i.e. at [member current_frame]). The animation will continue from where it was paused when changing this property to [code]false[/code].
</member>
+ <member name="resource_local_to_scene" type="bool" setter="set_local_to_scene" getter="is_local_to_scene" overrides="Resource" default="false" />
<member name="speed_scale" type="float" setter="set_speed_scale" getter="get_speed_scale" default="1.0">
The animation speed is multiplied by this value. If set to a negative value, the animation is played in reverse.
</member>
diff --git a/doc/classes/AtlasTexture.xml b/doc/classes/AtlasTexture.xml
index 809d983a9d..fc75459e46 100644
--- a/doc/classes/AtlasTexture.xml
+++ b/doc/classes/AtlasTexture.xml
@@ -23,5 +23,6 @@
<member name="region" type="Rect2" setter="set_region" getter="get_region" default="Rect2(0, 0, 0, 0)">
The region used to draw the [member atlas].
</member>
+ <member name="resource_local_to_scene" type="bool" setter="set_local_to_scene" getter="is_local_to_scene" overrides="Resource" default="false" />
</members>
</class>
diff --git a/doc/classes/CameraTexture.xml b/doc/classes/CameraTexture.xml
index 8eedfe3580..e7020c869e 100644
--- a/doc/classes/CameraTexture.xml
+++ b/doc/classes/CameraTexture.xml
@@ -16,6 +16,7 @@
<member name="camera_is_active" type="bool" setter="set_camera_active" getter="get_camera_active" default="false">
Convenience property that gives access to the active property of the [CameraFeed].
</member>
+ <member name="resource_local_to_scene" type="bool" setter="set_local_to_scene" getter="is_local_to_scene" overrides="Resource" default="false" />
<member name="which_feed" type="int" setter="set_which_feed" getter="get_which_feed" enum="CameraServer.FeedImage" default="0">
Which image within the [CameraFeed] we want access to, important if the camera image is split in a Y and CbCr component.
</member>
diff --git a/doc/classes/CanvasTexture.xml b/doc/classes/CanvasTexture.xml
index 2dc83790c7..d5bf65835f 100644
--- a/doc/classes/CanvasTexture.xml
+++ b/doc/classes/CanvasTexture.xml
@@ -17,6 +17,7 @@
The normal map texture to use. Only has a visible effect if [Light2D]s are affecting this [CanvasTexture].
[b]Note:[/b] Godot expects the normal map to use X+, Y+, and Z+ coordinates. See [url=http://wiki.polycount.com/wiki/Normal_Map_Technical_Details#Common_Swizzle_Coordinates]this page[/url] for a comparison of normal map coordinates expected by popular engines.
</member>
+ <member name="resource_local_to_scene" type="bool" setter="set_local_to_scene" getter="is_local_to_scene" overrides="Resource" default="false" />
<member name="specular_color" type="Color" setter="set_specular_color" getter="get_specular_color" default="Color(1, 1, 1, 1)">
The multiplier for specular reflection colors. The [Light2D]'s color is also taken into account when determining the reflection color. Only has a visible effect if [Light2D]s are affecting this [CanvasTexture].
</member>
diff --git a/doc/classes/CompressedTexture2D.xml b/doc/classes/CompressedTexture2D.xml
index f74265b8d5..f7464d8951 100644
--- a/doc/classes/CompressedTexture2D.xml
+++ b/doc/classes/CompressedTexture2D.xml
@@ -21,5 +21,6 @@
<member name="load_path" type="String" setter="load" getter="get_load_path" default="&quot;&quot;">
The CompressedTexture's file path to a [code].ctex[/code] file.
</member>
+ <member name="resource_local_to_scene" type="bool" setter="set_local_to_scene" getter="is_local_to_scene" overrides="Resource" default="false" />
</members>
</class>
diff --git a/doc/classes/CurveTexture.xml b/doc/classes/CurveTexture.xml
index 85473fc237..03e008d738 100644
--- a/doc/classes/CurveTexture.xml
+++ b/doc/classes/CurveTexture.xml
@@ -13,6 +13,7 @@
<member name="curve" type="Curve" setter="set_curve" getter="get_curve">
The [Curve] that is rendered onto the texture.
</member>
+ <member name="resource_local_to_scene" type="bool" setter="set_local_to_scene" getter="is_local_to_scene" overrides="Resource" default="false" />
<member name="texture_mode" type="int" setter="set_texture_mode" getter="get_texture_mode" enum="CurveTexture.TextureMode" default="0">
The format the texture should be generated with. When passing a CurveTexture as a input to a [Shader], this may need to be adjusted.
</member>
diff --git a/doc/classes/CurveXYZTexture.xml b/doc/classes/CurveXYZTexture.xml
index e3f2e8fc45..8c4e2dce0f 100644
--- a/doc/classes/CurveXYZTexture.xml
+++ b/doc/classes/CurveXYZTexture.xml
@@ -19,6 +19,7 @@
<member name="curve_z" type="Curve" setter="set_curve_z" getter="get_curve_z">
The [Curve] that is rendered onto the texture's blue channel.
</member>
+ <member name="resource_local_to_scene" type="bool" setter="set_local_to_scene" getter="is_local_to_scene" overrides="Resource" default="false" />
<member name="width" type="int" setter="set_width" getter="get_width" default="256">
The width of the texture (in pixels). Higher values make it possible to represent high-frequency data better (such as sudden direction changes), at the cost of increased generation time and memory usage.
</member>
diff --git a/doc/classes/DisplayServer.xml b/doc/classes/DisplayServer.xml
index 113987bb52..76c67fd704 100644
--- a/doc/classes/DisplayServer.xml
+++ b/doc/classes/DisplayServer.xml
@@ -1725,9 +1725,17 @@
</constant>
<constant name="WINDOW_VIEW" value="2" enum="HandleType">
Window view:
+ - Windows: [code]HDC[/code] for the window (only with the GL Compatibility renderer).
- macOS: [code]NSView*[/code] for the window main view.
- iOS: [code]UIView*[/code] for the window main view.
</constant>
+ <constant name="OPENGL_CONTEXT" value="3" enum="HandleType">
+ OpenGL context (only with the GL Compatibility renderer):
+ - Windows: [code]HGLRC[/code] for the window.
+ - Linux: [code]GLXContext*[/code] for the window.
+ - MacOS: [code]NSOpenGLContext*[/code] for the window.
+ - Android: [code]EGLContext[/code] for the window.
+ </constant>
<constant name="TTS_UTTERANCE_STARTED" value="0" enum="TTSUtteranceEvent">
Utterance has begun to be spoken.
</constant>
diff --git a/doc/classes/EditorSpinSlider.xml b/doc/classes/EditorSpinSlider.xml
index 784a3c1214..de105b32e1 100644
--- a/doc/classes/EditorSpinSlider.xml
+++ b/doc/classes/EditorSpinSlider.xml
@@ -22,6 +22,8 @@
<member name="read_only" type="bool" setter="set_read_only" getter="is_read_only" default="false">
If [code]true[/code], the slider can't be interacted with.
</member>
+ <member name="size_flags_vertical" type="int" setter="set_v_size_flags" getter="get_v_size_flags" overrides="Control" default="1" />
+ <member name="step" type="float" setter="set_step" getter="get_step" overrides="Range" default="1.0" />
<member name="suffix" type="String" setter="set_suffix" getter="get_suffix" default="&quot;&quot;">
The suffix to display after the value (in a faded color). This should generally be a plural word. You may have to use an abbreviation if the suffix is too long to be displayed.
</member>
diff --git a/doc/classes/GradientTexture1D.xml b/doc/classes/GradientTexture1D.xml
index 3254754ac1..fa572eeed0 100644
--- a/doc/classes/GradientTexture1D.xml
+++ b/doc/classes/GradientTexture1D.xml
@@ -12,6 +12,7 @@
<member name="gradient" type="Gradient" setter="set_gradient" getter="get_gradient">
The [Gradient] that will be used to fill the texture.
</member>
+ <member name="resource_local_to_scene" type="bool" setter="set_local_to_scene" getter="is_local_to_scene" overrides="Resource" default="false" />
<member name="use_hdr" type="bool" setter="set_use_hdr" getter="is_using_hdr" default="false">
If [code]true[/code], the generated texture will support high dynamic range ([constant Image.FORMAT_RGBAF] format). This allows for glow effects to work if [member Environment.glow_enabled] is [code]true[/code]. If [code]false[/code], the generated texture will use low dynamic range; overbright colors will be clamped ([constant Image.FORMAT_RGBA8] format).
</member>
diff --git a/doc/classes/GradientTexture2D.xml b/doc/classes/GradientTexture2D.xml
index 7561f1b947..87d86e7a59 100644
--- a/doc/classes/GradientTexture2D.xml
+++ b/doc/classes/GradientTexture2D.xml
@@ -27,6 +27,7 @@
<member name="repeat" type="int" setter="set_repeat" getter="get_repeat" enum="GradientTexture2D.Repeat" default="0">
The gradient repeat type, one of the [enum Repeat] values. The texture is filled starting from [member fill_from] to [member fill_to] offsets by default, but the gradient fill can be repeated to cover the entire texture.
</member>
+ <member name="resource_local_to_scene" type="bool" setter="set_local_to_scene" getter="is_local_to_scene" overrides="Resource" default="false" />
<member name="use_hdr" type="bool" setter="set_use_hdr" getter="is_using_hdr" default="false">
If [code]true[/code], the generated texture will support high dynamic range ([constant Image.FORMAT_RGBAF] format). This allows for glow effects to work if [member Environment.glow_enabled] is [code]true[/code]. If [code]false[/code], the generated texture will use low dynamic range; overbright colors will be clamped ([constant Image.FORMAT_RGBA8] format).
</member>
diff --git a/doc/classes/ImageTexture.xml b/doc/classes/ImageTexture.xml
index 45cbd7ac87..03d1947475 100644
--- a/doc/classes/ImageTexture.xml
+++ b/doc/classes/ImageTexture.xml
@@ -67,4 +67,7 @@
</description>
</method>
</methods>
+ <members>
+ <member name="resource_local_to_scene" type="bool" setter="set_local_to_scene" getter="is_local_to_scene" overrides="Resource" default="false" />
+ </members>
</class>
diff --git a/doc/classes/MeshTexture.xml b/doc/classes/MeshTexture.xml
index 8e2bccc79f..d09fa4c898 100644
--- a/doc/classes/MeshTexture.xml
+++ b/doc/classes/MeshTexture.xml
@@ -18,5 +18,6 @@
<member name="mesh" type="Mesh" setter="set_mesh" getter="get_mesh">
Sets the mesh used to draw. It must be a mesh using 2D vertices.
</member>
+ <member name="resource_local_to_scene" type="bool" setter="set_local_to_scene" getter="is_local_to_scene" overrides="Resource" default="false" />
</members>
</class>
diff --git a/doc/classes/PhysicsDirectBodyState2D.xml b/doc/classes/PhysicsDirectBodyState2D.xml
index e8062f3e94..eca6a1cbc7 100644
--- a/doc/classes/PhysicsDirectBodyState2D.xml
+++ b/doc/classes/PhysicsDirectBodyState2D.xml
@@ -209,40 +209,40 @@
</method>
</methods>
<members>
- <member name="angular_velocity" type="float" setter="set_angular_velocity" getter="get_angular_velocity" default="0.0">
+ <member name="angular_velocity" type="float" setter="set_angular_velocity" getter="get_angular_velocity">
The body's rotational velocity in [i]radians[/i] per second.
</member>
- <member name="center_of_mass" type="Vector2" setter="" getter="get_center_of_mass" default="Vector2(0, 0)">
+ <member name="center_of_mass" type="Vector2" setter="" getter="get_center_of_mass">
The body's center of mass position relative to the body's center in the global coordinate system.
</member>
- <member name="center_of_mass_local" type="Vector2" setter="" getter="get_center_of_mass_local" default="Vector2(0, 0)">
+ <member name="center_of_mass_local" type="Vector2" setter="" getter="get_center_of_mass_local">
The body's center of mass position in the body's local coordinate system.
</member>
- <member name="inverse_inertia" type="float" setter="" getter="get_inverse_inertia" default="0.0">
+ <member name="inverse_inertia" type="float" setter="" getter="get_inverse_inertia">
The inverse of the inertia of the body.
</member>
- <member name="inverse_mass" type="float" setter="" getter="get_inverse_mass" default="0.0">
+ <member name="inverse_mass" type="float" setter="" getter="get_inverse_mass">
The inverse of the mass of the body.
</member>
- <member name="linear_velocity" type="Vector2" setter="set_linear_velocity" getter="get_linear_velocity" default="Vector2(0, 0)">
+ <member name="linear_velocity" type="Vector2" setter="set_linear_velocity" getter="get_linear_velocity">
The body's linear velocity in pixels per second.
</member>
- <member name="sleeping" type="bool" setter="set_sleep_state" getter="is_sleeping" default="false">
+ <member name="sleeping" type="bool" setter="set_sleep_state" getter="is_sleeping">
If [code]true[/code], this body is currently sleeping (not active).
</member>
- <member name="step" type="float" setter="" getter="get_step" default="0.0">
+ <member name="step" type="float" setter="" getter="get_step">
The timestep (delta) used for the simulation.
</member>
- <member name="total_angular_damp" type="float" setter="" getter="get_total_angular_damp" default="0.0">
+ <member name="total_angular_damp" type="float" setter="" getter="get_total_angular_damp">
The rate at which the body stops rotating, if there are not any other forces moving it.
</member>
- <member name="total_gravity" type="Vector2" setter="" getter="get_total_gravity" default="Vector2(0, 0)">
+ <member name="total_gravity" type="Vector2" setter="" getter="get_total_gravity">
The total gravity vector being currently applied to this body.
</member>
- <member name="total_linear_damp" type="float" setter="" getter="get_total_linear_damp" default="0.0">
+ <member name="total_linear_damp" type="float" setter="" getter="get_total_linear_damp">
The rate at which the body stops moving, if there are not any other forces moving it.
</member>
- <member name="transform" type="Transform2D" setter="set_transform" getter="get_transform" default="Transform2D(1, 0, 0, 1, 0, 0)">
+ <member name="transform" type="Transform2D" setter="set_transform" getter="get_transform">
The body's transformation matrix.
</member>
</members>
diff --git a/doc/classes/PhysicsDirectBodyState3D.xml b/doc/classes/PhysicsDirectBodyState3D.xml
index 4c6d51c85a..a809384642 100644
--- a/doc/classes/PhysicsDirectBodyState3D.xml
+++ b/doc/classes/PhysicsDirectBodyState3D.xml
@@ -216,45 +216,45 @@
</method>
</methods>
<members>
- <member name="angular_velocity" type="Vector3" setter="set_angular_velocity" getter="get_angular_velocity" default="Vector3(0, 0, 0)">
+ <member name="angular_velocity" type="Vector3" setter="set_angular_velocity" getter="get_angular_velocity">
The body's rotational velocity in [i]radians[/i] per second.
</member>
- <member name="center_of_mass" type="Vector3" setter="" getter="get_center_of_mass" default="Vector3(0, 0, 0)">
+ <member name="center_of_mass" type="Vector3" setter="" getter="get_center_of_mass">
The body's center of mass position relative to the body's center in the global coordinate system.
</member>
- <member name="center_of_mass_local" type="Vector3" setter="" getter="get_center_of_mass_local" default="Vector3(0, 0, 0)">
+ <member name="center_of_mass_local" type="Vector3" setter="" getter="get_center_of_mass_local">
The body's center of mass position in the body's local coordinate system.
</member>
- <member name="inverse_inertia" type="Vector3" setter="" getter="get_inverse_inertia" default="Vector3(0, 0, 0)">
+ <member name="inverse_inertia" type="Vector3" setter="" getter="get_inverse_inertia">
The inverse of the inertia of the body.
</member>
- <member name="inverse_inertia_tensor" type="Basis" setter="" getter="get_inverse_inertia_tensor" default="Basis(1, 0, 0, 0, 1, 0, 0, 0, 1)">
+ <member name="inverse_inertia_tensor" type="Basis" setter="" getter="get_inverse_inertia_tensor">
The inverse of the inertia tensor of the body.
</member>
- <member name="inverse_mass" type="float" setter="" getter="get_inverse_mass" default="0.0">
+ <member name="inverse_mass" type="float" setter="" getter="get_inverse_mass">
The inverse of the mass of the body.
</member>
- <member name="linear_velocity" type="Vector3" setter="set_linear_velocity" getter="get_linear_velocity" default="Vector3(0, 0, 0)">
+ <member name="linear_velocity" type="Vector3" setter="set_linear_velocity" getter="get_linear_velocity">
The body's linear velocity in units per second.
</member>
- <member name="principal_inertia_axes" type="Basis" setter="" getter="get_principal_inertia_axes" default="Basis(1, 0, 0, 0, 1, 0, 0, 0, 1)">
+ <member name="principal_inertia_axes" type="Basis" setter="" getter="get_principal_inertia_axes">
</member>
- <member name="sleeping" type="bool" setter="set_sleep_state" getter="is_sleeping" default="false">
+ <member name="sleeping" type="bool" setter="set_sleep_state" getter="is_sleeping">
If [code]true[/code], this body is currently sleeping (not active).
</member>
- <member name="step" type="float" setter="" getter="get_step" default="0.0">
+ <member name="step" type="float" setter="" getter="get_step">
The timestep (delta) used for the simulation.
</member>
- <member name="total_angular_damp" type="float" setter="" getter="get_total_angular_damp" default="0.0">
+ <member name="total_angular_damp" type="float" setter="" getter="get_total_angular_damp">
The rate at which the body stops rotating, if there are not any other forces moving it.
</member>
- <member name="total_gravity" type="Vector3" setter="" getter="get_total_gravity" default="Vector3(0, 0, 0)">
+ <member name="total_gravity" type="Vector3" setter="" getter="get_total_gravity">
The total gravity vector being currently applied to this body.
</member>
- <member name="total_linear_damp" type="float" setter="" getter="get_total_linear_damp" default="0.0">
+ <member name="total_linear_damp" type="float" setter="" getter="get_total_linear_damp">
The rate at which the body stops moving, if there are not any other forces moving it.
</member>
- <member name="transform" type="Transform3D" setter="set_transform" getter="get_transform" default="Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0)">
+ <member name="transform" type="Transform3D" setter="set_transform" getter="get_transform">
The body's transformation matrix.
</member>
</members>
diff --git a/doc/classes/PlaceholderTexture2D.xml b/doc/classes/PlaceholderTexture2D.xml
index 76e575265b..5d8509ec77 100644
--- a/doc/classes/PlaceholderTexture2D.xml
+++ b/doc/classes/PlaceholderTexture2D.xml
@@ -7,6 +7,7 @@
<tutorials>
</tutorials>
<members>
+ <member name="resource_local_to_scene" type="bool" setter="set_local_to_scene" getter="is_local_to_scene" overrides="Resource" default="false" />
<member name="size" type="Vector2" setter="set_size" getter="get_size" default="Vector2(1, 1)">
</member>
</members>
diff --git a/doc/classes/PortableCompressedTexture2D.xml b/doc/classes/PortableCompressedTexture2D.xml
index a0492f2c07..b64cda6df5 100644
--- a/doc/classes/PortableCompressedTexture2D.xml
+++ b/doc/classes/PortableCompressedTexture2D.xml
@@ -58,6 +58,7 @@
When running on the editor, this class will keep the source compressed data in memory. Otherwise, the source compressed data is lost after loading and the resource can't be re saved.
This flag allows to keep the compressed data in memory if you intend it to persist after loading.
</member>
+ <member name="resource_local_to_scene" type="bool" setter="set_local_to_scene" getter="is_local_to_scene" overrides="Resource" default="false" />
<member name="size_override" type="Vector2" setter="set_size_override" getter="get_size_override" default="Vector2(0, 0)">
Allow overriding the texture size (for 2D only).
</member>
diff --git a/doc/classes/ProgressBar.xml b/doc/classes/ProgressBar.xml
index f8c5dc0e1f..510b8d5bd1 100644
--- a/doc/classes/ProgressBar.xml
+++ b/doc/classes/ProgressBar.xml
@@ -15,8 +15,6 @@
<member name="show_percentage" type="bool" setter="set_show_percentage" getter="is_percentage_shown" default="true">
If [code]true[/code], the fill percentage is displayed on the bar.
</member>
- <member name="size_flags_vertical" type="int" setter="set_v_size_flags" getter="get_v_size_flags" overrides="Control" default="0" />
- <member name="step" type="float" setter="set_step" getter="get_step" overrides="Range" default="0.01" />
</members>
<constants>
<constant name="FILL_BEGIN_TO_END" value="0" enum="FillMode">
diff --git a/doc/classes/Range.xml b/doc/classes/Range.xml
index 8aa89015c6..2dcfc90955 100644
--- a/doc/classes/Range.xml
+++ b/doc/classes/Range.xml
@@ -62,7 +62,8 @@
<member name="rounded" type="bool" setter="set_use_rounded_values" getter="is_using_rounded_values" default="false">
If [code]true[/code], [code]value[/code] will always be rounded to the nearest integer.
</member>
- <member name="step" type="float" setter="set_step" getter="get_step" default="1.0">
+ <member name="size_flags_vertical" type="int" setter="set_v_size_flags" getter="get_v_size_flags" overrides="Control" default="0" />
+ <member name="step" type="float" setter="set_step" getter="get_step" default="0.01">
If greater than 0, [code]value[/code] will always be rounded to a multiple of [code]step[/code]. If [code]rounded[/code] is also [code]true[/code], [code]value[/code] will first be rounded to a multiple of [code]step[/code] then rounded to the nearest integer.
</member>
<member name="value" type="float" setter="set_value" getter="get_value" default="0.0">
diff --git a/doc/classes/ScrollBar.xml b/doc/classes/ScrollBar.xml
index 266787c9c8..247e892c24 100644
--- a/doc/classes/ScrollBar.xml
+++ b/doc/classes/ScrollBar.xml
@@ -12,7 +12,6 @@
<member name="custom_step" type="float" setter="set_custom_step" getter="get_custom_step" default="-1.0">
Overrides the step used when clicking increment and decrement buttons or when using arrow keys when the [ScrollBar] is focused.
</member>
- <member name="size_flags_vertical" type="int" setter="set_v_size_flags" getter="get_v_size_flags" overrides="Control" default="0" />
<member name="step" type="float" setter="set_step" getter="get_step" overrides="Range" default="0.0" />
</members>
<signals>
diff --git a/doc/classes/Slider.xml b/doc/classes/Slider.xml
index 0e626842bd..cecca0a5fb 100644
--- a/doc/classes/Slider.xml
+++ b/doc/classes/Slider.xml
@@ -17,7 +17,7 @@
<member name="scrollable" type="bool" setter="set_scrollable" getter="is_scrollable" default="true">
If [code]true[/code], the value can be changed using the mouse wheel.
</member>
- <member name="size_flags_vertical" type="int" setter="set_v_size_flags" getter="get_v_size_flags" overrides="Control" default="0" />
+ <member name="step" type="float" setter="set_step" getter="get_step" overrides="Range" default="1.0" />
<member name="tick_count" type="int" setter="set_ticks" getter="get_ticks" default="0">
Number of ticks displayed on the slider, including border ticks. Ticks are uniformly-distributed value markers.
</member>
diff --git a/doc/classes/SpinBox.xml b/doc/classes/SpinBox.xml
index 93799b58f0..e214867890 100644
--- a/doc/classes/SpinBox.xml
+++ b/doc/classes/SpinBox.xml
@@ -59,6 +59,8 @@
<member name="select_all_on_focus" type="bool" setter="set_select_all_on_focus" getter="is_select_all_on_focus" default="false">
If [code]true[/code], the [SpinBox] will select the whole text when the [LineEdit] gains focus. Clicking the up and down arrows won't trigger this behavior.
</member>
+ <member name="size_flags_vertical" type="int" setter="set_v_size_flags" getter="get_v_size_flags" overrides="Control" default="1" />
+ <member name="step" type="float" setter="set_step" getter="get_step" overrides="Range" default="1.0" />
<member name="suffix" type="String" setter="set_suffix" getter="get_suffix" default="&quot;&quot;">
Adds the specified [code]suffix[/code] string after the numerical value of the [SpinBox].
</member>
diff --git a/doc/classes/TextureProgressBar.xml b/doc/classes/TextureProgressBar.xml
index ded4dac7da..54b77bf5eb 100644
--- a/doc/classes/TextureProgressBar.xml
+++ b/doc/classes/TextureProgressBar.xml
@@ -41,6 +41,8 @@
<member name="radial_initial_angle" type="float" setter="set_radial_initial_angle" getter="get_radial_initial_angle" default="0.0">
Starting angle for the fill of [member texture_progress] if [member fill_mode] is [constant FILL_CLOCKWISE] or [constant FILL_COUNTER_CLOCKWISE]. When the node's [code]value[/code] is equal to its [code]min_value[/code], the texture doesn't show up at all. When the [code]value[/code] increases, the texture fills and tends towards [member radial_fill_degrees].
</member>
+ <member name="size_flags_vertical" type="int" setter="set_v_size_flags" getter="get_v_size_flags" overrides="Control" default="1" />
+ <member name="step" type="float" setter="set_step" getter="get_step" overrides="Range" default="1.0" />
<member name="stretch_margin_bottom" type="int" setter="set_stretch_margin" getter="get_stretch_margin" default="0">
The height of the 9-patch's bottom row. A margin of 16 means the 9-slice's bottom corners and side will have a height of 16 pixels. You can set all 4 margin values individually to create panels with non-uniform borders.
</member>
diff --git a/doc/classes/ViewportTexture.xml b/doc/classes/ViewportTexture.xml
index 955f054cea..6bd64a50bb 100644
--- a/doc/classes/ViewportTexture.xml
+++ b/doc/classes/ViewportTexture.xml
@@ -15,7 +15,6 @@
<link title="3D Viewport Scaling Demo">https://godotengine.org/asset-library/asset/586</link>
</tutorials>
<members>
- <member name="resource_local_to_scene" type="bool" setter="set_local_to_scene" getter="is_local_to_scene" overrides="Resource" default="true" />
<member name="viewport_path" type="NodePath" setter="set_viewport_path_in_scene" getter="get_viewport_path_in_scene" default="NodePath(&quot;&quot;)">
The path to the [Viewport] node to display. This is relative to the scene root, not to the node which uses the texture.
</member>
diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp
index 2e8c95fe61..734911ccdb 100644
--- a/drivers/gles3/rasterizer_scene_gles3.cpp
+++ b/drivers/gles3/rasterizer_scene_gles3.cpp
@@ -1642,6 +1642,9 @@ void RasterizerSceneGLES3::render_scene(const Ref<RenderSceneBuffers> &p_render_
ERR_FAIL_COND(rb.is_null());
}
+ GLES3::RenderTarget *rt = texture_storage->get_render_target(rb->render_target);
+ ERR_FAIL_COND(!rt);
+
// Assign render data
// Use the format from rendererRD
RenderDataGLES3 render_data;
@@ -1729,8 +1732,20 @@ void RasterizerSceneGLES3::render_scene(const Ref<RenderSceneBuffers> &p_render_
scene_state.ubo.emissive_exposure_normalization = -1.0; // Use default exposure normalization.
+ bool flip_y = !render_data.reflection_probe.is_valid();
+
+ if (rt->overridden.color.is_valid()) {
+ // If we've overridden the render target's color texture, then don't render upside down.
+ // We're probably rendering directly to an XR device.
+ flip_y = false;
+ }
+ if (!flip_y) {
+ // If we're rendering right-side up, then we need to change the winding order.
+ glFrontFace(GL_CW);
+ }
+
_setup_lights(&render_data, false, render_data.directional_light_count, render_data.omni_light_count, render_data.spot_light_count);
- _setup_environment(&render_data, render_data.reflection_probe.is_valid(), screen_size, !render_data.reflection_probe.is_valid(), clear_color, false);
+ _setup_environment(&render_data, render_data.reflection_probe.is_valid(), screen_size, flip_y, clear_color, false);
_fill_render_list(RENDER_LIST_OPAQUE, &render_data, PASS_MODE_COLOR);
render_list[RENDER_LIST_OPAQUE].sort_by_key();
@@ -1811,7 +1826,7 @@ void RasterizerSceneGLES3::render_scene(const Ref<RenderSceneBuffers> &p_render_
}
}
- glBindFramebuffer(GL_FRAMEBUFFER, rb->framebuffer);
+ glBindFramebuffer(GL_FRAMEBUFFER, rt->fbo);
glViewport(0, 0, rb->width, rb->height);
// Do depth prepass if it's explicitly enabled
@@ -1917,6 +1932,11 @@ void RasterizerSceneGLES3::render_scene(const Ref<RenderSceneBuffers> &p_render_
_render_list_template<PASS_MODE_COLOR_TRANSPARENT>(&render_list_params_alpha, &render_data, 0, render_list[RENDER_LIST_ALPHA].elements.size(), true);
+ if (!flip_y) {
+ // Restore the default winding order.
+ glFrontFace(GL_CCW);
+ }
+
if (rb.is_valid()) {
_render_buffers_debug_draw(rb, p_shadow_atlas, p_occluder_debug_tex);
}
@@ -1973,6 +1993,8 @@ void RasterizerSceneGLES3::_render_list_template(RenderListParameters *p_params,
}
}
+ bool should_request_redraw = false;
+
for (uint32_t i = p_from_element; i < p_to_element; i++) {
const GeometryInstanceSurface *surf = p_params->elements[i];
GeometryInstanceGLES3 *inst = surf->owner;
@@ -2003,6 +2025,11 @@ void RasterizerSceneGLES3::_render_list_template(RenderListParameters *p_params,
continue;
}
+ //request a redraw if one of the shaders uses TIME
+ if (shader->uses_time) {
+ should_request_redraw = true;
+ }
+
if constexpr (p_pass_mode == PASS_MODE_COLOR_TRANSPARENT) {
if (scene_state.current_depth_test != shader->depth_test) {
if (shader->depth_test == GLES3::SceneShaderData::DEPTH_TEST_DISABLED) {
@@ -2227,6 +2254,11 @@ void RasterizerSceneGLES3::_render_list_template(RenderListParameters *p_params,
glDisableVertexAttribArray(15);
}
}
+
+ // Make the actual redraw request
+ if (should_request_redraw) {
+ RenderingServerDefault::redraw_request();
+ }
}
void RasterizerSceneGLES3::render_material(const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) {
diff --git a/drivers/gles3/storage/render_scene_buffers_gles3.cpp b/drivers/gles3/storage/render_scene_buffers_gles3.cpp
index b8e4530f56..e0e78de728 100644
--- a/drivers/gles3/storage/render_scene_buffers_gles3.cpp
+++ b/drivers/gles3/storage/render_scene_buffers_gles3.cpp
@@ -33,17 +33,12 @@
#include "render_scene_buffers_gles3.h"
#include "texture_storage.h"
-#ifdef ANDROID_ENABLED
-#define glFramebufferTextureMultiviewOVR GLES3::Config::get_singleton()->eglFramebufferTextureMultiviewOVR
-#endif
-
RenderSceneBuffersGLES3::~RenderSceneBuffersGLES3() {
free_render_buffer_data();
}
void RenderSceneBuffersGLES3::configure(RID p_render_target, const Size2i p_internal_size, const Size2i p_target_size, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa, RenderingServer::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) {
GLES3::TextureStorage *texture_storage = GLES3::TextureStorage::get_singleton();
- GLES3::Config *config = GLES3::Config::get_singleton();
//internal_size.x = p_internal_size.x; // ignore for now
//internal_size.y = p_internal_size.y;
@@ -62,66 +57,9 @@ void RenderSceneBuffersGLES3::configure(RID p_render_target, const Size2i p_inte
GLES3::RenderTarget *rt = texture_storage->get_render_target(p_render_target);
is_transparent = rt->is_transparent;
-
- // framebuffer
- glGenFramebuffers(1, &framebuffer);
- glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
-
- if (view_count > 1 && config->multiview_supported) {
- glBindTexture(GL_TEXTURE_2D_ARRAY, rt->color);
- glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, rt->color, 0, 0, view_count);
- } else {
- glBindTexture(GL_TEXTURE_2D, rt->color);
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->color, 0);
- }
-
- glGenTextures(1, &depth_texture);
- if (view_count > 1 && config->multiview_supported) {
- glBindTexture(GL_TEXTURE_2D_ARRAY, depth_texture);
- glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_DEPTH_COMPONENT24, rt->size.x, rt->size.y, view_count, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, nullptr);
-
- glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- } else {
- glBindTexture(GL_TEXTURE_2D, depth_texture);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, rt->size.x, rt->size.y, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, nullptr);
-
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- }
-
- if (view_count > 1 && config->multiview_supported) {
- glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depth_texture, 0, 0, view_count);
- } else {
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depth_texture, 0);
- }
-
- GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
-
- glBindTexture(GL_TEXTURE_2D, 0);
- glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
- glBindFramebuffer(GL_FRAMEBUFFER, texture_storage->system_fbo);
-
- if (status != GL_FRAMEBUFFER_COMPLETE) {
- free_render_buffer_data();
- WARN_PRINT("Could not create 3D renderbuffer, status: " + texture_storage->get_framebuffer_error(status));
- return;
- }
}
void RenderSceneBuffersGLES3::free_render_buffer_data() {
- if (depth_texture) {
- glDeleteTextures(1, &depth_texture);
- depth_texture = 0;
- }
- if (framebuffer) {
- glDeleteFramebuffers(1, &framebuffer);
- framebuffer = 0;
- }
}
#endif // GLES3_ENABLED
diff --git a/drivers/gles3/storage/render_scene_buffers_gles3.h b/drivers/gles3/storage/render_scene_buffers_gles3.h
index dbedbd22c3..092c14e1b8 100644
--- a/drivers/gles3/storage/render_scene_buffers_gles3.h
+++ b/drivers/gles3/storage/render_scene_buffers_gles3.h
@@ -61,9 +61,6 @@ public:
bool is_transparent = false;
RID render_target;
- GLuint internal_texture = 0; // Used for rendering when post effects are enabled
- GLuint depth_texture = 0; // Main depth texture
- GLuint framebuffer = 0; // Main framebuffer, contains internal_texture and depth_texture or render_target->color and depth_texture
//built-in textures used for ping pong image processing and blurring
struct Blur {
diff --git a/drivers/gles3/storage/texture_storage.cpp b/drivers/gles3/storage/texture_storage.cpp
index 11151c4100..e0457a8d28 100644
--- a/drivers/gles3/storage/texture_storage.cpp
+++ b/drivers/gles3/storage/texture_storage.cpp
@@ -614,7 +614,9 @@ void TextureStorage::texture_free(RID p_texture) {
}
if (t->tex_id != 0) {
- glDeleteTextures(1, &t->tex_id);
+ if (!t->is_external) {
+ glDeleteTextures(1, &t->tex_id);
+ }
t->tex_id = 0;
}
@@ -680,6 +682,35 @@ void TextureStorage::texture_proxy_initialize(RID p_texture, RID p_base) {
texture_owner.initialize_rid(p_texture, proxy_tex);
}
+RID TextureStorage::texture_create_external(Texture::Type p_type, Image::Format p_format, unsigned int p_image, int p_width, int p_height, int p_depth, int p_layers, RS::TextureLayeredType p_layered_type) {
+ Texture texture;
+ texture.active = true;
+ texture.is_external = true;
+ texture.type = p_type;
+
+ switch (p_type) {
+ case Texture::TYPE_2D: {
+ texture.target = GL_TEXTURE_2D;
+ } break;
+ case Texture::TYPE_3D: {
+ texture.target = GL_TEXTURE_3D;
+ } break;
+ case Texture::TYPE_LAYERED: {
+ texture.target = GL_TEXTURE_2D_ARRAY;
+ } break;
+ }
+
+ texture.real_format = texture.format = p_format;
+ texture.tex_id = p_image;
+ texture.alloc_width = texture.width = p_width;
+ texture.alloc_height = texture.height = p_height;
+ texture.depth = p_depth;
+ texture.layers = p_layers;
+ texture.layered_type = p_layered_type;
+
+ return texture_owner.make_rid(texture);
+}
+
void TextureStorage::texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer) {
texture_set_data(p_texture, p_image, p_layer);
#ifdef TOOLS_ENABLED
@@ -1459,43 +1490,74 @@ void TextureStorage::_update_render_target(RenderTarget *rt) {
glDepthMask(GL_FALSE);
{
- /* Front FBO */
+ Texture *texture;
+ bool use_multiview = rt->view_count > 1 && config->multiview_supported;
+ GLenum texture_target = use_multiview ? GL_TEXTURE_2D_ARRAY : GL_TEXTURE_2D;
- Texture *texture = get_texture(rt->texture);
- ERR_FAIL_COND(!texture);
+ /* Front FBO */
- // framebuffer
glGenFramebuffers(1, &rt->fbo);
glBindFramebuffer(GL_FRAMEBUFFER, rt->fbo);
// color
- glGenTextures(1, &rt->color);
- if (rt->view_count > 1 && config->multiview_supported) {
- glBindTexture(GL_TEXTURE_2D_ARRAY, rt->color);
- glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, rt->color_internal_format, rt->size.x, rt->size.y, rt->view_count, 0, rt->color_format, rt->color_type, nullptr);
-
- glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ if (rt->overridden.color.is_valid()) {
+ texture = get_texture(rt->overridden.color);
+ ERR_FAIL_COND(!texture);
+
+ rt->color = texture->tex_id;
+ rt->size = Size2i(texture->width, texture->height);
} else {
- glBindTexture(GL_TEXTURE_2D, rt->color);
- glTexImage2D(GL_TEXTURE_2D, 0, rt->color_internal_format, rt->size.x, rt->size.y, 0, rt->color_format, rt->color_type, nullptr);
+ texture = get_texture(rt->texture);
+ ERR_FAIL_COND(!texture);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- }
+ glGenTextures(1, &rt->color);
+ glBindTexture(texture_target, rt->color);
+
+ if (use_multiview) {
+ glTexImage3D(texture_target, 0, rt->color_internal_format, rt->size.x, rt->size.y, rt->view_count, 0, rt->color_format, rt->color_type, nullptr);
+ } else {
+ glTexImage2D(texture_target, 0, rt->color_internal_format, rt->size.x, rt->size.y, 0, rt->color_format, rt->color_type, nullptr);
+ }
- if (rt->view_count > 1 && config->multiview_supported) {
+ glTexParameteri(texture_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(texture_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(texture_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(texture_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ }
+ if (use_multiview) {
glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, rt->color, 0, 0, rt->view_count);
} else {
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->color, 0);
}
- GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+ // depth
+ if (rt->overridden.depth.is_valid()) {
+ texture = get_texture(rt->overridden.depth);
+ ERR_FAIL_COND(!texture);
+ rt->depth = texture->tex_id;
+ } else {
+ glGenTextures(1, &rt->depth);
+ glBindTexture(texture_target, rt->depth);
+
+ if (use_multiview) {
+ glTexImage3D(texture_target, 0, GL_DEPTH_COMPONENT24, rt->size.x, rt->size.y, rt->view_count, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, nullptr);
+ } else {
+ glTexImage2D(texture_target, 0, GL_DEPTH_COMPONENT24, rt->size.x, rt->size.y, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, nullptr);
+ }
+
+ glTexParameteri(texture_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(texture_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(texture_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(texture_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ }
+ if (use_multiview) {
+ glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, rt->depth, 0, 0, rt->view_count);
+ } else {
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, rt->depth, 0);
+ }
+
+ GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if (status != GL_FRAMEBUFFER_COMPLETE) {
glDeleteFramebuffers(1, &rt->fbo);
glDeleteTextures(1, &rt->color);
@@ -1503,32 +1565,38 @@ void TextureStorage::_update_render_target(RenderTarget *rt) {
rt->size.x = 0;
rt->size.y = 0;
rt->color = 0;
- texture->tex_id = 0;
- texture->active = false;
+ rt->depth = 0;
+ if (rt->overridden.color.is_null()) {
+ texture->tex_id = 0;
+ texture->active = false;
+ }
WARN_PRINT("Could not create render target, status: " + get_framebuffer_error(status));
return;
}
- texture->format = rt->image_format;
- texture->real_format = rt->image_format;
- if (rt->view_count > 1 && config->multiview_supported) {
- texture->type = Texture::TYPE_LAYERED;
- texture->target = GL_TEXTURE_2D_ARRAY;
- texture->layers = rt->view_count;
+ if (rt->overridden.color.is_valid()) {
+ texture->is_render_target = true;
} else {
- texture->type = Texture::TYPE_2D;
- texture->target = GL_TEXTURE_2D;
- texture->layers = 1;
+ texture->format = rt->image_format;
+ texture->real_format = rt->image_format;
+ texture->target = texture_target;
+ if (rt->view_count > 1 && config->multiview_supported) {
+ texture->type = Texture::TYPE_LAYERED;
+ texture->layers = rt->view_count;
+ } else {
+ texture->type = Texture::TYPE_2D;
+ texture->layers = 1;
+ }
+ texture->gl_format_cache = rt->color_format;
+ texture->gl_type_cache = GL_UNSIGNED_BYTE;
+ texture->gl_internal_format_cache = rt->color_internal_format;
+ texture->tex_id = rt->color;
+ texture->width = rt->size.x;
+ texture->alloc_width = rt->size.x;
+ texture->height = rt->size.y;
+ texture->alloc_height = rt->size.y;
+ texture->active = true;
}
- texture->gl_format_cache = rt->color_format;
- texture->gl_type_cache = GL_UNSIGNED_BYTE;
- texture->gl_internal_format_cache = rt->color_internal_format;
- texture->tex_id = rt->color;
- texture->width = rt->size.x;
- texture->alloc_width = rt->size.x;
- texture->height = rt->size.y;
- texture->alloc_height = rt->size.y;
- texture->active = true;
}
glClearColor(0, 0, 0, 0);
@@ -1596,17 +1664,32 @@ void TextureStorage::_clear_render_target(RenderTarget *rt) {
if (rt->fbo) {
glDeleteFramebuffers(1, &rt->fbo);
- glDeleteTextures(1, &rt->color);
rt->fbo = 0;
+ }
+
+ if (rt->overridden.color.is_null()) {
+ glDeleteTextures(1, &rt->color);
rt->color = 0;
}
- Texture *tex = get_texture(rt->texture);
- tex->alloc_height = 0;
- tex->alloc_width = 0;
- tex->width = 0;
- tex->height = 0;
- tex->active = false;
+ if (rt->overridden.depth.is_null()) {
+ glDeleteTextures(1, &rt->depth);
+ rt->depth = 0;
+ }
+
+ if (rt->texture.is_valid()) {
+ Texture *tex = get_texture(rt->texture);
+ tex->alloc_height = 0;
+ tex->alloc_width = 0;
+ tex->width = 0;
+ tex->height = 0;
+ tex->active = false;
+ }
+
+ if (rt->overridden.color.is_valid()) {
+ Texture *tex = get_texture(rt->overridden.color);
+ tex->is_render_target = false;
+ }
if (rt->backbuffer_fbo != 0) {
glDeleteFramebuffers(1, &rt->backbuffer_fbo);
@@ -1617,6 +1700,15 @@ void TextureStorage::_clear_render_target(RenderTarget *rt) {
_render_target_clear_sdf(rt);
}
+void TextureStorage::_clear_render_target_overridden_fbo_cache(RenderTarget *rt) {
+ // Dispose of the cached fbo's and the allocated textures
+ for (KeyValue<uint32_t, RenderTarget::RTOverridden::FBOCacheEntry> &E : rt->overridden.fbo_cache) {
+ glDeleteTextures(E.value.allocated_textures.size(), E.value.allocated_textures.ptr());
+ glDeleteFramebuffers(1, &E.value.fbo);
+ }
+ rt->overridden.fbo_cache.clear();
+}
+
RID TextureStorage::render_target_create() {
RenderTarget render_target;
//render_target.was_used = false;
@@ -1635,11 +1727,14 @@ RID TextureStorage::render_target_create() {
void TextureStorage::render_target_free(RID p_rid) {
RenderTarget *rt = render_target_owner.get_or_null(p_rid);
_clear_render_target(rt);
+ _clear_render_target_overridden_fbo_cache(rt);
Texture *t = get_texture(rt->texture);
if (t) {
t->is_render_target = false;
- texture_free(rt->texture);
+ if (rt->overridden.color.is_null()) {
+ texture_free(rt->texture);
+ }
//memdelete(t);
}
render_target_owner.free(p_rid);
@@ -1666,6 +1761,9 @@ void TextureStorage::render_target_set_size(RID p_render_target, int p_width, in
if (p_width == rt->size.x && p_height == rt->size.y && p_view_count == rt->view_count) {
return;
}
+ if (rt->overridden.color.is_valid()) {
+ return;
+ }
_clear_render_target(rt);
@@ -1683,10 +1781,91 @@ Size2i TextureStorage::render_target_get_size(RID p_render_target) const {
return rt->size;
}
+void TextureStorage::render_target_set_override(RID p_render_target, RID p_color_texture, RID p_depth_texture, RID p_velocity_texture) {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND(!rt);
+ ERR_FAIL_COND(rt->direct_to_screen);
+
+ rt->overridden.velocity = p_velocity_texture;
+
+ if (rt->overridden.color == p_color_texture && rt->overridden.depth == p_depth_texture) {
+ return;
+ }
+
+ if (p_color_texture.is_null() && p_depth_texture.is_null()) {
+ _clear_render_target(rt);
+ rt->overridden.is_overridden = false;
+ rt->overridden.color = RID();
+ rt->overridden.depth = RID();
+ rt->size = Size2i();
+ _clear_render_target_overridden_fbo_cache(rt);
+ return;
+ }
+
+ if (!rt->overridden.is_overridden) {
+ _clear_render_target(rt);
+ }
+
+ rt->overridden.color = p_color_texture;
+ rt->overridden.depth = p_depth_texture;
+ rt->overridden.is_overridden = true;
+
+ uint32_t hash_key = hash_murmur3_one_64(p_color_texture.get_id());
+ hash_key = hash_murmur3_one_64(p_depth_texture.get_id(), hash_key);
+ hash_key = hash_fmix32(hash_key);
+
+ RBMap<uint32_t, RenderTarget::RTOverridden::FBOCacheEntry>::Element *cache;
+ if ((cache = rt->overridden.fbo_cache.find(hash_key)) != nullptr) {
+ rt->fbo = cache->get().fbo;
+ rt->size = cache->get().size;
+ rt->texture = p_color_texture;
+ return;
+ }
+
+ _update_render_target(rt);
+
+ RenderTarget::RTOverridden::FBOCacheEntry new_entry;
+ new_entry.fbo = rt->fbo;
+ new_entry.size = rt->size;
+ // Keep track of any textures we had to allocate because they weren't overridden.
+ if (p_color_texture.is_null()) {
+ new_entry.allocated_textures.push_back(rt->color);
+ }
+ if (p_depth_texture.is_null()) {
+ new_entry.allocated_textures.push_back(rt->depth);
+ }
+ rt->overridden.fbo_cache.insert(hash_key, new_entry);
+}
+
+RID TextureStorage::render_target_get_override_color(RID p_render_target) const {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND_V(!rt, RID());
+
+ return rt->overridden.color;
+}
+
+RID TextureStorage::render_target_get_override_depth(RID p_render_target) const {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND_V(!rt, RID());
+
+ return rt->overridden.depth;
+}
+
+RID TextureStorage::render_target_get_override_velocity(RID p_render_target) const {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND_V(!rt, RID());
+
+ return rt->overridden.velocity;
+}
+
RID TextureStorage::render_target_get_texture(RID p_render_target) {
RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
ERR_FAIL_COND_V(!rt, RID());
+ if (rt->overridden.color.is_valid()) {
+ return rt->overridden.color;
+ }
+
return rt->texture;
}
@@ -1696,8 +1875,10 @@ void TextureStorage::render_target_set_transparent(RID p_render_target, bool p_t
rt->is_transparent = p_transparent;
- _clear_render_target(rt);
- _update_render_target(rt);
+ if (rt->overridden.color.is_null()) {
+ _clear_render_target(rt);
+ _update_render_target(rt);
+ }
}
bool TextureStorage::render_target_get_transparent(RID p_render_target) const {
@@ -1718,6 +1899,11 @@ void TextureStorage::render_target_set_direct_to_screen(RID p_render_target, boo
// those functions change how they operate depending on the value of DIRECT_TO_SCREEN
_clear_render_target(rt);
rt->direct_to_screen = p_direct_to_screen;
+ if (rt->direct_to_screen) {
+ rt->overridden.color = RID();
+ rt->overridden.depth = RID();
+ rt->overridden.velocity = RID();
+ }
_update_render_target(rt);
}
@@ -1750,6 +1936,7 @@ void TextureStorage::render_target_set_msaa(RID p_render_target, RS::ViewportMSA
}
WARN_PRINT("2D MSAA is not yet supported for GLES3.");
+
_clear_render_target(rt);
rt->msaa = p_msaa;
_update_render_target(rt);
diff --git a/drivers/gles3/storage/texture_storage.h b/drivers/gles3/storage/texture_storage.h
index 35fa16c894..5dff768bd7 100644
--- a/drivers/gles3/storage/texture_storage.h
+++ b/drivers/gles3/storage/texture_storage.h
@@ -126,6 +126,7 @@ struct Texture {
RID self;
bool is_proxy = false;
+ bool is_external = false;
bool is_render_target = false;
RID proxy_to = RID();
@@ -187,6 +188,7 @@ struct Texture {
void copy_from(const Texture &o) {
proxy_to = o.proxy_to;
is_proxy = o.is_proxy;
+ is_external = o.is_external;
width = o.width;
height = o.height;
alloc_width = o.alloc_width;
@@ -310,6 +312,7 @@ struct RenderTarget {
RID self;
GLuint fbo = 0;
GLuint color = 0;
+ GLuint depth = 0;
GLuint backbuffer_fbo = 0;
GLuint backbuffer = 0;
@@ -333,6 +336,20 @@ struct RenderTarget {
bool used_in_frame = false;
RS::ViewportMSAA msaa = RS::VIEWPORT_MSAA_DISABLED;
+ struct RTOverridden {
+ bool is_overridden = false;
+ RID color;
+ RID depth;
+ RID velocity;
+
+ struct FBOCacheEntry {
+ GLuint fbo;
+ Size2i size;
+ Vector<GLuint> allocated_textures;
+ };
+ RBMap<uint32_t, FBOCacheEntry> fbo_cache;
+ } overridden;
+
RID texture;
Color clear_color = Color(1, 1, 1, 1);
@@ -395,6 +412,7 @@ private:
mutable RID_Owner<RenderTarget> render_target_owner;
void _clear_render_target(RenderTarget *rt);
+ void _clear_render_target_overridden_fbo_cache(RenderTarget *rt);
void _update_render_target(RenderTarget *rt);
void _create_render_target_backbuffer(RenderTarget *rt);
void _render_target_allocate_sdf(RenderTarget *rt);
@@ -454,6 +472,8 @@ public:
virtual void texture_3d_initialize(RID p_texture, Image::Format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data) override;
virtual void texture_proxy_initialize(RID p_texture, RID p_base) override; //all slices, then all the mipmaps, must be coherent
+ RID texture_create_external(Texture::Type p_type, Image::Format p_format, unsigned int p_image, int p_width, int p_height, int p_depth, int p_layers, RS::TextureLayeredType p_layered_type = RS::TEXTURE_LAYERED_2D_ARRAY);
+
virtual void texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer = 0) override;
virtual void texture_3d_update(RID p_texture, const Vector<Ref<Image>> &p_data) override{};
virtual void texture_proxy_update(RID p_proxy, RID p_base) override;
@@ -593,10 +613,10 @@ public:
virtual void render_target_set_vrs_texture(RID p_render_target, RID p_texture) override {}
virtual RID render_target_get_vrs_texture(RID p_render_target) const override { return RID(); }
- virtual void render_target_set_override(RID p_render_target, RID p_color_texture, RID p_depth_texture, RID p_velocity_texture) override {}
- virtual RID render_target_get_override_color(RID p_render_target) const override { return RID(); }
- virtual RID render_target_get_override_depth(RID p_render_target) const override { return RID(); }
- virtual RID render_target_get_override_velocity(RID p_render_target) const override { return RID(); }
+ virtual void render_target_set_override(RID p_render_target, RID p_color_texture, RID p_depth_texture, RID p_velocity_texture) override;
+ virtual RID render_target_get_override_color(RID p_render_target) const override;
+ virtual RID render_target_get_override_depth(RID p_render_target) const override;
+ virtual RID render_target_get_override_velocity(RID p_render_target) const override;
virtual RID render_target_get_texture(RID p_render_target) override;
diff --git a/editor/doc_tools.cpp b/editor/doc_tools.cpp
index 6e6416e3ca..14a2640e63 100644
--- a/editor/doc_tools.cpp
+++ b/editor/doc_tools.cpp
@@ -335,7 +335,7 @@ static Variant get_documentation_default_value(const StringName &p_class_name, c
Variant default_value = Variant();
r_default_value_valid = false;
- if (ClassDB::can_instantiate(p_class_name)) { // Keep this condition in sync with ClassDB::class_get_default_property_value.
+ if (ClassDB::can_instantiate(p_class_name) && !ClassDB::is_virtual(p_class_name)) { // Keep this condition in sync with ClassDB::class_get_default_property_value.
default_value = ClassDB::class_get_default_property_value(p_class_name, p_property_name, &r_default_value_valid);
} else {
// Cannot get default value of classes that can't be instantiated
diff --git a/modules/noise/doc_classes/NoiseTexture2D.xml b/modules/noise/doc_classes/NoiseTexture2D.xml
index 9eea2738c5..0a800a143b 100644
--- a/modules/noise/doc_classes/NoiseTexture2D.xml
+++ b/modules/noise/doc_classes/NoiseTexture2D.xml
@@ -44,6 +44,7 @@
<member name="noise" type="Noise" setter="set_noise" getter="get_noise">
The instance of the [Noise] object.
</member>
+ <member name="resource_local_to_scene" type="bool" setter="set_local_to_scene" getter="is_local_to_scene" overrides="Resource" default="false" />
<member name="seamless" type="bool" setter="set_seamless" getter="get_seamless" default="false">
If [code]true[/code], a seamless texture is requested from the [Noise] resource.
[b]Note:[/b] Seamless noise textures may take longer to generate and/or can have a lower contrast compared to non-seamless noise depending on the used [Noise] resource. This is because some implementations use higher dimensions for generating seamless noise.
diff --git a/modules/openxr/SCsub b/modules/openxr/SCsub
index b5978ab134..84542be3b9 100644
--- a/modules/openxr/SCsub
+++ b/modules/openxr/SCsub
@@ -90,6 +90,8 @@ if env["platform"] == "android":
env_openxr.add_source_files(module_obj, "extensions/openxr_android_extension.cpp")
if env["vulkan"]:
env_openxr.add_source_files(module_obj, "extensions/openxr_vulkan_extension.cpp")
+if env["opengl3"]:
+ env_openxr.add_source_files(module_obj, "extensions/openxr_opengl_extension.cpp")
env_openxr.add_source_files(module_obj, "extensions/openxr_palm_pose_extension.cpp")
env_openxr.add_source_files(module_obj, "extensions/openxr_composition_layer_depth_extension.cpp")
diff --git a/modules/openxr/extensions/openxr_opengl_extension.cpp b/modules/openxr/extensions/openxr_opengl_extension.cpp
new file mode 100644
index 0000000000..a25727f885
--- /dev/null
+++ b/modules/openxr/extensions/openxr_opengl_extension.cpp
@@ -0,0 +1,479 @@
+/*************************************************************************/
+/* openxr_opengl_extension.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* 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. */
+/*************************************************************************/
+
+#ifdef GLES3_ENABLED
+
+#include "../extensions/openxr_opengl_extension.h"
+#include "../openxr_util.h"
+#include "drivers/gles3/effects/copy_effects.h"
+#include "drivers/gles3/storage/texture_storage.h"
+#include "servers/rendering/rendering_server_globals.h"
+#include "servers/rendering_server.h"
+
+OpenXROpenGLExtension::OpenXROpenGLExtension(OpenXRAPI *p_openxr_api) :
+ OpenXRGraphicsExtensionWrapper(p_openxr_api) {
+#ifdef ANDROID_ENABLED
+ request_extensions[XR_KHR_OPENGL_ES_ENABLE_EXTENSION_NAME] = nullptr;
+#else
+ request_extensions[XR_KHR_OPENGL_ENABLE_EXTENSION_NAME] = nullptr;
+#endif
+
+ ERR_FAIL_NULL(openxr_api);
+}
+
+OpenXROpenGLExtension::~OpenXROpenGLExtension() {
+}
+
+void OpenXROpenGLExtension::on_instance_created(const XrInstance p_instance) {
+ ERR_FAIL_NULL(openxr_api);
+
+ // Obtain pointers to functions we're accessing here.
+
+#ifdef ANDROID_ENABLED
+ EXT_INIT_XR_FUNC(xrGetOpenGLESGraphicsRequirementsKHR);
+#else
+ EXT_INIT_XR_FUNC(xrGetOpenGLGraphicsRequirementsKHR);
+#endif
+ EXT_INIT_XR_FUNC(xrEnumerateSwapchainImages);
+}
+
+bool OpenXROpenGLExtension::check_graphics_api_support(XrVersion p_desired_version) {
+ ERR_FAIL_NULL_V(openxr_api, false);
+
+ XrSystemId system_id = openxr_api->get_system_id();
+ XrInstance instance = openxr_api->get_instance();
+
+#ifdef ANDROID_ENABLED
+ XrGraphicsRequirementsOpenGLESKHR opengl_requirements;
+ opengl_requirements.type = XR_TYPE_GRAPHICS_REQUIREMENTS_OPENGL_ES_KHR;
+ opengl_requirements.next = nullptr;
+
+ XrResult result = xrGetOpenGLESGraphicsRequirementsKHR(instance, system_id, &opengl_requirements);
+ if (!openxr_api->xr_result(result, "Failed to get OpenGL graphics requirements!")) {
+ return false;
+ }
+#else
+ XrGraphicsRequirementsOpenGLKHR opengl_requirements;
+ opengl_requirements.type = XR_TYPE_GRAPHICS_REQUIREMENTS_OPENGL_KHR;
+ opengl_requirements.next = nullptr;
+
+ XrResult result = xrGetOpenGLGraphicsRequirementsKHR(instance, system_id, &opengl_requirements);
+ if (!openxr_api->xr_result(result, "Failed to get OpenGL graphics requirements!")) {
+ return false;
+ }
+#endif
+
+ if (p_desired_version < opengl_requirements.minApiVersionSupported) {
+ print_line("OpenXR: Requested OpenGL version does not meet the minimum version this runtime supports.");
+ print_line("- desired_version ", OpenXRUtil::make_xr_version_string(p_desired_version));
+ print_line("- minApiVersionSupported ", OpenXRUtil::make_xr_version_string(opengl_requirements.minApiVersionSupported));
+ print_line("- maxApiVersionSupported ", OpenXRUtil::make_xr_version_string(opengl_requirements.maxApiVersionSupported));
+ return false;
+ }
+
+ if (p_desired_version > opengl_requirements.maxApiVersionSupported) {
+ print_line("OpenXR: Requested OpenGL version exceeds the maximum version this runtime has been tested on and is known to support.");
+ print_line("- desired_version ", OpenXRUtil::make_xr_version_string(p_desired_version));
+ print_line("- minApiVersionSupported ", OpenXRUtil::make_xr_version_string(opengl_requirements.minApiVersionSupported));
+ print_line("- maxApiVersionSupported ", OpenXRUtil::make_xr_version_string(opengl_requirements.maxApiVersionSupported));
+ }
+
+ return true;
+}
+
+#ifdef WIN32
+XrGraphicsBindingOpenGLWin32KHR OpenXROpenGLExtension::graphics_binding_gl;
+#elif ANDROID_ENABLED
+XrGraphicsBindingOpenGLESAndroidKHR OpenXROpenGLExtension::graphics_binding_gl;
+#else
+XrGraphicsBindingOpenGLXlibKHR OpenXROpenGLExtension::graphics_binding_gl;
+#endif
+
+void *OpenXROpenGLExtension::set_session_create_and_get_next_pointer(void *p_next_pointer) {
+ XrVersion desired_version = XR_MAKE_VERSION(3, 3, 0);
+
+ if (!check_graphics_api_support(desired_version)) {
+ print_line("OpenXR: Trying to initialize with OpenGL anyway...");
+ //return p_next_pointer;
+ }
+
+ DisplayServer *display_server = DisplayServer::get_singleton();
+
+#ifdef WIN32
+ graphics_binding_gl.type = XR_TYPE_GRAPHICS_BINDING_OPENGL_WIN32_KHR,
+ graphics_binding_gl.next = p_next_pointer;
+
+ graphics_binding_gl.hDC = (HDC)display_server->window_get_native_handle(DisplayServer::WINDOW_VIEW);
+ graphics_binding_gl.hGLRC = (HGLRC)display_server->window_get_native_handle(DisplayServer::OPENGL_CONTEXT);
+#elif ANDROID_ENABLED
+ graphics_binding_gl.type = XR_TYPE_GRAPHICS_BINDING_OPENGL_ES_ANDROID_KHR;
+ graphics_binding_gl.next = p_next_pointer;
+
+ graphics_binding_gl.display = eglGetCurrentDisplay();
+ graphics_binding_gl.config = (EGLConfig)0; // https://github.com/KhronosGroup/OpenXR-SDK-Source/blob/master/src/tests/hello_xr/graphicsplugin_opengles.cpp#L122
+ graphics_binding_gl.context = eglGetCurrentContext();
+#else
+ graphics_binding_gl.type = XR_TYPE_GRAPHICS_BINDING_OPENGL_XLIB_KHR;
+ graphics_binding_gl.next = p_next_pointer;
+
+ void *display_handle = (void *)display_server->window_get_native_handle(DisplayServer::DISPLAY_HANDLE);
+ void *glxcontext_handle = (void *)display_server->window_get_native_handle(DisplayServer::OPENGL_CONTEXT);
+ void *glxdrawable_handle = (void *)display_server->window_get_native_handle(DisplayServer::WINDOW_HANDLE);
+
+ graphics_binding_gl.xDisplay = (Display *)display_handle;
+ graphics_binding_gl.glxContext = (GLXContext)glxcontext_handle;
+ graphics_binding_gl.glxDrawable = (GLXDrawable)glxdrawable_handle;
+
+ if (graphics_binding_gl.xDisplay == nullptr) {
+ print_line("OpenXR Failed to get xDisplay from Godot, using XOpenDisplay(nullptr)");
+ graphics_binding_gl.xDisplay = XOpenDisplay(nullptr);
+ }
+ if (graphics_binding_gl.glxContext == nullptr) {
+ print_line("OpenXR Failed to get glxContext from Godot, using glXGetCurrentContext()");
+ graphics_binding_gl.glxContext = glXGetCurrentContext();
+ }
+ if (graphics_binding_gl.glxDrawable == 0) {
+ print_line("OpenXR Failed to get glxDrawable from Godot, using glXGetCurrentDrawable()");
+ graphics_binding_gl.glxDrawable = glXGetCurrentDrawable();
+ }
+
+ // spec says to use proper values but runtimes don't care
+ graphics_binding_gl.visualid = 0;
+ graphics_binding_gl.glxFBConfig = 0;
+#endif
+
+ return &graphics_binding_gl;
+}
+
+void OpenXROpenGLExtension::get_usable_swapchain_formats(Vector<int64_t> &p_usable_swap_chains) {
+#ifdef WIN32
+ p_usable_swap_chains.push_back(GL_SRGB8_ALPHA8);
+ p_usable_swap_chains.push_back(GL_RGBA8);
+#elif ANDROID_ENABLED
+ p_usable_swap_chains.push_back(GL_SRGB8_ALPHA8);
+ p_usable_swap_chains.push_back(GL_RGBA8);
+#else
+ p_usable_swap_chains.push_back(GL_SRGB8_ALPHA8_EXT);
+ p_usable_swap_chains.push_back(GL_RGBA8_EXT);
+#endif
+}
+
+void OpenXROpenGLExtension::get_usable_depth_formats(Vector<int64_t> &p_usable_depth_formats) {
+ p_usable_depth_formats.push_back(GL_DEPTH_COMPONENT32F);
+ p_usable_depth_formats.push_back(GL_DEPTH24_STENCIL8);
+ p_usable_depth_formats.push_back(GL_DEPTH32F_STENCIL8);
+}
+
+bool OpenXROpenGLExtension::get_swapchain_image_data(XrSwapchain p_swapchain, int64_t p_swapchain_format, uint32_t p_width, uint32_t p_height, uint32_t p_sample_count, uint32_t p_array_size, void **r_swapchain_graphics_data) {
+ GLES3::TextureStorage *texture_storage = GLES3::TextureStorage::get_singleton();
+ ERR_FAIL_NULL_V(texture_storage, false);
+
+ uint32_t swapchain_length;
+ XrResult result = xrEnumerateSwapchainImages(p_swapchain, 0, &swapchain_length, nullptr);
+ if (XR_FAILED(result)) {
+ print_line("OpenXR: Failed to get swapchaim image count [", openxr_api->get_error_string(result), "]");
+ return false;
+ }
+
+#ifdef ANDROID_ENABLED
+ XrSwapchainImageOpenGLESKHR *images = (XrSwapchainImageOpenGLESKHR *)memalloc(sizeof(XrSwapchainImageOpenGLESKHR) * swapchain_length);
+#else
+ XrSwapchainImageOpenGLKHR *images = (XrSwapchainImageOpenGLKHR *)memalloc(sizeof(XrSwapchainImageOpenGLKHR) * swapchain_length);
+#endif
+ ERR_FAIL_NULL_V_MSG(images, false, "OpenXR Couldn't allocate memory for swap chain image");
+
+ for (uint64_t i = 0; i < swapchain_length; i++) {
+#ifdef ANDROID_ENABLED
+ images[i].type = XR_TYPE_SWAPCHAIN_IMAGE_OPENGL_ES_KHR;
+#else
+ images[i].type = XR_TYPE_SWAPCHAIN_IMAGE_OPENGL_KHR;
+#endif
+ images[i].next = nullptr;
+ images[i].image = 0;
+ }
+
+ result = xrEnumerateSwapchainImages(p_swapchain, swapchain_length, &swapchain_length, (XrSwapchainImageBaseHeader *)images);
+ if (XR_FAILED(result)) {
+ print_line("OpenXR: Failed to get swapchaim images [", openxr_api->get_error_string(result), "]");
+ memfree(images);
+ return false;
+ }
+
+ SwapchainGraphicsData *data = memnew(SwapchainGraphicsData);
+ if (data == nullptr) {
+ print_line("OpenXR: Failed to allocate memory for swapchain data");
+ memfree(images);
+ return false;
+ }
+ *r_swapchain_graphics_data = data;
+ data->is_multiview = (p_array_size > 1);
+
+ Image::Format format = Image::FORMAT_RGBA8;
+
+ Vector<RID> texture_rids;
+
+ for (uint64_t i = 0; i < swapchain_length; i++) {
+ RID texture_rid = texture_storage->texture_create_external(
+ p_array_size == 1 ? GLES3::Texture::TYPE_2D : GLES3::Texture::TYPE_LAYERED,
+ format,
+ images[i].image,
+ p_width,
+ p_height,
+ 1,
+ p_array_size);
+
+ texture_rids.push_back(texture_rid);
+ }
+
+ data->texture_rids = texture_rids;
+
+ memfree(images);
+
+ return true;
+}
+
+bool OpenXROpenGLExtension::create_projection_fov(const XrFovf p_fov, double p_z_near, double p_z_far, Projection &r_camera_matrix) {
+ XrMatrix4x4f matrix;
+ XrMatrix4x4f_CreateProjectionFov(&matrix, GRAPHICS_OPENGL, p_fov, (float)p_z_near, (float)p_z_far);
+
+ for (int j = 0; j < 4; j++) {
+ for (int i = 0; i < 4; i++) {
+ r_camera_matrix.columns[j][i] = matrix.m[j * 4 + i];
+ }
+ }
+
+ return true;
+}
+
+RID OpenXROpenGLExtension::get_texture(void *p_swapchain_graphics_data, int p_image_index) {
+ SwapchainGraphicsData *data = (SwapchainGraphicsData *)p_swapchain_graphics_data;
+ ERR_FAIL_NULL_V(data, RID());
+
+ ERR_FAIL_INDEX_V(p_image_index, data->texture_rids.size(), RID());
+ return data->texture_rids[p_image_index];
+}
+
+void OpenXROpenGLExtension::cleanup_swapchain_graphics_data(void **p_swapchain_graphics_data) {
+ if (*p_swapchain_graphics_data == nullptr) {
+ return;
+ }
+
+ GLES3::TextureStorage *texture_storage = GLES3::TextureStorage::get_singleton();
+ ERR_FAIL_NULL(texture_storage);
+
+ SwapchainGraphicsData *data = (SwapchainGraphicsData *)*p_swapchain_graphics_data;
+
+ for (int i = 0; i < data->texture_rids.size(); i++) {
+ texture_storage->texture_free(data->texture_rids[i]);
+ }
+ data->texture_rids.clear();
+
+ memdelete(data);
+ *p_swapchain_graphics_data = nullptr;
+}
+
+#define ENUM_TO_STRING_CASE(e) \
+ case e: { \
+ return String(#e); \
+ } break;
+
+String OpenXROpenGLExtension::get_swapchain_format_name(int64_t p_swapchain_format) const {
+ // These are somewhat different per platform, will need to weed some stuff out...
+ switch (p_swapchain_format) {
+#ifdef WIN32
+ // using definitions from GLAD
+ ENUM_TO_STRING_CASE(GL_R8_SNORM)
+ ENUM_TO_STRING_CASE(GL_RG8_SNORM)
+ ENUM_TO_STRING_CASE(GL_RGB8_SNORM)
+ ENUM_TO_STRING_CASE(GL_RGBA8_SNORM)
+ ENUM_TO_STRING_CASE(GL_R16_SNORM)
+ ENUM_TO_STRING_CASE(GL_RG16_SNORM)
+ ENUM_TO_STRING_CASE(GL_RGB16_SNORM)
+ ENUM_TO_STRING_CASE(GL_RGBA16_SNORM)
+ ENUM_TO_STRING_CASE(GL_RGB4)
+ ENUM_TO_STRING_CASE(GL_RGB5)
+ ENUM_TO_STRING_CASE(GL_RGB8)
+ ENUM_TO_STRING_CASE(GL_RGB10)
+ ENUM_TO_STRING_CASE(GL_RGB12)
+ ENUM_TO_STRING_CASE(GL_RGB16)
+ ENUM_TO_STRING_CASE(GL_RGBA2)
+ ENUM_TO_STRING_CASE(GL_RGBA4)
+ ENUM_TO_STRING_CASE(GL_RGB5_A1)
+ ENUM_TO_STRING_CASE(GL_RGBA8)
+ ENUM_TO_STRING_CASE(GL_RGB10_A2)
+ ENUM_TO_STRING_CASE(GL_RGBA12)
+ ENUM_TO_STRING_CASE(GL_RGBA16)
+ ENUM_TO_STRING_CASE(GL_RGBA32F)
+ ENUM_TO_STRING_CASE(GL_RGB32F)
+ ENUM_TO_STRING_CASE(GL_RGBA16F)
+ ENUM_TO_STRING_CASE(GL_RGB16F)
+ ENUM_TO_STRING_CASE(GL_RGBA32UI)
+ ENUM_TO_STRING_CASE(GL_RGB32UI)
+ ENUM_TO_STRING_CASE(GL_RGBA16UI)
+ ENUM_TO_STRING_CASE(GL_RGB16UI)
+ ENUM_TO_STRING_CASE(GL_RGBA8UI)
+ ENUM_TO_STRING_CASE(GL_RGB8UI)
+ ENUM_TO_STRING_CASE(GL_RGBA32I)
+ ENUM_TO_STRING_CASE(GL_RGB32I)
+ ENUM_TO_STRING_CASE(GL_RGBA16I)
+ ENUM_TO_STRING_CASE(GL_RGB16I)
+ ENUM_TO_STRING_CASE(GL_RGBA8I)
+ ENUM_TO_STRING_CASE(GL_RGB8I)
+ ENUM_TO_STRING_CASE(GL_RGB10_A2UI)
+ ENUM_TO_STRING_CASE(GL_SRGB)
+ ENUM_TO_STRING_CASE(GL_SRGB8)
+ ENUM_TO_STRING_CASE(GL_SRGB_ALPHA)
+ ENUM_TO_STRING_CASE(GL_SRGB8_ALPHA8)
+ ENUM_TO_STRING_CASE(GL_DEPTH_COMPONENT16)
+ ENUM_TO_STRING_CASE(GL_DEPTH_COMPONENT24)
+ ENUM_TO_STRING_CASE(GL_DEPTH_COMPONENT32)
+ ENUM_TO_STRING_CASE(GL_DEPTH24_STENCIL8)
+ ENUM_TO_STRING_CASE(GL_R11F_G11F_B10F)
+ ENUM_TO_STRING_CASE(GL_DEPTH_COMPONENT32F)
+ ENUM_TO_STRING_CASE(GL_DEPTH32F_STENCIL8)
+
+#elif ANDROID_ENABLED
+ // using definitions from GLES3/gl3.h
+
+ ENUM_TO_STRING_CASE(GL_RGBA4)
+ ENUM_TO_STRING_CASE(GL_RGB5_A1)
+ ENUM_TO_STRING_CASE(GL_RGB565)
+ ENUM_TO_STRING_CASE(GL_RGB8)
+ ENUM_TO_STRING_CASE(GL_RGBA8)
+ ENUM_TO_STRING_CASE(GL_RGB10_A2)
+ ENUM_TO_STRING_CASE(GL_RGBA32F)
+ ENUM_TO_STRING_CASE(GL_RGB32F)
+ ENUM_TO_STRING_CASE(GL_RGBA16F)
+ ENUM_TO_STRING_CASE(GL_RGB16F)
+ ENUM_TO_STRING_CASE(GL_R11F_G11F_B10F)
+ ENUM_TO_STRING_CASE(GL_UNSIGNED_INT_10F_11F_11F_REV)
+ ENUM_TO_STRING_CASE(GL_RGB9_E5)
+ ENUM_TO_STRING_CASE(GL_UNSIGNED_INT_5_9_9_9_REV)
+ ENUM_TO_STRING_CASE(GL_RGBA32UI)
+ ENUM_TO_STRING_CASE(GL_RGB32UI)
+ ENUM_TO_STRING_CASE(GL_RGBA16UI)
+ ENUM_TO_STRING_CASE(GL_RGB16UI)
+ ENUM_TO_STRING_CASE(GL_RGBA8UI)
+ ENUM_TO_STRING_CASE(GL_RGB8UI)
+ ENUM_TO_STRING_CASE(GL_RGBA32I)
+ ENUM_TO_STRING_CASE(GL_RGB32I)
+ ENUM_TO_STRING_CASE(GL_RGBA16I)
+ ENUM_TO_STRING_CASE(GL_RGB16I)
+ ENUM_TO_STRING_CASE(GL_RGBA8I)
+ ENUM_TO_STRING_CASE(GL_RGB8I)
+ ENUM_TO_STRING_CASE(GL_RG)
+ ENUM_TO_STRING_CASE(GL_RG_INTEGER)
+ ENUM_TO_STRING_CASE(GL_R8)
+ ENUM_TO_STRING_CASE(GL_RG8)
+ ENUM_TO_STRING_CASE(GL_R16F)
+ ENUM_TO_STRING_CASE(GL_R32F)
+ ENUM_TO_STRING_CASE(GL_RG16F)
+ ENUM_TO_STRING_CASE(GL_RG32F)
+ ENUM_TO_STRING_CASE(GL_R8I)
+ ENUM_TO_STRING_CASE(GL_R8UI)
+ ENUM_TO_STRING_CASE(GL_R16I)
+ ENUM_TO_STRING_CASE(GL_R16UI)
+ ENUM_TO_STRING_CASE(GL_R32I)
+ ENUM_TO_STRING_CASE(GL_R32UI)
+ ENUM_TO_STRING_CASE(GL_RG8I)
+ ENUM_TO_STRING_CASE(GL_RG8UI)
+ ENUM_TO_STRING_CASE(GL_RG16I)
+ ENUM_TO_STRING_CASE(GL_RG16UI)
+ ENUM_TO_STRING_CASE(GL_RG32I)
+ ENUM_TO_STRING_CASE(GL_RG32UI)
+ ENUM_TO_STRING_CASE(GL_R8_SNORM)
+ ENUM_TO_STRING_CASE(GL_RG8_SNORM)
+ ENUM_TO_STRING_CASE(GL_RGB8_SNORM)
+ ENUM_TO_STRING_CASE(GL_RGBA8_SNORM)
+ ENUM_TO_STRING_CASE(GL_RGB10_A2UI)
+ ENUM_TO_STRING_CASE(GL_SRGB)
+ ENUM_TO_STRING_CASE(GL_SRGB8)
+ ENUM_TO_STRING_CASE(GL_SRGB8_ALPHA8)
+ ENUM_TO_STRING_CASE(GL_COMPRESSED_R11_EAC)
+ ENUM_TO_STRING_CASE(GL_COMPRESSED_SIGNED_R11_EAC)
+ ENUM_TO_STRING_CASE(GL_COMPRESSED_RG11_EAC)
+ ENUM_TO_STRING_CASE(GL_COMPRESSED_SIGNED_RG11_EAC)
+ ENUM_TO_STRING_CASE(GL_COMPRESSED_RGB8_ETC2)
+ ENUM_TO_STRING_CASE(GL_COMPRESSED_SRGB8_ETC2)
+ ENUM_TO_STRING_CASE(GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2)
+ ENUM_TO_STRING_CASE(GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2)
+ ENUM_TO_STRING_CASE(GL_COMPRESSED_RGBA8_ETC2_EAC)
+ ENUM_TO_STRING_CASE(GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC)
+ ENUM_TO_STRING_CASE(GL_DEPTH_COMPONENT16)
+ ENUM_TO_STRING_CASE(GL_DEPTH_COMPONENT24)
+ ENUM_TO_STRING_CASE(GL_DEPTH24_STENCIL8)
+
+#else
+ // using definitions from GL/gl.h
+ ENUM_TO_STRING_CASE(GL_ALPHA4_EXT)
+ ENUM_TO_STRING_CASE(GL_ALPHA8_EXT)
+ ENUM_TO_STRING_CASE(GL_ALPHA12_EXT)
+ ENUM_TO_STRING_CASE(GL_ALPHA16_EXT)
+ ENUM_TO_STRING_CASE(GL_LUMINANCE4_EXT)
+ ENUM_TO_STRING_CASE(GL_LUMINANCE8_EXT)
+ ENUM_TO_STRING_CASE(GL_LUMINANCE12_EXT)
+ ENUM_TO_STRING_CASE(GL_LUMINANCE16_EXT)
+ ENUM_TO_STRING_CASE(GL_LUMINANCE4_ALPHA4_EXT)
+ ENUM_TO_STRING_CASE(GL_LUMINANCE6_ALPHA2_EXT)
+ ENUM_TO_STRING_CASE(GL_LUMINANCE8_ALPHA8_EXT)
+ ENUM_TO_STRING_CASE(GL_LUMINANCE12_ALPHA4_EXT)
+ ENUM_TO_STRING_CASE(GL_LUMINANCE12_ALPHA12_EXT)
+ ENUM_TO_STRING_CASE(GL_LUMINANCE16_ALPHA16_EXT)
+ ENUM_TO_STRING_CASE(GL_INTENSITY_EXT)
+ ENUM_TO_STRING_CASE(GL_INTENSITY4_EXT)
+ ENUM_TO_STRING_CASE(GL_INTENSITY8_EXT)
+ ENUM_TO_STRING_CASE(GL_INTENSITY12_EXT)
+ ENUM_TO_STRING_CASE(GL_INTENSITY16_EXT)
+ ENUM_TO_STRING_CASE(GL_RGB2_EXT)
+ ENUM_TO_STRING_CASE(GL_RGB4_EXT)
+ ENUM_TO_STRING_CASE(GL_RGB5_EXT)
+ ENUM_TO_STRING_CASE(GL_RGB8_EXT)
+ ENUM_TO_STRING_CASE(GL_RGB10_EXT)
+ ENUM_TO_STRING_CASE(GL_RGB12_EXT)
+ ENUM_TO_STRING_CASE(GL_RGB16_EXT)
+ ENUM_TO_STRING_CASE(GL_RGBA2_EXT)
+ ENUM_TO_STRING_CASE(GL_RGBA4_EXT)
+ ENUM_TO_STRING_CASE(GL_RGB5_A1_EXT)
+ ENUM_TO_STRING_CASE(GL_RGBA8_EXT)
+ ENUM_TO_STRING_CASE(GL_RGB10_A2_EXT)
+ ENUM_TO_STRING_CASE(GL_RGBA12_EXT)
+ ENUM_TO_STRING_CASE(GL_RGBA16_EXT)
+ ENUM_TO_STRING_CASE(GL_SRGB_EXT)
+ ENUM_TO_STRING_CASE(GL_SRGB8_EXT)
+ ENUM_TO_STRING_CASE(GL_SRGB_ALPHA_EXT)
+ ENUM_TO_STRING_CASE(GL_SRGB8_ALPHA8_EXT)
+#endif
+ default: {
+ return String("Swapchain format 0x") + String::num_int64(p_swapchain_format, 16);
+ } break;
+ }
+}
+
+#endif // GLES3_ENABLED
diff --git a/modules/openxr/extensions/openxr_opengl_extension.h b/modules/openxr/extensions/openxr_opengl_extension.h
new file mode 100644
index 0000000000..b666653c8e
--- /dev/null
+++ b/modules/openxr/extensions/openxr_opengl_extension.h
@@ -0,0 +1,120 @@
+/*************************************************************************/
+/* openxr_opengl_extension.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* 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. */
+/*************************************************************************/
+
+#ifndef OPENXR_OPENGL_EXTENSION_H
+#define OPENXR_OPENGL_EXTENSION_H
+
+#ifdef GLES3_ENABLED
+
+#include "core/templates/vector.h"
+#include "openxr_extension_wrapper.h"
+
+#include "../openxr_api.h"
+#include "../util.h"
+
+#ifdef ANDROID_ENABLED
+#define XR_USE_GRAPHICS_API_OPENGL_ES
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+#include <GLES3/gl3.h>
+#include <GLES3/gl3ext.h>
+#else
+#define XR_USE_GRAPHICS_API_OPENGL
+#endif
+
+#ifdef WINDOWS_ENABLED
+// Including windows.h here is absolutely evil, we shouldn't be doing this outside of platform
+// however due to the way the openxr headers are put together, we have no choice.
+#include <windows.h>
+#endif
+
+#ifdef X11_ENABLED
+#include OPENGL_INCLUDE_H
+#define GL_GLEXT_PROTOTYPES 1
+#define GL3_PROTOTYPES 1
+#include <GL/gl.h>
+#include <GL/glext.h>
+#include <GL/glx.h>
+#include <X11/Xlib.h>
+#endif
+
+#ifdef ANDROID_ENABLED
+// The jobject type from jni.h is used by openxr_platform.h on Android.
+#include <jni.h>
+#endif
+
+// include platform dependent structs
+#include <openxr/openxr_platform.h>
+
+class OpenXROpenGLExtension : public OpenXRGraphicsExtensionWrapper {
+public:
+ OpenXROpenGLExtension(OpenXRAPI *p_openxr_api);
+ virtual ~OpenXROpenGLExtension() override;
+
+ virtual void on_instance_created(const XrInstance p_instance) override;
+ virtual void *set_session_create_and_get_next_pointer(void *p_next_pointer) override;
+
+ virtual void get_usable_swapchain_formats(Vector<int64_t> &p_usable_swap_chains) override;
+ virtual void get_usable_depth_formats(Vector<int64_t> &p_usable_swap_chains) override;
+ virtual String get_swapchain_format_name(int64_t p_swapchain_format) const override;
+ virtual bool get_swapchain_image_data(XrSwapchain p_swapchain, int64_t p_swapchain_format, uint32_t p_width, uint32_t p_height, uint32_t p_sample_count, uint32_t p_array_size, void **r_swapchain_graphics_data) override;
+ virtual void cleanup_swapchain_graphics_data(void **p_swapchain_graphics_data) override;
+ virtual bool create_projection_fov(const XrFovf p_fov, double p_z_near, double p_z_far, Projection &r_camera_matrix) override;
+ virtual RID get_texture(void *p_swapchain_graphics_data, int p_image_index) override;
+
+private:
+ static OpenXROpenGLExtension *singleton;
+
+#ifdef WIN32
+ static XrGraphicsBindingOpenGLWin32KHR graphics_binding_gl;
+#elif ANDROID_ENABLED
+ static XrGraphicsBindingOpenGLESAndroidKHR graphics_binding_gl;
+#else
+ static XrGraphicsBindingOpenGLXlibKHR graphics_binding_gl;
+#endif
+
+ struct SwapchainGraphicsData {
+ bool is_multiview;
+ Vector<RID> texture_rids;
+ };
+
+ bool check_graphics_api_support(XrVersion p_desired_version);
+
+#ifdef ANDROID_ENABLED
+ EXT_PROTO_XRRESULT_FUNC3(xrGetOpenGLESGraphicsRequirementsKHR, (XrInstance), p_instance, (XrSystemId), p_system_id, (XrGraphicsRequirementsOpenGLESKHR *), p_graphics_requirements)
+#else
+ EXT_PROTO_XRRESULT_FUNC3(xrGetOpenGLGraphicsRequirementsKHR, (XrInstance), p_instance, (XrSystemId), p_system_id, (XrGraphicsRequirementsOpenGLKHR *), p_graphics_requirements)
+#endif
+ EXT_PROTO_XRRESULT_FUNC4(xrEnumerateSwapchainImages, (XrSwapchain), p_swapchain, (uint32_t), p_image_capacity_input, (uint32_t *), p_image_count_output, (XrSwapchainImageBaseHeader *), p_images)
+};
+
+#endif // GLES3_ENABLED
+
+#endif // OPENXR_OPENGL_EXTENSION_H
diff --git a/modules/openxr/openxr_api.cpp b/modules/openxr/openxr_api.cpp
index 8b189cf027..88111afede 100644
--- a/modules/openxr/openxr_api.cpp
+++ b/modules/openxr/openxr_api.cpp
@@ -45,10 +45,40 @@
#include "extensions/openxr_android_extension.h"
#endif
+// We need to have all the graphics API defines before the Vulkan or OpenGL
+// extensions are included, otherwise we'll only get one graphics API.
+#ifdef VULKAN_ENABLED
+#define XR_USE_GRAPHICS_API_VULKAN
+#endif
+#ifdef GLES3_ENABLED
+#ifdef ANDROID
+#define XR_USE_GRAPHICS_API_OPENGL_ES
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+#include <GLES3/gl3.h>
+#include <GLES3/gl3ext.h>
+#else
+#define XR_USE_GRAPHICS_API_OPENGL
+#endif // ANDROID
+#ifdef X11_ENABLED
+#include OPENGL_INCLUDE_H
+#define GL_GLEXT_PROTOTYPES 1
+#define GL3_PROTOTYPES 1
+#include <GL/gl.h>
+#include <GL/glext.h>
+#include <GL/glx.h>
+#include <X11/Xlib.h>
+#endif // X11_ENABLED
+#endif // GLES_ENABLED
+
#ifdef VULKAN_ENABLED
#include "extensions/openxr_vulkan_extension.h"
#endif
+#ifdef GLES3_ENABLED
+#include "extensions/openxr_opengl_extension.h"
+#endif
+
#include "extensions/openxr_composition_layer_depth_extension.h"
#include "extensions/openxr_fb_display_refresh_rate_extension.h"
#include "extensions/openxr_fb_passthrough_extension_wrapper.h"
@@ -1142,9 +1172,8 @@ bool OpenXRAPI::initialize(const String &p_rendering_driver) {
#endif
} else if (p_rendering_driver == "opengl3") {
#ifdef GLES3_ENABLED
- // graphics_extension = memnew(OpenXROpenGLExtension(this));
- // register_extension_wrapper(graphics_extension);
- ERR_FAIL_V_MSG(false, "OpenXR: OpenGL is not supported at this time.");
+ graphics_extension = memnew(OpenXROpenGLExtension(this));
+ register_extension_wrapper(graphics_extension);
#else
// shouldn't be possible...
ERR_FAIL_V(false);
diff --git a/platform/android/display_server_android.cpp b/platform/android/display_server_android.cpp
index 08369e735d..967f5c7dae 100644
--- a/platform/android/display_server_android.cpp
+++ b/platform/android/display_server_android.cpp
@@ -321,6 +321,11 @@ int64_t DisplayServerAndroid::window_get_native_handle(HandleType p_handle_type,
case WINDOW_VIEW: {
return 0; // Not supported.
}
+#ifdef GLES3_ENABLED
+ case OPENGL_CONTEXT: {
+ return eglGetCurrentContext();
+ }
+#endif
default: {
return 0;
}
diff --git a/platform/linuxbsd/x11/detect_prime_x11.cpp b/platform/linuxbsd/x11/detect_prime_x11.cpp
index fb833ab5e6..78a10fa2b0 100644
--- a/platform/linuxbsd/x11/detect_prime_x11.cpp
+++ b/platform/linuxbsd/x11/detect_prime_x11.cpp
@@ -208,7 +208,10 @@ int detect_prime() {
print_verbose("Couldn't write vendor/renderer string.");
}
close(fdset[1]);
- exit(0);
+
+ // The function quick_exit() is used because exit() will call destructors on static objects copied by fork().
+ // These objects will be freed anyway when the process finishes execution.
+ quick_exit(0);
}
}
diff --git a/platform/linuxbsd/x11/display_server_x11.cpp b/platform/linuxbsd/x11/display_server_x11.cpp
index f477787771..c3a86c69e1 100644
--- a/platform/linuxbsd/x11/display_server_x11.cpp
+++ b/platform/linuxbsd/x11/display_server_x11.cpp
@@ -1309,6 +1309,11 @@ int64_t DisplayServerX11::window_get_native_handle(HandleType p_handle_type, Win
case WINDOW_VIEW: {
return 0; // Not supported.
}
+#ifdef GLES3_ENABLED
+ case OPENGL_CONTEXT: {
+ return (int64_t)gl_manager->get_glx_context(p_window);
+ }
+#endif
default: {
return 0;
}
diff --git a/platform/linuxbsd/x11/gl_manager_x11.cpp b/platform/linuxbsd/x11/gl_manager_x11.cpp
index f586c57dda..893a22e75e 100644
--- a/platform/linuxbsd/x11/gl_manager_x11.cpp
+++ b/platform/linuxbsd/x11/gl_manager_x11.cpp
@@ -376,6 +376,17 @@ bool GLManager_X11::is_using_vsync() const {
return use_vsync;
}
+void *GLManager_X11::get_glx_context(DisplayServer::WindowID p_window_id) {
+ if (p_window_id == -1) {
+ return nullptr;
+ }
+
+ const GLWindow &win = _windows[p_window_id];
+ const GLDisplay &disp = get_display(win.gldisplay_id);
+
+ return (void *)disp.context->glx_context;
+}
+
GLManager_X11::GLManager_X11(const Vector2i &p_size, ContextType p_context_type) {
context_type = p_context_type;
diff --git a/platform/linuxbsd/x11/gl_manager_x11.h b/platform/linuxbsd/x11/gl_manager_x11.h
index 4f78c45c88..1594c82801 100644
--- a/platform/linuxbsd/x11/gl_manager_x11.h
+++ b/platform/linuxbsd/x11/gl_manager_x11.h
@@ -116,6 +116,8 @@ public:
void set_use_vsync(bool p_use);
bool is_using_vsync() const;
+ void *get_glx_context(DisplayServer::WindowID p_window_id);
+
GLManager_X11(const Vector2i &p_size, ContextType p_context_type);
~GLManager_X11();
};
diff --git a/platform/macos/display_server_macos.mm b/platform/macos/display_server_macos.mm
index 4478a635a8..33d8a8dd14 100644
--- a/platform/macos/display_server_macos.mm
+++ b/platform/macos/display_server_macos.mm
@@ -2932,6 +2932,11 @@ int64_t DisplayServerMacOS::window_get_native_handle(HandleType p_handle_type, W
case WINDOW_VIEW: {
return (int64_t)windows[p_window].window_view;
}
+#ifdef GLES3_ENABLED
+ case OPENGL_CONTEXT: {
+ return (int64_t)gl_manager->get_context(p_window);
+ }
+#endif
default: {
return 0;
}
diff --git a/platform/macos/gl_manager_macos_legacy.h b/platform/macos/gl_manager_macos_legacy.h
index 8752086551..d7ad5b1197 100644
--- a/platform/macos/gl_manager_macos_legacy.h
+++ b/platform/macos/gl_manager_macos_legacy.h
@@ -89,6 +89,8 @@ public:
void set_use_vsync(bool p_use);
bool is_using_vsync() const;
+ NSOpenGLContext *get_context(DisplayServer::WindowID p_window_id);
+
GLManager_MacOS(ContextType p_context_type);
~GLManager_MacOS();
};
diff --git a/platform/macos/gl_manager_macos_legacy.mm b/platform/macos/gl_manager_macos_legacy.mm
index dec4821b86..ea5c36da6c 100644
--- a/platform/macos/gl_manager_macos_legacy.mm
+++ b/platform/macos/gl_manager_macos_legacy.mm
@@ -215,6 +215,15 @@ bool GLManager_MacOS::is_using_vsync() const {
return use_vsync;
}
+NSOpenGLContext *GLManager_MacOS::get_context(DisplayServer::WindowID p_window_id) {
+ if (!windows.has(p_window_id)) {
+ return nullptr;
+ }
+
+ GLWindow &win = windows[p_window_id];
+ return win.context;
+}
+
GLManager_MacOS::GLManager_MacOS(ContextType p_context_type) {
context_type = p_context_type;
}
diff --git a/platform/web/display_server_web.cpp b/platform/web/display_server_web.cpp
index 5a1a56b9da..f704124704 100644
--- a/platform/web/display_server_web.cpp
+++ b/platform/web/display_server_web.cpp
@@ -54,7 +54,15 @@ DisplayServerWeb *DisplayServerWeb::get_singleton() {
// Window (canvas)
bool DisplayServerWeb::check_size_force_redraw() {
- return godot_js_display_size_update() != 0;
+ bool size_changed = godot_js_display_size_update() != 0;
+ if (size_changed && !rect_changed_callback.is_null()) {
+ Variant size = Rect2i(Point2i(), window_get_size()); // TODO use window_get_position if implemented.
+ Variant *vp = &size;
+ Variant ret;
+ Callable::CallError ce;
+ rect_changed_callback.callp((const Variant **)&vp, 1, ret, ce);
+ }
+ return size_changed;
}
void DisplayServerWeb::fullscreen_change_callback(int p_fullscreen) {
@@ -903,7 +911,7 @@ ObjectID DisplayServerWeb::window_get_attached_instance_id(WindowID p_window) co
}
void DisplayServerWeb::window_set_rect_changed_callback(const Callable &p_callable, WindowID p_window) {
- // Not supported.
+ rect_changed_callback = p_callable;
}
void DisplayServerWeb::window_set_window_event_callback(const Callable &p_callable, WindowID p_window) {
diff --git a/platform/web/display_server_web.h b/platform/web/display_server_web.h
index 3222e2483e..1919736802 100644
--- a/platform/web/display_server_web.h
+++ b/platform/web/display_server_web.h
@@ -60,6 +60,7 @@ private:
WindowMode window_mode = WINDOW_MODE_WINDOWED;
ObjectID window_attached_instance_id = {};
+ Callable rect_changed_callback;
Callable window_event_callback;
Callable input_event_callback;
Callable input_text_callback;
diff --git a/platform/windows/display_server_windows.cpp b/platform/windows/display_server_windows.cpp
index d6ee712a31..2c8058fdc5 100644
--- a/platform/windows/display_server_windows.cpp
+++ b/platform/windows/display_server_windows.cpp
@@ -741,9 +741,14 @@ int64_t DisplayServerWindows::window_get_native_handle(HandleType p_handle_type,
case WINDOW_HANDLE: {
return (int64_t)windows[p_window].hWnd;
}
+#if defined(GLES3_ENABLED)
case WINDOW_VIEW: {
- return 0; // Not supported.
+ return (int64_t)gl_manager->get_hdc(p_window);
}
+ case OPENGL_CONTEXT: {
+ return (int64_t)gl_manager->get_hglrc(p_window);
+ }
+#endif
default: {
return 0;
}
diff --git a/platform/windows/gl_manager_windows.cpp b/platform/windows/gl_manager_windows.cpp
index 7689751f1b..900bca8258 100644
--- a/platform/windows/gl_manager_windows.cpp
+++ b/platform/windows/gl_manager_windows.cpp
@@ -339,6 +339,16 @@ bool GLManager_Windows::is_using_vsync() const {
return use_vsync;
}
+HDC GLManager_Windows::get_hdc(DisplayServer::WindowID p_window_id) {
+ return get_window(p_window_id).hDC;
+}
+
+HGLRC GLManager_Windows::get_hglrc(DisplayServer::WindowID p_window_id) {
+ const GLWindow &win = get_window(p_window_id);
+ const GLDisplay &disp = get_display(win.gldisplay_id);
+ return disp.hRC;
+}
+
GLManager_Windows::GLManager_Windows(ContextType p_context_type) {
context_type = p_context_type;
diff --git a/platform/windows/gl_manager_windows.h b/platform/windows/gl_manager_windows.h
index 5e43a3de2a..c6d5f9f855 100644
--- a/platform/windows/gl_manager_windows.h
+++ b/platform/windows/gl_manager_windows.h
@@ -113,6 +113,9 @@ public:
void set_use_vsync(bool p_use);
bool is_using_vsync() const;
+ HDC get_hdc(DisplayServer::WindowID p_window_id);
+ HGLRC get_hglrc(DisplayServer::WindowID p_window_id);
+
GLManager_Windows(ContextType p_context_type);
~GLManager_Windows();
};
diff --git a/scene/resources/animation.cpp b/scene/resources/animation.cpp
index dfd9c6eb2f..1eb78f0160 100644
--- a/scene/resources/animation.cpp
+++ b/scene/resources/animation.cpp
@@ -5851,18 +5851,18 @@ Variant Animation::interpolate_variant(const Variant &a, const Variant &b, float
return dst;
}
case Variant::PACKED_INT32_ARRAY: {
- const Vector<int32_t> *arr_a = Object::cast_to<Vector<int32_t>>(a);
- const Vector<int32_t> *arr_b = Object::cast_to<Vector<int32_t>>(b);
- int32_t sz = arr_a->size();
- if (sz == 0 || arr_b->size() != sz) {
+ const Vector<int32_t> arr_a = a;
+ const Vector<int32_t> arr_b = b;
+ int32_t sz = arr_a.size();
+ if (sz == 0 || arr_b.size() != sz) {
return a;
} else {
Vector<int32_t> v;
v.resize(sz);
{
int32_t *vw = v.ptrw();
- const int32_t *ar = arr_a->ptr();
- const int32_t *br = arr_b->ptr();
+ const int32_t *ar = arr_a.ptr();
+ const int32_t *br = arr_b.ptr();
Variant va;
for (int32_t i = 0; i < sz; i++) {
@@ -5874,18 +5874,18 @@ Variant Animation::interpolate_variant(const Variant &a, const Variant &b, float
}
}
case Variant::PACKED_INT64_ARRAY: {
- const Vector<int64_t> *arr_a = Object::cast_to<Vector<int64_t>>(a);
- const Vector<int64_t> *arr_b = Object::cast_to<Vector<int64_t>>(b);
- int64_t sz = arr_a->size();
- if (sz == 0 || arr_b->size() != sz) {
+ const Vector<int64_t> arr_a = a;
+ const Vector<int64_t> arr_b = b;
+ int64_t sz = arr_a.size();
+ if (sz == 0 || arr_b.size() != sz) {
return a;
} else {
Vector<int64_t> v;
v.resize(sz);
{
int64_t *vw = v.ptrw();
- const int64_t *ar = arr_a->ptr();
- const int64_t *br = arr_b->ptr();
+ const int64_t *ar = arr_a.ptr();
+ const int64_t *br = arr_b.ptr();
Variant va;
for (int64_t i = 0; i < sz; i++) {
@@ -5897,18 +5897,18 @@ Variant Animation::interpolate_variant(const Variant &a, const Variant &b, float
}
}
case Variant::PACKED_FLOAT32_ARRAY: {
- const Vector<float> *arr_a = Object::cast_to<Vector<float>>(a);
- const Vector<float> *arr_b = Object::cast_to<Vector<float>>(b);
- int sz = arr_a->size();
- if (sz == 0 || arr_b->size() != sz) {
+ const Vector<float> arr_a = a;
+ const Vector<float> arr_b = b;
+ int sz = arr_a.size();
+ if (sz == 0 || arr_b.size() != sz) {
return a;
} else {
Vector<float> v;
v.resize(sz);
{
float *vw = v.ptrw();
- const float *ar = arr_a->ptr();
- const float *br = arr_b->ptr();
+ const float *ar = arr_a.ptr();
+ const float *br = arr_b.ptr();
Variant va;
for (int i = 0; i < sz; i++) {
@@ -5920,18 +5920,18 @@ Variant Animation::interpolate_variant(const Variant &a, const Variant &b, float
}
}
case Variant::PACKED_FLOAT64_ARRAY: {
- const Vector<double> *arr_a = Object::cast_to<Vector<double>>(a);
- const Vector<double> *arr_b = Object::cast_to<Vector<double>>(b);
- int sz = arr_a->size();
- if (sz == 0 || arr_b->size() != sz) {
+ const Vector<double> arr_a = a;
+ const Vector<double> arr_b = b;
+ int sz = arr_a.size();
+ if (sz == 0 || arr_b.size() != sz) {
return a;
} else {
Vector<double> v;
v.resize(sz);
{
double *vw = v.ptrw();
- const double *ar = arr_a->ptr();
- const double *br = arr_b->ptr();
+ const double *ar = arr_a.ptr();
+ const double *br = arr_b.ptr();
Variant va;
for (int i = 0; i < sz; i++) {
@@ -5943,18 +5943,18 @@ Variant Animation::interpolate_variant(const Variant &a, const Variant &b, float
}
}
case Variant::PACKED_VECTOR2_ARRAY: {
- const Vector<Vector2> *arr_a = Object::cast_to<Vector<Vector2>>(a);
- const Vector<Vector2> *arr_b = Object::cast_to<Vector<Vector2>>(b);
- int sz = arr_a->size();
- if (sz == 0 || arr_b->size() != sz) {
+ const Vector<Vector2> arr_a = a;
+ const Vector<Vector2> arr_b = b;
+ int sz = arr_a.size();
+ if (sz == 0 || arr_b.size() != sz) {
return a;
} else {
Vector<Vector2> v;
v.resize(sz);
{
Vector2 *vw = v.ptrw();
- const Vector2 *ar = arr_a->ptr();
- const Vector2 *br = arr_b->ptr();
+ const Vector2 *ar = arr_a.ptr();
+ const Vector2 *br = arr_b.ptr();
for (int i = 0; i < sz; i++) {
vw[i] = ar[i].lerp(br[i], c);
@@ -5964,18 +5964,18 @@ Variant Animation::interpolate_variant(const Variant &a, const Variant &b, float
}
}
case Variant::PACKED_VECTOR3_ARRAY: {
- const Vector<Vector3> *arr_a = Object::cast_to<Vector<Vector3>>(a);
- const Vector<Vector3> *arr_b = Object::cast_to<Vector<Vector3>>(b);
- int sz = arr_a->size();
- if (sz == 0 || arr_b->size() != sz) {
+ const Vector<Vector3> arr_a = a;
+ const Vector<Vector3> arr_b = b;
+ int sz = arr_a.size();
+ if (sz == 0 || arr_b.size() != sz) {
return a;
} else {
Vector<Vector3> v;
v.resize(sz);
{
Vector3 *vw = v.ptrw();
- const Vector3 *ar = arr_a->ptr();
- const Vector3 *br = arr_b->ptr();
+ const Vector3 *ar = arr_a.ptr();
+ const Vector3 *br = arr_b.ptr();
for (int i = 0; i < sz; i++) {
vw[i] = ar[i].lerp(br[i], c);
@@ -5985,18 +5985,18 @@ Variant Animation::interpolate_variant(const Variant &a, const Variant &b, float
}
}
case Variant::PACKED_COLOR_ARRAY: {
- const Vector<Color> *arr_a = Object::cast_to<Vector<Color>>(a);
- const Vector<Color> *arr_b = Object::cast_to<Vector<Color>>(b);
- int sz = arr_a->size();
- if (sz == 0 || arr_b->size() != sz) {
+ const Vector<Color> arr_a = a;
+ const Vector<Color> arr_b = b;
+ int sz = arr_a.size();
+ if (sz == 0 || arr_b.size() != sz) {
return a;
} else {
Vector<Color> v;
v.resize(sz);
{
Color *vw = v.ptrw();
- const Color *ar = arr_a->ptr();
- const Color *br = arr_b->ptr();
+ const Color *ar = arr_a.ptr();
+ const Color *br = arr_b.ptr();
for (int i = 0; i < sz; i++) {
vw[i] = ar[i].lerp(br[i], c);
diff --git a/servers/display_server.cpp b/servers/display_server.cpp
index 1897612562..52d7f66203 100644
--- a/servers/display_server.cpp
+++ b/servers/display_server.cpp
@@ -826,6 +826,7 @@ void DisplayServer::_bind_methods() {
BIND_ENUM_CONSTANT(DISPLAY_HANDLE);
BIND_ENUM_CONSTANT(WINDOW_HANDLE);
BIND_ENUM_CONSTANT(WINDOW_VIEW);
+ BIND_ENUM_CONSTANT(OPENGL_CONTEXT);
BIND_ENUM_CONSTANT(TTS_UTTERANCE_STARTED);
BIND_ENUM_CONSTANT(TTS_UTTERANCE_ENDED);
diff --git a/servers/display_server.h b/servers/display_server.h
index 55e9fb55dc..a796377f88 100644
--- a/servers/display_server.h
+++ b/servers/display_server.h
@@ -70,6 +70,7 @@ public:
DISPLAY_HANDLE,
WINDOW_HANDLE,
WINDOW_VIEW,
+ OPENGL_CONTEXT,
};
typedef DisplayServer *(*CreateFunction)(const String &, WindowMode, VSyncMode, uint32_t, const Point2i *, const Size2i &, Error &r_error);
diff --git a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
index f76d016ae7..898521ca4d 100644
--- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
+++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
@@ -2004,6 +2004,7 @@ void RenderForwardMobile::_render_list_template(RenderingDevice::DrawListID p_dr
RID prev_index_array_rd;
RID prev_pipeline_rd;
RID prev_xforms_uniform_set;
+ bool should_request_redraw = false;
bool shadow_pass = (p_params->pass_mode == PASS_MODE_SHADOW) || (p_params->pass_mode == PASS_MODE_SHADOW_DP);
@@ -2090,6 +2091,11 @@ void RenderForwardMobile::_render_list_template(RenderingDevice::DrawListID p_dr
continue;
}
+ //request a redraw if one of the shaders uses TIME
+ if (shader->uses_time) {
+ should_request_redraw = true;
+ }
+
//find cull variant
SceneShaderForwardMobile::ShaderData::CullVariant cull_variant;
@@ -2191,6 +2197,11 @@ void RenderForwardMobile::_render_list_template(RenderingDevice::DrawListID p_dr
RD::get_singleton()->draw_list_draw(draw_list, index_array_rd.is_valid(), instance_count);
}
+
+ // Make the actual redraw request
+ if (should_request_redraw) {
+ RenderingServerDefault::redraw_request();
+ }
}
/* Geometry instance */