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>
This commit is contained in:
parent
439e0164cd
commit
09b4c198b8
@ -263,6 +263,9 @@ EXCEPTION_DISPOSITION
|
||||
win32_close_exception_handler(struct _EXCEPTION_RECORD*, void*,
|
||||
struct _CONTEXT*, void*);
|
||||
|
||||
void *qemu_win32_map_alloc(size_t size, HANDLE *h, Error **errp);
|
||||
void qemu_win32_map_free(void *ptr, HANDLE h, Error **errp);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -143,6 +143,10 @@ typedef struct DisplaySurface {
|
||||
GLenum gltype;
|
||||
GLuint texture;
|
||||
#endif
|
||||
#ifdef WIN32
|
||||
HANDLE handle;
|
||||
uint32_t handle_offset;
|
||||
#endif
|
||||
} DisplaySurface;
|
||||
|
||||
typedef struct QemuUIInfo {
|
||||
@ -329,6 +333,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);
|
||||
#endif
|
||||
PixelFormat qemu_default_pixelformat(int bpp);
|
||||
|
||||
DisplaySurface *qemu_create_displaysurface(int width, int height);
|
||||
|
59
ui/console.c
59
ui/console.c
@ -1513,18 +1513,59 @@ static QemuConsole *new_console(DisplayState *ds, console_type_t console_type,
|
||||
return s;
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
void qemu_displaysurface_win32_set_handle(DisplaySurface *surface,
|
||||
HANDLE h, uint32_t offset)
|
||||
{
|
||||
assert(!surface->handle);
|
||||
|
||||
surface->handle = h;
|
||||
surface->handle_offset = offset;
|
||||
}
|
||||
|
||||
static void
|
||||
win32_pixman_image_destroy(pixman_image_t *image, void *data)
|
||||
{
|
||||
DisplaySurface *surface = data;
|
||||
|
||||
if (!surface->handle) {
|
||||
return;
|
||||
}
|
||||
|
||||
assert(surface->handle_offset == 0);
|
||||
|
||||
qemu_win32_map_free(
|
||||
pixman_image_get_data(surface->image),
|
||||
surface->handle,
|
||||
&error_warn
|
||||
);
|
||||
}
|
||||
#endif
|
||||
|
||||
DisplaySurface *qemu_create_displaysurface(int width, int height)
|
||||
{
|
||||
DisplaySurface *surface = g_new0(DisplaySurface, 1);
|
||||
DisplaySurface *surface;
|
||||
void *bits = NULL;
|
||||
#ifdef WIN32
|
||||
HANDLE handle = NULL;
|
||||
#endif
|
||||
|
||||
trace_displaysurface_create(surface, width, height);
|
||||
surface->format = PIXMAN_x8r8g8b8;
|
||||
surface->image = pixman_image_create_bits(surface->format,
|
||||
width, height,
|
||||
NULL, width * 4);
|
||||
assert(surface->image != NULL);
|
||||
trace_displaysurface_create(width, height);
|
||||
|
||||
#ifdef WIN32
|
||||
bits = qemu_win32_map_alloc(width * height * 4, &handle, &error_abort);
|
||||
#endif
|
||||
|
||||
surface = qemu_create_displaysurface_from(
|
||||
width, height,
|
||||
PIXMAN_x8r8g8b8,
|
||||
width * 4, bits
|
||||
);
|
||||
surface->flags = QEMU_ALLOCATED_FLAG;
|
||||
|
||||
#ifdef WIN32
|
||||
qemu_displaysurface_win32_set_handle(surface, handle, 0);
|
||||
#endif
|
||||
return surface;
|
||||
}
|
||||
|
||||
@ -1540,6 +1581,10 @@ DisplaySurface *qemu_create_displaysurface_from(int width, int height,
|
||||
width, height,
|
||||
(void *)data, linesize);
|
||||
assert(surface->image != NULL);
|
||||
#ifdef WIN32
|
||||
pixman_image_set_destroy_function(surface->image,
|
||||
win32_pixman_image_destroy, surface);
|
||||
#endif
|
||||
|
||||
return surface;
|
||||
}
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include "qemu/osdep.h"
|
||||
#include "ui/console.h"
|
||||
#include "standard-headers/drm/drm_fourcc.h"
|
||||
#include "trace.h"
|
||||
|
||||
PixelFormat qemu_pixelformat_from_pixman(pixman_format_code_t format)
|
||||
{
|
||||
|
@ -9,7 +9,7 @@ console_putchar_unhandled(int ch) "unhandled escape character '%c'"
|
||||
console_txt_new(int w, int h) "%dx%d"
|
||||
console_select(int nr) "%d"
|
||||
console_refresh(int interval) "interval %d ms"
|
||||
displaysurface_create(void *display_surface, int w, int h) "surface=%p, %dx%d"
|
||||
displaysurface_create(int w, int h) "%dx%d"
|
||||
displaysurface_create_from(void *display_surface, int w, int h, uint32_t format) "surface=%p, %dx%d, format 0x%x"
|
||||
displaysurface_create_pixman(void *display_surface) "surface=%p"
|
||||
displaysurface_free(void *display_surface) "surface=%p"
|
||||
|
@ -835,3 +835,36 @@ int qemu_msync(void *addr, size_t length, int fd)
|
||||
*/
|
||||
return qemu_fdatasync(fd);
|
||||
}
|
||||
|
||||
void *qemu_win32_map_alloc(size_t size, HANDLE *h, Error **errp)
|
||||
{
|
||||
void *bits;
|
||||
|
||||
trace_win32_map_alloc(size);
|
||||
|
||||
*h = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0,
|
||||
size, NULL);
|
||||
if (*h == NULL) {
|
||||
error_setg_win32(errp, GetLastError(), "Failed to CreateFileMapping");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bits = MapViewOfFile(*h, FILE_MAP_ALL_ACCESS, 0, 0, size);
|
||||
if (bits == NULL) {
|
||||
error_setg_win32(errp, GetLastError(), "Failed to MapViewOfFile");
|
||||
CloseHandle(*h);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return bits;
|
||||
}
|
||||
|
||||
void qemu_win32_map_free(void *ptr, HANDLE h, Error **errp)
|
||||
{
|
||||
trace_win32_map_free(ptr, h);
|
||||
|
||||
if (UnmapViewOfFile(ptr) == 0) {
|
||||
error_setg_win32(errp, GetLastError(), "Failed to UnmapViewOfFile");
|
||||
}
|
||||
CloseHandle(h);
|
||||
}
|
||||
|
@ -52,6 +52,10 @@ qemu_anon_ram_alloc(size_t size, void *ptr) "size %zu ptr %p"
|
||||
qemu_vfree(void *ptr) "ptr %p"
|
||||
qemu_anon_ram_free(void *ptr, size_t size) "ptr %p size %zu"
|
||||
|
||||
# oslib-win32.c
|
||||
win32_map_alloc(size_t size) "size:%zd"
|
||||
win32_map_free(void *ptr, void *h) "ptr:%p handle:%p"
|
||||
|
||||
# hbitmap.c
|
||||
hbitmap_iter_skip_words(const void *hb, void *hbi, uint64_t pos, unsigned long cur) "hb %p hbi %p pos %"PRId64" cur 0x%lx"
|
||||
hbitmap_reset(void *hb, uint64_t start, uint64_t count, uint64_t sbit, uint64_t ebit) "hb %p items %"PRIu64",%"PRIu64" bits %"PRIu64"..%"PRIu64
|
||||
|
Loading…
Reference in New Issue
Block a user