Skip to content

Commit 09b4c19

Browse files
committed
console/win32: allocate shareable display surface
Introduce qemu_win32_map_alloc() and qemu_win32_map_free() to allocate shared memory mapping. The handle can be used to share the mapping with another process. Teach qemu_create_displaysurface() to allocate shared memory. Following patches will introduce other places for shared memory allocation. Other patches for -display dbus will share the memory when possible with the client, to avoid expensive memory copy between the processes. Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com> Message-Id: <20230606115658.677673-10-marcandre.lureau@redhat.com>
1 parent 439e016 commit 09b4c19

File tree

7 files changed

+102
-8
lines changed

7 files changed

+102
-8
lines changed

include/sysemu/os-win32.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,9 @@ EXCEPTION_DISPOSITION
263263
win32_close_exception_handler(struct _EXCEPTION_RECORD*, void*,
264264
struct _CONTEXT*, void*);
265265

266+
void *qemu_win32_map_alloc(size_t size, HANDLE *h, Error **errp);
267+
void qemu_win32_map_free(void *ptr, HANDLE h, Error **errp);
268+
266269
#ifdef __cplusplus
267270
}
268271
#endif

include/ui/console.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,10 @@ typedef struct DisplaySurface {
143143
GLenum gltype;
144144
GLuint texture;
145145
#endif
146+
#ifdef WIN32
147+
HANDLE handle;
148+
uint32_t handle_offset;
149+
#endif
146150
} DisplaySurface;
147151

