egl: Add EGL_WL_bind_wayland_display
authorBenjamin Franzke <benjaminfranzke@googlemail.com>
Mon, 21 Feb 2011 15:22:34 +0000 (16:22 +0100)
committerKristian Høgsberg <krh@bitplanet.net>
Tue, 1 Mar 2011 22:23:50 +0000 (17:23 -0500)
24 files changed:
configure.ac
docs/WL_bind_wayland_display.spec [new file with mode: 0644]
include/EGL/eglext.h
src/egl/Makefile
src/egl/drivers/dri2/Makefile
src/egl/drivers/dri2/egl_dri2.c
src/egl/drivers/dri2/egl_dri2.h
src/egl/drivers/dri2/platform_drm.c
src/egl/drivers/dri2/platform_wayland.c
src/egl/drivers/dri2/platform_x11.c
src/egl/main/Makefile
src/egl/main/eglapi.c
src/egl/main/eglapi.h
src/egl/main/egldisplay.h
src/egl/main/eglmisc.c
src/egl/wayland/Makefile
src/egl/wayland/wayland-drm/.gitignore [new file with mode: 0644]
src/egl/wayland/wayland-drm/Makefile [new file with mode: 0644]
src/egl/wayland/wayland-drm/protocol/wayland-drm.xml [new file with mode: 0644]
src/egl/wayland/wayland-drm/wayland-drm.c [new file with mode: 0644]
src/egl/wayland/wayland-drm/wayland-drm.h [new file with mode: 0644]
src/egl/wayland/wayland-egl.c
src/gallium/state_trackers/egl/Makefile
src/gallium/state_trackers/egl/wayland/native_wayland.c

index dcfddb1ed9950bc6c9d2f8d8765af18b756ee057..9fa5eeea18699de04442a164bc850229e3681cac 100644 (file)
@@ -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 (file)
index 0000000..0ff49d6
--- /dev/null
@@ -0,0 +1,92 @@
+Name
+
+    WL_bind_wayland_display
+
+Name Strings
+
+    EGL_WL_bind_wayland_display
+
+Contact
+
+    Kristian Høgsberg <krh@bitplanet.net>
+    Benjamin Franzke <benjaminfranzke@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)
index 04603931b3844a1fdb65fba824bfc4f9b034cbb9..fa523a51d6718dcf1e5ddfc4de1dff47bb39f74f 100644 (file)
@@ -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
index 52daf2efa7e2705dd22cba96ec94acfcfc398aec..361f6889580a2a781de19ec37bd9e747e8cf45cf 100644 (file)
@@ -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
 
index 89e9dd7970a46c3b6d188a3c25d3f28e892a54b8..eac599e6745fa896948ef97707103bfdc1209388 100644 (file)
@@ -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
index 99f87f076c1dba4b9661f4ba87ae903b39351911..015b801c75793079d9089746cafabac2af6b2dfe 100644 (file)
@@ -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;
index 235e30df3d87b353df836ac0050c2cf09ab48464..5afd3d3c9c8601b0f04f39204439ba7f9d522715 100644 (file)
@@ -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
index 3dab899decb479aa5f9bbc6e4a898e36d615a351..bd4fa80af59780fe4513e537d63e18e37ce2db47 100644 (file)
@@ -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);
 
index 21b440624ff14b69f73384bb224520a48f386fe8..6ae3f6554b16ef91d544fe96862814a88afc9b04 100644 (file)
@@ -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:
index 50310eec5a9c385ed392aef55fb5ba34dbd4215e..c7bdfa628765c04c016290788a639d0be9270e3d 100644 (file)
@@ -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;
index a5b929950205beaf4df4b49a9311145f9afc44ab..820788d696b42081e6612437c356d0e229b73072 100644 (file)
@@ -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)
index 4e64ce6f7188108c9c4f44a75f8ba0702f7204ec..19dfd574268852c8acbd3942086357c33cf7a73f 100644 (file)
@@ -913,6 +913,10 @@ eglGetProcAddress(const char *procname)
 #ifdef EGL_MESA_drm_image
       { "eglCreateDRMImageMESA", (_EGLProc) eglCreateDRMImageMESA },
       { "eglExportDRMImageMESA", (_EGLProc) eglExportDRMImageMESA },
+#endif
+#ifdef EGL_WL_bind_display
+      { "eglBindWaylandDisplayWL", (_EGLProc) eglBindWaylandDisplayWL },
+      { "eglUnbindWaylandDisplayWL", (_EGLProc) eglUnbindWaylandDisplayWL },
 #endif
       { NULL, NULL }
    };
@@ -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
index 01492082f66581ad14648d196771251fd59aa81d..c9913f10a10e79934484083e3b7590fc24a75943 100644 (file)
@@ -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 */
index ce035eb2ef124255003bc3dc2af51ef0c878137a..97ae2b01ba01b2ebe9112909b67de1773aa47f41 100644 (file)
@@ -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;
index f8ba5f33eb949092e3a1f31b464fde920deceb52..6bb2498eef468071f890f66531fb1081501210cd 100644 (file)
@@ -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)
index 4cd036519db841a43533d5d4384db47ff43bc37d..3499aef0486868f9d127f250717dea8a3b862b93 100644 (file)
@@ -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 (file)
index 0000000..f4ed848
--- /dev/null
@@ -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 (file)
index 0000000..c232769
--- /dev/null
@@ -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 (file)
index 0000000..46725d8
--- /dev/null
@@ -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 (file)
index 0000000..6624fbe
--- /dev/null
@@ -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@bitplanet.net>
+ *    Benjamin Franzke <benjaminfranzke@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 (file)
index 0000000..675a6a5
--- /dev/null
@@ -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
index 12fbdfa29c15551778e373af66738eab6afba44a..2c84bec64a5dd2cfe304cfd751ea8b2dfcc34b25 100644 (file)
 #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)
index 98167cceeb3770727f8cfddd1018108d4c9c2446..686432140608bf1e684c375d7e361d2d506a591b 100644 (file)
@@ -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)
index b10fc54adb8033159d6e55b77445cde137bf7308..068c3cd7c8e5f5b41fdc05a5ea156dc9e3708086 100644 (file)
@@ -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>