From ee9eff875f685b806e909afb86290b5d020b6469 Mon Sep 17 00:00:00 2001 From: "Wonsik, Jung" Date: Wed, 12 Apr 2017 13:11:52 +0900 Subject: [PATCH] [EvasGL] Add more thread safety to wayland egl This patch is for thread safety to wayland egl backend It is oriented by "Add more thread safety to gl_x11"(author:JPEG) Change-Id: I121d3aa68ed110e9c5f4eb0a3dfb5ade0335fa2d --- .../evas/engines/wayland_egl/evas_wl_main.c | 125 ++++++++++++++++----- 1 file changed, 97 insertions(+), 28 deletions(-) diff --git a/src/modules/evas/engines/wayland_egl/evas_wl_main.c b/src/modules/evas/engines/wayland_egl/evas_wl_main.c index 8ffa75a..ec2c46a 100644 --- a/src/modules/evas/engines/wayland_egl/evas_wl_main.c +++ b/src/modules/evas/engines/wayland_egl/evas_wl_main.c @@ -10,15 +10,77 @@ 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; + +typedef EGLContext GLContext; static int win_count = 0; +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; + + eina_tls_set(_outbuf_key, NULL); + eina_tls_set(_context_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); +} + Outbuf * _orig_eng_window_new(Evas *evas, Evas_Engine_Info_Wayland_Egl *einfo, int w, int h, Render_Engine_Swap_Mode swap_mode, int depth_bits, int stencil_bits, int msaa_bits) { Outbuf *gw; + GLContext context; int context_attrs[3]; int config_attrs[40]; int major_version, minor_version; @@ -30,16 +92,6 @@ _orig_eng_window_new(Evas *evas, Evas_Engine_Info_Wayland_Egl *einfo, int w, int /* try to allocate space for our window */ if (!(gw = calloc(1, sizeof(Outbuf)))) return NULL; -// TIZEN_ONLY(20160425): Fix linking to 'context_restore_set' -#define LINK2GENERIC(sym) \ - do { \ - if (!glsym_##sym) {\ - glsym_##sym = dlsym(RTLD_DEFAULT, #sym); \ - if (!glsym_##sym) ERR("Could not find function '%s'", #sym); }\ - } while(0) - - LINK2GENERIC(evas_gl_common_context_restore_set); -// win_count++; gw->info = einfo; @@ -174,6 +226,7 @@ _orig_eng_window_new(Evas *evas, Evas_Engine_Info_Wayland_Egl *einfo, int w, int DBG("PreRotation is invalid!!"); } + 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) @@ -183,7 +236,8 @@ _orig_eng_window_new(Evas *evas, Evas_Engine_Info_Wayland_Egl *einfo, int w, int 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_thread_cmd(gw->egl_disp, gw->egl_surface[0], @@ -256,13 +310,17 @@ _orig_eng_window_new(Evas *evas, Evas_Engine_Info_Wayland_Egl *einfo, int w, int void eng_window_free(Outbuf *gw) { + Outbuf *wl_win; + GLContext context; int ref = 0; 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; @@ -286,7 +344,7 @@ eng_window_free(Outbuf *gw) if (context) eglDestroyContext(gw->egl_disp, context); eglTerminate(gw->egl_disp); eglReleaseThread_thread_cmd(); - context = EGL_NO_CONTEXT; + _tls_context_set(EGL_NO_CONTEXT); } free(gw); @@ -366,26 +424,34 @@ 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_thread_cmd() != _evas_gl_wl_window->egl_context[0]) - || (eglGetCurrentDisplay_thread_cmd() != _evas_gl_wl_window->egl_disp)) + if ((eglGetCurrentDisplay_thread_cmd() != + wl_win->egl_disp) || + (eglGetCurrentContext_thread_cmd() != + wl_win->egl_context[0]) + || (eglGetCurrentSurface_thread_cmd(EGL_READ) != + wl_win->egl_surface[0]) + || (eglGetCurrentSurface_thread_cmd(EGL_DRAW) != + wl_win->egl_surface[0])) 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) { if (gw->egl_surface[0] != EGL_NO_SURFACE) @@ -413,10 +479,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_thread_cmd(gw->egl_disp, EGL_NO_SURFACE, @@ -425,7 +494,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; -- 2.7.4