diff options
author | Kristian Høgsberg <[email protected]> | 2013-02-02 12:26:12 -0500 |
---|---|---|
committer | Kristian Høgsberg <[email protected]> | 2013-03-18 21:15:41 -0400 |
commit | de315f76a266ce51ca0638b9ea2ec3ccfd31f03b (patch) | |
tree | 2b467ec888d24b2645bbdb0e6c0cad7204d520aa /src/egl/drivers | |
parent | 2356e28452454ed3b584af9b4d28c553c2a80769 (diff) |
wayland: Add prime fd passing as a buffer sharing mechanism
Reviewed-by: Ander Conselvan de Oliveira <[email protected]>
Diffstat (limited to 'src/egl/drivers')
-rw-r--r-- | src/egl/drivers/dri2/egl_dri2.c | 37 | ||||
-rw-r--r-- | src/egl/drivers/dri2/egl_dri2.h | 1 | ||||
-rw-r--r-- | src/egl/drivers/dri2/platform_wayland.c | 69 |
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); } } |