wayland-egl: Make wl_egl_window a versioned struct
authorMiguel A. Vico <mvicomoya@nvidia.com>
Thu, 20 Jul 2017 00:27:12 +0000 (17:27 -0700)
committerEmil Velikov <emil.l.velikov@gmail.com>
Mon, 24 Jul 2017 09:27:52 +0000 (10:27 +0100)
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 <mvicomoya@nvidia.com>
Reviewed-by: James Jones <jajones@nvidia.com>
Acked-by: Daniel Stone <daniels@collabora.com>
Reviewed-by: Emil Velikov <emil.velikov@collabora.com>
src/egl/drivers/dri2/platform_wayland.c
src/egl/wayland/wayland-egl/wayland-egl-priv.h
src/egl/wayland/wayland-egl/wayland-egl.c

index 211036f45f4b0e6e072a1efe1a2b39b5f7dee370..f4c09ac0bc10c6885f3d9447cb9352ab8725da54 100644 (file)
@@ -43,6 +43,7 @@
 #include "egl_dri2_fallbacks.h"
 #include "loader.h"
 #include "util/u_vector.h"
+#include "eglglobals.h"
 
 #include <wayland-client.h>
 #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;
index 92c31d94543ccb101a21e8d1fb30417a048a9f20..3b59908cc162d0094e6509a0b4932fb42b1fcf59 100644 (file)
 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
index 4a4701a2de7f378703c9a5f36c6787789621cb17..f16324c9f6100e0d97a15e2fcd16ee37ec45f86e 100644 (file)
@@ -28,6 +28,7 @@
  */
 
 #include <stdlib.h>
+#include <string.h>
 
 #include <wayland-client.h>
 #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;