evas gl: Partially fix MSAA for GLES 3 drivers
authorJean-Philippe Andre <jp.andre@samsung.com>
Mon, 13 Feb 2017 08:42:10 +0000 (17:42 +0900)
committerJean-Philippe Andre <jp.andre@samsung.com>
Mon, 13 Feb 2017 11:11:22 +0000 (20:11 +0900)
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!

src/modules/evas/engines/gl_common/evas_gl_common.h
src/modules/evas/engines/gl_common/evas_gl_context.c
src/modules/evas/engines/gl_common/evas_gl_core.c

index 5a10fd5..59549ef 100644 (file)
@@ -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);
index 602dac4..3d984e7 100644 (file)
@@ -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;
 
index c81d8ec..24e6a48 100644 (file)
@@ -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 (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 (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
 #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);
 
+   gles_version = evas_gl_common_version_check();
+
    // 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
-   int max_samples = 0;
-
-   if (EXTENSION_SUPPORT(IMG_multisampled_render_to_texture))
+   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