-static _EGLImage *
-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;
- size_t offsets[3];
- size_t pitches[3];
- enum chroma_order chroma_order;
- int fourcc;
- int ret;
-
- if (!dri2_dpy->gralloc->lock_ycbcr) {
- _eglLog(_EGL_WARNING, "Gralloc does not support lock_ycbcr");
- return NULL;
- }
-
- 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
- * https://issuetracker.google.com/32077885.*/
- if (buf->format == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED)
- return NULL;
-
- _eglLog(_EGL_WARNING, "gralloc->lock_ycbcr failed: %d", ret);
- return NULL;
- }
- dri2_dpy->gralloc->unlock(dri2_dpy->gralloc, buf->handle);
-
- /* 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;
- /* 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;
- } else {
- chroma_order = YCbCr;
- offsets[1] = (size_t)ycbcr.cb;
- 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;
- }
-
- /*
- * 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, fds[0],
- EGL_DMA_BUF_PLANE0_PITCH_EXT, pitches[0],
- EGL_DMA_BUF_PLANE0_OFFSET_EXT, offsets[0],
- 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
- };
-
- return dri2_create_image_dma_buf(disp, ctx, NULL, attr_list_2plane);
- } else {
- /* Fully planar Y + Cb + Cr or Y + Cr + Cb format. */
- const EGLint attr_list_3plane[] = {
- EGL_WIDTH, buf->width,
- EGL_HEIGHT, buf->height,
- EGL_LINUX_DRM_FOURCC_EXT, fourcc,
- 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, fds[1],
- EGL_DMA_BUF_PLANE1_PITCH_EXT, pitches[1],
- EGL_DMA_BUF_PLANE1_OFFSET_EXT, offsets[1],
- 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
- };
-
- return dri2_create_image_dma_buf(disp, ctx, NULL, attr_list_3plane);
- }
-}
-
-static _EGLImage *
-droid_create_image_from_prime_fds(_EGLDisplay *disp, _EGLContext *ctx,
- struct ANativeWindowBuffer *buf, int num_fds, int fds[3])