Mesa (master): egl: Add EGL_WL_bind_wayland_display

Kristian Høgsberg krh at kemper.freedesktop.org
Tue Mar 1 22:25:53 UTC 2011


Module: Mesa
Branch: master
Commit: 6b369c4c7cd8a52f99bbff2a57fb316b33a87495
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=6b369c4c7cd8a52f99bbff2a57fb316b33a87495

Author: Benjamin Franzke <benjaminfranzke at googlemail.com>
Date:   Mon Feb 21 16:22:34 2011 +0100

egl: Add EGL_WL_bind_wayland_display

---

 configure.ac                                       |    2 +-
 docs/WL_bind_wayland_display.spec                  |   92 +++++++++
 include/EGL/eglext.h                               |   14 ++
 src/egl/Makefile                                   |    3 +-
 src/egl/drivers/dri2/Makefile                      |    6 +-
 src/egl/drivers/dri2/egl_dri2.c                    |   94 +++++++++
 src/egl/drivers/dri2/egl_dri2.h                    |    4 +
 src/egl/drivers/dri2/platform_drm.c                |   56 ++++++-
 src/egl/drivers/dri2/platform_wayland.c            |   36 ++++-
 src/egl/drivers/dri2/platform_x11.c                |   45 +++--
 src/egl/main/Makefile                              |    3 +
 src/egl/main/eglapi.c                              |   44 +++++
 src/egl/main/eglapi.h                              |   11 +
 src/egl/main/egldisplay.h                          |    2 +
 src/egl/main/eglmisc.c                             |    2 +
 src/egl/wayland/Makefile                           |   18 ++-
 src/egl/wayland/wayland-drm/.gitignore             |    3 +
 src/egl/wayland/wayland-drm/Makefile               |   45 +++++
 .../wayland/wayland-drm/protocol/wayland-drm.xml   |   38 ++++
 src/egl/wayland/wayland-drm/wayland-drm.c          |  203 ++++++++++++++++++++
 src/egl/wayland/wayland-drm/wayland-drm.h          |   26 +++
 src/egl/wayland/wayland-egl.c                      |    4 +-
 src/gallium/state_trackers/egl/Makefile            |    1 +
 .../state_trackers/egl/wayland/native_wayland.c    |    1 +
 24 files changed, 729 insertions(+), 24 deletions(-)

diff --git a/configure.ac b/configure.ac
index dcfddb1..9fa5eee 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1587,7 +1587,7 @@ yes)
                 GALLIUM_WINSYS_DIRS="$GALLIUM_WINSYS_DIRS sw/fbdev"
         fi
 	if test "$plat" = "wayland"; then
