ui: refactor using a common qemu_pixman_shareable
Use a common shareable type for win32 & unix, and helper functions. This simplify the code as it avoids a lot of #ifdef'ery. Note: if it helps review, commits could be reordered to introduce the common type before introducing shareable memory for unix. Suggested-by: Akihiko Odaki <akihiko.odaki@daynix.com> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com> Reviewed-by: Akihiko Odaki <akihiko.odaki@daynix.com> Message-ID: <20241008125028.1177932-19-marcandre.lureau@redhat.com>
This commit is contained in:
parent
5f899c34af
commit
1ff788db97
@ -239,20 +239,6 @@ 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;
|
||||
}
|
||||
#ifdef WIN32
|
||||
void *data = res->handle;
|
||||
#else
|
||||
void *data = GINT_TO_POINTER(res->shmfd);
|
||||
#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)
|
||||
{
|
||||
@ -299,21 +285,17 @@ 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
|
||||
bits = qemu_win32_map_alloc(res->hostmem, &res->handle, &error_warn);
|
||||
#else
|
||||
bits = qemu_memfd_alloc("virtio-gpu-res", res->hostmem, 0, &res->shmfd, &error_warn);
|
||||
#endif
|
||||
if (!bits) {
|
||||
if (!qemu_pixman_image_new_shareable(
|
||||
&res->image,
|
||||
&res->share_handle,
|
||||
"virtio-gpu res",
|
||||
pformat,
|
||||
c2d.width,
|
||||
c2d.height,
|
||||
c2d.height ? res->hostmem / c2d.height : 0,
|
||||
&error_warn)) {
|
||||
goto end;
|
||||
}
|
||||
res->image = pixman_image_create_bits(
|
||||
pformat,
|
||||
c2d.width,
|
||||
c2d.height,
|
||||
bits, c2d.height ? res->hostmem / c2d.height : 0);
|
||||
resource_set_image_destroy(res);
|
||||
}
|
||||
|
||||
end:
|
||||
@ -687,11 +669,7 @@ static bool virtio_gpu_do_set_scanout(VirtIOGPU *g,
|
||||
|
||||
/* realloc the surface ptr */
|
||||
scanout->ds = qemu_create_displaysurface_pixman(rect);
|
||||
#ifdef WIN32
|
||||
qemu_displaysurface_win32_set_handle(scanout->ds, res->handle, fb->offset);
|
||||
#else
|
||||
qemu_displaysurface_set_shmfd(scanout->ds, res->shmfd, fb->offset);
|
||||
#endif
|
||||
qemu_displaysurface_set_share_handle(scanout->ds, res->share_handle, fb->offset);
|
||||
|
||||
pixman_image_unref(rect);
|
||||
dpy_gfx_replace_surface(g->parent_obj.scanout[scanout_id].con,
|
||||
@ -1287,7 +1265,6 @@ static int virtio_gpu_load(QEMUFile *f, void *opaque, size_t size,
|
||||
VirtIOGPU *g = opaque;
|
||||
struct virtio_gpu_simple_resource *res;
|
||||
uint32_t resource_id, pformat;
|
||||
void *bits = NULL;
|
||||
int i;
|
||||
|
||||
g->hostmem = 0;
|
||||
@ -1314,24 +1291,17 @@ static int virtio_gpu_load(QEMUFile *f, void *opaque, size_t size,
|
||||
}
|
||||
|
||||
res->hostmem = calc_image_hostmem(pformat, res->width, res->height);
|
||||
#ifdef WIN32
|
||||
bits = qemu_win32_map_alloc(res->hostmem, &res->handle, &error_warn);
|
||||
#else
|
||||
bits = qemu_memfd_alloc("virtio-gpu-res", res->hostmem, 0, &res->shmfd, &error_warn);
|
||||
#endif
|
||||
if (!bits) {
|
||||
if (!qemu_pixman_image_new_shareable(&res->image,
|
||||
&res->share_handle,
|
||||
"virtio-gpu res",
|
||||
pformat,
|
||||
res->width,
|
||||
res->height,
|
||||
res->height ? res->hostmem / res->height : 0,
|
||||
&error_warn)) {
|
||||
g_free(res);
|
||||
return -EINVAL;
|
||||
}
|
||||
res->image = pixman_image_create_bits(
|
||||
pformat,
|
||||
res->width, res->height,
|
||||
bits, res->height ? res->hostmem / res->height : 0);
|
||||
if (!res->image) {
|
||||
g_free(res);
|
||||
return -EINVAL;
|
||||
}
|
||||
resource_set_image_destroy(res);
|
||||
|
||||
res->addrs = g_new(uint64_t, res->iov_cnt);
|
||||
res->iov = g_new(struct iovec, res->iov_cnt);
|
||||
@ -1464,11 +1434,7 @@ static int virtio_gpu_post_load(void *opaque, int version_id)
|
||||
return -EINVAL;
|
||||
}
|
||||
scanout->ds = qemu_create_displaysurface_pixman(res->image);
|
||||
#ifdef WIN32
|
||||
qemu_displaysurface_win32_set_handle(scanout->ds, res->handle, 0);
|
||||
#else
|
||||
qemu_displaysurface_set_shmfd(scanout->ds, res->shmfd, 0);
|
||||
#endif
|
||||
qemu_displaysurface_set_share_handle(scanout->ds, res->share_handle, 0);
|
||||
dpy_gfx_replace_surface(scanout->con, scanout->ds);
|
||||
}
|
||||
|
||||
|
@ -51,11 +51,7 @@ struct virtio_gpu_simple_resource {
|
||||
unsigned int iov_cnt;
|
||||
uint32_t scanout_bitmask;
|
||||
pixman_image_t *image;
|
||||
#ifdef WIN32
|
||||
HANDLE handle;
|
||||
#else
|
||||
int shmfd;
|
||||
#endif
|
||||
qemu_pixman_shareable share_handle;
|
||||
uint64_t hostmem;
|
||||
|
||||
uint64_t blob_size;
|
||||
|
@ -12,6 +12,8 @@
|
||||
#include "pixman-minimal.h"
|
||||
#endif
|
||||
|
||||
#include "qapi/error.h"
|
||||
|
||||
/*
|
||||
* pixman image formats are defined to be native endian,
|
||||
* that means host byte order on qemu. So we go define
|
||||
@ -97,7 +99,27 @@ void qemu_pixman_glyph_render(pixman_image_t *glyph,
|
||||
|
||||
void qemu_pixman_image_unref(pixman_image_t *image);
|
||||
|
||||
void qemu_pixman_shared_image_destroy(pixman_image_t *image, void *data);
|
||||
#ifdef WIN32
|
||||
typedef HANDLE qemu_pixman_shareable;
|
||||
#define SHAREABLE_NONE (NULL)
|
||||
#define SHAREABLE_TO_PTR(handle) (handle)
|
||||
#define PTR_TO_SHAREABLE(ptr) (ptr)
|
||||
#else
|
||||
typedef int qemu_pixman_shareable;
|
||||
#define SHAREABLE_NONE (-1)
|
||||
#define SHAREABLE_TO_PTR(handle) GINT_TO_POINTER(handle)
|
||||
#define PTR_TO_SHAREABLE(ptr) GPOINTER_TO_INT(ptr)
|
||||
#endif
|
||||
|
||||
bool qemu_pixman_image_new_shareable(
|
||||
pixman_image_t **image,
|
||||
qemu_pixman_shareable *handle,
|
||||
const char *name,
|
||||
pixman_format_code_t format,
|
||||
int width,
|
||||
int height,
|
||||
int rowstride_bytes,
|
||||
Error **errp);
|
||||
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(pixman_image_t, qemu_pixman_image_unref)
|
||||
|
||||
|
@ -23,13 +23,8 @@ typedef struct DisplaySurface {
|
||||
GLenum gltype;
|
||||
GLuint texture;
|
||||
#endif
|
||||
#ifdef WIN32
|
||||
HANDLE handle;
|
||||
uint32_t handle_offset;
|
||||
#else
|
||||
int shmfd;
|
||||
uint32_t shmfd_offset;
|
||||
#endif
|
||||
qemu_pixman_shareable share_handle;
|
||||
uint32_t share_handle_offset;
|
||||
} DisplaySurface;
|
||||
|
||||
PixelFormat qemu_default_pixelformat(int bpp);
|
||||
@ -40,13 +35,10 @@ DisplaySurface *qemu_create_displaysurface_from(int width, int height,
|
||||
DisplaySurface *qemu_create_displaysurface_pixman(pixman_image_t *image);
|
||||
DisplaySurface *qemu_create_placeholder_surface(int w, int h,
|
||||
const char *msg);
|
||||
#ifdef WIN32
|
||||
void qemu_displaysurface_win32_set_handle(DisplaySurface *surface,
|
||||
HANDLE h, uint32_t offset);
|
||||
#else
|
||||
void qemu_displaysurface_set_shmfd(DisplaySurface *surface,
|
||||
int shmfd, uint32_t offset);
|
||||
#endif
|
||||
|
||||
void qemu_displaysurface_set_share_handle(DisplaySurface *surface,
|
||||
qemu_pixman_shareable handle,
|
||||
uint32_t offset);
|
||||
|
||||
DisplaySurface *qemu_create_displaysurface(int width, int height);
|
||||
void qemu_free_displaysurface(DisplaySurface *surface);
|
||||
|
80
ui/console.c
80
ui/console.c
@ -453,61 +453,26 @@ qemu_graphic_console_init(Object *obj)
|
||||
{
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
void qemu_displaysurface_win32_set_handle(DisplaySurface *surface,
|
||||
HANDLE h, uint32_t offset)
|
||||
void qemu_displaysurface_set_share_handle(DisplaySurface *surface,
|
||||
qemu_pixman_shareable handle,
|
||||
uint32_t offset)
|
||||
{
|
||||
assert(!surface->handle);
|
||||
assert(surface->share_handle == SHAREABLE_NONE);
|
||||
|
||||
surface->handle = h;
|
||||
surface->handle_offset = offset;
|
||||
}
|
||||
#else
|
||||
void qemu_displaysurface_set_shmfd(DisplaySurface *surface,
|
||||
int shmfd, uint32_t offset)
|
||||
{
|
||||
assert(surface->shmfd == -1);
|
||||
surface->share_handle = handle;
|
||||
surface->share_handle_offset = offset;
|
||||
|
||||
surface->shmfd = shmfd;
|
||||
surface->shmfd_offset = offset;
|
||||
}
|
||||
#endif
|
||||
|
||||
DisplaySurface *qemu_create_displaysurface(int width, int height)
|
||||
{
|
||||
DisplaySurface *surface;
|
||||
void *bits = NULL;
|
||||
#ifdef WIN32
|
||||
HANDLE handle = NULL;
|
||||
#else
|
||||
int shmfd = -1;
|
||||
#endif
|
||||
|
||||
trace_displaysurface_create(width, height);
|
||||
|
||||
#ifdef WIN32
|
||||
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
|
||||
|
||||
surface = qemu_create_displaysurface_from(
|
||||
return qemu_create_displaysurface_from(
|
||||
width, height,
|
||||
PIXMAN_x8r8g8b8,
|
||||
width * 4, bits
|
||||
width * 4, NULL
|
||||
);
|
||||
surface->flags = QEMU_ALLOCATED_FLAG;
|
||||
|
||||
#ifdef WIN32
|
||||
qemu_displaysurface_win32_set_handle(surface, handle, 0);
|
||||
void *data = handle;
|
||||
#else
|
||||
qemu_displaysurface_set_shmfd(surface, shmfd, 0);
|
||||
void *data = GINT_TO_POINTER(shmfd);
|
||||
#endif
|
||||
pixman_image_set_destroy_function(surface->image, qemu_pixman_shared_image_destroy, data);
|
||||
|
||||
return surface;
|
||||
}
|
||||
|
||||
DisplaySurface *qemu_create_displaysurface_from(int width, int height,
|
||||
@ -517,14 +482,25 @@ DisplaySurface *qemu_create_displaysurface_from(int width, int height,
|
||||
DisplaySurface *surface = g_new0(DisplaySurface, 1);
|
||||
|
||||
trace_displaysurface_create_from(surface, width, height, format);
|
||||
#ifndef WIN32
|
||||
surface->shmfd = -1;
|
||||
#endif
|
||||
surface->image = pixman_image_create_bits(format,
|
||||
width, height,
|
||||
(void *)data, linesize);
|
||||
assert(surface->image != NULL);
|
||||
surface->share_handle = SHAREABLE_NONE;
|
||||
|
||||
if (data) {
|
||||
surface->image = pixman_image_create_bits(format,
|
||||
width, height,
|
||||
(void *)data, linesize);
|
||||
} else {
|
||||
qemu_pixman_image_new_shareable(&surface->image,
|
||||
&surface->share_handle,
|
||||
"displaysurface",
|
||||
format,
|
||||
width,
|
||||
height,
|
||||
linesize,
|
||||
&error_abort);
|
||||
surface->flags = QEMU_ALLOCATED_FLAG;
|
||||
}
|
||||
|
||||
assert(surface->image != NULL);
|
||||
return surface;
|
||||
}
|
||||
|
||||
@ -533,9 +509,7 @@ DisplaySurface *qemu_create_displaysurface_pixman(pixman_image_t *image)
|
||||
DisplaySurface *surface = g_new0(DisplaySurface, 1);
|
||||
|
||||
trace_displaysurface_create_pixman(surface);
|
||||
#ifndef WIN32
|
||||
surface->shmfd = -1;
|
||||
#endif
|
||||
surface->share_handle = SHAREABLE_NONE;
|
||||
surface->image = pixman_image_ref(image);
|
||||
|
||||
return surface;
|
||||
|
@ -336,13 +336,13 @@ static bool dbus_scanout_map(DBusDisplayListener *ddl)
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!ddl->can_share_map || !ddl->ds->handle) {
|
||||
if (!ddl->can_share_map || !ddl->ds->share_handle) {
|
||||
return false;
|
||||
}
|
||||
|
||||
success = DuplicateHandle(
|
||||
GetCurrentProcess(),
|
||||
ddl->ds->handle,
|
||||
ddl->ds->share_handle,
|
||||
ddl->peer_process,
|
||||
&target_handle,
|
||||
FILE_MAP_READ | SECTION_QUERY,
|
||||
@ -359,7 +359,7 @@ static bool dbus_scanout_map(DBusDisplayListener *ddl)
|
||||
if (!qemu_dbus_display1_listener_win32_map_call_scanout_map_sync(
|
||||
ddl->map_proxy,
|
||||
GPOINTER_TO_UINT(target_handle),
|
||||
ddl->ds->handle_offset,
|
||||
ddl->ds->share_handle_offset,
|
||||
surface_width(ddl->ds),
|
||||
surface_height(ddl->ds),
|
||||
surface_stride(ddl->ds),
|
||||
@ -453,13 +453,13 @@ static bool dbus_scanout_map(DBusDisplayListener *ddl)
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!ddl->can_share_map || ddl->ds->shmfd == -1) {
|
||||
if (!ddl->can_share_map || ddl->ds->share_handle == SHAREABLE_NONE) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ddl_discard_display_messages(ddl);
|
||||
fd_list = g_unix_fd_list_new();
|
||||
if (g_unix_fd_list_append(fd_list, ddl->ds->shmfd, &err) != 0) {
|
||||
if (g_unix_fd_list_append(fd_list, ddl->ds->share_handle, &err) != 0) {
|
||||
g_debug("Failed to setup scanout map fdlist: %s", err->message);
|
||||
ddl->can_share_map = false;
|
||||
return false;
|
||||
@ -468,7 +468,7 @@ static bool dbus_scanout_map(DBusDisplayListener *ddl)
|
||||
if (!qemu_dbus_display1_listener_unix_map_call_scanout_map_sync(
|
||||
ddl->map_proxy,
|
||||
g_variant_new_handle(0),
|
||||
ddl->ds->shmfd_offset,
|
||||
ddl->ds->share_handle_offset,
|
||||
surface_width(ddl->ds),
|
||||
surface_height(ddl->ds),
|
||||
surface_stride(ddl->ds),
|
||||
|
@ -270,19 +270,71 @@ void qemu_pixman_glyph_render(pixman_image_t *glyph,
|
||||
}
|
||||
#endif /* CONFIG_PIXMAN */
|
||||
|
||||
void
|
||||
qemu_pixman_shared_image_destroy(pixman_image_t *image, void *data)
|
||||
static void *
|
||||
qemu_pixman_shareable_alloc(const char *name, size_t size,
|
||||
qemu_pixman_shareable *handle,
|
||||
Error **errp)
|
||||
{
|
||||
void *ptr = pixman_image_get_data(image);
|
||||
|
||||
#ifdef WIN32
|
||||
HANDLE handle = data;
|
||||
|
||||
qemu_win32_map_free(ptr, handle, &error_warn);
|
||||
return qemu_win32_map_alloc(size, handle, errp);
|
||||
#else
|
||||
int shmfd = GPOINTER_TO_INT(data);
|
||||
size_t size = pixman_image_get_height(image) * pixman_image_get_stride(image);
|
||||
|
||||
qemu_memfd_free(ptr, size, shmfd);
|
||||
return qemu_memfd_alloc(name, size, 0, handle, errp);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
qemu_pixman_shareable_free(qemu_pixman_shareable handle,
|
||||
void *ptr, size_t size)
|
||||
{
|
||||
#ifdef WIN32
|
||||
qemu_win32_map_free(ptr, handle, &error_warn);
|
||||
#else
|
||||
qemu_memfd_free(ptr, size, handle);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
qemu_pixman_shared_image_destroy(pixman_image_t *image, void *data)
|
||||
{
|
||||
qemu_pixman_shareable handle = PTR_TO_SHAREABLE(data);
|
||||
void *ptr = pixman_image_get_data(image);
|
||||
size_t size = pixman_image_get_height(image) * pixman_image_get_stride(image);
|
||||
|
||||
qemu_pixman_shareable_free(handle, ptr, size);
|
||||
}
|
||||
|
||||
bool
|
||||
qemu_pixman_image_new_shareable(pixman_image_t **image,
|
||||
qemu_pixman_shareable *handle,
|
||||
const char *name,
|
||||
pixman_format_code_t format,
|
||||
int width,
|
||||
int height,
|
||||
int rowstride_bytes,
|
||||
Error **errp)
|
||||
{
|
||||
ERRP_GUARD();
|
||||
size_t size = height * rowstride_bytes;
|
||||
void *bits = NULL;
|
||||
|
||||
g_return_val_if_fail(image != NULL, false);
|
||||
g_return_val_if_fail(handle != NULL, false);
|
||||
|
||||
bits = qemu_pixman_shareable_alloc(name, size, handle, errp);
|
||||
if (!bits) {
|
||||
return false;
|
||||
}
|
||||
|
||||
*image = pixman_image_create_bits(format, width, height, bits, rowstride_bytes);
|
||||
if (!*image) {
|
||||
error_setg(errp, "Failed to allocate image");
|
||||
qemu_pixman_shareable_free(*handle, bits, size);
|
||||
return false;
|
||||
}
|
||||
|
||||
pixman_image_set_destroy_function(*image,
|
||||
qemu_pixman_shared_image_destroy,
|
||||
SHAREABLE_TO_PTR(*handle));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user