[PATCH v2] Adapt the EGL_WL_create_wayland_buffer_from_image extension for YUV

Neil Roberts neil at linux.intel.com
Fri Feb 14 09:46:57 PST 2014


Here is a second version of the patch based on feedback from Kristian.
Instead of modifying the existing eglCreateWaylandBufferFromImageWL
function it adds a second version to support passing multiple images.
The worry is that the original version of the extension is already
being used so it's a bit painful to change it in an incompatible way
now. The original function is probably a good convenience wrapper for
the common case where only one image is used anyway so I don't think
it's too messy to leave it in.

------- >8 --------------- (use git am --scissors to automatically chop here)

An additional function is added to the eglCreateWaylandBufferFromImageWL
extension which instead of just taking a single image can take a set of
images. Each EGLImage will represent a plane from a planar image. The overall
format for the combined set of images isn't stored in the EGLImages so instead
of trying to deduce it the new function also has a format parameter. This
should contain the EGLenum returned in the EGL_TEXTURE_FORMAT attribute
retreived via eglQueryWaylandBufferWL. The exact wl_drm_format value to use is
deduced from the EGL format and the size of the images. The number of images
passed must match the number of planes required by the texture format. The
EGLImages must all point to the same buffer and this is determined by checking
the names of the images. If any of these criteria fail then the function will
report EGL_BAD_MATCH.
---
 .../specs/WL_create_wayland_buffer_from_image.spec |  77 ++++--
 include/EGL/eglmesaext.h                           |   2 +
 src/egl/drivers/dri2/platform_wayland.c            | 274 ++++++++++++++++++---
 src/egl/main/eglapi.c                              |  35 +++
 src/egl/main/eglapi.h                              |   4 +-
 5 files changed, 343 insertions(+), 49 deletions(-)

diff --git a/docs/specs/WL_create_wayland_buffer_from_image.spec b/docs/specs/WL_create_wayland_buffer_from_image.spec
index aa5eb4d..b08c8a2 100644
--- a/docs/specs/WL_create_wayland_buffer_from_image.spec
+++ b/docs/specs/WL_create_wayland_buffer_from_image.spec
@@ -22,7 +22,7 @@ Status
 
 Version
 
-    Version 2, October 25, 2013
+    Version 3, February 5, 2014
 
 Number
 
@@ -35,20 +35,22 @@ Dependencies
 
     EGL_KHR_base_image is required.
 
+    EGL_WL_bind_wayland_display affects the definition of this extension.
+
 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.
+    This extension provides entry points to create a wl_buffer which shares
+    its contents with a given EGLImage or a set of planar EGLImages. 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.
+    The nested compositor can create the EGLImages 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
 
@@ -59,6 +61,11 @@ New Procedures and Functions
     struct wl_buffer *eglCreateWaylandBufferFromImageWL(EGLDisplay dpy,
                                                         EGLImageKHR image);
 
+    struct wl_buffer *eglCreateWaylandBufferFromPlanarImagesWL(EGLDisplay dpy,
+                                                               EGLenum format,
+                                                               EGLImageKHR *ims,
+                                                               EGLint n_images);
+
 New Tokens
 
     None.
@@ -67,8 +74,8 @@ 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);
+    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
@@ -82,13 +89,50 @@ Additions to the EGL 1.4 Specification:
     format or tiling mode or that the buffer is in memory that is inaccessible
     to the GPU that the given EGLDisplay is using.
 
