diff options
Diffstat (limited to 'ui/egl-helpers.c')
-rw-r--r-- | ui/egl-helpers.c | 103 |
1 files changed, 76 insertions, 27 deletions
diff --git a/ui/egl-helpers.c b/ui/egl-helpers.c index d591159..9cda2bb 100644 --- a/ui/egl-helpers.c +++ b/ui/egl-helpers.c @@ -23,6 +23,7 @@ #include "system/system.h" #include "qapi/error.h" #include "trace.h" +#include "standard-headers/drm/drm_fourcc.h" EGLDisplay *qemu_egl_display; EGLConfig qemu_egl_config; @@ -257,6 +258,11 @@ int egl_rendernode_init(const char *rendernode, DisplayGLMode mode) error_report("egl: EGL_MESA_image_dma_buf_export not supported"); goto err; } + if (!epoxy_has_egl_extension(qemu_egl_display, + "EGL_EXT_image_dma_buf_import_modifiers")) { + error_report("egl: EGL_EXT_image_dma_buf_import_modifiers not supported"); + goto err; + } qemu_egl_rn_ctx = qemu_egl_init_ctx(); if (!qemu_egl_rn_ctx) { @@ -277,44 +283,86 @@ err: return -1; } -int egl_get_fd_for_texture(uint32_t tex_id, EGLint *stride, EGLint *fourcc, - EGLuint64KHR *modifier) +bool egl_dmabuf_export_texture(uint32_t tex_id, int *fd, EGLint *offset, + EGLint *stride, EGLint *fourcc, int *num_planes, + EGLuint64KHR *modifier) { EGLImageKHR image; - EGLint num_planes, fd; + EGLuint64KHR modifiers[DMABUF_MAX_PLANES]; image = eglCreateImageKHR(qemu_egl_display, eglGetCurrentContext(), EGL_GL_TEXTURE_2D_KHR, (EGLClientBuffer)(unsigned long)tex_id, NULL); if (!image) { - return -1; + return false; } eglExportDMABUFImageQueryMESA(qemu_egl_display, image, fourcc, - &num_planes, modifier); - if (num_planes != 1) { - eglDestroyImageKHR(qemu_egl_display, image); - return -1; - } - eglExportDMABUFImageMESA(qemu_egl_display, image, &fd, stride, NULL); + num_planes, modifiers); + eglExportDMABUFImageMESA(qemu_egl_display, image, fd, stride, offset); eglDestroyImageKHR(qemu_egl_display, image); - return fd; + /* Only first modifier matters. */ + if (modifier) { + *modifier = modifiers[0]; + } + + return true; } void egl_dmabuf_import_texture(QemuDmaBuf *dmabuf) { EGLImageKHR image = EGL_NO_IMAGE_KHR; EGLint attrs[64]; - int i = 0; - uint64_t modifier; + int i = 0, j; + uint64_t modifier = qemu_dmabuf_get_modifier(dmabuf); uint32_t texture = qemu_dmabuf_get_texture(dmabuf); + int nfds, noffsets, nstrides; + const int *fds = qemu_dmabuf_get_fds(dmabuf, &nfds); + const uint32_t *offsets = qemu_dmabuf_get_offsets(dmabuf, &noffsets); + const uint32_t *strides = qemu_dmabuf_get_strides(dmabuf, &nstrides); + uint32_t num_planes = qemu_dmabuf_get_num_planes(dmabuf); + + EGLint fd_attrs[] = { + EGL_DMA_BUF_PLANE0_FD_EXT, + EGL_DMA_BUF_PLANE1_FD_EXT, + EGL_DMA_BUF_PLANE2_FD_EXT, + EGL_DMA_BUF_PLANE3_FD_EXT, + }; + EGLint offset_attrs[] = { + EGL_DMA_BUF_PLANE0_OFFSET_EXT, + EGL_DMA_BUF_PLANE1_OFFSET_EXT, + EGL_DMA_BUF_PLANE2_OFFSET_EXT, + EGL_DMA_BUF_PLANE3_OFFSET_EXT, + }; + EGLint stride_attrs[] = { + EGL_DMA_BUF_PLANE0_PITCH_EXT, + EGL_DMA_BUF_PLANE1_PITCH_EXT, + EGL_DMA_BUF_PLANE2_PITCH_EXT, + EGL_DMA_BUF_PLANE3_PITCH_EXT, + }; + EGLint modifier_lo_attrs[] = { + EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT, + EGL_DMA_BUF_PLANE1_MODIFIER_LO_EXT, + EGL_DMA_BUF_PLANE2_MODIFIER_LO_EXT, + EGL_DMA_BUF_PLANE3_MODIFIER_LO_EXT, + }; + EGLint modifier_hi_attrs[] = { + EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT, + EGL_DMA_BUF_PLANE1_MODIFIER_HI_EXT, + EGL_DMA_BUF_PLANE2_MODIFIER_HI_EXT, + EGL_DMA_BUF_PLANE3_MODIFIER_HI_EXT, + }; if (texture != 0) { return; } + assert(nfds >= num_planes); + assert(noffsets >= num_planes); + assert(nstrides >= num_planes); + attrs[i++] = EGL_WIDTH; attrs[i++] = qemu_dmabuf_get_backing_width(dmabuf); attrs[i++] = EGL_HEIGHT; @@ -322,21 +370,22 @@ void egl_dmabuf_import_texture(QemuDmaBuf *dmabuf) attrs[i++] = EGL_LINUX_DRM_FOURCC_EXT; attrs[i++] = qemu_dmabuf_get_fourcc(dmabuf); - attrs[i++] = EGL_DMA_BUF_PLANE0_FD_EXT; - attrs[i++] = qemu_dmabuf_get_fd(dmabuf); - attrs[i++] = EGL_DMA_BUF_PLANE0_PITCH_EXT; - attrs[i++] = qemu_dmabuf_get_stride(dmabuf); - attrs[i++] = EGL_DMA_BUF_PLANE0_OFFSET_EXT; - attrs[i++] = 0; -#ifdef EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT - modifier = qemu_dmabuf_get_modifier(dmabuf); - if (modifier) { - attrs[i++] = EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT; - attrs[i++] = (modifier >> 0) & 0xffffffff; - attrs[i++] = EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT; - attrs[i++] = (modifier >> 32) & 0xffffffff; + for (j = 0; j < num_planes; j++) { + attrs[i++] = fd_attrs[j]; + /* fd[1-3] may be -1 if using a joint buffer for all planes */ + attrs[i++] = fds[j] >= 0 ? fds[j] : fds[0]; + attrs[i++] = stride_attrs[j]; + attrs[i++] = strides[j]; + attrs[i++] = offset_attrs[j]; + attrs[i++] = offsets[j]; + if (modifier != DRM_FORMAT_MOD_INVALID) { + attrs[i++] = modifier_lo_attrs[j]; + attrs[i++] = (modifier >> 0) & 0xffffffff; + attrs[i++] = modifier_hi_attrs[j]; + attrs[i++] = (modifier >> 32) & 0xffffffff; + } } -#endif + attrs[i++] = EGL_NONE; image = eglCreateImageKHR(qemu_egl_display, |