From a3d5aec68dc63227e1271a91333cb2e901f24221 Mon Sep 17 00:00:00 2001 From: clayjohn Date: Mon, 29 Apr 2019 11:51:09 -0700 Subject: [PATCH] added MSAA to GLES backend --- drivers/gles2/rasterizer_gles2.cpp | 4 + drivers/gles2/rasterizer_scene_gles2.cpp | 87 ++++++- drivers/gles2/rasterizer_scene_gles2.h | 1 + drivers/gles2/rasterizer_storage_gles2.cpp | 286 +++++++++++++++------ drivers/gles2/rasterizer_storage_gles2.h | 12 +- platform/android/detect.py | 2 +- thirdparty/glad/glad.c | 24 +- thirdparty/glad/glad/glad.h | 29 ++- 8 files changed, 363 insertions(+), 82 deletions(-) diff --git a/drivers/gles2/rasterizer_gles2.cpp b/drivers/gles2/rasterizer_gles2.cpp index d3c6b041a86e..f49f52e47b3c 100644 --- a/drivers/gles2/rasterizer_gles2.cpp +++ b/drivers/gles2/rasterizer_gles2.cpp @@ -202,6 +202,10 @@ Error RasterizerGLES2::is_viable() { return ERR_UNAVAILABLE; } } + + if (GLAD_GL_EXT_framebuffer_multisample) { + glRenderbufferStorageMultisample = glRenderbufferStorageMultisampleEXT; + } #endif // GLES_OVER_GL #endif // GLAD_ENABLED diff --git a/drivers/gles2/rasterizer_scene_gles2.cpp b/drivers/gles2/rasterizer_scene_gles2.cpp index 9f1425189c3d..76b9c6d1adc0 100644 --- a/drivers/gles2/rasterizer_scene_gles2.cpp +++ b/drivers/gles2/rasterizer_scene_gles2.cpp @@ -42,6 +42,16 @@ #define glClearDepth glClearDepthf #endif +#ifndef GLES_OVER_GL +#ifdef IPHONE_ENABLED +#include +//void *glResolveMultisampleFramebufferAPPLE; + +#define GL_READ_FRAMEBUFFER 0x8CA8 +#define GL_DRAW_FRAMEBUFFER 0x8CA9 +#endif +#endif + static const GLenum _cube_side_enum[6] = { GL_TEXTURE_CUBE_MAP_NEGATIVE_X, @@ -1148,6 +1158,30 @@ void RasterizerSceneGLES2::_add_geometry_with_material(RasterizerStorageGLES2::G } } +void RasterizerSceneGLES2::_copy_texture_to_front_buffer(GLuint p_texture) { + + //copy to front buffer + glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->fbo); + + glDepthMask(GL_FALSE); + glDisable(GL_DEPTH_TEST); + glDisable(GL_CULL_FACE); + glDisable(GL_BLEND); + glDepthFunc(GL_LEQUAL); + glColorMask(1, 1, 1, 1); + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, p_texture); + + glViewport(0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height); + + storage->shaders.copy.bind(); + + storage->bind_quad_array(); + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + glBindBuffer(GL_ARRAY_BUFFER, 0); +} + void RasterizerSceneGLES2::_fill_render_list(InstanceBase **p_cull_result, int p_cull_count, bool p_depth_pass, bool p_shadow_pass) { render_pass++; @@ -2689,7 +2723,11 @@ void RasterizerSceneGLES2::render_scene(const Transform &p_cam_transform, const if (storage->frame.current_rt->external.fbo != 0) { current_fb = storage->frame.current_rt->external.fbo; } else { - current_fb = storage->frame.current_rt->fbo; + if (storage->frame.current_rt->multisample_active) { + current_fb = storage->frame.current_rt->multisample_fbo; + } else { + current_fb = storage->frame.current_rt->fbo; + } } env = environment_owner.getornull(p_environment); @@ -2838,7 +2876,38 @@ void RasterizerSceneGLES2::render_scene(const Transform &p_cam_transform, const if (storage->frame.current_rt && state.used_screen_texture) { //copy screen texture + + if (storage->frame.current_rt && storage->frame.current_rt->multisample_active) { + // Resolve framebuffer to front buffer before copying +#ifdef GLES_OVER_GL + + glBindFramebuffer(GL_READ_FRAMEBUFFER, storage->frame.current_rt->multisample_fbo); + glReadBuffer(GL_COLOR_ATTACHMENT0); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, storage->frame.current_rt->fbo); + glBlitFramebuffer(0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height, 0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, GL_NEAREST); + + glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); +#elif IPHONE_ENABLED + glBindFramebuffer(GL_READ_FRAMEBUFFER, storage->frame.current_rt->multisample_fbo); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, storage->frame.current_rt->fbo); + glResolveMultisampleFramebufferAPPLE(); + + glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); +#else + // In GLES2 Blit is not available, so just copy color texture manually + _copy_texture_to_front_buffer(storage->frame.current_rt->multisample_color); +#endif + } + storage->canvas->_copy_screen(Rect2()); + + if (storage->frame.current_rt && storage->frame.current_rt->multisample_active) { + // Rebind the current framebuffer + glBindFramebuffer(GL_FRAMEBUFFER, current_fb); + glViewport(0, 0, viewport_width, viewport_height); + } } // alpha pass @@ -2851,6 +2920,22 @@ void RasterizerSceneGLES2::render_scene(const Transform &p_cam_transform, const glDisable(GL_DEPTH_TEST); + if (storage->frame.current_rt && storage->frame.current_rt->multisample_active) { +#ifdef GLES_OVER_GL + + glBindFramebuffer(GL_READ_FRAMEBUFFER, storage->frame.current_rt->multisample_fbo); + glReadBuffer(GL_COLOR_ATTACHMENT0); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, storage->frame.current_rt->fbo); + glBlitFramebuffer(0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height, 0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, GL_NEAREST); + + glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); +#else + // In GLES2 Blit is not available, so just copy color texture manually + _copy_texture_to_front_buffer(storage->frame.current_rt->multisample_color); +#endif + } + //#define GLES2_SHADOW_ATLAS_DEBUG_VIEW #ifdef GLES2_SHADOW_ATLAS_DEBUG_VIEW diff --git a/drivers/gles2/rasterizer_scene_gles2.h b/drivers/gles2/rasterizer_scene_gles2.h index f23e45b52fad..09ef1b3b54b7 100644 --- a/drivers/gles2/rasterizer_scene_gles2.h +++ b/drivers/gles2/rasterizer_scene_gles2.h @@ -646,6 +646,7 @@ public: void _add_geometry(RasterizerStorageGLES2::Geometry *p_geometry, InstanceBase *p_instance, RasterizerStorageGLES2::GeometryOwner *p_owner, int p_material, bool p_depth_pass, bool p_shadow_pass); void _add_geometry_with_material(RasterizerStorageGLES2::Geometry *p_geometry, InstanceBase *p_instance, RasterizerStorageGLES2::GeometryOwner *p_owner, RasterizerStorageGLES2::Material *p_material, bool p_depth_pass, bool p_shadow_pass); + void _copy_texture_to_front_buffer(GLuint texture); void _fill_render_list(InstanceBase **p_cull_result, int p_cull_count, bool p_depth_pass, bool p_shadow_pass); void _render_render_list(RenderList::Element **p_elements, int p_element_count, const Transform &p_view_transform, diff --git a/drivers/gles2/rasterizer_storage_gles2.cpp b/drivers/gles2/rasterizer_storage_gles2.cpp index 1e32d8166f75..1c73d1153cce 100644 --- a/drivers/gles2/rasterizer_storage_gles2.cpp +++ b/drivers/gles2/rasterizer_storage_gles2.cpp @@ -81,6 +81,28 @@ GLuint RasterizerStorageGLES2::system_fbo = 0; #define _DEPTH_COMPONENT24_OES 0x81A6 +#ifndef GLES_OVER_GL +// enable extensions manually for android and ios +#include // needed to load extensions + +#ifdef IPHONE_ENABLED + +#include +//void *glRenderbufferStorageMultisampleAPPLE; +//void *glResolveMultisampleFramebufferAPPLE; +#define glRenderbufferStorageMultisample glRenderbufferStorageMultisampleAPPLE +#else + +#include +PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC glRenderbufferStorageMultisampleEXT; +PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEEXTPROC glFramebufferTexture2DMultisampleEXT; +#define glRenderbufferStorageMultisample glRenderbufferStorageMultisampleEXT +#define glFramebufferTexture2DMultisample glFramebufferTexture2DMultisampleEXT +#endif + +#define GL_MAX_SAMPLES 0x8D57 +#endif //!GLES_OVER_GL + void RasterizerStorageGLES2::bind_quad_array() const { glBindBuffer(GL_ARRAY_BUFFER, resources.quadie); glVertexAttribPointer(VS::ARRAY_VERTEX, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 4, 0); @@ -4534,95 +4556,174 @@ void RasterizerStorageGLES2::_render_target_allocate(RenderTarget *rt) { if (rt->width <= 0 || rt->height <= 0) return; - Texture *texture = texture_owner.getornull(rt->texture); - ERR_FAIL_COND(!texture); - - // create fbo - - glGenFramebuffers(1, &rt->fbo); - glBindFramebuffer(GL_FRAMEBUFFER, rt->fbo); - - // color - - glGenTextures(1, &rt->color); - glBindTexture(GL_TEXTURE_2D, rt->color); + GLuint color_internal_format; + GLuint color_format; + GLuint color_type = GL_UNSIGNED_BYTE; if (rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]) { - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, rt->width, rt->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + color_internal_format = GL_RGBA; + color_format = GL_RGBA; } else { - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, rt->width, rt->height, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); + color_internal_format = GL_RGB; + color_format = GL_RGB; } - if (texture->flags & VS::TEXTURE_FLAG_FILTER) { + { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - } else { + /* Front FBO */ - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - } - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + Texture *texture = texture_owner.getornull(rt->texture); + ERR_FAIL_COND(!texture); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->color, 0); + // framebuffer + glGenFramebuffers(1, &rt->fbo); + glBindFramebuffer(GL_FRAMEBUFFER, rt->fbo); - // depth + // color + glGenTextures(1, &rt->color); + glBindTexture(GL_TEXTURE_2D, rt->color); - if (config.support_depth_texture) { - glGenTextures(1, &rt->depth); - glBindTexture(GL_TEXTURE_2D, rt->depth); - glTexImage2D(GL_TEXTURE_2D, 0, config.depth_internalformat, rt->width, rt->height, 0, GL_DEPTH_COMPONENT, config.depth_type, NULL); + glTexImage2D(GL_TEXTURE_2D, 0, color_internal_format, rt->width, rt->height, 0, color_format, color_type, NULL); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + if (texture->flags & VS::TEXTURE_FLAG_FILTER) { - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, rt->depth, 0); - } else { - glGenRenderbuffers(1, &rt->depth); - glBindRenderbuffer(GL_RENDERBUFFER, rt->depth); - - glRenderbufferStorage(GL_RENDERBUFFER, config.depth_internalformat, rt->width, rt->height); - - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rt->depth); - } - - GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); - - if (status != GL_FRAMEBUFFER_COMPLETE) { - - glDeleteFramebuffers(1, &rt->fbo); - if (config.support_depth_texture) { - glDeleteTextures(1, &rt->depth); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); } else { - glDeleteRenderbuffers(1, &rt->depth); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); } - glDeleteTextures(1, &rt->color); - rt->fbo = 0; - rt->width = 0; - rt->height = 0; - rt->color = 0; - rt->depth = 0; - texture->tex_id = 0; - texture->active = false; - WARN_PRINT("Could not create framebuffer!!"); - return; + + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->color, 0); + + // depth + + if (config.support_depth_texture) { + + glGenTextures(1, &rt->depth); + glBindTexture(GL_TEXTURE_2D, rt->depth); + glTexImage2D(GL_TEXTURE_2D, 0, config.depth_internalformat, rt->width, rt->height, 0, GL_DEPTH_COMPONENT, config.depth_type, NULL); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, rt->depth, 0); + } else { + + glGenRenderbuffers(1, &rt->depth); + glBindRenderbuffer(GL_RENDERBUFFER, rt->depth); + + glRenderbufferStorage(GL_RENDERBUFFER, config.depth_internalformat, rt->width, rt->height); + + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rt->depth); + } + + GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); + + if (status != GL_FRAMEBUFFER_COMPLETE) { + + glDeleteFramebuffers(1, &rt->fbo); + if (config.support_depth_texture) { + + glDeleteTextures(1, &rt->depth); + } else { + + glDeleteRenderbuffers(1, &rt->depth); + } + + glDeleteTextures(1, &rt->color); + rt->fbo = 0; + rt->width = 0; + rt->height = 0; + rt->color = 0; + rt->depth = 0; + texture->tex_id = 0; + texture->active = false; + WARN_PRINT("Could not create framebuffer!!"); + return; + } + + texture->format = Image::FORMAT_RGBA8; + texture->gl_format_cache = GL_RGBA; + texture->gl_type_cache = GL_UNSIGNED_BYTE; + texture->gl_internal_format_cache = GL_RGBA; + texture->tex_id = rt->color; + texture->width = rt->width; + texture->alloc_width = rt->width; + texture->height = rt->height; + texture->alloc_height = rt->height; + texture->active = true; + + texture_set_flags(rt->texture, texture->flags); } - texture->format = Image::FORMAT_RGBA8; - texture->gl_format_cache = GL_RGBA; - texture->gl_type_cache = GL_UNSIGNED_BYTE; - texture->gl_internal_format_cache = GL_RGBA; - texture->tex_id = rt->color; - texture->width = rt->width; - texture->alloc_width = rt->width; - texture->height = rt->height; - texture->alloc_height = rt->height; - texture->active = true; + /* BACK FBO */ + /* For MSAA */ - texture_set_flags(rt->texture, texture->flags); + if (rt->msaa != VS::VIEWPORT_MSAA_DISABLED && config.multisample_supported) { + + rt->multisample_active = true; + + static const int msaa_value[] = { 0, 2, 4, 8, 16 }; + int msaa = msaa_value[rt->msaa]; + + int max_samples = 0; + glGetIntegerv(GL_MAX_SAMPLES, &max_samples); + if (msaa > max_samples) { + WARN_PRINTS("MSAA must be <= GL_MAX_SAMPLES, falling-back to GL_MAX_SAMPLES = " + itos(max_samples)); + msaa = max_samples; + } + + //regular fbo + glGenFramebuffers(1, &rt->multisample_fbo); + glBindFramebuffer(GL_FRAMEBUFFER, rt->multisample_fbo); + + glGenRenderbuffers(1, &rt->multisample_depth); + glBindRenderbuffer(GL_RENDERBUFFER, rt->multisample_depth); + glRenderbufferStorageMultisample(GL_RENDERBUFFER, msaa, config.depth_internalformat, rt->width, rt->height); + + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rt->multisample_depth); + +#if defined(GLES_OVER_GL) || defined(IPHONE_ENABLED) + + glGenRenderbuffers(1, &rt->multisample_color); + glBindRenderbuffer(GL_RENDERBUFFER, rt->multisample_color); + glRenderbufferStorageMultisample(GL_RENDERBUFFER, msaa, color_internal_format, rt->width, rt->height); + + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rt->multisample_color); +#else + // Render to a texture in android + glGenTextures(1, &rt->multisample_color); + glBindTexture(GL_TEXTURE_2D, rt->multisample_color); + + glTexImage2D(GL_TEXTURE_2D, 0, color_internal_format, rt->width, rt->height, 0, color_format, color_type, NULL); + + // multisample buffer is same size as front buffer, so just use nearest + 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); +#endif + + GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); + + if (status != GL_FRAMEBUFFER_COMPLETE) { + printf("err status: %x\n", status); + _render_target_clear(rt); + ERR_FAIL_COND(status != GL_FRAMEBUFFER_COMPLETE); + } + + glBindRenderbuffer(GL_RENDERBUFFER, 0); + + } else { + rt->multisample_active = false; + } glClearColor(0, 0, 0, 0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); @@ -4651,7 +4752,7 @@ void RasterizerStorageGLES2::_render_target_allocate(RenderTarget *rt) { glClearColor(0, 0, 0, 0); glClear(GL_COLOR_BUFFER_BIT); - status = glCheckFramebufferStatus(GL_FRAMEBUFFER); + GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); if (status != GL_FRAMEBUFFER_COMPLETE) { _render_target_clear(rt); ERR_FAIL_COND(status != GL_FRAMEBUFFER_COMPLETE); @@ -4710,6 +4811,20 @@ void RasterizerStorageGLES2::_render_target_clear(RenderTarget *rt) { glDeleteTextures(1, &rt->copy_screen_effect.color); rt->copy_screen_effect.color = 0; } + + if (rt->multisample_active) { + glDeleteFramebuffers(1, &rt->multisample_fbo); + rt->multisample_fbo = 0; + + glDeleteRenderbuffers(1, &rt->multisample_depth); + rt->multisample_depth = 0; +#ifdef GLES_OVER_GL + glDeleteRenderbuffers(1, &rt->multisample_color); +#else + glDeleteTextures(1, &rt->multisample_color); +#endif + rt->multisample_color = 0; + } } RID RasterizerStorageGLES2::render_target_create() { @@ -4911,6 +5026,11 @@ void RasterizerStorageGLES2::render_target_set_msaa(RID p_render_target, VS::Vie if (rt->msaa == p_msaa) return; + if (!config.multisample_supported) { + ERR_PRINT("MSAA not supported on this hardware."); + return; + } + _render_target_clear(rt); rt->msaa = p_msaa; _render_target_allocate(rt); @@ -5434,6 +5554,26 @@ void RasterizerStorageGLES2::initialize() { config.support_npot_repeat_mipmap = config.extensions.has("GL_OES_texture_npot"); #endif + +#ifndef GLES_OVER_GL + //Manually load extensions for android and ios + +#ifdef IPHONE_ENABLED + + //void *gles2_lib = dlopen(NULL, RTLD_LAZY); + //glRenderbufferStorageMultisampleAPPLE = dlsym(gles2_lib, "glRenderbufferStorageMultisampleAPPLE"); + //glResolveMultisampleFramebufferAPPLE = dlsym(gles2_lib, "glResolveMultisampleFramebufferAPPLE"); +#else + + void *gles2_lib = dlopen("libGLESv2.so", RTLD_LAZY); + glRenderbufferStorageMultisampleEXT = (PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC)dlsym(gles2_lib, "glRenderbufferStorageMultisampleEXT"); + glFramebufferTexture2DMultisampleEXT = (PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEEXTPROC)dlsym(gles2_lib, "glFramebufferTexture2DMultisampleEXT"); +#endif +#endif + + // Check for multisample support + 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 config.use_rgba_2d_shadows = false; config.support_depth_texture = true; diff --git a/drivers/gles2/rasterizer_storage_gles2.h b/drivers/gles2/rasterizer_storage_gles2.h index 2ac68fa47a45..24e415d04046 100644 --- a/drivers/gles2/rasterizer_storage_gles2.h +++ b/drivers/gles2/rasterizer_storage_gles2.h @@ -92,6 +92,8 @@ public: bool support_shadow_cubemaps; + bool multisample_supported; + GLuint depth_internalformat; GLuint depth_type; @@ -1129,10 +1131,14 @@ public: struct RenderTarget : public RID_Data { GLuint fbo; - GLuint color; GLuint depth; + GLuint multisample_fbo; + GLuint multisample_color; + GLuint multisample_depth; + bool multisample_active; + // TODO post processing effects? // TODO HDR? @@ -1179,6 +1185,10 @@ public: fbo(0), color(0), depth(0), + multisample_fbo(0), + multisample_color(0), + multisample_depth(0), + multisample_active(false), width(0), height(0), used_in_frame(false), diff --git a/platform/android/detect.py b/platform/android/detect.py index 6c67067db728..531e32101c2f 100644 --- a/platform/android/detect.py +++ b/platform/android/detect.py @@ -301,7 +301,7 @@ def configure(env): env.Append(CPPPATH=['#platform/android']) env.Append(CPPFLAGS=['-DANDROID_ENABLED', '-DUNIX_ENABLED', '-DNO_FCNTL']) - env.Append(LIBS=['OpenSLES', 'EGL', 'GLESv3', 'android', 'log', 'z', 'dl']) + env.Append(LIBS=['OpenSLES', 'EGL', 'GLESv3', 'GLESv2', 'android', 'log', 'z', 'dl']) # Return NDK version string in source.properties (adapted from the Chromium project). def get_ndk_version(path): diff --git a/thirdparty/glad/glad.c b/thirdparty/glad/glad.c index e7c64a7e1797..9704c1079f92 100644 --- a/thirdparty/glad/glad.c +++ b/thirdparty/glad/glad.c @@ -1,6 +1,6 @@ /* - OpenGL loader generated by glad 0.1.29 on Mon Mar 4 12:47:22 2019. + OpenGL loader generated by glad 0.1.29 on Wed May 1 23:16:34 2019. Language/Generator: C/C++ Specification: gl @@ -9,6 +9,8 @@ Extensions: GL_ARB_debug_output, GL_ARB_framebuffer_object, + GL_EXT_framebuffer_blit, + GL_EXT_framebuffer_multisample, GL_EXT_framebuffer_object Loader: True Local files: False @@ -16,9 +18,9 @@ Reproducible: False Commandline: - --profile="compatibility" --api="gl=3.3" --generator="c" --spec="gl" --extensions="GL_ARB_debug_output,GL_ARB_framebuffer_object,GL_EXT_framebuffer_object" + --profile="compatibility" --api="gl=3.3" --generator="c" --spec="gl" --extensions="GL_ARB_debug_output,GL_ARB_framebuffer_object,GL_EXT_framebuffer_blit,GL_EXT_framebuffer_multisample,GL_EXT_framebuffer_object" Online: - https://glad.dav1d.de/#profile=compatibility&language=c&specification=gl&loader=on&api=gl%3D3.3&extensions=GL_ARB_debug_output&extensions=GL_ARB_framebuffer_object&extensions=GL_EXT_framebuffer_object + https://glad.dav1d.de/#profile=compatibility&language=c&specification=gl&loader=on&api=gl%3D3.3&extensions=GL_ARB_debug_output&extensions=GL_ARB_framebuffer_object&extensions=GL_EXT_framebuffer_blit&extensions=GL_EXT_framebuffer_multisample&extensions=GL_EXT_framebuffer_object */ #include @@ -992,11 +994,15 @@ PFNGLWINDOWPOS3SPROC glad_glWindowPos3s = NULL; PFNGLWINDOWPOS3SVPROC glad_glWindowPos3sv = NULL; int GLAD_GL_ARB_debug_output = 0; int GLAD_GL_ARB_framebuffer_object = 0; +int GLAD_GL_EXT_framebuffer_blit = 0; +int GLAD_GL_EXT_framebuffer_multisample = 0; int GLAD_GL_EXT_framebuffer_object = 0; PFNGLDEBUGMESSAGECONTROLARBPROC glad_glDebugMessageControlARB = NULL; PFNGLDEBUGMESSAGEINSERTARBPROC glad_glDebugMessageInsertARB = NULL; PFNGLDEBUGMESSAGECALLBACKARBPROC glad_glDebugMessageCallbackARB = NULL; PFNGLGETDEBUGMESSAGELOGARBPROC glad_glGetDebugMessageLogARB = NULL; +PFNGLBLITFRAMEBUFFEREXTPROC glad_glBlitFramebufferEXT = NULL; +PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC glad_glRenderbufferStorageMultisampleEXT = NULL; PFNGLISRENDERBUFFEREXTPROC glad_glIsRenderbufferEXT = NULL; PFNGLBINDRENDERBUFFEREXTPROC glad_glBindRenderbufferEXT = NULL; PFNGLDELETERENDERBUFFERSEXTPROC glad_glDeleteRenderbuffersEXT = NULL; @@ -1807,6 +1813,14 @@ static void load_GL_ARB_framebuffer_object(GLADloadproc load) { glad_glRenderbufferStorageMultisample = (PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC)load("glRenderbufferStorageMultisample"); glad_glFramebufferTextureLayer = (PFNGLFRAMEBUFFERTEXTURELAYERPROC)load("glFramebufferTextureLayer"); } +static void load_GL_EXT_framebuffer_blit(GLADloadproc load) { + if(!GLAD_GL_EXT_framebuffer_blit) return; + glad_glBlitFramebufferEXT = (PFNGLBLITFRAMEBUFFEREXTPROC)load("glBlitFramebufferEXT"); +} +static void load_GL_EXT_framebuffer_multisample(GLADloadproc load) { + if(!GLAD_GL_EXT_framebuffer_multisample) return; + glad_glRenderbufferStorageMultisampleEXT = (PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC)load("glRenderbufferStorageMultisampleEXT"); +} static void load_GL_EXT_framebuffer_object(GLADloadproc load) { if(!GLAD_GL_EXT_framebuffer_object) return; glad_glIsRenderbufferEXT = (PFNGLISRENDERBUFFEREXTPROC)load("glIsRenderbufferEXT"); @@ -1831,6 +1845,8 @@ static int find_extensionsGL(void) { if (!get_exts()) return 0; GLAD_GL_ARB_debug_output = has_ext("GL_ARB_debug_output"); GLAD_GL_ARB_framebuffer_object = has_ext("GL_ARB_framebuffer_object"); + GLAD_GL_EXT_framebuffer_blit = has_ext("GL_EXT_framebuffer_blit"); + GLAD_GL_EXT_framebuffer_multisample = has_ext("GL_EXT_framebuffer_multisample"); GLAD_GL_EXT_framebuffer_object = has_ext("GL_EXT_framebuffer_object"); free_exts(); return 1; @@ -1912,6 +1928,8 @@ int gladLoadGLLoader(GLADloadproc load) { if (!find_extensionsGL()) return 0; load_GL_ARB_debug_output(load); load_GL_ARB_framebuffer_object(load); + load_GL_EXT_framebuffer_blit(load); + load_GL_EXT_framebuffer_multisample(load); load_GL_EXT_framebuffer_object(load); return GLVersion.major != 0 || GLVersion.minor != 0; } diff --git a/thirdparty/glad/glad/glad.h b/thirdparty/glad/glad/glad.h index 6345de6f7aef..b398faf627f8 100644 --- a/thirdparty/glad/glad/glad.h +++ b/thirdparty/glad/glad/glad.h @@ -1,6 +1,6 @@ /* - OpenGL loader generated by glad 0.1.29 on Mon Mar 4 12:47:22 2019. + OpenGL loader generated by glad 0.1.29 on Wed May 1 23:16:34 2019. Language/Generator: C/C++ Specification: gl @@ -9,6 +9,8 @@ Extensions: GL_ARB_debug_output, GL_ARB_framebuffer_object, + GL_EXT_framebuffer_blit, + GL_EXT_framebuffer_multisample, GL_EXT_framebuffer_object Loader: True Local files: False @@ -16,9 +18,9 @@ Reproducible: False Commandline: - --profile="compatibility" --api="gl=3.3" --generator="c" --spec="gl" --extensions="GL_ARB_debug_output,GL_ARB_framebuffer_object,GL_EXT_framebuffer_object" + --profile="compatibility" --api="gl=3.3" --generator="c" --spec="gl" --extensions="GL_ARB_debug_output,GL_ARB_framebuffer_object,GL_EXT_framebuffer_blit,GL_EXT_framebuffer_multisample,GL_EXT_framebuffer_object" Online: - https://glad.dav1d.de/#profile=compatibility&language=c&specification=gl&loader=on&api=gl%3D3.3&extensions=GL_ARB_debug_output&extensions=GL_ARB_framebuffer_object&extensions=GL_EXT_framebuffer_object + https://glad.dav1d.de/#profile=compatibility&language=c&specification=gl&loader=on&api=gl%3D3.3&extensions=GL_ARB_debug_output&extensions=GL_ARB_framebuffer_object&extensions=GL_EXT_framebuffer_blit&extensions=GL_EXT_framebuffer_multisample&extensions=GL_EXT_framebuffer_object */ @@ -3633,6 +3635,13 @@ GLAPI PFNGLSECONDARYCOLORP3UIVPROC glad_glSecondaryColorP3uiv; #define GL_DEBUG_SEVERITY_HIGH_ARB 0x9146 #define GL_DEBUG_SEVERITY_MEDIUM_ARB 0x9147 #define GL_DEBUG_SEVERITY_LOW_ARB 0x9148 +#define GL_READ_FRAMEBUFFER_EXT 0x8CA8 +#define GL_DRAW_FRAMEBUFFER_EXT 0x8CA9 +#define GL_DRAW_FRAMEBUFFER_BINDING_EXT 0x8CA6 +#define GL_READ_FRAMEBUFFER_BINDING_EXT 0x8CAA +#define GL_RENDERBUFFER_SAMPLES_EXT 0x8CAB +#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT 0x8D56 +#define GL_MAX_SAMPLES_EXT 0x8D57 #define GL_INVALID_FRAMEBUFFER_OPERATION_EXT 0x0506 #define GL_MAX_RENDERBUFFER_SIZE_EXT 0x84E8 #define GL_FRAMEBUFFER_BINDING_EXT 0x8CA6 @@ -3704,6 +3713,20 @@ GLAPI PFNGLGETDEBUGMESSAGELOGARBPROC glad_glGetDebugMessageLogARB; #define GL_ARB_framebuffer_object 1 GLAPI int GLAD_GL_ARB_framebuffer_object; #endif +#ifndef GL_EXT_framebuffer_blit +#define GL_EXT_framebuffer_blit 1 +GLAPI int GLAD_GL_EXT_framebuffer_blit; +typedef void (APIENTRYP PFNGLBLITFRAMEBUFFEREXTPROC)(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); +GLAPI PFNGLBLITFRAMEBUFFEREXTPROC glad_glBlitFramebufferEXT; +#define glBlitFramebufferEXT glad_glBlitFramebufferEXT +#endif +#ifndef GL_EXT_framebuffer_multisample +#define GL_EXT_framebuffer_multisample 1 +GLAPI int GLAD_GL_EXT_framebuffer_multisample; +typedef void (APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC)(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); +GLAPI PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC glad_glRenderbufferStorageMultisampleEXT; +#define glRenderbufferStorageMultisampleEXT glad_glRenderbufferStorageMultisampleEXT +#endif #ifndef GL_EXT_framebuffer_object #define GL_EXT_framebuffer_object 1 GLAPI int GLAD_GL_EXT_framebuffer_object;