Skip to content

Commit d39f534

Browse files
committed
Merge pull request godotengine#96982 from dsnopek/external-texture
Add external texture support (GLES3)
2 parents b271a88 + 1a6f851 commit d39f534

24 files changed

+355
-5
lines changed

doc/classes/ExternalTexture.xml

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
<?xml version="1.0" encoding="UTF-8" ?>
2+
<class name="ExternalTexture" inherits="Texture2D" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
3+
<brief_description>
4+
Texture which displays the content of an external buffer.
5+
</brief_description>
6+
<description>
7+
Displays the content of an external buffer provided by the platform.
8+
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).
9+
[b]Note:[/b] This is currently only supported in Android builds.
10+
</description>
11+
<tutorials>
12+
</tutorials>
13+
<methods>
14+
<method name="get_external_texture_id" qualifiers="const">
15+
<return type="int" />
16+
<description>
17+
Returns the external texture ID.
18+
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.
19+
</description>
20+
</method>
21+
<method name="set_external_buffer_id">
22+
<return type="void" />
23+
<param index="0" name="external_buffer_id" type="int" />
24+
<description>
25+
Sets the external buffer ID.
26+
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.
27+
</description>
28+
</method>
29+
</methods>
30+
<members>
31+
<member name="resource_local_to_scene" type="bool" setter="set_local_to_scene" getter="is_local_to_scene" overrides="Resource" default="false" />
32+
<member name="size" type="Vector2" setter="set_size" getter="get_size" default="Vector2(256, 256)">
33+
External texture size.
34+
</member>
35+
</members>
36+
</class>

doc/classes/RenderingServer.xml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5660,7 +5660,10 @@
56605660
<constant name="GLOBAL_VAR_TYPE_SAMPLERCUBE" value="27" enum="GlobalShaderParameterType">
56615661
Cubemap sampler global shader parameter ([code]global uniform samplerCube ...[/code]). Exposed as a [Cubemap] in the editor UI.
56625662
</constant>
5663-
<constant name="GLOBAL_VAR_TYPE_MAX" value="28" enum="GlobalShaderParameterType">
5663+
<constant name="GLOBAL_VAR_TYPE_SAMPLEREXT" value="28" enum="GlobalShaderParameterType">
5664+
External sampler global shader parameter ([code]global uniform samplerExternalOES ...[/code]). Exposed as a [ExternalTexture] in the editor UI.
5665+
</constant>
5666+
<constant name="GLOBAL_VAR_TYPE_MAX" value="29" enum="GlobalShaderParameterType">
56645667
Represents the size of the [enum GlobalShaderParameterType] enum.
56655668
</constant>
56665669
<constant name="RENDERING_INFO_TOTAL_OBJECTS_IN_FRAME" value="0" enum="RenderingInfo">

drivers/gles3/shader_gles3.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,14 @@ void ShaderGLES3::_build_variant_code(StringBuilder &builder, uint32_t p_variant
189189
}
190190
builder.append("\n"); //make sure defines begin at newline
191191

192+
// Optional support for external textures.
193+
if (GLES3::Config::get_singleton()->external_texture_supported) {
194+
builder.append("#extension GL_OES_EGL_image_external : enable\n");
195+
builder.append("#extension GL_OES_EGL_image_external_essl3 : enable\n");
196+
} else {
197+
builder.append("#define samplerExternalOES sampler2D\n");
198+
}
199+
192200
// Insert multiview extension loading, because it needs to appear before
193201
// any non-preprocessor code (like the "precision highp..." lines below).
194202
builder.append("#ifdef USE_MULTIVIEW\n");

