Evas GL common: Create OpenGL ES 3.x contexts by default
authorJean-Philippe Andre <jp.andre@samsung.com>
Thu, 5 Mar 2015 10:21:24 +0000 (19:21 +0900)
committerJean-Philippe Andre <jp.andre@samsung.com>
Thu, 5 Mar 2015 11:59:53 +0000 (20:59 +0900)
Automatically fallback to OpenGL ES 2.0 if OpenGL ES 3 is not supported.
This is a first step in trying to support GLES 3 for Evas GL.

This commit is also a wild test to see whether using GLES 3 contexts
by default will break anything. The theory says that GLES 3 is
backwards compatible with GLESv2.

So, if anything GL breaks for you... scream loudly!
But before reporting any bugs, please set the env variable:
- export EVAS_GL_DISABLE_GLES3=1

This does not add any requirement for GLESv3 support.

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_x11/evas_engine.c
src/modules/evas/engines/gl_x11/evas_engine.h
src/modules/evas/engines/gl_x11/evas_x_main.c

index 24e926f..c0f3c97 100644 (file)
@@ -515,6 +515,7 @@ struct _Evas_Engine_GL_Context
 #endif
 
    GLuint preserve_bit;
+   int gles_version;
 };
 
 struct _Evas_GL_Texture_Pool
index b925d36..3f47cb6 100644 (file)
@@ -337,13 +337,14 @@ matrix_ortho(GLfloat *m,
 }
 
 static int
-_evas_gl_common_version_check()
+_evas_gl_common_version_check(int *gles_ver)
 {
    char *version;
    char *tmp;
    char *tmp2;
    int major = 0;
    int minor = 0;
+   *gles_ver = 0;
 
   /*
    * glGetString returns a string describing the current GL connection.
@@ -375,11 +376,21 @@ _evas_gl_common_version_check()
         return 0;
      }
 
+   /* OpenGL ES 3.*  */
+
+   if (strstr(version, "OpenGL ES 3"))
+     {
+        /* Supported */
+        *gles_ver = 3;
+        return 1;
+     }
+
    /* OpenGL ES 2.* ? */
 
    if (strstr(version, "OpenGL ES "))
      {
         /* Supported */
+        *gles_ver = 2;
         return 1;
      }
 
@@ -422,7 +433,14 @@ _evas_gl_common_version_check()
    free(version);
 
    if (((major == 1) && (minor >= 4)) || (major >= 2))
-     return 1;
+     {
+        /* Map GL to GLES version: Refer http://en.wikipedia.org/wiki/OpenGL_ES */
+        if ((major >=4 ) && (minor >= 3))
+          *gles_ver = 3;
+        else
+          *gles_ver = 2;
+        return 1;
+     }
 
    return 0;
 }
@@ -579,7 +597,7 @@ evas_gl_common_context_new(void)
 {
    Evas_Engine_GL_Context *gc;
    const char *s;
-   int i;
+   int i, gles_version;
 
 #if 1
    if (_evas_gl_common_context)
@@ -588,12 +606,13 @@ evas_gl_common_context_new(void)
         return _evas_gl_common_context;
      }
 #endif
-   if (!_evas_gl_common_version_check())
+   if (!_evas_gl_common_version_check(&gles_version))
      return NULL;
    gc = calloc(1, sizeof(Evas_Engine_GL_Context));
    if (!gc) return NULL;
 
    tbm_symbols();
+   gc->gles_version = gles_version;
 
    gc->references = 1;
 
