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 external textures on Android #89840

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
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
8 changes: 8 additions & 0 deletions drivers/gles3/shader_gles3.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,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 (Android only)
#ifdef ANDROID_ENABLED
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");
#endif

// 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");
Expand Down
4 changes: 4 additions & 0 deletions drivers/gles3/storage/material_storage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -679,6 +679,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
};

Expand Down Expand Up @@ -949,6 +950,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:
Expand Down
33 changes: 33 additions & 0 deletions drivers/gles3/storage/texture_storage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,9 @@ TextureStorage::TextureStorage() {
}
default_gl_textures[DEFAULT_GL_TEXTURE_CUBEMAP_BLACK] = texture_allocate();
texture_2d_layered_initialize(default_gl_textures[DEFAULT_GL_TEXTURE_CUBEMAP_BLACK], images, RS::TEXTURE_LAYERED_CUBEMAP);

default_gl_textures[DEFAULT_GL_TEXTURE_EXT] = texture_allocate();
texture_external_initialize(default_gl_textures[DEFAULT_GL_TEXTURE_EXT], image);
}

{
Expand All @@ -134,6 +137,15 @@ TextureStorage::TextureStorage() {
texture_2d_initialize(default_gl_textures[DEFAULT_GL_TEXTURE_TRANSPARENT], image);
}

{ // red
Ref<Image> image = Image::create_empty(4, 4, true, Image::FORMAT_RGBA8);
image->fill(Color(1, 0, 0, 1));
image->generate_mipmaps();

default_gl_textures[DEFAULT_GL_TEXTURE_EXT] = texture_allocate();
texture_external_initialize(default_gl_textures[DEFAULT_GL_TEXTURE_EXT], image);
}

{
Ref<Image> image = Image::create_empty(4, 4, true, Image::FORMAT_RGBA8);
image->fill(Color(0.5, 0.5, 1, 1));
Expand Down Expand Up @@ -769,6 +781,27 @@ 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, const Ref<Image> &p_image) {
ERR_FAIL_COND(p_image.is_null());

Texture texture;
texture.width = p_image->get_width();
texture.height = p_image->get_height();
texture.alloc_width = texture.width;
texture.alloc_height = texture.height;
texture.mipmaps = p_image->get_mipmap_count() + 1;
texture.format = p_image->get_format();
texture.type = Texture::TYPE_2D;
texture.target = _GL_TEXTURE_EXTERNAL_OES;
_get_gl_image_and_format(Ref<Image>(), texture.format, texture.real_format, texture.gl_format_cache, texture.gl_internal_format_cache, texture.gl_type_cache, texture.compressed, false);
texture.total_data_size = p_image->get_image_data_size(texture.width, texture.height, texture.format, texture.mipmaps);
texture.active = true;
glGenTextures(1, &texture.tex_id);
GLES3::Utilities::get_singleton()->texture_allocated_data(texture.tex_id, texture.total_data_size, "Texture EXT");
texture_owner.initialize_rid(p_texture, texture);
texture_set_data(p_texture, p_image);
}

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());

Expand Down
2 changes: 2 additions & 0 deletions drivers/gles3/storage/texture_storage.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
};

