ui/surface: allocate shared memory on !win32

Use qemu_memfd_alloc() to allocate the display surface memory, which
will fallback on tmpfile/mmap() on systems without memfd, and allow to
share the display with other processes.

This is similar to how display memory is allocated on win32 since commit
09b4c198 ("console/win32: allocate shareable display surface").

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Akihiko Odaki <akihiko.odaki@daynix.com>
Message-ID: <20241008125028.1177932-13-marcandre.lureau@redhat.com>
This commit is contained in:
Marc-André Lureau 2024-10-08 16:50:21 +04:00
parent 28a3ca0478
commit ec818df000
2 changed files with 32 additions and 2 deletions

View File

@ -26,6 +26,9 @@ typedef struct DisplaySurface {
#ifdef WIN32 #ifdef WIN32
HANDLE handle; HANDLE handle;
uint32_t handle_offset; uint32_t handle_offset;
#else
int shmfd;
uint32_t shmfd_offset;
#endif #endif
} DisplaySurface; } DisplaySurface;
@ -40,6 +43,9 @@ DisplaySurface *qemu_create_placeholder_surface(int w, int h,
#ifdef WIN32 #ifdef WIN32
void qemu_displaysurface_win32_set_handle(DisplaySurface *surface, void qemu_displaysurface_win32_set_handle(DisplaySurface *surface,
HANDLE h, uint32_t offset); HANDLE h, uint32_t offset);
#else
void qemu_displaysurface_set_shmfd(DisplaySurface *surface,
int shmfd, uint32_t offset);
#endif #endif
DisplaySurface *qemu_create_displaysurface(int width, int height); DisplaySurface *qemu_create_displaysurface(int width, int height);

View File

@ -37,6 +37,7 @@
#include "trace.h" #include "trace.h"
#include "exec/memory.h" #include "exec/memory.h"
#include "qom/object.h" #include "qom/object.h"
#include "qemu/memfd.h"
#include "console-priv.h" #include "console-priv.h"
@ -461,6 +462,15 @@ void qemu_displaysurface_win32_set_handle(DisplaySurface *surface,
surface->handle = h; surface->handle = h;
surface->handle_offset = offset; surface->handle_offset = offset;
} }
#else
void qemu_displaysurface_set_shmfd(DisplaySurface *surface,
int shmfd, uint32_t offset)
{
assert(surface->shmfd == -1);
surface->shmfd = shmfd;
surface->shmfd_offset = offset;
}
#endif #endif
DisplaySurface *qemu_create_displaysurface(int width, int height) DisplaySurface *qemu_create_displaysurface(int width, int height)
@ -469,12 +479,16 @@ DisplaySurface *qemu_create_displaysurface(int width, int height)
void *bits = NULL; void *bits = NULL;
#ifdef WIN32 #ifdef WIN32
HANDLE handle = NULL; HANDLE handle = NULL;
#else
int shmfd = -1;
#endif #endif
trace_displaysurface_create(width, height); trace_displaysurface_create(width, height);
#ifdef WIN32 #ifdef WIN32
bits = qemu_win32_map_alloc(width * height * 4, &handle, &error_abort); bits = qemu_win32_map_alloc(width * height * 4, &handle, &error_abort);
#else
bits = qemu_memfd_alloc("displaysurface", width * height * 4, 0, &shmfd, &error_abort);
#endif #endif
surface = qemu_create_displaysurface_from( surface = qemu_create_displaysurface_from(
@ -486,9 +500,13 @@ DisplaySurface *qemu_create_displaysurface(int width, int height)
#ifdef WIN32 #ifdef WIN32
qemu_displaysurface_win32_set_handle(surface, handle, 0); qemu_displaysurface_win32_set_handle(surface, handle, 0);
pixman_image_set_destroy_function(surface->image, void *data = handle;
qemu_pixman_shared_image_destroy, handle); #else
qemu_displaysurface_set_shmfd(surface, shmfd, 0);
void *data = GINT_TO_POINTER(shmfd);
#endif #endif
pixman_image_set_destroy_function(surface->image, qemu_pixman_shared_image_destroy, data);
return surface; return surface;
} }
@ -499,6 +517,9 @@ DisplaySurface *qemu_create_displaysurface_from(int width, int height,
DisplaySurface *surface = g_new0(DisplaySurface, 1); DisplaySurface *surface = g_new0(DisplaySurface, 1);
trace_displaysurface_create_from(surface, width, height, format); trace_displaysurface_create_from(surface, width, height, format);
#ifndef WIN32
surface->shmfd = -1;
#endif
surface->image = pixman_image_create_bits(format, surface->image = pixman_image_create_bits(format,
width, height, width, height,
(void *)data, linesize); (void *)data, linesize);
@ -512,6 +533,9 @@ DisplaySurface *qemu_create_displaysurface_pixman(pixman_image_t *image)
DisplaySurface *surface = g_new0(DisplaySurface, 1); DisplaySurface *surface = g_new0(DisplaySurface, 1);
trace_displaysurface_create_pixman(surface); trace_displaysurface_create_pixman(surface);
#ifndef WIN32
surface->shmfd = -1;
#endif
surface->image = pixman_image_ref(image); surface->image = pixman_image_ref(image);
return surface; return surface;