[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH 09/21] console/win32: allocate shareable display surface
From: |
marcandre . lureau |
Subject: |
[PATCH 09/21] console/win32: allocate shareable display surface |
Date: |
Tue, 6 Jun 2023 15:56:46 +0400 |
From: Marc-André Lureau <marcandre.lureau@redhat.com>
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>
---
include/sysemu/os-win32.h | 3 ++
include/ui/console.h | 8 ++++++
ui/console.c | 59 ++++++++++++++++++++++++++++++++++-----
ui/qemu-pixman.c | 1 +
util/oslib-win32.c | 33 ++++++++++++++++++++++
ui/trace-events | 2 +-
util/trace-events | 4 +++
7 files changed, 102 insertions(+), 8 deletions(-)
diff --git a/include/sysemu/os-win32.h b/include/sysemu/os-win32.h
index 65f6c9ea57..91aa0d7ec0 100644
--- a/include/sysemu/os-win32.h
+++ b/include/sysemu/os-win32.h
@@ -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
diff --git a/include/ui/console.h b/include/ui/console.h
index ae5ec466c1..0fd2692110 100644
--- a/include/ui/console.h
+++ b/include/ui/console.h
@@ -128,6 +128,10 @@ typedef struct DisplaySurface {
GLenum gltype;
GLuint texture;
#endif
+#ifdef WIN32
+ HANDLE handle;
+ uint32_t handle_offset;
+#endif
} DisplaySurface;
typedef struct QemuUIInfo {
@@ -314,6 +318,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);
diff --git a/ui/console.c b/ui/console.c
index e173731e20..2b53c64ef0 100644
--- a/ui/console.c
+++ b/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;
}
diff --git a/ui/qemu-pixman.c b/ui/qemu-pixman.c
index 3ab7e2e958..e4f024a85e 100644
--- a/ui/qemu-pixman.c
+++ b/ui/qemu-pixman.c
@@ -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)
{
diff --git a/util/oslib-win32.c b/util/oslib-win32.c
index fafbab80b4..429542face 100644
--- a/util/oslib-win32.c
+++ b/util/oslib-win32.c
@@ -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);
+}
diff --git a/ui/trace-events b/ui/trace-events
index 6747361745..712c4b2273 100644
--- a/ui/trace-events
+++ b/ui/trace-events
@@ -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"
diff --git a/util/trace-events b/util/trace-events
index 3f7e766683..49a4962e18 100644
--- a/util/trace-events
+++ b/util/trace-events
@@ -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
--
2.40.1
- [PATCH 12/21] ui: add egl-headless support on win32, (continued)
- [PATCH 12/21] ui: add egl-headless support on win32, marcandre . lureau, 2023/06/06
- [PATCH 13/21] ui/egl: default to GLES on windows, marcandre . lureau, 2023/06/06
- [PATCH 14/21] ui: add egl_fb_read_rect(), marcandre . lureau, 2023/06/06
- [PATCH 15/21] ui/dbus: add GL support on win32, marcandre . lureau, 2023/06/06
- [PATCH 16/21] ui/dbus: add some GL traces, marcandre . lureau, 2023/06/06
- [PATCH 18/21] ui/egl: query ANGLE d3d device, marcandre . lureau, 2023/06/06
- [PATCH 17/21] virtio-gpu-virgl: teach it to get the QEMU EGL display, marcandre . lureau, 2023/06/06
- [PATCH 19/21] ui: add optional d3d texture pointer to scanout texture, marcandre . lureau, 2023/06/06
- [PATCH 20/21] virtio-gpu-virgl: use D3D11_SHARE_TEXTURE when available, marcandre . lureau, 2023/06/06
- [PATCH 21/21] ui/dbus: use shared D3D11 Texture2D when possible, marcandre . lureau, 2023/06/06
- [PATCH 09/21] console/win32: allocate shareable display surface,
marcandre . lureau <=