-		PKG_CHECK_MODULES([WAYLAND], [wayland-client],, \
+		PKG_CHECK_MODULES([WAYLAND], [wayland-client wayland-server],, \
 				  [AC_MSG_ERROR([cannot find libwayland-client])])
 		WAYLAND_EGL_LIB_DEPS="$WAYLAND_LIBS $LIBDRM_LIBS"
 	fi
diff --git a/docs/WL_bind_wayland_display.spec b/docs/WL_bind_wayland_display.spec
new file mode 100644
index 0000000..0ff49d6
--- /dev/null
+++ b/docs/WL_bind_wayland_display.spec
@@ -0,0 +1,92 @@
+Name
+
+    WL_bind_wayland_display
+
+Name Strings
+
+    EGL_WL_bind_wayland_display
+
+Contact
+
+    Kristian Høgsberg <krh at bitplanet.net>
+    Benjamin Franzke <benjaminfranzke at googlemail.com>
+
+Status
+
+    Proposal
+
+Version
+
+    Version 1, March 1, 2011
+
+Number
+
+    EGL Extension #not assigned
+
+Dependencies
+
+    Reguires EGL 1.4 or later.  This extension is written against the
+    wording of the EGL 1.4 specification.
+
+    EGL_KHR_base_image is required.
+
+Overview
+
+    This extension provides entry points for binding and unbinding the
+    wl_display of a Wayland compositor to an EGLDisplay.  Binding a
+    wl_display means that the EGL implementation should provide one or
+    more interfaces in the Wayland protocol to allow clients to create
+    wl_buffer objects.  On the server side, this extension also
+    provides a new target for eglCreateImageKHR, to create an EGLImage
+    from a wl_buffer
+
+    Adding a implementation specific wayland interface, allows the
+    EGL implementation to define specific wayland requests and events,
+    needed for buffer sharing in a EGL wayland platform.
+
+IP Status
+
+    Open-source; freely implementable.
+
+New Procedures and Functions
+
+    EGLBoolean eglBindWaylandDisplayWL(EGLDisplay dpy,
+                                       struct wl_display *display);
+
+    EGLBoolean eglUnbindWaylandDisplayWL(EGLDisplay dpy,
+                                         struct wl_display *display);
+
+New Tokens
+
+    Accepted as <target> in eglCreateImageKHR
+
+        EGL_WAYLAND_BUFFER_WL                   0x31D5
+
+Additions to the EGL 1.4 Specification:
+
+    To bind a server side wl_display to an EGLDisplay, call
+
+        EGLBoolean eglBindWaylandDisplayWL(EGLDisplay dpy,
+                                           struct wl_display *display);
+
+    To unbind a server side wl_display from an EGLDisplay, call
+    
+        EGLBoolean eglUnbindWaylandDisplayWL(EGLDisplay dpy,
+                                             struct wl_display *display);
+
+    eglBindWaylandDisplayWL returns EGL_FALSE when there is already a
+    wl_display bound to EGLDisplay otherwise EGL_TRUE.
+
+    eglUnbindWaylandDisplayWL returns EGL_FALSE when there is no
+    wl_display bound to the EGLDisplay currently otherwise EGL_TRUE.
+
+    Import a wl_buffer by calling eglCreateImageKHR with
+    wl_buffer as EGLClientBuffer, EGL_WAYLAND_BUFFER_WL as the target,
+    and an empty attribute_list.
+
+Issues
+
+Revision History
+
+    Version 1, March 1, 2011
+        Initial draft (Benjamin Franzke)
diff --git a/include/EGL/eglext.h b/include/EGL/eglext.h
index 0460393..fa523a5 100644
--- a/include/EGL/eglext.h
+++ b/include/EGL/eglext.h
@@ -143,6 +143,20 @@ typedef EGLImageKHR (EGLAPIENTRYP PFNEGLCREATEDRMIMAGEMESA) (EGLDisplay dpy, con
 typedef EGLBoolean (EGLAPIENTRYP PFNEGLEXPORTDRMIMAGEMESA) (EGLDisplay dpy, EGLImageKHR image, EGLint *name, EGLint *handle, EGLint *stride);
 #endif
 
+#ifndef EGL_WL_bind_wayland_display
+#define EGL_WL_bind_wayland_display 1
+
+#define EGL_WAYLAND_BUFFER_WL			0x31D5 /* eglCreateImageKHR target */
+struct wl_display;
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglBindWaylandDisplayWL(EGLDisplay dpy, struct wl_display *display);
+EGLAPI EGLBoolean EGLAPIENTRY eglUnbindWaylandDisplayWL(EGLDisplay dpy, struct wl_display *display);
+#else
+typedef EGLBoolean (EGLAPIENTRY PFNEGLBINDWAYLANDDISPLAYWL) (EGLDisplay dpy, struct wl_display *display);
+typedef EGLBoolean (EGLAPIENTRY PFNEGLUNBINDWAYLANDDISPLAYWL) (EGLDisplay dpy, struct wl_display *display);
+#endif
+#endif
+
 #if KHRONOS_SUPPORT_INT64   /* EGLTimeKHR requires 64-bit uint support */
 #ifndef EGL_KHR_reusable_sync
 #define EGL_KHR_reusable_sync 1
diff --git a/src/egl/Makefile b/src/egl/Makefile
index 52daf2e..361f688 100644
--- a/src/egl/Makefile
+++ b/src/egl/Makefile
@@ -3,12 +3,13 @@
 TOP = ../..
 include $(TOP)/configs/current
 
-SUBDIRS = drivers main
+SUBDIRS =
 
 ifneq ($(findstring wayland, $(EGL_PLATFORMS)),)
 SUBDIRS += wayland
 endif
 
+SUBDIRS += drivers main
 
 default: subdirs
 
diff --git a/src/egl/drivers/dri2/Makefile b/src/egl/drivers/dri2/Makefile
index 89e9dd7..eac599e 100644
--- a/src/egl/drivers/dri2/Makefile
+++ b/src/egl/drivers/dri2/Makefile
@@ -27,8 +27,10 @@ endif
 ifneq ($(findstring wayland, $(EGL_PLATFORMS)),)
 EGL_SOURCES += platform_wayland.c
 EGL_INCLUDES += -DHAVE_WAYLAND_PLATFORM $(WAYLAND_CFLAGS) \
-		-I$(TOP)/src/egl/wayland
-EGL_LIBS += $(WAYLAND_LIBS)
+		-I$(TOP)/src/egl/wayland \
+		-I$(TOP)/src/egl/wayland/wayland-drm
+EGL_LIBS += $(WAYLAND_LIBS) \
+	    $(TOP)/src/egl/wayland/wayland-drm/libwayland-drm.a
 endif
 
 include ../Makefile.template
diff --git a/src/egl/drivers/dri2/egl_dri2.c b/src/egl/drivers/dri2/egl_dri2.c
index 99f87f0..015b801 100644
--- a/src/egl/drivers/dri2/egl_dri2.c
+++ b/src/egl/drivers/dri2/egl_dri2.c
@@ -915,6 +915,51 @@ dri2_create_image_mesa_drm_buffer(_EGLDisplay *disp, _EGLContext *ctx,
    return &dri2_img->base;
 }
 
+static EGLBoolean
+dri2_export_drm_image_mesa(_EGLDriver *drv, _EGLDisplay *disp, _EGLImage *img,
+			  EGLint *name, EGLint *handle, EGLint *stride);
+
+static _EGLImage *
+dri2_reference_drm_image(_EGLDisplay *disp, _EGLContext *ctx,
+			 _EGLImage *image, EGLint width, EGLint height)
+{
+   EGLint attr_list[] = {
+		EGL_WIDTH,		0,
+		EGL_HEIGHT,		0,
+		EGL_DRM_BUFFER_STRIDE_MESA,	0,
+		EGL_DRM_BUFFER_FORMAT_MESA,	EGL_DRM_BUFFER_FORMAT_ARGB32_MESA,
+		EGL_NONE
+   };
+   EGLint name, stride;
+   
+   dri2_export_drm_image_mesa(disp->Driver, disp, image,
+			      &name, NULL, &stride);
+
+   attr_list[1] = width;
+   attr_list[3] = height;
+   attr_list[5] = stride / 4;
+
+   return dri2_create_image_mesa_drm_buffer(disp, ctx,
+					    (EGLClientBuffer)(intptr_t) name,
+					    attr_list);
+}
+
+#ifdef HAVE_WAYLAND_PLATFORM
+static _EGLImage *
+dri2_create_image_wayland_wl_buffer(_EGLDisplay *disp, _EGLContext *ctx,
+				    EGLClientBuffer buffer,
+				    const EGLint *attr_list)
+{
+	struct wl_drm_buffer *wl_drm_buffer = (struct wl_drm_buffer *) buffer;
+
+        (void) attr_list;
+
+	return dri2_reference_drm_image(disp, ctx, wl_drm_buffer->image,
+					wl_drm_buffer->buffer.width,
+					wl_drm_buffer->buffer.height);
+}
+#endif
+
 _EGLImage *
 dri2_create_image_khr(_EGLDriver *drv, _EGLDisplay *disp,
 		      _EGLContext *ctx, EGLenum target,
@@ -927,6 +972,10 @@ dri2_create_image_khr(_EGLDriver *drv, _EGLDisplay *disp,
       return dri2_create_image_khr_renderbuffer(disp, ctx, buffer, attr_list);
    case EGL_DRM_BUFFER_MESA:
       return dri2_create_image_mesa_drm_buffer(disp, ctx, buffer, attr_list);
+#ifdef HAVE_WAYLAND_PLATFORM
+   case EGL_WAYLAND_BUFFER_WL:
+      return dri2_create_image_wayland_wl_buffer(disp, ctx, buffer, attr_list);
+#endif
    default:
       _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr");
       return EGL_NO_IMAGE_KHR;
@@ -1055,6 +1104,47 @@ dri2_export_drm_image_mesa(_EGLDriver *drv, _EGLDisplay *disp, _EGLImage *img,
    return EGL_TRUE;
 }
 
+#ifdef HAVE_WAYLAND_PLATFORM
+static EGLBoolean
+dri2_bind_wayland_display_wl(_EGLDriver *drv, _EGLDisplay *disp,
+			     struct wl_display *wl_dpy)
+{
+   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
+
+   (void) drv;
+
+   if (dri2_dpy->wl_server_drm)
+	   return EGL_FALSE;
+
+   dri2_dpy->wl_server_drm =
+	   wayland_drm_init(wl_dpy, disp,
+			    dri2_dpy->authenticate,
+			    dri2_dpy->device_name);
+
+   if (!dri2_dpy->wl_server_drm)
+	   return EGL_FALSE;
+
+   return EGL_TRUE;
+}
+
+static EGLBoolean
+dri2_unbind_wayland_display_wl(_EGLDriver *drv, _EGLDisplay *disp,
+			       struct wl_display *wl_dpy)
+{
+   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
+
+   (void) drv;
+
+   if (!dri2_dpy->wl_server_drm)
+	   return EGL_FALSE;
+
+   wayland_drm_destroy(dri2_dpy->wl_server_drm);
+   dri2_dpy->wl_server_drm = NULL;
+
+   return EGL_TRUE;
+}
+#endif
+
 static void
 dri2_unload(_EGLDriver *drv)
 {
@@ -1140,6 +1230,10 @@ _EGL_MAIN(const char *args)
    dri2_drv->base.API.DestroyImageKHR = dri2_destroy_image_khr;
    dri2_drv->base.API.CreateDRMImageMESA = dri2_create_drm_image_mesa;
    dri2_drv->base.API.ExportDRMImageMESA = dri2_export_drm_image_mesa;
+#ifdef HAVE_WAYLAND_PLATFORM
+   dri2_drv->base.API.BindWaylandDisplayWL = dri2_bind_wayland_display_wl;
+   dri2_drv->base.API.UnbindWaylandDisplayWL = dri2_unbind_wayland_display_wl;
+#endif
 
    dri2_drv->base.Name = "DRI2";
    dri2_drv->base.Unload = dri2_unload;
diff --git a/src/egl/drivers/dri2/egl_dri2.h b/src/egl/drivers/dri2/egl_dri2.h
index 235e30d..5afd3d3 100644
--- a/src/egl/drivers/dri2/egl_dri2.h
+++ b/src/egl/drivers/dri2/egl_dri2.h
@@ -35,6 +35,7 @@
 
 #ifdef HAVE_WAYLAND_PLATFORM
 #include <wayland-client.h>
+#include "wayland-drm.h"
 #include "wayland-egl-priv.h"
 #endif
 
@@ -85,7 +86,10 @@ struct dri2_egl_display
    const __DRIextension     *extensions[3];
 #ifdef HAVE_WAYLAND_PLATFORM
    struct wl_egl_display    *wl_dpy;
+   struct wl_drm            *wl_server_drm;
 #endif
+
+   int (*authenticate) (struct dri2_egl_display *dri_dpy, uint32_t id);
 };
 
 struct dri2_egl_context
diff --git a/src/egl/drivers/dri2/platform_drm.c b/src/egl/drivers/dri2/platform_drm.c
index 3dab899..bd4fa80 100644
--- a/src/egl/drivers/dri2/platform_drm.c
+++ b/src/egl/drivers/dri2/platform_drm.c
@@ -568,6 +568,39 @@ const struct dri2_driver_map driver_map[] = {
    { 0x10de, "nouveau", NULL, -1 },
 };
 
+static char *
+dri2_get_device_name(int fd)
+{
+   struct udev *udev;
+   struct udev_device *device;
+   struct stat buf;
+   char *device_name;
+
+   udev = udev_new();
+   if (fstat(fd, &buf) < 0) {
+      _eglLog(_EGL_WARNING, "EGL-DRI2: failed to stat fd %d", fd);
+      goto out;
+   }
+
+   device = udev_device_new_from_devnum(udev, 'c', buf.st_rdev);
+   if (device == NULL) {
+      _eglLog(_EGL_WARNING,
+	      "EGL-DRI2: could not create udev device for fd %d", fd);
+      goto out;
+   }
+
+   device_name = udev_device_get_devnode(device);
+   if (!device_name)
+	   goto out;
+   device_name = strdup(device_name);
+
+ out:
+   udev_device_unref(device);
+   udev_unref(udev);
+
+   return device_name;
+}
+
 char *
 dri2_get_driver_for_fd(int fd)
 {
@@ -629,6 +662,14 @@ dri2_get_driver_for_fd(int fd)
    return driver;
 }
 
+static int
+dri2_drm_authenticate(_EGLDisplay *disp, uint32_t id)
+{
+   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
+
+   return drmAuthMagic(dri2_dpy->fd, id);
+}
+
 EGLBoolean
 dri2_initialize_drm(_EGLDriver *drv, _EGLDisplay *disp)
 {
@@ -648,8 +689,14 @@ dri2_initialize_drm(_EGLDriver *drv, _EGLDisplay *disp)
    if (dri2_dpy->driver_name == NULL)
       return _eglError(EGL_BAD_ALLOC, "DRI2: failed to get driver name");
 
-   if (!dri2_load_driver(disp))
+   dri2_dpy->device_name = dri2_get_device_name(dri2_dpy->fd);
+   if (dri2_dpy->device_name == NULL) {
+      _eglError(EGL_BAD_ALLOC, "DRI2: failed to get device name");
       goto cleanup_driver_name;
+   }
+
+   if (!dri2_load_driver(disp))
+      goto cleanup_device_name;
 
    dri2_dpy->extensions[0] = &image_lookup_extension.base;
    dri2_dpy->extensions[1] = &use_invalidate.base;
@@ -666,6 +713,11 @@ dri2_initialize_drm(_EGLDriver *drv, _EGLDisplay *disp)
    disp->Extensions.KHR_gl_renderbuffer_image = EGL_TRUE;
    disp->Extensions.KHR_gl_texture_2D_image = EGL_TRUE;
 
+#ifdef HAVE_WAYLAND_PLATFORM
+   disp->Extensions.WL_bind_wayland_display = EGL_TRUE;
+#endif
+   dri2_dpy->authenticate = dri2_drm_authenticate;
+   
    /* we're supporting EGL 1.4 */
    disp->VersionMajor = 1;
    disp->VersionMinor = 4;
@@ -674,6 +726,8 @@ dri2_initialize_drm(_EGLDriver *drv, _EGLDisplay *disp)
 
  cleanup_driver:
    dlclose(dri2_dpy->driver);
+ cleanup_device_name:
+   free(dri2_dpy->device_name);
  cleanup_driver_name:
    free(dri2_dpy->driver_name);
 
diff --git a/src/egl/drivers/dri2/platform_wayland.c b/src/egl/drivers/dri2/platform_wayland.c
index 21b4406..6ae3f65 100644
--- a/src/egl/drivers/dri2/platform_wayland.c
+++ b/src/egl/drivers/dri2/platform_wayland.c
@@ -35,6 +35,9 @@
 
 #include "egl_dri2.h"
 
+#include <wayland-client.h>
+#include "wayland-drm-client-protocol.h"
+
 static void
 sync_callback(void *data)
 {
@@ -561,6 +564,26 @@ dri2_wayland_create_image_khr(_EGLDriver *drv, _EGLDisplay *disp,
    }
 }
 
+static int
+dri2_wayland_authenticate(_EGLDisplay *disp, uint32_t id)
+{
+   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
+   int ret = 0;
+
+   dri2_dpy->wl_dpy->authenticated = false;
+
+   wl_drm_authenticate(dri2_dpy->wl_dpy->drm, id);
+   force_roundtrip(dri2_dpy->wl_dpy->display);
+
+   if (!dri2_dpy->wl_dpy->authenticated)
+      ret = -1;
+
+   /* reset authenticated */
+   dri2_dpy->wl_dpy->authenticated = true;
+
+   return ret;
+}
+
 /**
  * Called via eglTerminate(), drv->API.Terminate().
  */
@@ -626,8 +649,14 @@ dri2_initialize_wayland(_EGLDriver *drv, _EGLDisplay *disp)
       goto cleanup_fd;
    }
 
-   if (!dri2_load_driver(disp))
+   dri2_dpy->device_name = strdup(dri2_dpy->wl_dpy->device_name);
+   if (dri2_dpy->device_name == NULL) {
+      _eglError(EGL_BAD_ALLOC, "DRI2: failed to get device name");
       goto cleanup_driver_name;
+   }
+
+   if (!dri2_load_driver(disp))
+      goto cleanup_device_name;
 
    dri2_dpy->dri2_loader_extension.base.name = __DRI_DRI2_LOADER;
    dri2_dpy->dri2_loader_extension.base.version = 3;
@@ -654,6 +683,9 @@ dri2_initialize_wayland(_EGLDriver *drv, _EGLDisplay *disp)
    disp->Extensions.KHR_gl_renderbuffer_image = EGL_TRUE;
    disp->Extensions.KHR_gl_texture_2D_image = EGL_TRUE;
 
+   disp->Extensions.WL_bind_wayland_display = EGL_TRUE;
+   dri2_dpy->authenticate = dri2_wayland_authenticate;
+
    /* we're supporting EGL 1.4 */
    disp->VersionMajor = 1;
    disp->VersionMinor = 4;
@@ -662,6 +694,8 @@ dri2_initialize_wayland(_EGLDriver *drv, _EGLDisplay *disp)
 
  cleanup_driver:
    dlclose(dri2_dpy->driver);
+ cleanup_device_name:
+   free(dri2_dpy->device_name);
  cleanup_driver_name:
    free(dri2_dpy->driver_name);
  cleanup_fd:
diff --git a/src/egl/drivers/dri2/platform_x11.c b/src/egl/drivers/dri2/platform_x11.c
index 50310ee..c7bdfa6 100644
--- a/src/egl/drivers/dri2/platform_x11.c
+++ b/src/egl/drivers/dri2/platform_x11.c
@@ -543,32 +543,46 @@ dri2_connect(struct dri2_egl_display *dri2_dpy)
    return EGL_TRUE;
 }
 
-static EGLBoolean
-dri2_authenticate(struct dri2_egl_display *dri2_dpy)
+static int
+dri2_x11_authenticate(_EGLDisplay *disp, uint32_t id)
 {
+   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
    xcb_dri2_authenticate_reply_t *authenticate;
    xcb_dri2_authenticate_cookie_t authenticate_cookie;
    xcb_screen_iterator_t s;
+   int ret = 0;
+
+   s = xcb_setup_roots_iterator(xcb_get_setup(dri2_dpy->conn));
+   authenticate_cookie =
+      xcb_dri2_authenticate_unchecked(dri2_dpy->conn, s.data->root, id);
+   authenticate =
+      xcb_dri2_authenticate_reply(dri2_dpy->conn, authenticate_cookie, NULL);
+
+   if (authenticate == NULL || !authenticate->authenticated)
+      ret = -1;
+
+   if (authenticate)
+      free(authenticate);
+   
+   return ret;
+}
+
+static EGLBoolean
+dri2_authenticate(_EGLDisplay *disp)
+{
+   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
    drm_magic_t magic;
 
    if (drmGetMagic(dri2_dpy->fd, &magic)) {
       _eglLog(_EGL_WARNING, "DRI2: failed to get drm magic");
       return EGL_FALSE;
    }
-
-   s = xcb_setup_roots_iterator(xcb_get_setup(dri2_dpy->conn));
-   authenticate_cookie =
-      xcb_dri2_authenticate_unchecked(dri2_dpy->conn, s.data->root, magic);
-   authenticate =
-      xcb_dri2_authenticate_reply(dri2_dpy->conn, authenticate_cookie, NULL);
-   if (authenticate == NULL || !authenticate->authenticated) {
+   
+   if (dri2_x11_authenticate(disp, magic) < 0) {
       _eglLog(_EGL_WARNING, "DRI2: failed to authenticate");
-      free(authenticate);
       return EGL_FALSE;
    }
 
-   free(authenticate);
-
    return EGL_TRUE;
 }
 
@@ -977,7 +991,7 @@ dri2_initialize_x11_dri2(_EGLDriver *drv, _EGLDisplay *disp)
    }
 
    if (dri2_dpy->conn) {
-      if (!dri2_authenticate(dri2_dpy))
+      if (!dri2_authenticate(disp))
 	 goto cleanup_fd;
    }
 
@@ -1016,6 +1030,11 @@ dri2_initialize_x11_dri2(_EGLDriver *drv, _EGLDisplay *disp)
    disp->Extensions.NOK_swap_region = EGL_TRUE;
    disp->Extensions.NOK_texture_from_pixmap = EGL_TRUE;
 
+#ifdef HAVE_WAYLAND_PLATFORM
+   disp->Extensions.WL_bind_wayland_display = EGL_TRUE;
+#endif
+   dri2_dpy->authenticate = dri2_x11_authenticate;
+
    /* we're supporting EGL 1.4 */
    disp->VersionMajor = 1;
    disp->VersionMinor = 4;
diff --git a/src/egl/main/Makefile b/src/egl/main/Makefile
index a5b9299..820788d 100644
--- a/src/egl/main/Makefile
+++ b/src/egl/main/Makefile
@@ -58,6 +58,9 @@ LOCAL_LIBS =
 ifeq ($(filter dri2, $(EGL_DRIVERS_DIRS)),dri2)
 LOCAL_CFLAGS += -D_EGL_BUILT_IN_DRIVER_DRI2
 LOCAL_LIBS += $(TOP)/src/egl/drivers/dri2/libegl_dri2.a
+ifneq ($(findstring wayland, $(EGL_PLATFORMS)),)
+LOCAL_LIBS += $(TOP)/src/egl/wayland/wayland-drm/libwayland-drm.a
+endif
 EGL_LIB_DEPS += $(XCB_DRI2_LIBS) $(LIBUDEV_LIBS) $(DLOPEN_LIBS) $(LIBDRM_LIB) $(WAYLAND_LIBS)
 endif
 ifeq ($(filter glx, $(EGL_DRIVERS_DIRS)),glx)
diff --git a/src/egl/main/eglapi.c b/src/egl/main/eglapi.c
index 4e64ce6..19dfd57 100644
--- a/src/egl/main/eglapi.c
+++ b/src/egl/main/eglapi.c
@@ -914,6 +914,10 @@ eglGetProcAddress(const char *procname)
       { "eglCreateDRMImageMESA", (_EGLProc) eglCreateDRMImageMESA },
       { "eglExportDRMImageMESA", (_EGLProc) eglExportDRMImageMESA },
 #endif
+#ifdef EGL_WL_bind_display
+      { "eglBindWaylandDisplayWL", (_EGLProc) eglBindWaylandDisplayWL },
+      { "eglUnbindWaylandDisplayWL", (_EGLProc) eglUnbindWaylandDisplayWL },
+#endif
       { NULL, NULL }
    };
    EGLint i;
@@ -1491,3 +1495,43 @@ eglExportDRMImageMESA(EGLDisplay dpy, EGLImageKHR image,
 }
 
 #endif
+
+#ifdef EGL_WL_bind_wayland_display
+struct wl_display;
+
+EGLBoolean EGLAPIENTRY
+eglBindWaylandDisplayWL(EGLDisplay dpy, struct wl_display *display)
+{
+   _EGLDisplay *disp = _eglLockDisplay(dpy);
+   _EGLDriver *drv;
+   EGLBoolean ret;
+
+   _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
+   assert(disp->Extensions.WL_bind_wayland_display);
+
+   if (!display)
+      RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
+
+   ret = drv->API.BindWaylandDisplayWL(drv, disp, display);
+
+   RETURN_EGL_EVAL(disp, ret);
+}
+
+EGLBoolean EGLAPIENTRY
+eglUnbindWaylandDisplayWL(EGLDisplay dpy, struct wl_display *display)
+{
+   _EGLDisplay *disp = _eglLockDisplay(dpy);
+   _EGLDriver *drv;
+   EGLBoolean ret;
+
+   _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
+   assert(disp->Extensions.WL_bind_wayland_display);
+
+   if (!display)
+      RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
+
+   ret = drv->API.UnbindWaylandDisplayWL(drv, disp, display);
+
+   RETURN_EGL_EVAL(disp, ret);
+}
+#endif
diff --git a/src/egl/main/eglapi.h b/src/egl/main/eglapi.h
index 0149208..c9913f1 100644
--- a/src/egl/main/eglapi.h
+++ b/src/egl/main/eglapi.h
@@ -95,6 +95,12 @@ typedef _EGLImage *(*CreateDRMImageMESA_t)(_EGLDriver *drv, _EGLDisplay *disp, c
 typedef EGLBoolean (*ExportDRMImageMESA_t)(_EGLDriver *drv, _EGLDisplay *disp, _EGLImage *img, EGLint *name, EGLint *handle, EGLint *stride);
 #endif
 
+#ifdef EGL_WL_bind_wayland_display
+struct wl_display;
+typedef EGLBoolean (*BindWaylandDisplayWL_t)(_EGLDriver *drv, _EGLDisplay *disp, struct wl_display *display);
+typedef EGLBoolean (*UnbindWaylandDisplayWL_t)(_EGLDriver *drv, _EGLDisplay *disp, struct wl_display *display);
+#endif
+
 /**
  * The API dispatcher jumps through these functions
  */
@@ -169,6 +175,11 @@ struct _egl_api
    CreateDRMImageMESA_t CreateDRMImageMESA;
    ExportDRMImageMESA_t ExportDRMImageMESA;
 #endif
+
+#ifdef EGL_WL_bind_wayland_display
+   BindWaylandDisplayWL_t BindWaylandDisplayWL;
+   UnbindWaylandDisplayWL_t UnbindWaylandDisplayWL;
+#endif
 };
 
 #endif /* EGLAPI_INCLUDED */
diff --git a/src/egl/main/egldisplay.h b/src/egl/main/egldisplay.h
index ce035eb..97ae2b0 100644
--- a/src/egl/main/egldisplay.h
+++ b/src/egl/main/egldisplay.h
@@ -58,6 +58,8 @@ struct _egl_extensions
    EGLBoolean MESA_drm_display;
    EGLBoolean MESA_drm_image;
 
+   EGLBoolean WL_bind_wayland_display;
+
    EGLBoolean KHR_image_base;
    EGLBoolean KHR_image_pixmap;
    EGLBoolean KHR_vg_parent_image;
diff --git a/src/egl/main/eglmisc.c b/src/egl/main/eglmisc.c
index f8ba5f3..6bb2498 100644
--- a/src/egl/main/eglmisc.c
+++ b/src/egl/main/eglmisc.c
@@ -89,6 +89,8 @@ _eglUpdateExtensionsString(_EGLDisplay *dpy)
    _EGL_CHECK_EXTENSION(MESA_drm_display);
    _EGL_CHECK_EXTENSION(MESA_drm_image);
 
+   _EGL_CHECK_EXTENSION(WL_bind_wayland_display);
+
    _EGL_CHECK_EXTENSION(KHR_image_base);
    _EGL_CHECK_EXTENSION(KHR_image_pixmap);
    if (dpy->Extensions.KHR_image_base && dpy->Extensions.KHR_image_pixmap)
diff --git a/src/egl/wayland/Makefile b/src/egl/wayland/Makefile
index 4cd0365..3499aef 100644
--- a/src/egl/wayland/Makefile
+++ b/src/egl/wayland/Makefile
@@ -1,4 +1,4 @@
-# src/egl/main/Makefile
+# src/egl/wayland/Makefile
 
 TOP = ../../..
 include $(TOP)/configs/current
@@ -10,14 +10,20 @@ SOURCES = wayland-egl.c
 
 OBJECTS = $(SOURCES:.c=.o)
 
-LOCAL_CFLAGS = -I$(TOP)/include/EGL $(LIBDRM_CFLAGS) $(WAYLAND_CFLAGS)
+LOCAL_CFLAGS = -I$(TOP)/include/EGL \
+	       -I$(TOP)/src/egl/wayland/wayland-drm \
+	       $(LIBDRM_CFLAGS) \
+	       $(WAYLAND_CFLAGS)
+
 LOCAL_LIBS =
 
+SUBDIRS = wayland-drm
+
 .c.o:
 	$(CC) -c $(INCLUDE_DIRS) $(CFLAGS) $(LOCAL_CFLAGS) $< -o $@
 
 
-default: depend library
+default: depend subdirs library
 
 # wayland-egl Library
 library: $(TOP)/$(LIB_DIR)/$(WAYLAND_EGL_LIB_NAME)
@@ -54,6 +60,12 @@ clean:
 	-rm -f *.o
 	-rm -f depend depend.bak
 
+subdirs:
+	@for dir in $(SUBDIRS) ; do \
+		if [ -d $$dir ] ; then \
+			(cd $$dir && $(MAKE)) || exit 1 ; \
+		fi \
+	done
 
 depend: $(SOURCES) $(HEADERS)
 	@ echo "running $(MKDEP)"
diff --git a/src/egl/wayland/wayland-drm/.gitignore b/src/egl/wayland/wayland-drm/.gitignore
new file mode 100644
index 0000000..f4ed848
--- /dev/null
+++ b/src/egl/wayland/wayland-drm/.gitignore
@@ -0,0 +1,3 @@
+wayland-drm-client-protocol.h
+wayland-drm-server-protocol.h
+wayland-drm-protocol.c
diff --git a/src/egl/wayland/wayland-drm/Makefile b/src/egl/wayland/wayland-drm/Makefile
new file mode 100644
index 0000000..c232769
--- /dev/null
+++ b/src/egl/wayland/wayland-drm/Makefile
@@ -0,0 +1,45 @@
+# src/egl/wayland/wayland-drm/Makefile
+
+TOP = ../../../..
+include $(TOP)/configs/current
+
+GEN_SOURCES = wayland-drm-protocol.c
+
+GEN_HEADERS = wayland-drm-client-protocol.h wayland-drm-server-protocol.h
+
+wayland_drm_SOURCES = wayland-drm.c $(GEN_SOURCES)
+wayland_drm_OBJECTS = $(wayland_drm_SOURCES:.c=.o)
+
+wayland_drm_INCLUDES = \
+		$(WAYLAND_CFLAGS) \
+		-I$(TOP)/src/egl/main
+
+# Generate protocol sources
+prefix=$(shell pkg-config --variable=prefix wayland-server)
+exec_prefx=$(shell pkg-config --variable=exec_prefix wayland-server)
+wayland_protocoldir = $(PWD)/protocol
+wayland_scanner=$(exec_prefix)/bin/wayland-scanner
+
+default: depend libwayland-drm.a $(GEN_SOURCES) $(GEN_HEADERS)
+
+libwayland-drm.a: $(wayland_drm_OBJECTS) Makefile
+	$(MKLIB) -o wayland-drm -static $(wayland_drm_OBJECTS)
+ 
+depend: 
+	rm -f depend
+	touch depend
+	$(MKDEP) $(MKDEP_OPTIONS) $(wayland_drm_INCLUDES) $(wayland_drm_SOURCES) 2> /dev/null
+
+clean:
+	rm -rf libwayland-drm.a $(wayland_drm_OBJECTS) \
+		$(GEN_SOURCES) $(GEN_HEADERS)
+
+install:
+	@echo -n ""
+
+$(wayland_drm_OBJECTS): %.o: %.c $(GEN_HEADERS)
+	$(CC) -c $(wayland_drm_INCLUDES) $(CFLAGS) $< -o $@
+
+include $(prefix)/share/aclocal/wayland-scanner.mk
+
+sinclude depend
diff --git a/src/egl/wayland/wayland-drm/protocol/wayland-drm.xml b/src/egl/wayland/wayland-drm/protocol/wayland-drm.xml
new file mode 100644
index 0000000..46725d8
--- /dev/null
+++ b/src/egl/wayland/wayland-drm/protocol/wayland-drm.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<protocol name="drm">
+  <!-- drm support. This object is created by the server and published
+       using the display's global event. -->
+  <interface name="drm" version="1">
+    <!-- Call this request with the magic received from drmGetMagic().
+         It will be passed on to the drmAuthMagic() or
+         DRIAuthConnection() call.  This authentication must be
+         completed before create_buffer could be used. -->
+    <request name="authenticate">
+      <arg name="id" type="uint"/>
+    </request>
+
+    <!-- Create a wayland buffer for the named DRM buffer.  The DRM
+         surface must have a name using the flink ioctl -->
+    <request name="create_buffer">
+      <arg name="id" type="new_id" interface="buffer"/>
+      <arg name="name" type="uint"/>
+      <arg name="width" type="int"/>
+      <arg name="height" type="int"/>
+      <arg name="stride" type="uint"/>
+      <arg name="visual" type="object" interface="visual"/>
+    </request>
+
+    <!-- Notification of the path of the drm device which is used by
+         the server.  The client should use this device for creating
+         local buffers.  Only buffers created from this device should
+         be be passed to the server using this drm object's
+         create_buffer request. -->
+    <event name="device">
+      <arg name="name" type="string"/>
+    </event>
+
+    <!-- Raised if the authenticate request succeeded -->
+    <event name="authenticated"/>
+  </interface>
+
+</protocol>
diff --git a/src/egl/wayland/wayland-drm/wayland-drm.c b/src/egl/wayland/wayland-drm/wayland-drm.c
new file mode 100644
index 0000000..6624fbe
--- /dev/null
+++ b/src/egl/wayland/wayland-drm/wayland-drm.c
@@ -0,0 +1,203 @@
+/*
+ * Copyright © 2011 Kristian Høgsberg
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Kristian Høgsberg <krh at bitplanet.net>
+ *    Benjamin Franzke <benjaminfranzke at googlemail.com>
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stddef.h>
+
+#include <wayland-server.h>
+#include "wayland-drm.h"
+#include "wayland-drm-server-protocol.h"
+
+#include "egldisplay.h"
+#include "egldriver.h"
+#include "eglimage.h"
+#include "egltypedefs.h"
+
+struct wl_drm {
+	struct wl_object object;
+	struct wl_display *display;
+
+	_EGLDisplay *edisp;
+
+	char *device_name;
+	authenticate_t authenticate;
+};
+
+static void
+drm_buffer_damage(struct wl_buffer *buffer_base,
+		  struct wl_surface *surface,
+		  int32_t x, int32_t y, int32_t width, int32_t height)
+{
+}
+
+static void
+destroy_buffer(struct wl_resource *resource, struct wl_client *client)
+{
+	struct wl_drm_buffer *buffer = (struct wl_drm_buffer *) resource;
+	_EGLDriver *drv = buffer->drm->edisp->Driver;
+
+	drv->API.DestroyImageKHR(drv, buffer->drm->edisp, buffer->image);
+	free(buffer);
+}
+
+static void
+buffer_destroy(struct wl_client *client, struct wl_buffer *buffer)
+{
+	wl_resource_destroy(&buffer->resource, client);
+}
+
+const static struct wl_buffer_interface buffer_interface = {
+	buffer_destroy
+};
+
+static void
+drm_create_buffer(struct wl_client *client, struct wl_drm *drm,
+		  uint32_t id, uint32_t name, int32_t width, int32_t height,
+		  uint32_t stride, struct wl_visual *visual)
+{
+	struct wl_drm_buffer *buffer;
+	EGLint attribs[] = {
+		EGL_WIDTH,		0,
+		EGL_HEIGHT,		0,
+		EGL_DRM_BUFFER_STRIDE_MESA,	0,
+		EGL_DRM_BUFFER_FORMAT_MESA,	EGL_DRM_BUFFER_FORMAT_ARGB32_MESA,
+		EGL_NONE
+	};
+	_EGLDriver *drv = drm->edisp->Driver;
+
+	buffer = malloc(sizeof *buffer);
+	if (buffer == NULL) {
+		wl_client_post_no_memory(client);
+		return;
+	}
+
+	buffer->drm = drm;
+	buffer->buffer.compositor = NULL;
+	buffer->buffer.width = width;
+	buffer->buffer.height = height;
+	buffer->buffer.visual = visual;
+	buffer->buffer.attach = NULL;
+	buffer->buffer.damage = drm_buffer_damage;
+
+	if (visual->object.interface != &wl_visual_interface) {
+		/* FIXME: Define a real exception event instead of
+		 * abusing this one */
+		wl_client_post_event(client,
+				     (struct wl_object *) drm->display,
+				     WL_DISPLAY_INVALID_OBJECT, 0);
+		fprintf(stderr, "invalid visual in create_buffer\n");
+		return;
+	}
+
+	attribs[1] = width;
+	attribs[3] = height;
+	attribs[5] = stride / 4;
+	buffer->image = drv->API.CreateImageKHR(drv, drm->edisp,
+						EGL_NO_CONTEXT,
+						EGL_DRM_BUFFER_MESA,
+						(EGLClientBuffer) (intptr_t) name,
+						attribs);
+
+	if (buffer->image == NULL) {
+		/* FIXME: Define a real exception event instead of
+		 * abusing this one */
+		wl_client_post_event(client,
+				     (struct wl_object *) drm->display,
+				     WL_DISPLAY_INVALID_OBJECT, 0);
+		fprintf(stderr, "failed to create image for name %d\n", name);
+		return;
+	}
+
+	buffer->buffer.resource.object.id = id;
+	buffer->buffer.resource.object.interface = &wl_buffer_interface;
+	buffer->buffer.resource.object.implementation = (void (**)(void))
+		&buffer_interface;
+
+	buffer->buffer.resource.destroy = destroy_buffer;
+
+	wl_client_add_resource(client, &buffer->buffer.resource);
+}
+
+static void
+drm_authenticate(struct wl_client *client,
+		 struct wl_drm *drm, uint32_t id)
+{
+	if (drm->authenticate(drm->edisp, id) < 0)
+		wl_client_post_event(client,
+				     (struct wl_object *) drm->display,
+				     WL_DISPLAY_INVALID_OBJECT, 0);
+	else
+		wl_client_post_event(client, &drm->object,
+				     WL_DRM_AUTHENTICATED);
+}
+
+const static struct wl_drm_interface drm_interface = {
+	drm_authenticate,
+	drm_create_buffer
+};
+
+static void
+post_drm_device(struct wl_client *client, struct wl_object *global)
+{
+	struct wl_drm *drm = (struct wl_drm *) global;
+
+	wl_client_post_event(client, global, WL_DRM_DEVICE, drm->device_name);
+}
+
+struct wl_drm *
+wayland_drm_init(struct wl_display *display, _EGLDisplay *disp,
+		 authenticate_t authenticate, char *device_name)
+{
+	struct wl_drm *drm;
+
+	drm = malloc(sizeof *drm);
+
+	drm->display = display;
+	drm->edisp = disp;
+	drm->authenticate = authenticate;
+	drm->device_name = strdup(device_name);
+
+	drm->object.interface = &wl_drm_interface;
+	drm->object.implementation = (void (**)(void)) &drm_interface;
+	wl_display_add_object(display, &drm->object);
+	wl_display_add_global(display, &drm->object, post_drm_device);
+
+	return drm;
+}
+
+void
+wayland_drm_destroy(struct wl_drm *drm)
+{
+	free(drm->device_name);
+
+	/* FIXME: need wl_display_del_{object,global} */
+
+	free(drm);
+}
diff --git a/src/egl/wayland/wayland-drm/wayland-drm.h b/src/egl/wayland/wayland-drm/wayland-drm.h
new file mode 100644
index 0000000..675a6a5
--- /dev/null
+++ b/src/egl/wayland/wayland-drm/wayland-drm.h
@@ -0,0 +1,26 @@
+#ifndef WAYLAND_DRM_H
+#define WAYLAND_DRM_H
+
+#include "egldisplay.h"
+#include "eglimage.h"
+
+#include <wayland-server.h>
+
+struct wl_drm;
+
+typedef int (*authenticate_t) (_EGLDisplay *disp, uint32_t id);
+
+struct wl_drm_buffer {
+	struct wl_buffer buffer;
+	struct wl_drm *drm;
+	_EGLImage *image;
+};
+
+struct wl_drm *
+wayland_drm_init(struct wl_display *display, _EGLDisplay *disp,
+		 authenticate_t authenticate, char *device_name);
+
+void
+wayland_drm_destroy(struct wl_drm *drm);
+
+#endif
diff --git a/src/egl/wayland/wayland-egl.c b/src/egl/wayland/wayland-egl.c
index 12fbdfa..2c84bec 100644
--- a/src/egl/wayland/wayland-egl.c
+++ b/src/egl/wayland/wayland-egl.c
@@ -12,10 +12,10 @@
 #include <dlfcn.h>
 
 #include <wayland-client.h>
