mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-08 18:23:57 -06:00
ui/egl: support multi-plane dmabuf when egl export/import
v2: * use new dmabuf API and check length Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com> Signed-off-by: Qiang Yu <yuq825@gmail.com> [ Fix style ] Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com> Message-ID: <20250327025848.46962-5-yuq825@gmail.com>
This commit is contained in:
parent
ac70568902
commit
0e15d0b927
4 changed files with 124 additions and 52 deletions
|
@ -46,8 +46,9 @@ extern int qemu_egl_rn_fd;
|
||||||
extern struct gbm_device *qemu_egl_rn_gbm_dev;
|
extern struct gbm_device *qemu_egl_rn_gbm_dev;
|
||||||
|
|
||||||
int egl_rendernode_init(const char *rendernode, DisplayGLMode mode);
|
int egl_rendernode_init(const char *rendernode, DisplayGLMode mode);
|
||||||
int egl_get_fd_for_texture(uint32_t tex_id, EGLint *stride, EGLint *fourcc,
|
bool egl_dmabuf_export_texture(uint32_t tex_id, int *fd, EGLint *offset,
|
||||||
EGLuint64KHR *modifier);
|
EGLint *stride, EGLint *fourcc, int *num_planes,
|
||||||
|
EGLuint64KHR *modifier);
|
||||||
|
|
||||||
void egl_dmabuf_import_texture(QemuDmaBuf *dmabuf);
|
void egl_dmabuf_import_texture(QemuDmaBuf *dmabuf);
|
||||||
void egl_dmabuf_release_texture(QemuDmaBuf *dmabuf);
|
void egl_dmabuf_release_texture(QemuDmaBuf *dmabuf);
|
||||||
|
|
|
@ -504,19 +504,22 @@ static void dbus_scanout_texture(DisplayChangeListener *dcl,
|
||||||
backing_width, backing_height, x, y, w, h);
|
backing_width, backing_height, x, y, w, h);
|
||||||
#ifdef CONFIG_GBM
|
#ifdef CONFIG_GBM
|
||||||
g_autoptr(QemuDmaBuf) dmabuf = NULL;
|
g_autoptr(QemuDmaBuf) dmabuf = NULL;
|
||||||
int fd;
|
int fd[DMABUF_MAX_PLANES], num_planes;
|
||||||
uint32_t offset = 0, stride, fourcc;
|
uint32_t offset[DMABUF_MAX_PLANES], stride[DMABUF_MAX_PLANES], fourcc;
|
||||||
uint64_t modifier;
|
uint64_t modifier;
|
||||||
|
|
||||||
assert(tex_id);
|
assert(tex_id);
|
||||||
fd = egl_get_fd_for_texture(tex_id, (EGLint *)&stride, (EGLint *)&fourcc,
|
if (!egl_dmabuf_export_texture(tex_id, fd, (EGLint *)offset, (EGLint *)stride,
|
||||||
&modifier);
|
(EGLint *)&fourcc, &num_planes, &modifier)) {
|
||||||
if (fd < 0) {
|
error_report("%s: failed to export dmabuf for texture", __func__);
|
||||||
error_report("%s: failed to get fd for texture", __func__);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
dmabuf = qemu_dmabuf_new(w, h, &offset, &stride, x, y, backing_width,
|
if (num_planes > 1) {
|
||||||
backing_height, fourcc, modifier, &fd, 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, num_planes,
|
||||||
false, backing_y_0_top);
|
false, backing_y_0_top);
|
||||||
|
|
||||||
dbus_scanout_dmabuf(dcl, dmabuf);
|
dbus_scanout_dmabuf(dcl, dmabuf);
|
||||||
|
|
|
@ -283,44 +283,86 @@ err:
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int egl_get_fd_for_texture(uint32_t tex_id, EGLint *stride, EGLint *fourcc,
|
bool egl_dmabuf_export_texture(uint32_t tex_id, int *fd, EGLint *offset,
|
||||||
EGLuint64KHR *modifier)
|
EGLint *stride, EGLint *fourcc, int *num_planes,
|
||||||
|
EGLuint64KHR *modifier)
|
||||||
{
|
{
|
||||||
EGLImageKHR image;
|
EGLImageKHR image;
|
||||||
EGLint num_planes, fd;
|
EGLuint64KHR modifiers[DMABUF_MAX_PLANES];
|
||||||
|
|
||||||
image = eglCreateImageKHR(qemu_egl_display, eglGetCurrentContext(),
|
image = eglCreateImageKHR(qemu_egl_display, eglGetCurrentContext(),
|
||||||
EGL_GL_TEXTURE_2D_KHR,
|
EGL_GL_TEXTURE_2D_KHR,
|
||||||
(EGLClientBuffer)(unsigned long)tex_id,
|
(EGLClientBuffer)(unsigned long)tex_id,
|
||||||
NULL);
|
NULL);
|
||||||
if (!image) {
|
if (!image) {
|
||||||
return -1;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
eglExportDMABUFImageQueryMESA(qemu_egl_display, image, fourcc,
|
eglExportDMABUFImageQueryMESA(qemu_egl_display, image, fourcc,
|
||||||
&num_planes, modifier);
|
num_planes, modifiers);
|
||||||
if (num_planes != 1) {
|
eglExportDMABUFImageMESA(qemu_egl_display, image, fd, stride, offset);
|
||||||
eglDestroyImageKHR(qemu_egl_display, image);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
eglExportDMABUFImageMESA(qemu_egl_display, image, &fd, stride, NULL);
|
|
||||||
eglDestroyImageKHR(qemu_egl_display, image);
|
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)
|
void egl_dmabuf_import_texture(QemuDmaBuf *dmabuf)
|
||||||
{
|
{
|
||||||
EGLImageKHR image = EGL_NO_IMAGE_KHR;
|
EGLImageKHR image = EGL_NO_IMAGE_KHR;
|
||||||
EGLint attrs[64];
|
EGLint attrs[64];
|
||||||
int i = 0;
|
int i = 0, j;
|
||||||
uint64_t modifier = qemu_dmabuf_get_modifier(dmabuf);
|
uint64_t modifier = qemu_dmabuf_get_modifier(dmabuf);
|
||||||
uint32_t texture = qemu_dmabuf_get_texture(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) {
|
if (texture != 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
assert(nfds >= num_planes);
|
||||||
|
assert(noffsets >= num_planes);
|
||||||
|
assert(nstrides >= num_planes);
|
||||||
|
|
||||||
attrs[i++] = EGL_WIDTH;
|
attrs[i++] = EGL_WIDTH;
|
||||||
attrs[i++] = qemu_dmabuf_get_backing_width(dmabuf);
|
attrs[i++] = qemu_dmabuf_get_backing_width(dmabuf);
|
||||||
attrs[i++] = EGL_HEIGHT;
|
attrs[i++] = EGL_HEIGHT;
|
||||||
|
@ -328,18 +370,22 @@ void egl_dmabuf_import_texture(QemuDmaBuf *dmabuf)
|
||||||
attrs[i++] = EGL_LINUX_DRM_FOURCC_EXT;
|
attrs[i++] = EGL_LINUX_DRM_FOURCC_EXT;
|
||||||
attrs[i++] = qemu_dmabuf_get_fourcc(dmabuf);
|
attrs[i++] = qemu_dmabuf_get_fourcc(dmabuf);
|
||||||
|
|
||||||
attrs[i++] = EGL_DMA_BUF_PLANE0_FD_EXT;
|
for (j = 0; j < num_planes; j++) {
|
||||||
attrs[i++] = qemu_dmabuf_get_fds(dmabuf, NULL)[0];
|
attrs[i++] = fd_attrs[j];
|
||||||
attrs[i++] = EGL_DMA_BUF_PLANE0_PITCH_EXT;
|
/* fd[1-3] may be -1 if using a joint buffer for all planes */
|
||||||
attrs[i++] = qemu_dmabuf_get_strides(dmabuf, NULL)[0];
|
attrs[i++] = fds[j] >= 0 ? fds[j] : fds[0];
|
||||||
attrs[i++] = EGL_DMA_BUF_PLANE0_OFFSET_EXT;
|
attrs[i++] = stride_attrs[j];
|
||||||
attrs[i++] = 0;
|
attrs[i++] = strides[j];
|
||||||
if (modifier != DRM_FORMAT_MOD_INVALID) {
|
attrs[i++] = offset_attrs[j];
|
||||||
attrs[i++] = EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT;
|
attrs[i++] = offsets[j];
|
||||||
attrs[i++] = (modifier >> 0) & 0xffffffff;
|
if (modifier != DRM_FORMAT_MOD_INVALID) {
|
||||||
attrs[i++] = EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT;
|
attrs[i++] = modifier_lo_attrs[j];
|
||||||
attrs[i++] = (modifier >> 32) & 0xffffffff;
|
attrs[i++] = (modifier >> 0) & 0xffffffff;
|
||||||
|
attrs[i++] = modifier_hi_attrs[j];
|
||||||
|
attrs[i++] = (modifier >> 32) & 0xffffffff;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
attrs[i++] = EGL_NONE;
|
attrs[i++] = EGL_NONE;
|
||||||
|
|
||||||
image = eglCreateImageKHR(qemu_egl_display,
|
image = eglCreateImageKHR(qemu_egl_display,
|
||||||
|
|
|
@ -876,19 +876,24 @@ static void spice_gl_switch(DisplayChangeListener *dcl,
|
||||||
struct DisplaySurface *new_surface)
|
struct DisplaySurface *new_surface)
|
||||||
{
|
{
|
||||||
SimpleSpiceDisplay *ssd = container_of(dcl, SimpleSpiceDisplay, dcl);
|
SimpleSpiceDisplay *ssd = container_of(dcl, SimpleSpiceDisplay, dcl);
|
||||||
EGLint stride, fourcc;
|
|
||||||
int fd;
|
|
||||||
|
|
||||||
if (ssd->ds) {
|
if (ssd->ds) {
|
||||||
surface_gl_destroy_texture(ssd->gls, ssd->ds);
|
surface_gl_destroy_texture(ssd->gls, ssd->ds);
|
||||||
}
|
}
|
||||||
ssd->ds = new_surface;
|
ssd->ds = new_surface;
|
||||||
if (ssd->ds) {
|
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);
|
surface_gl_create_texture(ssd->gls, ssd->ds);
|
||||||
fd = egl_get_fd_for_texture(ssd->ds->texture,
|
if (!egl_dmabuf_export_texture(ssd->ds->texture, fd, (EGLint *)offset,
|
||||||
&stride, &fourcc,
|
(EGLint *)stride, &fourcc, &num_planes, NULL)) {
|
||||||
NULL);
|
surface_gl_destroy_texture(ssd->gls, ssd->ds);
|
||||||
if (fd < 0) {
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (num_planes > 1) {
|
||||||
|
fprintf(stderr, "%s: does not support multi-plane texture\n", __func__);
|
||||||
surface_gl_destroy_texture(ssd->gls, ssd->ds);
|
surface_gl_destroy_texture(ssd->gls, ssd->ds);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -899,10 +904,10 @@ static void spice_gl_switch(DisplayChangeListener *dcl,
|
||||||
fourcc);
|
fourcc);
|
||||||
|
|
||||||
/* note: spice server will close the fd */
|
/* 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_width(ssd->ds),
|
||||||
surface_height(ssd->ds),
|
surface_height(ssd->ds),
|
||||||
stride, fourcc, false);
|
stride[0], fourcc, false);
|
||||||
ssd->have_surface = true;
|
ssd->have_surface = true;
|
||||||
ssd->have_scanout = false;
|
ssd->have_scanout = false;
|
||||||
|
|
||||||
|
@ -941,20 +946,24 @@ static void qemu_spice_gl_scanout_texture(DisplayChangeListener *dcl,
|
||||||
void *d3d_tex2d)
|
void *d3d_tex2d)
|
||||||
{
|
{
|
||||||
SimpleSpiceDisplay *ssd = container_of(dcl, SimpleSpiceDisplay, dcl);
|
SimpleSpiceDisplay *ssd = container_of(dcl, SimpleSpiceDisplay, dcl);
|
||||||
EGLint stride = 0, fourcc = 0;
|
EGLint offset[DMABUF_MAX_PLANES], stride[DMABUF_MAX_PLANES], fourcc = 0;
|
||||||
int fd = -1;
|
int fd[DMABUF_MAX_PLANES], num_planes;
|
||||||
|
|
||||||
assert(tex_id);
|
assert(tex_id);
|
||||||
fd = egl_get_fd_for_texture(tex_id, &stride, &fourcc, NULL);
|
if (!egl_dmabuf_export_texture(tex_id, fd, offset, stride, &fourcc,
|
||||||
if (fd < 0) {
|
&num_planes, NULL)) {
|
||||||
fprintf(stderr, "%s: failed to get fd for texture\n", __func__);
|
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;
|
return;
|
||||||
}
|
}
|
||||||
trace_qemu_spice_gl_scanout_texture(ssd->qxl.id, w, h, fourcc);
|
trace_qemu_spice_gl_scanout_texture(ssd->qxl.id, w, h, fourcc);
|
||||||
|
|
||||||
/* note: spice server will close the fd */
|
/* note: spice server will close the fd */
|
||||||
spice_qxl_gl_scanout(&ssd->qxl, fd, backing_width, backing_height,
|
spice_qxl_gl_scanout(&ssd->qxl, fd[0], backing_width, backing_height,
|
||||||
stride, fourcc, y_0_top);
|
stride[0], fourcc, y_0_top);
|
||||||
qemu_spice_gl_monitor_config(ssd, x, y, w, h);
|
qemu_spice_gl_monitor_config(ssd, x, y, w, h);
|
||||||
ssd->have_surface = false;
|
ssd->have_surface = false;
|
||||||
ssd->have_scanout = true;
|
ssd->have_scanout = true;
|
||||||
|
@ -1064,15 +1073,28 @@ static void qemu_spice_gl_update(DisplayChangeListener *dcl,
|
||||||
/* dest framebuffer */
|
/* dest framebuffer */
|
||||||
if (ssd->blit_fb.width != width ||
|
if (ssd->blit_fb.width != width ||
|
||||||
ssd->blit_fb.height != height) {
|
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,
|
trace_qemu_spice_gl_render_dmabuf(ssd->qxl.id, width,
|
||||||
height);
|
height);
|
||||||
egl_fb_destroy(&ssd->blit_fb);
|
egl_fb_destroy(&ssd->blit_fb);
|
||||||
egl_fb_setup_new_tex(&ssd->blit_fb,
|
egl_fb_setup_new_tex(&ssd->blit_fb,
|
||||||
width, height);
|
width, height);
|
||||||
fd = egl_get_fd_for_texture(ssd->blit_fb.texture,
|
if (!egl_dmabuf_export_texture(ssd->blit_fb.texture, fds,
|
||||||
&stride, &fourcc, NULL);
|
(EGLint *)offsets, (EGLint *)strides,
|
||||||
spice_qxl_gl_scanout(&ssd->qxl, fd, width, height,
|
&fourcc, &num_planes, NULL)) {
|
||||||
stride, fourcc, false);
|
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 {
|
} else {
|
||||||
stride = qemu_dmabuf_get_strides(dmabuf, NULL)[0];
|
stride = qemu_dmabuf_get_strides(dmabuf, NULL)[0];
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue