From 2d5d61bc491b6cef08ced8f1ad57b154d4fa5f66 Mon Sep 17 00:00:00 2001 From: "Miguel A. Vico" Date: Wed, 19 Jul 2017 17:27:12 -0700 Subject: [PATCH] wayland-egl: Make wl_egl_window a versioned struct We need wl_egl_window to be a versioned struct in order to keep track of ABI changes. This change makes the first member of wl_egl_window the version number. An heuristic in the wayland driver is added so that we don't break backwards compatibility: - If the first field (version) is an actual pointer, it is an old implementation of wl_egl_window, and version points to the wl_surface proxy. - Else, the first field is the version number, and we have wl_egl_window::surface pointing to the wl_surface proxy. Signed-off-by: Miguel A. Vico Reviewed-by: James Jones Acked-by: Daniel Stone Reviewed-by: Emil Velikov --- src/egl/drivers/dri2/platform_wayland.c | 16 +++++++++++++++- src/egl/wayland/wayland-egl/wayland-egl-priv.h | 6 +++++- src/egl/wayland/wayland-egl/wayland-egl.c | 4 ++++ 3 files changed, 24 insertions(+), 2 deletions(-) diff --git a/src/egl/drivers/dri2/platform_wayland.c b/src/egl/drivers/dri2/platform_wayland.c index 211036f45f4..f4c09ac0bc1 100644 --- a/src/egl/drivers/dri2/platform_wayland.c +++ b/src/egl/drivers/dri2/platform_wayland.c @@ -43,6 +43,7 @@ #include "egl_dri2_fallbacks.h" #include "loader.h" #include "util/u_vector.h" +#include "eglglobals.h" #include #include "wayland-drm-client-protocol.h" @@ -111,6 +112,19 @@ destroy_window_callback(void *data) dri2_surf->wl_win = NULL; } +static struct wl_surface * +get_wl_surface_proxy(struct wl_egl_window *window) +{ + /* Version 3 of wl_egl_window introduced a version field at the same + * location where a pointer to wl_surface was stored. Thus, if + * window->version is dereferencable, we've been given an older version of + * wl_egl_window, and window->version points to wl_surface */ + if (_eglPointerIsDereferencable((void *)(window->version))) { + return wl_proxy_create_wrapper((void *)(window->version)); + } + return wl_proxy_create_wrapper(window->surface); +} + /** * Called via eglCreateWindowSurface(), drv->API.CreateWindowSurface(). */ @@ -182,7 +196,7 @@ dri2_wl_create_window_surface(_EGLDriver *drv, _EGLDisplay *disp, wl_proxy_set_queue((struct wl_proxy *)dri2_surf->wl_dpy_wrapper, dri2_surf->wl_queue); - dri2_surf->wl_surface_wrapper = wl_proxy_create_wrapper(window->surface); + dri2_surf->wl_surface_wrapper = get_wl_surface_proxy(window); if (!dri2_surf->wl_surface_wrapper) { _eglError(EGL_BAD_ALLOC, "dri2_create_surface"); goto cleanup_drm; diff --git a/src/egl/wayland/wayland-egl/wayland-egl-priv.h b/src/egl/wayland/wayland-egl/wayland-egl-priv.h index 92c31d94543..3b59908cc16 100644 --- a/src/egl/wayland/wayland-egl/wayland-egl-priv.h +++ b/src/egl/wayland/wayland-egl/wayland-egl-priv.h @@ -41,8 +41,10 @@ extern "C" { #endif +#define WL_EGL_WINDOW_VERSION 3 + struct wl_egl_window { - struct wl_surface *surface; + const intptr_t version; int width; int height; @@ -55,6 +57,8 @@ struct wl_egl_window { void *private; void (*resize_callback)(struct wl_egl_window *, void *); void (*destroy_window_callback)(void *); + + struct wl_surface *surface; }; #ifdef __cplusplus diff --git a/src/egl/wayland/wayland-egl/wayland-egl.c b/src/egl/wayland/wayland-egl/wayland-egl.c index 4a4701a2de7..f16324c9f61 100644 --- a/src/egl/wayland/wayland-egl/wayland-egl.c +++ b/src/egl/wayland/wayland-egl/wayland-egl.c @@ -28,6 +28,7 @@ */ #include +#include #include #include "wayland-egl.h" @@ -54,6 +55,7 @@ WL_EGL_EXPORT struct wl_egl_window * wl_egl_window_create(struct wl_surface *surface, int width, int height) { + struct wl_egl_window _INIT_ = { .version = WL_EGL_WINDOW_VERSION }; struct wl_egl_window *egl_window; if (width <= 0 || height <= 0) @@ -63,6 +65,8 @@ wl_egl_window_create(struct wl_surface *surface, if (!egl_window) return NULL; + memcpy(egl_window, &_INIT_, sizeof *egl_window); + egl_window->surface = surface; egl_window->private = NULL; egl_window->resize_callback = NULL; -- 2.30.2