summaryrefslogtreecommitdiff
path: root/drivers/gles3/storage
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gles3/storage')
-rw-r--r--drivers/gles3/storage/config.cpp31
-rw-r--r--drivers/gles3/storage/config.h6
-rw-r--r--drivers/gles3/storage/material_storage.cpp53
-rw-r--r--drivers/gles3/storage/material_storage.h20
-rw-r--r--drivers/gles3/storage/mesh_storage.cpp104
-rw-r--r--drivers/gles3/storage/mesh_storage.h10
-rw-r--r--drivers/gles3/storage/texture_storage.cpp109
-rw-r--r--drivers/gles3/storage/texture_storage.h6
8 files changed, 240 insertions, 99 deletions
diff --git a/drivers/gles3/storage/config.cpp b/drivers/gles3/storage/config.cpp
index 369e523cc4..7280868564 100644
--- a/drivers/gles3/storage/config.cpp
+++ b/drivers/gles3/storage/config.cpp
@@ -120,16 +120,6 @@ Config::Config() {
support_write_depth = extensions.has("GL_EXT_frag_depth");
#endif
- support_half_float_vertices = true;
-//every platform should support this except web, iOS has issues with their support, so add option to disable
-#ifdef JAVASCRIPT_ENABLED
- support_half_float_vertices = false;
-#endif
- bool disable_half_float = false; //GLOBAL_GET("rendering/opengl/compatibility/disable_half_float");
- if (disable_half_float) {
- support_half_float_vertices = false;
- }
-
//picky requirements for these
support_shadow_cubemaps = support_write_depth && support_depth_cubemaps;
// the use skeleton software path should be used if either float texture is not supported,
@@ -149,6 +139,27 @@ Config::Config() {
force_vertex_shading = false; //GLOBAL_GET("rendering/quality/shading/force_vertex_shading");
use_nearest_mip_filter = GLOBAL_GET("rendering/textures/default_filters/use_nearest_mipmap_filter");
+
+ use_depth_prepass = bool(GLOBAL_GET("rendering/driver/depth_prepass/enable"));
+ if (use_depth_prepass) {
+ String vendors = GLOBAL_GET("rendering/driver/depth_prepass/disable_for_vendors");
+ Vector<String> vendor_match = vendors.split(",");
+ String renderer = (const char *)glGetString(GL_RENDERER);
+ for (int i = 0; i < vendor_match.size(); i++) {
+ String v = vendor_match[i].strip_edges();
+ if (v == String()) {
+ continue;
+ }
+
+ if (renderer.findn(v) != -1) {
+ use_depth_prepass = false;
+ }
+ }
+ }
+
+ max_renderable_elements = GLOBAL_GET("rendering/limits/opengl/max_renderable_elements");
+ max_renderable_lights = GLOBAL_GET("rendering/limits/opengl/max_renderable_lights");
+ max_lights_per_object = GLOBAL_GET("rendering/limits/opengl/max_lights_per_object");
}
Config::~Config() {
diff --git a/drivers/gles3/storage/config.h b/drivers/gles3/storage/config.h
index 0646881b72..7e143c1c1e 100644
--- a/drivers/gles3/storage/config.h
+++ b/drivers/gles3/storage/config.h
@@ -58,6 +58,9 @@ public:
int max_texture_image_units = 0;
int max_texture_size = 0;
int max_uniform_buffer_size = 0;
+ int max_renderable_elements = 0;
+ int max_renderable_lights = 0;
+ int max_lights_per_object = 0;
// TODO implement wireframe in OpenGL
// bool generate_wireframes;
@@ -82,7 +85,6 @@ public:
bool support_32_bits_indices = false;
bool support_write_depth = false;
- bool support_half_float_vertices = false;
bool support_npot_repeat_mipmap = false;
bool support_depth_cubemaps = false;
bool support_shadow_cubemaps = false;
@@ -97,6 +99,8 @@ public:
// so the user can switch orphaning off for them.
bool should_orphan = true;
+ bool use_depth_prepass = true;
+
static Config *get_singleton() { return singleton; };
Config();
diff --git a/drivers/gles3/storage/material_storage.cpp b/drivers/gles3/storage/material_storage.cpp
index a3111da28a..6dff8a2a51 100644
--- a/drivers/gles3/storage/material_storage.cpp
+++ b/drivers/gles3/storage/material_storage.cpp
@@ -43,7 +43,7 @@ using namespace GLES3;
///////////////////////////////////////////////////////////////////////////
// UBI helper functions
-_FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataType type, int p_array_size, const Variant &value, uint8_t *data, bool p_linear_color) {
+_FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataType type, int p_array_size, const Variant &value, uint8_t *data) {
switch (type) {
case ShaderLanguage::TYPE_BOOL: {
uint32_t *gui = (uint32_t *)data;
@@ -399,9 +399,6 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy
for (int i = 0, j = 0; i < p_array_size; i++, j += 4) {
if (i < s) {
Color color = a[i];
- if (p_linear_color) {
- color = color.srgb_to_linear();
- }
gui[j] = color.r;
gui[j + 1] = color.g;
gui[j + 2] = color.b;
@@ -433,10 +430,6 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy
if (value.get_type() == Variant::COLOR) {
Color v = value;
- if (p_linear_color) {
- v = v.srgb_to_linear();
- }
-
gui[0] = v.r;
gui[1] = v.g;
gui[2] = v.b;
@@ -459,9 +452,6 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy
for (int i = 0, j = 0; i < p_array_size; i++, j += 4) {
if (i < s) {
Color color = a[i];
- if (p_linear_color) {
- color = color.srgb_to_linear();
- }
gui[j] = color.r;
gui[j + 1] = color.g;
gui[j + 2] = color.b;
@@ -496,10 +486,6 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy
if (value.get_type() == Variant::COLOR) {
Color v = value;
- if (p_linear_color) {
- v = v.srgb_to_linear();
- }
-
gui[0] = v.r;
gui[1] = v.g;
gui[2] = v.b;
@@ -987,7 +973,7 @@ void MaterialData::update_uniform_buffer(const Map<StringName, ShaderLanguage::S
if (V) {
//user provided
- _fill_std140_variant_ubo_value(E.value.type, E.value.array_size, V->get(), data, p_use_linear_color);
+ _fill_std140_variant_ubo_value(E.value.type, E.value.array_size, V->get(), data);
} else if (E.value.default_value.size()) {
//default value
@@ -997,7 +983,7 @@ void MaterialData::update_uniform_buffer(const Map<StringName, ShaderLanguage::S
//zero because it was not provided
if ((E.value.type == ShaderLanguage::TYPE_VEC3 || E.value.type == ShaderLanguage::TYPE_VEC4) && E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_COLOR) {
//colors must be set as black, with alpha as 1.0
- _fill_std140_variant_ubo_value(E.value.type, E.value.array_size, Color(0, 0, 0, 1), data, p_use_linear_color);
+ _fill_std140_variant_ubo_value(E.value.type, E.value.array_size, Color(0, 0, 0, 1), data);
} else {
//else just zero it out
_fill_std140_ubo_empty(E.value.type, E.value.array_size, data);
@@ -1883,7 +1869,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
bv.w = v.a;
GlobalVariables::Value &bv_linear = global_variables.buffer_values[p_index + 1];
- v = v.srgb_to_linear();
+ //v = v.srgb_to_linear();
bv_linear.x = v.r;
bv_linear.y = v.g;
bv_linear.z = v.b;
@@ -2322,7 +2308,7 @@ void MaterialStorage::global_variables_instance_update(RID p_instance, int p_ind
pos += p_index;
- _fill_std140_variant_ubo_value(datatype, 0, p_value, (uint8_t *)&global_variables.buffer_values[pos], true); //instances always use linear color in this renderer
+ _fill_std140_variant_ubo_value(datatype, 0, p_value, (uint8_t *)&global_variables.buffer_values[pos]);
_global_variable_mark_buffer_dirty(pos, 1);
}
@@ -2929,7 +2915,7 @@ void CanvasMaterialData::update_parameters(const Map<StringName, Variant> &p_par
void CanvasMaterialData::bind_uniforms() {
// Bind Material Uniforms
- glBindBufferBase(GL_UNIFORM_BUFFER, RasterizerCanvasGLES3::MATERIAL_UNIFORM_BUFFER_OBJECT, uniform_buffer);
+ glBindBufferBase(GL_UNIFORM_BUFFER, RasterizerCanvasGLES3::MATERIAL_UNIFORM_LOCATION, uniform_buffer);
RID *textures = texture_cache.ptrw();
ShaderCompiler::GeneratedCode::Texture *texture_uniforms = shader_data->texture_uniforms.ptrw();
@@ -3162,7 +3148,7 @@ GLES3::MaterialData *GLES3::_create_sky_material_func(ShaderData *p_shader) {
void SkyMaterialData::bind_uniforms() {
// Bind Material Uniforms
- glBindBufferBase(GL_UNIFORM_BUFFER, 3, uniform_buffer);
+ glBindBufferBase(GL_UNIFORM_BUFFER, SKY_MATERIAL_UNIFORM_LOCATION, uniform_buffer);
RID *textures = texture_cache.ptrw();
ShaderCompiler::GeneratedCode::Texture *texture_uniforms = shader_data->texture_uniforms.ptrw();
@@ -3278,6 +3264,18 @@ void SceneShaderData::set_code(const String &p_code) {
actions.write_flag_pointers["VERTEX"] = &uses_vertex;
actions.write_flag_pointers["POSITION"] = &uses_position;
+ actions.usage_flag_pointers["TANGENT"] = &uses_tangent;
+ actions.usage_flag_pointers["BINORMAL"] = &uses_tangent;
+ actions.usage_flag_pointers["COLOR"] = &uses_color;
+ actions.usage_flag_pointers["UV"] = &uses_uv;
+ actions.usage_flag_pointers["UV2"] = &uses_uv2;
+ actions.usage_flag_pointers["CUSTOM0"] = &uses_custom0;
+ actions.usage_flag_pointers["CUSTOM1"] = &uses_custom1;
+ actions.usage_flag_pointers["CUSTOM2"] = &uses_custom2;
+ actions.usage_flag_pointers["CUSTOM3"] = &uses_custom3;
+ actions.usage_flag_pointers["BONE_INDICES"] = &uses_bones;
+ actions.usage_flag_pointers["BONE_WEIGHTS"] = &uses_weights;
+
actions.uniforms = &uniforms;
Error err = MaterialStorage::get_singleton()->shaders.compiler_scene.compile(RS::SHADER_SPATIAL, code, &actions, path, gen_code);
@@ -3292,6 +3290,17 @@ void SceneShaderData::set_code(const String &p_code) {
cull_mode = Cull(cull_modei);
blend_mode = BlendMode(blend_modei);
alpha_antialiasing_mode = AlphaAntiAliasing(alpha_antialiasing_modei);
+ vertex_input_mask = uint32_t(uses_normal);
+ vertex_input_mask |= uses_tangent << 1;
+ vertex_input_mask |= uses_color << 2;
+ vertex_input_mask |= uses_uv << 3;
+ vertex_input_mask |= uses_uv2 << 4;
+ vertex_input_mask |= uses_custom0 << 5;
+ vertex_input_mask |= uses_custom1 << 6;
+ vertex_input_mask |= uses_custom2 << 7;
+ vertex_input_mask |= uses_custom3 << 8;
+ vertex_input_mask |= uses_bones << 9;
+ vertex_input_mask |= uses_weights << 10;
#if 0
print_line("**compiling shader:");
@@ -3455,7 +3464,7 @@ GLES3::MaterialData *GLES3::_create_scene_material_func(ShaderData *p_shader) {
void SceneMaterialData::bind_uniforms() {
// Bind Material Uniforms
- glBindBufferBase(GL_UNIFORM_BUFFER, 3, uniform_buffer);
+ glBindBufferBase(GL_UNIFORM_BUFFER, SCENE_MATERIAL_UNIFORM_LOCATION, uniform_buffer);
RID *textures = texture_cache.ptrw();
ShaderCompiler::GeneratedCode::Texture *texture_uniforms = shader_data->texture_uniforms.ptrw();
diff --git a/drivers/gles3/storage/material_storage.h b/drivers/gles3/storage/material_storage.h
index f9901f0085..aa36dda4e6 100644
--- a/drivers/gles3/storage/material_storage.h
+++ b/drivers/gles3/storage/material_storage.h
@@ -279,14 +279,6 @@ struct SceneShaderData : public ShaderData {
CULL_BACK
};
- enum CullVariant {
- CULL_VARIANT_NORMAL,
- CULL_VARIANT_REVERSED,
- CULL_VARIANT_DOUBLE_SIDED,
- CULL_VARIANT_MAX
-
- };
-
enum AlphaAntiAliasing {
ALPHA_ANTIALIASING_OFF,
ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE,
@@ -335,6 +327,18 @@ struct SceneShaderData : public ShaderData {
bool uses_time;
bool writes_modelview_or_projection;
bool uses_world_coordinates;
+ bool uses_tangent;
+ bool uses_color;
+ bool uses_uv;
+ bool uses_uv2;
+ bool uses_custom0;
+ bool uses_custom1;
+ bool uses_custom2;
+ bool uses_custom3;
+ bool uses_bones;
+ bool uses_weights;
+
+ uint32_t vertex_input_mask = 0;
uint64_t last_pass = 0;
uint32_t index = 0;
diff --git a/drivers/gles3/storage/mesh_storage.cpp b/drivers/gles3/storage/mesh_storage.cpp
index 41b5107b6c..a2b9cb6a62 100644
--- a/drivers/gles3/storage/mesh_storage.cpp
+++ b/drivers/gles3/storage/mesh_storage.cpp
@@ -194,6 +194,7 @@ void MeshStorage::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface)
glBindBuffer(GL_ARRAY_BUFFER, s->attribute_buffer);
glBufferData(GL_ARRAY_BUFFER, p_surface.attribute_data.size(), p_surface.attribute_data.ptr(), (s->format & RS::ARRAY_FLAG_USE_DYNAMIC_UPDATE) ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind
+ s->attribute_buffer_size = p_surface.attribute_data.size();
}
if (p_surface.skin_data.size()) {
glGenBuffers(1, &s->skin_buffer);
@@ -216,6 +217,7 @@ void MeshStorage::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface)
glBufferData(GL_ELEMENT_ARRAY_BUFFER, p_surface.index_data.size(), p_surface.index_data.ptr(), GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); //unbind
s->index_count = p_surface.index_count;
+ s->index_buffer_size = p_surface.index_data.size();
if (p_surface.lods.size()) {
s->lods = memnew_arr(Mesh::Surface::LOD, p_surface.lods.size());
@@ -323,7 +325,97 @@ RID MeshStorage::mesh_surface_get_material(RID p_mesh, int p_surface) const {
}
RS::SurfaceData MeshStorage::mesh_get_surface(RID p_mesh, int p_surface) const {
- return RS::SurfaceData();
+ Mesh *mesh = mesh_owner.get_or_null(p_mesh);
+ ERR_FAIL_COND_V(!mesh, RS::SurfaceData());
+ ERR_FAIL_UNSIGNED_INDEX_V((uint32_t)p_surface, mesh->surface_count, RS::SurfaceData());
+
+ Mesh::Surface &s = *mesh->surfaces[p_surface];
+
+ RS::SurfaceData sd;
+ sd.format = s.format;
+ {
+ Vector<uint8_t> ret;
+ ret.resize(s.vertex_buffer_size);
+ glBindBuffer(GL_ARRAY_BUFFER, s.vertex_buffer);
+
+#if defined(__EMSCRIPTEN__)
+ {
+ uint8_t *w = ret.ptrw();
+ glGetBufferSubData(GL_ARRAY_BUFFER, 0, s.vertex_buffer_size, w);
+ }
+#else
+ void *data = glMapBufferRange(GL_ARRAY_BUFFER, 0, s.vertex_buffer_size, GL_MAP_READ_BIT);
+ ERR_FAIL_NULL_V(data, RS::SurfaceData());
+ {
+ uint8_t *w = ret.ptrw();
+ memcpy(w, data, s.vertex_buffer_size);
+ }
+ glUnmapBuffer(GL_ARRAY_BUFFER);
+#endif
+ sd.vertex_data = ret;
+ }
+
+ if (s.attribute_buffer != 0) {
+ Vector<uint8_t> ret;
+ ret.resize(s.attribute_buffer_size);
+ glBindBuffer(GL_ARRAY_BUFFER, s.attribute_buffer);
+
+#if defined(__EMSCRIPTEN__)
+ {
+ uint8_t *w = ret.ptrw();
+ glGetBufferSubData(GL_ARRAY_BUFFER, 0, s.attribute_buffer_size, w);
+ }
+#else
+ void *data = glMapBufferRange(GL_ARRAY_BUFFER, 0, s.attribute_buffer_size, GL_MAP_READ_BIT);
+ ERR_FAIL_NULL_V(data, RS::SurfaceData());
+ {
+ uint8_t *w = ret.ptrw();
+ memcpy(w, data, s.attribute_buffer_size);
+ }
+ glUnmapBuffer(GL_ARRAY_BUFFER);
+#endif
+ sd.attribute_data = ret;
+ }
+
+ sd.vertex_count = s.vertex_count;
+ sd.index_count = s.index_count;
+ sd.primitive = s.primitive;
+
+ if (sd.index_count) {
+ Vector<uint8_t> ret;
+ ret.resize(s.index_buffer_size);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, s.index_buffer);
+
+#if defined(__EMSCRIPTEN__)
+ {
+ uint8_t *w = ret.ptrw();
+ glGetBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, s.index_buffer_size, w);
+ }
+#else
+ void *data = glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER, 0, s.index_buffer_size, GL_MAP_READ_BIT);
+ ERR_FAIL_NULL_V(data, RS::SurfaceData());
+ {
+ uint8_t *w = ret.ptrw();
+ memcpy(w, data, s.index_buffer_size);
+ }
+ glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER);
+#endif
+ sd.index_data = ret;
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+ }
+
+ sd.aabb = s.aabb;
+ for (uint32_t i = 0; i < s.lod_count; i++) {
+ RS::SurfaceData::LOD lod;
+ lod.edge_length = s.lods[i].edge_length;
+ //lod.index_data = RD::get_singleton()->buffer_get_data(s.lods[i].index_buffer);
+ sd.lods.push_back(lod);
+ }
+
+ sd.bone_aabbs = s.bone_aabbs;
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+
+ return sd;
}
int MeshStorage::mesh_get_surface_count(RID p_mesh) const {
@@ -496,7 +588,6 @@ void MeshStorage::mesh_clear(RID p_mesh) {
if (s.index_buffer != 0) {
glDeleteBuffers(1, &s.index_buffer);
- glDeleteVertexArrays(1, &s.index_array);
}
memdelete(mesh->surfaces[i]);
}
@@ -553,14 +644,14 @@ void MeshStorage::_mesh_surface_generate_version_for_input_mask(Mesh::Surface::V
case RS::ARRAY_NORMAL: {
attribs[i].offset = vertex_stride;
// Will need to change to accommodate octahedral compression
- attribs[i].size = 1;
+ attribs[i].size = 4;
attribs[i].type = GL_UNSIGNED_INT_2_10_10_10_REV;
vertex_stride += sizeof(float);
attribs[i].normalized = GL_TRUE;
} break;
case RS::ARRAY_TANGENT: {
attribs[i].offset = vertex_stride;
- attribs[i].size = 1;
+ attribs[i].size = 4;
attribs[i].type = GL_UNSIGNED_INT_2_10_10_10_REV;
vertex_stride += sizeof(float);
attribs[i].normalized = GL_TRUE;
@@ -629,14 +720,17 @@ void MeshStorage::_mesh_surface_generate_version_for_input_mask(Mesh::Surface::V
continue;
}
if (i <= RS::ARRAY_TANGENT) {
+ attribs[i].stride = vertex_stride;
if (mis) {
glBindBuffer(GL_ARRAY_BUFFER, mis->vertex_buffer);
} else {
glBindBuffer(GL_ARRAY_BUFFER, s->vertex_buffer);
}
} else if (i <= RS::ARRAY_CUSTOM3) {
+ attribs[i].stride = attributes_stride;
glBindBuffer(GL_ARRAY_BUFFER, s->attribute_buffer);
} else {
+ attribs[i].stride = skin_stride;
glBindBuffer(GL_ARRAY_BUFFER, s->skin_buffer);
}
@@ -645,7 +739,7 @@ void MeshStorage::_mesh_surface_generate_version_for_input_mask(Mesh::Surface::V
} else {
glVertexAttribPointer(i, attribs[i].size, attribs[i].type, attribs[i].normalized, attribs[i].stride, CAST_INT_TO_UCHAR_PTR(attribs[i].offset));
}
- glEnableVertexAttribArray(attribs[i].index);
+ glEnableVertexAttribArray(i);
}
// Do not bind index here as we want to switch between index buffers for LOD
diff --git a/drivers/gles3/storage/mesh_storage.h b/drivers/gles3/storage/mesh_storage.h
index 6b0d0c83b2..dfb9046e7b 100644
--- a/drivers/gles3/storage/mesh_storage.h
+++ b/drivers/gles3/storage/mesh_storage.h
@@ -54,7 +54,6 @@ struct Mesh {
struct Attrib {
bool enabled;
bool integer;
- GLuint index;
GLint size;
GLenum type;
GLboolean normalized;
@@ -69,6 +68,7 @@ struct Mesh {
GLuint skin_buffer = 0;
uint32_t vertex_count = 0;
uint32_t vertex_buffer_size = 0;
+ uint32_t attribute_buffer_size = 0;
uint32_t skin_buffer_size = 0;
// Cache vertex arrays so they can be created
@@ -84,8 +84,8 @@ struct Mesh {
uint32_t version_count = 0;
GLuint index_buffer = 0;
- GLuint index_array = 0;
uint32_t index_count = 0;
+ uint32_t index_buffer_size = 0;
struct LOD {
float edge_length = 0.0;
@@ -357,6 +357,12 @@ public:
}
}
+ _FORCE_INLINE_ GLenum mesh_surface_get_index_type(void *p_surface) const {
+ Mesh::Surface *s = reinterpret_cast<Mesh::Surface *>(p_surface);
+
+ return s->vertex_count <= 65536 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT;
+ }
+
// Use this to cache Vertex Array Objects so they are only generated once
_FORCE_INLINE_ void mesh_surface_get_vertex_arrays_and_format(void *p_surface, uint32_t p_input_mask, GLuint &r_vertex_array_gl) {
Mesh::Surface *s = reinterpret_cast<Mesh::Surface *>(p_surface);
diff --git a/drivers/gles3/storage/texture_storage.cpp b/drivers/gles3/storage/texture_storage.cpp
index 6f2dc391d8..4396ca4f93 100644
--- a/drivers/gles3/storage/texture_storage.cpp
+++ b/drivers/gles3/storage/texture_storage.cpp
@@ -62,8 +62,9 @@ TextureStorage::TextureStorage() {
Ref<Image> image;
image.instantiate();
- image->create(4, 4, false, Image::FORMAT_RGBA8);
+ image->create(4, 4, true, Image::FORMAT_RGBA8);
image->fill(Color(1, 1, 1, 1));
+ image->generate_mipmaps();
default_gl_textures[DEFAULT_GL_TEXTURE_WHITE] = texture_allocate();
texture_2d_initialize(default_gl_textures[DEFAULT_GL_TEXTURE_WHITE], image);
@@ -92,8 +93,9 @@ TextureStorage::TextureStorage() {
{ // black
Ref<Image> image;
image.instantiate();
- image->create(4, 4, false, Image::FORMAT_RGBA8);
+ image->create(4, 4, true, Image::FORMAT_RGBA8);
image->fill(Color(0, 0, 0, 1));
+ image->generate_mipmaps();
default_gl_textures[DEFAULT_GL_TEXTURE_BLACK] = texture_allocate();
texture_2d_initialize(default_gl_textures[DEFAULT_GL_TEXTURE_BLACK], image);
@@ -117,8 +119,9 @@ TextureStorage::TextureStorage() {
{
Ref<Image> image;
image.instantiate();
- image->create(4, 4, false, Image::FORMAT_RGBA8);
+ image->create(4, 4, true, Image::FORMAT_RGBA8);
image->fill(Color(0.5, 0.5, 1, 1));
+ image->generate_mipmaps();
default_gl_textures[DEFAULT_GL_TEXTURE_NORMAL] = texture_allocate();
texture_2d_initialize(default_gl_textures[DEFAULT_GL_TEXTURE_NORMAL], image);
@@ -127,8 +130,9 @@ TextureStorage::TextureStorage() {
{
Ref<Image> image;
image.instantiate();
- image->create(4, 4, false, Image::FORMAT_RGBA8);
+ image->create(4, 4, true, Image::FORMAT_RGBA8);
image->fill(Color(1.0, 0.5, 1, 1));
+ image->generate_mipmaps();
default_gl_textures[DEFAULT_GL_TEXTURE_ANISO] = texture_allocate();
texture_2d_initialize(default_gl_textures[DEFAULT_GL_TEXTURE_ANISO], image);
@@ -189,18 +193,7 @@ TextureStorage::~TextureStorage() {
}
}
-void TextureStorage::set_main_thread_id(Thread::ID p_id) {
- _main_thread_id = p_id;
-}
-
-bool TextureStorage::_is_main_thread() {
- //#if defined DEBUG_ENABLED && defined TOOLS_ENABLED
- // must be called from main thread in OpenGL
- bool is_main_thread = _main_thread_id == Thread::get_caller_id();
- //#endif
- return is_main_thread;
-}
-
+//TODO, move back to storage
bool TextureStorage::can_create_resources_async() const {
return false;
}
@@ -644,10 +637,14 @@ void TextureStorage::texture_2d_initialize(RID p_texture, const Ref<Image> &p_im
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();
texture.format = p_image->get_format();
texture.type = Texture::TYPE_2D;
texture.target = GL_TEXTURE_2D;
- texture.image_cache_2d = p_image; //TODO, remove this once texture_2d_get is implemented
+ _get_gl_image_and_format(Ref<Image>(), texture.format, 0, 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(); // verify that this returns size in bytes
texture.active = true;
glGenTextures(1, &texture.tex_id);
texture_owner.initialize_rid(p_texture, texture);
@@ -740,49 +737,66 @@ void TextureStorage::texture_3d_placeholder_initialize(RID p_texture) {
}
Ref<Image> TextureStorage::texture_2d_get(RID p_texture) const {
- Texture *tex = texture_owner.get_or_null(p_texture);
- ERR_FAIL_COND_V(!tex, Ref<Image>());
+ Texture *texture = texture_owner.get_or_null(p_texture);
+ ERR_FAIL_COND_V(!texture, Ref<Image>());
#ifdef TOOLS_ENABLED
- if (tex->image_cache_2d.is_valid() && !tex->is_render_target) {
- return tex->image_cache_2d;
+ if (texture->image_cache_2d.is_valid() && !texture->is_render_target) {
+ return texture->image_cache_2d;
}
#endif
- /*
-#ifdef TOOLS_ENABLED
- if (tex->image_cache_2d.is_valid()) {
- return tex->image_cache_2d;
+#ifdef GLES_OVER_GL
+ // OpenGL 3.3 supports glGetTexImage which is faster and simpler than glReadPixels.
+ Vector<uint8_t> data;
+
+ int data_size = Image::get_image_data_size(texture->alloc_width, texture->alloc_height, texture->real_format, texture->mipmaps > 1);
+
+ data.resize(data_size * 2); //add some memory at the end, just in case for buggy drivers
+ uint8_t *w = data.ptrw();
+
+ glActiveTexture(GL_TEXTURE0);
+
+ glBindTexture(texture->target, texture->tex_id);
+
+ glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
+
+ for (int i = 0; i < texture->mipmaps; i++) {
+ int ofs = Image::get_image_mipmap_offset(texture->alloc_width, texture->alloc_height, texture->real_format, i);
+
+ if (texture->compressed) {
+ glPixelStorei(GL_PACK_ALIGNMENT, 4);
+ glGetCompressedTexImage(texture->target, i, &w[ofs]);
+
+ } else {
+ glPixelStorei(GL_PACK_ALIGNMENT, 1);
+
+ glGetTexImage(texture->target, i, texture->gl_format_cache, texture->gl_type_cache, &w[ofs]);
+ }
}
-#endif
- Vector<uint8_t> data = RD::get_singleton()->texture_get_data(tex->rd_texture, 0);
+
+ data.resize(data_size);
+
ERR_FAIL_COND_V(data.size() == 0, Ref<Image>());
Ref<Image> image;
- image.instance();
- image->create(tex->width, tex->height, tex->mipmaps > 1, tex->validated_format, data);
- ERR_FAIL_COND_V(image->empty(), Ref<Image>());
- if (tex->format != tex->validated_format) {
- image->convert(tex->format);
+ image.instantiate();
+ image->create(texture->width, texture->height, texture->mipmaps > 1, texture->real_format, data);
+ ERR_FAIL_COND_V(image->is_empty(), Ref<Image>());
+ if (texture->format != texture->real_format) {
+ image->convert(texture->format);
}
+#else
+ // Support for Web and Mobile will come later.
+ Ref<Image> image;
+#endif
#ifdef TOOLS_ENABLED
- if (Engine::get_singleton()->is_editor_hint()) {
- tex->image_cache_2d = image;
+ if (Engine::get_singleton()->is_editor_hint() && !texture->is_render_target) {
+ texture->image_cache_2d = image;
}
#endif
-*/
-
- /*
- #ifdef TOOLS_ENABLED
- if (Engine::get_singleton()->is_editor_hint() && !tex->is_render_target) {
- tex->image_cache_2d = image;
- }
- #endif
- */
-
- // return image;
- return Ref<Image>();
+ return image;
}
void TextureStorage::texture_replace(RID p_texture, RID p_by_texture) {
@@ -1357,6 +1371,9 @@ void TextureStorage::_update_render_target(RenderTarget *rt) {
}
texture->format = rt->image_format;
+ texture->real_format = rt->image_format;
+ texture->type = Texture::TYPE_2D;
+ texture->target = GL_TEXTURE_2D;
texture->gl_format_cache = rt->color_format;
texture->gl_type_cache = GL_UNSIGNED_BYTE;
texture->gl_internal_format_cache = rt->color_internal_format;
diff --git a/drivers/gles3/storage/texture_storage.h b/drivers/gles3/storage/texture_storage.h
index a841ff8f46..8281b8c596 100644
--- a/drivers/gles3/storage/texture_storage.h
+++ b/drivers/gles3/storage/texture_storage.h
@@ -141,6 +141,7 @@ struct Texture {
int alloc_width = 0;
int alloc_height = 0;
Image::Format format = Image::FORMAT_R8;
+ Image::Format real_format = Image::FORMAT_R8;
enum Type {
TYPE_2D,
@@ -370,9 +371,6 @@ private:
RID default_gl_textures[DEFAULT_GL_TEXTURE_MAX];
- Thread::ID _main_thread_id = 0;
- bool _is_main_thread();
-
/* Canvas Texture API */
RID_Owner<CanvasTexture, true> canvas_texture_owner;
@@ -440,8 +438,6 @@ public:
};
bool owns_texture(RID p_rid) { return texture_owner.owns(p_rid); };
- void set_main_thread_id(Thread::ID p_id);
-
virtual bool can_create_resources_async() const override;
RID texture_create();