Mesa (9.0): egl/wayland: Update to Wayland 0.99 API

Ian Romanick idr at kemper.freedesktop.org
Fri Nov 2 19:23:36 UTC 2012


Module: Mesa
Branch: 9.0
Commit: a5776ac0b8c015bf5d6a8513cefec5920895cc8e
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=a5776ac0b8c015bf5d6a8513cefec5920895cc8e

Author: Kristian Høgsberg <krh at bitplanet.net>
Date:   Wed Oct 10 22:10:42 2012 -0400

egl/wayland: Update to Wayland 0.99 API

The 0.99.0 Wayland release changes the event API to provide a thread-safe
mechanism for receiving events specific to a subsystem (such as EGL) and
we need to use it in the EGL platform.

The Wayland protocol now also requires a commit request to make changes
take effect, issue that from eglSwapBuffers.

---

 configure.ac                                       |    2 +-
 src/egl/drivers/dri2/egl_dri2.h                    |    4 +-
 src/egl/drivers/dri2/platform_wayland.c            |  102 ++++++++++++++-----
 .../state_trackers/egl/wayland/native_drm.c        |   40 +++++---
 .../state_trackers/egl/wayland/native_shm.c        |   34 ++++---
 .../state_trackers/egl/wayland/native_wayland.c    |   53 ++++++++--
 .../state_trackers/egl/wayland/native_wayland.h    |    7 +-
 7 files changed, 173 insertions(+), 69 deletions(-)

diff --git a/configure.ac b/configure.ac
index b42cf04..4746dcb 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1516,7 +1516,7 @@ for plat in $egl_platforms; do
 		;;
 
 	wayland)
