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.cpp265
1 files changed, 257 insertions, 8 deletions
diff --git a/drivers/gles2/rasterizer_storage_gles2.cpp b/drivers/gles2/rasterizer_storage_gles2.cpp
index af698f3988..d00d572ccf 100644
--- a/drivers/gles2/rasterizer_storage_gles2.cpp
+++ b/drivers/gles2/rasterizer_storage_gles2.cpp
@@ -195,11 +195,11 @@ Ref<Image> RasterizerStorageGLES2::_get_gl_image_and_format(const Ref<Image> &p_
} break;
case Image::FORMAT_DXT1: {
- r_compressed = true;
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;
+ r_compressed = true;
} else {
need_decompress = true;
}
@@ -846,6 +846,17 @@ void RasterizerStorageGLES2::textures_keep_original(bool p_enable) {
config.keep_original_textures = p_enable;
}
+Size2 RasterizerStorageGLES2::texture_size_with_proxy(RID p_texture) const {
+
+ const Texture *texture = texture_owner.getornull(p_texture);
+ ERR_FAIL_COND_V(!texture, Size2());
+ if (texture->proxy) {
+ return Size2(texture->proxy->width, texture->proxy->height);
+ } else {
+ return Size2(texture->width, texture->height);
+ }
+}
+
void RasterizerStorageGLES2::texture_set_proxy(RID p_texture, RID p_proxy) {
Texture *texture = texture_owner.getornull(p_texture);
ERR_FAIL_COND(!texture);
@@ -1715,8 +1726,196 @@ RID RasterizerStorageGLES2::mesh_create() {
return mesh_owner.make_rid(mesh);
}
+static PoolVector<uint8_t> _unpack_half_floats(const PoolVector<uint8_t> &array, uint32_t &format, int p_vertices) {
+
+ uint32_t p_format = format;
+
+ static int src_size[VS::ARRAY_MAX];
+ static int dst_size[VS::ARRAY_MAX];
+ static int to_convert[VS::ARRAY_MAX];
+
+ int src_stride = 0;
+ int dst_stride = 0;
+
+ for (int i = 0; i < VS::ARRAY_MAX; i++) {
+
+ to_convert[i] = 0;
+ if (!(p_format & (1 << i))) {
+ src_size[i] = 0;
+ dst_size[i] = 0;
+ continue;
+ }
+
+ switch (i) {
+
+ case VS::ARRAY_VERTEX: {
+
+ if (p_format & VS::ARRAY_COMPRESS_VERTEX) {
+
+ if (p_format & VS::ARRAY_FLAG_USE_2D_VERTICES) {
+ src_size[i] = 4;
+ dst_size[i] = 8;
+ to_convert[i] = 2;
+ } else {
+ src_size[i] = 8;
+ dst_size[i] = 12;
+ to_convert[i] = 3;
+ }
+
+ format &= ~VS::ARRAY_COMPRESS_VERTEX;
+ } else {
+
+ if (p_format & VS::ARRAY_FLAG_USE_2D_VERTICES) {
+ src_size[i] = 8;
+ dst_size[i] = 8;
+ } else {
+ src_size[i] = 12;
+ dst_size[i] = 12;
+ }
+ }
+
+ } break;
+ case VS::ARRAY_NORMAL: {
+
+ if (p_format & VS::ARRAY_COMPRESS_NORMAL) {
+ src_size[i] = 4;
+ dst_size[i] = 4;
+ } else {
+ src_size[i] = 12;
+ dst_size[i] = 12;
+ }
+
+ } break;
+ case VS::ARRAY_TANGENT: {
+
+ if (p_format & VS::ARRAY_COMPRESS_TANGENT) {
+ src_size[i] = 4;
+ dst_size[i] = 4;
+ } else {
+ src_size[i] = 16;
+ dst_size[i] = 16;
+ }
+
+ } break;
+ case VS::ARRAY_COLOR: {
+
+ if (p_format & VS::ARRAY_COMPRESS_COLOR) {
+ src_size[i] = 4;
+ dst_size[i] = 4;
+ } else {
+ src_size[i] = 16;
+ dst_size[i] = 16;
+ }
+
+ } break;
+ case VS::ARRAY_TEX_UV: {
+
+ if (p_format & VS::ARRAY_COMPRESS_TEX_UV) {
+ src_size[i] = 4;
+ to_convert[i] = 2;
+ format &= ~VS::ARRAY_COMPRESS_TEX_UV;
+ } else {
+ src_size[i] = 8;
+ }
+
+ dst_size[i] = 8;
+
+ } break;
+ case VS::ARRAY_TEX_UV2: {
+
+ if (p_format & VS::ARRAY_COMPRESS_TEX_UV2) {
+ src_size[i] = 4;
+ to_convert[i] = 2;
+ format &= ~VS::ARRAY_COMPRESS_TEX_UV2;
+ } else {
+ src_size[i] = 8;
+ }
+
+ dst_size[i] = 8;
+
+ } break;
+ case VS::ARRAY_BONES: {
+
+ if (p_format & VS::ARRAY_FLAG_USE_16_BIT_BONES) {
+ src_size[i] = 8;
+ dst_size[i] = 8;
+ } else {
+ src_size[i] = 4;
+ dst_size[i] = 4;
+ }
+
+ } break;
+ case VS::ARRAY_WEIGHTS: {
+
+ if (p_format & VS::ARRAY_COMPRESS_WEIGHTS) {
+ src_size[i] = 8;
+ dst_size[i] = 8;
+ } else {
+ src_size[i] = 16;
+ dst_size[i] = 16;
+ }
+
+ } break;
+ case VS::ARRAY_INDEX: {
+
+ src_size[i] = 0;
+ dst_size[i] = 0;
+
+ } break;
+ }
+
+ src_stride += src_size[i];
+ dst_stride += dst_size[i];
+ }
+
+ PoolVector<uint8_t> ret;
+ ret.resize(p_vertices * dst_stride);
+
+ PoolVector<uint8_t>::Read r = array.read();
+ PoolVector<uint8_t>::Write w = ret.write();
+
+ int src_offset = 0;
+ int dst_offset = 0;
+
+ for (int i = 0; i < VS::ARRAY_MAX; i++) {
+
+ if (src_size[i] == 0) {
+ continue; //no go
+ }
+ const uint8_t *rptr = r.ptr();
+ uint8_t *wptr = w.ptr();
+ if (to_convert[i]) { //converting
+
+ for (int j = 0; j < p_vertices; j++) {
+ const uint16_t *src = (const uint16_t *)&rptr[src_stride * j + src_offset];
+ float *dst = (float *)&wptr[dst_stride * j + dst_offset];
+
+ for (int k = 0; k < to_convert[i]; k++) {
+
+ dst[k] = Math::half_to_float(src[k]);
+ }
+ }
+
+ } else {
+ //just copy
+ for (int j = 0; j < p_vertices; j++) {
+ for (int k = 0; k < src_size[i]; k++) {
+ wptr[dst_stride * j + dst_offset + k] = rptr[src_stride * j + src_offset + k];
+ }
+ }
+ }
+
+ src_offset += src_size[i];
+ dst_offset += dst_size[i];
+ }
+
+ r = PoolVector<uint8_t>::Read();
+ w = PoolVector<uint8_t>::Write();
+
+ return ret;
+}
+
void RasterizerStorageGLES2::mesh_add_surface(RID p_mesh, uint32_t p_format, VS::PrimitiveType p_primitive, const PoolVector<uint8_t> &p_array, int p_vertex_count, const PoolVector<uint8_t> &p_index_array, int p_index_count, const AABB &p_aabb, const Vector<PoolVector<uint8_t> > &p_blend_shapes, const Vector<AABB> &p_bone_aabbs) {
- PoolVector<uint8_t> array = p_array;
Mesh *mesh = mesh_owner.getornull(p_mesh);
ERR_FAIL_COND(!mesh);
@@ -1735,6 +1934,7 @@ void RasterizerStorageGLES2::mesh_add_surface(RID p_mesh, uint32_t p_format, VS:
Surface::Attrib attribs[VS::ARRAY_MAX];
int stride = 0;
+ bool uses_half_float = false;
for (int i = 0; i < VS::ARRAY_MAX; i++) {
@@ -1763,6 +1963,7 @@ void RasterizerStorageGLES2::mesh_add_surface(RID p_mesh, uint32_t p_format, VS:
if (p_format & VS::ARRAY_COMPRESS_VERTEX) {
attribs[i].type = _GL_HALF_FLOAT_OES;
stride += attribs[i].size * 2;
+ uses_half_float = true;
} else {
attribs[i].type = GL_FLOAT;
stride += attribs[i].size * 4;
@@ -1823,6 +2024,7 @@ void RasterizerStorageGLES2::mesh_add_surface(RID p_mesh, uint32_t p_format, VS:
if (p_format & VS::ARRAY_COMPRESS_TEX_UV) {
attribs[i].type = _GL_HALF_FLOAT_OES;
stride += 4;
+ uses_half_float = true;
} else {
attribs[i].type = GL_FLOAT;
stride += 8;
@@ -1838,6 +2040,7 @@ void RasterizerStorageGLES2::mesh_add_surface(RID p_mesh, uint32_t p_format, VS:
if (p_format & VS::ARRAY_COMPRESS_TEX_UV2) {
attribs[i].type = _GL_HALF_FLOAT_OES;
stride += 4;
+ uses_half_float = true;
} else {
attribs[i].type = GL_FLOAT;
stride += 8;
@@ -1900,6 +2103,7 @@ void RasterizerStorageGLES2::mesh_add_surface(RID p_mesh, uint32_t p_format, VS:
}
//validate sizes
+ PoolVector<uint8_t> array = p_array;
int array_size = stride * p_vertex_count;
int index_array_size = 0;
@@ -1931,6 +2135,15 @@ void RasterizerStorageGLES2::mesh_add_surface(RID p_mesh, uint32_t p_format, VS:
ERR_FAIL_COND(array.size() != array_size);
+ if (!config.support_half_float_vertices && uses_half_float) {
+
+ uint32_t new_format = p_format;
+ PoolVector<uint8_t> unpacked_array = _unpack_half_floats(array, new_format, p_vertex_count);
+
+ mesh_add_surface(p_mesh, new_format, p_primitive, unpacked_array, p_vertex_count, p_index_array, p_index_count, p_aabb, p_blend_shapes, p_bone_aabbs);
+ return; //do not go any further, above function used unpacked stuff will be used instead.
+ }
+
if (p_format & VS::ARRAY_FORMAT_INDEX) {
index_array_size = attribs[VS::ARRAY_INDEX].stride * p_index_count;
@@ -4007,7 +4220,11 @@ void RasterizerStorageGLES2::_render_target_allocate(RenderTarget *rt) {
glGenRenderbuffers(1, &rt->depth);
glBindRenderbuffer(GL_RENDERBUFFER, rt->depth);
+#ifdef JAVASCRIPT_ENABLED
+ glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, rt->width, rt->height);
+#else
glRenderbufferStorage(GL_RENDERBUFFER, _DEPTH_COMPONENT24_OES, rt->width, rt->height);
+#endif
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rt->depth);
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
@@ -4045,7 +4262,8 @@ void RasterizerStorageGLES2::_render_target_allocate(RenderTarget *rt) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// copy texscreen buffers
- {
+ if (!(rt->flags[RasterizerStorage::RENDER_TARGET_NO_SAMPLING])) {
+
int w = rt->width;
int h = rt->height;
@@ -4053,10 +4271,17 @@ void RasterizerStorageGLES2::_render_target_allocate(RenderTarget *rt) {
glBindTexture(GL_TEXTURE_2D, rt->copy_screen_effect.color);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+ 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);
glGenFramebuffers(1, &rt->copy_screen_effect.fbo);
glBindFramebuffer(GL_FRAMEBUFFER, rt->copy_screen_effect.fbo);
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->color, 0);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->copy_screen_effect.color, 0);
+
+ glClearColor(0, 0, 0, 0);
+ glClear(GL_COLOR_BUFFER_BIT);
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if (status != GL_FRAMEBUFFER_COMPLETE) {
@@ -4218,7 +4443,11 @@ RID RasterizerStorageGLES2::canvas_light_shadow_buffer_create(int p_width) {
glGenRenderbuffers(1, &cls->depth);
glBindRenderbuffer(GL_RENDERBUFFER, cls->depth);
- glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, cls->size, cls->height);
+#ifdef JAVASCRIPT_ENABLED
+ glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, cls->size, cls->height);
+#else
+ glRenderbufferStorage(GL_RENDERBUFFER, _DEPTH_COMPONENT24_OES, cls->size, cls->height);
+#endif
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, cls->depth);
glBindRenderbuffer(GL_RENDERBUFFER, 0);
@@ -4413,7 +4642,7 @@ bool RasterizerStorageGLES2::free(RID p_rid) {
Shader *shader = shader_owner.get(p_rid);
- if (shader->shader) {
+ if (shader->shader && shader->custom_code_id) {
shader->shader->free_custom_shader(shader->custom_code_id);
}
@@ -4650,14 +4879,34 @@ void RasterizerStorageGLES2::initialize() {
config.etc1_supported = false;
#else
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.etc1_supported = config.extensions.has("GL_OES_compressed_ETC1_RGB8_texture");
+ 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");
#endif
#ifdef GLES_OVER_GL
config.use_rgba_2d_shadows = false;
#else
config.use_rgba_2d_shadows = !(config.float_texture_supported && config.extensions.has("GL_EXT_texture_rg"));
#endif
+
+#ifdef GLES_OVER_GL
+ config.support_32_bits_indices = true;
+#else
+ config.support_32_bits_indices = config.extensions.has("GL_OES_element_index_uint");
+#endif
+
+#ifdef GLES_OVER_GL
+ config.support_write_depth = true;
+#else
+ config.support_write_depth = config.extensions.has("GL_EXT_frag_depth");
+#endif
+
+#ifdef JAVASCRIPT_ENABLED
+ config.support_half_float_vertices = false;
+#else
+ //every other platform, be it mobile or desktop, supports this (even if not in the GLES2 spec).
+ config.support_half_float_vertices = true;
+#endif
+
frame.count = 0;
frame.delta = 0;
frame.current_rt = NULL;