148152
typedef struct QemuUIInfo {
@@ -329,6 +333,10 @@ DisplaySurface *qemu_create_displaysurface_from(int width, int height,
329333
DisplaySurface *qemu_create_displaysurface_pixman(pixman_image_t *image);
330334
DisplaySurface *qemu_create_placeholder_surface(int w, int h,
331335
const char *msg);
336+
#ifdef WIN32
337+
void qemu_displaysurface_win32_set_handle(DisplaySurface *surface,
338+
HANDLE h, uint32_t offset);
339+
#endif
332340
PixelFormat qemu_default_pixelformat(int bpp);
333341

334342
DisplaySurface *qemu_create_displaysurface(int width, int height);

ui/console.c

Lines changed: 52 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1513,18 +1513,59 @@ static QemuConsole *new_console(DisplayState *ds, console_type_t console_type,
15131513
return s;
15141514
}
15151515

1516+
#ifdef WIN32
1517+
void qemu_displaysurface_win32_set_handle(DisplaySurface *surface,
1518+
HANDLE h, uint32_t offset)
1519+
{
1520+
assert(!surface->handle);
1521+
1522+
surface->handle = h;
1523+
surface->handle_offset = offset;
1524+
}
1525+
1526+
static void
1527+
win32_pixman_image_destroy(pixman_image_t *image, void *data)
1528+
{
1529+
DisplaySurface *surface = data;
1530+
1531+
if (!surface->handle) {
1532+
return;
1533+
}
1534+
1535+
assert(surface->handle_offset == 0);
1536+
1537+
qemu_win32_map_free(
1538+
pixman_image_get_data(surface->image),
1539+
surface->handle,
1540+
&error_warn
1541+
);
1542+
}
1543+
#endif
1544+
15161545
DisplaySurface *qemu_create_displaysurface(int width, int height)
15171546
{
1518-
DisplaySurface *surface = g_new0(DisplaySurface, 1);
1547+
DisplaySurface *surface;
1548+
void *bits = NULL;
1549+
#ifdef WIN32
1550+
HANDLE handle = NULL;
1551+
#endif
15191552

1520-
trace_displaysurface_create(surface, width, height);
1521-
surface->format = PIXMAN_x8r8g8b8;
1522-
surface->image = pixman_image_create_bits(surface->format,
1523-
width, height,
1524-
NULL, width * 4);
1525-
assert(surface->image != NULL);
1553+
trace_displaysurface_create(width, height);
1554+
1555+
#ifdef WIN32
1556+
bits = qemu_win32_map_alloc(width * height * 4, &handle, &error_abort);
1557+
#endif
1558+
1559+
surface = qemu_create_displaysurface_from(
1560+
width, height,
1561+
PIXMAN_x8r8g8b8,
1562+
width * 4, bits
1563+
);
15261564
surface->flags = QEMU_ALLOCATED_FLAG;
15271565

1566+
#ifdef WIN32
1567+
qemu_displaysurface_win32_set_handle(surface, handle, 0);
1568+
#endif
15281569
return surface;
15291570
}
15301571

@@ -1540,6 +1581,10 @@ DisplaySurface *qemu_create_displaysurface_from(int width, int height,
15401581
width, height,
15411582
(void *)data, linesize);
15421583
assert(surface->image != NULL);
1584+
#ifdef WIN32
1585+
pixman_image_set_destroy_function(surface->image,
1586+
win32_pixman_image_destroy, surface);
1587+
#endif
15431588

15441589
return surface;
15451590
}

ui/qemu-pixman.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include "qemu/osdep.h"
77
#include "ui/console.h"
88
#include "standard-headers/drm/drm_fourcc.h"
9+
#include "trace.h"
910

1011
PixelFormat qemu_pixelformat_from_pixman(pixman_format_code_t format)
1112
{

ui/trace-events

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ console_putchar_unhandled(int ch) "unhandled escape character '%c'"
99
console_txt_new(int w, int h) "%dx%d"
1010
console_select(int nr) "%d"
1111
console_refresh(int interval) "interval %d ms"
12-
displaysurface_create(void *display_surface, int w, int h) "surface=%p, %dx%d"
12+
displaysurface_create(int w, int h) "%dx%d"
1313
displaysurface_create_from(void *display_surface, int w, int h, uint32_t format) "surface=%p, %dx%d, format 0x%x"
1414
displaysurface_create_pixman(void *display_surface) "surface=%p"
1515
displaysurface_free(void *display_surface) "surface=%p"

util/oslib-win32.c

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -835,3 +835,36 @@ int qemu_msync(void *addr, size_t length, int fd)
835835
*/
836836
return qemu_fdatasync(fd);
837837
}
838+
839+
void *qemu_win32_map_alloc(size_t size, HANDLE *h, Error **errp)
840+
{
841+
void *bits;
842+
843+
trace_win32_map_alloc(size);
844+
845+
*h = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0,
846+
size, NULL);
847+
if (*h == NULL) {
848+
error_setg_win32(errp, GetLastError(), "Failed to CreateFileMapping");
849+
return NULL;
850+
}
851+
852+
bits = MapViewOfFile(*h, FILE_MAP_ALL_ACCESS, 0, 0, size);
853+
if (bits == NULL) {
854+
error_setg_win32(errp, GetLastError(), "Failed to MapViewOfFile");
855+
CloseHandle(*h);
856+
return NULL;
857+
}
858+
859+
return bits;
860+
}
861+
862+
void qemu_win32_map_free(void *ptr, HANDLE h, Error **errp)
863+
{
864+
trace_win32_map_free(ptr, h);
865+
866+
if (UnmapViewOfFile(ptr) == 0) {
867+
error_setg_win32(errp, GetLastError(), "Failed to UnmapViewOfFile");
868+
}
869+
CloseHandle(h);
870+
}

util/trace-events

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,10 @@ qemu_anon_ram_alloc(size_t size, void *ptr) "size %zu ptr %p"
5252
qemu_vfree(void *ptr) "ptr %p"
5353
qemu_anon_ram_free(void *ptr, size_t size) "ptr %p size %zu"
5454

55+
# oslib-win32.c
56+
win32_map_alloc(size_t size) "size:%zd"
57+
win32_map_free(void *ptr, void *h) "ptr:%p handle:%p"
58+
5559
# hbitmap.c
5660
hbitmap_iter_skip_words(const void *hb, void *hbi, uint64_t pos, unsigned long cur) "hb %p hbi %p pos %"PRId64" cur 0x%lx"
5761
hbitmap_reset(void *hb, uint64_t start, uint64_t count, uint64_t sbit, uint64_t ebit) "hb %p items %"PRIu64",%"PRIu64" bits %"PRIu64"..%"PRIu64

0 commit comments

Comments
 (0)