diff --git a/src/egl/drivers/dri2/platform_android.c b/src/egl/drivers/dri2/platform_android.c index a200615f9e3..988e0a3c181 100644 --- a/src/egl/drivers/dri2/platform_android.c +++ b/src/egl/drivers/dri2/platform_android.c @@ -187,114 +187,120 @@ get_native_buffer_name(struct ANativeWindowBuffer *buf) } #endif /* HAVE_DRM_GRALLOC */ -static __DRIimage * -droid_create_image_from_prime_fds_yuv(_EGLDisplay *disp, - struct ANativeWindowBuffer *buf, - void *priv, - int num_fds, int fds[3]) +struct buffer_info { + uint32_t drm_fourcc; + int num_planes; + int fds[4]; + uint64_t modifier; + int offsets[4]; + int pitches[4]; + enum __DRIYUVColorSpace yuv_color_space; + enum __DRISampleRange sample_range; + enum __DRIChromaSiting horizontal_siting; + enum __DRIChromaSiting vertical_siting; +}; + +static int +get_yuv_buffer_info(_EGLDisplay *disp, + struct ANativeWindowBuffer *buf, + struct buffer_info *out_buf_info) { struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); struct android_ycbcr ycbcr; - int offsets[3]; - int pitches[3]; enum chroma_order chroma_order; - int fourcc; + int drm_fourcc = 0; + int num_fds = 0; + int fds[3]; int ret; - unsigned error; + + num_fds = get_native_buffer_fds(buf, fds); + if (num_fds == 0) + return -EINVAL; if (!dri2_dpy->gralloc->lock_ycbcr) { _eglLog(_EGL_WARNING, "Gralloc does not support lock_ycbcr"); - return NULL; + return -EINVAL; } memset(&ycbcr, 0, sizeof(ycbcr)); 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_fds() and + /* HACK: See native_window_buffer_get_buffer_info() and * https://issuetracker.google.com/32077885.*/ if (buf->format == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) - return NULL; + return -EAGAIN; _eglLog(_EGL_WARNING, "gralloc->lock_ycbcr failed: %d", ret); - return NULL; + return -EINVAL; } dri2_dpy->gralloc->unlock(dri2_dpy->gralloc, buf->handle); + chroma_order = ((size_t)ycbcr.cr < (size_t)ycbcr.cb) ? YCrCb : YCbCr; + + /* .chroma_step is the byte distance between the same chroma channel + * values of subsequent pixels, assumed to be the same for Cb and Cr. */ + drm_fourcc = get_fourcc_yuv(buf->format, chroma_order, ycbcr.chroma_step); + if (drm_fourcc == -1) { + _eglLog(_EGL_WARNING, "unsupported YUV format, native = %x, chroma_order = %s, chroma_step = %d", + buf->format, chroma_order == YCbCr ? "YCbCr" : "YCrCb", ycbcr.chroma_step); + return -EINVAL; + } + /* When lock_ycbcr's usage argument contains no SW_READ/WRITE flags * it will return the .y/.cb/.cr pointers based on a NULL pointer, * so they can be interpreted as offsets. */ - offsets[0] = (size_t)ycbcr.y; + out_buf_info->offsets[0] = (size_t)ycbcr.y; /* We assume here that all the planes are located in one DMA-buf. */ - if ((size_t)ycbcr.cr < (size_t)ycbcr.cb) { - chroma_order = YCrCb; - offsets[1] = (size_t)ycbcr.cr; - offsets[2] = (size_t)ycbcr.cb; + if (chroma_order == YCrCb) { + out_buf_info->offsets[1] = (size_t)ycbcr.cr; + out_buf_info->offsets[2] = (size_t)ycbcr.cb; } else { - chroma_order = YCbCr; - offsets[1] = (size_t)ycbcr.cb; - offsets[2] = (size_t)ycbcr.cr; + out_buf_info->offsets[1] = (size_t)ycbcr.cb; + out_buf_info->offsets[2] = (size_t)ycbcr.cr; } /* .ystride is the line length (in bytes) of the Y plane, * .cstride is the line length (in bytes) of any of the remaining * Cb/Cr/CbCr planes, assumed to be the same for Cb and Cr for fully * planar formats. */ - pitches[0] = ycbcr.ystride; - pitches[1] = pitches[2] = ycbcr.cstride; - - /* .chroma_step is the byte distance between the same chroma channel - * values of subsequent pixels, assumed to be the same for Cb and Cr. */ - fourcc = get_fourcc_yuv(buf->format, chroma_order, ycbcr.chroma_step); - if (fourcc == -1) { - _eglLog(_EGL_WARNING, "unsupported YUV format, native = %x, chroma_order = %s, chroma_step = %d", - buf->format, chroma_order == YCbCr ? "YCbCr" : "YCrCb", ycbcr.chroma_step); - return NULL; - } + out_buf_info->pitches[0] = ycbcr.ystride; + out_buf_info->pitches[1] = out_buf_info->pitches[2] = ycbcr.cstride; /* * 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: */ - int num_planes = (ycbcr.chroma_step == 2) ? 2 : 3; + out_buf_info->num_planes = (ycbcr.chroma_step == 2) ? 2 : 3; if (num_fds == 1) { - fds[2] = fds[1] = fds[0]; + out_buf_info->fds[1] = out_buf_info->fds[0] = fds[0]; + if (out_buf_info->num_planes == 3) + out_buf_info->fds[2] = fds[0]; } else { - assert(num_fds == num_planes); + assert(num_fds == out_buf_info->num_planes); + out_buf_info->fds[0] = fds[0]; + out_buf_info->fds[1] = fds[1]; + out_buf_info->fds[2] = fds[2]; } - return dri2_dpy->image->createImageFromDmaBufs(dri2_dpy->dri_screen, - buf->width, buf->height, fourcc, - fds, num_planes, pitches, offsets, - EGL_ITU_REC601_EXT, - EGL_YUV_NARROW_RANGE_EXT, - EGL_YUV_CHROMA_SITING_0_EXT, - EGL_YUV_CHROMA_SITING_0_EXT, - &error, - priv); + out_buf_info->drm_fourcc = drm_fourcc; + + return 0; } -static __DRIimage * -droid_create_image_from_prime_fds(_EGLDisplay *disp, - struct ANativeWindowBuffer *buf, - void *priv) +static int +native_window_buffer_get_buffer_info(_EGLDisplay *disp, + struct ANativeWindowBuffer *buf, + struct buffer_info *out_buf_info) { - struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); - int pitches[4] = { 0 }, offsets[4] = { 0 }; - unsigned error; - int num_fds; + int num_planes = 0; + int drm_fourcc = 0; + int pitch = 0; int fds[3]; - num_fds = get_native_buffer_fds(buf, fds); - if (num_fds == 0) - return NULL; - if (is_yuv(buf->format)) { - __DRIimage *image; - - image = droid_create_image_from_prime_fds_yuv( - disp, buf, priv, num_fds, fds); + int ret = get_yuv_buffer_info(disp, buf, out_buf_info); /* * HACK: https://issuetracker.google.com/32077885 * There is no API available to properly query the IMPLEMENTATION_DEFINED @@ -302,8 +308,8 @@ droid_create_image_from_prime_fds(_EGLDisplay *disp, * an arbitrary YCbCr 4:2:0 or RGBX_8888, with the latter being recognized * by lock_ycbcr failing. */ - if (image || buf->format != HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) - return image; + if (ret != -EAGAIN) + return ret; } /* @@ -311,29 +317,30 @@ droid_create_image_from_prime_fds(_EGLDisplay *disp, * color compression state buffer, but the rest of the code isn't ready * yet to deal with modifiers: */ - assert(num_fds == 1); + num_planes = get_native_buffer_fds(buf, fds); + if (num_planes == 0) + return -EINVAL; - const int fourcc = get_fourcc(buf->format); - if (fourcc == -1) { + assert(num_planes == 1); + + drm_fourcc = get_fourcc(buf->format); + if (drm_fourcc == -1) { _eglError(EGL_BAD_PARAMETER, "eglCreateEGLImageKHR"); - return NULL; + return -EINVAL; } - pitches[0] = buf->stride * get_format_bpp(buf->format); - if (pitches[0] == 0) { + pitch = buf->stride * get_format_bpp(buf->format); + if (pitch == 0) { _eglError(EGL_BAD_PARAMETER, "eglCreateEGLImageKHR"); - return NULL; + return -EINVAL; } - return dri2_dpy->image->createImageFromDmaBufs(dri2_dpy->dri_screen, - buf->width, buf->height, fourcc, - fds, num_fds, pitches, offsets, - EGL_ITU_REC601_EXT, - EGL_YUV_NARROW_RANGE_EXT, - EGL_YUV_CHROMA_SITING_0_EXT, - EGL_YUV_CHROMA_SITING_0_EXT, - &error, - priv); + out_buf_info->num_planes = num_planes; + out_buf_info->drm_fourcc = drm_fourcc; + out_buf_info->pitches[0] = pitch; + out_buf_info->fds[0] = fds[0]; + + return 0; } /* More recent CrOS gralloc has a perform op that fills out the struct below @@ -359,36 +366,32 @@ struct cros_gralloc0_buffer_info { int stride[4]; }; -static __DRIimage * -droid_create_image_from_cros_info(_EGLDisplay *disp, - struct ANativeWindowBuffer *buf, - void* priv) +static int +cros_get_buffer_info(_EGLDisplay *disp, + struct ANativeWindowBuffer *buf, + struct buffer_info *out_buf_info) { struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); struct cros_gralloc0_buffer_info info; - unsigned error; if (strcmp(dri2_dpy->gralloc->common.name, cros_gralloc_module_name) == 0 && dri2_dpy->gralloc->perform && - dri2_dpy->image->base.version >= 15 && - dri2_dpy->image->createImageFromDmaBufs2 != NULL && dri2_dpy->gralloc->perform(dri2_dpy->gralloc, CROS_GRALLOC_DRM_GET_BUFFER_INFO, buf->handle, &info) == 0) { - return dri2_dpy->image->createImageFromDmaBufs2(dri2_dpy->dri_screen, - buf->width, buf->height, - info.drm_fourcc, info.modifier, - info.fds, info.num_fds, - info.stride, info.offset, - EGL_ITU_REC601_EXT, - EGL_YUV_FULL_RANGE_EXT, - EGL_YUV_CHROMA_SITING_0_EXT, - EGL_YUV_CHROMA_SITING_0_EXT, - &error, - priv); + out_buf_info->drm_fourcc = info.drm_fourcc; + out_buf_info->modifier = info.modifier; + out_buf_info->num_planes = info.num_fds; + for (int i = 0; i < out_buf_info->num_planes; i++) { + out_buf_info->fds[i] = info.fds[i]; + out_buf_info->offsets[i] = info.offset[i]; + out_buf_info->pitches[i] = info.stride[i]; + } + + return 0; } - return NULL; + return -EINVAL; } static __DRIimage * @@ -396,13 +399,40 @@ droid_create_image_from_native_buffer(_EGLDisplay *disp, struct ANativeWindowBuffer *buf, void *priv) { - __DRIimage *dri_image; + struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); + struct buffer_info buf_info = {.modifier = DRM_FORMAT_MOD_INVALID}; + unsigned error; - dri_image = droid_create_image_from_cros_info(disp, buf, priv); - if (dri_image) - return dri_image; + do { + if (!cros_get_buffer_info(disp, buf, &buf_info)) + break; - return droid_create_image_from_prime_fds(disp, buf, priv); + if (!native_window_buffer_get_buffer_info(disp, buf, &buf_info)) + break; + + return NULL; + } while (0); + + if (dri2_dpy->image->base.version >= 15 && + dri2_dpy->image->createImageFromDmaBufs2 != NULL) { + return dri2_dpy->image->createImageFromDmaBufs2(dri2_dpy->dri_screen, + buf->width, buf->height, buf_info.drm_fourcc, buf_info.modifier, + buf_info.fds, buf_info.num_planes, + buf_info.pitches, buf_info.offsets, + buf_info.yuv_color_space, buf_info.sample_range, + buf_info.horizontal_siting, buf_info.vertical_siting, + &error, + priv); + } else { + return dri2_dpy->image->createImageFromDmaBufs(dri2_dpy->dri_screen, + buf->width, buf->height, buf_info.drm_fourcc, + buf_info.fds, buf_info.num_planes, + buf_info.pitches, buf_info.offsets, + buf_info.yuv_color_space, buf_info.sample_range, + buf_info.horizontal_siting, buf_info.vertical_siting, + &error, + priv); + } } static EGLBoolean