-#include <xf86drm.h>
-
 #include "wayland-egl.h"
 #include "wayland-egl-priv.h"
+#include "wayland-drm-client-protocol.h"
+#include <xf86drm.h>
 
 static void
 drm_handle_device(void *data, struct wl_drm *drm, const char *device)
diff --git a/src/gallium/state_trackers/egl/Makefile b/src/gallium/state_trackers/egl/Makefile
index 98167cc..6864321 100644
--- a/src/gallium/state_trackers/egl/Makefile
+++ b/src/gallium/state_trackers/egl/Makefile
@@ -26,6 +26,7 @@ x11_OBJECTS = $(x11_SOURCES:.c=.o)
 wayland_INCLUDES = \
 	-I$(TOP)/src/gallium/winsys \
 	-I$(TOP)/src/egl/wayland \
+	-I$(TOP)/src/egl/wayland/wayland-drm \
 	$(shell pkg-config --cflags-only-I libdrm wayland-client)
 
 wayland_SOURCES = $(wildcard wayland/*.c)
diff --git a/src/gallium/state_trackers/egl/wayland/native_wayland.c b/src/gallium/state_trackers/egl/wayland/native_wayland.c
index b10fc54..068c3cd 100644
--- a/src/gallium/state_trackers/egl/wayland/native_wayland.c
+++ b/src/gallium/state_trackers/egl/wayland/native_wayland.c
@@ -41,6 +41,7 @@
 #include "radeon/drm/radeon_drm_public.h"
 
 #include <wayland-client.h>
+#include "wayland-drm-client-protocol.h"
 #include "wayland-egl-priv.h"
 
 #include <xf86drm.h>




More information about the mesa-commit mailing list