From cadcaf1e832eb58dd500f0c46c510dbee79fa6f0 Mon Sep 17 00:00:00 2001 From: Gurchetan Singh Date: Thu, 18 Jul 2019 16:16:43 -0700 Subject: [PATCH] virgl/egl: allow creating EGL images from dma-bufs It's possible to EGL images from any dmabuf. Currently, gbm-based dma-bufs are supported. v2: 39 attributes --> 37 attributes (@davidriley) Reviewed-by: David Riley Signed-off-by: Gurchetan Singh --- src/virgl_egl.h | 3 ++ src/virgl_egl_context.c | 61 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+) diff --git a/src/virgl_egl.h b/src/virgl_egl.h index 13f4801..e7f0270 100644 --- a/src/virgl_egl.h +++ b/src/virgl_egl.h @@ -28,6 +28,7 @@ #include "vrend_renderer.h" struct virgl_egl; struct virgl_gbm; +struct gbm_bo; struct virgl_egl *virgl_egl_init(struct virgl_gbm *gbm, bool surfaceless, bool gles); @@ -51,4 +52,6 @@ int virgl_egl_get_fd_for_texture(struct virgl_egl *egl, uint32_t tex_id, int *fd int virgl_egl_get_fd_for_texture2(struct virgl_egl *egl, uint32_t tex_id, int *fd, int *stride, int *offset); + +void *virgl_egl_image_from_dmabuf(struct virgl_egl *egl, struct gbm_bo *bo); #endif diff --git a/src/virgl_egl_context.c b/src/virgl_egl_context.c index a08acc4..5a387fd 100644 --- a/src/virgl_egl_context.c +++ b/src/virgl_egl_context.c @@ -374,3 +374,64 @@ bool virgl_has_egl_khr_gl_colorspace(struct virgl_egl *egl) { return egl->have_khr_gl_colorspace; } + +void *virgl_egl_image_from_dmabuf(struct virgl_egl *egl, struct gbm_bo *bo) +{ + int ret; + EGLImageKHR image; + int fds[4] = {-1, -1, -1, -1}; + int num_planes = gbm_bo_get_plane_count(bo); + // When the bo has 3 planes with modifier support, it requires 37 components. + EGLint khr_image_attrs[37] = { + EGL_WIDTH, + gbm_bo_get_width(bo), + EGL_HEIGHT, + gbm_bo_get_height(bo), + EGL_LINUX_DRM_FOURCC_EXT, + (int)gbm_bo_get_format(bo), + EGL_NONE, + }; + + if (num_planes < 0 || num_planes > 4) + return (void *)EGL_NO_IMAGE_KHR; + + for (int plane = 0; plane < num_planes; plane++) { + uint32_t handle = gbm_bo_get_handle_for_plane(bo, plane).u32; + ret = drmPrimeHandleToFD(gbm_device_get_fd(egl->gbm->device), handle, DRM_CLOEXEC, + &fds[plane]); + if (ret < 0) { + vrend_printf( "failed to export plane handle\n"); + image = (void *)EGL_NO_IMAGE_KHR; + goto out_close; + } + } + + size_t attrs_index = 6; + for (int plane = 0; plane < num_planes; plane++) { + khr_image_attrs[attrs_index++] = EGL_DMA_BUF_PLANE0_FD_EXT + plane * 3; + khr_image_attrs[attrs_index++] = fds[plane]; + khr_image_attrs[attrs_index++] = EGL_DMA_BUF_PLANE0_OFFSET_EXT + plane * 3; + khr_image_attrs[attrs_index++] = gbm_bo_get_offset(bo, plane); + khr_image_attrs[attrs_index++] = EGL_DMA_BUF_PLANE0_PITCH_EXT + plane * 3; + khr_image_attrs[attrs_index++] = gbm_bo_get_stride_for_plane(bo, plane); + if (egl->have_ext_image_dma_buf_import_modifiers) { + const uint64_t modifier = gbm_bo_get_modifier(bo); + khr_image_attrs[attrs_index++] = + EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT + plane * 2; + khr_image_attrs[attrs_index++] = modifier & 0xfffffffful; + khr_image_attrs[attrs_index++] = + EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT + plane * 2; + khr_image_attrs[attrs_index++] = modifier >> 32; + } + } + + khr_image_attrs[attrs_index++] = EGL_NONE; + image = eglCreateImageKHR(egl->egl_display, EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT, NULL, + khr_image_attrs); + +out_close: + for (int plane = 0; plane < num_planes; plane++) + close(fds[plane]); + + return (void*)image; +}