Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for opengl external textures #36342

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions doc/classes/ExternalTexture.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="ExternalTexture" inherits="Texture" category="Core" version="3.2">
<brief_description>
Adds support for external textures as defined by https://www.khronos.org/registry/OpenGL/extensions/OES/OES_EGL_image_external.txt
</brief_description>
<description>
</description>
<tutorials>
</tutorials>
<methods>
<method name="get_external_texture_id" qualifiers="const">
<return type="int"/>
<description>
Returns the external texture name.
</description>
</method>
</methods>
<members>
<member name="size" type="Vector2" setter="set_size" getter="get_size" default="Vector2( 1, 1 )">
External texture size.
</member>
</members>
<constants>
</constants>
</class>
4 changes: 4 additions & 0 deletions doc/classes/Shader.xml
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@
<member name="code" type="String" setter="set_code" getter="get_code" default="&quot;&quot;">
Returns the shader's code as the user has written it, not the full generated code used internally.
</member>
<member name="custom_defines" type="String" setter="set_custom_defines" getter="get_custom_defines" default="&quot;&quot;">
Returns the shader's custom defines. Custom defines can be used in Godot to add GLSL preprocessor directives (e.g: extensions) required for the shader logic.
[b]Note:[/b] Custom defines are not validated by the Godot shader parser, so care should be taken when using them.
</member>
</members>
<constants>
<constant name="MODE_SPATIAL" value="0" enum="Mode">
Expand Down
4 changes: 4 additions & 0 deletions drivers/dummy/rasterizer_dummy.h
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,10 @@ class RasterizerStorageDummy : public RasterizerStorage {
void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture) {}
RID shader_get_default_texture_param(RID p_shader, const StringName &p_name) const { return RID(); }

void shader_add_custom_define(RID p_shader, const String &p_define) {}
void shader_get_custom_defines(RID p_shader, Vector<String> *p_defines) const {}
void shader_clear_custom_defines(RID p_shader) {}

/* COMMON MATERIAL API */

RID material_create() { return RID(); }
Expand Down
103 changes: 77 additions & 26 deletions drivers/gles2/rasterizer_storage_gles2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ GLuint RasterizerStorageGLES2::system_fbo = 0;
#define _EXT_COMPRESSED_RGB_BPTC_SIGNED_FLOAT 0x8E8E
#define _EXT_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT 0x8E8F

#define _GL_TEXTURE_EXTERNAL_OES 0x8D65

#ifdef GLES_OVER_GL
#define _GL_HALF_FLOAT_OES 0x140B
#else
Expand Down Expand Up @@ -562,6 +564,10 @@ void RasterizerStorageGLES2::texture_allocate(RID p_texture, int p_width, int p_
texture->target = GL_TEXTURE_2D;
texture->images.resize(1);
} break;
case VS::TEXTURE_TYPE_EXTERNAL: {
texture->target = _GL_TEXTURE_EXTERNAL_OES;
texture->images.resize(0);
} break;
case VS::TEXTURE_TYPE_CUBEMAP: {
texture->target = GL_TEXTURE_CUBE_MAP;
texture->images.resize(6);
Expand All @@ -578,44 +584,59 @@ void RasterizerStorageGLES2::texture_allocate(RID p_texture, int p_width, int p_
}
}

