[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