From 6b369c4c7cd8a52f99bbff2a57fb316b33a87495 Mon Sep 17 00:00:00 2001 From: Benjamin Franzke Date: Mon, 21 Feb 2011 16:22:34 +0100 Subject: egl: Add EGL_WL_bind_wayland_display --- 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 +++++++++++----- 6 files changed, 224 insertions(+), 17 deletions(-) (limited to 'src/egl/drivers') diff --git a/src/egl/drivers/dri2/Makefile b/src/egl/drivers/dri2/Makefile index 89e9dd7970..eac599e674 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 99f87f076c..015b801c75 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 235e30df3d..5afd3d3c9c 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 +#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 3dab899dec..bd4fa80af5 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 21b440624f..6ae3f6554b 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 +#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 50310eec5a..c7bdfa6287 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; -- cgit v1.2.3