texture->alloc_width = texture->width;
texture->alloc_height = texture->height;
texture->resize_to_po2 = false;
if (!config.support_npot_repeat_mipmap) {
int po2_width = next_power_of_2(p_width);
int po2_height = next_power_of_2(p_height);
if (p_type != VS::TEXTURE_TYPE_EXTERNAL) {
texture->alloc_width = texture->width;
texture->alloc_height = texture->height;
texture->resize_to_po2 = false;
if (!config.support_npot_repeat_mipmap) {
int po2_width = next_power_of_2(p_width);
int po2_height = next_power_of_2(p_height);

bool is_po2 = p_width == po2_width && p_height == po2_height;
bool is_po2 = p_width == po2_width && p_height == po2_height;

if (!is_po2 && (p_flags & VS::TEXTURE_FLAG_REPEAT || p_flags & VS::TEXTURE_FLAG_MIPMAPS)) {
if (!is_po2 && (p_flags & VS::TEXTURE_FLAG_REPEAT || p_flags & VS::TEXTURE_FLAG_MIPMAPS)) {

if (p_flags & VS::TEXTURE_FLAG_USED_FOR_STREAMING) {
//not supported
ERR_PRINTS("Streaming texture for non power of 2 or has mipmaps on this hardware: " + texture->path + "'. Mipmaps and repeat disabled.");
texture->flags &= ~(VS::TEXTURE_FLAG_REPEAT | VS::TEXTURE_FLAG_MIPMAPS);
} else {
texture->alloc_height = po2_height;
texture->alloc_width = po2_width;
texture->resize_to_po2 = true;
if (p_flags & VS::TEXTURE_FLAG_USED_FOR_STREAMING) {
//not supported
ERR_PRINT("Streaming texture for non power of 2 or has mipmaps on this hardware: " + texture->path + "'. Mipmaps and repeat disabled.");
texture->flags &= ~(VS::TEXTURE_FLAG_REPEAT | VS::TEXTURE_FLAG_MIPMAPS);
} else {
texture->alloc_height = po2_height;
texture->alloc_width = po2_width;
texture->resize_to_po2 = true;
}
}
}
}

Image::Format real_format;
_get_gl_image_and_format(Ref<Image>(), texture->format, texture->flags, real_format, format, internal_format, type, compressed, texture->resize_to_po2);
Image::Format real_format;
_get_gl_image_and_format(Ref<Image>(),
texture->format,
texture->flags,
real_format,
format,
internal_format,
type,
compressed,
texture->resize_to_po2);

texture->gl_format_cache = format;
texture->gl_type_cache = type;
texture->gl_internal_format_cache = internal_format;
texture->data_size = 0;
texture->mipmaps = 1;
texture->gl_format_cache = format;
texture->gl_type_cache = type;
texture->gl_internal_format_cache = internal_format;
texture->data_size = 0;
texture->mipmaps = 1;

texture->compressed = compressed;
texture->compressed = compressed;
}

glActiveTexture(GL_TEXTURE0);
glBindTexture(texture->target, texture->tex_id);

if (p_flags & VS::TEXTURE_FLAG_USED_FOR_STREAMING) {
if (p_type == VS::TEXTURE_TYPE_EXTERNAL) {
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);
} else if (p_flags & VS::TEXTURE_FLAG_USED_FOR_STREAMING) {
//prealloc if video
glTexImage2D(texture->target, 0, internal_format, texture->alloc_width, texture->alloc_height, 0, format, type, NULL);
}
Expand All @@ -635,6 +656,7 @@ void RasterizerStorageGLES2::texture_set_data(RID p_texture, const Ref<Image> &p
ERR_FAIL_COND(texture->render_target);
ERR_FAIL_COND(texture->format != p_image->get_format());
ERR_FAIL_COND(p_image.is_null());
ERR_FAIL_COND(texture->type == VS::TEXTURE_TYPE_EXTERNAL);

GLenum type;
GLenum format;
Expand Down Expand Up @@ -1624,6 +1646,7 @@ void RasterizerStorageGLES2::shader_get_param_list(RID p_shader, List<PropertyIn
} break;

case ShaderLanguage::TYPE_SAMPLER2D:
case ShaderLanguage::TYPE_SAMPLEREXT:
case ShaderLanguage::TYPE_ISAMPLER2D:
case ShaderLanguage::TYPE_USAMPLER2D: {
pi.type = Variant::OBJECT;
Expand Down Expand Up @@ -1680,6 +1703,34 @@ RID RasterizerStorageGLES2::shader_get_default_texture_param(RID p_shader, const
return E->get();
}

void RasterizerStorageGLES2::shader_add_custom_define(RID p_shader, const String &p_define) {

Shader *shader = shader_owner.get(p_shader);
ERR_FAIL_COND(!shader);

shader->shader->add_custom_define(p_define);

_shader_make_dirty(shader);
}

void RasterizerStorageGLES2::shader_get_custom_defines(RID p_shader, Vector<String> *p_defines) const {

Shader *shader = shader_owner.get(p_shader);
ERR_FAIL_COND(!shader);

shader->shader->get_custom_defines(p_defines);
}

void RasterizerStorageGLES2::shader_clear_custom_defines(RID p_shader) {

Shader *shader = shader_owner.get(p_shader);
ERR_FAIL_COND(!shader);

shader->shader->clear_custom_defines();

_shader_make_dirty(shader);
}

/* COMMON MATERIAL API */

void RasterizerStorageGLES2::_material_make_dirty(Material *p_material) const {
Expand Down
4 changes: 4 additions & 0 deletions drivers/gles2/rasterizer_storage_gles2.h
Original file line number Diff line number Diff line change
Expand Up @@ -525,6 +525,10 @@ class RasterizerStorageGLES2 : public RasterizerStorage {
virtual void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture);
virtual RID shader_get_default_texture_param(RID p_shader, const StringName &p_name) const;

virtual void shader_add_custom_define(RID p_shader, const String &p_define);
virtual void shader_get_custom_defines(RID p_shader, Vector<String> *p_defines) const;
virtual void shader_clear_custom_defines(RID p_shader);

void _update_shader(Shader *p_shader) const;
void update_dirty_shaders();

Expand Down
3 changes: 2 additions & 1 deletion drivers/gles2/shader_compiler_gles2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -656,7 +656,8 @@ String ShaderCompilerGLES2::_dump_node_code(SL::Node *p_node, int p_level, Gener
if (var_node->name == "texture") {
// emit texture call

if (op_node->arguments[1]->get_datatype() == SL::TYPE_SAMPLER2D) {
if (op_node->arguments[1]->get_datatype() == SL::TYPE_SAMPLER2D ||
op_node->arguments[1]->get_datatype() == SL::TYPE_SAMPLEREXT) {
code += "texture2D";
} else if (op_node->arguments[1]->get_datatype() == SL::TYPE_SAMPLERCUBE) {
code += "textureCube";
Expand Down
18 changes: 18 additions & 0 deletions drivers/gles2/shader_gles2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,16 @@ ShaderGLES2::Version *ShaderGLES2::get_current_version() {

#endif

#ifdef ANDROID_ENABLED
strings.push_back("#define ANDROID_ENABLED\n");
#endif

for (int i = 0; i < custom_defines.size(); i++) {

strings.push_back(custom_defines[i].get_data());
strings.push_back("\n");
}

for (int j = 0; j < conditional_count; j++) {
bool enable = (conditional_version.version & (1 << j)) > 0;

Expand Down Expand Up @@ -941,6 +951,10 @@ void ShaderGLES2::use_material(void *p_material) {

} break;

case ShaderLanguage::TYPE_SAMPLEREXT: {

} break;

case ShaderLanguage::TYPE_ISAMPLER2D: {

} break;
Expand Down Expand Up @@ -1060,6 +1074,10 @@ void ShaderGLES2::use_material(void *p_material) {

} break;

case ShaderLanguage::TYPE_SAMPLEREXT: {

} break;

case ShaderLanguage::TYPE_ISAMPLER2D: {

} break;
Expand Down
10 changes: 10 additions & 0 deletions drivers/gles2/shader_gles2.h
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,16 @@ class ShaderGLES2 {
custom_defines.push_back(p_define.utf8());
}

void get_custom_defines(Vector<String> *p_defines) {
for (int i = 0; i < custom_defines.size(); i++) {
p_defines->push_back(custom_defines[i].get_data());
}
}

void clear_custom_defines() {
custom_defines.clear();
}

virtual ~ShaderGLES2();
};

Expand Down
Loading