Mesa (master): egl/android: handle multi-fd native windows

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Tue Jul 16 18:49:53 UTC 2019


Module: Mesa
Branch: master
Commit: a9f34b563189072a4830fe07fe034e902a7d48f2
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=a9f34b563189072a4830fe07fe034e902a7d48f2

Author: Rob Clark <robdclark at chromium.org>
Date:   Fri Jul 12 09:17:30 2019 -0700

egl/android: handle multi-fd native windows

We can hit multi-fd EGL_NATIVE_BUFFER_ANDROID case when the native
android buffer is YUV.  So we need to handle that.

Currently this went unnoticed because, even though we have two or
three fd's for YUV native android buffers, they all reference the
same backing buffer.  But we really shouldn't rely on that.

Signed-off-by: Rob Clark <robdclark at chromium.org>
Reviewed-by: Eric Engestrom <eric at engestrom.ch>
Reviewed-by: Kristian H. Kristensen <hoegsberg at google.com>
Reviewed-by: Eric Anholt <eric at anholt.net>

---

 src/egl/drivers/dri2/platform_android.c | 80 ++++++++++++++++++++++-----------
 1 file changed, 55 insertions(+), 25 deletions(-)

diff --git a/src/egl/drivers/dri2/platform_android.c b/src/egl/drivers/dri2/platform_android.c
index db6ba4a4b4d..d949ed42a38 100644
--- a/src/egl/drivers/dri2/platform_android.c
+++ b/src/egl/drivers/dri2/platform_android.c
@@ -72,7 +72,7 @@ static const struct droid_yuv_format droid_yuv_formats[] = {
    { HAL_PIXEL_FORMAT_YCbCr_420_888, YCbCr, 1, __DRI_IMAGE_FOURCC_YUV420 },
    { HAL_PIXEL_FORMAT_YCbCr_420_888, YCrCb, 1, __DRI_IMAGE_FOURCC_YVU420 },
    { HAL_PIXEL_FORMAT_YV12,          YCrCb, 1, __DRI_IMAGE_FOURCC_YVU420 },
-   /* HACK: See droid_create_image_from_prime_fd() and
+   /* HACK: See droid_create_image_from_prime_fds() and
     * https://issuetracker.google.com/32077885. */
    { HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, YCbCr, 2, __DRI_IMAGE_FOURCC_NV12 },
    { HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, YCbCr, 1, __DRI_IMAGE_FOURCC_YUV420 },
@@ -167,16 +167,24 @@ static int get_format(int format)
    return -1;
 }
 
-static int
-get_native_buffer_fd(struct ANativeWindowBuffer *buf)
+/* returns # of fds, and by reference the actual fds */
+static unsigned
+get_native_buffer_fds(struct ANativeWindowBuffer *buf, int fds[3])
 {
    native_handle_t *handle = (native_handle_t *)buf->handle;
+
+   if (!handle)
+      return 0;
+
    /*
     * Various gralloc implementations exist, but the dma-buf fd tends
     * to be first. Access it directly to avoid a dependency on specific
     * gralloc versions.
     */
-   return (handle && handle->numFds) ? handle->data[0] : -1;
+   for (int i = 0; i < handle->numFds; i++)
+      fds[i] = handle->data[i];
+
+   return handle->numFds;
 }
 
 #ifdef HAVE_DRM_GRALLOC
@@ -533,7 +541,8 @@ get_back_bo(struct dri2_egl_surface *dri2_surf)
    struct dri2_egl_display *dri2_dpy =
       dri2_egl_display(dri2_surf->base.Resource.Display);
    int fourcc, pitch;
-   int offset = 0, fd;
+   int offset = 0, fds[3];
+   unsigned num_fds;
 
    if (dri2_surf->dri_image_back)
       return 0;
@@ -544,8 +553,8 @@ get_back_bo(struct dri2_egl_surface *dri2_surf)
          return -1;
       }
 