drivers/gles3/storage/config.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@ Config::Config() {
138138
// These are GLES only
139139
rt_msaa_supported = extensions.has("GL_EXT_multisampled_render_to_texture");
140140
rt_msaa_multiview_supported = extensions.has("GL_OVR_multiview_multisampled_render_to_texture");
141+
external_texture_supported = extensions.has("GL_OES_EGL_image_external_essl3");
141142

142143
if (multiview_supported) {
143144
eglFramebufferTextureMultiviewOVR = (PFNGLFRAMEBUFFERTEXTUREMULTIVIEWOVRPROC)eglGetProcAddress("glFramebufferTextureMultiviewOVR");
@@ -166,6 +167,13 @@ Config::Config() {
166167
rt_msaa_multiview_supported = false;
167168
}
168169
}
170+
171+
if (external_texture_supported) {
172+
eglEGLImageTargetTexture2DOES = (PFNEGLIMAGETARGETTEXTURE2DOESPROC)eglGetProcAddress("glEGLImageTargetTexture2DOES");
173+
if (eglEGLImageTargetTexture2DOES == nullptr) {
174+
external_texture_supported = false;
175+
}
176+
}
169177
#endif
170178

171179
force_vertex_shading = false; //GLOBAL_GET("rendering/quality/shading/force_vertex_shading");

drivers/gles3/storage/config.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ typedef void (*PFNGLFRAMEBUFFERTEXTUREMULTIVIEWOVRPROC)(GLenum, GLenum, GLuint,
4545
typedef void (*PFNGLTEXSTORAGE3DMULTISAMPLEPROC)(GLenum, GLsizei, GLenum, GLsizei, GLsizei, GLsizei, GLboolean);
4646
typedef void (*PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEEXTPROC)(GLenum, GLenum, GLenum, GLuint, GLint, GLsizei);
4747
typedef void (*PFNGLFRAMEBUFFERTEXTUREMULTISAMPLEMULTIVIEWOVRPROC)(GLenum, GLenum, GLuint, GLint, GLsizei, GLint, GLsizei);
48+
typedef void (*PFNEGLIMAGETARGETTEXTURE2DOESPROC)(GLenum, void *);
4849
#endif
4950

5051
namespace GLES3 {
@@ -91,6 +92,7 @@ class Config {
9192
bool rt_msaa_supported = false;
9293
bool rt_msaa_multiview_supported = false;
9394
bool multiview_supported = false;
95+
bool external_texture_supported = false;
9496

9597
// Adreno 3XX compatibility
9698
bool disable_particles_workaround = false; // set to 'true' to disable 'GPUParticles'
@@ -104,6 +106,7 @@ class Config {
104106
PFNGLTEXSTORAGE3DMULTISAMPLEPROC eglTexStorage3DMultisample = nullptr;
105107
PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEEXTPROC eglFramebufferTexture2DMultisampleEXT = nullptr;
106108
PFNGLFRAMEBUFFERTEXTUREMULTISAMPLEMULTIVIEWOVRPROC eglFramebufferTextureMultisampleMultiviewOVR = nullptr;
109+
PFNEGLIMAGETARGETTEXTURE2DOESPROC eglEGLImageTargetTexture2DOES = nullptr;
107110
#endif
108111

109112
static Config *get_singleton() { return singleton; };

drivers/gles3/storage/material_storage.cpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -675,6 +675,7 @@ static const GLenum target_from_type[ShaderLanguage::TYPE_MAX] = {
675675
GL_TEXTURE_3D, // TYPE_USAMPLER3D,
676676
GL_TEXTURE_CUBE_MAP, // TYPE_SAMPLERCUBE,
677677
GL_TEXTURE_CUBE_MAP, // TYPE_SAMPLERCUBEARRAY,
678+
_GL_TEXTURE_EXTERNAL_OES, // TYPE_SAMPLEREXT
678679
GL_TEXTURE_2D, // TYPE_STRUCT
679680
};
680681

@@ -946,6 +947,9 @@ void MaterialData::update_textures(const HashMap<StringName, Variant> &p_paramet
946947
case ShaderLanguage::TYPE_SAMPLERCUBEARRAY: {
947948
ERR_PRINT_ONCE("Type: SamplerCubeArray not supported in GL Compatibility rendering backend, please use another type.");
948949
} break;
950+
case ShaderLanguage::TYPE_SAMPLEREXT: {
951+
gl_texture = texture_storage->texture_gl_get_default(DEFAULT_GL_TEXTURE_EXT);
952+
} break;
949953

950954
case ShaderLanguage::TYPE_ISAMPLER3D:
951955
case ShaderLanguage::TYPE_USAMPLER3D:
@@ -1949,6 +1953,7 @@ void MaterialStorage::global_shader_parameters_load_settings(bool p_load_texture
19491953
"sampler2DArray",
19501954
"sampler3D",
19511955
"samplerCube",
1956+
"samplerExternalOES"
19521957
};
19531958

19541959
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
26612666
const ShaderCompiler::GeneratedCode::Texture &texture_uniform = texture_uniforms[texture_uniform_index];
26622667
if (texture) {
26632668
glActiveTexture(GL_TEXTURE0 + texture_offset + ti);
2664-
glBindTexture(target_from_type[texture_uniform.type], texture->tex_id);
2669+
GLenum target = target_from_type[texture_uniform.type];
2670+
if (target == _GL_TEXTURE_EXTERNAL_OES && !GLES3::Config::get_singleton()->external_texture_supported) {
2671+
target = GL_TEXTURE_2D;
2672+
}
2673+
glBindTexture(target, texture->tex_id);
26652674
if (texture->render_target) {
26662675
texture->render_target->used_in_frame = true;
26672676
}

drivers/gles3/storage/texture_storage.cpp

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,11 @@ TextureStorage::TextureStorage() {
152152
texture_2d_initialize(default_gl_textures[DEFAULT_GL_TEXTURE_ANISO], image);
153153
}
154154

155+
{
156+
default_gl_textures[DEFAULT_GL_TEXTURE_EXT] = texture_allocate();
157+
texture_external_initialize(default_gl_textures[DEFAULT_GL_TEXTURE_EXT], 1, 1, 0);
158+
}
159+
155160
{
156161
unsigned char pixel_data[4 * 4 * 4];
157162
for (int i = 0; i < 16; i++) {
@@ -769,6 +774,48 @@ void TextureStorage::texture_2d_initialize(RID p_texture, const Ref<Image> &p_im
769774
texture_set_data(p_texture, p_image);
770775
}
771776

777+
void TextureStorage::texture_external_initialize(RID p_texture, int p_width, int p_height, uint64_t p_external_buffer) {
778+
Texture texture;
779+
texture.active = true;
780+
texture.alloc_width = texture.width = p_width;
781+
texture.alloc_height = texture.height = p_height;
782+
texture.real_format = texture.format = Image::FORMAT_RGB8;
783+
texture.type = Texture::TYPE_2D;
784+
785+
if (GLES3::Config::get_singleton()->external_texture_supported) {
786+
texture.target = _GL_TEXTURE_EXTERNAL_OES;
787+
} else {
788+
texture.target = GL_TEXTURE_2D;
789+
}
790+
791+
glGenTextures(1, &texture.tex_id);
792+
glBindTexture(texture.target, texture.tex_id);
793+
794+
#ifdef ANDROID_ENABLED
795+
if (texture.target == _GL_TEXTURE_EXTERNAL_OES) {
796+
if (p_external_buffer) {
797+
GLES3::Config::get_singleton()->eglEGLImageTargetTexture2DOES(_GL_TEXTURE_EXTERNAL_OES, reinterpret_cast<void *>(p_external_buffer));
798+
}
799+
texture.total_data_size = 0;
800+
} else
801+
#endif
802+
{
803+
// If external textures aren't supported, allocate an empty 1x1 texture.
804+
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 1, 1, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr);
805+
texture.total_data_size = 3;
806+
}
807+
808+
glTexParameteri(texture.target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
809+
glTexParameteri(texture.target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
810+
glTexParameteri(texture.target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
811+
glTexParameteri(texture.target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
812+
813+
GLES3::Utilities::get_singleton()->texture_allocated_data(texture.tex_id, texture.total_data_size, "Texture External");
814+
texture_owner.initialize_rid(p_texture, texture);
815+
816+
glBindTexture(texture.target, 0);
817+
}
818+
772819
void TextureStorage::texture_2d_layered_initialize(RID p_texture, const Vector<Ref<Image>> &p_layers, RS::TextureLayeredType p_layered_type) {
773820
ERR_FAIL_COND(p_layers.is_empty());
774821

@@ -930,6 +977,22 @@ void TextureStorage::texture_3d_update(RID p_texture, const Vector<Ref<Image>> &
930977
GLES3::Utilities::get_singleton()->texture_resize_data(tex->tex_id, tex->total_data_size);
931978
}
932979

980+
void TextureStorage::texture_external_update(RID p_texture, int p_width, int p_height, uint64_t p_external_buffer) {
981+
Texture *tex = texture_owner.get_or_null(p_texture);
982+
ERR_FAIL_NULL(tex);
983+
984+
tex->alloc_width = tex->width = p_width;
985+
tex->alloc_height = tex->height = p_height;
986+
987+
#ifdef ANDROID_ENABLED
988+
if (tex->target == _GL_TEXTURE_EXTERNAL_OES && p_external_buffer) {
989+
glBindTexture(_GL_TEXTURE_EXTERNAL_OES, tex->tex_id);
990+
GLES3::Config::get_singleton()->eglEGLImageTargetTexture2DOES(_GL_TEXTURE_EXTERNAL_OES, reinterpret_cast<void *>(p_external_buffer));
991+
glBindTexture(_GL_TEXTURE_EXTERNAL_OES, 0);
992+
}
993+
#endif
994+
}
995+
933996
void TextureStorage::texture_proxy_update(RID p_texture, RID p_proxy_to) {
934997
Texture *tex = texture_owner.get_or_null(p_texture);
935998
ERR_FAIL_NULL(tex);

drivers/gles3/storage/texture_storage.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ enum DefaultGLTexture {
126126
DEFAULT_GL_TEXTURE_3D_BLACK,
127127
DEFAULT_GL_TEXTURE_2D_ARRAY_WHITE,
128128
DEFAULT_GL_TEXTURE_2D_UINT,
129+
DEFAULT_GL_TEXTURE_EXT,
129130
DEFAULT_GL_TEXTURE_MAX
130131
};
131132

@@ -512,12 +513,14 @@ class TextureStorage : public RendererTextureStorage {
512513
virtual void texture_2d_initialize(RID p_texture, const Ref<Image> &p_image) override;
513514
virtual void texture_2d_layered_initialize(RID p_texture, const Vector<Ref<Image>> &p_layers, RS::TextureLayeredType p_layered_type) override;
514515
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;
516+
virtual void texture_external_initialize(RID p_texture, int p_width, int p_height, uint64_t p_external_buffer) override;
515517
virtual void texture_proxy_initialize(RID p_texture, RID p_base) override; //all slices, then all the mipmaps, must be coherent
516518

517519
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;
518520

519521
virtual void texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer = 0) override;
520522
virtual void texture_3d_update(RID p_texture, const Vector<Ref<Image>> &p_data) override;
523+
virtual void texture_external_update(RID p_texture, int p_width, int p_height, uint64_t p_external_buffer) override;
521524
virtual void texture_proxy_update(RID p_proxy, RID p_base) override;
522525

523526
//these two APIs can be used together or in combination with the others.

editor/renames_map_3_to_4.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1518,7 +1518,6 @@ const char *RenamesMap3To4::class_renames[][2] = {
15181518
{ "EditorSceneImporterGLTF", "EditorSceneFormatImporterGLTF" },
15191519
{ "EditorSpatialGizmo", "EditorNode3DGizmo" },
15201520
{ "EditorSpatialGizmoPlugin", "EditorNode3DGizmoPlugin" },
1521-
{ "ExternalTexture", "ImageTexture" },
15221521
{ "GIProbe", "VoxelGI" },
15231522
{ "GIProbeData", "VoxelGIData" },
15241523
{ "Generic6DOFJoint", "Generic6DOFJoint3D" },

scene/register_scene_types.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@
117117
#include "scene/resources/compressed_texture.h"
118118
#include "scene/resources/curve_texture.h"
119119
#include "scene/resources/environment.h"
120+
#include "scene/resources/external_texture.h"
120121
#include "scene/resources/font.h"
121122
#include "scene/resources/gradient.h"
122123
#include "scene/resources/gradient_texture.h"
@@ -926,6 +927,7 @@ void register_scene_types() {
926927
GDREGISTER_CLASS(GradientTexture2D);
927928
GDREGISTER_CLASS(AnimatedTexture);
928929
GDREGISTER_CLASS(CameraTexture);
930+
GDREGISTER_CLASS(ExternalTexture);
929931
GDREGISTER_VIRTUAL_CLASS(TextureLayered);
930932
GDREGISTER_ABSTRACT_CLASS(ImageTextureLayered);
931933
GDREGISTER_VIRTUAL_CLASS(Texture3D);

0 commit comments

Comments
 (0)