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@chromium.org>
Reviewed-by: Eric Engestrom <eric@engestrom.ch>
Reviewed-by: Kristian H. Kristensen <hoegsberg@google.com>
Reviewed-by: Eric Anholt <eric@anholt.net>
This commit is contained in:
Rob Clark 2019-07-12 09:17:30 -07:00 committed by Rob Clark
parent 110669c85c
commit a9f34b5631

View file

@ -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);