evas_tbm : Add more thread safety
authorJoogab Yun <joogab.yun@samsung.com>
Mon, 2 Jul 2018 02:46:00 +0000 (11:46 +0900)
committerShinwoo Kim <cinoo.kim@samsung.com>
Tue, 24 Jul 2018 05:17:24 +0000 (14:17 +0900)
Change-Id: I093469f2f081205f9fa633487313c5b9bded4521

src/modules/evas/engines/gl_tbm/evas_engine.h
src/modules/evas/engines/gl_tbm/evas_tbm_main.c

index e459ba4..b8ae825 100755 (executable)
@@ -62,7 +62,6 @@ struct _Outbuf
 
    void *tbm_queue;
    Eina_Bool ext_tbm_queue;
-   void *tbm_disp;
 
    Render_Output_Swap_Mode swap_mode;
    int prev_age, vsync;
index 1eebc8d..e3b5935 100755 (executable)
@@ -11,15 +11,95 @@ glsym_func_void glsym_evas_gl_common_context_restore_set = NULL;
 //
 
 /* local variables */
-static Outbuf *_evas_gl_wl_window = NULL;
-static EGLContext context = EGL_NO_CONTEXT;
+static Eina_TLS _outbuf_key = 0;
+static Eina_TLS _context_key = 0;
+static Eina_TLS _display_key = 0;
+
+typedef EGLContext GLContext;
 static int win_count = 0;
 static void _convert_glcoords(int *result, Outbuf *ob, int x, int y, int w, int h);
 