+    Alternatively it is possible to create a buffer from a planar image where
+    each plane is contained in a separate EGLImage using the following
+    function:
+
+    struct wl_buffer *eglCreateWaylandBufferFromPlanarImagesWL(EGLDisplay dpy,
+                                                               EGLenum format,
+                                                               EGLImageKHR *ims,
+                                                               EGLint n_images);
+
+    The number of images passed should match the number of planes required for
+    the format given in the format parameter. For non-planar formats this will
+    just be 1. Each image represents one plane within the buffer.
+
+    The formats accepted in the format parameter are:
+
+       EGL_TEXTURE_RGB        A single image is used which contains RGB
+                              components.
+       EGL_TEXTURE_RGBA       A single image is used which contains RGBA
+                              components.
+       EGL_TEXTURE_Y_U_V_WL   Three images are used; one containing the
+                              luminance component, one containing the
+                              U component of the chrominance data and another
+                              containing the V component.
+       EGL_TEXTURE_Y_UV_WL    Two images are used; one containing a single
+                              luminance component and the other containing the
+                              two chrominance components.
+       EGL_TEXTURE_Y_XUXV_WL  Two images are used; one containing a single
+                              luminance component and the other containing the
+                              two chrominance components along with two unused
+                              components.
+
+Dependencies on EGL_WL_bind_wayland_display
+
+    If EGL_WL_bind_wayland_display is not implemented then references to
+    EGL_TEXTURE_Y_U_V_WL, EGL_TEXTURE_Y_UV_WL and EGL_TEXTURE_Y_XUXV_WL are
+    void.
+
 Issues
 
     1) Under what circumstances can the EGL_BAD_MATCH error be generated? Does
        this include for example unsupported tiling modes?
 
        RESOLVED: Yes, the EGL_BAD_MATCH error can be generated for any reason
-       which prevents the implementation from representing the image as a
+       which prevents the implementation from representing the images as a
        wl_buffer. For example, these problems can be but are not limited to
        unsupported tiling modes, inaccessible memory or an unsupported pixel
        format.
@@ -99,3 +143,6 @@ Revision History
         Initial draft (Neil Roberts)
     Version 2, October 25, 2013
         Added a note about more possible reasons for returning EGL_BAD_FORMAT.