-      fd = get_native_buffer_fd(dri2_surf->buffer);
-      if (fd < 0) {
+      num_fds = get_native_buffer_fds(dri2_surf->buffer, fds);
+      if (num_fds == 0) {
          _eglLog(_EGL_WARNING, "Could not get native buffer FD");
          return -1;
       }
@@ -566,8 +575,8 @@ get_back_bo(struct dri2_egl_surface *dri2_surf)
                                              dri2_surf->base.Width,
                                              dri2_surf->base.Height,
                                              fourcc,
-                                             &fd,
-                                             1,
+                                             fds,
+                                             num_fds,
                                              &pitch,
                                              &offset,
                                              dri2_surf);
@@ -766,8 +775,9 @@ droid_set_damage_region(_EGLDriver *drv,
 #endif
 
 static _EGLImage *
-droid_create_image_from_prime_fd_yuv(_EGLDisplay *disp, _EGLContext *ctx,
-                                     struct ANativeWindowBuffer *buf, int fd)
+droid_create_image_from_prime_fds_yuv(_EGLDisplay *disp, _EGLContext *ctx,
+                                     struct ANativeWindowBuffer *buf,
+                                     int num_fds, int fds[3])
 {
    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
    struct android_ycbcr ycbcr;
@@ -786,7 +796,7 @@ droid_create_image_from_prime_fd_yuv(_EGLDisplay *disp, _EGLContext *ctx,
    ret = dri2_dpy->gralloc->lock_ycbcr(dri2_dpy->gralloc, buf->handle,
                                        0, 0, 0, 0, 0, &ycbcr);
    if (ret) {
-      /* HACK: See droid_create_image_from_prime_fd() and
+      /* HACK: See droid_create_image_from_prime_fds() and
        * https://issuetracker.google.com/32077885.*/
       if (buf->format == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED)
          return NULL;
@@ -827,16 +837,28 @@ droid_create_image_from_prime_fd_yuv(_EGLDisplay *disp, _EGLContext *ctx,
       return NULL;
    }
 
+   /*
+    * Since this is EGL_NATIVE_BUFFER_ANDROID don't assume that
+    * the single-fd case cannot happen.  So handle eithe single
+    * fd or fd-per-plane case:
+    */
+   if (num_fds == 1) {
+      fds[2] = fds[1] = fds[0];
+   } else {
+      int expected_planes = (ycbcr.chroma_step == 2) ? 2 : 3;
+      assert(num_fds == expected_planes);
+   }
+
    if (ycbcr.chroma_step == 2) {
       /* Semi-planar Y + CbCr or Y + CrCb format. */
       const EGLint attr_list_2plane[] = {
          EGL_WIDTH, buf->width,
          EGL_HEIGHT, buf->height,
          EGL_LINUX_DRM_FOURCC_EXT, fourcc,
-         EGL_DMA_BUF_PLANE0_FD_EXT, fd,
+         EGL_DMA_BUF_PLANE0_FD_EXT, fds[0],
          EGL_DMA_BUF_PLANE0_PITCH_EXT, pitches[0],
          EGL_DMA_BUF_PLANE0_OFFSET_EXT, offsets[0],
-         EGL_DMA_BUF_PLANE1_FD_EXT, fd,
+         EGL_DMA_BUF_PLANE1_FD_EXT, fds[1],
          EGL_DMA_BUF_PLANE1_PITCH_EXT, pitches[1],
          EGL_DMA_BUF_PLANE1_OFFSET_EXT, offsets[1],
          EGL_NONE, 0
@@ -849,13 +871,13 @@ droid_create_image_from_prime_fd_yuv(_EGLDisplay *disp, _EGLContext *ctx,
          EGL_WIDTH, buf->width,
          EGL_HEIGHT, buf->height,
          EGL_LINUX_DRM_FOURCC_EXT, fourcc,
-         EGL_DMA_BUF_PLANE0_FD_EXT, fd,
+         EGL_DMA_BUF_PLANE0_FD_EXT, fds[0],
          EGL_DMA_BUF_PLANE0_PITCH_EXT, pitches[0],
          EGL_DMA_BUF_PLANE0_OFFSET_EXT, offsets[0],
-         EGL_DMA_BUF_PLANE1_FD_EXT, fd,
+         EGL_DMA_BUF_PLANE1_FD_EXT, fds[1],
          EGL_DMA_BUF_PLANE1_PITCH_EXT, pitches[1],
          EGL_DMA_BUF_PLANE1_OFFSET_EXT, offsets[1],
-         EGL_DMA_BUF_PLANE2_FD_EXT, fd,
+         EGL_DMA_BUF_PLANE2_FD_EXT, fds[2],
          EGL_DMA_BUF_PLANE2_PITCH_EXT, pitches[2],
          EGL_DMA_BUF_PLANE2_OFFSET_EXT, offsets[2],
          EGL_NONE, 0
@@ -866,15 +888,15 @@ droid_create_image_from_prime_fd_yuv(_EGLDisplay *disp, _EGLContext *ctx,
 }
 
 static _EGLImage *
-droid_create_image_from_prime_fd(_EGLDisplay *disp, _EGLContext *ctx,
-                                 struct ANativeWindowBuffer *buf, int fd)
+droid_create_image_from_prime_fds(_EGLDisplay *disp, _EGLContext *ctx,
+                                  struct ANativeWindowBuffer *buf, int num_fds, int fds[3])
 {
    unsigned int pitch;
 
    if (is_yuv(buf->format)) {
       _EGLImage *image;
 
-      image = droid_create_image_from_prime_fd_yuv(disp, ctx, buf, fd);
+      image = droid_create_image_from_prime_fds_yuv(disp, ctx, buf, num_fds, fds);
       /*
        * HACK: https://issuetracker.google.com/32077885
        * There is no API available to properly query the IMPLEMENTATION_DEFINED
@@ -886,6 +908,13 @@ droid_create_image_from_prime_fd(_EGLDisplay *disp, _EGLContext *ctx,
          return image;
    }
 
+   /*
+    * Non-YUV formats could *also* have multiple planes, such as ancillary
+    * color compression state buffer, but the rest of the code isn't ready
+    * yet to deal with modifiers:
+    */
+   assert(num_fds == 1);
+
    const int fourcc = get_fourcc(buf->format);
    if (fourcc == -1) {
       _eglError(EGL_BAD_PARAMETER, "eglCreateEGLImageKHR");
@@ -902,7 +931,7 @@ droid_create_image_from_prime_fd(_EGLDisplay *disp, _EGLContext *ctx,
       EGL_WIDTH, buf->width,
       EGL_HEIGHT, buf->height,
       EGL_LINUX_DRM_FOURCC_EXT, fourcc,
-      EGL_DMA_BUF_PLANE0_FD_EXT, fd,
+      EGL_DMA_BUF_PLANE0_FD_EXT, fds[0],
       EGL_DMA_BUF_PLANE0_PITCH_EXT, pitch,
       EGL_DMA_BUF_PLANE0_OFFSET_EXT, 0,
       EGL_NONE, 0
@@ -988,7 +1017,8 @@ dri2_create_image_android_native_buffer(_EGLDisplay *disp,
                                         _EGLContext *ctx,
                                         struct ANativeWindowBuffer *buf)
 {
-   int fd;
+   int fds[3];
+   unsigned num_fds;
 
    if (ctx != NULL) {
       /* From the EGL_ANDROID_image_native_buffer spec:
@@ -1008,9 +1038,9 @@ dri2_create_image_android_native_buffer(_EGLDisplay *disp,
       return NULL;
    }
 
-   fd = get_native_buffer_fd(buf);
-   if (fd >= 0)
-      return droid_create_image_from_prime_fd(disp, ctx, buf, fd);
+   num_fds = get_native_buffer_fds(buf, fds);
+   if (num_fds > 0)
+      return droid_create_image_from_prime_fds(disp, ctx, buf, num_fds, fds);
 
 #ifdef HAVE_DRM_GRALLOC
    return droid_create_image_from_name(disp, ctx, buf);




More information about the mesa-commit mailing list