index 6bda8ea..0f5ae53 100644 (file)
@@ -479,6 +479,9 @@ evgl_eng_context_create(void *data, void *share_ctx, Evas_GL_Context_Version ver
    EGLContext context = EGL_NO_CONTEXT;
    int context_attrs[3];
 
+   if (eng_get_ob(re)->gles3 && (version >= EVAS_GL_GLES_2_X))
+     version = 3;
+
    context_attrs[0] = EGL_CONTEXT_CLIENT_VERSION;
    context_attrs[1] = version;
    context_attrs[2] = EGL_NONE;
@@ -698,7 +701,10 @@ evgl_eng_pbuffer_surface_create(void *data, EVGL_Surface *sfc,
      }
 
    config_attrs[i++] = EGL_RENDERABLE_TYPE;
-   config_attrs[i++] = EGL_OPENGL_ES2_BIT;
+   if (eng_get_ob(re)->gles3)
+     config_attrs[i++] = EGL_OPENGL_ES3_BIT_KHR;
+   else
+     config_attrs[i++] = EGL_OPENGL_ES2_BIT;
    config_attrs[i++] = EGL_SURFACE_TYPE;
    config_attrs[i++] = EGL_PBUFFER_BIT;
    config_attrs[i++] = EGL_NONE;
@@ -2239,7 +2245,10 @@ eng_image_native_set(void *data, void *image, void *native)
               config_attrs[i++] = EGL_STENCIL_SIZE;
               config_attrs[i++] = 0;
               config_attrs[i++] = EGL_RENDERABLE_TYPE;
-              config_attrs[i++] = EGL_OPENGL_ES2_BIT;
+              if (eng_get_ob(re)->gles3)
+                config_attrs[i++] = EGL_OPENGL_ES3_BIT_KHR;
+              else
+                config_attrs[i++] = EGL_OPENGL_ES2_BIT;
               config_attrs[i++] = EGL_SURFACE_TYPE;
               config_attrs[i++] = EGL_PIXMAP_BIT;
               config_attrs[i++] = EGL_NONE;
index 347c41f..114ea6e 100644 (file)
@@ -65,6 +65,7 @@ struct _Outbuf
    EGLSurface       egl_surface[2];
    EGLConfig        egl_config;
    EGLDisplay       egl_disp;
+   Eina_Bool        gles3 : 1;
 #else
    GLXContext       context;
    GLXWindow        glxwin;
index 7cad2e6..767f580 100644 (file)
@@ -7,6 +7,7 @@ static Eina_TLS _context_key = 0;
 typedef EGLContext GLContext;
 static EGLConfig fbconf = 0;
 static EGLConfig rgba_fbconf = 0;
+static Eina_Bool gles3_supported = EINA_FALSE;
 #else
 // FIXME: this will only work for 1 display connection (glx land can have > 1)
 typedef GLXContext GLContext;
@@ -158,10 +159,7 @@ eng_window_new(Evas_Engine_Info_GL_X11 *info,
 
 // EGL / GLES
 #ifdef GL_GLES
-   context_attrs[0] = EGL_CONTEXT_CLIENT_VERSION;
-   context_attrs[1] = 2;
-   context_attrs[2] = EGL_NONE;
-
+   gw->gles3 = gles3_supported;
    gw->egl_disp = eglGetDisplay((EGLNativeDisplayType)(gw->disp));
    if (!gw->egl_disp)
      {
@@ -197,13 +195,25 @@ eng_window_new(Evas_Engine_Info_GL_X11 *info,
         eng_window_free(gw);
         return NULL;
      }
-   
+
+try_gles2:
+   context_attrs[0] = EGL_CONTEXT_CLIENT_VERSION;
+   context_attrs[1] = gw->gles3 ? 3 : 2;
+   context_attrs[2] = EGL_NONE;
+
    context = _tls_context_get();
    gw->egl_context[0] = eglCreateContext
      (gw->egl_disp, gw->egl_config, context, context_attrs);
    if (gw->egl_context[0] == EGL_NO_CONTEXT)
      {
         ERR("eglCreateContext() fail. code=%#x", eglGetError());
+        if (gw->gles3)
+          {
+             /* Note: this shouldn't happen */
+             ERR("Trying again with an Open GL ES 2 context (fallback).");
+             gw->gles3 = EINA_FALSE;
+             goto try_gles2;
+          }
         eng_window_free(gw);
         return NULL;
      }
@@ -687,11 +697,46 @@ eng_best_visual_get(Evas_Engine_Info_GL_X11 *einfo)
         EGLDisplay *egl_disp;
         EGLConfig configs[200];
         int major_version, minor_version;
+        const char *eglexts, *s;
 
         egl_disp = eglGetDisplay((EGLNativeDisplayType)(einfo->info.display));
         if (!egl_disp) return NULL;
         if (!eglInitialize(egl_disp, &major_version, &minor_version)) return NULL;
 
+        eglexts = eglQueryString(egl_disp, EGL_EXTENSIONS);
+        if (eglexts && strstr(eglexts, "EGL_KHR_create_context"))
+          {
+             int k, numconfigs = 0, value;
+             EGLConfig *eglconfigs;
+
+             if (eglGetConfigs(egl_disp, NULL, 0, &numconfigs) &&
+                 (numconfigs > 0))
+               {
+                  eglconfigs = alloca(numconfigs * sizeof(EGLConfig));
+                  eglGetConfigs(egl_disp, eglconfigs, numconfigs, &numconfigs);
+                  for (k = 0; k < numconfigs; k++)
+                    {
+                       value = 0;
+                       if (eglGetConfigAttrib(egl_disp, eglconfigs[k], EGL_RENDERABLE_TYPE, &value) &&
+                           ((value & EGL_OPENGL_ES3_BIT_KHR) != 0) &&
+                           eglGetConfigAttrib(egl_disp, eglconfigs[k], EGL_SURFACE_TYPE, &value) &&
+                           ((value & EGL_WINDOW_BIT) != 0))
+                         {
+                            INF("OpenGL ES 3.x is supported!");
+                            gles3_supported = EINA_TRUE;
+                            break;
+                         }
+                    }
+               }
+          }
+
+        if (gles3_supported &&
+            (!(s = getenv("EVAS_GL_DISABLE_GLES3")) || (atoi(s) != 1)))
+          {
+             INF("Disabling OpenGL ES 3.x support.");
+             gles3_supported = EINA_FALSE;
+          }
+
         for (alpha = 0; alpha < 2; alpha++)
           {
              Eina_Bool found;
@@ -703,7 +748,10 @@ eng_best_visual_get(Evas_Engine_Info_GL_X11 *einfo)
              config_attrs[n++] = EGL_SURFACE_TYPE;
              config_attrs[n++] = EGL_WINDOW_BIT;
              config_attrs[n++] = EGL_RENDERABLE_TYPE;
-             config_attrs[n++] = EGL_OPENGL_ES2_BIT;
+             if (gles3_supported)
+               config_attrs[n++] = EGL_OPENGL_ES3_BIT_KHR;
+             else
+               config_attrs[n++] = EGL_OPENGL_ES2_BIT;
 # if 0
              // FIXME: n900 - omap3 sgx libs break here
              config_attrs[n++] = EGL_RED_SIZE;
@@ -1007,6 +1055,8 @@ eng_gl_context_new(Outbuf *win)
    if (!ctx) return NULL;
 
 #if GL_GLES
+   if (win->gles3)
+     context_attrs[1] = 3;
    ctx->context = eglCreateContext(win->egl_disp, win->egl_config,
                                    win->egl_context[0], context_attrs);