+    Version 3, February 5, 2014
+        Support for passing multiple images in order to create a planar
+        buffer.
diff --git a/include/EGL/eglmesaext.h b/include/EGL/eglmesaext.h
index b3229e3..b78aa8b 100644
--- a/include/EGL/eglmesaext.h
+++ b/include/EGL/eglmesaext.h
@@ -139,8 +139,10 @@ typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYWAYLANDBUFFERWL) (EGLDisplay dpy, st
 
 #ifdef EGL_EGLEXT_PROTOTYPES
 EGLAPI struct wl_buffer * EGLAPIENTRY eglCreateWaylandBufferFromImageWL(EGLDisplay dpy, EGLImageKHR image);
+EGLAPI struct wl_buffer * EGLAPIENTRY eglCreateWaylandBufferFromPlanarImagesWL(EGLDisplay dpy, EGLenum format, EGLImageKHR *images, EGLint n_images);
 #endif
 typedef struct wl_buffer * (EGLAPIENTRYP PFNEGLCREATEWAYLANDBUFFERFROMIMAGEWL) (EGLDisplay dpy, EGLImageKHR image);
+typedef struct wl_buffer * (EGLAPIENTRYP PFNEGLCREATEWAYLANDBUFFERFROMPLANARIMAGESWL) (EGLDisplay dpy, EGLenum format, EGLImageKHR *images, EGLint n_images);
 
 #endif
 
diff --git a/src/egl/drivers/dri2/platform_wayland.c b/src/egl/drivers/dri2/platform_wayland.c
index 089ed62..556a45a 100644
--- a/src/egl/drivers/dri2/platform_wayland.c
+++ b/src/egl/drivers/dri2/platform_wayland.c
@@ -698,64 +698,238 @@ dri2_can_handle_format(struct dri2_egl_display *dri2_dpy,
    return EGL_FALSE;
 }
 
+struct plane_attribs {
+   struct dri2_egl_image *dri2_img;
+   __DRIimage *image;
+   int offset;
+   int stride;
+   int width;
+   int height;
+   int format;
+};
+
+struct planar_format {
+   enum wl_drm_format wl_format;
+   EGLenum components;
+   int n_planes;
+   struct {
+      int width_shift;
+      int height_shift;
+      uint32_t dri_format;
+   } planes[3];
+};
+
+static const struct planar_format
+planar_formats[] = {
+   { WL_DRM_FORMAT_ARGB8888, EGL_TEXTURE_RGBA, 1,
+     { { 0, 0, __DRI_IMAGE_FORMAT_ARGB8888 } } },
+
+   { WL_DRM_FORMAT_XRGB8888, EGL_TEXTURE_RGB, 1,
+     { { 0, 0, __DRI_IMAGE_FORMAT_XRGB8888 }, } },
+
+   { WL_DRM_FORMAT_RGB565, EGL_TEXTURE_RGB, 1,
+     { { 0, 0, __DRI_IMAGE_FORMAT_RGB565 } } },
+
+   { WL_DRM_FORMAT_YUV410, EGL_TEXTURE_Y_U_V_WL, 3,
+     { { 0, 0, __DRI_IMAGE_FORMAT_R8 },
+       { 2, 2, __DRI_IMAGE_FORMAT_R8 },
+       { 2, 2, __DRI_IMAGE_FORMAT_R8 } } },
+
+   { WL_DRM_FORMAT_YUV411, EGL_TEXTURE_Y_U_V_WL, 3,
+     { { 0, 0, __DRI_IMAGE_FORMAT_R8 },
+       { 2, 0, __DRI_IMAGE_FORMAT_R8 },
+       { 2, 0, __DRI_IMAGE_FORMAT_R8 } } },
+
+   { WL_DRM_FORMAT_YUV420, EGL_TEXTURE_Y_U_V_WL, 3,
+     { { 0, 0, __DRI_IMAGE_FORMAT_R8 },
+       { 1, 1, __DRI_IMAGE_FORMAT_R8 },
+       { 1, 1, __DRI_IMAGE_FORMAT_R8 } } },
+
+   { WL_DRM_FORMAT_YUV422, EGL_TEXTURE_Y_U_V_WL, 3,
+     { { 0, 0, __DRI_IMAGE_FORMAT_R8 },
+       { 1, 0, __DRI_IMAGE_FORMAT_R8 },
+       { 1, 0, __DRI_IMAGE_FORMAT_R8 } } },
+
+   { WL_DRM_FORMAT_YUV444, EGL_TEXTURE_Y_U_V_WL, 3,
+     { { 0, 0, __DRI_IMAGE_FORMAT_R8 },
+       { 0, 0, __DRI_IMAGE_FORMAT_R8 },
+       { 0, 0, __DRI_IMAGE_FORMAT_R8 } } },
+
+   { WL_DRM_FORMAT_NV12, EGL_TEXTURE_Y_UV_WL, 2,
+     { { 0, 0, __DRI_IMAGE_FORMAT_R8 },
+       { 1, 1, __DRI_IMAGE_FORMAT_GR88 } } },
+
+   { WL_DRM_FORMAT_NV16, EGL_TEXTURE_Y_UV_WL, 2,
+     { { 0, 0, __DRI_IMAGE_FORMAT_R8 },
+       { 1, 0, __DRI_IMAGE_FORMAT_GR88 } } },
+
+   { WL_DRM_FORMAT_YUYV, EGL_TEXTURE_Y_XUXV_WL, 2,
+     { { 0, 0, __DRI_IMAGE_FORMAT_GR88 },
+       { 1, 0, __DRI_IMAGE_FORMAT_ARGB8888 } } }
+};
+
+static void
+get_planar_format_max_shifts(const struct planar_format *planar_format,
+                             int *max_width_shift,
+                             int *max_height_shift)
+{
+   int i;
+
+   *max_width_shift = 0;
+   *max_height_shift = 0;
+
+   for (i = 0; i < planar_format->n_planes; i++) {
+      if (planar_format->planes[i].width_shift > *max_width_shift)
+         *max_width_shift = planar_format->planes[i].width_shift;
+      if (planar_format->planes[i].height_shift > *max_height_shift)
+         *max_height_shift = planar_format->planes[i].height_shift;
+   }
+}
+
+static EGLBoolean
+check_plane_attribs_match_format(const struct plane_attribs *planes,
+                                 const struct planar_format *planar_format)
+{
+   int width, height;
+   int i;
+
+   for (i = 0; i < planar_format->n_planes; i++) {
+      if (planes[i].format != planar_format->planes[i].dri_format)
+         return EGL_FALSE;
+
+      width = planes[0].width >> planar_format->planes[i].width_shift;
+      height = planes[0].height >> planar_format->planes[i].height_shift;
+
+      if (planes[i].width != width || planes[i].height != height)
+         return EGL_FALSE;
+   }
+
+   return EGL_TRUE;
+}
+
+static EGLBoolean
+find_planar_format(EGLenum components,
+                   const struct plane_attribs *planes,
+                   int n_planes,
+                   enum wl_drm_format *wl_format)
+{
+   const struct planar_format *planar_format;
+   int max_width_shift, max_height_shift;
+   int i;
+
+   for (i = 0; i < ARRAY_SIZE(planar_formats); i++) {
+      planar_format = planar_formats + i;
+
+      if (n_planes != planar_format->n_planes ||
+          components != planar_format->components)
+         continue;
+
+      /* Check if the size of the first plane is a multiple of the maximum
+       * shift */
+      get_planar_format_max_shifts(planar_format,
+                                   &max_width_shift,
+                                   &max_height_shift);
+      if ((planes[0].width & ((1 << max_width_shift) - 1)) != 0 ||
+          (planes[0].height & ((1 << max_height_shift) - 1)) != 0)
+         continue;
+
+      if (!check_plane_attribs_match_format(planes, planar_format))
+         continue;
+
+      *wl_format = planar_format->wl_format;
+      return EGL_TRUE;
+   }
+
+   return EGL_FALSE;
+}
+
 static struct wl_buffer *
-dri2_create_wayland_buffer_from_image_wl(_EGLDriver *drv,
-                                         _EGLDisplay *disp,
-                                         _EGLImage *img)
+dri2_create_wayland_buffer_from_planar_images_wl(_EGLDriver *drv,
+                                                 _EGLDisplay *disp,
+                                                 EGLenum format,
+                                                 _EGLImage **images,
+                                                 EGLint n_images)
 {
    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;
+   struct plane_attribs plane[3];
+   int name, other_name;
+   int i;
 
-   dri2_dpy->image->queryImage(image, __DRI_IMAGE_ATTRIB_FORMAT, &format);
+   if (n_images < 1 || n_images > 3)
+      goto bad_format;
 
-   switch (format) {
-   case __DRI_IMAGE_FORMAT_ARGB8888:
-      if (!dri2_can_handle_format(dri2_dpy, WL_DRM_FORMAT_ARGB8888))
-         goto bad_format;
-      wl_format = WL_DRM_FORMAT_ARGB8888;
-      break;
-   case __DRI_IMAGE_FORMAT_XRGB8888:
-      if (!dri2_can_handle_format(dri2_dpy, WL_DRM_FORMAT_XRGB8888))
+   for (i = 0; i < n_images; i++) {
+      plane[i].dri2_img = dri2_egl_image(images[i]);
+      plane[i].image = plane[i].dri2_img->dri_image;
+   }
+
+   /* Verify the all of the images have the same name (ie, they point to the
+    * same buffer) */
+   dri2_dpy->image->queryImage(plane[0].image, __DRI_IMAGE_ATTRIB_NAME, &name);
+   for (i = 1; i < n_images; i++) {
+      dri2_dpy->image->queryImage(plane[i].image,
+                                  __DRI_IMAGE_ATTRIB_NAME,
+                                  &other_name);
+      if (other_name != name)
          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);
+   for (i = 0; i < n_images; i++) {
+      dri2_dpy->image->queryImage(plane[i].image,
+                                  __DRI_IMAGE_ATTRIB_FORMAT,
+                                  &plane[i].format);
+      dri2_dpy->image->queryImage(plane[i].image,
+                                  __DRI_IMAGE_ATTRIB_WIDTH,
+                                  &plane[i].width);
+      dri2_dpy->image->queryImage(plane[i].image,
+                                  __DRI_IMAGE_ATTRIB_HEIGHT,
+                                  &plane[i].height);
+      dri2_dpy->image->queryImage(plane[i].image,
+                                  __DRI_IMAGE_ATTRIB_STRIDE,
+                                  &plane[i].stride);
+
+      if (dri2_dpy->image->base.version >= 9)
+         dri2_dpy->image->queryImage(plane[i].image,
+                                     __DRI_IMAGE_ATTRIB_OFFSET,
+                                     &plane[i].offset);
+      else
+         plane[i].offset = 0;
+   }
+
+   /* We need prime to create planar buffers */
+   if (n_images > 1 &&
+       (dri2_dpy->capabilities & WL_DRM_CAPABILITY_PRIME) == 0)
+      goto bad_format;
+
+   if (!find_planar_format(format, plane, n_images, &wl_format))
+      goto bad_format;
+
+   if (!dri2_can_handle_format(dri2_dpy, wl_format))
+      goto bad_format;
 
    if (dri2_dpy->capabilities & WL_DRM_CAPABILITY_PRIME) {
       int fd;
 
-      dri2_dpy->image->queryImage(image, __DRI_IMAGE_ATTRIB_FD, &fd);
+      dri2_dpy->image->queryImage(plane[0].image, __DRI_IMAGE_ATTRIB_FD, &fd);
 
       buffer =
          wl_drm_create_prime_buffer(dri2_dpy->wl_drm,
                                     fd,
-                                    width, height,
+                                    plane[0].width, plane[0].height,
                                     wl_format,
-                                    0, pitch,
-                                    0, 0,
-                                    0, 0);
+                                    plane[0].offset, plane[0].stride,
+                                    plane[1].offset, plane[1].stride,
+                                    plane[2].offset, plane[2].stride);
 
       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,
+                              plane[0].width, plane[0].height,
+                              plane[0].stride,
                               wl_format);
    }
 
@@ -773,6 +947,38 @@ bad_format:
    return NULL;
 }
 
