jpeg pushed a commit to branch master.

http://git.enlightenment.org/core/efl.git/commit/?id=68ca82e83f4cd69f3772d5554486b1856d830f1a

commit 68ca82e83f4cd69f3772d5554486b1856d830f1a
Author: Jean-Philippe Andre <[email protected]>
Date:   Mon Sep 1 19:40:07 2014 +0900

    Evas GL: Add more thread safety to gl_x11
---
 src/modules/evas/engines/gl_x11/evas_x_main.c | 175 +++++++++++++++++++++-----
 1 file changed, 143 insertions(+), 32 deletions(-)

diff --git a/src/modules/evas/engines/gl_x11/evas_x_main.c 
b/src/modules/evas/engines/gl_x11/evas_x_main.c
index 18ed377..ebb5bcf 100644
--- a/src/modules/evas/engines/gl_x11/evas_x_main.c
+++ b/src/modules/evas/engines/gl_x11/evas_x_main.c
@@ -1,13 +1,14 @@
 #include "evas_engine.h"
 
-static Outbuf *_evas_gl_x11_window = NULL;
+static Eina_TLS _outbuf_key = 0;
+static Eina_TLS _context_key = 0;
 
 #ifdef GL_GLES
-static EGLContext context = EGL_NO_CONTEXT;
+typedef EGLContext GLContext;
 #else
 // FIXME: this will only work for 1 display connection (glx land can have > 1)
-static GLXContext context = 0;
-static GLXContext rgba_context = 0;
+typedef GLXContext GLContext;
+static Eina_TLS _rgba_context_key = 0;
 static GLXFBConfig fbconf = 0;
 static GLXFBConfig rgba_fbconf = 0;
 #endif
@@ -21,6 +22,80 @@ static Colormap     _evas_gl_x11_cmap = 0;
 static Colormap     _evas_gl_x11_rgba_cmap = 0;
 
 static int win_count = 0;
