[PATCH] wayland: Add an extension to create wl_buffers from EGLImages
Axel Davy
axel.davy at ens.fr
Mon Sep 9 09:44:39 PDT 2013
I think there is a problem with tiling handling in your patch.
Thinks of a session compositor running on an other graphic card for example.
Main compositor: card A
session compositor: card B. buffer is shared between A and B and when
creating it, tiling was disabled (because A and B share no tiling mode)
clients in the session compositor: card B. buffer is created on B, when
creating it, tiling was enabled.
In this configuration, your function should fail or do a copy (because A
won't recognize the tiling mode of B)
Axel Davy
> 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.
> ---
> .../specs/WL_create_wayland_buffer_from_image.spec | 85
> ++++++++++++++++++++++
> include/EGL/eglmesaext.h | 10 +++
> src/egl/drivers/dri2/platform_wayland.c | 71
> ++++++++++++++++++
> src/egl/main/eglapi.c | 25 +++++++
> src/egl/main/eglapi.h | 8 ++
> src/egl/main/egldisplay.h | 1 +
> src/egl/main/eglmisc.c | 1 +
> 7 files changed, 201 insertions(+)
> create mode 100644 docs/specs/WL_create_wayland_buffer_from_image.spec
>
> diff --git a/docs/specs/WL_create_wayland_buffer_from_image.spec
> b/docs/specs/WL_create_wayland_buffer_from_image.spec
> new file mode 100644
> index 0000000..7e27695
> --- /dev/null
> +++ b/docs/specs/WL_create_wayland_buffer_from_image.spec
> @@ -0,0 +1,85 @@
> +Name
> +
> + WL_create_wayland_buffer_from_image
> +
> +Name Strings
> +
> + EGL_WL_create_wayland_buffer_from_image
> +
> +Contact
> +
> + Neil Roberts <neil.s.roberts at intel.com>
> +
> +Status
> +
> + Proposal
> +
> +Version
> +
> + Version 1, September 6, 2013
> +
> +Number
> +
> + EGL Extension #not assigned
> +
> +Dependencies
> +
> + Requires EGL 1.4 or later. This extension is written against the
> + wording of the EGL 1.4 specification.
> +
> + EGL_KHR_base_image is required.
> +
> +Overview
> +
> + This extension provides an entry point to create a wl_buffer which
> shares
> + its contents with a 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 nested compositor can create an EGLImage from a client buffer
> resource
> + using the existing WL_bind_wayland_display extension. It should also
> be
> + possible to create buffers using other types of images although there
> is
> + no expected use case for that.
> +
> +IP Status
> +
> + Open-source; freely implementable.
> +
> +New Procedures and Functions
> +
> + struct wl_buffer *eglCreateWaylandBufferFromImageWL(EGLDisplay dpy,
> + EGLImageKHR
> image);
> +
> +New Tokens
> +
> + None.
> +
> +Additions to the EGL 1.4 Specification:
> +
> + To create a client-side wl_buffer from an EGLImage call
> +
> + struct wl_buffer *eglCreateWaylandBufferFromImageWL(EGLDisplay dpy,
> + EGLImageKHR
> image);
> +
> + The returned buffer will share the contents with the given EGLImage.
> Any
> + updates to the image will also be updated in the wl_buffer. Typically
> the
> + EGLImage will be generated in a nested Wayland compositor using a
> buffer
> + resource from a client via the EGL_WL_bind_wayland_display extension.
> +
> + If there was an error then the function will return NULL. In
> particular it
> + will generate EGL_BAD_MATCH if the image is not in a format which the
> + implementation can represent in a wl_buffer. It is
> implementation-defined
> + what formats and types of EGLImage will be successfully converted to
> a
> + wl_buffer without error.
> +
> +Issues
> +
> + None.
> +
> +Revision History
> +
> + Version 1, September 6, 2013
> + Initial draft (Neil Roberts)
> diff --git a/include/EGL/eglmesaext.h b/include/EGL/eglmesaext.h
> index e0eae28..0a65cb8 100644
> --- a/include/EGL/eglmesaext.h
> +++ b/include/EGL/eglmesaext.h
> @@ -132,6 +132,16 @@ typedef EGLBoolean (EGLAPIENTRYP
> PFNEGLQUERYWAYLANDBUFFERWL) (EGLDisplay dpy, st
>
> #endif
>
> +#ifndef EGL_WL_create_wayland_buffer_from_image
> +#define EGL_WL_create_wayland_buffer_from_image 1
> +
> +#ifdef EGL_EGLEXT_PROTOTYPES
> +EGLAPI struct wl_buffer * EGLAPIENTRY
> eglCreateWaylandBufferFromImageWL(EGLDisplay dpy, EGLImageKHR image);
> +#endif
> +typedef struct wl_buffer * (EGLAPIENTRYP
> PFNEGLCREATEWAYLANDBUFFERFROMIMAGEWL) (EGLDisplay dpy, EGLImageKHR image);
> +
> +#endif
> +
> #ifndef EGL_NOK_swap_region
> #define EGL_NOK_swap_region 1
>
> diff --git a/src/egl/drivers/dri2/platform_wayland.c
> b/src/egl/drivers/dri2/platform_wayland.c
> index 1d417bb..ee1a6bc 100644
> --- a/src/egl/drivers/dri2/platform_wayland.c
> +++ b/src/egl/drivers/dri2/platform_wayland.c
> @@ -586,6 +586,74 @@ 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);
> + }
> +
> + return buffer;
> +
> +bad_format:
> + _eglError(EGL_BAD_MATCH, "unsupported image format");
> + return NULL;
> +}
> +
> static int
> dri2_wayland_authenticate(_EGLDisplay *disp, uint32_t id)
> {
> @@ -743,6 +811,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)
> @@ -820,6 +890,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;
>
> diff --git a/src/egl/main/eglapi.c b/src/egl/main/eglapi.c
> index 2d8653f..5399932 100644
> --- a/src/egl/main/eglapi.c
> +++ b/src/egl/main/eglapi.c
> @@ -967,6 +967,9 @@ eglGetProcAddress(const char *procname)
> { "eglUnbindWaylandDisplayWL", (_EGLProc) eglUnbindWaylandDisplayWL
> },
> { "eglQueryWaylandBufferWL", (_EGLProc) eglQueryWaylandBufferWL },
> #endif
> +#ifdef EGL_WL_create_wayland_buffer_from_image
> + { "eglCreateWaylandBufferFromImageWL", (_EGLProc)
> eglCreateWaylandBufferFromImageWL },
> +#endif
> { "eglPostSubBufferNV", (_EGLProc) eglPostSubBufferNV },
> #ifdef EGL_EXT_swap_buffers_with_damage
> { "eglSwapBuffersWithDamageEXT", (_EGLProc)
> eglSwapBuffersWithDamageEXT },
> @@ -1595,6 +1598,28 @@ eglQueryWaylandBufferWL(EGLDisplay dpy, struct
> wl_resource *buffer,
> }
> #endif
>
> +#ifdef EGL_WL_create_wayland_buffer_from_image
> +struct wl_buffer * EGLAPIENTRY
> +eglCreateWaylandBufferFromImageWL(EGLDisplay dpy, EGLImageKHR image)
> +{
> + _EGLDisplay *disp = _eglLockDisplay(dpy);
> + _EGLImage *img;
> + _EGLDriver *drv;
> + struct wl_buffer *ret;
> +
> + _EGL_CHECK_DISPLAY(disp, NULL, drv);
> + assert(disp->Extensions.WL_create_wayland_buffer_from_image);
> +
> + img = _eglLookupImage(image, disp);
> +
> + if (!img)
> + RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, NULL);
> +
> + ret = drv->API.CreateWaylandBufferFromImageWL(drv, disp, img);
> +
> + RETURN_EGL_EVAL(disp, ret);
> +}
> +#endif
>
> EGLBoolean EGLAPIENTRY
> eglPostSubBufferNV(EGLDisplay dpy, EGLSurface surface,
> diff --git a/src/egl/main/eglapi.h b/src/egl/main/eglapi.h
> index 4a4f976..0580344 100644
> --- a/src/egl/main/eglapi.h
> +++ b/src/egl/main/eglapi.h
> @@ -126,6 +126,10 @@ typedef EGLBoolean
> (*UnbindWaylandDisplayWL_t)(_EGLDriver *drv, _EGLDisplay *dis
> typedef EGLBoolean (*QueryWaylandBufferWL_t)(_EGLDriver *drv, _EGLDisplay
> *displ, struct wl_resource *buffer, EGLint attribute, EGLint *value);
> #endif
>
> +#ifdef EGL_WL_create_wayland_buffer_from_image
> +typedef struct wl_buffer * (*CreateWaylandBufferFromImageWL_t)(_EGLDriver
> *drv, _EGLDisplay *disp, _EGLImage *img);
> +#endif
> +
> typedef EGLBoolean (*PostSubBufferNV_t)(_EGLDriver *drv, _EGLDisplay
> *disp, _EGLSurface *surface, EGLint x, EGLint y, EGLint width, EGLint
> height);
>
> typedef EGLint (*QueryBufferAge_t)(_EGLDriver *drv,
> @@ -210,6 +214,10 @@ struct _egl_api
> QueryWaylandBufferWL_t QueryWaylandBufferWL;
> #endif
>
> +#ifdef EGL_WL_create_wayland_buffer_from_image
> + CreateWaylandBufferFromImageWL_t CreateWaylandBufferFromImageWL;
> +#endif
> +
> #ifdef EGL_EXT_swap_buffers_with_damage
> SwapBuffersWithDamageEXT_t SwapBuffersWithDamageEXT;
> #endif /* EGL_EXT_swap_buffers_with_damage */
> diff --git a/src/egl/main/egldisplay.h b/src/egl/main/egldisplay.h
> index fefd19c..b95b2f7 100644
> --- a/src/egl/main/egldisplay.h
> +++ b/src/egl/main/egldisplay.h
> @@ -91,6 +91,7 @@ struct _egl_extensions
> EGLBoolean MESA_drm_image;
>
> EGLBoolean WL_bind_wayland_display;
> + EGLBoolean WL_create_wayland_buffer_from_image;
>
> EGLBoolean KHR_image_base;
> EGLBoolean KHR_image_pixmap;
> diff --git a/src/egl/main/eglmisc.c b/src/egl/main/eglmisc.c
> index 2decc1b..cff6166 100644
> --- a/src/egl/main/eglmisc.c
> +++ b/src/egl/main/eglmisc.c
> @@ -92,6 +92,7 @@ _eglUpdateExtensionsString(_EGLDisplay *dpy)
> _EGL_CHECK_EXTENSION(MESA_drm_image);
>
> _EGL_CHECK_EXTENSION(WL_bind_wayland_display);
> + _EGL_CHECK_EXTENSION(WL_create_wayland_buffer_from_image);
>
> _EGL_CHECK_EXTENSION(KHR_image_base);
> _EGL_CHECK_EXTENSION(KHR_image_pixmap);
> --
> 1.8.3.1
>
> _______________________________________________
> wayland-devel mailing list
> wayland-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/wayland-devel
>
More information about the wayland-devel
mailing list