+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;
+   EGLenum components;
+   int format;
+
+   dri2_dpy->image->queryImage(image, __DRI_IMAGE_ATTRIB_FORMAT, &format);
+
+   switch (format) {
+   case __DRI_IMAGE_FORMAT_ARGB8888:
+      components = EGL_TEXTURE_RGBA;
+      break;
+   case __DRI_IMAGE_FORMAT_XRGB8888:
+      components = EGL_TEXTURE_RGB;
+      break;
+   default:
+      _eglError(EGL_BAD_MATCH, "unsupported image format");
+      return NULL;
+   }
+
+   return dri2_create_wayland_buffer_from_planar_images_wl(drv,
+                                                           disp,
+                                                           components,
+                                                           &img,
+                                                           1 /* n_imgs */);
+}
+
 static int
 dri2_wayland_authenticate(_EGLDisplay *disp, uint32_t id)
 {
@@ -1013,6 +1219,8 @@ dri2_initialize_wayland(_EGLDriver *drv, _EGLDisplay *disp)
 
    drv->API.CreateWaylandBufferFromImageWL =
       dri2_create_wayland_buffer_from_image_wl;
+   drv->API.CreateWaylandBufferFromPlanarImagesWL =
+      dri2_create_wayland_buffer_from_planar_images_wl;
 
    dri2_dpy = calloc(1, sizeof *dri2_dpy);
    if (!dri2_dpy)
diff --git a/src/egl/main/eglapi.c b/src/egl/main/eglapi.c
index 59e214c..b0b4e72 100644
--- a/src/egl/main/eglapi.c
+++ b/src/egl/main/eglapi.c
@@ -975,6 +975,7 @@ eglGetProcAddress(const char *procname)
 #endif
 #ifdef EGL_WL_create_wayland_buffer_from_image
       { "eglCreateWaylandBufferFromImageWL", (_EGLProc) eglCreateWaylandBufferFromImageWL },
+      { "eglCreateWaylandBufferFromPlanarImagesWL", (_EGLProc) eglCreateWaylandBufferFromPlanarImagesWL },
 #endif
       { "eglPostSubBufferNV", (_EGLProc) eglPostSubBufferNV },
 #ifdef EGL_EXT_swap_buffers_with_damage
@@ -1606,6 +1607,40 @@ eglQueryWaylandBufferWL(EGLDisplay dpy, struct wl_resource *buffer,
 
 #ifdef EGL_WL_create_wayland_buffer_from_image
 struct wl_buffer * EGLAPIENTRY
+eglCreateWaylandBufferFromPlanarImagesWL(EGLDisplay dpy,
+                                         EGLenum format,
+                                         EGLImageKHR *images,
+                                         EGLint n_images)
+{
+   _EGLDisplay *disp = _eglLockDisplay(dpy);
+   _EGLImage *imgs[3];
+   _EGLDriver *drv;
+   struct wl_buffer *ret;
+   int i;
+
+   _EGL_CHECK_DISPLAY(disp, NULL, drv);
+   assert(disp->Extensions.WL_create_wayland_buffer_from_image);
+
+   if (n_images < 0 || n_images > ARRAY_SIZE(imgs))
+      RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, NULL);
+
+   for (i = 0; i < n_images; i++) {
+      imgs[i] = _eglLookupImage(images[i], disp);
+
+      if (!imgs[i])
+         RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, NULL);
+   }
+
+   ret = drv->API.CreateWaylandBufferFromPlanarImagesWL(drv,
+                                                        disp,
+                                                        format,
+                                                        imgs,
+                                                        n_images);
+
+   RETURN_EGL_EVAL(disp, ret);
+}
+
+struct wl_buffer * EGLAPIENTRY
 eglCreateWaylandBufferFromImageWL(EGLDisplay dpy, EGLImageKHR image)
 {
    _EGLDisplay *disp = _eglLockDisplay(dpy);
diff --git a/src/egl/main/eglapi.h b/src/egl/main/eglapi.h
index 091c09c..7e8d797 100644
--- a/src/egl/main/eglapi.h
+++ b/src/egl/main/eglapi.h
@@ -127,7 +127,8 @@ typedef EGLBoolean (*QueryWaylandBufferWL_t)(_EGLDriver *drv, _EGLDisplay *displ
 #endif
 
 #ifdef EGL_WL_create_wayland_buffer_from_image
-typedef struct wl_buffer * (*CreateWaylandBufferFromImageWL_t)(_EGLDriver *drv, _EGLDisplay *disp, _EGLImage *img);
+typedef struct wl_buffer * (*CreateWaylandBufferFromImageWL_t)(_EGLDriver *drv, _EGLDisplay *disp, _EGLImage *images);
+typedef struct wl_buffer * (*CreateWaylandBufferFromPlanarImagesWL_t)(_EGLDriver *drv, _EGLDisplay *disp, EGLenum format, _EGLImage **images, EGLint n_images);
 #endif
 
 typedef EGLBoolean (*PostSubBufferNV_t)(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surface, EGLint x, EGLint y, EGLint width, EGLint height);
@@ -216,6 +217,7 @@ struct _egl_api
 
 #ifdef EGL_WL_create_wayland_buffer_from_image
    CreateWaylandBufferFromImageWL_t CreateWaylandBufferFromImageWL;
+   CreateWaylandBufferFromPlanarImagesWL_t CreateWaylandBufferFromPlanarImagesWL;
 #endif
 
 #ifdef EGL_EXT_swap_buffers_with_damage
-- 
1.8.5.3



More information about the wayland-devel mailing list