aboutsummaryrefslogtreecommitdiff
path: root/ui/qemu-pixman.c
diff options
context:
space:
mode:
Diffstat (limited to 'ui/qemu-pixman.c')
-rw-r--r--ui/qemu-pixman.c71
1 files changed, 71 insertions, 0 deletions
diff --git a/ui/qemu-pixman.c b/ui/qemu-pixman.c
index 6cada8b..6ef4376 100644
--- a/ui/qemu-pixman.c
+++ b/ui/qemu-pixman.c
@@ -4,7 +4,9 @@
*/
#include "qemu/osdep.h"
+#include "qapi/error.h"
#include "ui/console.h"
+#include "qemu/memfd.h"
#include "standard-headers/drm/drm_fourcc.h"
#include "trace.h"
@@ -267,3 +269,72 @@ void qemu_pixman_glyph_render(pixman_image_t *glyph,
pixman_image_unref(ibg);
}
#endif /* CONFIG_PIXMAN */
+
+static void *
+qemu_pixman_shareable_alloc(const char *name, size_t size,
+ qemu_pixman_shareable *handle,
+ Error **errp)
+{
+#ifdef WIN32
+ return qemu_win32_map_alloc(size, handle, errp);
+#else
+ 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;
+}