On Mon, Oct 07, 2013 at 10:09:17PM +0200, Giulio Camuffo wrote:
> Suppose we create a wl_egl_window and an EGLSurface. Then we call
> eglMakeCurrent(dpy,surf,surf,ctx) with that surface, render and swap.
> Later we destroy the surface and the window, and we make current
> another surface. That resulted in two invalid writes because
> the surface, which is refcounted, gets actually deleted at the
> eglMakeCurrent() call, and in dri2_destroy_surface() its window
> was used, window which was deleted earlier.
> So make also wl_egl_window refcounted, so that it isn't destroyed
> while its surface is still alive.

Just for reference, we discussed this in IRC and it came down to a
misunderstanding of how EGL works.  An EGLSurface is current for a
context from eglMakeCurrent up until eglMakeCurrent is called for the
conetxte with another surface or the context is destroyed.  The
wl_egl_surface (the native window object) has to be available (can not
be destroyed) for the entire time the EGLSurface exists.

Kristian

> Cc: mesa-sta...@lists.freedesktop.org
> ---
>  src/egl/drivers/dri2/platform_wayland.c        | 3 +++
>  src/egl/wayland/wayland-egl/wayland-egl-priv.h | 2 ++
>  src/egl/wayland/wayland-egl/wayland-egl.c      | 5 ++++-
>  3 files changed, 9 insertions(+), 1 deletion(-)
> 
> diff --git a/src/egl/drivers/dri2/platform_wayland.c 
> b/src/egl/drivers/dri2/platform_wayland.c
> index 1d417bb..831cd23 100644
> --- a/src/egl/drivers/dri2/platform_wayland.c
> +++ b/src/egl/drivers/dri2/platform_wayland.c
> @@ -143,6 +143,7 @@ dri2_create_surface(_EGLDriver *drv, _EGLDisplay *disp, 
> EGLint type,
>  
>        dri2_surf->wl_win->private = dri2_surf;
>        dri2_surf->wl_win->resize_callback = resize_callback;
> +      ++dri2_surf->wl_win->ref_count;
>  
>        dri2_surf->base.Width =  -1;
>        dri2_surf->base.Height = -1;
> @@ -222,6 +223,8 @@ dri2_destroy_surface(_EGLDriver *drv, _EGLDisplay *disp, 
> _EGLSurface *surf)
>        dri2_surf->wl_win->resize_callback = NULL;
>     }
>  
> +   (dri2_surf->wl_win->destroy)(dri2_surf->wl_win);
> +
>     free(surf);
>  
>     return EGL_TRUE;
> diff --git a/src/egl/wayland/wayland-egl/wayland-egl-priv.h 
> b/src/egl/wayland/wayland-egl/wayland-egl-priv.h
> index da25be9..302e2cf 100644
> --- a/src/egl/wayland/wayland-egl/wayland-egl-priv.h
> +++ b/src/egl/wayland/wayland-egl/wayland-egl-priv.h
> @@ -25,8 +25,10 @@ struct wl_egl_window {
>       int attached_width;
>       int attached_height;
>  
> +     int ref_count;
>       void *private;
>       void (*resize_callback)(struct wl_egl_window *, void *);
> +     void (*destroy)(struct wl_egl_window *);
>  };
>  
>  #ifdef  __cplusplus
> diff --git a/src/egl/wayland/wayland-egl/wayland-egl.c 
> b/src/egl/wayland/wayland-egl/wayland-egl.c
> index 8bd49cf..7a93987 100644
> --- a/src/egl/wayland/wayland-egl/wayland-egl.c
> +++ b/src/egl/wayland/wayland-egl/wayland-egl.c
> @@ -34,6 +34,8 @@ wl_egl_window_create(struct wl_surface *surface,
>       wl_egl_window_resize(egl_window, width, height, 0, 0);
>       egl_window->attached_width  = 0;
>       egl_window->attached_height = 0;
> +     egl_window->ref_count = 1;
> +     egl_window->destroy = wl_egl_window_destroy;
>       
>       return egl_window;
>  }
> @@ -41,7 +43,8 @@ wl_egl_window_create(struct wl_surface *surface,
>  WL_EGL_EXPORT void
>  wl_egl_window_destroy(struct wl_egl_window *egl_window)
>  {
> -     free(egl_window);
> +     if (--egl_window->ref_count < 1)
> +             free(egl_window);
>  }
>  
>  WL_EGL_EXPORT void
> -- 
> 1.8.4
> 
> _______________________________________________
> wayland-devel mailing list
> wayland-devel@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/wayland-devel
_______________________________________________
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel

Reply via email to