diff options
author | Neil Roberts <[email protected]> | 2013-10-28 15:07:03 +0000 |
---|---|---|
committer | Kristian Høgsberg <[email protected]> | 2013-12-04 17:04:57 -0800 |
commit | 5cddb1ce3c9890435374ae3e03fc4a5b57dee314 (patch) | |
tree | 97be439739da18c825b2941f846edb0709f280bd /src/egl/drivers | |
parent | bce64c6c83122b1f4a684cc7890c7a61d2f9ffd7 (diff) |
wayland: Add an extension to create wl_buffers from EGLImages
This adds an extension called EGL_WL_create_wayland_buffer_from_image
which adds the following single function:
struct wl_buffer *
eglCreateWaylandBufferFromImageWL(EGLDisplay dpy, EGLImageKHR image);
The function creates a wl_buffer which shares its contents with the given
EGLImage. The expected use case for this is in a nested Wayland compositor
which is using subsurfaces to present buffers from its clients. Using this
extension it can attach the client buffers directly to the subsurface without
having to blit the contents into an intermediate buffer. The compositing can
then be done in the parent compositor.
The extension is only implemented in the Wayland EGL platform because of
course it wouldn't make sense anywhere else.
Diffstat (limited to 'src/egl/drivers')
-rw-r--r-- | src/egl/drivers/dri2/platform_wayland.c | 78 |
1 files changed, 78 insertions, 0 deletions
diff --git a/src/egl/drivers/dri2/platform_wayland.c b/src/egl/drivers/dri2/platform_wayland.c index 43e8f4b0c5a..443bdcaeda3 100644 --- a/src/egl/drivers/dri2/platform_wayland.c +++ b/src/egl/drivers/dri2/platform_wayland.c @@ -651,6 +651,81 @@ dri2_swap_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw) return dri2_swap_buffers_with_damage (drv, disp, draw, NULL, 0); } +static struct wl_buffer * +dri2_create_wayland_buffer_from_image_wl(_EGLDriver *drv, + _EGLDisplay *disp, + _EGLImage *img) +{ + struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); + struct dri2_egl_image *dri2_img = dri2_egl_image(img); + __DRIimage *image = dri2_img->dri_image; + struct wl_buffer *buffer; + int width, height, format, pitch; + enum wl_drm_format wl_format; + + dri2_dpy->image->queryImage(image, __DRI_IMAGE_ATTRIB_FORMAT, &format); + + switch (format) { + case __DRI_IMAGE_FORMAT_ARGB8888: + if (!(dri2_dpy->formats & HAS_ARGB8888)) + goto bad_format; + wl_format = WL_DRM_FORMAT_ARGB8888; + break; + case __DRI_IMAGE_FORMAT_XRGB8888: + if (!(dri2_dpy->formats & HAS_XRGB8888)) + goto bad_format; + wl_format = WL_DRM_FORMAT_XRGB8888; + break; + default: + goto bad_format; + } + + dri2_dpy->image->queryImage(image, __DRI_IMAGE_ATTRIB_WIDTH, &width); + dri2_dpy->image->queryImage(image, __DRI_IMAGE_ATTRIB_HEIGHT, &height); + dri2_dpy->image->queryImage(image, __DRI_IMAGE_ATTRIB_STRIDE, &pitch); + + if (dri2_dpy->capabilities & WL_DRM_CAPABILITY_PRIME) { + int fd; + + dri2_dpy->image->queryImage(image, __DRI_IMAGE_ATTRIB_FD, &fd); + + buffer = + wl_drm_create_prime_buffer(dri2_dpy->wl_drm, + fd, + width, height, + wl_format, + 0, pitch, + 0, 0, + 0, 0); + + close(fd); + } else { + int name; + + dri2_dpy->image->queryImage(image, __DRI_IMAGE_ATTRIB_NAME, &name); + + buffer = + wl_drm_create_buffer(dri2_dpy->wl_drm, + name, + width, height, + pitch, + wl_format); + } + + /* The buffer object will have been created with our internal event queue + * because it is using the wl_drm object as a proxy factory. We want the + * buffer to be used by the application so we'll reset it to the display's + * default event queue */ + if (buffer) + wl_proxy_set_queue((struct wl_proxy *) buffer, NULL); + + return buffer; + +bad_format: + _eglError(EGL_BAD_MATCH, "unsupported image format"); + return NULL; +} + static int dri2_wayland_authenticate(_EGLDisplay *disp, uint32_t id) { @@ -812,6 +887,8 @@ dri2_initialize_wayland(_EGLDriver *drv, _EGLDisplay *disp) drv->API.SwapBuffersWithDamageEXT = dri2_swap_buffers_with_damage; drv->API.Terminate = dri2_terminate; drv->API.QueryBufferAge = dri2_query_buffer_age; + drv->API.CreateWaylandBufferFromImageWL = + dri2_create_wayland_buffer_from_image_wl; dri2_dpy = calloc(1, sizeof *dri2_dpy); if (!dri2_dpy) @@ -892,6 +969,7 @@ dri2_initialize_wayland(_EGLDriver *drv, _EGLDisplay *disp) } disp->Extensions.WL_bind_wayland_display = EGL_TRUE; + disp->Extensions.WL_create_wayland_buffer_from_image = EGL_TRUE; disp->Extensions.EXT_buffer_age = EGL_TRUE; dri2_dpy->authenticate = dri2_wayland_authenticate; |