From a9f34b563189072a4830fe07fe034e902a7d48f2 Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Fri, 12 Jul 2019 09:17:30 -0700 Subject: [PATCH] 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 Reviewed-by: Eric Engestrom Reviewed-by: Kristian H. Kristensen Reviewed-by: Eric Anholt --- 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); -- 2.30.2