From: Qiang Yu <yuq825@gmail.com>
v2:
* use new dmabuf API and check length
Signed-off-by: Qiang Yu <yuq825@gmail.com>
---
include/ui/egl-helpers.h | 5 ++-
ui/dbus-listener.c | 19 +++++----
ui/egl-helpers.c | 91 ++++++++++++++++++++++++++++++----------
ui/spice-display.c | 58 ++++++++++++++++---------
4 files changed, 121 insertions(+), 52 deletions(-)
diff --git a/include/ui/egl-helpers.h b/include/ui/egl-helpers.h
index 4b8c0d2281..fb80e15142 100644
--- a/include/ui/egl-helpers.h
+++ b/include/ui/egl-helpers.h
@@ -46,8 +46,9 @@ extern int qemu_egl_rn_fd;
extern struct gbm_device *qemu_egl_rn_gbm_dev;
int egl_rendernode_init(const char *rendernode, DisplayGLMode mode);
-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);
void egl_dmabuf_import_texture(QemuDmaBuf *dmabuf);
void egl_dmabuf_release_texture(QemuDmaBuf *dmabuf);
diff --git a/ui/dbus-listener.c b/ui/dbus-listener.c
index 65373d519c..90147972cd 100644
--- a/ui/dbus-listener.c
+++ b/ui/dbus-listener.c
@@ -504,19 +504,22 @@ static void dbus_scanout_texture(DisplayChangeListener *dcl,
backing_width, backing_height, x, y, w, h);
#ifdef CONFIG_GBM
g_autoptr(QemuDmaBuf) dmabuf = NULL;
- int fd;
- uint32_t offset = 0, stride, fourcc;
+ int fd[DMABUF_MAX_PLANES], num_planes;
+ uint32_t offset[DMABUF_MAX_PLANES], stride[DMABUF_MAX_PLANES], fourcc;
uint64_t modifier;
assert(tex_id);
- fd = egl_get_fd_for_texture(tex_id, (EGLint *)&stride, (EGLint *)&fourcc,
- &modifier);
- if (fd < 0) {
- error_report("%s: failed to get fd for texture", __func__);
+ if (!egl_dmabuf_export_texture(tex_id, fd, (EGLint *)offset, (EGLint *)stride,
+ (EGLint *)&fourcc, &num_planes, &modifier)) {
+ error_report("%s: failed to export dmabuf for texture", __func__);
+ return;
+ }
+ if (num_planes > 1) {
+ error_report("%s: does not support multi-plane dmabuf", __func__);
return;
}
- dmabuf = qemu_dmabuf_new(w, h, &offset, &stride, x, y, backing_width,
- backing_height, fourcc, modifier, &fd, 1,
+ dmabuf = qemu_dmabuf_new(w, h, offset, stride, x, y, backing_width,
+ backing_height, fourcc, modifier, fd, num_planes,
false, backing_y_0_top);
dbus_scanout_dmabuf(dcl, dmabuf);
diff --git a/ui/egl-helpers.c b/ui/egl-helpers.c
index 8c0e394d2b..f76d0c04a2 100644
--- a/ui/egl-helpers.c
+++ b/ui/egl-helpers.c
@@ -283,44 +283,85 @@ 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;
+ 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;
@@ -328,18 +369,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_fds(dmabuf, NULL)[0];
- attrs[i++] = EGL_DMA_BUF_PLANE0_PITCH_EXT;
- attrs[i++] = qemu_dmabuf_get_strides(dmabuf, NULL)[0];
- attrs[i++] = EGL_DMA_BUF_PLANE0_OFFSET_EXT;
- attrs[i++] = 0;
- if (modifier != DRM_FORMAT_MOD_INVALID) {
- 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;
+ }
}
+
attrs[i++] = EGL_NONE;
image = eglCreateImageKHR(qemu_egl_display,
diff --git a/ui/spice-display.c b/ui/spice-display.c
index 40547edb5e..d7ebb3682d 100644
--- a/ui/spice-display.c
+++ b/ui/spice-display.c
@@ -876,19 +876,24 @@ static void spice_gl_switch(DisplayChangeListener *dcl,
struct DisplaySurface *new_surface)
{
SimpleSpiceDisplay *ssd = container_of(dcl, SimpleSpiceDisplay, dcl);
- EGLint stride, fourcc;
- int fd;
if (ssd->ds) {
surface_gl_destroy_texture(ssd->gls, ssd->ds);
}
ssd->ds = new_surface;
if (ssd->ds) {
+ uint32_t offset[DMABUF_MAX_PLANES], stride[DMABUF_MAX_PLANES];
+ int fd[DMABUF_MAX_PLANES], num_planes, fourcc;
+
surface_gl_create_texture(ssd->gls, ssd->ds);
- fd = egl_get_fd_for_texture(ssd->ds->texture,
- &stride, &fourcc,
- NULL);
- if (fd < 0) {
+ if (!egl_dmabuf_export_texture(ssd->ds->texture, fd, (EGLint *)offset,
+ (EGLint *)stride, &fourcc, &num_planes, NULL)) {
+ surface_gl_destroy_texture(ssd->gls, ssd->ds);
+ return;
+ }
+
+ if (num_planes > 1) {
+ fprintf(stderr, "%s: does not support multi-plane texture\n", __func__);
surface_gl_destroy_texture(ssd->gls, ssd->ds);
return;
}
@@ -899,10 +904,10 @@ static void spice_gl_switch(DisplayChangeListener *dcl,
fourcc);
/* note: spice server will close the fd */
- spice_qxl_gl_scanout(&ssd->qxl, fd,
+ spice_qxl_gl_scanout(&ssd->qxl, fd[0],
surface_width(ssd->ds),
surface_height(ssd->ds),
- stride, fourcc, false);
+ stride[0], fourcc, false);
ssd->have_surface = true;
ssd->have_scanout = false;
@@ -941,20 +946,24 @@ static void qemu_spice_gl_scanout_texture(DisplayChangeListener *dcl,
void *d3d_tex2d)
{
SimpleSpiceDisplay *ssd = container_of(dcl, SimpleSpiceDisplay, dcl);
- EGLint stride = 0, fourcc = 0;
- int fd = -1;
+ EGLint offset[DMABUF_MAX_PLANES], stride[DMABUF_MAX_PLANES], fourcc = 0;
+ int fd[DMABUF_MAX_PLANES], num_planes;
assert(tex_id);
- fd = egl_get_fd_for_texture(tex_id, &stride, &fourcc, NULL);
- if (fd < 0) {
- fprintf(stderr, "%s: failed to get fd for texture\n", __func__);
+ if (!egl_dmabuf_export_texture(tex_id, fd, offset, stride, &fourcc,
+ &num_planes, NULL)) {
+ fprintf(stderr, "%s: failed to export dmabuf for texture\n", __func__);
+ return;
+ }
+ if (num_planes > 1) {
+ fprintf(stderr, "%s: does not support multi-plane dmabuf\n", __func__);
return;
}
trace_qemu_spice_gl_scanout_texture(ssd->qxl.id, w, h, fourcc);
/* note: spice server will close the fd */
- spice_qxl_gl_scanout(&ssd->qxl, fd, backing_width, backing_height,
- stride, fourcc, y_0_top);
+ spice_qxl_gl_scanout(&ssd->qxl, fd[0], backing_width, backing_height,
+ stride[0], fourcc, y_0_top);
qemu_spice_gl_monitor_config(ssd, x, y, w, h);
ssd->have_surface = false;
ssd->have_scanout = true;
@@ -1064,15 +1073,26 @@ static void qemu_spice_gl_update(DisplayChangeListener *dcl,
/* dest framebuffer */
if (ssd->blit_fb.width != width ||
ssd->blit_fb.height != height) {
+ int fds[DMABUF_MAX_PLANES], num_planes;
+ uint32_t offsets[DMABUF_MAX_PLANES], strides[DMABUF_MAX_PLANES];
+
trace_qemu_spice_gl_render_dmabuf(ssd->qxl.id, width,
height);
egl_fb_destroy(&ssd->blit_fb);
egl_fb_setup_new_tex(&ssd->blit_fb,
width, height);
- fd = egl_get_fd_for_texture(ssd->blit_fb.texture,
- &stride, &fourcc, NULL);
- spice_qxl_gl_scanout(&ssd->qxl, fd, width, height,
- stride, fourcc, false);
+ if (!egl_dmabuf_export_texture(ssd->blit_fb.texture, fds,
+ (EGLint *)offsets, (EGLint *)strides,
+ &fourcc, &num_planes, NULL)) {
+ fprintf(stderr, "%s: failed to export dmabuf for texture\n", __func__);
+ return;
+ }
+ if (num_planes > 1) {
+ fprintf(stderr, "%s: does not support multi-plane dmabuf\n", __func__);
+ return;
+ }
+ spice_qxl_gl_scanout(&ssd->qxl, fds[0], width, height,
+ strides[0], fourcc, false);
}
} else {
stride = qemu_dmabuf_get_strides(dmabuf, NULL)[0];
--
2.43.0
On Wed, Mar 26, 2025 at 1:34 PM <yuq825@gmail.com> wrote:
>
> From: Qiang Yu <yuq825@gmail.com>
>
> v2:
> * use new dmabuf API and check length
>
> Signed-off-by: Qiang Yu <yuq825@gmail.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
> include/ui/egl-helpers.h | 5 ++-
> ui/dbus-listener.c | 19 +++++----
> ui/egl-helpers.c | 91 ++++++++++++++++++++++++++++++----------
> ui/spice-display.c | 58 ++++++++++++++++---------
> 4 files changed, 121 insertions(+), 52 deletions(-)
>
> diff --git a/include/ui/egl-helpers.h b/include/ui/egl-helpers.h
> index 4b8c0d2281..fb80e15142 100644
> --- a/include/ui/egl-helpers.h
> +++ b/include/ui/egl-helpers.h
> @@ -46,8 +46,9 @@ extern int qemu_egl_rn_fd;
> extern struct gbm_device *qemu_egl_rn_gbm_dev;
>
> int egl_rendernode_init(const char *rendernode, DisplayGLMode mode);
> -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);
>
> void egl_dmabuf_import_texture(QemuDmaBuf *dmabuf);
> void egl_dmabuf_release_texture(QemuDmaBuf *dmabuf);
> diff --git a/ui/dbus-listener.c b/ui/dbus-listener.c
> index 65373d519c..90147972cd 100644
> --- a/ui/dbus-listener.c
> +++ b/ui/dbus-listener.c
> @@ -504,19 +504,22 @@ static void dbus_scanout_texture(DisplayChangeListener *dcl,
> backing_width, backing_height, x, y, w, h);
> #ifdef CONFIG_GBM
> g_autoptr(QemuDmaBuf) dmabuf = NULL;
> - int fd;
> - uint32_t offset = 0, stride, fourcc;
> + int fd[DMABUF_MAX_PLANES], num_planes;
> + uint32_t offset[DMABUF_MAX_PLANES], stride[DMABUF_MAX_PLANES], fourcc;
> uint64_t modifier;
>
> assert(tex_id);
> - fd = egl_get_fd_for_texture(tex_id, (EGLint *)&stride, (EGLint *)&fourcc,
> - &modifier);
> - if (fd < 0) {
> - error_report("%s: failed to get fd for texture", __func__);
> + if (!egl_dmabuf_export_texture(tex_id, fd, (EGLint *)offset, (EGLint *)stride,
> + (EGLint *)&fourcc, &num_planes, &modifier)) {
> + error_report("%s: failed to export dmabuf for texture", __func__);
> + return;
> + }
> + if (num_planes > 1) {
> + error_report("%s: does not support multi-plane dmabuf", __func__);
> return;
> }
> - dmabuf = qemu_dmabuf_new(w, h, &offset, &stride, x, y, backing_width,
> - backing_height, fourcc, modifier, &fd, 1,
> + dmabuf = qemu_dmabuf_new(w, h, offset, stride, x, y, backing_width,
> + backing_height, fourcc, modifier, fd, num_planes,
> false, backing_y_0_top);
>
> dbus_scanout_dmabuf(dcl, dmabuf);
> diff --git a/ui/egl-helpers.c b/ui/egl-helpers.c
> index 8c0e394d2b..f76d0c04a2 100644
> --- a/ui/egl-helpers.c
> +++ b/ui/egl-helpers.c
> @@ -283,44 +283,85 @@ 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;
> + 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;
> @@ -328,18 +369,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_fds(dmabuf, NULL)[0];
> - attrs[i++] = EGL_DMA_BUF_PLANE0_PITCH_EXT;
> - attrs[i++] = qemu_dmabuf_get_strides(dmabuf, NULL)[0];
> - attrs[i++] = EGL_DMA_BUF_PLANE0_OFFSET_EXT;
> - attrs[i++] = 0;
> - if (modifier != DRM_FORMAT_MOD_INVALID) {
> - 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;
> + }
> }
> +
> attrs[i++] = EGL_NONE;
>
> image = eglCreateImageKHR(qemu_egl_display,
> diff --git a/ui/spice-display.c b/ui/spice-display.c
> index 40547edb5e..d7ebb3682d 100644
> --- a/ui/spice-display.c
> +++ b/ui/spice-display.c
> @@ -876,19 +876,24 @@ static void spice_gl_switch(DisplayChangeListener *dcl,
> struct DisplaySurface *new_surface)
> {
> SimpleSpiceDisplay *ssd = container_of(dcl, SimpleSpiceDisplay, dcl);
> - EGLint stride, fourcc;
> - int fd;
>
> if (ssd->ds) {
> surface_gl_destroy_texture(ssd->gls, ssd->ds);
> }
> ssd->ds = new_surface;
> if (ssd->ds) {
> + uint32_t offset[DMABUF_MAX_PLANES], stride[DMABUF_MAX_PLANES];
> + int fd[DMABUF_MAX_PLANES], num_planes, fourcc;
> +
> surface_gl_create_texture(ssd->gls, ssd->ds);
> - fd = egl_get_fd_for_texture(ssd->ds->texture,
> - &stride, &fourcc,
> - NULL);
> - if (fd < 0) {
> + if (!egl_dmabuf_export_texture(ssd->ds->texture, fd, (EGLint *)offset,
> + (EGLint *)stride, &fourcc, &num_planes, NULL)) {
> + surface_gl_destroy_texture(ssd->gls, ssd->ds);
> + return;
> + }
> +
> + if (num_planes > 1) {
> + fprintf(stderr, "%s: does not support multi-plane texture\n", __func__);
> surface_gl_destroy_texture(ssd->gls, ssd->ds);
> return;
> }
> @@ -899,10 +904,10 @@ static void spice_gl_switch(DisplayChangeListener *dcl,
> fourcc);
>
> /* note: spice server will close the fd */
> - spice_qxl_gl_scanout(&ssd->qxl, fd,
> + spice_qxl_gl_scanout(&ssd->qxl, fd[0],
> surface_width(ssd->ds),
> surface_height(ssd->ds),
> - stride, fourcc, false);
> + stride[0], fourcc, false);
> ssd->have_surface = true;
> ssd->have_scanout = false;
>
> @@ -941,20 +946,24 @@ static void qemu_spice_gl_scanout_texture(DisplayChangeListener *dcl,
> void *d3d_tex2d)
> {
> SimpleSpiceDisplay *ssd = container_of(dcl, SimpleSpiceDisplay, dcl);
> - EGLint stride = 0, fourcc = 0;
> - int fd = -1;
> + EGLint offset[DMABUF_MAX_PLANES], stride[DMABUF_MAX_PLANES], fourcc = 0;
> + int fd[DMABUF_MAX_PLANES], num_planes;
>
> assert(tex_id);
> - fd = egl_get_fd_for_texture(tex_id, &stride, &fourcc, NULL);
> - if (fd < 0) {
> - fprintf(stderr, "%s: failed to get fd for texture\n", __func__);
> + if (!egl_dmabuf_export_texture(tex_id, fd, offset, stride, &fourcc,
> + &num_planes, NULL)) {
> + fprintf(stderr, "%s: failed to export dmabuf for texture\n", __func__);
> + return;
> + }
> + if (num_planes > 1) {
> + fprintf(stderr, "%s: does not support multi-plane dmabuf\n", __func__);
> return;
> }
> trace_qemu_spice_gl_scanout_texture(ssd->qxl.id, w, h, fourcc);
>
> /* note: spice server will close the fd */
> - spice_qxl_gl_scanout(&ssd->qxl, fd, backing_width, backing_height,
> - stride, fourcc, y_0_top);
> + spice_qxl_gl_scanout(&ssd->qxl, fd[0], backing_width, backing_height,
> + stride[0], fourcc, y_0_top);
> qemu_spice_gl_monitor_config(ssd, x, y, w, h);
> ssd->have_surface = false;
> ssd->have_scanout = true;
> @@ -1064,15 +1073,26 @@ static void qemu_spice_gl_update(DisplayChangeListener *dcl,
> /* dest framebuffer */
> if (ssd->blit_fb.width != width ||
> ssd->blit_fb.height != height) {
> + int fds[DMABUF_MAX_PLANES], num_planes;
> + uint32_t offsets[DMABUF_MAX_PLANES], strides[DMABUF_MAX_PLANES];
> +
> trace_qemu_spice_gl_render_dmabuf(ssd->qxl.id, width,
> height);
> egl_fb_destroy(&ssd->blit_fb);
> egl_fb_setup_new_tex(&ssd->blit_fb,
> width, height);
> - fd = egl_get_fd_for_texture(ssd->blit_fb.texture,
> - &stride, &fourcc, NULL);
> - spice_qxl_gl_scanout(&ssd->qxl, fd, width, height,
> - stride, fourcc, false);
> + if (!egl_dmabuf_export_texture(ssd->blit_fb.texture, fds,
> + (EGLint *)offsets, (EGLint *)strides,
> + &fourcc, &num_planes, NULL)) {
> + fprintf(stderr, "%s: failed to export dmabuf for texture\n", __func__);
> + return;
> + }
> + if (num_planes > 1) {
> + fprintf(stderr, "%s: does not support multi-plane dmabuf\n", __func__);
> + return;
> + }
> + spice_qxl_gl_scanout(&ssd->qxl, fds[0], width, height,
> + strides[0], fourcc, false);
> }
> } else {
> stride = qemu_dmabuf_get_strides(dmabuf, NULL)[0];
> --
> 2.43.0
>
--
Marc-André Lureau
© 2016 - 2026 Red Hat, Inc.