From 0a2d8d834ab3b7f0a01b4905250087526435bdbe Mon Sep 17 00:00:00 2001 From: Jean-Philippe Andre Date: Mon, 13 Feb 2017 17:42:10 +0900 Subject: [PATCH] evas gl: Partially fix MSAA for GLES 3 drivers MSAA (multisampled_render_to_texture) support was implemented with GLES 2 in mind, but for GLES 3 it comes as a core feature, not as an extension. Also it relies on renderbuffers, not textures. GL is awesome. Note: MSAA still doesn't work! --- .../evas/engines/gl_common/evas_gl_common.h | 2 + .../evas/engines/gl_common/evas_gl_context.c | 30 +++---- .../evas/engines/gl_common/evas_gl_core.c | 90 +++++++++++++------ 3 files changed, 79 insertions(+), 43 deletions(-) diff --git a/src/modules/evas/engines/gl_common/evas_gl_common.h b/src/modules/evas/engines/gl_common/evas_gl_common.h index 5a10fd51d7..59549efe84 100644 --- a/src/modules/evas/engines/gl_common/evas_gl_common.h +++ b/src/modules/evas/engines/gl_common/evas_gl_common.h @@ -543,6 +543,7 @@ typedef void (*Evas_Gl_Symbols)(void *(*GetProcAddress)(const char *sym)); EAPI void __evas_gl_err(int err, const char *file, const char *func, int line, const char *op); +int evas_gl_common_version_check(void); void evas_gl_common_tiling_start(Evas_Engine_GL_Context *gc, int rot, int gw, int gh, int cx, int cy, int cw, int ch, @@ -709,6 +710,7 @@ extern void (*glsym_glProgramParameteri) (GLuint a, GLuint b, GLint d); extern void (*glsym_glReleaseShaderCompiler)(void); extern void *(*glsym_glMapBuffer) (GLenum a, GLenum b); extern GLboolean (*glsym_glUnmapBuffer) (GLenum a); +extern void (*glsym_glRenderbufferStorageMultisample)(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); #ifdef GL_GLES EAPI void * evas_gl_common_eglCreateImage (EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLAttrib *attrib_list); diff --git a/src/modules/evas/engines/gl_common/evas_gl_context.c b/src/modules/evas/engines/gl_common/evas_gl_context.c index 602dac49c9..3d984e7e63 100644 --- a/src/modules/evas/engines/gl_common/evas_gl_context.c +++ b/src/modules/evas/engines/gl_common/evas_gl_context.c @@ -31,6 +31,7 @@ void *(*glsym_glMapBuffer) (GLenum a, GLenum b) = NULL; GLboolean (*glsym_glUnmapBuffer) (GLenum a) = NULL; void (*glsym_glStartTiling) (GLuint a, GLuint b, GLuint c, GLuint d, GLuint e) = NULL; void (*glsym_glEndTiling) (GLuint a) = NULL; +void (*glsym_glRenderbufferStorageMultisample)(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height) = NULL; const char *(*glsym_glGetStringi) (GLenum name, GLuint index) = NULL; @@ -289,6 +290,8 @@ evas_gl_symbols(void *(*GetProcAddress)(const char *name)) FINDSYM(glsym_glUnmapBuffer, "glUnmapBufferEXT", NULL, glsym_func_boolean); } + FINDSYM(glsym_glRenderbufferStorageMultisample, "glRenderbufferStorageMultisample", NULL, glsym_func_void); + #ifdef GL_GLES // yes - gl core looking for egl stuff. i know it's odd. a reverse-layer thing // but it will work as the egl/glx layer calls gl core common stuff and thus @@ -489,15 +492,14 @@ matrix_ortho(GLfloat *m, m[15] = (m[3] * tx) + (m[7] * ty) + orth; } -static int -_evas_gl_common_version_check(int *gles_ver) +int +evas_gl_common_version_check(void) { char *version; char *tmp; char *tmp2; int major = 0; int minor = 0; - *gles_ver = 0; /* * glGetString returns a string describing the current GL connection. @@ -539,8 +541,7 @@ _evas_gl_common_version_check(int *gles_ver) if (strstr(version, "OpenGL ES 3")) { /* Supported */ - *gles_ver = 3; - return 1; + return 3; } /* OpenGL ES 2.* ? */ @@ -548,8 +549,7 @@ _evas_gl_common_version_check(int *gles_ver) if (strstr(version, "OpenGL ES ")) { /* Supported */ - *gles_ver = 2; - return 1; + return 2; } /* @@ -594,19 +594,16 @@ _evas_gl_common_version_check(int *gles_ver) { /* Map GL to GLES version: Refer http://en.wikipedia.org/wiki/OpenGL_ES */ if ((major >= 4) && (minor >= 3)) - *gles_ver = 3; + return 3; else if ((major > 3) || ((major == 3) && (minor >= 3))) /* >= 3.3 */ { const char *exts = NULL; int num = 0; + if (_has_ext("GL_ARB_ES3_compatibility", &exts, &num)) - *gles_ver = 3; - else - *gles_ver = 2; + return 3; } - else - *gles_ver = 2; /* emulated support */ - return 1; + return 2; /* emulated support */ } return 0; @@ -790,8 +787,9 @@ evas_gl_common_context_new(void) if (!glsym_glGetStringi) glsym_glGetStringi = dlsym(RTLD_DEFAULT, "glGetStringi"); - if (!_evas_gl_common_version_check(&gles_version)) - return NULL; + gles_version = evas_gl_common_version_check(); + if (!gles_version) return NULL; + gc = calloc(1, sizeof(Evas_Engine_GL_Context)); if (!gc) return NULL; diff --git a/src/modules/evas/engines/gl_common/evas_gl_core.c b/src/modules/evas/engines/gl_common/evas_gl_core.c index c81d8ec3a7..24e6a48b48 100644 --- a/src/modules/evas/engines/gl_common/evas_gl_core.c +++ b/src/modules/evas/engines/gl_common/evas_gl_core.c @@ -266,23 +266,25 @@ _texture_destroy(GLuint *tex) static void _texture_attach_2d(GLuint tex, GLenum attach, GLenum attach2, int samples, Evas_GL_Context_Version version) { - if (samples) + if (samples && (version == EVAS_GL_GLES_2_X)) { #ifdef GL_GLES - //<<< TODO : CHECK EXTENSION SUPPORT>>> - EXT_FUNC(glFramebufferTexture2DMultisample)(GL_FRAMEBUFFER, - attach, - GL_TEXTURE_2D, tex, - 0, samples); + if (EXT_FUNC(glFramebufferTexture2DMultisample)) + { + EXT_FUNC(glFramebufferTexture2DMultisample)(GL_FRAMEBUFFER, + attach, + GL_TEXTURE_2D, tex, + 0, samples); - if (attach2) - EXT_FUNC(glFramebufferTexture2DMultisample)(GL_FRAMEBUFFER, - attach2, - GL_TEXTURE_2D, tex, - 0, samples); -#else - ERR("MSAA not supported. Should not have come in here...!"); + if (attach2) + EXT_FUNC(glFramebufferTexture2DMultisample)(GL_FRAMEBUFFER, + attach2, + GL_TEXTURE_2D, tex, + 0, samples); + } + else #endif + ERR("MSAA not supported. Should not have come in here...!"); } else if (version == EVAS_GL_GLES_1_X) { @@ -435,17 +437,22 @@ _renderbuffer_allocate(GLuint buf, GLenum fmt, int w, int h, int samples) { glBindRenderbuffer(GL_RENDERBUFFER, buf); if (samples) + { + if (glsym_glRenderbufferStorageMultisample) + glsym_glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples, fmt, w, h); + else + { #ifdef GL_GLES - EXT_FUNC(glRenderbufferStorageMultisample)(GL_RENDERBUFFER, samples, fmt, w, h); -#else - ERR("MSAA not supported. Should not have come in here...!"); + if (EXT_FUNC(glRenderbufferStorageMultisample)) + EXT_FUNC(glRenderbufferStorageMultisample)(GL_RENDERBUFFER, samples, fmt, w, h); + else #endif + ERR("MSAA not supported. Should not have come in here...!"); + } + } else - glRenderbufferStorage(GL_RENDERBUFFER, fmt, w, h); + glRenderbufferStorage(GL_RENDERBUFFER, fmt, w, h); glBindRenderbuffer(GL_RENDERBUFFER, 0); - - return; - samples = 0; } static void @@ -487,17 +494,21 @@ _fbo_surface_cap_test(GLint color_ifmt, GLenum color_fmt, int depth_stencil = 0; int fb_status = 0; int w = 2, h = 2; // Test it with a simple (2,2) surface. Should I test it with NPOT? + Evas_GL_Context_Version ver = evas_gl_common_version_check(); // Gen FBO glGenFramebuffers(1, &fbo); glBindFramebuffer(GL_FRAMEBUFFER, fbo); + // FIXME: GLES 3 support for MSAA is NOT IMPLEMENTED! + // Needs to use RenderbufferStorageMultisample + FramebufferRenderbuffer + // Color Buffer Texture if ((color_ifmt) && (color_fmt)) { _texture_create(&color_buf); _texture_allocate_2d(color_buf, color_ifmt, color_fmt, GL_UNSIGNED_BYTE, w, h); - _texture_attach_2d(color_buf, GL_COLOR_ATTACHMENT0, 0, mult_samples, EVAS_GL_GLES_2_X); + _texture_attach_2d(color_buf, GL_COLOR_ATTACHMENT0, 0, mult_samples, ver); } // Check Depth_Stencil Format First @@ -882,8 +893,10 @@ error: static int _surface_cap_init(void *eng_data) { + int gles_version; int ret = 0; int max_size = 0; + int max_samples = 0; // Do internal make current if (!_internal_resource_make_current(eng_data, NULL, NULL)) @@ -899,11 +912,17 @@ _surface_cap_init(void *eng_data) evgl_engine->caps.max_h = max_size; DBG("Max Surface Width: %d Height: %d", evgl_engine->caps.max_w, evgl_engine->caps.max_h); - // Check for MSAA support -#ifdef GL_GLES - int max_samples = 0; + gles_version = evas_gl_common_version_check(); - if (EXTENSION_SUPPORT(IMG_multisampled_render_to_texture)) + // Check for MSAA support + if (gles_version == 3) + { + glGetIntegerv(GL_MAX_SAMPLES, &max_samples); + INF("MSAA support for GLES 3 is not implemented yet!"); + max_samples = 0; + } +#ifdef GL_GLES + else if (EXTENSION_SUPPORT(IMG_multisampled_render_to_texture)) { glGetIntegerv(GL_MAX_SAMPLES_IMG, &max_samples); } @@ -911,6 +930,16 @@ _surface_cap_init(void *eng_data) { glGetIntegerv(GL_MAX_SAMPLES_EXT, &max_samples); } + else + { + const char *exts = (const char *) glGetString(GL_EXTENSIONS); + + if (exts && strstr(exts, "EXT_multisampled_render_to_texture")) + glGetIntegerv(GL_MAX_SAMPLES_EXT, &max_samples); + else if (exts && strstr(exts, "IMG_multisampled_render_to_texture")) + glGetIntegerv(GL_MAX_SAMPLES_IMG, &max_samples); + } +#endif if (max_samples >= 2) { @@ -919,7 +948,6 @@ _surface_cap_init(void *eng_data) evgl_engine->caps.msaa_samples[2] = max_samples; evgl_engine->caps.msaa_supported = 1; } -#endif // Load Surface Cap if (!_surface_cap_cache_load()) @@ -1493,7 +1521,8 @@ try_again: if (cfg_index < 0) { - ERR("Unable to find a matching config format."); + ERR("Unable to find a matching config format (depth:%d, stencil:%d, msaa:%d)", + depth_size, stencil_bit, msaa_samples); if ((stencil_bit > 8) || (depth_size > 24)) { INF("Please note that Evas GL might not support 32-bit depth or " @@ -1508,6 +1537,13 @@ try_again: DBG("Fallback to depth:%d, stencil:%d", depth_size, stencil_bit); goto try_again; } + else if (msaa_samples > 0) + { + msaa_samples /= 2; + if (msaa_samples == 1) msaa_samples = 0; + DBG("Fallback to msaa:%d", msaa_samples); + goto try_again; + } return 0; } else