diff options
42 files changed, 472 insertions, 36 deletions
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index cb25337fad..8cfb00fd8e 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -39,14 +39,14 @@ repos: stages: [manual] # Not automatically triggered, invoked via `pre-commit run --hook-stage manual clang-tidy` - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.4.4 + rev: v0.6.6 hooks: - id: ruff args: [--fix] - id: ruff-format - repo: https://github.com/pre-commit/mirrors-mypy - rev: v0.971 + rev: v1.11.2 hooks: - id: mypy files: \.py$ diff --git a/core/object/object.cpp b/core/object/object.cpp index 2d9d468d38..b3a4ec6e2e 100644 --- a/core/object/object.cpp +++ b/core/object/object.cpp @@ -1457,6 +1457,24 @@ bool Object::is_connected(const StringName &p_signal, const Callable &p_callable return s->slot_map.has(*p_callable.get_base_comparator()); } +bool Object::has_connections(const StringName &p_signal) const { + const SignalData *s = signal_map.getptr(p_signal); + if (!s) { + bool signal_is_valid = ClassDB::has_signal(get_class_name(), p_signal); + if (signal_is_valid) { + return false; + } + + if (!script.is_null() && Ref<Script>(script)->has_script_signal(p_signal)) { + return false; + } + + ERR_FAIL_V_MSG(false, "Nonexistent signal: " + p_signal + "."); + } + + return !s->slot_map.is_empty(); +} + void Object::disconnect(const StringName &p_signal, const Callable &p_callable) { _disconnect(p_signal, p_callable); } @@ -1697,6 +1715,7 @@ void Object::_bind_methods() { ClassDB::bind_method(D_METHOD("connect", "signal", "callable", "flags"), &Object::connect, DEFVAL(0)); ClassDB::bind_method(D_METHOD("disconnect", "signal", "callable"), &Object::disconnect); ClassDB::bind_method(D_METHOD("is_connected", "signal", "callable"), &Object::is_connected); + ClassDB::bind_method(D_METHOD("has_connections", "signal"), &Object::has_connections); ClassDB::bind_method(D_METHOD("set_block_signals", "enable"), &Object::set_block_signals); ClassDB::bind_method(D_METHOD("is_blocking_signals"), &Object::is_blocking_signals); diff --git a/core/object/object.h b/core/object/object.h index 1274247d71..763e2974b9 100644 --- a/core/object/object.h +++ b/core/object/object.h @@ -932,6 +932,7 @@ public: MTVIRTUAL Error connect(const StringName &p_signal, const Callable &p_callable, uint32_t p_flags = 0); MTVIRTUAL void disconnect(const StringName &p_signal, const Callable &p_callable); MTVIRTUAL bool is_connected(const StringName &p_signal, const Callable &p_callable) const; + MTVIRTUAL bool has_connections(const StringName &p_signal) const; template <typename... VarArgs> void call_deferred(const StringName &p_name, VarArgs... p_args) { diff --git a/core/variant/callable.cpp b/core/variant/callable.cpp index 9dff5c1e91..bb2d0313f6 100644 --- a/core/variant/callable.cpp +++ b/core/variant/callable.cpp @@ -545,6 +545,13 @@ bool Signal::is_connected(const Callable &p_callable) const { return obj->is_connected(name, p_callable); } +bool Signal::has_connections() const { + Object *obj = get_object(); + ERR_FAIL_NULL_V(obj, false); + + return obj->has_connections(name); +} + Array Signal::get_connections() const { Object *obj = get_object(); if (!obj) { diff --git a/core/variant/callable.h b/core/variant/callable.h index 63757d9d6e..e3c940a0e5 100644 --- a/core/variant/callable.h +++ b/core/variant/callable.h @@ -192,6 +192,7 @@ public: Error connect(const Callable &p_callable, uint32_t p_flags = 0); void disconnect(const Callable &p_callable); bool is_connected(const Callable &p_callable) const; + bool has_connections() const; Array get_connections() const; Signal(const Object *p_object, const StringName &p_name); diff --git a/core/variant/variant_call.cpp b/core/variant/variant_call.cpp index 178c0bc4ec..63fb5e8d94 100644 --- a/core/variant/variant_call.cpp +++ b/core/variant/variant_call.cpp @@ -2121,6 +2121,7 @@ static void _register_variant_builtin_methods_misc() { bind_method(Signal, disconnect, sarray("callable"), varray()); bind_method(Signal, is_connected, sarray("callable"), varray()); bind_method(Signal, get_connections, sarray(), varray()); + bind_method(Signal, has_connections, sarray(), varray()); bind_custom(Signal, emit, _VariantCall::func_Signal_emit, false, Variant); diff --git a/doc/classes/ExternalTexture.xml b/doc/classes/ExternalTexture.xml new file mode 100644 index 0000000000..6f27b62f24 --- /dev/null +++ b/doc/classes/ExternalTexture.xml @@ -0,0 +1,36 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="ExternalTexture" inherits="Texture2D" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> + <brief_description> + Texture which displays the content of an external buffer. + </brief_description> + <description> + Displays the content of an external buffer provided by the platform. + Requires the [url=https://registry.khronos.org/OpenGL/extensions/OES/OES_EGL_image_external.txt]OES_EGL_image_external[/url] extension (OpenGL) or [url=https://registry.khronos.org/vulkan/specs/1.1-extensions/html/vkspec.html#VK_ANDROID_external_memory_android_hardware_buffer]VK_ANDROID_external_memory_android_hardware_buffer[/url] extension (Vulkan). + [b]Note:[/b] This is currently only supported in Android builds. + </description> + <tutorials> + </tutorials> + <methods> + <method name="get_external_texture_id" qualifiers="const"> + <return type="int" /> + <description> + Returns the external texture ID. + Depending on your use case, you may need to pass this to platform APIs, for example, when creating an [code]android.graphics.SurfaceTexture[/code] on Android. + </description> + </method> + <method name="set_external_buffer_id"> + <return type="void" /> + <param index="0" name="external_buffer_id" type="int" /> + <description> + Sets the external buffer ID. + Depending on your use case, you may need to call this with data received from a platform API, for example, [code]SurfaceTexture.getHardwareBuffer()[/code] on Android. + </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" /> + <member name="size" type="Vector2" setter="set_size" getter="get_size" default="Vector2(256, 256)"> + External texture size. + </member> + </members> +</class> diff --git a/doc/classes/Object.xml b/doc/classes/Object.xml index d0d0876108..2767a11e80 100644 --- a/doc/classes/Object.xml +++ b/doc/classes/Object.xml @@ -824,6 +824,14 @@ Returns the name of the translation domain used by [method tr] and [method tr_n]. See also [TranslationServer]. </description> </method> + <method name="has_connections" qualifiers="const"> + <return type="bool" /> + <param index="0" name="signal" type="StringName" /> + <description> + Returns [code]true[/code] if any connection exists on the given [param signal] name. + [b]Note:[/b] In C#, [param signal] must be in snake_case when referring to built-in Godot methods. Prefer using the names exposed in the [code]SignalName[/code] class to avoid allocating a new [StringName] on each call. + </description> + </method> <method name="has_meta" qualifiers="const"> <return type="bool" /> <param index="0" name="name" type="StringName" /> diff --git a/doc/classes/RenderingServer.xml b/doc/classes/RenderingServer.xml index 7a0893268a..144f78349f 100644 --- a/doc/classes/RenderingServer.xml +++ b/doc/classes/RenderingServer.xml @@ -5660,7 +5660,10 @@ <constant name="GLOBAL_VAR_TYPE_SAMPLERCUBE" value="27" enum="GlobalShaderParameterType"> Cubemap sampler global shader parameter ([code]global uniform samplerCube ...[/code]). Exposed as a [Cubemap] in the editor UI. </constant> - <constant name="GLOBAL_VAR_TYPE_MAX" value="28" enum="GlobalShaderParameterType"> + <constant name="GLOBAL_VAR_TYPE_SAMPLEREXT" value="28" enum="GlobalShaderParameterType"> + External sampler global shader parameter ([code]global uniform samplerExternalOES ...[/code]). Exposed as a [ExternalTexture] in the editor UI. + </constant> + <constant name="GLOBAL_VAR_TYPE_MAX" value="29" enum="GlobalShaderParameterType"> Represents the size of the [enum GlobalShaderParameterType] enum. </constant> <constant name="RENDERING_INFO_TOTAL_OBJECTS_IN_FRAME" value="0" enum="RenderingInfo"> diff --git a/doc/classes/ScrollContainer.xml b/doc/classes/ScrollContainer.xml index 2181194fd4..405bba3564 100644 --- a/doc/classes/ScrollContainer.xml +++ b/doc/classes/ScrollContainer.xml @@ -102,6 +102,9 @@ <constant name="SCROLL_MODE_SHOW_NEVER" value="3" enum="ScrollMode"> Scrolling enabled, scrollbar will be hidden. </constant> + <constant name="SCROLL_MODE_RESERVE" value="4" enum="ScrollMode"> + Combines [constant SCROLL_MODE_AUTO] and [constant SCROLL_MODE_SHOW_ALWAYS]. The scrollbar is only visible if necessary, but the content size is adjusted as if it was always visible. It's useful for ensuring that content size stays the same regardless if the scrollbar is visible. + </constant> </constants> <theme_items> <theme_item name="panel" data_type="style" type="StyleBox"> diff --git a/doc/classes/Signal.xml b/doc/classes/Signal.xml index 7d6ff1e9b0..65168d6980 100644 --- a/doc/classes/Signal.xml +++ b/doc/classes/Signal.xml @@ -109,6 +109,12 @@ Returns the ID of the object emitting this signal (see [method Object.get_instance_id]). </description> </method> + <method name="has_connections" qualifiers="const"> + <return type="bool" /> + <description> + Returns [code]true[/code] if any [Callable] is connected to this signal. + </description> + </method> <method name="is_connected" qualifiers="const"> <return type="bool" /> <param index="0" name="callable" type="Callable" /> diff --git a/drivers/gles3/shader_gles3.cpp b/drivers/gles3/shader_gles3.cpp index 5a0f394db0..b73debf04a 100644 --- a/drivers/gles3/shader_gles3.cpp +++ b/drivers/gles3/shader_gles3.cpp @@ -189,6 +189,14 @@ void ShaderGLES3::_build_variant_code(StringBuilder &builder, uint32_t p_variant } builder.append("\n"); //make sure defines begin at newline + // Optional support for external textures. + if (GLES3::Config::get_singleton()->external_texture_supported) { + builder.append("#extension GL_OES_EGL_image_external : enable\n"); + builder.append("#extension GL_OES_EGL_image_external_essl3 : enable\n"); + } else { + builder.append("#define samplerExternalOES sampler2D\n"); + } + // Insert multiview extension loading, because it needs to appear before // any non-preprocessor code (like the "precision highp..." lines below). builder.append("#ifdef USE_MULTIVIEW\n"); diff --git a/drivers/gles3/storage/config.cpp b/drivers/gles3/storage/config.cpp index d6472c44c1..4947d5d4ce 100644 --- a/drivers/gles3/storage/config.cpp +++ b/drivers/gles3/storage/config.cpp @@ -138,6 +138,7 @@ Config::Config() { // These are GLES only rt_msaa_supported = extensions.has("GL_EXT_multisampled_render_to_texture"); rt_msaa_multiview_supported = extensions.has("GL_OVR_multiview_multisampled_render_to_texture"); + external_texture_supported = extensions.has("GL_OES_EGL_image_external_essl3"); if (multiview_supported) { eglFramebufferTextureMultiviewOVR = (PFNGLFRAMEBUFFERTEXTUREMULTIVIEWOVRPROC)eglGetProcAddress("glFramebufferTextureMultiviewOVR"); @@ -166,6 +167,13 @@ Config::Config() { rt_msaa_multiview_supported = false; } } + + if (external_texture_supported) { + eglEGLImageTargetTexture2DOES = (PFNEGLIMAGETARGETTEXTURE2DOESPROC)eglGetProcAddress("glEGLImageTargetTexture2DOES"); + if (eglEGLImageTargetTexture2DOES == nullptr) { + external_texture_supported = false; + } + } #endif force_vertex_shading = false; //GLOBAL_GET("rendering/quality/shading/force_vertex_shading"); diff --git a/drivers/gles3/storage/config.h b/drivers/gles3/storage/config.h index ff72fc5b58..1de00094f0 100644 --- a/drivers/gles3/storage/config.h +++ b/drivers/gles3/storage/config.h @@ -45,6 +45,7 @@ typedef void (*PFNGLFRAMEBUFFERTEXTUREMULTIVIEWOVRPROC)(GLenum, GLenum, GLuint, typedef void (*PFNGLTEXSTORAGE3DMULTISAMPLEPROC)(GLenum, GLsizei, GLenum, GLsizei, GLsizei, GLsizei, GLboolean); typedef void (*PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEEXTPROC)(GLenum, GLenum, GLenum, GLuint, GLint, GLsizei); typedef void (*PFNGLFRAMEBUFFERTEXTUREMULTISAMPLEMULTIVIEWOVRPROC)(GLenum, GLenum, GLuint, GLint, GLsizei, GLint, GLsizei); +typedef void (*PFNEGLIMAGETARGETTEXTURE2DOESPROC)(GLenum, void *); #endif namespace GLES3 { @@ -91,6 +92,7 @@ public: bool rt_msaa_supported = false; bool rt_msaa_multiview_supported = false; bool multiview_supported = false; + bool external_texture_supported = false; // Adreno 3XX compatibility bool disable_particles_workaround = false; // set to 'true' to disable 'GPUParticles' @@ -104,6 +106,7 @@ public: PFNGLTEXSTORAGE3DMULTISAMPLEPROC eglTexStorage3DMultisample = nullptr; PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEEXTPROC eglFramebufferTexture2DMultisampleEXT = nullptr; PFNGLFRAMEBUFFERTEXTUREMULTISAMPLEMULTIVIEWOVRPROC eglFramebufferTextureMultisampleMultiviewOVR = nullptr; + PFNEGLIMAGETARGETTEXTURE2DOESPROC eglEGLImageTargetTexture2DOES = nullptr; #endif static Config *get_singleton() { return singleton; }; diff --git a/drivers/gles3/storage/material_storage.cpp b/drivers/gles3/storage/material_storage.cpp index 7d5af48384..c29c741c2a 100644 --- a/drivers/gles3/storage/material_storage.cpp +++ b/drivers/gles3/storage/material_storage.cpp @@ -675,6 +675,7 @@ static const GLenum target_from_type[ShaderLanguage::TYPE_MAX] = { GL_TEXTURE_3D, // TYPE_USAMPLER3D, GL_TEXTURE_CUBE_MAP, // TYPE_SAMPLERCUBE, GL_TEXTURE_CUBE_MAP, // TYPE_SAMPLERCUBEARRAY, + _GL_TEXTURE_EXTERNAL_OES, // TYPE_SAMPLEREXT GL_TEXTURE_2D, // TYPE_STRUCT }; @@ -946,6 +947,9 @@ void MaterialData::update_textures(const HashMap<StringName, Variant> &p_paramet case ShaderLanguage::TYPE_SAMPLERCUBEARRAY: { ERR_PRINT_ONCE("Type: SamplerCubeArray not supported in GL Compatibility rendering backend, please use another type."); } break; + case ShaderLanguage::TYPE_SAMPLEREXT: { + gl_texture = texture_storage->texture_gl_get_default(DEFAULT_GL_TEXTURE_EXT); + } break; case ShaderLanguage::TYPE_ISAMPLER3D: case ShaderLanguage::TYPE_USAMPLER3D: @@ -1949,6 +1953,7 @@ void MaterialStorage::global_shader_parameters_load_settings(bool p_load_texture "sampler2DArray", "sampler3D", "samplerCube", + "samplerExternalOES" }; RS::GlobalShaderParameterType gvtype = RS::GLOBAL_VAR_TYPE_MAX; @@ -2661,7 +2666,11 @@ static void bind_uniforms_generic(const Vector<RID> &p_textures, const Vector<Sh const ShaderCompiler::GeneratedCode::Texture &texture_uniform = texture_uniforms[texture_uniform_index]; if (texture) { glActiveTexture(GL_TEXTURE0 + texture_offset + ti); - glBindTexture(target_from_type[texture_uniform.type], texture->tex_id); + GLenum target = target_from_type[texture_uniform.type]; + if (target == _GL_TEXTURE_EXTERNAL_OES && !GLES3::Config::get_singleton()->external_texture_supported) { + target = GL_TEXTURE_2D; + } + glBindTexture(target, texture->tex_id); if (texture->render_target) { texture->render_target->used_in_frame = true; } diff --git a/drivers/gles3/storage/texture_storage.cpp b/drivers/gles3/storage/texture_storage.cpp index bd824a076e..27ba89aa5f 100644 --- a/drivers/gles3/storage/texture_storage.cpp +++ b/drivers/gles3/storage/texture_storage.cpp @@ -153,6 +153,11 @@ TextureStorage::TextureStorage() { } { + default_gl_textures[DEFAULT_GL_TEXTURE_EXT] = texture_allocate(); + texture_external_initialize(default_gl_textures[DEFAULT_GL_TEXTURE_EXT], 1, 1, 0); + } + + { unsigned char pixel_data[4 * 4 * 4]; for (int i = 0; i < 16; i++) { pixel_data[i * 4 + 0] = 0; @@ -769,6 +774,48 @@ void TextureStorage::texture_2d_initialize(RID p_texture, const Ref<Image> &p_im texture_set_data(p_texture, p_image); } +void TextureStorage::texture_external_initialize(RID p_texture, int p_width, int p_height, uint64_t p_external_buffer) { + Texture texture; + texture.active = true; + texture.alloc_width = texture.width = p_width; + texture.alloc_height = texture.height = p_height; + texture.real_format = texture.format = Image::FORMAT_RGB8; + texture.type = Texture::TYPE_2D; + + if (GLES3::Config::get_singleton()->external_texture_supported) { + texture.target = _GL_TEXTURE_EXTERNAL_OES; + } else { + texture.target = GL_TEXTURE_2D; + } + + glGenTextures(1, &texture.tex_id); + glBindTexture(texture.target, texture.tex_id); + +#ifdef ANDROID_ENABLED + if (texture.target == _GL_TEXTURE_EXTERNAL_OES) { + if (p_external_buffer) { + GLES3::Config::get_singleton()->eglEGLImageTargetTexture2DOES(_GL_TEXTURE_EXTERNAL_OES, reinterpret_cast<void *>(p_external_buffer)); + } + texture.total_data_size = 0; + } else +#endif + { + // If external textures aren't supported, allocate an empty 1x1 texture. + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 1, 1, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr); + texture.total_data_size = 3; + } + + glTexParameteri(texture.target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(texture.target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(texture.target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(texture.target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + GLES3::Utilities::get_singleton()->texture_allocated_data(texture.tex_id, texture.total_data_size, "Texture External"); + texture_owner.initialize_rid(p_texture, texture); + + glBindTexture(texture.target, 0); +} + void TextureStorage::texture_2d_layered_initialize(RID p_texture, const Vector<Ref<Image>> &p_layers, RS::TextureLayeredType p_layered_type) { ERR_FAIL_COND(p_layers.is_empty()); @@ -930,6 +977,22 @@ void TextureStorage::texture_3d_update(RID p_texture, const Vector<Ref<Image>> & GLES3::Utilities::get_singleton()->texture_resize_data(tex->tex_id, tex->total_data_size); } +void TextureStorage::texture_external_update(RID p_texture, int p_width, int p_height, uint64_t p_external_buffer) { + Texture *tex = texture_owner.get_or_null(p_texture); + ERR_FAIL_NULL(tex); + + tex->alloc_width = tex->width = p_width; + tex->alloc_height = tex->height = p_height; + +#ifdef ANDROID_ENABLED + if (tex->target == _GL_TEXTURE_EXTERNAL_OES && p_external_buffer) { + glBindTexture(_GL_TEXTURE_EXTERNAL_OES, tex->tex_id); + GLES3::Config::get_singleton()->eglEGLImageTargetTexture2DOES(_GL_TEXTURE_EXTERNAL_OES, reinterpret_cast<void *>(p_external_buffer)); + glBindTexture(_GL_TEXTURE_EXTERNAL_OES, 0); + } +#endif +} + void TextureStorage::texture_proxy_update(RID p_texture, RID p_proxy_to) { Texture *tex = texture_owner.get_or_null(p_texture); ERR_FAIL_NULL(tex); diff --git a/drivers/gles3/storage/texture_storage.h b/drivers/gles3/storage/texture_storage.h index b1d4630978..2bf8546c0f 100644 --- a/drivers/gles3/storage/texture_storage.h +++ b/drivers/gles3/storage/texture_storage.h @@ -126,6 +126,7 @@ enum DefaultGLTexture { DEFAULT_GL_TEXTURE_3D_BLACK, DEFAULT_GL_TEXTURE_2D_ARRAY_WHITE, DEFAULT_GL_TEXTURE_2D_UINT, + DEFAULT_GL_TEXTURE_EXT, DEFAULT_GL_TEXTURE_MAX }; @@ -512,12 +513,14 @@ public: virtual void texture_2d_initialize(RID p_texture, const Ref<Image> &p_image) override; virtual void texture_2d_layered_initialize(RID p_texture, const Vector<Ref<Image>> &p_layers, RS::TextureLayeredType p_layered_type) override; 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_external_initialize(RID p_texture, int p_width, int p_height, uint64_t p_external_buffer) override; virtual void texture_proxy_initialize(RID p_texture, RID p_base) override; //all slices, then all the mipmaps, must be coherent virtual RID texture_create_from_native_handle(RS::TextureType p_type, Image::Format p_format, uint64_t p_native_handle, int p_width, int p_height, int p_depth, int p_layers = 1, RS::TextureLayeredType p_layered_type = RS::TEXTURE_LAYERED_2D_ARRAY) override; 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_external_update(RID p_texture, int p_width, int p_height, uint64_t p_external_buffer) override; virtual void texture_proxy_update(RID p_proxy, RID p_base) override; //these two APIs can be used together or in combination with the others. diff --git a/editor/editor_help_search.cpp b/editor/editor_help_search.cpp index 47ff21bc82..47f16f219f 100644 --- a/editor/editor_help_search.cpp +++ b/editor/editor_help_search.cpp @@ -530,7 +530,7 @@ bool EditorHelpSearch::Runner::_phase_fill_member_items_init() { return true; } -TreeItem *EditorHelpSearch::Runner::_create_category_item(TreeItem *p_parent, const String &p_class, const StringName &p_icon, const String &p_metatype, const String &p_text) { +TreeItem *EditorHelpSearch::Runner::_create_category_item(TreeItem *p_parent, const String &p_class, const StringName &p_icon, const String &p_text, const String &p_metatype) { const String item_meta = "class_" + p_metatype + ":" + p_class; TreeItem *item = nullptr; @@ -620,7 +620,7 @@ bool EditorHelpSearch::Runner::_phase_fill_member_items() { if ((search_flags & SEARCH_PROPERTIES) && !class_doc->properties.is_empty()) { TreeItem *parent_item = item; if (search_all) { - parent_item = _create_category_item(parent_item, class_doc->name, SNAME("MemberProperty"), TTRC("Prtoperties"), "propertiess"); + parent_item = _create_category_item(parent_item, class_doc->name, SNAME("MemberProperty"), TTRC("Properties"), "properties"); } for (const DocData::PropertyDoc &property_doc : class_doc->properties) { _create_property_item(parent_item, class_doc, &property_doc); diff --git a/editor/editor_help_search.h b/editor/editor_help_search.h index b8b3c26b41..f4d0c6c89e 100644 --- a/editor/editor_help_search.h +++ b/editor/editor_help_search.h @@ -198,7 +198,7 @@ class EditorHelpSearch::Runner : public RefCounted { TreeItem *_create_class_hierarchy(const ClassMatch &p_match); TreeItem *_create_class_hierarchy(const DocData::ClassDoc *p_class_doc, const String &p_matching_keyword, bool p_gray); TreeItem *_create_class_item(TreeItem *p_parent, const DocData::ClassDoc *p_doc, bool p_gray, const String &p_matching_keyword); - TreeItem *_create_category_item(TreeItem *p_parent, const String &p_class, const StringName &p_icon, const String &p_metatype, const String &p_type); + TreeItem *_create_category_item(TreeItem *p_parent, const String &p_class, const StringName &p_icon, const String &p_text, const String &p_metatype); TreeItem *_create_method_item(TreeItem *p_parent, const DocData::ClassDoc *p_class_doc, const MemberMatch<DocData::MethodDoc> &p_match); TreeItem *_create_constructor_item(TreeItem *p_parent, const DocData::ClassDoc *p_class_doc, const MemberMatch<DocData::MethodDoc> &p_match); TreeItem *_create_operator_item(TreeItem *p_parent, const DocData::ClassDoc *p_class_doc, const MemberMatch<DocData::MethodDoc> &p_match); diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index 44292b4185..184176391a 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -4952,8 +4952,10 @@ String EditorNode::_get_system_info() const { godot_version += " " + hash; } + String display_session_type; #ifdef LINUXBSD_ENABLED - const String display_server = OS::get_singleton()->get_environment("XDG_SESSION_TYPE").capitalize().replace(" ", ""); // `replace` is necessary, because `capitalize` introduces a whitespace between "x" and "11". + // `replace` is necessary, because `capitalize` introduces a whitespace between "x" and "11". + display_session_type = OS::get_singleton()->get_environment("XDG_SESSION_TYPE").capitalize().replace(" ", ""); #endif // LINUXBSD_ENABLED String driver_name = OS::get_singleton()->get_current_rendering_driver_name().to_lower(); String rendering_method = OS::get_singleton()->get_current_rendering_method().to_lower(); @@ -5014,16 +5016,33 @@ String EditorNode::_get_system_info() const { // Join info. Vector<String> info; info.push_back(godot_version); + String distribution_display_session_type = distribution_name; if (!distribution_version.is_empty()) { - info.push_back(distribution_name + " " + distribution_version); - } else { - info.push_back(distribution_name); + distribution_display_session_type += " " + distribution_version; } -#ifdef LINUXBSD_ENABLED - if (!display_server.is_empty()) { - info.push_back(display_server); + if (!display_session_type.is_empty()) { + distribution_display_session_type += " on " + display_session_type; } + info.push_back(distribution_display_session_type); + + String display_driver_window_mode; +#ifdef LINUXBSD_ENABLED + // `replace` is necessary, because `capitalize` introduces a whitespace between "x" and "11". + display_driver_window_mode = DisplayServer::get_singleton()->get_name().capitalize().replace(" ", "") + " display driver"; #endif // LINUXBSD_ENABLED + if (!display_driver_window_mode.is_empty()) { + display_driver_window_mode += ", "; + } + display_driver_window_mode += get_viewport()->is_embedding_subwindows() ? "Single-window" : "Multi-window"; + + if (DisplayServer::get_singleton()->get_screen_count() == 1) { + display_driver_window_mode += ", " + itos(DisplayServer::get_singleton()->get_screen_count()) + " monitor"; + } else { + display_driver_window_mode += ", " + itos(DisplayServer::get_singleton()->get_screen_count()) + " monitors"; + } + + info.push_back(display_driver_window_mode); + info.push_back(vformat("%s (%s)", driver_name, rendering_method)); String graphics; @@ -5042,7 +5061,7 @@ String EditorNode::_get_system_info() const { } info.push_back(graphics); - info.push_back(vformat("%s (%d Threads)", processor_name, processor_count)); + info.push_back(vformat("%s (%d threads)", processor_name, processor_count)); return String(" - ").join(info); } diff --git a/editor/renames_map_3_to_4.cpp b/editor/renames_map_3_to_4.cpp index 8eab3fbea9..ae7c86a5e5 100644 --- a/editor/renames_map_3_to_4.cpp +++ b/editor/renames_map_3_to_4.cpp @@ -1518,7 +1518,6 @@ const char *RenamesMap3To4::class_renames[][2] = { { "EditorSceneImporterGLTF", "EditorSceneFormatImporterGLTF" }, { "EditorSpatialGizmo", "EditorNode3DGizmo" }, { "EditorSpatialGizmoPlugin", "EditorNode3DGizmoPlugin" }, - { "ExternalTexture", "ImageTexture" }, { "GIProbe", "VoxelGI" }, { "GIProbeData", "VoxelGIData" }, { "Generic6DOFJoint", "Generic6DOFJoint3D" }, diff --git a/modules/raycast/godot_update_embree.py b/modules/raycast/godot_update_embree.py index c179060365..c4fff330c9 100644 --- a/modules/raycast/godot_update_embree.py +++ b/modules/raycast/godot_update_embree.py @@ -4,8 +4,8 @@ import re import shutil import stat import subprocess -from types import TracebackType -from typing import Any, Callable, Tuple, Type +import sys +from typing import Any, Callable git_tag = "v4.3.1" @@ -100,9 +100,7 @@ subprocess.run(["git", "checkout", git_tag]) commit_hash = str(subprocess.check_output(["git", "rev-parse", "HEAD"], universal_newlines=True)).strip() -def on_rm_error( - function: Callable[..., Any], path: str, excinfo: Tuple[Type[Exception], Exception, TracebackType] -) -> None: +def on_rm_error(function: Callable[..., Any], path: str, excinfo: Exception) -> None: """ Error handler for `shutil.rmtree()`. @@ -113,10 +111,12 @@ def on_rm_error( os.unlink(path) -# 3.12 Python and beyond should replace `onerror` with `onexc`. # We remove the .git directory because it contains # a lot of read-only files that are problematic on Windows. -shutil.rmtree(".git", onerror=on_rm_error) +if sys.version_info >= (3, 12): + shutil.rmtree(".git", onexc=on_rm_error) +else: + shutil.rmtree(".git", onerror=on_rm_error) # type: ignore all_files = set(cpp_files) diff --git a/pyproject.toml b/pyproject.toml index 59b6d09a03..1cf789b460 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -10,6 +10,7 @@ warn_unreachable = true namespace_packages = true explicit_package_bases = true exclude = ["thirdparty/"] +python_version = "3.8" [tool.ruff] extend-exclude = ["thirdparty"] diff --git a/scene/gui/scroll_container.cpp b/scene/gui/scroll_container.cpp index f1902bade4..2211bd76fc 100644 --- a/scene/gui/scroll_container.cpp +++ b/scene/gui/scroll_container.cpp @@ -58,7 +58,7 @@ Size2 ScrollContainer::get_minimum_size() const { if (horizontal_scroll_mode == SCROLL_MODE_DISABLED) { min_size.x = largest_child_min_size.x; - bool v_scroll_show = vertical_scroll_mode == SCROLL_MODE_SHOW_ALWAYS || (vertical_scroll_mode == SCROLL_MODE_AUTO && largest_child_min_size.y > size.y); + bool v_scroll_show = vertical_scroll_mode == SCROLL_MODE_SHOW_ALWAYS || vertical_scroll_mode == SCROLL_MODE_RESERVE || (vertical_scroll_mode == SCROLL_MODE_AUTO && largest_child_min_size.y > size.y); if (v_scroll_show && v_scroll->get_parent() == this) { min_size.x += v_scroll->get_minimum_size().x; } @@ -66,7 +66,7 @@ Size2 ScrollContainer::get_minimum_size() const { if (vertical_scroll_mode == SCROLL_MODE_DISABLED) { min_size.y = largest_child_min_size.y; - bool h_scroll_show = horizontal_scroll_mode == SCROLL_MODE_SHOW_ALWAYS || (horizontal_scroll_mode == SCROLL_MODE_AUTO && largest_child_min_size.x > size.x); + bool h_scroll_show = horizontal_scroll_mode == SCROLL_MODE_SHOW_ALWAYS || horizontal_scroll_mode == SCROLL_MODE_RESERVE || (horizontal_scroll_mode == SCROLL_MODE_AUTO && largest_child_min_size.x > size.x); if (h_scroll_show && h_scroll->get_parent() == this) { min_size.y += h_scroll->get_minimum_size().y; } @@ -92,6 +92,15 @@ void ScrollContainer::_cancel_drag() { } } +bool ScrollContainer::_is_h_scroll_visible() const { + // Scrolls may have been moved out for reasons. + return h_scroll->is_visible() && h_scroll->get_parent() == this; +} + +bool ScrollContainer::_is_v_scroll_visible() const { + return v_scroll->is_visible() && v_scroll->get_parent() == this; +} + void ScrollContainer::gui_input(const Ref<InputEvent> &p_gui_input) { ERR_FAIL_COND(p_gui_input.is_null()); @@ -298,11 +307,11 @@ void ScrollContainer::_reposition_children() { ofs += theme_cache.panel_style->get_offset(); bool rtl = is_layout_rtl(); - if (h_scroll->is_visible_in_tree() && h_scroll->get_parent() == this) { //scrolls may have been moved out for reasons + if (_is_h_scroll_visible() || horizontal_scroll_mode == SCROLL_MODE_RESERVE) { size.y -= h_scroll->get_minimum_size().y; } - if (v_scroll->is_visible_in_tree() && v_scroll->get_parent() == this) { //scrolls may have been moved out for reasons + if (_is_v_scroll_visible() || vertical_scroll_mode == SCROLL_MODE_RESERVE) { size.x -= v_scroll->get_minimum_size().x; } @@ -324,7 +333,7 @@ void ScrollContainer::_reposition_children() { r.size.height = MAX(size.height, minsize.height); } r.position += ofs; - if (rtl && v_scroll->is_visible_in_tree() && v_scroll->get_parent() == this) { + if (rtl && _is_v_scroll_visible()) { r.position.x += v_scroll->get_minimum_size().x; } r.position = r.position.floor(); @@ -436,14 +445,14 @@ void ScrollContainer::update_scrollbars() { Size2 hmin = h_scroll->get_combined_minimum_size(); Size2 vmin = v_scroll->get_combined_minimum_size(); - h_scroll->set_visible(horizontal_scroll_mode == SCROLL_MODE_SHOW_ALWAYS || (horizontal_scroll_mode == SCROLL_MODE_AUTO && largest_child_min_size.width > size.width)); - v_scroll->set_visible(vertical_scroll_mode == SCROLL_MODE_SHOW_ALWAYS || (vertical_scroll_mode == SCROLL_MODE_AUTO && largest_child_min_size.height > size.height)); + h_scroll->set_visible(horizontal_scroll_mode == SCROLL_MODE_SHOW_ALWAYS || ((horizontal_scroll_mode == SCROLL_MODE_AUTO || horizontal_scroll_mode == SCROLL_MODE_RESERVE) && largest_child_min_size.width > size.width)); + v_scroll->set_visible(vertical_scroll_mode == SCROLL_MODE_SHOW_ALWAYS || ((vertical_scroll_mode == SCROLL_MODE_AUTO || vertical_scroll_mode == SCROLL_MODE_RESERVE) && largest_child_min_size.height > size.height)); h_scroll->set_max(largest_child_min_size.width); - h_scroll->set_page((v_scroll->is_visible() && v_scroll->get_parent() == this) ? size.width - vmin.width : size.width); + h_scroll->set_page(_is_v_scroll_visible() ? size.width - vmin.width : size.width); v_scroll->set_max(largest_child_min_size.height); - v_scroll->set_page((h_scroll->is_visible() && h_scroll->get_parent() == this) ? size.height - hmin.height : size.height); + v_scroll->set_page(_is_h_scroll_visible() ? size.height - hmin.height : size.height); // Avoid scrollbar overlapping. _updating_scrollbars = true; @@ -603,14 +612,15 @@ void ScrollContainer::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT, "scroll_vertical", PROPERTY_HINT_NONE, "suffix:px"), "set_v_scroll", "get_v_scroll"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "scroll_horizontal_custom_step", PROPERTY_HINT_RANGE, "-1,4096,suffix:px"), "set_horizontal_custom_step", "get_horizontal_custom_step"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "scroll_vertical_custom_step", PROPERTY_HINT_RANGE, "-1,4096,suffix:px"), "set_vertical_custom_step", "get_vertical_custom_step"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "horizontal_scroll_mode", PROPERTY_HINT_ENUM, "Disabled,Auto,Always Show,Never Show"), "set_horizontal_scroll_mode", "get_horizontal_scroll_mode"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "vertical_scroll_mode", PROPERTY_HINT_ENUM, "Disabled,Auto,Always Show,Never Show"), "set_vertical_scroll_mode", "get_vertical_scroll_mode"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "horizontal_scroll_mode", PROPERTY_HINT_ENUM, "Disabled,Auto,Always Show,Never Show,Reserve"), "set_horizontal_scroll_mode", "get_horizontal_scroll_mode"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "vertical_scroll_mode", PROPERTY_HINT_ENUM, "Disabled,Auto,Always Show,Never Show,Reserve"), "set_vertical_scroll_mode", "get_vertical_scroll_mode"); ADD_PROPERTY(PropertyInfo(Variant::INT, "scroll_deadzone"), "set_deadzone", "get_deadzone"); BIND_ENUM_CONSTANT(SCROLL_MODE_DISABLED); BIND_ENUM_CONSTANT(SCROLL_MODE_AUTO); BIND_ENUM_CONSTANT(SCROLL_MODE_SHOW_ALWAYS); BIND_ENUM_CONSTANT(SCROLL_MODE_SHOW_NEVER); + BIND_ENUM_CONSTANT(SCROLL_MODE_RESERVE); BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_STYLEBOX, ScrollContainer, panel_style, "panel"); diff --git a/scene/gui/scroll_container.h b/scene/gui/scroll_container.h index 02146618cd..afd3c8bd57 100644 --- a/scene/gui/scroll_container.h +++ b/scene/gui/scroll_container.h @@ -44,6 +44,7 @@ public: SCROLL_MODE_AUTO, SCROLL_MODE_SHOW_ALWAYS, SCROLL_MODE_SHOW_NEVER, + SCROLL_MODE_RESERVE, }; private: @@ -75,6 +76,9 @@ private: void _cancel_drag(); + bool _is_h_scroll_visible() const; + bool _is_v_scroll_visible() const; + protected: Size2 get_minimum_size() const override; diff --git a/scene/main/node.cpp b/scene/main/node.cpp index eb3448e1a2..d921cc5b67 100644 --- a/scene/main/node.cpp +++ b/scene/main/node.cpp @@ -4019,4 +4019,9 @@ bool Node::is_connected(const StringName &p_signal, const Callable &p_callable) return Object::is_connected(p_signal, p_callable); } +bool Node::has_connections(const StringName &p_signal) const { + ERR_THREAD_GUARD_V(false); + return Object::has_connections(p_signal); +} + #endif diff --git a/scene/main/node.h b/scene/main/node.h index 4560ed085c..298cbc7e59 100644 --- a/scene/main/node.h +++ b/scene/main/node.h @@ -797,6 +797,7 @@ public: virtual Error connect(const StringName &p_signal, const Callable &p_callable, uint32_t p_flags = 0) override; virtual void disconnect(const StringName &p_signal, const Callable &p_callable) override; virtual bool is_connected(const StringName &p_signal, const Callable &p_callable) const override; + virtual bool has_connections(const StringName &p_signal) const override; #endif Node(); ~Node(); diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp index 76678e609a..09227e260f 100644 --- a/scene/register_scene_types.cpp +++ b/scene/register_scene_types.cpp @@ -117,6 +117,7 @@ #include "scene/resources/compressed_texture.h" #include "scene/resources/curve_texture.h" #include "scene/resources/environment.h" +#include "scene/resources/external_texture.h" #include "scene/resources/font.h" #include "scene/resources/gradient.h" #include "scene/resources/gradient_texture.h" @@ -926,6 +927,7 @@ void register_scene_types() { GDREGISTER_CLASS(GradientTexture2D); GDREGISTER_CLASS(AnimatedTexture); GDREGISTER_CLASS(CameraTexture); + GDREGISTER_CLASS(ExternalTexture); GDREGISTER_VIRTUAL_CLASS(TextureLayered); GDREGISTER_ABSTRACT_CLASS(ImageTextureLayered); GDREGISTER_VIRTUAL_CLASS(Texture3D); diff --git a/scene/resources/external_texture.cpp b/scene/resources/external_texture.cpp new file mode 100644 index 0000000000..c088406030 --- /dev/null +++ b/scene/resources/external_texture.cpp @@ -0,0 +1,92 @@ +/**************************************************************************/ +/* external_texture.cpp */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#include "external_texture.h" + +#include "drivers/gles3/storage/texture_storage.h" +#include "servers/rendering/rendering_server_globals.h" + +void ExternalTexture::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_size", "size"), &ExternalTexture::set_size); + ClassDB::bind_method(D_METHOD("get_external_texture_id"), &ExternalTexture::get_external_texture_id); + ClassDB::bind_method(D_METHOD("set_external_buffer_id", "external_buffer_id"), &ExternalTexture::set_external_buffer_id); + + ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "size"), "set_size", "get_size"); +} + +uint64_t ExternalTexture::get_external_texture_id() const { + return RenderingServer::get_singleton()->texture_get_native_handle(texture); +} + +void ExternalTexture::set_size(const Size2 &p_size) { + if (p_size.width > 0 && p_size.height > 0 && p_size != size) { + size = p_size; + RenderingServer::get_singleton()->texture_external_update(texture, size.width, size.height, external_buffer); + emit_changed(); + } +} + +Size2 ExternalTexture::get_size() const { + return size; +} + +void ExternalTexture::set_external_buffer_id(uint64_t p_external_buffer) { + if (p_external_buffer != external_buffer) { + external_buffer = p_external_buffer; + RenderingServer::get_singleton()->texture_external_update(texture, size.width, size.height, external_buffer); + } +} + +int ExternalTexture::get_width() const { + return size.width; +} + +int ExternalTexture::get_height() const { + return size.height; +} + +bool ExternalTexture::has_alpha() const { + return false; +} + +RID ExternalTexture::get_rid() const { + return texture; +} + +ExternalTexture::ExternalTexture() { + texture = RenderingServer::get_singleton()->texture_external_create(size.width, size.height); +} + +ExternalTexture::~ExternalTexture() { + if (texture.is_valid()) { + ERR_FAIL_NULL(RenderingServer::get_singleton()); + RenderingServer::get_singleton()->free(texture); + } +} diff --git a/scene/resources/external_texture.h b/scene/resources/external_texture.h new file mode 100644 index 0000000000..96bcd8d0fe --- /dev/null +++ b/scene/resources/external_texture.h @@ -0,0 +1,66 @@ +/**************************************************************************/ +/* external_texture.h */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#ifndef EXTERNAL_TEXTURE_H +#define EXTERNAL_TEXTURE_H + +#include "scene/resources/texture.h" + +// External textures as defined by OES_EGL_image_external (GLES) or VK_ANDROID_external_memory_android_hardware_buffer (Vulkan). +class ExternalTexture : public Texture2D { + GDCLASS(ExternalTexture, Texture2D); + +private: + RID texture; + Size2 size = Size2(256, 256); + uint64_t external_buffer = 0; + +protected: + static void _bind_methods(); + +public: + uint64_t get_external_texture_id() const; + + virtual Size2 get_size() const override; + void set_size(const Size2 &p_size); + + void set_external_buffer_id(uint64_t p_external_buffer); + + virtual int get_width() const override; + virtual int get_height() const override; + + virtual RID get_rid() const override; + virtual bool has_alpha() const override; + + ExternalTexture(); + ~ExternalTexture(); +}; + +#endif // EXTERNAL_TEXTURE_H diff --git a/servers/rendering/dummy/storage/texture_storage.h b/servers/rendering/dummy/storage/texture_storage.h index 1a566b518d..6da7446e69 100644 --- a/servers/rendering/dummy/storage/texture_storage.h +++ b/servers/rendering/dummy/storage/texture_storage.h @@ -90,12 +90,14 @@ public: }; virtual void texture_2d_layered_initialize(RID p_texture, const Vector<Ref<Image>> &p_layers, RS::TextureLayeredType p_layered_type) override {} 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_external_initialize(RID p_texture, int p_width, int p_height, uint64_t p_external_buffer) override {} virtual void texture_proxy_initialize(RID p_texture, RID p_base) override {} //all slices, then all the mipmaps, must be coherent virtual RID texture_create_from_native_handle(RS::TextureType p_type, Image::Format p_format, uint64_t p_native_handle, int p_width, int p_height, int p_depth, int p_layers = 1, RS::TextureLayeredType p_layered_type = RS::TEXTURE_LAYERED_2D_ARRAY) override { return RID(); } 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_external_update(RID p_texture, int p_width, int p_height, uint64_t p_external_buffer) override {} virtual void texture_proxy_update(RID p_proxy, RID p_base) override {} //these two APIs can be used together or in combination with the others. diff --git a/servers/rendering/renderer_rd/shader_rd.cpp b/servers/rendering/renderer_rd/shader_rd.cpp index e6a745d3b4..39c3e9b168 100644 --- a/servers/rendering/renderer_rd/shader_rd.cpp +++ b/servers/rendering/renderer_rd/shader_rd.cpp @@ -200,6 +200,8 @@ void ShaderRD::_build_variant_code(StringBuilder &builder, uint32_t p_variant, c #endif builder.append(String("#define RENDER_DRIVER_") + OS::get_singleton()->get_current_rendering_driver_name().to_upper() + "\n"); + builder.append("#define samplerExternalOES sampler2D\n"); + builder.append("#define textureExternalOES texture2D\n"); } break; case StageTemplate::Chunk::TYPE_MATERIAL_UNIFORMS: { builder.append(p_version->uniforms.get_data()); //uniforms (same for vertex and fragment) diff --git a/servers/rendering/renderer_rd/storage_rd/material_storage.cpp b/servers/rendering/renderer_rd/storage_rd/material_storage.cpp index 9f390c99f9..3bfc1bd15c 100644 --- a/servers/rendering/renderer_rd/storage_rd/material_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/material_storage.cpp @@ -1639,6 +1639,7 @@ void MaterialStorage::global_shader_parameters_load_settings(bool p_load_texture "sampler2DArray", "sampler3D", "samplerCube", + "samplerExternalOES", }; RS::GlobalShaderParameterType gvtype = RS::GLOBAL_VAR_TYPE_MAX; diff --git a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp index 81ab384edc..e5a8dbb9b2 100644 --- a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp @@ -1087,6 +1087,9 @@ void TextureStorage::texture_3d_initialize(RID p_texture, Image::Format p_format texture_owner.initialize_rid(p_texture, texture); } +void TextureStorage::texture_external_initialize(RID p_texture, int p_width, int p_height, uint64_t p_external_buffer) { +} + void TextureStorage::texture_proxy_initialize(RID p_texture, RID p_base) { Texture *tex = texture_owner.get_or_null(p_base); ERR_FAIL_NULL(tex); @@ -1361,6 +1364,9 @@ void TextureStorage::texture_3d_update(RID p_texture, const Vector<Ref<Image>> & RD::get_singleton()->texture_update(tex->rd_texture, 0, all_data); } +void TextureStorage::texture_external_update(RID p_texture, int p_width, int p_height, uint64_t p_external_buffer) { +} + void TextureStorage::texture_proxy_update(RID p_texture, RID p_proxy_to) { Texture *tex = texture_owner.get_or_null(p_texture); ERR_FAIL_NULL(tex); diff --git a/servers/rendering/renderer_rd/storage_rd/texture_storage.h b/servers/rendering/renderer_rd/storage_rd/texture_storage.h index d352690fff..9de4ff7b6b 100644 --- a/servers/rendering/renderer_rd/storage_rd/texture_storage.h +++ b/servers/rendering/renderer_rd/storage_rd/texture_storage.h @@ -491,12 +491,14 @@ public: virtual void texture_2d_initialize(RID p_texture, const Ref<Image> &p_image) override; virtual void texture_2d_layered_initialize(RID p_texture, const Vector<Ref<Image>> &p_layers, RS::TextureLayeredType p_layered_type) override; 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_external_initialize(RID p_texture, int p_width, int p_height, uint64_t p_external_buffer) override; virtual void texture_proxy_initialize(RID p_texture, RID p_base) override; //all slices, then all the mipmaps, must be coherent virtual RID texture_create_from_native_handle(RS::TextureType p_type, Image::Format p_format, uint64_t p_native_handle, int p_width, int p_height, int p_depth, int p_layers = 1, RS::TextureLayeredType p_layered_type = RS::TEXTURE_LAYERED_2D_ARRAY) override; 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_external_update(RID p_texture, int p_width, int p_height, uint64_t p_external_buffer) override; virtual void texture_proxy_update(RID p_proxy, RID p_base) override; //these two APIs can be used together or in combination with the others. diff --git a/servers/rendering/rendering_server_default.h b/servers/rendering/rendering_server_default.h index fb4f4aa756..2dcdc3f254 100644 --- a/servers/rendering/rendering_server_default.h +++ b/servers/rendering/rendering_server_default.h @@ -162,6 +162,17 @@ public: return ret; \ } +#define FUNCRIDTEX3(m_type, m_type1, m_type2, m_type3) \ + virtual RID m_type##_create(m_type1 p1, m_type2 p2, m_type3 p3) override { \ + RID ret = RSG::texture_storage->texture_allocate(); \ + if (Thread::get_caller_id() == server_thread || RSG::texture_storage->can_create_resources_async()) { \ + RSG::texture_storage->m_type##_initialize(ret, p1, p2, p3); \ + } else { \ + command_queue.push(RSG::texture_storage, &RendererTextureStorage::m_type##_initialize, ret, p1, p2, p3); \ + } \ + return ret; \ + } + #define FUNCRIDTEX6(m_type, m_type1, m_type2, m_type3, m_type4, m_type5, m_type6) \ virtual RID m_type##_create(m_type1 p1, m_type2 p2, m_type3 p3, m_type4 p4, m_type5 p5, m_type6 p6) override { \ RID ret = RSG::texture_storage->texture_allocate(); \ @@ -177,6 +188,7 @@ public: FUNCRIDTEX1(texture_2d, const Ref<Image> &) FUNCRIDTEX2(texture_2d_layered, const Vector<Ref<Image>> &, TextureLayeredType) FUNCRIDTEX6(texture_3d, Image::Format, int, int, int, bool, const Vector<Ref<Image>> &) + FUNCRIDTEX3(texture_external, int, int, uint64_t) FUNCRIDTEX1(texture_proxy, RID) // Called directly, not through the command queue. @@ -187,6 +199,7 @@ public: //these go through command queue if they are in another thread FUNC3(texture_2d_update, RID, const Ref<Image> &, int) FUNC2(texture_3d_update, RID, const Vector<Ref<Image>> &) + FUNC4(texture_external_update, RID, int, int, uint64_t) FUNC2(texture_proxy_update, RID, RID) //these also go pass-through diff --git a/servers/rendering/shader_compiler.cpp b/servers/rendering/shader_compiler.cpp index 5f97fa0c9b..3a0b9cf158 100644 --- a/servers/rendering/shader_compiler.cpp +++ b/servers/rendering/shader_compiler.cpp @@ -113,6 +113,8 @@ static int _get_datatype_alignment(SL::DataType p_type) { return 16; case SL::TYPE_SAMPLERCUBEARRAY: return 16; + case SL::TYPE_SAMPLEREXT: + return 16; case SL::TYPE_STRUCT: return 0; case SL::TYPE_MAX: { diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp index 5a3c5d2fd0..14bd3841df 100644 --- a/servers/rendering/shader_language.cpp +++ b/servers/rendering/shader_language.cpp @@ -315,6 +315,7 @@ const ShaderLanguage::KeyWord ShaderLanguage::keyword_list[] = { { TK_TYPE_USAMPLER3D, "usampler3D", KCF_SAMPLER_DATATYPE, {}, {} }, { TK_TYPE_SAMPLERCUBE, "samplerCube", KCF_SAMPLER_DATATYPE, {}, {} }, { TK_TYPE_SAMPLERCUBEARRAY, "samplerCubeArray", KCF_SAMPLER_DATATYPE, {}, {} }, + { TK_TYPE_SAMPLEREXT, "samplerExternalOES", KCF_SAMPLER_DATATYPE, {}, {} }, // interpolation qualifiers @@ -1027,7 +1028,8 @@ bool ShaderLanguage::is_token_datatype(TokenType p_type) { p_type == TK_TYPE_ISAMPLER3D || p_type == TK_TYPE_USAMPLER3D || p_type == TK_TYPE_SAMPLERCUBE || - p_type == TK_TYPE_SAMPLERCUBEARRAY); + p_type == TK_TYPE_SAMPLERCUBEARRAY || + p_type == TK_TYPE_SAMPLEREXT); } ShaderLanguage::DataType ShaderLanguage::get_token_datatype(TokenType p_type) { @@ -1162,6 +1164,8 @@ String ShaderLanguage::get_datatype_name(DataType p_type) { return "samplerCube"; case TYPE_SAMPLERCUBEARRAY: return "samplerCubeArray"; + case TYPE_SAMPLEREXT: + return "samplerExternalOES"; case TYPE_STRUCT: return "struct"; case TYPE_MAX: @@ -3169,6 +3173,8 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = { { "texture", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, false }, { "texture", TYPE_VEC4, { TYPE_SAMPLERCUBEARRAY, TYPE_VEC4, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, false }, { "texture", TYPE_VEC4, { TYPE_SAMPLERCUBEARRAY, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, false }, + { "texture", TYPE_VEC4, { TYPE_SAMPLEREXT, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, false }, + { "texture", TYPE_VEC4, { TYPE_SAMPLEREXT, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, false }, // textureProj @@ -4482,7 +4488,8 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<Scalar> &p_value, case ShaderLanguage::TYPE_USAMPLER2D: case ShaderLanguage::TYPE_USAMPLER3D: case ShaderLanguage::TYPE_SAMPLERCUBE: - case ShaderLanguage::TYPE_SAMPLERCUBEARRAY: { + case ShaderLanguage::TYPE_SAMPLERCUBEARRAY: + case ShaderLanguage::TYPE_SAMPLEREXT: { // Texture types, likely not relevant here. break; } @@ -4707,6 +4714,17 @@ PropertyInfo ShaderLanguage::uniform_to_property_info(const ShaderNode::Uniform pi.hint_string = "Texture3D"; } } break; + case ShaderLanguage::TYPE_SAMPLEREXT: { + if (p_uniform.array_size > 0) { + pi.type = Variant::ARRAY; + pi.hint = PROPERTY_HINT_ARRAY_TYPE; + pi.hint_string = MAKE_RESOURCE_TYPE_HINT("ExternalTexture"); + } else { + pi.type = Variant::OBJECT; + pi.hint = PROPERTY_HINT_RESOURCE_TYPE; + pi.hint_string = "ExternalTexture"; + } + } break; case ShaderLanguage::TYPE_STRUCT: { // FIXME: Implement this. } break; @@ -4780,6 +4798,8 @@ uint32_t ShaderLanguage::get_datatype_size(ShaderLanguage::DataType p_type) { return 16; case TYPE_SAMPLERCUBEARRAY: return 16; + case TYPE_SAMPLEREXT: + return 16; case TYPE_STRUCT: return 0; case TYPE_MAX: { @@ -4921,6 +4941,7 @@ ShaderLanguage::DataType ShaderLanguage::get_scalar_type(DataType p_type) { TYPE_UINT, TYPE_FLOAT, TYPE_FLOAT, + TYPE_FLOAT, TYPE_VOID, }; @@ -4963,6 +4984,7 @@ int ShaderLanguage::get_cardinality(DataType p_type) { 1, 1, 1, + 1, }; static_assert(sizeof(cardinality_table) / sizeof(*cardinality_table) == TYPE_MAX); diff --git a/servers/rendering/shader_language.h b/servers/rendering/shader_language.h index b0d579dfe7..48df77f6bb 100644 --- a/servers/rendering/shader_language.h +++ b/servers/rendering/shader_language.h @@ -91,6 +91,7 @@ public: TK_TYPE_USAMPLER3D, TK_TYPE_SAMPLERCUBE, TK_TYPE_SAMPLERCUBEARRAY, + TK_TYPE_SAMPLEREXT, TK_INTERPOLATION_FLAT, TK_INTERPOLATION_SMOOTH, TK_CONST, @@ -235,6 +236,7 @@ public: TYPE_USAMPLER3D, TYPE_SAMPLERCUBE, TYPE_SAMPLERCUBEARRAY, + TYPE_SAMPLEREXT, TYPE_STRUCT, TYPE_MAX }; diff --git a/servers/rendering/storage/texture_storage.h b/servers/rendering/storage/texture_storage.h index 6e1cb9eb7f..fd17b052ee 100644 --- a/servers/rendering/storage/texture_storage.h +++ b/servers/rendering/storage/texture_storage.h @@ -69,12 +69,14 @@ public: virtual void texture_2d_initialize(RID p_texture, const Ref<Image> &p_image) = 0; virtual void texture_2d_layered_initialize(RID p_texture, const Vector<Ref<Image>> &p_layers, RS::TextureLayeredType p_layered_type) = 0; 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) = 0; + virtual void texture_external_initialize(RID p_texture, int p_width, int p_height, uint64_t p_external_buffer) = 0; virtual void texture_proxy_initialize(RID p_texture, RID p_base) = 0; //all slices, then all the mipmaps, must be coherent virtual RID texture_create_from_native_handle(RS::TextureType p_type, Image::Format p_format, uint64_t p_native_handle, int p_width, int p_height, int p_depth, int p_layers = 1, RS::TextureLayeredType p_layered_type = RS::TEXTURE_LAYERED_2D_ARRAY) = 0; virtual void texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer = 0) = 0; virtual void texture_3d_update(RID p_texture, const Vector<Ref<Image>> &p_data) = 0; + virtual void texture_external_update(RID p_proxy, int p_width, int p_height, uint64_t p_external_buffer) = 0; virtual void texture_proxy_update(RID p_proxy, RID p_base) = 0; //these two APIs can be used together or in combination with the others. diff --git a/servers/rendering_server.cpp b/servers/rendering_server.cpp index a1c05fa2e7..0ad56961c0 100644 --- a/servers/rendering_server.cpp +++ b/servers/rendering_server.cpp @@ -3405,6 +3405,7 @@ void RenderingServer::_bind_methods() { BIND_ENUM_CONSTANT(GLOBAL_VAR_TYPE_SAMPLER2DARRAY); BIND_ENUM_CONSTANT(GLOBAL_VAR_TYPE_SAMPLER3D); BIND_ENUM_CONSTANT(GLOBAL_VAR_TYPE_SAMPLERCUBE); + BIND_ENUM_CONSTANT(GLOBAL_VAR_TYPE_SAMPLEREXT); BIND_ENUM_CONSTANT(GLOBAL_VAR_TYPE_MAX); /* Free */ diff --git a/servers/rendering_server.h b/servers/rendering_server.h index 2b45b73f09..a130ae0ba2 100644 --- a/servers/rendering_server.h +++ b/servers/rendering_server.h @@ -137,12 +137,14 @@ public: virtual RID texture_2d_create(const Ref<Image> &p_image) = 0; virtual RID texture_2d_layered_create(const Vector<Ref<Image>> &p_layers, TextureLayeredType p_layered_type) = 0; virtual RID texture_3d_create(Image::Format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data) = 0; //all slices, then all the mipmaps, must be coherent + virtual RID texture_external_create(int p_width, int p_height, uint64_t p_external_buffer = 0) = 0; virtual RID texture_proxy_create(RID p_base) = 0; virtual RID texture_create_from_native_handle(TextureType p_type, Image::Format p_format, uint64_t p_native_handle, int p_width, int p_height, int p_depth, int p_layers = 1, TextureLayeredType p_layered_type = TEXTURE_LAYERED_2D_ARRAY) = 0; virtual void texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer = 0) = 0; virtual void texture_3d_update(RID p_texture, const Vector<Ref<Image>> &p_data) = 0; + virtual void texture_external_update(RID p_texture, int p_width, int p_height, uint64_t p_external_buffer = 0) = 0; virtual void texture_proxy_update(RID p_texture, RID p_proxy_to) = 0; // These two APIs can be used together or in combination with the others. @@ -1647,6 +1649,7 @@ public: GLOBAL_VAR_TYPE_SAMPLER2DARRAY, GLOBAL_VAR_TYPE_SAMPLER3D, GLOBAL_VAR_TYPE_SAMPLERCUBE, + GLOBAL_VAR_TYPE_SAMPLEREXT, GLOBAL_VAR_TYPE_MAX }; |