summaryrefslogtreecommitdiff
path: root/src/egl/drivers
diff options
context:
space:
mode:
authorKristian Høgsberg <krh@bitplanet.net>2013-02-02 12:26:12 -0500
committerKristian Høgsberg <krh@bitplanet.net>2013-03-18 21:15:41 -0400
commitde315f76a266ce51ca0638b9ea2ec3ccfd31f03b (patch)
tree2b467ec888d24b2645bbdb0e6c0cad7204d520aa /src/egl/drivers
parent2356e28452454ed3b584af9b4d28c553c2a80769 (diff)
wayland: Add prime fd passing as a buffer sharing mechanism
Reviewed-by: Ander Conselvan de Oliveira <conselvan2@gmail.com>
Diffstat (limited to 'src/egl/drivers')
-rw-r--r--src/egl/drivers/dri2/egl_dri2.c37
-rw-r--r--src/egl/drivers/dri2/egl_dri2.h1
-rw-r--r--src/egl/drivers/dri2/platform_wayland.c69
3 files changed, 82 insertions, 25 deletions
diff --git a/src/egl/drivers/dri2/egl_dri2.c b/src/egl/drivers/dri2/egl_dri2.c
index b7749196c5d..a3aabf5ab51 100644
--- a/src/egl/drivers/dri2/egl_dri2.c
+++ b/src/egl/drivers/dri2/egl_dri2.c
@@ -320,7 +320,7 @@ static struct dri2_extension_match dri2_driver_extensions[] = {
static struct dri2_extension_match dri2_core_extensions[] = {
{ __DRI2_FLUSH, 1, offsetof(struct dri2_egl_display, flush) },
{ __DRI_TEX_BUFFER, 2, offsetof(struct dri2_egl_display, tex_buffer) },
- { __DRI_IMAGE, 1, offsetof(struct dri2_egl_display, image) },
+ { __DRI_IMAGE, 7, offsetof(struct dri2_egl_display, image) },
{ NULL, 0, 0 }
};
@@ -1498,7 +1498,7 @@ dri2_export_drm_image_mesa(_EGLDriver *drv, _EGLDisplay *disp, _EGLImage *img,
#ifdef HAVE_WAYLAND_PLATFORM
static void
-dri2_wl_reference_buffer(void *user_data, uint32_t name,
+dri2_wl_reference_buffer(void *user_data, uint32_t name, int fd,
struct wl_drm_buffer *buffer)
{
_EGLDisplay *disp = user_data;
@@ -1506,13 +1506,24 @@ dri2_wl_reference_buffer(void *user_data, uint32_t name,
__DRIimage *img;
int i, dri_components = 0;
- img = dri2_dpy->image->createImageFromNames(dri2_dpy->dri_screen,
- buffer->buffer.width,
- buffer->buffer.height,
- buffer->format, (int*)&name, 1,
- buffer->stride,
- buffer->offset,
- NULL);
+ if (fd == -1)
+ img = dri2_dpy->image->createImageFromNames(dri2_dpy->dri_screen,
+ buffer->buffer.width,
+ buffer->buffer.height,
+ buffer->format,
+ (int*)&name, 1,
+ buffer->stride,
+ buffer->offset,
+ NULL);
+ else
+ img = dri2_dpy->image->createImageFromFds(dri2_dpy->dri_screen,
+ buffer->buffer.width,
+ buffer->buffer.height,
+ buffer->format,
+ &fd, 1,
+ buffer->stride,
+ buffer->offset,
+ NULL);
if (img == NULL)
return;
@@ -1550,6 +1561,8 @@ dri2_bind_wayland_display_wl(_EGLDriver *drv, _EGLDisplay *disp,
struct wl_display *wl_dpy)
{
struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
+ int ret, flags = 0;
+ uint64_t cap;
(void) drv;
@@ -1559,9 +1572,13 @@ dri2_bind_wayland_display_wl(_EGLDriver *drv, _EGLDisplay *disp,
wl_drm_callbacks.authenticate =
(int(*)(void *, uint32_t)) dri2_dpy->authenticate;
+ ret = drmGetCap(dri2_dpy->fd, DRM_CAP_PRIME, &cap);
+ if (ret == 0 && cap == (DRM_PRIME_CAP_IMPORT | DRM_PRIME_CAP_EXPORT))
+ flags |= WAYLAND_DRM_PRIME;
+
dri2_dpy->wl_server_drm =
wayland_drm_init(wl_dpy, dri2_dpy->device_name,
- &wl_drm_callbacks, disp);
+ &wl_drm_callbacks, disp, flags);
if (!dri2_dpy->wl_server_drm)
return EGL_FALSE;
diff --git a/src/egl/drivers/dri2/egl_dri2.h b/src/egl/drivers/dri2/egl_dri2.h
index 7f3ed4e3745..6dfdf946fc8 100644
--- a/src/egl/drivers/dri2/egl_dri2.h
+++ b/src/egl/drivers/dri2/egl_dri2.h
@@ -132,6 +132,7 @@ struct dri2_egl_display
struct wl_event_queue *wl_queue;
int authenticated;
int formats;
+ uint32_t capabilities;
#endif
int (*authenticate) (_EGLDisplay *disp, uint32_t id);
diff --git a/src/egl/drivers/dri2/platform_wayland.c b/src/egl/drivers/dri2/platform_wayland.c
index b5cd04a5ec3..740fc7d4e0f 100644
--- a/src/egl/drivers/dri2/platform_wayland.c
+++ b/src/egl/drivers/dri2/platform_wayland.c
@@ -451,6 +451,46 @@ static const struct wl_callback_listener frame_listener = {
wayland_frame_callback
};
+static void
+create_wl_buffer(struct dri2_egl_surface *dri2_surf)
+{
+ struct dri2_egl_display *dri2_dpy =
+ dri2_egl_display(dri2_surf->base.Resource.Display);
+ int fd;
+
+ if (dri2_surf->current->wl_buffer != NULL)
+ return;
+
+ if (dri2_dpy->capabilities & WL_DRM_CAPABILITY_PRIME) {
+ dri2_dpy->image->queryImage(dri2_surf->current->dri_image,
+ __DRI_IMAGE_ATTRIB_FD, &fd);
+
+ dri2_surf->current->wl_buffer =
+ wl_drm_create_prime_buffer(dri2_dpy->wl_drm,
+ fd,
+ dri2_surf->base.Width,
+ dri2_surf->base.Height,
+ dri2_surf->format,
+ 0, dri2_surf->current->pitch,
+ 0, 0,
+ 0, 0);
+ close(fd);
+ } else {
+ dri2_surf->current->wl_buffer =
+ wl_drm_create_buffer(dri2_dpy->wl_drm,
+ dri2_surf->current->name,
+ dri2_surf->base.Width,
+ dri2_surf->base.Height,
+ dri2_surf->current->pitch,
+ dri2_surf->format);
+ }
+
+ wl_proxy_set_queue((struct wl_proxy *) dri2_surf->current->wl_buffer,
+ dri2_dpy->wl_queue);
+ wl_buffer_add_listener(dri2_surf->current->wl_buffer,
+ &wl_buffer_listener, dri2_surf);
+}
+
/**
* Called via eglSwapBuffers(), drv->API.SwapBuffers().
*/
@@ -488,19 +528,7 @@ dri2_swap_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw)
dri2_surf->current = dri2_surf->back;
dri2_surf->back = NULL;
- if (dri2_surf->current->wl_buffer == NULL) {
- dri2_surf->current->wl_buffer =
- wl_drm_create_buffer(dri2_dpy->wl_drm,
- dri2_surf->current->name,
- dri2_surf->base.Width,
- dri2_surf->base.Height,
- dri2_surf->current->pitch,
- dri2_surf->format);
- wl_proxy_set_queue((struct wl_proxy *) dri2_surf->current->wl_buffer,
- dri2_dpy->wl_queue);
- wl_buffer_add_listener(dri2_surf->current->wl_buffer,
- &wl_buffer_listener, dri2_surf);
- }
+ create_wl_buffer(dri2_surf);
wl_surface_attach(dri2_surf->wl_win->surface,
dri2_surf->current->wl_buffer,
@@ -630,6 +658,14 @@ drm_handle_format(void *data, struct wl_drm *drm, uint32_t format)
}
static void
+drm_handle_capabilities(void *data, struct wl_drm *drm, uint32_t value)
+{
+ struct dri2_egl_display *dri2_dpy = data;
+
+ dri2_dpy->capabilities = value;
+}
+
+static void
drm_handle_authenticated(void *data, struct wl_drm *drm)
{
struct dri2_egl_display *dri2_dpy = data;
@@ -640,7 +676,8 @@ drm_handle_authenticated(void *data, struct wl_drm *drm)
static const struct wl_drm_listener drm_listener = {
drm_handle_device,
drm_handle_format,
- drm_handle_authenticated
+ drm_handle_authenticated,
+ drm_handle_capabilities
};
static void
@@ -649,9 +686,11 @@ registry_handle_global(void *data, struct wl_registry *registry, uint32_t name,
{
struct dri2_egl_display *dri2_dpy = data;
+ if (version > 1)
+ version = 2;
if (strcmp(interface, "wl_drm") == 0) {
dri2_dpy->wl_drm =
- wl_registry_bind(registry, name, &wl_drm_interface, 1);
+ wl_registry_bind(registry, name, &wl_drm_interface, version);
wl_drm_add_listener(dri2_dpy->wl_drm, &drm_listener, dri2_dpy);
}
}