Expand Down Expand Up @@ -512,6 +513,7 @@ class TextureStorage : public RendererTextureStorage {
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, const Ref<Image> &p_image) 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);
Expand Down
2 changes: 2 additions & 0 deletions scene/register_scene_types.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,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"
Expand Down Expand Up @@ -913,6 +914,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);
Expand Down
91 changes: 91 additions & 0 deletions scene/resources/external_texture.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
/**************************************************************************/
/* camera_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 "servers/rendering/rendering_server_globals.h"
#include "drivers/gles3/storage/texture_storage.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);

ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "size"), "set_size", "get_size");
}

uint32_t ExternalTexture::get_external_texture_id() {
return ((GLES3::TextureStorage*) RSG::texture_storage)->texture_get_texid(_texture);
}

void ExternalTexture::set_size(const Size2 &p_size) {
if (p_size.width > 0 && p_size.height > 0) {
_size = p_size;
RenderingServer::get_singleton()->texture_set_size_override(_texture, _size.width, _size.height);
notify_property_list_changed();
}
}

Size2 ExternalTexture::get_size() const {
return _size;
}

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;
}

Ref<Image> ExternalTexture::get_image() const {
// not (yet) supported
return Ref<Image>();
}

ExternalTexture::ExternalTexture() {
_size = Size2(1.0, 1.0);
Ref<Image> image = Image::create_empty(_size.width, _size.height, true, Image::FORMAT_RGBA8);
_texture = RenderingServer::get_singleton()->texture_external_create(image);
notify_property_list_changed();
}

ExternalTexture::~ExternalTexture() {
if (_texture.is_valid()) {
ERR_FAIL_NULL(RenderingServer::get_singleton());
RenderingServer::get_singleton()->free(_texture);
}
}
61 changes: 61 additions & 0 deletions scene/resources/external_texture.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/**************************************************************************/
/* camera_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"

class ExternalTexture : public Texture2D {
GDCLASS(ExternalTexture, Texture2D);

private:
mutable RID _texture;
Size2 _size;

protected:
static void _bind_methods();

public:
uint32_t get_external_texture_id();
virtual Size2 get_size() const;
void set_size(const Size2 &p_size);

virtual int get_width() const override;
virtual int get_height() const override;
virtual RID get_rid() const override;
virtual bool has_alpha() const override;
virtual Ref<Image> get_image() const override;

ExternalTexture();
~ExternalTexture();
};

#endif // EXTERNAL_TEXTURE_H
1 change: 1 addition & 0 deletions servers/rendering/dummy/storage/texture_storage.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ class TextureStorage : public RendererTextureStorage {
};
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, const Ref<Image> &p_image) override {};
virtual void texture_proxy_initialize(RID p_texture, RID p_base) override{}; //all slices, then all the mipmaps, must be coherent

virtual void texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer = 0) override{};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -490,6 +490,7 @@ class TextureStorage : public RendererTextureStorage {
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, const Ref<Image> &p_image) override {};
virtual void texture_proxy_initialize(RID p_texture, RID p_base) override; //all slices, then all the mipmaps, must be coherent

virtual void texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer = 0) override;
Expand Down
1 change: 1 addition & 0 deletions servers/rendering/rendering_server_default.h
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,7 @@ class RenderingServerDefault : public RenderingServer {

//these go pass-through, as they can be called from any thread
FUNCRIDTEX1(texture_2d, const Ref<Image> &)
FUNCRIDTEX1(texture_external, 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>> &)
FUNCRIDTEX1(texture_proxy, RID)
Expand Down
2 changes: 2 additions & 0 deletions servers/rendering/shader_compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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: {
Expand Down
18 changes: 15 additions & 3 deletions servers/rendering/shader_language.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,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

Expand Down Expand Up @@ -968,7 +969,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) {
Expand Down Expand Up @@ -1103,6 +1105,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:
Expand Down Expand Up @@ -2731,6 +2735,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

Expand Down Expand Up @@ -4051,7 +4057,8 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::C
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;
}
Expand Down Expand Up @@ -4231,7 +4238,8 @@ PropertyInfo ShaderLanguage::uniform_to_property_info(const ShaderNode::Uniform
case ShaderLanguage::TYPE_ISAMPLER2DARRAY:
case ShaderLanguage::TYPE_USAMPLER2DARRAY:
case ShaderLanguage::TYPE_SAMPLERCUBE:
case ShaderLanguage::TYPE_SAMPLERCUBEARRAY: {
case ShaderLanguage::TYPE_SAMPLERCUBEARRAY:
case ShaderLanguage::TYPE_SAMPLEREXT: {
if (p_uniform.array_size > 0) {
pi.type = Variant::ARRAY;
pi.hint = PROPERTY_HINT_ARRAY_TYPE;
Expand Down Expand Up @@ -4328,6 +4336,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: {
Expand Down Expand Up @@ -4423,6 +4433,7 @@ ShaderLanguage::DataType ShaderLanguage::get_scalar_type(DataType p_type) {
TYPE_UINT,
TYPE_FLOAT,
TYPE_FLOAT,
TYPE_FLOAT,
TYPE_VOID,
};

Expand Down Expand Up @@ -4465,6 +4476,7 @@ int ShaderLanguage::get_cardinality(DataType p_type) {
1,
1,
1,
1,
};

static_assert(sizeof(cardinality_table) / sizeof(*cardinality_table) == TYPE_MAX);
Expand Down
Loading
Loading