From: Marc-André Lureau <marcandre.lureau@redhat.com>
Similar to what was done in commit 9462ff46 ("virtio-gpu/win32: allocate
shareable 2d resources/images") for win32, allocate resource memory with
memfd, so the associated display surface memory can be shared with a
different process.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
include/hw/virtio/virtio-gpu.h | 4 ++-
hw/display/virtio-gpu.c | 47 ++++++++++++++++++++++------------
2 files changed, 34 insertions(+), 17 deletions(-)
diff --git a/include/hw/virtio/virtio-gpu.h b/include/hw/virtio/virtio-gpu.h
index 7a59379f5a..a0d715198b 100644
--- a/include/hw/virtio/virtio-gpu.h
+++ b/include/hw/virtio/virtio-gpu.h
@@ -51,7 +51,9 @@ struct virtio_gpu_simple_resource {
unsigned int iov_cnt;
uint32_t scanout_bitmask;
pixman_image_t *image;
-#ifdef WIN32
+#ifndef WIN32
+ int shmfd;
+#else
HANDLE handle;
#endif
uint64_t hostmem;
diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
index 77f6e76f23..295d0afca3 100644
--- a/hw/display/virtio-gpu.c
+++ b/hw/display/virtio-gpu.c
@@ -28,6 +28,7 @@
#include "hw/virtio/virtio-bus.h"
#include "hw/qdev-properties.h"
#include "qemu/log.h"
+#include "qemu/memfd.h"
#include "qemu/module.h"
#include "qapi/error.h"
#include "qemu/error-report.h"
@@ -238,6 +239,20 @@ static uint32_t calc_image_hostmem(pixman_format_code_t pformat,
return height * stride;
}
+static void
+resource_set_image_destroy(struct virtio_gpu_simple_resource *res)
+{
+ if (!res) {
+ return;
+ }
+#ifndef WIN32
+ void *data = GINT_TO_POINTER(res->shmfd);
+#else
+ void *data = res->handle;
+#endif
+ pixman_image_set_destroy_function(res->image, qemu_pixman_shared_image_destroy, data);
+}
+
static void virtio_gpu_resource_create_2d(VirtIOGPU *g,
struct virtio_gpu_ctrl_command *cmd)
{
@@ -285,27 +300,23 @@ static void virtio_gpu_resource_create_2d(VirtIOGPU *g,
res->hostmem = calc_image_hostmem(pformat, c2d.width, c2d.height);
if (res->hostmem + g->hostmem < g->conf_max_hostmem) {
void *bits = NULL;
-#ifdef WIN32
+#ifndef WIN32
+ bits = qemu_memfd_alloc("virtio-gpu-res", res->hostmem, 0, &res->shmfd, &error_warn);
+#else
bits = qemu_win32_map_alloc(res->hostmem, &res->handle, &error_warn);
+#endif
if (!bits) {
goto end;
}
-#endif
res->image = pixman_image_create_bits(
pformat,
c2d.width,
c2d.height,
bits, c2d.height ? res->hostmem / c2d.height : 0);
-#ifdef WIN32
- if (res->image) {
- pixman_image_set_destroy_function(res->image, qemu_pixman_shared_image_destroy, res->handle);
- }
-#endif
+ resource_set_image_destroy(res);
}
-#ifdef WIN32
end:
-#endif
if (!res->image) {
qemu_log_mask(LOG_GUEST_ERROR,
"%s: resource creation failed %d %d %d\n",
@@ -676,7 +687,9 @@ static bool virtio_gpu_do_set_scanout(VirtIOGPU *g,
/* realloc the surface ptr */
scanout->ds = qemu_create_displaysurface_pixman(rect);
-#ifdef WIN32
+#ifndef WIN32
+ qemu_displaysurface_set_shmfd(scanout->ds, res->shmfd, fb->offset);
+#else
qemu_displaysurface_win32_set_handle(scanout->ds, res->handle, fb->offset);
#endif
@@ -1301,13 +1314,15 @@ static int virtio_gpu_load(QEMUFile *f, void *opaque, size_t size,
}
res->hostmem = calc_image_hostmem(pformat, res->width, res->height);
-#ifdef WIN32
+#ifndef WIN32
+ bits = qemu_memfd_alloc("virtio-gpu-res", res->hostmem, 0, &res->shmfd, &error_warn);
+#else
bits = qemu_win32_map_alloc(res->hostmem, &res->handle, &error_warn);
+#endif
if (!bits) {
g_free(res);
return -EINVAL;
}
-#endif
res->image = pixman_image_create_bits(
pformat,
res->width, res->height,
@@ -1316,9 +1331,7 @@ static int virtio_gpu_load(QEMUFile *f, void *opaque, size_t size,
g_free(res);
return -EINVAL;
}
-#ifdef WIN32
- pixman_image_set_destroy_function(res->image, qemu_pixman_shared_image_destroy, res->handle);
-#endif
+ resource_set_image_destroy(res);
res->addrs = g_new(uint64_t, res->iov_cnt);
res->iov = g_new(struct iovec, res->iov_cnt);
@@ -1451,7 +1464,9 @@ static int virtio_gpu_post_load(void *opaque, int version_id)
return -EINVAL;
}
scanout->ds = qemu_create_displaysurface_pixman(res->image);
-#ifdef WIN32
+#ifndef WIN32
+ qemu_displaysurface_set_shmfd(scanout->ds, res->shmfd, 0);
+#else
qemu_displaysurface_win32_set_handle(scanout->ds, res->handle, 0);
#endif
dpy_gfx_replace_surface(scanout->con, scanout->ds);
--
2.45.2.827.g557ae147e6