summaryrefslogtreecommitdiffstats
path: root/src/egl/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'src/egl/drivers')
-rw-r--r--src/egl/drivers/dri2/Makefile6
-rw-r--r--src/egl/drivers/dri2/egl_dri2.c94
-rw-r--r--src/egl/drivers/dri2/egl_dri2.h4
-rw-r--r--src/egl/drivers/dri2/platform_drm.c56
-rw-r--r--src/egl/drivers/dri2/platform_wayland.c36
-rw-r--r--src/egl/drivers/dri2/platform_x11.c45
6 files changed, 224 insertions, 17 deletions
diff --git a/src/egl/drivers/dri2/Makefile b/src/egl/drivers/dri2/Makefile
index 89e9dd7970a..eac599e6745 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 99f87f076c1..015b801c757 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 235e30df3d8..5afd3d3c9c8 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 3dab899decb..bd4fa80af59 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 21b440624ff..6ae3f6554b1 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 50310eec5a9..c7bdfa62876 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;