[PATCH] evas/wayland_egl: Fix segfault when doing alpha setting in elementary.

cpmichael1 at comcast.net cpmichael1 at comcast.net
Mon Jul 16 13:18:57 PDT 2012


Alex,

Thanks for the patch :) After a preliminary glance, it seems ok however I will not be able to commit this until I have had time to test it. I am currently engaged with a few other projects at work so it may be some time before I can get to this :( but I will save it in my TODO list and get to it as soon as I can.

Thanks again :)
devilhorns


----- Original Message -----
From: "zhiwen wu" <zhiwen.wu at linux.intel.com>
To: enlightenment-devel at lists.sourceforge.net
Cc: "Alex Wu" <zhiwen.wu at linux.intel.com>, devilhorns at comcast.net, wayland-devel at lists.freedesktop.org
Sent: Monday, July 16, 2012 9:51:44 AM
Subject: [PATCH] evas/wayland_egl: Fix segfault when doing alpha setting in	elementary.

From: Alex Wu <zhiwen.wu at linux.intel.com>

The current wayland_egl engine uses a global singleton EGLContext
object to render context. All Evas_GL_Wl_Window objects, which
wraps EGLSurface, share this object, so we have no chance to
differentiate the frame buffer configuration for each EGLSurface.

When calling elm_win_alpha_set(), the global EGLContext object keep
unchanged, but the new EGLSurface object subjects to the new EGLConfig
with changed alpha_size. This makes eng_window_new() failed and hence
free the  Render_Engine object (e->engine.data.output) and nullize it.
Next time other objects reference the output, segfault occurs.

In this patch, I give every Evas_GL_Wl_Window object a EGLContext object
and all these EGLContext objects share the same shader program objects.
A new global EGLContext object "share_context" added, which is
responsible for keeping the shared objects alive. e.g. shader program
objects. In eng_setup, should create the new window before free the old
one, that will keep the "share_context" avaliable for next calling of
eng_window_new(). The "share_context" will be taken as the 3rd argument
when calling eglCreateContext(), and then updated to the new created
EGLContext to keep the shared gl objects available.
---
 .../src/modules/engines/wayland_egl/evas_engine.c  |   41 ++++++++++++--------
 .../src/modules/engines/wayland_egl/evas_wl_main.c |   23 ++++++-----
 2 files changed, 39 insertions(+), 25 deletions(-)

diff --git a/trunk/evas/src/modules/engines/wayland_egl/evas_engine.c b/trunk/evas/src/modules/engines/wayland_egl/evas_engine.c
index 7dc158b..758481b 100644
--- a/trunk/evas/src/modules/engines/wayland_egl/evas_engine.c
+++ b/trunk/evas/src/modules/engines/wayland_egl/evas_engine.c
@@ -600,6 +600,7 @@ eng_setup(Evas *e, void *in)
 {
    Render_Engine *re;
    Evas_Engine_Info_Wayland_Egl *info;
+   Evas_GL_Wl_Window *new_win = NULL;
 
    info = (Evas_Engine_Info_Wayland_Egl *)in;
    if (!e->engine.data.output)
@@ -679,28 +680,36 @@ eng_setup(Evas *e, void *in)
                        return 0;
                     }
 
-                  if (re->win)
-                    {
-                       re->win->gl_context->references++;
-                       eng_window_free(re->win);
-                       inc = 1;
-                       gl_wins--;
-                    }
-                  re->w = e->output.w;
-                  re->h = e->output.h;
-                  re->win = eng_window_new(re->info->info.display,
+                  new_win = eng_window_new(re->info->info.display,
                                            re->info->info.surface,
                                            re->info->info.screen,
                                            re->info->info.depth,
-                                           re->w, re->h,
+                                           e->output.w, e->output.h,
                                            re->info->indirect,
                                            re->info->info.destination_alpha,
                                            re->info->info.rotation);
-                  eng_window_use(re->win);
-                  if (re->win) gl_wins++;
-                  if ((re->win) && (inc))
-                     re->win->gl_context->references--;
-               }
+
+                  if (new_win) 
+                    {
+                       // free old win
+                       if (re->win)
+                         {
+                            re->win->gl_context->references++;
+                            eng_window_free(re->win);
+                            inc = 1;
+                            gl_wins--;
+                         }
+
+                     	re->win = new_win;
+                     	re->w = e->output.w;
+                     	re->h = e->output.h;
+                    
+                     	eng_window_use(re->win);
+                     	if (re->win) gl_wins++;
+                     	if ((re->win) && (inc))
+                     		re->win->gl_context->references--;
+                    }
+							 }
              else if ((re->win->w != e->output.w) ||
                       (re->win->h != e->output.h))
                {
diff --git a/trunk/evas/src/modules/engines/wayland_egl/evas_wl_main.c b/trunk/evas/src/modules/engines/wayland_egl/evas_wl_main.c
index 58ab1c3..0c5eef1 100644
--- a/trunk/evas/src/modules/engines/wayland_egl/evas_wl_main.c
+++ b/trunk/evas/src/modules/engines/wayland_egl/evas_wl_main.c
@@ -2,7 +2,7 @@
 
 static Evas_GL_Wl_Window *_evas_gl_wl_window = NULL;
 
-static EGLContext context = EGL_NO_CONTEXT;
+static EGLContext share_context = EGL_NO_CONTEXT;
 
 // fixme: something is up/wrong here - dont know what tho...
 //#define NEWGL 1
@@ -146,18 +146,17 @@ eng_window_new(struct wl_display *disp, struct wl_surface *surface, int screen,
      {
         ERR("eglCreateWindowSurface() fail for %p. code=%#x",
             gw->win, eglGetError());
-	eng_window_free(gw);
+        eng_window_free(gw);
         return NULL;
      }
 
-   if (context == EGL_NO_CONTEXT)
-     context = eglCreateContext(gw->egl_disp, gw->egl_config, NULL,
-                                context_attrs);
-   gw->egl_context[0] = context;
+   gw->egl_context[0] = eglCreateContext(gw->egl_disp, gw->egl_config, share_context, context_attrs);
+   share_context = gw->egl_context[0];
+
    if (gw->egl_context[0] == EGL_NO_CONTEXT)
      {
         ERR("eglCreateContext() fail. code=%#x", eglGetError());
-	eng_window_free(gw);
+        eng_window_free(gw);
         return NULL;
      }
 
@@ -213,10 +212,16 @@ eng_window_free(Evas_GL_Wl_Window *gw)
    if (gw->egl_surface[0] != EGL_NO_SURFACE)
       eglDestroySurface(gw->egl_disp, gw->egl_surface[0]);
    eglMakeCurrent(gw->egl_disp, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+
+   if (gw->egl_context[0] != EGL_NO_CONTEXT) 
+     {
+       if (gw->egl_context[0] == share_context)
+         share_context = EGL_NO_CONTEXT;
+       eglDestroyContext(gw->egl_disp, gw->egl_context[0]);
+     }
+
    if (ref == 0)
      {
-        if (context) eglDestroyContext(gw->egl_disp, context);
-        context = EGL_NO_CONTEXT;
         /* NB: This is causing an unknown hang when we run elm apps as 
          * wayland clients inside the weston compositor */
         /* eglTerminate(gw->egl_disp); */
-- 
1.7.9.5

_______________________________________________
wayland-devel mailing list
wayland-devel at lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel


More information about the wayland-devel mailing list