From: Marc-André Lureau <marcandre.lureau@redhat.com>
Use qemu_memfd_alloc() to allocate the display surface memory, which
will fallback on tmpfile/mmap() on systems without memfd, and allow to
share the display with other processes.
This is similar to how display memory is allocated on win32 since commit
09b4c198 ("console/win32: allocate shareable display surface").
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
include/ui/surface.h | 8 ++++++++
ui/console.c | 30 ++++++++++++++++++++++++++++--
2 files changed, 36 insertions(+), 2 deletions(-)
diff --git a/include/ui/surface.h b/include/ui/surface.h
index 345b19169d..dacf12ffe2 100644
--- a/include/ui/surface.h
+++ b/include/ui/surface.h
@@ -23,6 +23,10 @@ typedef struct DisplaySurface {
GLenum gltype;
GLuint texture;
#endif
+#ifndef WIN32
+ int shmfd;
+ uint32_t shmfd_offset;
+#endif
#ifdef WIN32
HANDLE handle;
uint32_t handle_offset;
@@ -37,6 +41,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);
+#ifndef WIN32
+void qemu_displaysurface_set_shmfd(DisplaySurface *surface,
+ int shmfd, uint32_t offset);
+#endif
#ifdef WIN32
void qemu_displaysurface_win32_set_handle(DisplaySurface *surface,
HANDLE h, uint32_t offset);
diff --git a/ui/console.c b/ui/console.c
index fdd76c2be4..56f2462c3d 100644
--- a/ui/console.c
+++ b/ui/console.c
@@ -37,6 +37,7 @@
#include "trace.h"
#include "exec/memory.h"
#include "qom/object.h"
+#include "qemu/memfd.h"
#include "console-priv.h"
@@ -452,6 +453,17 @@ qemu_graphic_console_init(Object *obj)
{
}
+#ifndef WIN32
+void qemu_displaysurface_set_shmfd(DisplaySurface *surface,
+ int shmfd, uint32_t offset)
+{
+ assert(surface->shmfd == -1);
+
+ surface->shmfd = shmfd;
+ surface->shmfd_offset = offset;
+}
+#endif
+
#ifdef WIN32
void qemu_displaysurface_win32_set_handle(DisplaySurface *surface,
HANDLE h, uint32_t offset)
@@ -469,12 +481,16 @@ DisplaySurface *qemu_create_displaysurface(int width, int height)
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(
@@ -486,9 +502,13 @@ DisplaySurface *qemu_create_displaysurface(int width, int height)
#ifdef WIN32
qemu_displaysurface_win32_set_handle(surface, handle, 0);
- pixman_image_set_destroy_function(surface->image,
- qemu_pixman_shared_image_destroy, handle);
+ 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;
}
@@ -499,6 +519,9 @@ 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);
@@ -512,6 +535,9 @@ 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->image = pixman_image_ref(image);
return surface;
--
2.45.2.827.g557ae147e6
On 2024/10/03 20:22, marcandre.lureau@redhat.com wrote:
> From: Marc-André Lureau <marcandre.lureau@redhat.com>
>
> Use qemu_memfd_alloc() to allocate the display surface memory, which
> will fallback on tmpfile/mmap() on systems without memfd, and allow to
> share the display with other processes.
>
> This is similar to how display memory is allocated on win32 since commit
> 09b4c198 ("console/win32: allocate shareable display surface").
>
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
> include/ui/surface.h | 8 ++++++++
> ui/console.c | 30 ++++++++++++++++++++++++++++--
> 2 files changed, 36 insertions(+), 2 deletions(-)
>
> diff --git a/include/ui/surface.h b/include/ui/surface.h
> index 345b19169d..dacf12ffe2 100644
> --- a/include/ui/surface.h
> +++ b/include/ui/surface.h
> @@ -23,6 +23,10 @@ typedef struct DisplaySurface {
> GLenum gltype;
> GLuint texture;
> #endif
> +#ifndef WIN32
> + int shmfd;
> + uint32_t shmfd_offset;
> +#endif
> #ifdef WIN32
> HANDLE handle;
What about defining a new struct that contains either of shmfd or
handle? We can then have a unified set of functions that uses the struct
to allocate/free a shared pixman image and to set one to DisplaySurface.
> uint32_t handle_offset;
> @@ -37,6 +41,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);
> +#ifndef WIN32
> +void qemu_displaysurface_set_shmfd(DisplaySurface *surface,
> + int shmfd, uint32_t offset);
> +#endif
> #ifdef WIN32
> void qemu_displaysurface_win32_set_handle(DisplaySurface *surface,
> HANDLE h, uint32_t offset);
> diff --git a/ui/console.c b/ui/console.c
> index fdd76c2be4..56f2462c3d 100644
> --- a/ui/console.c
> +++ b/ui/console.c
> @@ -37,6 +37,7 @@
> #include "trace.h"
> #include "exec/memory.h"
> #include "qom/object.h"
> +#include "qemu/memfd.h"
>
> #include "console-priv.h"
>
> @@ -452,6 +453,17 @@ qemu_graphic_console_init(Object *obj)
> {
> }
>
> +#ifndef WIN32
> +void qemu_displaysurface_set_shmfd(DisplaySurface *surface,
> + int shmfd, uint32_t offset)
> +{
> + assert(surface->shmfd == -1);
> +
> + surface->shmfd = shmfd;
> + surface->shmfd_offset = offset;
> +}
> +#endif
> +
> #ifdef WIN32
> void qemu_displaysurface_win32_set_handle(DisplaySurface *surface,
> HANDLE h, uint32_t offset)
> @@ -469,12 +481,16 @@ DisplaySurface *qemu_create_displaysurface(int width, int height)
> 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(
> @@ -486,9 +502,13 @@ DisplaySurface *qemu_create_displaysurface(int width, int height)
>
> #ifdef WIN32
> qemu_displaysurface_win32_set_handle(surface, handle, 0);
> - pixman_image_set_destroy_function(surface->image,
> - qemu_pixman_shared_image_destroy, handle);
> + 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;
> }
>
> @@ -499,6 +519,9 @@ 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);
> @@ -512,6 +535,9 @@ 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->image = pixman_image_ref(image);
>
> return surface;
On Sat, Oct 5, 2024 at 12:59 PM Akihiko Odaki <akihiko.odaki@daynix.com> wrote:
>
> On 2024/10/03 20:22, marcandre.lureau@redhat.com wrote:
> > From: Marc-André Lureau <marcandre.lureau@redhat.com>
> >
> > Use qemu_memfd_alloc() to allocate the display surface memory, which
> > will fallback on tmpfile/mmap() on systems without memfd, and allow to
> > share the display with other processes.
> >
> > This is similar to how display memory is allocated on win32 since commit
> > 09b4c198 ("console/win32: allocate shareable display surface").
> >
> > Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> > ---
> > include/ui/surface.h | 8 ++++++++
> > ui/console.c | 30 ++++++++++++++++++++++++++++--
> > 2 files changed, 36 insertions(+), 2 deletions(-)
> >
> > diff --git a/include/ui/surface.h b/include/ui/surface.h
> > index 345b19169d..dacf12ffe2 100644
> > --- a/include/ui/surface.h
> > +++ b/include/ui/surface.h
> > @@ -23,6 +23,10 @@ typedef struct DisplaySurface {
> > GLenum gltype;
> > GLuint texture;
> > #endif
> > +#ifndef WIN32
> > + int shmfd;
> > + uint32_t shmfd_offset;
> > +#endif
> > #ifdef WIN32
> > HANDLE handle;
>
> What about defining a new struct that contains either of shmfd or
> handle? We can then have a unified set of functions that uses the struct
> to allocate/free a shared pixman image and to set one to DisplaySurface.
Well, that structure is pretty much DisplaySurface. I am not sure if
it's valuable to introduce another abstraction.
>
> > uint32_t handle_offset;
> > @@ -37,6 +41,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);
> > +#ifndef WIN32
> > +void qemu_displaysurface_set_shmfd(DisplaySurface *surface,
> > + int shmfd, uint32_t offset);
> > +#endif
> > #ifdef WIN32
> > void qemu_displaysurface_win32_set_handle(DisplaySurface *surface,
> > HANDLE h, uint32_t offset);
> > diff --git a/ui/console.c b/ui/console.c
> > index fdd76c2be4..56f2462c3d 100644
> > --- a/ui/console.c
> > +++ b/ui/console.c
> > @@ -37,6 +37,7 @@
> > #include "trace.h"
> > #include "exec/memory.h"
> > #include "qom/object.h"
> > +#include "qemu/memfd.h"
> >
> > #include "console-priv.h"
> >
> > @@ -452,6 +453,17 @@ qemu_graphic_console_init(Object *obj)
> > {
> > }
> >
> > +#ifndef WIN32
> > +void qemu_displaysurface_set_shmfd(DisplaySurface *surface,
> > + int shmfd, uint32_t offset)
> > +{
> > + assert(surface->shmfd == -1);
> > +
> > + surface->shmfd = shmfd;
> > + surface->shmfd_offset = offset;
> > +}
> > +#endif
> > +
> > #ifdef WIN32
> > void qemu_displaysurface_win32_set_handle(DisplaySurface *surface,
> > HANDLE h, uint32_t offset)
> > @@ -469,12 +481,16 @@ DisplaySurface *qemu_create_displaysurface(int width, int height)
> > 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(
> > @@ -486,9 +502,13 @@ DisplaySurface *qemu_create_displaysurface(int width, int height)
> >
> > #ifdef WIN32
> > qemu_displaysurface_win32_set_handle(surface, handle, 0);
> > - pixman_image_set_destroy_function(surface->image,
> > - qemu_pixman_shared_image_destroy, handle);
> > + 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;
> > }
> >
> > @@ -499,6 +519,9 @@ 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);
> > @@ -512,6 +535,9 @@ 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->image = pixman_image_ref(image);
> >
> > return surface;
>
On 2024/10/07 20:47, Marc-André Lureau wrote:
> On Sat, Oct 5, 2024 at 12:59 PM Akihiko Odaki <akihiko.odaki@daynix.com> wrote:
>>
>> On 2024/10/03 20:22, marcandre.lureau@redhat.com wrote:
>>> From: Marc-André Lureau <marcandre.lureau@redhat.com>
>>>
>>> Use qemu_memfd_alloc() to allocate the display surface memory, which
>>> will fallback on tmpfile/mmap() on systems without memfd, and allow to
>>> share the display with other processes.
>>>
>>> This is similar to how display memory is allocated on win32 since commit
>>> 09b4c198 ("console/win32: allocate shareable display surface").
>>>
>>> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
>>> ---
>>> include/ui/surface.h | 8 ++++++++
>>> ui/console.c | 30 ++++++++++++++++++++++++++++--
>>> 2 files changed, 36 insertions(+), 2 deletions(-)
>>>
>>> diff --git a/include/ui/surface.h b/include/ui/surface.h
>>> index 345b19169d..dacf12ffe2 100644
>>> --- a/include/ui/surface.h
>>> +++ b/include/ui/surface.h
>>> @@ -23,6 +23,10 @@ typedef struct DisplaySurface {
>>> GLenum gltype;
>>> GLuint texture;
>>> #endif
>>> +#ifndef WIN32
>>> + int shmfd;
>>> + uint32_t shmfd_offset;
>>> +#endif
>>> #ifdef WIN32
>>> HANDLE handle;
>>
>> What about defining a new struct that contains either of shmfd or
>> handle? We can then have a unified set of functions that uses the struct
>> to allocate/free a shared pixman image and to set one to DisplaySurface.
>
> Well, that structure is pretty much DisplaySurface. I am not sure if
> it's valuable to introduce another abstraction.
I was thinking using the abstraction for virtio-gpu to save ifdefs. It
already has resource_set_image_destroy to abstract away the resource
deallocation so ui/console.c can absorb it.
>
>>
>>> uint32_t handle_offset;
>>> @@ -37,6 +41,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);
>>> +#ifndef WIN32
>>> +void qemu_displaysurface_set_shmfd(DisplaySurface *surface,
>>> + int shmfd, uint32_t offset);
>>> +#endif
>>> #ifdef WIN32
>>> void qemu_displaysurface_win32_set_handle(DisplaySurface *surface,
>>> HANDLE h, uint32_t offset);
>>> diff --git a/ui/console.c b/ui/console.c
>>> index fdd76c2be4..56f2462c3d 100644
>>> --- a/ui/console.c
>>> +++ b/ui/console.c
>>> @@ -37,6 +37,7 @@
>>> #include "trace.h"
>>> #include "exec/memory.h"
>>> #include "qom/object.h"
>>> +#include "qemu/memfd.h"
>>>
>>> #include "console-priv.h"
>>>
>>> @@ -452,6 +453,17 @@ qemu_graphic_console_init(Object *obj)
>>> {
>>> }
>>>
>>> +#ifndef WIN32
>>> +void qemu_displaysurface_set_shmfd(DisplaySurface *surface,
>>> + int shmfd, uint32_t offset)
>>> +{
>>> + assert(surface->shmfd == -1);
>>> +
>>> + surface->shmfd = shmfd;
>>> + surface->shmfd_offset = offset;
>>> +}
>>> +#endif
>>> +
>>> #ifdef WIN32
>>> void qemu_displaysurface_win32_set_handle(DisplaySurface *surface,
>>> HANDLE h, uint32_t offset)
>>> @@ -469,12 +481,16 @@ DisplaySurface *qemu_create_displaysurface(int width, int height)
>>> 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(
>>> @@ -486,9 +502,13 @@ DisplaySurface *qemu_create_displaysurface(int width, int height)
>>>
>>> #ifdef WIN32
>>> qemu_displaysurface_win32_set_handle(surface, handle, 0);
>>> - pixman_image_set_destroy_function(surface->image,
>>> - qemu_pixman_shared_image_destroy, handle);
>>> + 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;
>>> }
>>>
>>> @@ -499,6 +519,9 @@ 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);
>>> @@ -512,6 +535,9 @@ 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->image = pixman_image_ref(image);
>>>
>>> return surface;
>>
>
© 2016 - 2026 Red Hat, Inc.