-		PKG_CHECK_MODULES([WAYLAND], [wayland-client wayland-server],, \
+		PKG_CHECK_MODULES([WAYLAND], [wayland-client >= 0.99.0 wayland-server >= 0.99.0],, \
 				  [AC_MSG_ERROR([cannot find libwayland-client])])
 		GALLIUM_WINSYS_DIRS="$GALLIUM_WINSYS_DIRS sw/wayland"
 
diff --git a/src/egl/drivers/dri2/egl_dri2.h b/src/egl/drivers/dri2/egl_dri2.h
index 81c1354..3c42338 100644
--- a/src/egl/drivers/dri2/egl_dri2.h
+++ b/src/egl/drivers/dri2/egl_dri2.h
@@ -122,8 +122,10 @@ struct dri2_egl_display
 
 #ifdef HAVE_WAYLAND_PLATFORM
    struct wl_display        *wl_dpy;
+   struct wl_registry       *wl_registry;
    struct wl_drm            *wl_server_drm;
    struct wl_drm            *wl_drm;
+   struct wl_event_queue    *wl_queue;
    int			     authenticated;
    int			     formats;
 #endif
@@ -174,7 +176,7 @@ struct dri2_egl_surface
    __DRIbuffer           *dri_buffers[__DRI_BUFFER_COUNT];
    __DRIbuffer           *third_buffer;
    __DRIbuffer           *pending_buffer;
-   EGLBoolean             block_swap_buffers;
+   struct wl_callback    *frame_callback;
    int			  format;
 #endif
 
diff --git a/src/egl/drivers/dri2/platform_wayland.c b/src/egl/drivers/dri2/platform_wayland.c
index d291f0f..7e00c33 100644
--- a/src/egl/drivers/dri2/platform_wayland.c
+++ b/src/egl/drivers/dri2/platform_wayland.c
@@ -46,6 +46,34 @@ enum wl_drm_format_flags {
 };
 
 static void
+sync_callback(void *data, struct wl_callback *callback, uint32_t serial)
+{
+   int *done = data;
+
+   *done = 1;
+   wl_callback_destroy(callback);
+}
+
+static const struct wl_callback_listener sync_listener = {
+   sync_callback
+};
+
+static int
+roundtrip(struct dri2_egl_display *dri2_dpy)
+{
+   struct wl_callback *callback;
+   int done = 0, ret = 0;
+
+   callback = wl_display_sync(dri2_dpy->wl_dpy);
+   wl_callback_add_listener(callback, &sync_listener, &done);
+   wl_proxy_set_queue((struct wl_proxy *) callback, dri2_dpy->wl_queue);
+   while (ret != -1 && !done)
+      ret = wl_display_dispatch_queue(dri2_dpy->wl_dpy, dri2_dpy->wl_queue);
+
+   return ret;
+}
+
+static void
 wl_buffer_release(void *data, struct wl_buffer *buffer)
 {
    struct dri2_egl_surface *dri2_surf = data;
@@ -104,7 +132,7 @@ dri2_create_surface(_EGLDriver *drv, _EGLDisplay *disp, EGLint type,
 
    dri2_surf->pending_buffer = NULL;
    dri2_surf->third_buffer = NULL;
-   dri2_surf->block_swap_buffers = EGL_FALSE;
+   dri2_surf->frame_callback = NULL;
 
    if (conf->AlphaSize == 0)
       dri2_surf->format = WL_DRM_FORMAT_XRGB8888;
@@ -333,11 +361,13 @@ dri2_release_buffers(struct dri2_egl_surface *dri2_surf)
          switch (i) {
          case __DRI_BUFFER_FRONT_LEFT:
             if (dri2_surf->pending_buffer)
-	      wl_display_roundtrip(dri2_dpy->wl_dpy);
+               roundtrip(dri2_dpy);
             dri2_surf->pending_buffer = dri2_surf->dri_buffers[i];
             callback = wl_display_sync(dri2_dpy->wl_dpy);
 	    wl_callback_add_listener(callback,
 				     &release_buffer_listener, dri2_surf);
+            wl_proxy_set_queue((struct wl_proxy *) callback,
+                               dri2_dpy->wl_queue);
             break;
          default:
             dri2_dpy->dri2->releaseBuffer(dri2_dpy->dri_screen,
@@ -552,7 +582,7 @@ wayland_frame_callback(void *data, struct wl_callback *callback, uint32_t time)
 {
    struct dri2_egl_surface *dri2_surf = data;
 
-   dri2_surf->block_swap_buffers = EGL_FALSE;
+   dri2_surf->frame_callback = NULL;
    wl_callback_destroy(callback);
 }
 
@@ -569,17 +599,18 @@ dri2_swap_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw)
    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
    struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw);
    struct dri2_egl_driver *dri2_drv = dri2_egl_driver(drv);
-   struct wl_callback *callback;
+   int ret = 0;
 
-   if (dri2_surf->block_swap_buffers) {
-      wl_display_flush(dri2_dpy->wl_dpy);
-      while (dri2_surf->block_swap_buffers)
-         wl_display_iterate(dri2_dpy->wl_dpy, WL_DISPLAY_READABLE);
-   }
+   while (dri2_surf->frame_callback && ret != -1)
+      ret = wl_display_dispatch_queue(dri2_dpy->wl_dpy, dri2_dpy->wl_queue);
+   if (ret < 0)
+      return EGL_FALSE;
 
-   dri2_surf->block_swap_buffers = EGL_TRUE;
-   callback = wl_surface_frame(dri2_surf->wl_win->surface);
-   wl_callback_add_listener(callback, &frame_listener, dri2_surf);
+   dri2_surf->frame_callback = wl_surface_frame(dri2_surf->wl_win->surface);
+   wl_callback_add_listener(dri2_surf->frame_callback,
+                            &frame_listener, dri2_surf);
+   wl_proxy_set_queue((struct wl_proxy *) dri2_surf->frame_callback,
+                      dri2_dpy->wl_queue);
 
    if (dri2_surf->base.Type == EGL_WINDOW_BIT) {
       pointer_swap(
@@ -611,6 +642,8 @@ dri2_swap_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw)
 
       wl_surface_damage(dri2_surf->wl_win->surface, 0, 0,
 	    dri2_surf->base.Width, dri2_surf->base.Height);
+
+      wl_surface_commit(dri2_surf->wl_win->surface);
    }
 
    _EGLContext *ctx;
@@ -700,7 +733,8 @@ dri2_wayland_authenticate(_EGLDisplay *disp, uint32_t id)
    dri2_dpy->authenticated = 0;
 
    wl_drm_authenticate(dri2_dpy->wl_drm, id);
-   wl_display_roundtrip(dri2_dpy->wl_dpy);
+   if (roundtrip(dri2_dpy) < 0)
+      ret = -1;
 
    if (!dri2_dpy->authenticated)
       ret = -1;
@@ -795,12 +829,29 @@ static const struct wl_drm_listener drm_listener = {
 	drm_handle_authenticated
 };
 
+static void
+registry_handle_global(void *data, struct wl_registry *registry, uint32_t name,
+		       const char *interface, uint32_t version)
+{
+   struct dri2_egl_display *dri2_dpy = data;
+
+   if (strcmp(interface, "wl_drm") == 0) {
+      dri2_dpy->wl_drm =
+         wl_registry_bind(registry, name, &wl_drm_interface, 1);
+      wl_drm_add_listener(dri2_dpy->wl_drm, &drm_listener, dri2_dpy);
+   }
+}
+
+static const struct wl_registry_listener registry_listener = {
+	registry_handle_global
+};
+
 EGLBoolean
 dri2_initialize_wayland(_EGLDriver *drv, _EGLDisplay *disp)
 {
    struct dri2_egl_display *dri2_dpy;
    const __DRIconfig *config;
-   uint32_t id, types;
+   uint32_t types;
    int i;
    static const unsigned int argb_masks[4] =
       { 0xff0000, 0xff00, 0xff, 0xff000000 };
@@ -829,22 +880,19 @@ dri2_initialize_wayland(_EGLDriver *drv, _EGLDisplay *disp)
       dri2_dpy->wl_dpy = disp->PlatformDisplay;
    }
 
-   id = wl_display_get_global(dri2_dpy->wl_dpy, "wl_drm", 1);
-   if (id == 0)
-      wl_display_roundtrip(dri2_dpy->wl_dpy);
-   id = wl_display_get_global(dri2_dpy->wl_dpy, "wl_drm", 1);
-   if (id == 0)
-      goto cleanup_dpy;
-   dri2_dpy->wl_drm = wl_display_bind(dri2_dpy->wl_dpy, id, &wl_drm_interface);
-   if (!dri2_dpy->wl_drm)
+   dri2_dpy->wl_queue = wl_display_create_queue(dri2_dpy->wl_dpy);
+   dri2_dpy->wl_registry = wl_display_get_registry(dri2_dpy->wl_dpy);
+   wl_proxy_set_queue((struct wl_proxy *) dri2_dpy->wl_registry,
+                      dri2_dpy->wl_queue);
+   wl_registry_add_listener(dri2_dpy->wl_registry,
+                            &registry_listener, dri2_dpy);
+   if (roundtrip(dri2_dpy) < 0 || dri2_dpy->wl_drm == NULL)
       goto cleanup_dpy;
-   wl_drm_add_listener(dri2_dpy->wl_drm, &drm_listener, dri2_dpy);
-   wl_display_roundtrip(dri2_dpy->wl_dpy);
-   if (dri2_dpy->fd == -1)
+
+   if (roundtrip(dri2_dpy) < 0 || dri2_dpy->fd == -1)
       goto cleanup_drm;
 
-   wl_display_roundtrip(dri2_dpy->wl_dpy);
-   if (!dri2_dpy->authenticated)
+   if (roundtrip(dri2_dpy) < 0 || !dri2_dpy->authenticated)
       goto cleanup_fd;
 
    dri2_dpy->driver_name = dri2_get_driver_for_fd(dri2_dpy->fd);
diff --git a/src/gallium/state_trackers/egl/wayland/native_drm.c b/src/gallium/state_trackers/egl/wayland/native_drm.c
index c6f6197..4671e33 100644
--- a/src/gallium/state_trackers/egl/wayland/native_drm.c
+++ b/src/gallium/state_trackers/egl/wayland/native_drm.c
@@ -182,35 +182,43 @@ static const struct wl_drm_listener drm_listener = {
    drm_handle_authenticated
 };
 
+static void
+registry_handle_global(void *data, struct wl_registry *registry, uint32_t name,
+                       const char *interface, uint32_t version)
+{
+   struct wayland_drm_display *drmdpy = data;
+
+   if (strcmp(interface, "wl_drm") == 0) {
+      drmdpy->wl_drm = wl_registry_bind(registry, name, &wl_drm_interface, 1);
+      wl_drm_add_listener(drmdpy->wl_drm, &drm_listener, drmdpy);
+   }
+}
+
+static const struct wl_registry_listener registry_listener = {
+       registry_handle_global
+};
+
 static boolean
 wayland_drm_display_init_screen(struct native_display *ndpy)
 {
    struct wayland_drm_display *drmdpy = wayland_drm_display(ndpy);
-   uint32_t id;
-
-   id = wl_display_get_global(drmdpy->base.dpy, "wl_drm", 1);
-   if (id == 0)
-      wl_display_roundtrip(drmdpy->base.dpy);
-   id = wl_display_get_global(drmdpy->base.dpy, "wl_drm", 1);
-   if (id == 0)
-      return FALSE;
 
-   drmdpy->wl_drm = wl_display_bind(drmdpy->base.dpy, id, &wl_drm_interface);
-   if (!drmdpy->wl_drm)
+   drmdpy->base.queue = wl_display_create_queue(drmdpy->base.dpy);
+   drmdpy->base.registry = wl_display_get_registry(drmdpy->base.dpy);
+   wl_proxy_set_queue((struct wl_proxy *) drmdpy->base.registry,
+                      drmdpy->base.queue);
+   wl_registry_add_listener(drmdpy->base.registry, &registry_listener, drmdpy);
+   if (wayland_roundtrip(&drmdpy->base) < 0 || drmdpy->wl_drm == NULL)
       return FALSE;
 
    wl_drm_add_listener(drmdpy->wl_drm, &drm_listener, drmdpy);
-   wl_display_roundtrip(drmdpy->base.dpy);
-   if (drmdpy->fd == -1)
+   if (wayland_roundtrip(&drmdpy->base) < 0 || drmdpy->fd == -1)
       return FALSE;
 
-   wl_display_roundtrip(drmdpy->base.dpy);
-   if (!drmdpy->authenticated)
+   if (wayland_roundtrip(&drmdpy->base) < 0 || !drmdpy->authenticated)
       return FALSE;
 
    if (drmdpy->base.formats == 0)
-      wl_display_roundtrip(drmdpy->base.dpy);
-   if (drmdpy->base.formats == 0)
       return FALSE;
 
    drmdpy->base.base.screen =
diff --git a/src/gallium/state_trackers/egl/wayland/native_shm.c b/src/gallium/state_trackers/egl/wayland/native_shm.c
index 574ffce..5ffe485 100644
--- a/src/gallium/state_trackers/egl/wayland/native_shm.c
+++ b/src/gallium/state_trackers/egl/wayland/native_shm.c
@@ -133,26 +133,36 @@ static const struct wl_shm_listener shm_listener = {
    shm_handle_format
 };
 
+static void
+registry_handle_global(void *data, struct wl_registry *registry, uint32_t name,
+                       const char *interface, uint32_t version)
+{
+   struct wayland_shm_display *shmdpy = data;
+
+   if (strcmp(interface, "wl_shm") == 0) {
+      shmdpy->wl_shm = wl_registry_bind(registry, name, &wl_shm_interface, 1);
+      wl_shm_add_listener(shmdpy->wl_shm, &shm_listener, shmdpy);
+   }
+}
+
+static const struct wl_registry_listener registry_listener = {
+       registry_handle_global
+};
+
 static boolean
 wayland_shm_display_init_screen(struct native_display *ndpy)
 {
    struct wayland_shm_display *shmdpy = wayland_shm_display(ndpy);
    struct sw_winsys *winsys = NULL;
-   uint32_t id;
 
-   id = wl_display_get_global(shmdpy->base.dpy, "wl_shm", 1);
-   if (id == 0)
-      wl_display_iterate(shmdpy->base.dpy, WL_DISPLAY_READABLE);
-   id = wl_display_get_global(shmdpy->base.dpy, "wl_shm", 1);
-   if (id == 0)
+   shmdpy->base.queue = wl_display_create_queue(shmdpy->base.dpy);
+   shmdpy->base.registry = wl_display_get_registry(shmdpy->base.dpy);
+   wl_proxy_set_queue((struct wl_proxy *) shmdpy->base.registry,
+                      shmdpy->base.queue);
+   wl_registry_add_listener(shmdpy->base.registry, &registry_listener, shmdpy);
+   if (wayland_roundtrip(&shmdpy->base) < 0 || shmdpy->wl_shm == NULL)
       return FALSE;
 
-   shmdpy->wl_shm = wl_display_bind(shmdpy->base.dpy, id, &wl_shm_interface);
-   if (!shmdpy->wl_shm)
-      return FALSE;
-
-   wl_shm_add_listener(shmdpy->wl_shm, &shm_listener, shmdpy);
-
    if (shmdpy->base.formats == 0)
       wl_display_roundtrip(shmdpy->base.dpy);
    if (shmdpy->base.formats == 0)
diff --git a/src/gallium/state_trackers/egl/wayland/native_wayland.c b/src/gallium/state_trackers/egl/wayland/native_wayland.c
index a7f9cb7..635b65f 100644
--- a/src/gallium/state_trackers/egl/wayland/native_wayland.c
+++ b/src/gallium/state_trackers/egl/wayland/native_wayland.c
@@ -35,6 +35,34 @@
 
 #include "native_wayland.h"
 
+static void
+sync_callback(void *data, struct wl_callback *callback, uint32_t serial)
+{
+   int *done = data;
+
+   *done = 1;
+   wl_callback_destroy(callback);
+}
+
+static const struct wl_callback_listener sync_listener = {
+   sync_callback
+};
+
+int
+wayland_roundtrip(struct wayland_display *display)
+{
+   struct wl_callback *callback;
+   int done = 0, ret = 0;
+
+   callback = wl_display_sync(display->dpy);
+   wl_callback_add_listener(callback, &sync_listener, &done);
+   wl_proxy_set_queue((struct wl_proxy *) callback, display->queue);
+   while (ret == 0 && !done)
+      ret = wl_display_dispatch_queue(display->dpy, display->queue);
+
+   return ret;
+}
+
 static const struct native_event_handler *wayland_event_handler;
 
 const static struct {
@@ -93,7 +121,6 @@ static int
 wayland_display_get_param(struct native_display *ndpy,
                           enum native_param_type param)
 {
-   struct wayland_display *display = wayland_display(ndpy);
    int val;
 
    switch (param) {
@@ -188,7 +215,7 @@ wayland_window_surface_handle_resize(struct wayland_surface *surface)
                                  surface->win->width, surface->win->height)) {
 
       if (surface->pending_resource)
-         wl_display_roundtrip(display->dpy);
+         wayland_roundtrip(display);
 
       if (front_resource) {
          struct wl_callback *callback;
@@ -198,6 +225,7 @@ wayland_window_surface_handle_resize(struct wayland_surface *surface)
 
          callback = wl_display_sync(display->dpy);
          wl_callback_add_listener(callback, &release_buffer_listener, surface);
+         wl_proxy_set_queue((struct wl_proxy *) callback, display->queue);
       }
 
       for (i = 0; i < WL_BUFFER_COUNT; ++i) {
@@ -245,7 +273,7 @@ wayland_frame_callback(void *data, struct wl_callback *callback, uint32_t time)
 {
    struct wayland_surface *surface = data;
 
-   surface->block_swap_buffers = FALSE;
+   surface->frame_callback = NULL;
 
    wl_callback_destroy(callback);
 }
@@ -269,15 +297,17 @@ wayland_surface_swap_buffers(struct native_surface *nsurf)
 {
    struct wayland_surface *surface = wayland_surface(nsurf);
    struct wayland_display *display = surface->display;
-   struct wl_callback *callback;
-
-   while (surface->block_swap_buffers)
-      wl_display_iterate(display->dpy, WL_DISPLAY_READABLE);
+   int ret = 0;
 
-   surface->block_swap_buffers = TRUE;
+   while (surface->frame_callback && ret != -1)
+      ret = wl_display_dispatch_queue(display->dpy, display->queue);
+   if (ret == -1)
+      return EGL_FALSE;
 
-   callback = wl_surface_frame(surface->win->surface);
-   wl_callback_add_listener(callback, &frame_listener, surface);
+   surface->frame_callback = wl_surface_frame(surface->win->surface);
+   wl_callback_add_listener(surface->frame_callback, &frame_listener, surface);
+   wl_proxy_set_queue((struct wl_proxy *) surface->frame_callback,
+                      display->queue);
 
    if (surface->type == WL_WINDOW_SURFACE) {
       resource_surface_swap_buffers(surface->rsurf,
@@ -349,6 +379,7 @@ wayland_surface_present(struct native_surface *nsurf,
    if (surface->type == WL_WINDOW_SURFACE) {
       resource_surface_get_size(surface->rsurf, &width, &height);
       wl_surface_damage(surface->win->surface, 0, 0, width, height);
+      wl_surface_commit(surface->win->surface);
    }
 
    return ret;
@@ -452,7 +483,7 @@ wayland_create_window_surface(struct native_display *ndpy,
    surface->win = (struct wl_egl_window *) win;
 
    surface->pending_resource = NULL;
-   surface->block_swap_buffers = FALSE;
+   surface->frame_callback = NULL;
    surface->type = WL_WINDOW_SURFACE;
 
    surface->buffer[WL_BUFFER_FRONT] = NULL;
diff --git a/src/gallium/state_trackers/egl/wayland/native_wayland.h b/src/gallium/state_trackers/egl/wayland/native_wayland.h
index e6a914f..268b3b7 100644
--- a/src/gallium/state_trackers/egl/wayland/native_wayland.h
+++ b/src/gallium/state_trackers/egl/wayland/native_wayland.h
@@ -45,6 +45,8 @@ struct wayland_display {
    struct native_display base;
 
    struct wl_display *dpy;
+   struct wl_event_queue *queue;
+   struct wl_registry *registry;
    boolean own_dpy;
    /* supported formats */
    uint32_t formats;
@@ -85,7 +87,7 @@ struct wayland_surface {
    struct wl_buffer *buffer[WL_BUFFER_COUNT];
    unsigned int attachment_mask;
 
-   boolean block_swap_buffers;
+   struct wl_callback *frame_callback;
    boolean premultiplied_alpha;
 };
 
@@ -119,4 +121,7 @@ struct wayland_display *
 wayland_create_drm_display(struct wl_display *display,
                            const struct native_event_handler *event_handler);
 
+int
+wayland_roundtrip(struct wayland_display *drmdpy);
+
 #endif /* _NATIVE_WAYLAND_H_ */




More information about the mesa-commit mailing list