+static Eina_Bool initted = EINA_FALSE;
+
+Eina_Bool
+eng_init(void)
+{
+   if (initted)
+     return EINA_TRUE;
+
+   // FIXME: These resources are never released
+   if (!eina_tls_new(&_outbuf_key))
+     goto error;
+   if (!eina_tls_new(&_context_key))
+     goto error;
+
+   eina_tls_set(_outbuf_key, NULL);
+   eina_tls_set(_context_key, NULL);
+
+#ifndef GL_GLES
+   if (!eina_tls_new(&_rgba_context_key))
+     goto error;
+   eina_tls_set(_rgba_context_key, NULL);
+#endif
+
+   initted = EINA_TRUE;
+   return EINA_TRUE;
+
+error:
+   ERR("Could not create TLS key!");
+   return EINA_FALSE;
+}
+
+static inline Outbuf *
+tls_outbuf_get(void)
+{
+   if (!initted) eng_init();
+   return eina_tls_get(_outbuf_key);
+}
+
+static inline Eina_Bool
+_tls_Outbuf_set(Outbuf *xwin)
+{
+   if (!initted) eng_init();
+   return eina_tls_set(_outbuf_key, xwin);
+}
+
+static inline GLContext
+_tls_context_get(void)
+{
+   if (!initted) eng_init();
+   return eina_tls_get(_context_key);
+}
+
+static inline Eina_Bool
+_tls_context_set(GLContext ctx)
+{
+   if (!initted) eng_init();
+   return eina_tls_set(_context_key, ctx);
+}
+
+#ifndef GL_GLES
+static inline GLXContext
+_tls_rgba_context_get(void)
+{
+   if (!initted) eng_init();
+   return eina_tls_get(_rgba_context_key);
+}
+
+static inline Eina_Bool
+_tls_rgba_context_set(GLXContext ctx)
+{
+   if (!initted) eng_init();
+   return eina_tls_set(_rgba_context_key, ctx);
+}
+#endif
 
 Outbuf *
 eng_window_new(Evas_Engine_Info_GL_X11 *info,
@@ -38,11 +113,16 @@ eng_window_new(Evas_Engine_Info_GL_X11 *info,
                Render_Engine_Swap_Mode swap_mode)
 {
    Outbuf *gw;
+   GLContext context;
 #ifdef GL_GLES
    int context_attrs[3];
    int config_attrs[40];
    int major_version, minor_version;
    int num_config, n = 0;
+#else
+# ifdef NEWGL
+   GLXContext rgbactx;
+# endif
 #endif
    const GLubyte *vendor, *renderer, *version;
    int blacklist = 0;
@@ -140,6 +220,7 @@ eng_window_new(Evas_Engine_Info_GL_X11 *info,
         return NULL;
      }
    
+   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)
@@ -148,7 +229,8 @@ eng_window_new(Evas_Engine_Info_GL_X11 *info,
         eng_window_free(gw);
         return NULL;
      }
-   if (context == EGL_NO_CONTEXT) context = gw->egl_context[0];
+   if (context == EGL_NO_CONTEXT)
+     _tls_context_set(gw->egl_context[0]);
    
    if (eglMakeCurrent(gw->egl_disp,
                       gw->egl_surface[0],
@@ -193,6 +275,7 @@ eng_window_new(Evas_Engine_Info_GL_X11 *info,
      }
 // GLX
 #else
+   context = _tls_context_get();
    if (!context)
      {
 #ifdef NEWGL
@@ -212,16 +295,18 @@ eng_window_new(Evas_Engine_Info_GL_X11 *info,
 #endif
      }
 #ifdef NEWGL
-   if ((gw->alpha) && (!rgba_context))
+   rgbactx = _tls_rgba_context_get();
+   if ((gw->alpha) && (!rgbactx))
      {
         if (indirect)
-          rgba_context = glXCreateNewContext(gw->disp, rgba_fbconf,
-                                             GLX_RGBA_TYPE, context,
-                                             GL_FALSE);
+          rgbactx = glXCreateNewContext(gw->disp, rgba_fbconf,
+                                        GLX_RGBA_TYPE, context,
+                                        GL_FALSE);
         else
-          rgba_context = glXCreateNewContext(gw->disp, rgba_fbconf,
-                                             GLX_RGBA_TYPE, context,
-                                             GL_TRUE);
+          rgbactx = glXCreateNewContext(gw->disp, rgba_fbconf,
+                                        GLX_RGBA_TYPE, context,
+                                        GL_TRUE);
+        _tls_rgba_context_set(rgbactx);
      }
    if (gw->alpha)
      gw->glxwin = glXCreateWindow(gw->disp, rgba_fbconf, gw->win, NULL);
@@ -234,7 +319,7 @@ eng_window_new(Evas_Engine_Info_GL_X11 *info,
         return NULL;
      }
 
-   if (gw->alpha) gw->context = rgba_context;
+   if (gw->alpha) gw->context = rgbactx;
    else gw->context = context;
 #else
    gw->context = context;
@@ -404,10 +489,16 @@ eng_window_new(Evas_Engine_Info_GL_X11 *info,
 void
 eng_window_free(Outbuf *gw)
 {
+   Outbuf *xwin;
+   GLContext context;
    int ref = 0;
    win_count--;
    eng_window_use(gw);
-   if (gw == _evas_gl_x11_window) _evas_gl_x11_window = NULL;
+
+   context = _tls_context_get();
+   xwin = tls_outbuf_get();
+
+   if (gw == xwin) _tls_Outbuf_set(NULL);
    if (gw->gl_context)
      {
         ref = gw->gl_context->references - 1;
@@ -417,6 +508,8 @@ eng_window_free(Outbuf *gw)
    eglMakeCurrent(gw->egl_disp, EGL_NO_SURFACE, EGL_NO_SURFACE, 
EGL_NO_CONTEXT);
    if (gw->egl_surface[0] != EGL_NO_SURFACE)
       eglDestroySurface(gw->egl_disp, gw->egl_surface[0]);
+   if (gw->egl_surface[1] != EGL_NO_SURFACE)
+      eglDestroySurface(gw->egl_disp, gw->egl_surface[1]);
    if (gw->egl_context[0] != context)
      eglDestroyContext(gw->egl_disp, gw->egl_context[0]);
    if (ref == 0)
@@ -424,7 +517,7 @@ eng_window_free(Outbuf *gw)
         if (context) eglDestroyContext(gw->egl_disp, context);
         eglTerminate(gw->egl_disp);
         eglReleaseThread();
-        context = EGL_NO_CONTEXT;
+        _tls_context_set(EGL_NO_CONTEXT);
      }
 #else
    if (gw->glxwin)
@@ -434,15 +527,16 @@ eng_window_free(Outbuf *gw)
      }
    if (ref == 0)
      {
+        GLXContext rgbactx = _tls_rgba_context_get();
         if (!gw->glxwin)
           {
              if (glXGetCurrentContext() == gw->context)
                glXMakeCurrent(gw->disp, 0, NULL);
           }
         if (context) glXDestroyContext(gw->disp, context);
-        if (rgba_context) glXDestroyContext(gw->disp, rgba_context);
-        context = 0;
-        rgba_context = 0;
+        if (rgbactx) glXDestroyContext(gw->disp, rgbactx);
+        _tls_context_set(0);
+        _tls_rgba_context_set(0);
         fbconf = 0;
         rgba_fbconf = 0;
      }
@@ -504,29 +598,39 @@ void
 eng_window_use(Outbuf *gw)
 {
    Eina_Bool force_use = EINA_FALSE;
+   Outbuf *xwin;
+
+   xwin = tls_outbuf_get();
 
    glsym_evas_gl_preload_render_lock(eng_window_make_current, gw);
 #ifdef GL_GLES
-   if (_evas_gl_x11_window)
+   if (xwin)
      {
-        if (eglGetCurrentContext() != _evas_gl_x11_window->egl_context[0])
-           force_use = EINA_TRUE;
+        if ((eglGetCurrentDisplay() !=
+             xwin->egl_disp) ||
+            (eglGetCurrentContext() !=
+             xwin->egl_context[0]) ||
+            (eglGetCurrentSurface(EGL_READ) !=
+             xwin->egl_surface[xwin->offscreen]) ||
+            (eglGetCurrentSurface(EGL_DRAW) !=
+             xwin->egl_surface[xwin->offscreen]))
+          force_use = EINA_TRUE;
      }
 #else
-   if (_evas_gl_x11_window)
+   if (xwin)
      {
-        if (glXGetCurrentContext() != _evas_gl_x11_window->context)
+        if (glXGetCurrentContext() != xwin->context)
            force_use = EINA_TRUE;
      }
 #endif
-   if ((_evas_gl_x11_window != gw) || (force_use))
+   if ((xwin != gw) || (force_use))
      {
-        if (_evas_gl_x11_window)
+        if (xwin)
           {
-             glsym_evas_gl_common_context_use(_evas_gl_x11_window->gl_context);
-             
glsym_evas_gl_common_context_flush(_evas_gl_x11_window->gl_context);
+             glsym_evas_gl_common_context_use(xwin->gl_context);
+             glsym_evas_gl_common_context_flush(xwin->gl_context);
           }
-        _evas_gl_x11_window = gw;
+        _tls_Outbuf_set(gw);
         if (gw)
           {
 // EGL / GLES
@@ -571,16 +675,23 @@ eng_window_unsurf(Outbuf *gw)
    if (!getenv("EVAS_GL_WIN_RESURF")) return;
    if (getenv("EVAS_GL_INFO"))
       printf("unsurf %p\n", gw);
+
 #ifdef GL_GLES
-   if (_evas_gl_x11_window)
-      glsym_evas_gl_common_context_flush(_evas_gl_x11_window->gl_context);
-   if (_evas_gl_x11_window == gw)
+   Outbuf *xwin;
+
+   xwin = _tls_Outbuf_get();
+   if (xwin)
+      evas_gl_common_context_flush(xwin->gl_context);
+   if (xwin == gw)
      {
         eglMakeCurrent(gw->egl_disp, EGL_NO_SURFACE, EGL_NO_SURFACE, 
EGL_NO_CONTEXT);
         if (gw->egl_surface[0] != EGL_NO_SURFACE)
            eglDestroySurface(gw->egl_disp, gw->egl_surface[0]);
         gw->egl_surface[0] = EGL_NO_SURFACE;
-        _evas_gl_x11_window = NULL;
+        if (gw->egl_surface[1] != EGL_NO_SURFACE)
+           eglDestroySurface(gw->egl_disp, gw->egl_surface[1]);
+        gw->egl_surface[1] = EGL_NO_SURFACE;
+        _tls_Outbuf_set(NULL);
      }
 #else
    if (gw->glxwin)

-- 


Reply via email to