+static Eina_Bool initted = EINA_FALSE;
+
+Eina_Bool
+eng_init(void)
+{
+   if (initted)
+     return EINA_TRUE;
+
+#define LINK2GENERIC(sym) \
+   glsym_##sym = dlsym(RTLD_DEFAULT, #sym); \
+   if (!glsym_##sym) ERR("Could not find function '%s'", #sym);
+
+   LINK2GENERIC(evas_gl_common_context_restore_set);
+
+   // FIXME: These resources are never released
+   if (!eina_tls_new(&_outbuf_key))
+     goto error;
+   if (!eina_tls_new(&_context_key))
+     goto error;
+   if (!eina_tls_new(&_display_key))
+     goto error;
+
+   eina_tls_set(_outbuf_key, NULL);
+   eina_tls_set(_context_key, NULL);
+   eina_tls_set(_display_key, NULL);
+
+   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 *wl_win)
+{
+   if (!initted) eng_init();
+   return eina_tls_set(_outbuf_key, wl_win);
+}
+
+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);
+}
+
+static inline void*
+_tls_display_get(void)
+{
+   if (!initted) eng_init();
+   return eina_tls_get(_display_key);
+}
+
+static inline Eina_Bool
+_tls_display_set(void* disp)
+{
+   if (!initted) eng_init();
+   return eina_tls_set(_display_key, disp);
+}
+
 Outbuf *
 eng_window_new(Evas_Engine_Info_GL_Tbm *einfo, int w, int h, Render_Output_Swap_Mode swap_mode)
 {
    Outbuf *gw;
+   GLContext context;
    int context_attrs[3];
    int config_attrs[40];
    int major_version, minor_version;
@@ -88,8 +168,13 @@ eng_window_new(Evas_Engine_Info_GL_Tbm *einfo, int w, int h, Render_Output_Swap_
     */
 
    setenv("EGL_PLATFORM", "tbm", 1);
-   gw->tbm_disp = tbm_dummy_display_create();
-   gw->egl_disp = eglGetDisplay((EGLNativeDisplayType)gw->tbm_disp);
+   void* tbm_disp = _tls_display_get();
+   if (tbm_disp == NULL)
+     {
+       tbm_disp = tbm_dummy_display_create();
+       _tls_display_set(tbm_disp);
+     }
+   gw->egl_disp = eglGetDisplay((EGLNativeDisplayType)tbm_disp);
 //   gw->egl_disp = eglGetDisplay((EGLNativeDisplayType)tbm_bufmgr_init(-1));
    if (!gw->egl_disp)
      {
@@ -130,6 +215,7 @@ eng_window_new(Evas_Engine_Info_GL_Tbm *einfo, int w, int h, Render_Output_Swap_
         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)
@@ -139,7 +225,8 @@ eng_window_new(Evas_Engine_Info_GL_Tbm *einfo, int w, int h, Render_Output_Swap_
         return NULL;
      }
 
-   if (context == EGL_NO_CONTEXT) context = gw->egl_context[0];
+   if (context == EGL_NO_CONTEXT)
+     _tls_context_set(gw->egl_context[0]);
 
    SET_RESTORE_CONTEXT();
    if (eglMakeCurrent(gw->egl_disp, gw->egl_surface[0],
@@ -216,13 +303,18 @@ eng_window_new(Evas_Engine_Info_GL_Tbm *einfo, int w, int h, Render_Output_Swap_
 void
 eng_window_free(Outbuf *gw)
 {
+   Outbuf *wl_win;
+   GLContext context;
    int ref = 0;
 
+   if (!gw) return;
    win_count--;
    eng_window_use(gw);
 
-   if (gw == _evas_gl_wl_window) _evas_gl_wl_window = NULL;
+   context = _tls_context_get();
+   wl_win = _tls_outbuf_get();
 
+   if (gw == wl_win) _tls_outbuf_set(NULL);
    if (gw->gl_context)
      {
         ref = gw->gl_context->references - 1;
@@ -243,9 +335,15 @@ eng_window_free(Outbuf *gw)
      {
         if (context) eglDestroyContext(gw->egl_disp, context);
         eglTerminate(gw->egl_disp);
-        tbm_dummy_display_destroy(gw->tbm_disp);
         eglReleaseThread();
-        context = EGL_NO_CONTEXT;
+
+        void* tbm_disp = _tls_display_get();
+        if (tbm_disp)
+          {
+            tbm_dummy_display_destroy(tbm_disp);
+            _tls_display_set(NULL);
+          }
+        _tls_context_set(EGL_NO_CONTEXT);
      }
 
    free(gw);
@@ -255,25 +353,28 @@ void
 eng_window_use(Outbuf *gw)
 {
    Eina_Bool force = EINA_FALSE;
+   Outbuf *wl_win;
+
+   wl_win = _tls_outbuf_get();
 
    glsym_evas_gl_preload_render_lock(eng_preload_make_current, gw);
 
-   if (_evas_gl_wl_window)
+   if (wl_win)
      {
-        if ((eglGetCurrentContext() != _evas_gl_wl_window->egl_context[0])
-            || (eglGetCurrentDisplay() != _evas_gl_wl_window->egl_disp))
+        if ((eglGetCurrentContext() != wl_win->egl_context[0])
+            || (eglGetCurrentDisplay() != wl_win->egl_disp))
           force = EINA_TRUE;
      }
 
-   if ((_evas_gl_wl_window != gw) || (force))
+   if ((wl_win != gw) || (force))
      {
-        if (_evas_gl_wl_window)
+        if (wl_win)
           {
-             glsym_evas_gl_common_context_use(_evas_gl_wl_window->gl_context);
-             glsym_evas_gl_common_context_flush(_evas_gl_wl_window->gl_context);
+             glsym_evas_gl_common_context_use(wl_win->gl_context);
+             glsym_evas_gl_common_context_flush(wl_win->gl_context);
           }
 
-        _evas_gl_wl_window = gw;
+        _tls_outbuf_set(gw);
 
         if (gw)
           {
@@ -302,10 +403,13 @@ eng_window_unsurf(Outbuf *gw)
    if (!getenv("EVAS_GL_WIN_RESURF")) return;
    if (getenv("EVAS_GL_INFO")) printf("unsurf %p\n", gw);
 
-   if (_evas_gl_wl_window)
-     glsym_evas_gl_common_context_flush(_evas_gl_wl_window->gl_context);
+   Outbuf *wl_win;
+
+   wl_win = _tls_outbuf_get();
+   if (wl_win)
+     glsym_evas_gl_common_context_flush(wl_win->gl_context);
 
-   if (_evas_gl_wl_window == gw)
+   if (wl_win == gw)
      {
         SET_RESTORE_CONTEXT();
         eglMakeCurrent(gw->egl_disp, EGL_NO_SURFACE,
@@ -314,7 +418,7 @@ eng_window_unsurf(Outbuf *gw)
           eglDestroySurface(gw->egl_disp, gw->egl_surface[0]);
         gw->egl_surface[0] = EGL_NO_SURFACE;
 
-        _evas_gl_wl_window = NULL;
+        _tls_outbuf_set(NULL);
      }
 
    gw->surf = EINA_FALSE;
@@ -555,6 +659,8 @@ eng_outbuf_flush(Outbuf *ob, Tilebuf_Rect *surface_damage, Tilebuf_Rect *buffer_
 Evas_Engine_GL_Context *
 eng_outbuf_gl_context_get(Outbuf *ob)
 {
+   if (!ob) return NULL;
+
    return ob->gl_context;
 }