summaryrefslogtreecommitdiff
path: root/drivers/gles2/rasterizer_storage_gles2.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gles2/rasterizer_storage_gles2.cpp')
-rw-r--r--drivers/gles2/rasterizer_storage_gles2.cpp182
1 files changed, 167 insertions, 15 deletions
diff --git a/drivers/gles2/rasterizer_storage_gles2.cpp b/drivers/gles2/rasterizer_storage_gles2.cpp
index 9f511cd787..0f51d07b6e 100644
--- a/drivers/gles2/rasterizer_storage_gles2.cpp
+++ b/drivers/gles2/rasterizer_storage_gles2.cpp
@@ -82,6 +82,8 @@ GLuint RasterizerStorageGLES2::system_fbo = 0;
#define _DEPTH_COMPONENT24_OES 0x81A6
#ifndef GLES_OVER_GL
+#define glClearDepth glClearDepthf
+
// enable extensions manually for android and ios
#include <dlfcn.h> // needed to load extensions
@@ -112,7 +114,7 @@ void RasterizerStorageGLES2::bind_quad_array() const {
glEnableVertexAttribArray(VS::ARRAY_TEX_UV);
}
-Ref<Image> RasterizerStorageGLES2::_get_gl_image_and_format(const Ref<Image> &p_image, Image::Format p_format, uint32_t p_flags, Image::Format &r_real_format, GLenum &r_gl_format, GLenum &r_gl_internal_format, GLenum &r_gl_type, bool &r_compressed, bool p_will_need_resize) const {
+Ref<Image> RasterizerStorageGLES2::_get_gl_image_and_format(const Ref<Image> &p_image, Image::Format p_format, uint32_t p_flags, Image::Format &r_real_format, GLenum &r_gl_format, GLenum &r_gl_internal_format, GLenum &r_gl_type, bool &r_compressed, bool p_force_decompress) const {
r_gl_format = 0;
Ref<Image> image = p_image;
@@ -259,7 +261,7 @@ Ref<Image> RasterizerStorageGLES2::_get_gl_image_and_format(const Ref<Image> &p_
} break;
case Image::FORMAT_DXT1: {
- if (config.s3tc_supported && !p_will_need_resize) {
+ if (config.s3tc_supported) {
r_gl_internal_format = _EXT_COMPRESSED_RGBA_S3TC_DXT1_EXT;
r_gl_format = GL_RGBA;
r_gl_type = GL_UNSIGNED_BYTE;
@@ -271,7 +273,7 @@ Ref<Image> RasterizerStorageGLES2::_get_gl_image_and_format(const Ref<Image> &p_
} break;
case Image::FORMAT_DXT3: {
- if (config.s3tc_supported && !p_will_need_resize) {
+ if (config.s3tc_supported) {
r_gl_internal_format = _EXT_COMPRESSED_RGBA_S3TC_DXT3_EXT;
r_gl_format = GL_RGBA;
r_gl_type = GL_UNSIGNED_BYTE;
@@ -283,7 +285,7 @@ Ref<Image> RasterizerStorageGLES2::_get_gl_image_and_format(const Ref<Image> &p_
} break;
case Image::FORMAT_DXT5: {
- if (config.s3tc_supported && !p_will_need_resize) {
+ if (config.s3tc_supported) {
r_gl_internal_format = _EXT_COMPRESSED_RGBA_S3TC_DXT5_EXT;
r_gl_format = GL_RGBA;
r_gl_type = GL_UNSIGNED_BYTE;
@@ -422,7 +424,7 @@ Ref<Image> RasterizerStorageGLES2::_get_gl_image_and_format(const Ref<Image> &p_
} break;
case Image::FORMAT_ETC: {
- if (config.etc1_supported && !p_will_need_resize) {
+ if (config.etc1_supported) {
r_gl_internal_format = _EXT_ETC1_RGB8_OES;
r_gl_format = GL_RGBA;
r_gl_type = GL_UNSIGNED_BYTE;
@@ -465,7 +467,7 @@ Ref<Image> RasterizerStorageGLES2::_get_gl_image_and_format(const Ref<Image> &p_
}
}
- if (need_decompress) {
+ if (need_decompress || p_force_decompress) {
if (!image.is_null()) {
@@ -636,7 +638,7 @@ void RasterizerStorageGLES2::texture_set_data(RID p_texture, const Ref<Image> &p
if (texture->resize_to_po2) {
if (p_image->is_compressed()) {
- ERR_PRINTS("Texture '" + texture->path + "' was required to be a power of 2 (because it uses either mipmaps or repeat), so it was decompressed. This will hurt performance and memory usage.");
+ ERR_PRINTS("Texture '" + texture->path + "' is required to be a power of 2 because it uses either mipmaps or repeat, so it was decompressed. This will hurt performance and memory usage.");
}
if (img == p_image) {
@@ -657,12 +659,13 @@ void RasterizerStorageGLES2::texture_set_data(RID p_texture, const Ref<Image> &p
img->resize(texture->alloc_width, texture->alloc_height, Image::INTERPOLATE_BILINEAR);
}
- };
+ }
GLenum blit_target = (texture->target == GL_TEXTURE_CUBE_MAP) ? _cube_side_enum[p_layer] : GL_TEXTURE_2D;
texture->data_size = img->get_data().size();
PoolVector<uint8_t>::Read read = img->get_data().read();
+ ERR_FAIL_COND(!read.ptr());
glActiveTexture(GL_TEXTURE0);
glBindTexture(texture->target, texture->tex_id);
@@ -716,7 +719,7 @@ void RasterizerStorageGLES2::texture_set_data(RID p_texture, const Ref<Image> &p
int size, ofs;
img->get_mipmap_offset_and_size(i, ofs, size);
- if (texture->compressed) {
+ if (compressed) {
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
int bw = w;
@@ -1480,8 +1483,9 @@ void RasterizerStorageGLES2::_update_shader(Shader *p_shader) const {
}
Error err = shaders.compiler.compile(p_shader->mode, p_shader->code, actions, p_shader->path, gen_code);
-
- ERR_FAIL_COND(err != OK);
+ if (err != OK) {
+ return;
+ }
p_shader->shader->set_custom_shader_code(p_shader->custom_code_id, gen_code.vertex, gen_code.vertex_global, gen_code.fragment, gen_code.light, gen_code.fragment_global, gen_code.uniforms, gen_code.texture_uniforms, gen_code.custom_defines);
@@ -3233,12 +3237,14 @@ Color RasterizerStorageGLES2::multimesh_instance_get_custom_data(RID p_multimesh
void RasterizerStorageGLES2::multimesh_set_as_bulk_array(RID p_multimesh, const PoolVector<float> &p_array) {
MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh);
ERR_FAIL_COND(!multimesh);
+ ERR_FAIL_COND(!multimesh->data.ptr());
int dsize = multimesh->data.size();
ERR_FAIL_COND(dsize != p_array.size());
PoolVector<float>::Read r = p_array.read();
+ ERR_FAIL_COND(!r.ptr());
copymem(multimesh->data.ptrw(), r.ptr(), dsize * sizeof(float));
multimesh->dirty_data = true;
@@ -4586,6 +4592,9 @@ void RasterizerStorageGLES2::_render_target_allocate(RenderTarget *rt) {
color_format = GL_RGB;
}
+ rt->used_dof_blur_near = false;
+ rt->mip_maps_allocated = false;
+
{
/* Front FBO */
@@ -4727,12 +4736,13 @@ void RasterizerStorageGLES2::_render_target_allocate(RenderTarget *rt) {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glFramebufferTexture2DMultisample(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->color, 0, msaa);
+ glFramebufferTexture2DMultisample(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->multisample_color, 0, msaa);
#endif
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if (status != GL_FRAMEBUFFER_COMPLETE) {
+ WARN_PRINT_ONCE("Cannot allocate back framebuffer for MSAA");
printf("err status: %x\n", status);
_render_target_clear(rt);
ERR_FAIL_COND(status != GL_FRAMEBUFFER_COMPLETE);
@@ -4780,6 +4790,126 @@ void RasterizerStorageGLES2::_render_target_allocate(RenderTarget *rt) {
}
}
+ // Allocate mipmap chains for post_process effects
+ if (!rt->flags[RasterizerStorage::RENDER_TARGET_NO_3D] && rt->width >= 2 && rt->height >= 2) {
+
+ for (int i = 0; i < 2; i++) {
+
+ ERR_FAIL_COND(rt->mip_maps[i].sizes.size());
+ int w = rt->width;
+ int h = rt->height;
+
+ if (i > 0) {
+ w >>= 1;
+ h >>= 1;
+ }
+
+ int level = 0;
+ int fb_w = w;
+ int fb_h = h;
+
+ while (true) {
+
+ RenderTarget::MipMaps::Size mm;
+ mm.width = w;
+ mm.height = h;
+ rt->mip_maps[i].sizes.push_back(mm);
+
+ w >>= 1;
+ h >>= 1;
+
+ if (w < 2 || h < 2)
+ break;
+
+ level++;
+ }
+
+ GLsizei width = fb_w;
+ GLsizei height = fb_h;
+
+ if (config.render_to_mipmap_supported) {
+
+ glGenTextures(1, &rt->mip_maps[i].color);
+ glBindTexture(GL_TEXTURE_2D, rt->mip_maps[i].color);
+
+ for (int l = 0; l < level + 1; l++) {
+ glTexImage2D(GL_TEXTURE_2D, l, color_internal_format, width, height, 0, color_format, color_type, NULL);
+ width = MAX(1, (width / 2));
+ height = MAX(1, (height / 2));
+ }
+#ifdef GLES_OVER_GL
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, level);
+#endif
+ } else {
+
+ // Can't render to specific levels of a mipmap in ES 2.0 or Webgl so create a texture for each level
+ for (int l = 0; l < level + 1; l++) {
+ glGenTextures(1, &rt->mip_maps[i].sizes.write[l].color);
+ glBindTexture(GL_TEXTURE_2D, rt->mip_maps[i].sizes[l].color);
+ glTexImage2D(GL_TEXTURE_2D, 0, color_internal_format, width, height, 0, color_format, color_type, NULL);
+ width = MAX(1, (width / 2));
+ height = MAX(1, (height / 2));
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ }
+ }
+
+ glDisable(GL_SCISSOR_TEST);
+ glColorMask(1, 1, 1, 1);
+ glDepthMask(GL_TRUE);
+
+ for (int j = 0; j < rt->mip_maps[i].sizes.size(); j++) {
+
+ RenderTarget::MipMaps::Size &mm = rt->mip_maps[i].sizes.write[j];
+
+ glGenFramebuffers(1, &mm.fbo);
+ glBindFramebuffer(GL_FRAMEBUFFER, mm.fbo);
+
+ if (config.render_to_mipmap_supported) {
+
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->mip_maps[i].color, j);
+ } else {
+
+ glBindTexture(GL_TEXTURE_2D, rt->mip_maps[i].sizes[j].color);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->mip_maps[i].sizes[j].color, 0);
+ }
+
+ bool used_depth = false;
+ if (j == 0 && i == 0) { //use always
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, rt->depth, 0);
+ used_depth = true;
+ }
+
+ GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+ if (status != GL_FRAMEBUFFER_COMPLETE) {
+ WARN_PRINT_ONCE("Cannot allocate mipmaps for 3D post processing effects");
+ glBindFramebuffer(GL_FRAMEBUFFER, RasterizerStorageGLES2::system_fbo);
+ return;
+ }
+
+ glClearColor(1.0, 0.0, 1.0, 0.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+ if (used_depth) {
+ glClearDepth(1.0);
+ glClear(GL_DEPTH_BUFFER_BIT);
+ }
+ }
+
+ rt->mip_maps[i].levels = level;
+
+ if (config.render_to_mipmap_supported) {
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ }
+ }
+ rt->mip_maps_allocated = true;
+ }
+
glBindFramebuffer(GL_FRAMEBUFFER, RasterizerStorageGLES2::system_fbo);
}
@@ -4837,6 +4967,20 @@ void RasterizerStorageGLES2::_render_target_clear(RenderTarget *rt) {
rt->copy_screen_effect.color = 0;
}
+ for (int i = 0; i < 2; i++) {
+ if (rt->mip_maps[i].sizes.size()) {
+ for (int j = 0; j < rt->mip_maps[i].sizes.size(); j++) {
+ glDeleteFramebuffers(1, &rt->mip_maps[i].sizes[j].fbo);
+ glDeleteTextures(1, &rt->mip_maps[i].sizes[j].color);
+ }
+
+ glDeleteTextures(1, &rt->mip_maps[i].color);
+ rt->mip_maps[i].sizes.clear();
+ rt->mip_maps[i].levels = 0;
+ rt->mip_maps[i].color = 0;
+ }
+ }
+
if (rt->multisample_active) {
glDeleteFramebuffers(1, &rt->multisample_fbo);
rt->multisample_fbo = 0;
@@ -5592,7 +5736,7 @@ void RasterizerStorageGLES2::initialize() {
config.float_texture_supported = config.extensions.has("GL_ARB_texture_float") || config.extensions.has("GL_OES_texture_float");
config.s3tc_supported = config.extensions.has("GL_EXT_texture_compression_s3tc") || config.extensions.has("WEBGL_compressed_texture_s3tc");
config.etc1_supported = config.extensions.has("GL_OES_compressed_ETC1_RGB8_texture") || config.extensions.has("WEBGL_compressed_texture_etc1");
- config.pvrtc_supported = config.extensions.has("IMG_texture_compression_pvrtc");
+ config.pvrtc_supported = config.extensions.has("IMG_texture_compression_pvrtc") || config.extensions.has("WEBGL_compressed_texture_pvrtc");
config.support_npot_repeat_mipmap = config.extensions.has("GL_OES_texture_npot");
#endif
@@ -5617,13 +5761,21 @@ void RasterizerStorageGLES2::initialize() {
config.multisample_supported = config.extensions.has("GL_EXT_framebuffer_multisample") || config.extensions.has("GL_EXT_multisampled_render_to_texture") || config.extensions.has("GL_APPLE_framebuffer_multisample");
#ifdef GLES_OVER_GL
+ //TODO: causes huge problems with desktop video drivers. Making false for now, needs to be true to render SCREEN_TEXTURE mipmaps
+ config.render_to_mipmap_supported = false;
+#else
+ //check if mipmaps can be used for SCREEN_TEXTURE and Glow on Mobile and web platforms
+ config.render_to_mipmap_supported = config.extensions.has("GL_OES_fbo_render_mipmap") && config.extensions.has("GL_EXT_texture_lod");
+#endif
+
+#ifdef GLES_OVER_GL
config.use_rgba_2d_shadows = false;
config.support_depth_texture = true;
config.use_rgba_3d_shadows = false;
config.support_depth_cubemaps = true;
#else
config.use_rgba_2d_shadows = !(config.float_texture_supported && config.extensions.has("GL_EXT_texture_rg"));
- config.support_depth_texture = config.extensions.has("GL_OES_depth_texture");
+ config.support_depth_texture = config.extensions.has("GL_OES_depth_texture") || config.extensions.has("WEBGL_depth_texture");
config.use_rgba_3d_shadows = !config.support_depth_texture;
config.support_depth_cubemaps = config.extensions.has("GL_OES_depth_texture_cube_map");
#endif
@@ -5650,7 +5802,7 @@ void RasterizerStorageGLES2::initialize() {
#endif
config.rgtc_supported = config.extensions.has("GL_EXT_texture_compression_rgtc") || config.extensions.has("GL_ARB_texture_compression_rgtc") || config.extensions.has("EXT_texture_compression_rgtc");
- config.bptc_supported = config.extensions.has("GL_ARB_texture_compression_bptc");
+ config.bptc_supported = config.extensions.has("GL_ARB_texture_compression_bptc") || config.extensions.has("EXT_texture_compression_bptc");
//determine formats for depth textures (or renderbuffers)
if (config.support_depth_texture) {