[PATCH 0/2] Consolidate create-sync and create-fence
From: Dongwon Kim Sync object itself is never used as is so can be removed from QemuDmaBuf struct. So now sync is only temporarily needed when creating fence for the object which means what was done in egl_dmabuf_create_sync can now be a part of egl_dmabuf_create_fence function. And egl_dmabuf_create_fence returns fence_fd so the better function name will be egl_dmabuf_create_fence_fd. Dongwon Kim (2): ui/egl-helpers: Consolidate create-sync and create-fence ui/dmabuf: Remove 'sync' from QemuDmaBuf struct include/ui/dmabuf.h | 2 -- include/ui/egl-helpers.h | 3 +-- ui/dmabuf.c | 14 -- ui/egl-helpers.c | 27 +++ ui/gtk-egl.c | 15 +++ ui/gtk-gl-area.c | 10 ++ 6 files changed, 17 insertions(+), 54 deletions(-) -- 2.34.1
[PATCH 1/2] ui/egl-helpers: Consolidate create-sync and create-fence
From: Dongwon Kim There is no reason to split those two operations so combining two functions - egl_dmabuf_create_sync and egl_dmabuf_create_fence. v2: egl_dmabuf_create_fence -> egl_dmabuf_create_fence_fd (Marc-André Lureau ) Cc: Gerd Hoffmann Cc: Marc-André Lureau Cc: Vivek Kasireddy Signed-off-by: Dongwon Kim --- include/ui/egl-helpers.h | 3 +-- ui/egl-helpers.c | 27 +++ ui/gtk-egl.c | 15 +++ ui/gtk-gl-area.c | 10 ++ 4 files changed, 17 insertions(+), 38 deletions(-) diff --git a/include/ui/egl-helpers.h b/include/ui/egl-helpers.h index 4b8c0d2281..221548e3c9 100644 --- a/include/ui/egl-helpers.h +++ b/include/ui/egl-helpers.h @@ -51,8 +51,7 @@ int egl_get_fd_for_texture(uint32_t tex_id, EGLint *stride, EGLint *fourcc, void egl_dmabuf_import_texture(QemuDmaBuf *dmabuf); void egl_dmabuf_release_texture(QemuDmaBuf *dmabuf); -void egl_dmabuf_create_sync(QemuDmaBuf *dmabuf); -void egl_dmabuf_create_fence(QemuDmaBuf *dmabuf); +int egl_dmabuf_create_fence_fd(QemuDmaBuf *dmabuf); #endif diff --git a/ui/egl-helpers.c b/ui/egl-helpers.c index 99b2ebbe23..ddbf52bf5f 100644 --- a/ui/egl-helpers.c +++ b/ui/egl-helpers.c @@ -371,34 +371,29 @@ void egl_dmabuf_release_texture(QemuDmaBuf *dmabuf) qemu_dmabuf_set_texture(dmabuf, 0); } -void egl_dmabuf_create_sync(QemuDmaBuf *dmabuf) +int egl_dmabuf_create_fence_fd(QemuDmaBuf *dmabuf) { EGLSyncKHR sync; +int fence_fd = -1; if (epoxy_has_egl_extension(qemu_egl_display, "EGL_KHR_fence_sync") && epoxy_has_egl_extension(qemu_egl_display, -"EGL_ANDROID_native_fence_sync")) { +"EGL_ANDROID_native_fence_sync") && +qemu_dmabuf_get_fence_fd(dmabuf) == -1) { sync = eglCreateSyncKHR(qemu_egl_display, EGL_SYNC_NATIVE_FENCE_ANDROID, NULL); if (sync != EGL_NO_SYNC_KHR) { -qemu_dmabuf_set_sync(dmabuf, sync); +fence_fd = eglDupNativeFenceFDANDROID(qemu_egl_display, + sync); +if (fence_fd >= 0) { +qemu_dmabuf_set_fence_fd(dmabuf, fence_fd); +} +eglDestroySyncKHR(qemu_egl_display, sync); } } -} - -void egl_dmabuf_create_fence(QemuDmaBuf *dmabuf) -{ -void *sync = qemu_dmabuf_get_sync(dmabuf); -int fence_fd; -if (sync) { -fence_fd = eglDupNativeFenceFDANDROID(qemu_egl_display, - sync); -qemu_dmabuf_set_fence_fd(dmabuf, fence_fd); -eglDestroySyncKHR(qemu_egl_display, sync); -qemu_dmabuf_set_sync(dmabuf, NULL); -} +return fence_fd; } #endif /* CONFIG_GBM */ diff --git a/ui/gtk-egl.c b/ui/gtk-egl.c index 9831c10e1b..8869cdee4f 100644 --- a/ui/gtk-egl.c +++ b/ui/gtk-egl.c @@ -68,7 +68,6 @@ void gd_egl_draw(VirtualConsole *vc) GdkWindow *window; #ifdef CONFIG_GBM QemuDmaBuf *dmabuf = vc->gfx.guest_fb.dmabuf; -int fence_fd; #endif int ww, wh, ws; @@ -99,13 +98,12 @@ void gd_egl_draw(VirtualConsole *vc) glFlush(); #ifdef CONFIG_GBM if (dmabuf) { -egl_dmabuf_create_fence(dmabuf); -fence_fd = qemu_dmabuf_get_fence_fd(dmabuf); +int fence_fd = egl_dmabuf_create_fence_fd(dmabuf); if (fence_fd >= 0) { qemu_set_fd_handler(fence_fd, gd_hw_gl_flushed, NULL, vc); -return; +} else { +graphic_hw_gl_block(vc->gfx.dcl.con, false); } -graphic_hw_gl_block(vc->gfx.dcl.con, false); } #endif } else { @@ -364,12 +362,6 @@ void gd_egl_scanout_flush(DisplayChangeListener *dcl, egl_fb_blit(>gfx.win_fb, >gfx.guest_fb, !vc->gfx.y0_top); } -#ifdef CONFIG_GBM -if (vc->gfx.guest_fb.dmabuf) { -egl_dmabuf_create_sync(vc->gfx.guest_fb.dmabuf); -} -#endif - eglSwapBuffers(qemu_egl_display, vc->gfx.esurface); } @@ -387,7 +379,6 @@ void gd_egl_flush(DisplayChangeListener *dcl, gtk_widget_queue_draw_area(area, x, y, w, h); return; } - gd_egl_scanout_flush(>gfx.dcl, x, y, w, h); } diff --git a/ui/gtk-gl-area.c b/ui/gtk-gl-area.c index b628b35451..a3c21c3c59 100644 --- a/ui/gtk-gl-area.c +++ b/ui/gtk-gl-area.c @@ -77,17 +77,10 @@ void gd_gl_area_draw(VirtualConsole *vc) glBlitFramebuffer(0, y1, vc->gfx.w, y2, 0, 0, ww, wh, GL_COLOR_BUFFER_BIT, GL_NEAREST); -#ifdef CONFIG_GBM -if (dmabuf) { -egl_dmabuf_create_sync(dmabuf); -} -#endif -glFlush(); #ifdef CONFIG_GBM if (dmabuf) { int fence_fd; -egl_dmabuf_create_fence(
[PATCH 2/2] ui/dmabuf: Remove 'sync' from QemuDmaBuf struct
From: Dongwon Kim Sync object is not used so removing it from QemuDmaBuf struct Cc: Gerd Hoffmann Cc: Marc-André Lureau Cc: Vivek Kasireddy Signed-off-by: Dongwon Kim --- include/ui/dmabuf.h | 2 -- ui/dmabuf.c | 14 -- 2 files changed, 16 deletions(-) diff --git a/include/ui/dmabuf.h b/include/ui/dmabuf.h index dc74ba895a..7f0f7f3f6e 100644 --- a/include/ui/dmabuf.h +++ b/include/ui/dmabuf.h @@ -36,13 +36,11 @@ uint32_t qemu_dmabuf_get_y(QemuDmaBuf *dmabuf); uint32_t qemu_dmabuf_get_backing_width(QemuDmaBuf *dmabuf); uint32_t qemu_dmabuf_get_backing_height(QemuDmaBuf *dmabuf); bool qemu_dmabuf_get_y0_top(QemuDmaBuf *dmabuf); -void *qemu_dmabuf_get_sync(QemuDmaBuf *dmabuf); int32_t qemu_dmabuf_get_fence_fd(QemuDmaBuf *dmabuf); bool qemu_dmabuf_get_allow_fences(QemuDmaBuf *dmabuf); bool qemu_dmabuf_get_draw_submitted(QemuDmaBuf *dmabuf); void qemu_dmabuf_set_texture(QemuDmaBuf *dmabuf, uint32_t texture); void qemu_dmabuf_set_fence_fd(QemuDmaBuf *dmabuf, int32_t fence_fd); -void qemu_dmabuf_set_sync(QemuDmaBuf *dmabuf, void *sync); void qemu_dmabuf_set_draw_submitted(QemuDmaBuf *dmabuf, bool draw_submitted); void qemu_dmabuf_set_fd(QemuDmaBuf *dmabuf, int32_t fd); diff --git a/ui/dmabuf.c b/ui/dmabuf.c index df7a09703f..2332292a08 100644 --- a/ui/dmabuf.c +++ b/ui/dmabuf.c @@ -23,7 +23,6 @@ struct QemuDmaBuf { uint32_t backing_width; uint32_t backing_height; bool y0_top; -void *sync; int fence_fd; bool allow_fences; bool draw_submitted; @@ -170,13 +169,6 @@ bool qemu_dmabuf_get_y0_top(QemuDmaBuf *dmabuf) return dmabuf->y0_top; } -void *qemu_dmabuf_get_sync(QemuDmaBuf *dmabuf) -{ -assert(dmabuf != NULL); - -return dmabuf->sync; -} - int32_t qemu_dmabuf_get_fence_fd(QemuDmaBuf *dmabuf) { assert(dmabuf != NULL); @@ -210,12 +202,6 @@ void qemu_dmabuf_set_fence_fd(QemuDmaBuf *dmabuf, int32_t fence_fd) dmabuf->fence_fd = fence_fd; } -void qemu_dmabuf_set_sync(QemuDmaBuf *dmabuf, void *sync) -{ -assert(dmabuf != NULL); -dmabuf->sync = sync; -} - void qemu_dmabuf_set_draw_submitted(QemuDmaBuf *dmabuf, bool draw_submitted) { assert(dmabuf != NULL); -- 2.34.1
[PATCH] ui/gtk: Attach fullscreen toggling cb to all detached VCs
From: Dongwon Kim Enable hotkey for toggling window fullscreening for all individual untabified VCs Cc: Marc-André Lureau Cc: Vivek Kasireddy Signed-off-by: Dongwon Kim --- ui/gtk.c | 39 +++ 1 file changed, 35 insertions(+), 4 deletions(-) diff --git a/ui/gtk.c b/ui/gtk.c index 93b13b7a30..768e66bec4 100644 --- a/ui/gtk.c +++ b/ui/gtk.c @@ -1396,6 +1396,34 @@ static gboolean gd_win_grab(void *opaque) return TRUE; } +static void gd_vc_fullscreen_toggle(void *opaque) +{ +VirtualConsole *vc = opaque; +GdkWindow *window; +GdkWindowState state; + +if (!vc->window) +return; + +window = gtk_widget_get_window(vc->window); +state = gdk_window_get_state(window); + +if (state & GDK_WINDOW_STATE_FULLSCREEN) { +gtk_window_unfullscreen(GTK_WINDOW(vc->window)); + +if (vc->type == GD_VC_GFX) { +vc->gfx.scale_x = 1.0; +vc->gfx.scale_y = 1.0; +gd_update_windowsize(vc); +} +} else { +if (vc->type == GD_VC_GFX) { +gtk_widget_set_size_request(vc->gfx.drawing_area, -1, -1); +} +gtk_window_fullscreen(GTK_WINDOW(vc->window)); +} +} + static void gd_menu_untabify(GtkMenuItem *item, void *opaque) { GtkDisplayState *s = opaque; @@ -1428,10 +1456,13 @@ static void gd_menu_untabify(GtkMenuItem *item, void *opaque) if (qemu_console_is_graphic(vc->gfx.dcl.con)) { GtkAccelGroup *ag = gtk_accel_group_new(); gtk_window_add_accel_group(GTK_WINDOW(vc->window), ag); - -GClosure *cb = g_cclosure_new_swap(G_CALLBACK(gd_win_grab), - vc, NULL); -gtk_accel_group_connect(ag, GDK_KEY_g, HOTKEY_MODIFIERS, 0, cb); +GClosure *cb_grab = g_cclosure_new_swap(G_CALLBACK(gd_win_grab), +vc, NULL); +gtk_accel_group_connect(ag, GDK_KEY_g, HOTKEY_MODIFIERS, 0, cb_grab); +GClosure *cb_fs = g_cclosure_new_swap( + G_CALLBACK(gd_vc_fullscreen_toggle), + vc, NULL); +gtk_accel_group_connect(ag, GDK_KEY_f, HOTKEY_MODIFIERS, 0, cb_fs); } gd_update_geometry_hints(vc); -- 2.34.1
[PATCH] ui/gtk: Negative Page number is not valid
From: Dongwon Kim Negative page number means the page with that number does not belong to the notebook so it shouldn't be used as a valid page number in gd_vc_find_by_page. This function should just return null in such case. This change, however, will cause a segfault during detaching /untabifying process in gtk_release_modifiers because the current VC's page number suddenly becomes '-1' as soon as the VC is detached, which makes gd_vc_find_by_page return null. So gtk_release_modifiers should do the null check on VC returned from gd_vc_find_by_page. Cc: Gerd Hoffmann Cc: Marc-André Lureau Signed-off-by: Vivek Kasireddy Signed-off-by: Dongwon Kim --- ui/gtk.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ui/gtk.c b/ui/gtk.c index 93b13b7a30..1f8523fd81 100644 --- a/ui/gtk.c +++ b/ui/gtk.c @@ -164,7 +164,7 @@ static VirtualConsole *gd_vc_find_by_page(GtkDisplayState *s, gint page) for (i = 0; i < s->nb_vcs; i++) { vc = >vc[i]; p = gtk_notebook_page_num(GTK_NOTEBOOK(s->notebook), vc->tab_item); -if (p == page) { +if (p > -1 && p == page) { return vc; } } @@ -357,7 +357,7 @@ static void gtk_release_modifiers(GtkDisplayState *s) { VirtualConsole *vc = gd_vc_find_current(s); -if (vc->type != GD_VC_GFX || +if (!vc || vc->type != GD_VC_GFX || !qemu_console_is_graphic(vc->gfx.dcl.con)) { return; } -- 2.34.1
[RFC PATCH 0/4] hw/display/virtio-gpu: Introducing asynchronous guest display render
From: Dongwon Kim Introducing new virtio-gpu param, 'render_sync' when guest scanout blob is used (blob=true). The new param is used to specify when to start rendering a guest scanout frame. By default (and so far) rendering of the guest frame is started in the draw event to make sure guest display update is sychronized with host's vsync. But this method inevitably brings some extra wait because most of time, the draw event is not happening right after the guest scanout frame is flushed. This delay often makes the guest stuck at certain frame for too long and causes general performance degradation of graphic workloads on the guest's side especially when the display update rate is high. This unwanted perf drop can be reduced if the guest scanout frame is rendered as soon as it is flushed through 'VIRTIO_GPU_CMD_RESOURCE_FLUSH' msg. The gl display pipeline can be unblocked a lot earlier in this case so that guest can move to the next display frame right away. However, this "asynchrounous" render mode may cause some waste of resources as the guest could produce more frames than what are actually displayed on the host display. This is similar as running rendering apps with no vblank or vsync option. This is why this feature should stay as optional. The param 'render_sync' is set to 'true' by default and this is in line with traditional way while setting it to 'false' is basically enabling this asynchronouse mode. Dongwon Kim (4): hw/display/virtio-gpu: Introducing render_sync param ui/egl-helpers: Consolidates create-sync and create-fence ui/gtk-egl: Start rendering of guest blob scanout if render_sync is off ui/gtk-gl-draw: Start rendering of guest blob scanout if render_sync is off include/hw/virtio/virtio-gpu.h | 3 ++ include/ui/dmabuf.h | 4 +- include/ui/egl-helpers.h| 3 +- hw/display/vhost-user-gpu.c | 3 +- hw/display/virtio-gpu-udmabuf.c | 3 +- hw/display/virtio-gpu.c | 2 + hw/vfio/display.c | 3 +- ui/dbus-listener.c | 2 +- ui/dmabuf.c | 11 +++- ui/egl-helpers.c| 27 -- ui/gtk-egl.c| 93 ++--- ui/gtk-gl-area.c| 90 +++ 12 files changed, 146 insertions(+), 98 deletions(-) -- 2.34.1
[RFC PATCH 3/4] ui/gtk-egl: Start rendering of guest blob scanout if render_sync is off
From: Dongwon Kim Draw (executing glBlitFramebuffer) immediately as soon as the frame is flushed instead of getting it done in the next draw event if render_sync flag is reset. With this, the fence will be signaled way ealier so the guest can be working on the next frame right away. Cc: Gerd Hoffmann Cc: Marc-André Lureau Cc: Vivek Kasireddy Signed-off-by: Dongwon Kim --- ui/gtk-egl.c | 88 ++-- 1 file changed, 51 insertions(+), 37 deletions(-) diff --git a/ui/gtk-egl.c b/ui/gtk-egl.c index 55199f8659..2877140c3b 100644 --- a/ui/gtk-egl.c +++ b/ui/gtk-egl.c @@ -80,6 +80,12 @@ void gd_egl_draw(VirtualConsole *vc) ww = gdk_window_get_width(window) * ws; wh = gdk_window_get_height(window) * ws; +vc->gfx.scale_x = (double)ww / surface_width(vc->gfx.ds); +vc->gfx.scale_y = (double)wh / surface_height(vc->gfx.ds); + +eglMakeCurrent(qemu_egl_display, vc->gfx.esurface, + vc->gfx.esurface, vc->gfx.ectx); + if (vc->gfx.scanout_mode) { #ifdef CONFIG_GBM if (dmabuf) { @@ -88,21 +94,9 @@ void gd_egl_draw(VirtualConsole *vc) } else { qemu_dmabuf_set_draw_submitted(dmabuf, false); } -} -#endif -gd_egl_scanout_flush(>gfx.dcl, 0, 0, vc->gfx.w, vc->gfx.h); -vc->gfx.scale_x = (double)ww / surface_width(vc->gfx.ds); -vc->gfx.scale_y = (double)wh / surface_height(vc->gfx.ds); - -glFlush(); -#ifdef CONFIG_GBM -if (dmabuf) { -fence_fd = egl_dmabuf_create_fence(dmabuf); -if (fence_fd >= 0) { -qemu_set_fd_handler(fence_fd, gd_hw_gl_flushed, NULL, vc); -} else { -graphic_hw_gl_block(vc->gfx.dcl.con, false); +if (qemu_dmabuf_get_render_sync(dmabuf)) { +gd_egl_scanout_flush(>gfx.dcl, 0, 0, vc->gfx.w, vc->gfx.h); } } #endif @@ -110,19 +104,12 @@ void gd_egl_draw(VirtualConsole *vc) if (!vc->gfx.ds) { return; } -eglMakeCurrent(qemu_egl_display, vc->gfx.esurface, - vc->gfx.esurface, vc->gfx.ectx); - surface_gl_setup_viewport(vc->gfx.gls, vc->gfx.ds, ww, wh); surface_gl_render_texture(vc->gfx.gls, vc->gfx.ds); - -eglSwapBuffers(qemu_egl_display, vc->gfx.esurface); - -vc->gfx.scale_x = (double)ww / surface_width(vc->gfx.ds); -vc->gfx.scale_y = (double)wh / surface_height(vc->gfx.ds); - -glFlush(); } + +eglSwapBuffers(qemu_egl_display, vc->gfx.esurface); +glFlush(); } void gd_egl_update(DisplayChangeListener *dcl, @@ -146,14 +133,20 @@ void gd_egl_refresh(DisplayChangeListener *dcl) { VirtualConsole *vc = container_of(dcl, VirtualConsole, gfx.dcl); +#ifdef CONFIG_GBM +QemuDmaBuf *dmabuf = vc->gfx.guest_fb.dmabuf; +#endif + gd_update_monitor_refresh_rate( vc, vc->window ? vc->window : vc->gfx.drawing_area); -if (vc->gfx.guest_fb.dmabuf && -qemu_dmabuf_get_draw_submitted(vc->gfx.guest_fb.dmabuf)) { +#ifdef CONFIG_GBM +if (dmabuf && qemu_dmabuf_get_draw_submitted(dmabuf) && +qemu_dmabuf_get_render_sync(dmabuf)) { gd_egl_draw(vc); return; } +#endif if (!vc->gfx.esurface) { gd_egl_init(vc); @@ -166,9 +159,9 @@ void gd_egl_refresh(DisplayChangeListener *dcl) surface_gl_create_texture(vc->gfx.gls, vc->gfx.ds); } #ifdef CONFIG_GBM -if (vc->gfx.guest_fb.dmabuf) { -egl_dmabuf_release_texture(vc->gfx.guest_fb.dmabuf); -gd_egl_scanout_dmabuf(dcl, vc->gfx.guest_fb.dmabuf); +if (dmabuf) { +egl_dmabuf_release_texture(dmabuf); +gd_egl_scanout_dmabuf(dcl, dmabuf); } #endif } @@ -344,6 +337,11 @@ void gd_egl_scanout_flush(DisplayChangeListener *dcl, return; } if (!vc->gfx.guest_fb.framebuffer) { +#ifdef CONFIG_GBM +if (dmabuf) { +graphic_hw_gl_block(vc->gfx.dcl.con, false); +} +#endif return; } @@ -366,7 +364,16 @@ void gd_egl_scanout_flush(DisplayChangeListener *dcl, egl_fb_blit(>gfx.win_fb, >gfx.guest_fb, !vc->gfx.y0_top); } -eglSwapBuffers(qemu_egl_display, vc->gfx.esurface); +#ifdef CONFIG_GBM +if (dmabuf) { +fence_fd = egl_dmabuf_create_fence(dmabuf); +if (fence_fd >= 0) { +qemu_set_fd_handler(fence_fd, gd_hw_gl_flushed, NULL, vc); +} else { +graphic_hw_gl_block(vc->gfx.dcl.con, false); +} +} +#endif } void gd_egl_flush(DisplayChangeListener *dcl, @@ -374,15 +381,22 @@ void gd_egl_flush(DisplayChangeListener *dcl, { VirtualConsole *vc = container_of(dcl, VirtualConsole, gfx.
[RFC PATCH 1/4] hw/display/virtio-gpu: Introducing render_sync param
From: Dongwon Kim Introducing new virtio-gpu param, 'render_sync' when guest scanout blob is used (blob=true). The new param is used to specify when to start rendering a guest scanout frame. By default (and so far) rendering of the guest frame is started in the draw event to make sure guest display update is sychronized with host's vsync. But this method inevitably brings some extra wait because most of time, the draw event is not happening right after the guest scanout frame is flushed. This delay often makes the guest stuck at certain frame for too long and causes general performance degradation of graphic workloads on the guest's side especially when the display update rate is high. This unwanted perf drop can be reduced if the guest scanout frame is rendered as soon as it is flushed through 'VIRTIO_GPU_CMD_RESOURCE_FLUSH' msg. The gl display pipeline can be unblocked a lot earlier in this case so that guest can move to the next display frame right away. However, this "asynchrounous" render mode may cause some waste of resources as the guest could produce more frames than what are actually displayed on the host display. This is similar as running rendering apps with no vblank or vsync option. This is why this feature should stay as optional. The param 'render_sync' is set to 'true' by default and this is in line with traditional way while setting it to 'false' is basically enabling this asynchronouse mode. Cc: Gerd Hoffmann Cc: Marc-André Lureau Cc: Vivek Kasireddy Signed-off-by: Dongwon Kim --- include/hw/virtio/virtio-gpu.h | 3 +++ include/ui/dmabuf.h | 4 +++- hw/display/vhost-user-gpu.c | 3 ++- hw/display/virtio-gpu-udmabuf.c | 3 ++- hw/display/virtio-gpu.c | 2 ++ hw/vfio/display.c | 3 ++- ui/dbus-listener.c | 2 +- ui/dmabuf.c | 11 ++- 8 files changed, 25 insertions(+), 6 deletions(-) diff --git a/include/hw/virtio/virtio-gpu.h b/include/hw/virtio/virtio-gpu.h index 7a59379f5a..9bcc572eab 100644 --- a/include/hw/virtio/virtio-gpu.h +++ b/include/hw/virtio/virtio-gpu.h @@ -97,6 +97,7 @@ enum virtio_gpu_base_conf_flags { VIRTIO_GPU_FLAG_EDID_ENABLED, VIRTIO_GPU_FLAG_DMABUF_ENABLED, VIRTIO_GPU_FLAG_BLOB_ENABLED, +VIRTIO_GPU_FLAG_RENDER_SYNC_ENABLED, VIRTIO_GPU_FLAG_CONTEXT_INIT_ENABLED, VIRTIO_GPU_FLAG_RUTABAGA_ENABLED, }; @@ -111,6 +112,8 @@ enum virtio_gpu_base_conf_flags { (_cfg.flags & (1 << VIRTIO_GPU_FLAG_DMABUF_ENABLED)) #define virtio_gpu_blob_enabled(_cfg) \ (_cfg.flags & (1 << VIRTIO_GPU_FLAG_BLOB_ENABLED)) +#define virtio_gpu_render_sync_enabled(_cfg) \ +(_cfg.flags & (1 << VIRTIO_GPU_FLAG_RENDER_SYNC_ENABLED)) #define virtio_gpu_context_init_enabled(_cfg) \ (_cfg.flags & (1 << VIRTIO_GPU_FLAG_CONTEXT_INIT_ENABLED)) #define virtio_gpu_rutabaga_enabled(_cfg) \ diff --git a/include/ui/dmabuf.h b/include/ui/dmabuf.h index dc74ba895a..45384e32e3 100644 --- a/include/ui/dmabuf.h +++ b/include/ui/dmabuf.h @@ -17,7 +17,8 @@ QemuDmaBuf *qemu_dmabuf_new(uint32_t width, uint32_t height, uint32_t y, uint32_t backing_width, uint32_t backing_height, uint32_t fourcc, uint64_t modifier, int dmabuf_fd, -bool allow_fences, bool y0_top); +bool allow_fences, bool y0_top, +bool render_sync); void qemu_dmabuf_free(QemuDmaBuf *dmabuf); G_DEFINE_AUTOPTR_CLEANUP_FUNC(QemuDmaBuf, qemu_dmabuf_free); @@ -40,6 +41,7 @@ void *qemu_dmabuf_get_sync(QemuDmaBuf *dmabuf); int32_t qemu_dmabuf_get_fence_fd(QemuDmaBuf *dmabuf); bool qemu_dmabuf_get_allow_fences(QemuDmaBuf *dmabuf); bool qemu_dmabuf_get_draw_submitted(QemuDmaBuf *dmabuf); +bool qemu_dmabuf_get_render_sync(QemuDmaBuf *dmabuf); void qemu_dmabuf_set_texture(QemuDmaBuf *dmabuf, uint32_t texture); void qemu_dmabuf_set_fence_fd(QemuDmaBuf *dmabuf, int32_t fence_fd); void qemu_dmabuf_set_sync(QemuDmaBuf *dmabuf, void *sync); diff --git a/hw/display/vhost-user-gpu.c b/hw/display/vhost-user-gpu.c index e4b398d26c..69fa722c88 100644 --- a/hw/display/vhost-user-gpu.c +++ b/hw/display/vhost-user-gpu.c @@ -285,7 +285,8 @@ vhost_user_gpu_handle_display(VhostUserGPU *g, VhostUserGpuMsg *msg) m->fd_stride, 0, 0, 0, 0, m->fd_drm_fourcc, modifier, fd, false, m->fd_flags & - VIRTIO_GPU_RESOURCE_FLAG_Y_0_TOP); + VIRTIO_GPU_RESOURCE_FLAG_Y_0_TOP, + false); dpy_gl_scanout_dmabuf(con, dmabuf); g->dmabuf[m->scanout_id] = dmabuf; diff --git a/hw/display/virtio-gpu-udmabuf.c b/hw/display/virtio-gpu-udmabuf.c index c02ec6d37d..8fcc0c3055 100644 --- a/hw/display/virtio
[RFC PATCH 4/4] ui/gtk-gl-draw: Start rendering of guest blob scanout if render_sync is off
From: Dongwon Kim Draw (executing glBlitFramebuffer) immediately as soon as the frame is flushed instead of getting it done in the next draw event if render_sync flag is reset. With this, the fence will be signaled way ealier so the guest can be working on the next frame right away. Cc: Marc-André Lureau Cc: Vivek Kasireddy Signed-off-by: Dongwon Kim --- ui/gtk-gl-area.c | 84 +--- 1 file changed, 58 insertions(+), 26 deletions(-) diff --git a/ui/gtk-gl-area.c b/ui/gtk-gl-area.c index 0b11423824..88d4e66a52 100644 --- a/ui/gtk-gl-area.c +++ b/ui/gtk-gl-area.c @@ -65,39 +65,36 @@ void gd_gl_area_draw(VirtualConsole *vc) } else { qemu_dmabuf_set_draw_submitted(dmabuf, false); } -} -#endif -glBindFramebuffer(GL_READ_FRAMEBUFFER, vc->gfx.guest_fb.framebuffer); -/* GtkGLArea sets GL_DRAW_FRAMEBUFFER for us */ - -glViewport(0, 0, ww, wh); -y1 = vc->gfx.y0_top ? 0 : vc->gfx.h; -y2 = vc->gfx.y0_top ? vc->gfx.h : 0; -glBlitFramebuffer(0, y1, vc->gfx.w, y2, - 0, 0, ww, wh, - GL_COLOR_BUFFER_BIT, GL_NEAREST); -#ifdef CONFIG_GBM -if (dmabuf) { -int fence_fd; -fence_fd = egl_dmabuf_create_fence(dmabuf); -if (fence_fd >= 0) { -qemu_set_fd_handler(fence_fd, gd_hw_gl_flushed, NULL, vc); -return; +if (qemu_dmabuf_get_render_sync(dmabuf)) { +int fence_fd; +glBindFramebuffer(GL_READ_FRAMEBUFFER, vc->gfx.guest_fb.framebuffer); +/* GtkGLArea sets GL_DRAW_FRAMEBUFFER for us */ + +glViewport(0, 0, ww, wh); +y1 = vc->gfx.y0_top ? 0 : vc->gfx.h; +y2 = vc->gfx.y0_top ? vc->gfx.h : 0; +glBlitFramebuffer(0, y1, vc->gfx.w, y2, + 0, 0, ww, wh, + GL_COLOR_BUFFER_BIT, GL_NEAREST); +fence_fd = egl_dmabuf_create_fence(dmabuf); +if (fence_fd >= 0) { +qemu_set_fd_handler(fence_fd, gd_hw_gl_flushed, NULL, vc); +} else { +graphic_hw_gl_block(vc->gfx.dcl.con, false); +} } -graphic_hw_gl_block(vc->gfx.dcl.con, false); } #endif -glFlush(); } else { if (!vc->gfx.ds) { return; } -gtk_gl_area_make_current(GTK_GL_AREA(vc->gfx.drawing_area)); surface_gl_setup_viewport(vc->gfx.gls, vc->gfx.ds, ww, wh); surface_gl_render_texture(vc->gfx.gls, vc->gfx.ds); } +glFlush(); } void gd_gl_area_update(DisplayChangeListener *dcl, @@ -119,13 +116,19 @@ void gd_gl_area_refresh(DisplayChangeListener *dcl) { VirtualConsole *vc = container_of(dcl, VirtualConsole, gfx.dcl); +#ifdef CONFIG_GBM +QemuDmaBuf *dmabuf = vc->gfx.guest_fb.dmabuf; +#endif + gd_update_monitor_refresh_rate(vc, vc->window ? vc->window : vc->gfx.drawing_area); -if (vc->gfx.guest_fb.dmabuf && -qemu_dmabuf_get_draw_submitted(vc->gfx.guest_fb.dmabuf)) { +#ifdef CONFIG_GBM +if (dmabuf && qemu_dmabuf_get_draw_submitted(dmabuf) && +qemu_dmabuf_get_render_sync(dmabuf)) { gd_gl_area_draw(vc); return; } +#endif if (!vc->gfx.gls) { if (!gtk_widget_get_realized(vc->gfx.drawing_area)) { @@ -282,13 +285,42 @@ void gd_gl_area_scanout_flush(DisplayChangeListener *dcl, uint32_t x, uint32_t y, uint32_t w, uint32_t h) { VirtualConsole *vc = container_of(dcl, VirtualConsole, gfx.dcl); +#ifdef CONFIG_GBM +QemuDmaBuf *dmabuf = vc->gfx.guest_fb.dmabuf; +int ww, wh, ws, y1, y2; + +if (dmabuf && !qemu_dmabuf_get_draw_submitted(dmabuf)) { +gtk_gl_area_make_current(GTK_GL_AREA(vc->gfx.drawing_area)); +ws = gdk_window_get_scale_factor(gtk_widget_get_window(vc->gfx.drawing_area)); +ww = gtk_widget_get_allocated_width(vc->gfx.drawing_area) * ws; +wh = gtk_widget_get_allocated_height(vc->gfx.drawing_area) * ws; -if (vc->gfx.guest_fb.dmabuf && -!qemu_dmabuf_get_draw_submitted(vc->gfx.guest_fb.dmabuf)) { graphic_hw_gl_block(vc->gfx.dcl.con, true); -qemu_dmabuf_set_draw_submitted(vc->gfx.guest_fb.dmabuf, true); +qemu_dmabuf_set_draw_submitted(dmabuf, true); gtk_gl_area_set_scanout_mode(vc, true); +if (!qemu_dmabuf_get_render_sync(dmabuf)) { +int fence_fd; +glBindFramebuffer(GL_READ_FRAMEBUFFER, vc->gfx.guest_fb.framebuffer); +/* GtkGLArea sets GL_DRAW_FRAMEBUFFER for us */ + +glViewport(0, 0, ww, wh); +y1 = vc->gfx
[RFC PATCH 2/4] ui/egl-helpers: Consolidates create-sync and create-fence
From: Dongwon Kim There is no reason to split those two operations so combining two functions - egl_dmabuf_create_sync and egl_dmabuf_create_fence. Cc: Gerd Hoffmann Cc: Marc-André Lureau Cc: Vivek Kasireddy Signed-off-by: Dongwon Kim --- include/ui/egl-helpers.h | 3 +-- ui/egl-helpers.c | 27 +++ ui/gtk-egl.c | 19 +++ ui/gtk-gl-area.c | 10 ++ 4 files changed, 21 insertions(+), 38 deletions(-) diff --git a/include/ui/egl-helpers.h b/include/ui/egl-helpers.h index 4b8c0d2281..606d6c8288 100644 --- a/include/ui/egl-helpers.h +++ b/include/ui/egl-helpers.h @@ -51,8 +51,7 @@ int egl_get_fd_for_texture(uint32_t tex_id, EGLint *stride, EGLint *fourcc, void egl_dmabuf_import_texture(QemuDmaBuf *dmabuf); void egl_dmabuf_release_texture(QemuDmaBuf *dmabuf); -void egl_dmabuf_create_sync(QemuDmaBuf *dmabuf); -void egl_dmabuf_create_fence(QemuDmaBuf *dmabuf); +int egl_dmabuf_create_fence(QemuDmaBuf *dmabuf); #endif diff --git a/ui/egl-helpers.c b/ui/egl-helpers.c index 99b2ebbe23..e16f2cb23d 100644 --- a/ui/egl-helpers.c +++ b/ui/egl-helpers.c @@ -371,34 +371,29 @@ void egl_dmabuf_release_texture(QemuDmaBuf *dmabuf) qemu_dmabuf_set_texture(dmabuf, 0); } -void egl_dmabuf_create_sync(QemuDmaBuf *dmabuf) +int egl_dmabuf_create_fence(QemuDmaBuf *dmabuf) { EGLSyncKHR sync; +int fence_fd = -1; if (epoxy_has_egl_extension(qemu_egl_display, "EGL_KHR_fence_sync") && epoxy_has_egl_extension(qemu_egl_display, -"EGL_ANDROID_native_fence_sync")) { +"EGL_ANDROID_native_fence_sync") && +qemu_dmabuf_get_fence_fd(dmabuf) == -1) { sync = eglCreateSyncKHR(qemu_egl_display, EGL_SYNC_NATIVE_FENCE_ANDROID, NULL); if (sync != EGL_NO_SYNC_KHR) { -qemu_dmabuf_set_sync(dmabuf, sync); +fence_fd = eglDupNativeFenceFDANDROID(qemu_egl_display, + sync); +if (fence_fd >= 0) { +qemu_dmabuf_set_fence_fd(dmabuf, fence_fd); +} +eglDestroySyncKHR(qemu_egl_display, sync); } } -} - -void egl_dmabuf_create_fence(QemuDmaBuf *dmabuf) -{ -void *sync = qemu_dmabuf_get_sync(dmabuf); -int fence_fd; -if (sync) { -fence_fd = eglDupNativeFenceFDANDROID(qemu_egl_display, - sync); -qemu_dmabuf_set_fence_fd(dmabuf, fence_fd); -eglDestroySyncKHR(qemu_egl_display, sync); -qemu_dmabuf_set_sync(dmabuf, NULL); -} +return fence_fd; } #endif /* CONFIG_GBM */ diff --git a/ui/gtk-egl.c b/ui/gtk-egl.c index 9831c10e1b..55199f8659 100644 --- a/ui/gtk-egl.c +++ b/ui/gtk-egl.c @@ -68,7 +68,6 @@ void gd_egl_draw(VirtualConsole *vc) GdkWindow *window; #ifdef CONFIG_GBM QemuDmaBuf *dmabuf = vc->gfx.guest_fb.dmabuf; -int fence_fd; #endif int ww, wh, ws; @@ -99,13 +98,12 @@ void gd_egl_draw(VirtualConsole *vc) glFlush(); #ifdef CONFIG_GBM if (dmabuf) { -egl_dmabuf_create_fence(dmabuf); -fence_fd = qemu_dmabuf_get_fence_fd(dmabuf); +fence_fd = egl_dmabuf_create_fence(dmabuf); if (fence_fd >= 0) { qemu_set_fd_handler(fence_fd, gd_hw_gl_flushed, NULL, vc); -return; +} else { +graphic_hw_gl_block(vc->gfx.dcl.con, false); } -graphic_hw_gl_block(vc->gfx.dcl.con, false); } #endif } else { @@ -336,7 +334,11 @@ void gd_egl_scanout_flush(DisplayChangeListener *dcl, { VirtualConsole *vc = container_of(dcl, VirtualConsole, gfx.dcl); GdkWindow *window; +#ifdef CONFIG_GBM +QemuDmaBuf *dmabuf = vc->gfx.guest_fb.dmabuf; +#endif int ww, wh, ws; +int fence_fd; if (!vc->gfx.scanout_mode) { return; @@ -364,12 +366,6 @@ void gd_egl_scanout_flush(DisplayChangeListener *dcl, egl_fb_blit(>gfx.win_fb, >gfx.guest_fb, !vc->gfx.y0_top); } -#ifdef CONFIG_GBM -if (vc->gfx.guest_fb.dmabuf) { -egl_dmabuf_create_sync(vc->gfx.guest_fb.dmabuf); -} -#endif - eglSwapBuffers(qemu_egl_display, vc->gfx.esurface); } @@ -387,7 +383,6 @@ void gd_egl_flush(DisplayChangeListener *dcl, gtk_widget_queue_draw_area(area, x, y, w, h); return; } - gd_egl_scanout_flush(>gfx.dcl, x, y, w, h); } diff --git a/ui/gtk-gl-area.c b/ui/gtk-gl-area.c index b628b35451..0b11423824 100644 --- a/ui/gtk-gl-area.c +++ b/ui/gtk-gl-area.c @@ -77,17 +77,10 @@ void gd_gl_area_draw(VirtualConsole *vc) glBlitFramebuffer(0, y1, vc->gfx.w, y2, 0, 0, ww, wh, GL_COLOR_BUFFER_BIT, GL_NEA
[PATCH RFC v2 2/2] ui/gtk: Add a new parameter to assign connectors/monitors
From: Vivek Kasireddy The new parameter named "connector" can be used to assign physical monitors/connectors to individual GFX VCs such that when the monitor is connected or hot-plugged, the associated GTK window would be moved to it. If the monitor is disconnected or unplugged, the associated GTK window would be hidden and a relevant disconnect event would be sent to the Guest. One usage example is here: -display gtk,gl=on,connectors=DP-1:eDP-1:HDMI-2... With this, the first graphic virtual console will be placed on DP-1 display, second on eDP-1 and the third on HDMI-2. v2: Connectors is now in a string format that includes all connector names separated with a colon (previously it was a linked list) Code refactoring Cc: Gerd Hoffmann Cc: Marc-André Lureau Cc: Daniel P. Berrangé Cc: Markus Armbruster Signed-off-by: Vivek Kasireddy Signed-off-by: Dongwon Kim --- qapi/ui.json | 25 - include/ui/gtk.h | 1 + ui/gtk.c | 250 +++ qemu-options.hx | 4 + 4 files changed, 279 insertions(+), 1 deletion(-) diff --git a/qapi/ui.json b/qapi/ui.json index f610bce118..46ed9e76fc 100644 --- a/qapi/ui.json +++ b/qapi/ui.json @@ -1335,13 +1335,36 @@ # @show-menubar: Display the main window menubar. Defaults to "on". # (Since 8.0) # +# @connectors: A list of physical monitor/connector names where the +# GTK windows containing the respective GFX VCs (virtual consoles) +# are to be placed. The connector names should be provided as +# a string, with each name separated by a colon +# (e.g., DP-1:DP-2:HDMI-1:HDMI-2). Each connector name in the +# string will be used as a label for each VC in order. +# VCs can be skipped by leaving an empty spot between colons +# (e.g., DP-1::HDMI-2). If a connector name is not provided for +# a VC, that VC will not be placed on any physical display and +# the guest will see it as disconnected. If a valid connector name +# is provided for a VC but its display cable is not plugged in +# when the guest is launched, the VC will not be displayed initially. +# It will appear on the display when the cable is plugged in +# (hot-plug). If the cable is disconnected, the VC will be hidden +# and the guest will see its virtual display as disconnected. +# Multiple VCs can share the same connector name. In this case, +# all VCs with that name will be displayed on the same physical +# monitor. However, a single VC cannot have multiple connector +# names. +# +# (Since 9.1) +# # Since: 2.12 ## { 'struct' : 'DisplayGTK', 'data': { '*grab-on-hover' : 'bool', '*zoom-to-fit' : 'bool', '*show-tabs' : 'bool', -'*show-menubar' : 'bool' } } +'*show-menubar' : 'bool', +'*connectors': 'str' } } ## # @DisplayEGLHeadless: diff --git a/include/ui/gtk.h b/include/ui/gtk.h index aa3d637029..3f78ee5996 100644 --- a/include/ui/gtk.h +++ b/include/ui/gtk.h @@ -83,6 +83,7 @@ typedef struct VirtualConsole { GtkWidget *menu_item; GtkWidget *tab_item; GtkWidget *focus; +GdkMonitor *monitor; VirtualConsoleType type; union { VirtualGfxConsole gfx; diff --git a/ui/gtk.c b/ui/gtk.c index 3bc84090c8..dc356e1dcf 100644 --- a/ui/gtk.c +++ b/ui/gtk.c @@ -38,6 +38,7 @@ #include "qemu/cutils.h" #include "qemu/error-report.h" #include "qemu/main-loop.h" +#include "qemu/option.h" #include "ui/console.h" #include "ui/gtk.h" @@ -1446,6 +1447,248 @@ static void gd_menu_untabify(GtkMenuItem *item, void *opaque) } } +static void gd_ui_mon_enable(VirtualConsole *vc) +{ +GdkWindow *window = gtk_widget_get_window(vc->gfx.drawing_area); +QemuUIInfo info; + +if (!dpy_ui_info_supported(vc->gfx.dcl.con)) { +return; +} + +info = *dpy_get_ui_info(vc->gfx.dcl.con); +info.width = gdk_window_get_width(window); +info.height = gdk_window_get_height(window); +dpy_set_ui_info(vc->gfx.dcl.con, , false); +} + +static void gd_ui_mon_disable(VirtualConsole *vc) +{ +QemuUIInfo info; + +if (!dpy_ui_info_supported(vc->gfx.dcl.con)) { +return; +} + +info = *dpy_get_ui_info(vc->gfx.dcl.con); +info.width = 0; +info.height = 0; +dpy_set_ui_info(vc->gfx.dcl.con, , false); +} + +static void gd_window_show_on_monitor(GdkDisplay *dpy, VirtualConsole *vc, + gint monitor_num) +{ +GtkDisplayState *s = vc->s; +GdkMonitor *monitor = gdk_display_get_monitor(dpy, monitor_num); +GdkRectangle geometry; +if (!vc->window) { +gd_tab_window_create(vc); +} + +gdk_window_show(gtk_widget_get_window(vc->window)); +gd_update_windowsize(vc); +gdk_monitor_get_geometry(monitor, ); + +gtk_window_mov
[RFC PATCH v2 0/2] ui/gtk: Introduce new param - Connectors
From: Dongwon Kim This patch series is a replacement of https://mail.gnu.org/archive/html/qemu-devel/2023-06/msg03989.html There is a need, expressed by several users, to assign ownership of one or more physical monitors/connectors to individual guests. This creates a clear notion of which guest's contents are being displayed on any given monitor. Given that there is always a display server/compositor running on the host, monitor ownership can never truly be transferred to guests. However, the closest approximation is to request the host compositor to fullscreen the guest's windows on individual monitors. This allows for various configurations, such as displaying four different guests' windows on four different monitors, a single guest's windows (or virtual consoles) on four monitors, or any similar combination. This patch series attempts to accomplish this by introducing a new parameter named "connector" to assign monitors to the GFX VCs associated with a guest. If the assigned monitor is not connected, the guest's window will not be displayed, similar to how a host compositor behaves when connectors are not connected. Once the monitor is hot-plugged, the guest's window(s) will be positioned on the assigned monitor. Usage example: -display gtk,gl=on,connectors=DP-1:eDP-1:HDMI-2... In this example, the first graphics virtual console will be placed on the DP-1 display, the second on eDP-1, and the third on HDMI-2. v2: Connectors is now in a string format that includes all connector names separated with a colon (previously it was a linked list) Code refactoring Vivek Kasireddy (2): ui/gtk: Factor out tab window creation into a separate ui/gtk: Add a new parameter to assign connectors/monitors qapi/ui.json | 25 +++- include/ui/gtk.h | 1 + ui/gtk.c | 301 +++ qemu-options.hx | 4 + 4 files changed, 308 insertions(+), 23 deletions(-) -- 2.34.1
[RFC PATCH v2 1/2] ui/gtk: Factor out tab window creation into a separate
From: Vivek Kasireddy Pull the code that creates a new window associated with a notebook tab into a separate function. This new function can be useful not just when user wants to detach a tab but also in the future when a new window creation is needed in other scenarios. Cc: Gerd Hoffmann Cc: Marc-André Lureau Cc: Daniel P. Berrangé Cc: Markus Armbruster Signed-off-by: Vivek Kasireddy Signed-off-by: Dongwon Kim --- ui/gtk.c | 65 +++- 1 file changed, 36 insertions(+), 29 deletions(-) diff --git a/ui/gtk.c b/ui/gtk.c index 93b13b7a30..3bc84090c8 100644 --- a/ui/gtk.c +++ b/ui/gtk.c @@ -1396,6 +1396,41 @@ static gboolean gd_win_grab(void *opaque) return TRUE; } +static void gd_tab_window_create(VirtualConsole *vc) +{ +GtkDisplayState *s = vc->s; + +gtk_widget_set_sensitive(vc->menu_item, false); +vc->window = gtk_window_new(GTK_WINDOW_TOPLEVEL); +#if defined(CONFIG_OPENGL) +if (vc->gfx.esurface) { +eglDestroySurface(qemu_egl_display, vc->gfx.esurface); +vc->gfx.esurface = NULL; +} +if (vc->gfx.ectx) { +eglDestroyContext(qemu_egl_display, vc->gfx.ectx); +vc->gfx.ectx = NULL; +} +#endif +gd_widget_reparent(s->notebook, vc->window, vc->tab_item); + +g_signal_connect(vc->window, "delete-event", + G_CALLBACK(gd_tab_window_close), vc); +gtk_widget_show_all(vc->window); + +if (qemu_console_is_graphic(vc->gfx.dcl.con)) { +GtkAccelGroup *ag = gtk_accel_group_new(); +gtk_window_add_accel_group(GTK_WINDOW(vc->window), ag); + +GClosure *cb = g_cclosure_new_swap(G_CALLBACK(gd_win_grab), + vc, NULL); +gtk_accel_group_connect(ag, GDK_KEY_g, HOTKEY_MODIFIERS, 0, cb); +} + +gd_update_geometry_hints(vc); +gd_update_caption(s); +} + static void gd_menu_untabify(GtkMenuItem *item, void *opaque) { GtkDisplayState *s = opaque; @@ -1407,35 +1442,7 @@ static void gd_menu_untabify(GtkMenuItem *item, void *opaque) FALSE); } if (!vc->window) { -gtk_widget_set_sensitive(vc->menu_item, false); -vc->window = gtk_window_new(GTK_WINDOW_TOPLEVEL); -#if defined(CONFIG_OPENGL) -if (vc->gfx.esurface) { -eglDestroySurface(qemu_egl_display, vc->gfx.esurface); -vc->gfx.esurface = NULL; -} -if (vc->gfx.ectx) { -eglDestroyContext(qemu_egl_display, vc->gfx.ectx); -vc->gfx.ectx = NULL; -} -#endif -gd_widget_reparent(s->notebook, vc->window, vc->tab_item); - -g_signal_connect(vc->window, "delete-event", - G_CALLBACK(gd_tab_window_close), vc); -gtk_widget_show_all(vc->window); - -if (qemu_console_is_graphic(vc->gfx.dcl.con)) { -GtkAccelGroup *ag = gtk_accel_group_new(); -gtk_window_add_accel_group(GTK_WINDOW(vc->window), ag); - -GClosure *cb = g_cclosure_new_swap(G_CALLBACK(gd_win_grab), - vc, NULL); -gtk_accel_group_connect(ag, GDK_KEY_g, HOTKEY_MODIFIERS, 0, cb); -} - -gd_update_geometry_hints(vc); -gd_update_caption(s); +gd_tab_window_create(vc); } } -- 2.34.1
[PATCH] ui/gtk: Wait until the current guest frame is rendered before switching to RUN_STATE_SAVE_VM
From: Dongwon Make sure rendering of the current frame is finished before switching the run state to RUN_STATE_SAVE_VM by waiting for egl-sync object to be signaled. Cc: Marc-André Lureau Cc: Vivek Kasireddy Signed-off-by: Dongwon Kim --- ui/egl-helpers.c | 2 -- ui/gtk.c | 19 +++ 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/ui/egl-helpers.c b/ui/egl-helpers.c index 99b2ebbe23..dafeb36074 100644 --- a/ui/egl-helpers.c +++ b/ui/egl-helpers.c @@ -396,8 +396,6 @@ void egl_dmabuf_create_fence(QemuDmaBuf *dmabuf) fence_fd = eglDupNativeFenceFDANDROID(qemu_egl_display, sync); qemu_dmabuf_set_fence_fd(dmabuf, fence_fd); -eglDestroySyncKHR(qemu_egl_display, sync); -qemu_dmabuf_set_sync(dmabuf, NULL); } } diff --git a/ui/gtk.c b/ui/gtk.c index 93b13b7a30..cf0dd6abed 100644 --- a/ui/gtk.c +++ b/ui/gtk.c @@ -600,9 +600,12 @@ void gd_hw_gl_flushed(void *vcon) fence_fd = qemu_dmabuf_get_fence_fd(dmabuf); if (fence_fd >= 0) { +void *sync = qemu_dmabuf_get_sync(dmabuf); qemu_set_fd_handler(fence_fd, NULL, NULL, NULL); close(fence_fd); qemu_dmabuf_set_fence_fd(dmabuf, -1); +eglDestroySyncKHR(qemu_egl_display, sync); +qemu_dmabuf_set_sync(dmabuf, NULL); graphic_hw_gl_block(vc->gfx.dcl.con, false); } } @@ -682,6 +685,22 @@ static const DisplayGLCtxOps egl_ctx_ops = { static void gd_change_runstate(void *opaque, bool running, RunState state) { GtkDisplayState *s = opaque; +QemuDmaBuf *dmabuf; +int i; + +if (state == RUN_STATE_SAVE_VM) { +for (i = 0; i < s->nb_vcs; i++) { +VirtualConsole *vc = >vc[i]; +dmabuf = vc->gfx.guest_fb.dmabuf; +if (dmabuf && qemu_dmabuf_get_fence_fd(dmabuf) >= 0) { +/* wait for the rendering to be completed */ +eglClientWaitSync(qemu_egl_display, + qemu_dmabuf_get_sync(dmabuf), + EGL_SYNC_FLUSH_COMMANDS_BIT_KHR, + 10); +} +} +} gd_update_caption(s); } -- 2.34.1
[PATCH v14 3/6] ui/console: Use qemu_dmabuf_get_..() helpers instead
From: Dongwon Kim This commit updates all instances where fields within the QemuDmaBuf struct are directly accessed, replacing them with calls to these new helper functions. v6: fix typos in helper names in ui/spice-display.c v7: removed prefix, "dpy_gl_" from all helpers v8: Introduction of helpers was removed as those were already added by the previous commit v11: -- Use new qemu_dmabuf_close() instead of close(qemu_dmabuf_get_fd()). (Daniel P. Berrangé ) -- Use new qemu_dmabuf_dup_fd() instead of dup(qemu_dmabuf_get_fd()). (Daniel P. Berrangé ) Suggested-by: Marc-André Lureau Reviewed-by: Marc-André Lureau Cc: Philippe Mathieu-Daudé Cc: Daniel P. Berrangé Cc: Vivek Kasireddy Signed-off-by: Dongwon Kim --- hw/display/vhost-user-gpu.c | 5 +--- hw/display/virtio-gpu-udmabuf.c | 7 +++-- hw/vfio/display.c | 12 +--- ui/console.c| 4 +-- ui/dbus-console.c | 9 -- ui/dbus-listener.c | 43 +--- ui/egl-headless.c | 23 ++- ui/egl-helpers.c| 47 ++- ui/gtk-egl.c| 48 --- ui/gtk-gl-area.c| 37 ui/gtk.c| 6 ++-- ui/spice-display.c | 50 +++-- 12 files changed, 181 insertions(+), 110 deletions(-) diff --git a/hw/display/vhost-user-gpu.c b/hw/display/vhost-user-gpu.c index 709c8a02a1..454e5afcff 100644 --- a/hw/display/vhost-user-gpu.c +++ b/hw/display/vhost-user-gpu.c @@ -262,10 +262,7 @@ vhost_user_gpu_handle_display(VhostUserGPU *g, VhostUserGpuMsg *msg) g->parent_obj.enable = 1; con = g->parent_obj.scanout[m->scanout_id].con; dmabuf = >dmabuf[m->scanout_id]; -if (dmabuf->fd >= 0) { -close(dmabuf->fd); -dmabuf->fd = -1; -} +qemu_dmabuf_close(dmabuf); dpy_gl_release_dmabuf(con, dmabuf); if (fd == -1) { dpy_gl_scanout_disable(con); diff --git a/hw/display/virtio-gpu-udmabuf.c b/hw/display/virtio-gpu-udmabuf.c index d51184d658..c90eba281e 100644 --- a/hw/display/virtio-gpu-udmabuf.c +++ b/hw/display/virtio-gpu-udmabuf.c @@ -206,6 +206,7 @@ int virtio_gpu_update_dmabuf(VirtIOGPU *g, { struct virtio_gpu_scanout *scanout = >parent_obj.scanout[scanout_id]; VGPUDMABuf *new_primary, *old_primary = NULL; +uint32_t width, height; new_primary = virtio_gpu_create_dmabuf(g, scanout_id, res, fb, r); if (!new_primary) { @@ -216,10 +217,10 @@ int virtio_gpu_update_dmabuf(VirtIOGPU *g, old_primary = g->dmabuf.primary[scanout_id]; } +width = qemu_dmabuf_get_width(_primary->buf); +height = qemu_dmabuf_get_height(_primary->buf); g->dmabuf.primary[scanout_id] = new_primary; -qemu_console_resize(scanout->con, -new_primary->buf.width, -new_primary->buf.height); +qemu_console_resize(scanout->con, width, height); dpy_gl_scanout_dmabuf(scanout->con, _primary->buf); if (old_primary) { diff --git a/hw/vfio/display.c b/hw/vfio/display.c index 1aa440c663..7784502b53 100644 --- a/hw/vfio/display.c +++ b/hw/vfio/display.c @@ -260,8 +260,9 @@ static VFIODMABuf *vfio_display_get_dmabuf(VFIOPCIDevice *vdev, static void vfio_display_free_one_dmabuf(VFIODisplay *dpy, VFIODMABuf *dmabuf) { QTAILQ_REMOVE(>dmabuf.bufs, dmabuf, next); + +qemu_dmabuf_close(>buf); dpy_gl_release_dmabuf(dpy->con, >buf); -close(dmabuf->buf.fd); g_free(dmabuf); } @@ -286,6 +287,7 @@ static void vfio_display_dmabuf_update(void *opaque) VFIOPCIDevice *vdev = opaque; VFIODisplay *dpy = vdev->dpy; VFIODMABuf *primary, *cursor; +uint32_t width, height; bool free_bufs = false, new_cursor = false; primary = vfio_display_get_dmabuf(vdev, DRM_PLANE_TYPE_PRIMARY); @@ -296,10 +298,12 @@ static void vfio_display_dmabuf_update(void *opaque) return; } +width = qemu_dmabuf_get_width(>buf); +height = qemu_dmabuf_get_height(>buf); + if (dpy->dmabuf.primary != primary) { dpy->dmabuf.primary = primary; -qemu_console_resize(dpy->con, -primary->buf.width, primary->buf.height); +qemu_console_resize(dpy->con, width, height); dpy_gl_scanout_dmabuf(dpy->con, >buf); free_bufs = true; } @@ -328,7 +332,7 @@ static void vfio_display_dmabuf_update(void *opaque) cursor->pos_updates = 0; } -dpy_gl_update(dpy->con, 0, 0, primary->buf.width, primary->buf.height); +dpy_gl_update(dpy->con, 0, 0, width, height); if (free_bufs) { vfio_display_free_dmabufs(vdev); diff --git a/ui/console.c b/ui
[PATCH v14 6/6] ui/console: move QemuDmaBuf struct def to dmabuf.c
From: Dongwon Kim To complete privatizing process of QemuDmaBuf, QemuDmaBuf struct def is moved to dmabuf.c Suggested-by: Marc-André Lureau Reviewed-by: Marc-André Lureau Cc: Philippe Mathieu-Daudé Cc: Daniel P. Berrangé Cc: Vivek Kasireddy Signed-off-by: Dongwon Kim --- include/ui/dmabuf.h | 19 +-- ui/dmabuf.c | 19 +++ 2 files changed, 20 insertions(+), 18 deletions(-) diff --git a/include/ui/dmabuf.h b/include/ui/dmabuf.h index 4198cdf85a..dc74ba895a 100644 --- a/include/ui/dmabuf.h +++ b/include/ui/dmabuf.h @@ -10,24 +10,7 @@ #ifndef DMABUF_H #define DMABUF_H -typedef struct QemuDmaBuf { -int fd; -uint32_t width; -uint32_t height; -uint32_t stride; -uint32_t fourcc; -uint64_t modifier; -uint32_t texture; -uint32_t x; -uint32_t y; -uint32_t backing_width; -uint32_t backing_height; -bool y0_top; -void *sync; -int fence_fd; -bool allow_fences; -bool draw_submitted; -} QemuDmaBuf; +typedef struct QemuDmaBuf QemuDmaBuf; QemuDmaBuf *qemu_dmabuf_new(uint32_t width, uint32_t height, uint32_t stride, uint32_t x, diff --git a/ui/dmabuf.c b/ui/dmabuf.c index e047d5ca26..df7a09703f 100644 --- a/ui/dmabuf.c +++ b/ui/dmabuf.c @@ -10,6 +10,25 @@ #include "qemu/osdep.h" #include "ui/dmabuf.h" +struct QemuDmaBuf { +int fd; +uint32_t width; +uint32_t height; +uint32_t stride; +uint32_t fourcc; +uint64_t modifier; +uint32_t texture; +uint32_t x; +uint32_t y; +uint32_t backing_width; +uint32_t backing_height; +bool y0_top; +void *sync; +int fence_fd; +bool allow_fences; +bool draw_submitted; +}; + QemuDmaBuf *qemu_dmabuf_new(uint32_t width, uint32_t height, uint32_t stride, uint32_t x, uint32_t y, uint32_t backing_width, -- 2.34.1
[PATCH v14 0/6] ui/console: Private QemuDmaBuf struct
From: Dongwon Kim This series introduces privacy enhancements to the QemuDmaBuf struct and its contained data to bolster security. it accomplishes this by introducing of helper functions for allocating, deallocating, and accessing individual fields within the struct and replacing all direct references to individual fields in the struct with methods using helpers throughout the codebase. This change was made based on a suggestion from Marc-André Lureau (Resumitting same patch series with this new cover-leter) v6: fixed some typos in patch - ui/console: Introduce dpy_gl_qemu_dmabuf_get_..() helpers) v7: included minor fix (ui/gtk: Check if fence_fd is equal to or greater than 0) (Marc-André Lureau ) migrated all helpers and QemuDmaBuf struct into dmabuf.c and their prototypes to dmabuf.h for better encapsulation (ui/dmabuf: New dmabuf.c and dmabuf.h..) (Daniel P. Berrangé and Marc-André Lureau ) removed 'dpy_gl' from all helpers' names Defined autoptr clean up function for QemuDmaBuf* (Daniel P. Berrangé ) Minor corrections v8: Introduce new dmabuf.c and dmabuf.h and all helper functions in the second patch in the series (ui/console: new dmabuf.h and dmabuf.c for QemuDma) (Philippe Mathieu-Daudé ) v9: set dmabuf->allow_fences true when it is created in virtio-gpu-udmabuf removed unnecessary spaces were added in the patch, 'ui/console: Use qemu_dmabuf_new() a...' v10: Change the license type for both dmabuf.h and dmabuf.c from MIT to GPL to be in line with QEMU's default license (Daniel P. Berrangé ) v11: New helpers added - qemu_dmabuf_dup_fd, qemu_dmabuf_close for duplicating and closing dmabuf->fd. And use them in places where applicable. (Daniel P. Berrangé ) qemu_dmabuf_free helper now close dmabuf->fd before freeing the struct to prevent any potential leakage (This eliminates the need for qemu_dmabuf_close in several places as qemu_dmabuf_close is done anyway.) (Daniel P. Berrangé ) v12: --- qemu_dmabuf_free does not include qemu_dmabuf_close as there are cases where fd still needs to be used even after QemuDmaBuf struct is destroyed (virtio-gpu: res->dmabuf_fd) --- 'dmabuf' is now allocated space so it should be freed at the end of dbus_scanout_texture v13: --- Immediately free dmabuf after it is released to prevent possible leaking of the ptr (Marc-André Lureau ) --- Use g_autoptr macro to define *dmabuf for auto clean up instead of calling qemu_dmabuf_free (Marc-André Lureau ) v14: In ui/console: Use qemu_dmabuf_new() and free() helpers instead --- (vhost-user-gpu) Change qemu_dmabuf_free back to g_clear_pointer as it was done because of some misunderstanding (v13). --- (vhost-user-gpu) g->dmabuf[m->scanout_id] needs to be set to NULL to prevent freed dmabuf to be accessed again in case if(fd==-1)break; happens (before new dmabuf is allocated). Otherwise, it would cause invalid memory access when the same function is executed. Also NULL check should be done before qemu_dmabuf_close (it asserts dmabuf!=NULL.). (Marc-André Lureau ) Dongwon Kim (6): ui/gtk: Check if fence_fd is equal to or greater than 0 ui/console: new dmabuf.h and dmabuf.c for QemuDmaBuf struct and helpers ui/console: Use qemu_dmabuf_get_..() helpers instead ui/console: Use qemu_dmabuf_set_..() helpers instead ui/console: Use qemu_dmabuf_new() and free() helpers instead ui/console: move QemuDmaBuf struct def to dmabuf.c include/hw/vfio/vfio-common.h | 2 +- include/hw/virtio/virtio-gpu.h | 4 +- include/ui/console.h| 20 +-- include/ui/dmabuf.h | 49 +++ hw/display/vhost-user-gpu.c | 32 +++-- hw/display/virtio-gpu-udmabuf.c | 27 ++-- hw/vfio/display.c | 32 ++--- ui/console.c| 4 +- ui/dbus-console.c | 9 +- ui/dbus-listener.c | 71 +- ui/dmabuf.c | 229 ui/egl-headless.c | 23 +++- ui/egl-helpers.c| 59 ui/gtk-egl.c| 52 +--- ui/gtk-gl-area.c| 41 -- ui/gtk.c| 12 +- ui/spice-display.c | 50 --- ui/meson.build | 1 + 18 files changed, 524 insertions(+), 193 deletions(-) create mode 100644 include/ui/dmabuf.h create mode 100644 ui/dmabuf.c -- 2.34.1
[PATCH v14 4/6] ui/console: Use qemu_dmabuf_set_..() helpers instead
From: Dongwon Kim This commit updates all occurrences where these fields were set directly have been updated to utilize helper functions. v7: removed prefix, "dpy_gl_" from all helpers v8: Introduction of helpers was removed as those were already added by the previous commit Suggested-by: Marc-André Lureau Reviewed-by: Marc-André Lureau Cc: Philippe Mathieu-Daudé Cc: Daniel P. Berrangé Cc: Vivek Kasireddy Signed-off-by: Dongwon Kim --- ui/egl-helpers.c | 16 +--- ui/gtk-egl.c | 4 ++-- ui/gtk-gl-area.c | 4 ++-- ui/gtk.c | 6 +++--- 4 files changed, 16 insertions(+), 14 deletions(-) diff --git a/ui/egl-helpers.c b/ui/egl-helpers.c index 3f96e63d25..99b2ebbe23 100644 --- a/ui/egl-helpers.c +++ b/ui/egl-helpers.c @@ -348,8 +348,8 @@ void egl_dmabuf_import_texture(QemuDmaBuf *dmabuf) return; } -glGenTextures(1, >texture); -texture = qemu_dmabuf_get_texture(dmabuf); +glGenTextures(1, ); +qemu_dmabuf_set_texture(dmabuf, texture); glBindTexture(GL_TEXTURE_2D, texture); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); @@ -368,7 +368,7 @@ void egl_dmabuf_release_texture(QemuDmaBuf *dmabuf) } glDeleteTextures(1, ); -dmabuf->texture = 0; +qemu_dmabuf_set_texture(dmabuf, 0); } void egl_dmabuf_create_sync(QemuDmaBuf *dmabuf) @@ -382,7 +382,7 @@ void egl_dmabuf_create_sync(QemuDmaBuf *dmabuf) sync = eglCreateSyncKHR(qemu_egl_display, EGL_SYNC_NATIVE_FENCE_ANDROID, NULL); if (sync != EGL_NO_SYNC_KHR) { -dmabuf->sync = sync; +qemu_dmabuf_set_sync(dmabuf, sync); } } } @@ -390,12 +390,14 @@ void egl_dmabuf_create_sync(QemuDmaBuf *dmabuf) void egl_dmabuf_create_fence(QemuDmaBuf *dmabuf) { void *sync = qemu_dmabuf_get_sync(dmabuf); +int fence_fd; if (sync) { -dmabuf->fence_fd = eglDupNativeFenceFDANDROID(qemu_egl_display, - sync); +fence_fd = eglDupNativeFenceFDANDROID(qemu_egl_display, + sync); +qemu_dmabuf_set_fence_fd(dmabuf, fence_fd); eglDestroySyncKHR(qemu_egl_display, sync); -dmabuf->sync = NULL; +qemu_dmabuf_set_sync(dmabuf, NULL); } } diff --git a/ui/gtk-egl.c b/ui/gtk-egl.c index 7a45daefa1..ec0bf45482 100644 --- a/ui/gtk-egl.c +++ b/ui/gtk-egl.c @@ -87,7 +87,7 @@ void gd_egl_draw(VirtualConsole *vc) if (!qemu_dmabuf_get_draw_submitted(dmabuf)) { return; } else { -dmabuf->draw_submitted = false; +qemu_dmabuf_set_draw_submitted(dmabuf, false); } } #endif @@ -381,7 +381,7 @@ void gd_egl_flush(DisplayChangeListener *dcl, if (vc->gfx.guest_fb.dmabuf && !qemu_dmabuf_get_draw_submitted(vc->gfx.guest_fb.dmabuf)) { graphic_hw_gl_block(vc->gfx.dcl.con, true); -vc->gfx.guest_fb.dmabuf->draw_submitted = true; +qemu_dmabuf_set_draw_submitted(vc->gfx.guest_fb.dmabuf, true); gtk_egl_set_scanout_mode(vc, true); gtk_widget_queue_draw_area(area, x, y, w, h); return; diff --git a/ui/gtk-gl-area.c b/ui/gtk-gl-area.c index 2d70280803..9a3f3d0d71 100644 --- a/ui/gtk-gl-area.c +++ b/ui/gtk-gl-area.c @@ -63,7 +63,7 @@ void gd_gl_area_draw(VirtualConsole *vc) if (!qemu_dmabuf_get_draw_submitted(dmabuf)) { return; } else { -dmabuf->draw_submitted = false; +qemu_dmabuf_set_draw_submitted(dmabuf, false); } } #endif @@ -291,7 +291,7 @@ void gd_gl_area_scanout_flush(DisplayChangeListener *dcl, if (vc->gfx.guest_fb.dmabuf && !qemu_dmabuf_get_draw_submitted(vc->gfx.guest_fb.dmabuf)) { graphic_hw_gl_block(vc->gfx.dcl.con, true); -vc->gfx.guest_fb.dmabuf->draw_submitted = true; +qemu_dmabuf_set_draw_submitted(vc->gfx.guest_fb.dmabuf, true); gtk_gl_area_set_scanout_mode(vc, true); } gtk_gl_area_queue_render(GTK_GL_AREA(vc->gfx.drawing_area)); diff --git a/ui/gtk.c b/ui/gtk.c index 237c913b26..3a6832eb1b 100644 --- a/ui/gtk.c +++ b/ui/gtk.c @@ -598,11 +598,11 @@ void gd_hw_gl_flushed(void *vcon) QemuDmaBuf *dmabuf = vc->gfx.guest_fb.dmabuf; int fence_fd; -if (dmabuf->fence_fd >= 0) { -fence_fd = qemu_dmabuf_get_fence_fd(dmabuf); +fence_fd = qemu_dmabuf_get_fence_fd(dmabuf); +if (fence_fd >= 0) { qemu_set_fd_handler(fence_fd, NULL, NULL, NULL); close(fence_fd); -dmabuf->fence_fd = -1; +qemu_dmabuf_set_fence_fd(dmabuf, -1); graphic_hw_gl_block(vc->gfx.dcl.con, false); } } -- 2.34.1
[PATCH v14 5/6] ui/console: Use qemu_dmabuf_new() and free() helpers instead
From: Dongwon Kim This commit introduces utility functions for the creation and deallocation of QemuDmaBuf instances. Additionally, it updates all relevant sections of the codebase to utilize these new utility functions. v7: remove prefix, "dpy_gl_" from all helpers qemu_dmabuf_free() returns without doing anything if input is null (Daniel P. Berrangé ) call G_DEFINE_AUTOPTR_CLEANUP_FUNC for qemu_dmabuf_free() (Daniel P. Berrangé ) v8: Introduction of helpers was removed as those were already added by the previous commit v9: set dmabuf->allow_fences to 'true' when dmabuf is created in virtio_gpu_create_dmabuf()/virtio-gpu-udmabuf.c removed unnecessary spaces were accidently added in the patch, 'ui/console: Use qemu_dmabuf_new() a...' v11: Calling qemu_dmabuf_close was removed as closing dmabuf->fd will be done in qemu_dmabuf_free anyway. (Daniel P. Berrangé ) v12: --- Calling qemu_dmabuf_close separately as qemu_dmabuf_free doesn't do it. --- 'dmabuf' is now allocated space so it should be freed at the end of dbus_scanout_texture v13: --- Immediately free dmabuf after it is released to prevent possible leaking of the ptr (Marc-André Lureau ) --- Use g_autoptr macro to define *dmabuf for auto clean up instead of calling qemu_dmabuf_free (Marc-André Lureau ) v14: --- (vhost-user-gpu) Change qemu_dmabuf_free back to g_clear_pointer as it was done because of some misunderstanding (v13). --- (vhost-user-gpu) g->dmabuf[m->scanout_id] needs to be set to NULL to prevent freed dmabuf to be accessed again in case if(fd==-1)break; happens (before new dmabuf is allocated). Otherwise, it would cause invalid memory access when the same function is executed. Also NULL check should be done before qemu_dmabuf_close (it asserts dmabuf!=NULL.). (Marc-André Lureau ) Suggested-by: Marc-André Lureau Cc: Philippe Mathieu-Daudé Cc: Daniel P. Berrangé Cc: Vivek Kasireddy Signed-off-by: Dongwon Kim --- include/hw/vfio/vfio-common.h | 2 +- include/hw/virtio/virtio-gpu.h | 4 ++-- hw/display/vhost-user-gpu.c | 31 +++ hw/display/virtio-gpu-udmabuf.c | 24 +--- hw/vfio/display.c | 26 -- ui/dbus-listener.c | 28 6 files changed, 55 insertions(+), 60 deletions(-) diff --git a/include/hw/vfio/vfio-common.h b/include/hw/vfio/vfio-common.h index b9da6c08ef..d66e27db02 100644 --- a/include/hw/vfio/vfio-common.h +++ b/include/hw/vfio/vfio-common.h @@ -148,7 +148,7 @@ typedef struct VFIOGroup { } VFIOGroup; typedef struct VFIODMABuf { -QemuDmaBuf buf; +QemuDmaBuf *buf; uint32_t pos_x, pos_y, pos_updates; uint32_t hot_x, hot_y, hot_updates; int dmabuf_id; diff --git a/include/hw/virtio/virtio-gpu.h b/include/hw/virtio/virtio-gpu.h index ed44cdad6b..56d6e821bf 100644 --- a/include/hw/virtio/virtio-gpu.h +++ b/include/hw/virtio/virtio-gpu.h @@ -169,7 +169,7 @@ struct VirtIOGPUBaseClass { DEFINE_PROP_UINT32("yres", _state, _conf.yres, 800) typedef struct VGPUDMABuf { -QemuDmaBuf buf; +QemuDmaBuf *buf; uint32_t scanout_id; QTAILQ_ENTRY(VGPUDMABuf) next; } VGPUDMABuf; @@ -238,7 +238,7 @@ struct VhostUserGPU { VhostUserBackend *vhost; int vhost_gpu_fd; /* closed by the chardev */ CharBackend vhost_chr; -QemuDmaBuf dmabuf[VIRTIO_GPU_MAX_SCANOUTS]; +QemuDmaBuf *dmabuf[VIRTIO_GPU_MAX_SCANOUTS]; bool backend_blocked; }; diff --git a/hw/display/vhost-user-gpu.c b/hw/display/vhost-user-gpu.c index 454e5afcff..e4b398d26c 100644 --- a/hw/display/vhost-user-gpu.c +++ b/hw/display/vhost-user-gpu.c @@ -249,6 +249,7 @@ vhost_user_gpu_handle_display(VhostUserGPU *g, VhostUserGpuMsg *msg) case VHOST_USER_GPU_DMABUF_SCANOUT: { VhostUserGpuDMABUFScanout *m = >payload.dmabuf_scanout; int fd = qemu_chr_fe_get_msgfd(>vhost_chr); +uint64_t modifier = 0; QemuDmaBuf *dmabuf; if (m->scanout_id >= g->parent_obj.conf.max_outputs) { @@ -261,27 +262,33 @@ vhost_user_gpu_handle_display(VhostUserGPU *g, VhostUserGpuMsg *msg) g->parent_obj.enable = 1; con = g->parent_obj.scanout[m->scanout_id].con; -dmabuf = >dmabuf[m->scanout_id]; -qemu_dmabuf_close(dmabuf); -dpy_gl_release_dmabuf(con, dmabuf); +dmabuf = g->dmabuf[m->scanout_id]; + +if (dmabuf) { +qemu_dmabuf_close(dmabuf); +dpy_gl_release_dmabuf(con, dmabuf); +g_clear_pointer(, qemu_dmabuf_free); +} + if (fd == -1) { dpy_gl_scanout_disable(con); +g->dmabuf[m->scanout_id] = NULL; break; } -*dmabuf = (QemuDmaBuf) { -.fd =
[PATCH v14 2/6] ui/console: new dmabuf.h and dmabuf.c for QemuDmaBuf struct and helpers
From: Dongwon Kim New header and source files are added for containing QemuDmaBuf struct definition and newly introduced helpers for creating/freeing the struct and accessing its data. v10: Change the license type for both dmabuf.h and dmabuf.c from MIT to GPL to be in line with QEMU's default license v11: -- Added new helpers, qemu_dmabuf_close for closing dmabuf->fd, qemu_dmabuf_dup_fd for duplicating dmabuf->fd (Daniel P. Berrangé ) -- Let qemu_dmabuf_fee to call qemu_dmabuf_close before freeing the struct to make sure fd is closed. (Daniel P. Berrangé ) v12: Not closing fd in qemu_dmabuf_free because there are cases fd should still be available even after the struct is destroyed (e.g. virtio-gpu: res->dmabuf_fd). Suggested-by: Marc-André Lureau Reviewed-by: Marc-André Lureau Cc: Philippe Mathieu-Daudé Cc: Daniel P. Berrangé Cc: Vivek Kasireddy Signed-off-by: Dongwon Kim --- include/ui/console.h | 20 + include/ui/dmabuf.h | 66 ++ ui/dmabuf.c | 210 +++ ui/meson.build | 1 + 4 files changed, 278 insertions(+), 19 deletions(-) create mode 100644 include/ui/dmabuf.h create mode 100644 ui/dmabuf.c diff --git a/include/ui/console.h b/include/ui/console.h index 0bc7a00ac0..a208a68b88 100644 --- a/include/ui/console.h +++ b/include/ui/console.h @@ -7,6 +7,7 @@ #include "qapi/qapi-types-ui.h" #include "ui/input.h" #include "ui/surface.h" +#include "ui/dmabuf.h" #define TYPE_QEMU_CONSOLE "qemu-console" OBJECT_DECLARE_TYPE(QemuConsole, QemuConsoleClass, QEMU_CONSOLE) @@ -185,25 +186,6 @@ struct QEMUGLParams { int minor_ver; }; -typedef struct QemuDmaBuf { -int fd; -uint32_t width; -uint32_t height; -uint32_t stride; -uint32_t fourcc; -uint64_t modifier; -uint32_t texture; -uint32_t x; -uint32_t y; -uint32_t backing_width; -uint32_t backing_height; -bool y0_top; -void *sync; -int fence_fd; -bool allow_fences; -bool draw_submitted; -} QemuDmaBuf; - enum display_scanout { SCANOUT_NONE, SCANOUT_SURFACE, diff --git a/include/ui/dmabuf.h b/include/ui/dmabuf.h new file mode 100644 index 00..4198cdf85a --- /dev/null +++ b/include/ui/dmabuf.h @@ -0,0 +1,66 @@ +/* + * SPDX-License-Identifier: GPL-2.0-or-later + * + * QemuDmaBuf struct and helpers used for accessing its data + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#ifndef DMABUF_H +#define DMABUF_H + +typedef struct QemuDmaBuf { +int fd; +uint32_t width; +uint32_t height; +uint32_t stride; +uint32_t fourcc; +uint64_t modifier; +uint32_t texture; +uint32_t x; +uint32_t y; +uint32_t backing_width; +uint32_t backing_height; +bool y0_top; +void *sync; +int fence_fd; +bool allow_fences; +bool draw_submitted; +} QemuDmaBuf; + +QemuDmaBuf *qemu_dmabuf_new(uint32_t width, uint32_t height, +uint32_t stride, uint32_t x, +uint32_t y, uint32_t backing_width, +uint32_t backing_height, uint32_t fourcc, +uint64_t modifier, int dmabuf_fd, +bool allow_fences, bool y0_top); +void qemu_dmabuf_free(QemuDmaBuf *dmabuf); + +G_DEFINE_AUTOPTR_CLEANUP_FUNC(QemuDmaBuf, qemu_dmabuf_free); + +int qemu_dmabuf_get_fd(QemuDmaBuf *dmabuf); +int qemu_dmabuf_dup_fd(QemuDmaBuf *dmabuf); +void qemu_dmabuf_close(QemuDmaBuf *dmabuf); +uint32_t qemu_dmabuf_get_width(QemuDmaBuf *dmabuf); +uint32_t qemu_dmabuf_get_height(QemuDmaBuf *dmabuf); +uint32_t qemu_dmabuf_get_stride(QemuDmaBuf *dmabuf); +uint32_t qemu_dmabuf_get_fourcc(QemuDmaBuf *dmabuf); +uint64_t qemu_dmabuf_get_modifier(QemuDmaBuf *dmabuf); +uint32_t qemu_dmabuf_get_texture(QemuDmaBuf *dmabuf); +uint32_t qemu_dmabuf_get_x(QemuDmaBuf *dmabuf); +uint32_t qemu_dmabuf_get_y(QemuDmaBuf *dmabuf); +uint32_t qemu_dmabuf_get_backing_width(QemuDmaBuf *dmabuf); +uint32_t qemu_dmabuf_get_backing_height(QemuDmaBuf *dmabuf); +bool qemu_dmabuf_get_y0_top(QemuDmaBuf *dmabuf); +void *qemu_dmabuf_get_sync(QemuDmaBuf *dmabuf); +int32_t qemu_dmabuf_get_fence_fd(QemuDmaBuf *dmabuf); +bool qemu_dmabuf_get_allow_fences(QemuDmaBuf *dmabuf); +bool qemu_dmabuf_get_draw_submitted(QemuDmaBuf *dmabuf); +void qemu_dmabuf_set_texture(QemuDmaBuf *dmabuf, uint32_t texture); +void qemu_dmabuf_set_fence_fd(QemuDmaBuf *dmabuf, int32_t fence_fd); +void qemu_dmabuf_set_sync(QemuDmaBuf *dmabuf, void *sync); +void qemu_dmabuf_set_draw_submitted(QemuDmaBuf *dmabuf, bool draw_submitted); +void qemu_dmabuf_set_fd(QemuDmaBuf *dmabuf, int32_t fd); + +#endif diff --git a/ui/dmabuf.c b/ui/dmabuf.c new file mode
[PATCH v14 1/6] ui/gtk: Check if fence_fd is equal to or greater than 0
From: Dongwon Kim 'fence_fd' needs to be validated always before being referenced And the passing condition should include '== 0' as 0 is a valid value for the file descriptor. Suggested-by: Marc-André Lureau Reviewed-by: Daniel P. Berrangé Cc: Philippe Mathieu-Daudé Cc: Daniel P. Berrangé Cc: Vivek Kasireddy Signed-off-by: Dongwon Kim --- ui/gtk-egl.c | 2 +- ui/gtk-gl-area.c | 2 +- ui/gtk.c | 10 ++ 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/ui/gtk-egl.c b/ui/gtk-egl.c index 3af5ac5bcf..955234429d 100644 --- a/ui/gtk-egl.c +++ b/ui/gtk-egl.c @@ -99,7 +99,7 @@ void gd_egl_draw(VirtualConsole *vc) #ifdef CONFIG_GBM if (dmabuf) { egl_dmabuf_create_fence(dmabuf); -if (dmabuf->fence_fd > 0) { +if (dmabuf->fence_fd >= 0) { qemu_set_fd_handler(dmabuf->fence_fd, gd_hw_gl_flushed, NULL, vc); return; } diff --git a/ui/gtk-gl-area.c b/ui/gtk-gl-area.c index 52dcac161e..7fffd0544e 100644 --- a/ui/gtk-gl-area.c +++ b/ui/gtk-gl-area.c @@ -86,7 +86,7 @@ void gd_gl_area_draw(VirtualConsole *vc) #ifdef CONFIG_GBM if (dmabuf) { egl_dmabuf_create_fence(dmabuf); -if (dmabuf->fence_fd > 0) { +if (dmabuf->fence_fd >= 0) { qemu_set_fd_handler(dmabuf->fence_fd, gd_hw_gl_flushed, NULL, vc); return; } diff --git a/ui/gtk.c b/ui/gtk.c index 810d7fc796..7819a86321 100644 --- a/ui/gtk.c +++ b/ui/gtk.c @@ -597,10 +597,12 @@ void gd_hw_gl_flushed(void *vcon) VirtualConsole *vc = vcon; QemuDmaBuf *dmabuf = vc->gfx.guest_fb.dmabuf; -qemu_set_fd_handler(dmabuf->fence_fd, NULL, NULL, NULL); -close(dmabuf->fence_fd); -dmabuf->fence_fd = -1; -graphic_hw_gl_block(vc->gfx.dcl.con, false); +if (dmabuf->fence_fd >= 0) { +qemu_set_fd_handler(dmabuf->fence_fd, NULL, NULL, NULL); +close(dmabuf->fence_fd); +dmabuf->fence_fd = -1; +graphic_hw_gl_block(vc->gfx.dcl.con, false); +} } /** DisplayState Callbacks (opengl version) **/ -- 2.34.1
[PATCH v13 1/6] ui/gtk: Check if fence_fd is equal to or greater than 0
From: Dongwon Kim 'fence_fd' needs to be validated always before being referenced And the passing condition should include '== 0' as 0 is a valid value for the file descriptor. Suggested-by: Marc-André Lureau Reviewed-by: Daniel P. Berrangé Cc: Philippe Mathieu-Daudé Cc: Daniel P. Berrangé Cc: Vivek Kasireddy Signed-off-by: Dongwon Kim --- ui/gtk-egl.c | 2 +- ui/gtk-gl-area.c | 2 +- ui/gtk.c | 10 ++ 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/ui/gtk-egl.c b/ui/gtk-egl.c index 3af5ac5bcf..955234429d 100644 --- a/ui/gtk-egl.c +++ b/ui/gtk-egl.c @@ -99,7 +99,7 @@ void gd_egl_draw(VirtualConsole *vc) #ifdef CONFIG_GBM if (dmabuf) { egl_dmabuf_create_fence(dmabuf); -if (dmabuf->fence_fd > 0) { +if (dmabuf->fence_fd >= 0) { qemu_set_fd_handler(dmabuf->fence_fd, gd_hw_gl_flushed, NULL, vc); return; } diff --git a/ui/gtk-gl-area.c b/ui/gtk-gl-area.c index 52dcac161e..7fffd0544e 100644 --- a/ui/gtk-gl-area.c +++ b/ui/gtk-gl-area.c @@ -86,7 +86,7 @@ void gd_gl_area_draw(VirtualConsole *vc) #ifdef CONFIG_GBM if (dmabuf) { egl_dmabuf_create_fence(dmabuf); -if (dmabuf->fence_fd > 0) { +if (dmabuf->fence_fd >= 0) { qemu_set_fd_handler(dmabuf->fence_fd, gd_hw_gl_flushed, NULL, vc); return; } diff --git a/ui/gtk.c b/ui/gtk.c index 810d7fc796..7819a86321 100644 --- a/ui/gtk.c +++ b/ui/gtk.c @@ -597,10 +597,12 @@ void gd_hw_gl_flushed(void *vcon) VirtualConsole *vc = vcon; QemuDmaBuf *dmabuf = vc->gfx.guest_fb.dmabuf; -qemu_set_fd_handler(dmabuf->fence_fd, NULL, NULL, NULL); -close(dmabuf->fence_fd); -dmabuf->fence_fd = -1; -graphic_hw_gl_block(vc->gfx.dcl.con, false); +if (dmabuf->fence_fd >= 0) { +qemu_set_fd_handler(dmabuf->fence_fd, NULL, NULL, NULL); +close(dmabuf->fence_fd); +dmabuf->fence_fd = -1; +graphic_hw_gl_block(vc->gfx.dcl.con, false); +} } /** DisplayState Callbacks (opengl version) **/ -- 2.34.1
[PATCH v13 4/6] ui/console: Use qemu_dmabuf_set_..() helpers instead
From: Dongwon Kim This commit updates all occurrences where these fields were set directly have been updated to utilize helper functions. v7: removed prefix, "dpy_gl_" from all helpers v8: Introduction of helpers was removed as those were already added by the previous commit Suggested-by: Marc-André Lureau Reviewed-by: Marc-André Lureau Cc: Philippe Mathieu-Daudé Cc: Daniel P. Berrangé Cc: Vivek Kasireddy Signed-off-by: Dongwon Kim --- ui/egl-helpers.c | 16 +--- ui/gtk-egl.c | 4 ++-- ui/gtk-gl-area.c | 4 ++-- ui/gtk.c | 6 +++--- 4 files changed, 16 insertions(+), 14 deletions(-) diff --git a/ui/egl-helpers.c b/ui/egl-helpers.c index 3f96e63d25..99b2ebbe23 100644 --- a/ui/egl-helpers.c +++ b/ui/egl-helpers.c @@ -348,8 +348,8 @@ void egl_dmabuf_import_texture(QemuDmaBuf *dmabuf) return; } -glGenTextures(1, >texture); -texture = qemu_dmabuf_get_texture(dmabuf); +glGenTextures(1, ); +qemu_dmabuf_set_texture(dmabuf, texture); glBindTexture(GL_TEXTURE_2D, texture); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); @@ -368,7 +368,7 @@ void egl_dmabuf_release_texture(QemuDmaBuf *dmabuf) } glDeleteTextures(1, ); -dmabuf->texture = 0; +qemu_dmabuf_set_texture(dmabuf, 0); } void egl_dmabuf_create_sync(QemuDmaBuf *dmabuf) @@ -382,7 +382,7 @@ void egl_dmabuf_create_sync(QemuDmaBuf *dmabuf) sync = eglCreateSyncKHR(qemu_egl_display, EGL_SYNC_NATIVE_FENCE_ANDROID, NULL); if (sync != EGL_NO_SYNC_KHR) { -dmabuf->sync = sync; +qemu_dmabuf_set_sync(dmabuf, sync); } } } @@ -390,12 +390,14 @@ void egl_dmabuf_create_sync(QemuDmaBuf *dmabuf) void egl_dmabuf_create_fence(QemuDmaBuf *dmabuf) { void *sync = qemu_dmabuf_get_sync(dmabuf); +int fence_fd; if (sync) { -dmabuf->fence_fd = eglDupNativeFenceFDANDROID(qemu_egl_display, - sync); +fence_fd = eglDupNativeFenceFDANDROID(qemu_egl_display, + sync); +qemu_dmabuf_set_fence_fd(dmabuf, fence_fd); eglDestroySyncKHR(qemu_egl_display, sync); -dmabuf->sync = NULL; +qemu_dmabuf_set_sync(dmabuf, NULL); } } diff --git a/ui/gtk-egl.c b/ui/gtk-egl.c index 7a45daefa1..ec0bf45482 100644 --- a/ui/gtk-egl.c +++ b/ui/gtk-egl.c @@ -87,7 +87,7 @@ void gd_egl_draw(VirtualConsole *vc) if (!qemu_dmabuf_get_draw_submitted(dmabuf)) { return; } else { -dmabuf->draw_submitted = false; +qemu_dmabuf_set_draw_submitted(dmabuf, false); } } #endif @@ -381,7 +381,7 @@ void gd_egl_flush(DisplayChangeListener *dcl, if (vc->gfx.guest_fb.dmabuf && !qemu_dmabuf_get_draw_submitted(vc->gfx.guest_fb.dmabuf)) { graphic_hw_gl_block(vc->gfx.dcl.con, true); -vc->gfx.guest_fb.dmabuf->draw_submitted = true; +qemu_dmabuf_set_draw_submitted(vc->gfx.guest_fb.dmabuf, true); gtk_egl_set_scanout_mode(vc, true); gtk_widget_queue_draw_area(area, x, y, w, h); return; diff --git a/ui/gtk-gl-area.c b/ui/gtk-gl-area.c index 2d70280803..9a3f3d0d71 100644 --- a/ui/gtk-gl-area.c +++ b/ui/gtk-gl-area.c @@ -63,7 +63,7 @@ void gd_gl_area_draw(VirtualConsole *vc) if (!qemu_dmabuf_get_draw_submitted(dmabuf)) { return; } else { -dmabuf->draw_submitted = false; +qemu_dmabuf_set_draw_submitted(dmabuf, false); } } #endif @@ -291,7 +291,7 @@ void gd_gl_area_scanout_flush(DisplayChangeListener *dcl, if (vc->gfx.guest_fb.dmabuf && !qemu_dmabuf_get_draw_submitted(vc->gfx.guest_fb.dmabuf)) { graphic_hw_gl_block(vc->gfx.dcl.con, true); -vc->gfx.guest_fb.dmabuf->draw_submitted = true; +qemu_dmabuf_set_draw_submitted(vc->gfx.guest_fb.dmabuf, true); gtk_gl_area_set_scanout_mode(vc, true); } gtk_gl_area_queue_render(GTK_GL_AREA(vc->gfx.drawing_area)); diff --git a/ui/gtk.c b/ui/gtk.c index 237c913b26..3a6832eb1b 100644 --- a/ui/gtk.c +++ b/ui/gtk.c @@ -598,11 +598,11 @@ void gd_hw_gl_flushed(void *vcon) QemuDmaBuf *dmabuf = vc->gfx.guest_fb.dmabuf; int fence_fd; -if (dmabuf->fence_fd >= 0) { -fence_fd = qemu_dmabuf_get_fence_fd(dmabuf); +fence_fd = qemu_dmabuf_get_fence_fd(dmabuf); +if (fence_fd >= 0) { qemu_set_fd_handler(fence_fd, NULL, NULL, NULL); close(fence_fd); -dmabuf->fence_fd = -1; +qemu_dmabuf_set_fence_fd(dmabuf, -1); graphic_hw_gl_block(vc->gfx.dcl.con, false); } } -- 2.34.1
[PATCH v13 2/6] ui/console: new dmabuf.h and dmabuf.c for QemuDmaBuf struct and helpers
From: Dongwon Kim New header and source files are added for containing QemuDmaBuf struct definition and newly introduced helpers for creating/freeing the struct and accessing its data. v10: Change the license type for both dmabuf.h and dmabuf.c from MIT to GPL to be in line with QEMU's default license v11: -- Added new helpers, qemu_dmabuf_close for closing dmabuf->fd, qemu_dmabuf_dup_fd for duplicating dmabuf->fd (Daniel P. Berrangé ) -- Let qemu_dmabuf_fee to call qemu_dmabuf_close before freeing the struct to make sure fd is closed. (Daniel P. Berrangé ) v12: Not closing fd in qemu_dmabuf_free because there are cases fd should still be available even after the struct is destroyed (e.g. virtio-gpu: res->dmabuf_fd). Suggested-by: Marc-André Lureau Reviewed-by: Marc-André Lureau Cc: Philippe Mathieu-Daudé Cc: Daniel P. Berrangé Cc: Vivek Kasireddy Signed-off-by: Dongwon Kim --- include/ui/console.h | 20 + include/ui/dmabuf.h | 66 ++ ui/dmabuf.c | 210 +++ ui/meson.build | 1 + 4 files changed, 278 insertions(+), 19 deletions(-) create mode 100644 include/ui/dmabuf.h create mode 100644 ui/dmabuf.c diff --git a/include/ui/console.h b/include/ui/console.h index 0bc7a00ac0..a208a68b88 100644 --- a/include/ui/console.h +++ b/include/ui/console.h @@ -7,6 +7,7 @@ #include "qapi/qapi-types-ui.h" #include "ui/input.h" #include "ui/surface.h" +#include "ui/dmabuf.h" #define TYPE_QEMU_CONSOLE "qemu-console" OBJECT_DECLARE_TYPE(QemuConsole, QemuConsoleClass, QEMU_CONSOLE) @@ -185,25 +186,6 @@ struct QEMUGLParams { int minor_ver; }; -typedef struct QemuDmaBuf { -int fd; -uint32_t width; -uint32_t height; -uint32_t stride; -uint32_t fourcc; -uint64_t modifier; -uint32_t texture; -uint32_t x; -uint32_t y; -uint32_t backing_width; -uint32_t backing_height; -bool y0_top; -void *sync; -int fence_fd; -bool allow_fences; -bool draw_submitted; -} QemuDmaBuf; - enum display_scanout { SCANOUT_NONE, SCANOUT_SURFACE, diff --git a/include/ui/dmabuf.h b/include/ui/dmabuf.h new file mode 100644 index 00..4198cdf85a --- /dev/null +++ b/include/ui/dmabuf.h @@ -0,0 +1,66 @@ +/* + * SPDX-License-Identifier: GPL-2.0-or-later + * + * QemuDmaBuf struct and helpers used for accessing its data + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#ifndef DMABUF_H +#define DMABUF_H + +typedef struct QemuDmaBuf { +int fd; +uint32_t width; +uint32_t height; +uint32_t stride; +uint32_t fourcc; +uint64_t modifier; +uint32_t texture; +uint32_t x; +uint32_t y; +uint32_t backing_width; +uint32_t backing_height; +bool y0_top; +void *sync; +int fence_fd; +bool allow_fences; +bool draw_submitted; +} QemuDmaBuf; + +QemuDmaBuf *qemu_dmabuf_new(uint32_t width, uint32_t height, +uint32_t stride, uint32_t x, +uint32_t y, uint32_t backing_width, +uint32_t backing_height, uint32_t fourcc, +uint64_t modifier, int dmabuf_fd, +bool allow_fences, bool y0_top); +void qemu_dmabuf_free(QemuDmaBuf *dmabuf); + +G_DEFINE_AUTOPTR_CLEANUP_FUNC(QemuDmaBuf, qemu_dmabuf_free); + +int qemu_dmabuf_get_fd(QemuDmaBuf *dmabuf); +int qemu_dmabuf_dup_fd(QemuDmaBuf *dmabuf); +void qemu_dmabuf_close(QemuDmaBuf *dmabuf); +uint32_t qemu_dmabuf_get_width(QemuDmaBuf *dmabuf); +uint32_t qemu_dmabuf_get_height(QemuDmaBuf *dmabuf); +uint32_t qemu_dmabuf_get_stride(QemuDmaBuf *dmabuf); +uint32_t qemu_dmabuf_get_fourcc(QemuDmaBuf *dmabuf); +uint64_t qemu_dmabuf_get_modifier(QemuDmaBuf *dmabuf); +uint32_t qemu_dmabuf_get_texture(QemuDmaBuf *dmabuf); +uint32_t qemu_dmabuf_get_x(QemuDmaBuf *dmabuf); +uint32_t qemu_dmabuf_get_y(QemuDmaBuf *dmabuf); +uint32_t qemu_dmabuf_get_backing_width(QemuDmaBuf *dmabuf); +uint32_t qemu_dmabuf_get_backing_height(QemuDmaBuf *dmabuf); +bool qemu_dmabuf_get_y0_top(QemuDmaBuf *dmabuf); +void *qemu_dmabuf_get_sync(QemuDmaBuf *dmabuf); +int32_t qemu_dmabuf_get_fence_fd(QemuDmaBuf *dmabuf); +bool qemu_dmabuf_get_allow_fences(QemuDmaBuf *dmabuf); +bool qemu_dmabuf_get_draw_submitted(QemuDmaBuf *dmabuf); +void qemu_dmabuf_set_texture(QemuDmaBuf *dmabuf, uint32_t texture); +void qemu_dmabuf_set_fence_fd(QemuDmaBuf *dmabuf, int32_t fence_fd); +void qemu_dmabuf_set_sync(QemuDmaBuf *dmabuf, void *sync); +void qemu_dmabuf_set_draw_submitted(QemuDmaBuf *dmabuf, bool draw_submitted); +void qemu_dmabuf_set_fd(QemuDmaBuf *dmabuf, int32_t fd); + +#endif diff --git a/ui/dmabuf.c b/ui/dmabuf.c new file mode
[PATCH v13 5/6] ui/console: Use qemu_dmabuf_new() and free() helpers instead
From: Dongwon Kim This commit introduces utility functions for the creation and deallocation of QemuDmaBuf instances. Additionally, it updates all relevant sections of the codebase to utilize these new utility functions. v7: remove prefix, "dpy_gl_" from all helpers qemu_dmabuf_free() returns without doing anything if input is null (Daniel P. Berrangé ) call G_DEFINE_AUTOPTR_CLEANUP_FUNC for qemu_dmabuf_free() (Daniel P. Berrangé ) v8: Introduction of helpers was removed as those were already added by the previous commit v9: set dmabuf->allow_fences to 'true' when dmabuf is created in virtio_gpu_create_dmabuf()/virtio-gpu-udmabuf.c removed unnecessary spaces were accidently added in the patch, 'ui/console: Use qemu_dmabuf_new() a...' v11: Calling qemu_dmabuf_close was removed as closing dmabuf->fd will be done in qemu_dmabuf_free anyway. (Daniel P. Berrangé ) v12: --- Calling qemu_dmabuf_close separately as qemu_dmabuf_free doesn't do it. --- 'dmabuf' is now allocated space so it should be freed at the end of dbus_scanout_texture v13: --- Immediately free dmabuf after it is released to prevent possible leaking of the ptr (Marc-André Lureau ) --- Use g_autoptr macro to define *dmabuf for auto clean up instead of calling qemu_dmabuf_free (Marc-André Lureau ) Suggested-by: Marc-André Lureau Cc: Philippe Mathieu-Daudé Cc: Daniel P. Berrangé Cc: Vivek Kasireddy Signed-off-by: Dongwon Kim --- include/hw/vfio/vfio-common.h | 2 +- include/hw/virtio/virtio-gpu.h | 4 ++-- hw/display/vhost-user-gpu.c | 21 +++-- hw/display/virtio-gpu-udmabuf.c | 24 +--- hw/vfio/display.c | 26 -- ui/dbus-listener.c | 28 6 files changed, 47 insertions(+), 58 deletions(-) diff --git a/include/hw/vfio/vfio-common.h b/include/hw/vfio/vfio-common.h index b9da6c08ef..d66e27db02 100644 --- a/include/hw/vfio/vfio-common.h +++ b/include/hw/vfio/vfio-common.h @@ -148,7 +148,7 @@ typedef struct VFIOGroup { } VFIOGroup; typedef struct VFIODMABuf { -QemuDmaBuf buf; +QemuDmaBuf *buf; uint32_t pos_x, pos_y, pos_updates; uint32_t hot_x, hot_y, hot_updates; int dmabuf_id; diff --git a/include/hw/virtio/virtio-gpu.h b/include/hw/virtio/virtio-gpu.h index ed44cdad6b..56d6e821bf 100644 --- a/include/hw/virtio/virtio-gpu.h +++ b/include/hw/virtio/virtio-gpu.h @@ -169,7 +169,7 @@ struct VirtIOGPUBaseClass { DEFINE_PROP_UINT32("yres", _state, _conf.yres, 800) typedef struct VGPUDMABuf { -QemuDmaBuf buf; +QemuDmaBuf *buf; uint32_t scanout_id; QTAILQ_ENTRY(VGPUDMABuf) next; } VGPUDMABuf; @@ -238,7 +238,7 @@ struct VhostUserGPU { VhostUserBackend *vhost; int vhost_gpu_fd; /* closed by the chardev */ CharBackend vhost_chr; -QemuDmaBuf dmabuf[VIRTIO_GPU_MAX_SCANOUTS]; +QemuDmaBuf *dmabuf[VIRTIO_GPU_MAX_SCANOUTS]; bool backend_blocked; }; diff --git a/hw/display/vhost-user-gpu.c b/hw/display/vhost-user-gpu.c index 454e5afcff..744792cf78 100644 --- a/hw/display/vhost-user-gpu.c +++ b/hw/display/vhost-user-gpu.c @@ -249,6 +249,7 @@ vhost_user_gpu_handle_display(VhostUserGPU *g, VhostUserGpuMsg *msg) case VHOST_USER_GPU_DMABUF_SCANOUT: { VhostUserGpuDMABUFScanout *m = >payload.dmabuf_scanout; int fd = qemu_chr_fe_get_msgfd(>vhost_chr); +uint64_t modifier = 0; QemuDmaBuf *dmabuf; if (m->scanout_id >= g->parent_obj.conf.max_outputs) { @@ -261,27 +262,27 @@ vhost_user_gpu_handle_display(VhostUserGPU *g, VhostUserGpuMsg *msg) g->parent_obj.enable = 1; con = g->parent_obj.scanout[m->scanout_id].con; -dmabuf = >dmabuf[m->scanout_id]; +dmabuf = g->dmabuf[m->scanout_id]; qemu_dmabuf_close(dmabuf); dpy_gl_release_dmabuf(con, dmabuf); +qemu_dmabuf_free(dmabuf); if (fd == -1) { dpy_gl_scanout_disable(con); break; } -*dmabuf = (QemuDmaBuf) { -.fd = fd, -.width = m->fd_width, -.height = m->fd_height, -.stride = m->fd_stride, -.fourcc = m->fd_drm_fourcc, -.y0_top = m->fd_flags & VIRTIO_GPU_RESOURCE_FLAG_Y_0_TOP, -}; if (msg->request == VHOST_USER_GPU_DMABUF_SCANOUT2) { VhostUserGpuDMABUFScanout2 *m2 = >payload.dmabuf_scanout2; -dmabuf->modifier = m2->modifier; +modifier = m2->modifier; } +dmabuf = qemu_dmabuf_new(m->fd_width, m->fd_height, + m->fd_stride, 0, 0, 0, 0, + m->fd_drm_fourcc, modifier, + fd, false, m->fd_flags &
[PATCH v13 6/6] ui/console: move QemuDmaBuf struct def to dmabuf.c
From: Dongwon Kim To complete privatizing process of QemuDmaBuf, QemuDmaBuf struct def is moved to dmabuf.c Suggested-by: Marc-André Lureau Reviewed-by: Marc-André Lureau Cc: Philippe Mathieu-Daudé Cc: Daniel P. Berrangé Cc: Vivek Kasireddy Signed-off-by: Dongwon Kim --- include/ui/dmabuf.h | 19 +-- ui/dmabuf.c | 19 +++ 2 files changed, 20 insertions(+), 18 deletions(-) diff --git a/include/ui/dmabuf.h b/include/ui/dmabuf.h index 4198cdf85a..dc74ba895a 100644 --- a/include/ui/dmabuf.h +++ b/include/ui/dmabuf.h @@ -10,24 +10,7 @@ #ifndef DMABUF_H #define DMABUF_H -typedef struct QemuDmaBuf { -int fd; -uint32_t width; -uint32_t height; -uint32_t stride; -uint32_t fourcc; -uint64_t modifier; -uint32_t texture; -uint32_t x; -uint32_t y; -uint32_t backing_width; -uint32_t backing_height; -bool y0_top; -void *sync; -int fence_fd; -bool allow_fences; -bool draw_submitted; -} QemuDmaBuf; +typedef struct QemuDmaBuf QemuDmaBuf; QemuDmaBuf *qemu_dmabuf_new(uint32_t width, uint32_t height, uint32_t stride, uint32_t x, diff --git a/ui/dmabuf.c b/ui/dmabuf.c index e047d5ca26..df7a09703f 100644 --- a/ui/dmabuf.c +++ b/ui/dmabuf.c @@ -10,6 +10,25 @@ #include "qemu/osdep.h" #include "ui/dmabuf.h" +struct QemuDmaBuf { +int fd; +uint32_t width; +uint32_t height; +uint32_t stride; +uint32_t fourcc; +uint64_t modifier; +uint32_t texture; +uint32_t x; +uint32_t y; +uint32_t backing_width; +uint32_t backing_height; +bool y0_top; +void *sync; +int fence_fd; +bool allow_fences; +bool draw_submitted; +}; + QemuDmaBuf *qemu_dmabuf_new(uint32_t width, uint32_t height, uint32_t stride, uint32_t x, uint32_t y, uint32_t backing_width, -- 2.34.1
[PATCH v13 3/6] ui/console: Use qemu_dmabuf_get_..() helpers instead
From: Dongwon Kim This commit updates all instances where fields within the QemuDmaBuf struct are directly accessed, replacing them with calls to these new helper functions. v6: fix typos in helper names in ui/spice-display.c v7: removed prefix, "dpy_gl_" from all helpers v8: Introduction of helpers was removed as those were already added by the previous commit v11: -- Use new qemu_dmabuf_close() instead of close(qemu_dmabuf_get_fd()). (Daniel P. Berrangé ) -- Use new qemu_dmabuf_dup_fd() instead of dup(qemu_dmabuf_get_fd()). (Daniel P. Berrangé ) Suggested-by: Marc-André Lureau Reviewed-by: Marc-André Lureau Cc: Philippe Mathieu-Daudé Cc: Daniel P. Berrangé Cc: Vivek Kasireddy Signed-off-by: Dongwon Kim --- hw/display/vhost-user-gpu.c | 5 +--- hw/display/virtio-gpu-udmabuf.c | 7 +++-- hw/vfio/display.c | 12 +--- ui/console.c| 4 +-- ui/dbus-console.c | 9 -- ui/dbus-listener.c | 43 +--- ui/egl-headless.c | 23 ++- ui/egl-helpers.c| 47 ++- ui/gtk-egl.c| 48 --- ui/gtk-gl-area.c| 37 ui/gtk.c| 6 ++-- ui/spice-display.c | 50 +++-- 12 files changed, 181 insertions(+), 110 deletions(-) diff --git a/hw/display/vhost-user-gpu.c b/hw/display/vhost-user-gpu.c index 709c8a02a1..454e5afcff 100644 --- a/hw/display/vhost-user-gpu.c +++ b/hw/display/vhost-user-gpu.c @@ -262,10 +262,7 @@ vhost_user_gpu_handle_display(VhostUserGPU *g, VhostUserGpuMsg *msg) g->parent_obj.enable = 1; con = g->parent_obj.scanout[m->scanout_id].con; dmabuf = >dmabuf[m->scanout_id]; -if (dmabuf->fd >= 0) { -close(dmabuf->fd); -dmabuf->fd = -1; -} +qemu_dmabuf_close(dmabuf); dpy_gl_release_dmabuf(con, dmabuf); if (fd == -1) { dpy_gl_scanout_disable(con); diff --git a/hw/display/virtio-gpu-udmabuf.c b/hw/display/virtio-gpu-udmabuf.c index d51184d658..c90eba281e 100644 --- a/hw/display/virtio-gpu-udmabuf.c +++ b/hw/display/virtio-gpu-udmabuf.c @@ -206,6 +206,7 @@ int virtio_gpu_update_dmabuf(VirtIOGPU *g, { struct virtio_gpu_scanout *scanout = >parent_obj.scanout[scanout_id]; VGPUDMABuf *new_primary, *old_primary = NULL; +uint32_t width, height; new_primary = virtio_gpu_create_dmabuf(g, scanout_id, res, fb, r); if (!new_primary) { @@ -216,10 +217,10 @@ int virtio_gpu_update_dmabuf(VirtIOGPU *g, old_primary = g->dmabuf.primary[scanout_id]; } +width = qemu_dmabuf_get_width(_primary->buf); +height = qemu_dmabuf_get_height(_primary->buf); g->dmabuf.primary[scanout_id] = new_primary; -qemu_console_resize(scanout->con, -new_primary->buf.width, -new_primary->buf.height); +qemu_console_resize(scanout->con, width, height); dpy_gl_scanout_dmabuf(scanout->con, _primary->buf); if (old_primary) { diff --git a/hw/vfio/display.c b/hw/vfio/display.c index 1aa440c663..7784502b53 100644 --- a/hw/vfio/display.c +++ b/hw/vfio/display.c @@ -260,8 +260,9 @@ static VFIODMABuf *vfio_display_get_dmabuf(VFIOPCIDevice *vdev, static void vfio_display_free_one_dmabuf(VFIODisplay *dpy, VFIODMABuf *dmabuf) { QTAILQ_REMOVE(>dmabuf.bufs, dmabuf, next); + +qemu_dmabuf_close(>buf); dpy_gl_release_dmabuf(dpy->con, >buf); -close(dmabuf->buf.fd); g_free(dmabuf); } @@ -286,6 +287,7 @@ static void vfio_display_dmabuf_update(void *opaque) VFIOPCIDevice *vdev = opaque; VFIODisplay *dpy = vdev->dpy; VFIODMABuf *primary, *cursor; +uint32_t width, height; bool free_bufs = false, new_cursor = false; primary = vfio_display_get_dmabuf(vdev, DRM_PLANE_TYPE_PRIMARY); @@ -296,10 +298,12 @@ static void vfio_display_dmabuf_update(void *opaque) return; } +width = qemu_dmabuf_get_width(>buf); +height = qemu_dmabuf_get_height(>buf); + if (dpy->dmabuf.primary != primary) { dpy->dmabuf.primary = primary; -qemu_console_resize(dpy->con, -primary->buf.width, primary->buf.height); +qemu_console_resize(dpy->con, width, height); dpy_gl_scanout_dmabuf(dpy->con, >buf); free_bufs = true; } @@ -328,7 +332,7 @@ static void vfio_display_dmabuf_update(void *opaque) cursor->pos_updates = 0; } -dpy_gl_update(dpy->con, 0, 0, primary->buf.width, primary->buf.height); +dpy_gl_update(dpy->con, 0, 0, width, height); if (free_bufs) { vfio_display_free_dmabufs(vdev); diff --git a/ui/console.c b/ui
[PATCH v13 0/6] ui/console: Private QemuDmaBuf struct
From: Your Name This series introduces privacy enhancements to the QemuDmaBuf struct and its contained data to bolster security. it accomplishes this by introducing of helper functions for allocating, deallocating, and accessing individual fields within the struct and replacing all direct references to individual fields in the struct with methods using helpers throughout the codebase. This change was made based on a suggestion from Marc-André Lureau (Resumitting same patch series with this new cover-leter) v6: fixed some typos in patch - ui/console: Introduce dpy_gl_qemu_dmabuf_get_..() helpers) v7: included minor fix (ui/gtk: Check if fence_fd is equal to or greater than 0) (Marc-André Lureau ) migrated all helpers and QemuDmaBuf struct into dmabuf.c and their prototypes to dmabuf.h for better encapsulation (ui/dmabuf: New dmabuf.c and dmabuf.h..) (Daniel P. Berrangé and Marc-André Lureau ) removed 'dpy_gl' from all helpers' names Defined autoptr clean up function for QemuDmaBuf* (Daniel P. Berrangé ) Minor corrections v8: Introduce new dmabuf.c and dmabuf.h and all helper functions in the second patch in the series (ui/console: new dmabuf.h and dmabuf.c for QemuDma) (Philippe Mathieu-Daudé ) v9: set dmabuf->allow_fences true when it is created in virtio-gpu-udmabuf removed unnecessary spaces were added in the patch, 'ui/console: Use qemu_dmabuf_new() a...' v10: Change the license type for both dmabuf.h and dmabuf.c from MIT to GPL to be in line with QEMU's default license (Daniel P. Berrangé ) v11: New helpers added - qemu_dmabuf_dup_fd, qemu_dmabuf_close for duplicating and closing dmabuf->fd. And use them in places where applicable. (Daniel P. Berrangé ) qemu_dmabuf_free helper now close dmabuf->fd before freeing the struct to prevent any potential leakage (This eliminates the need for qemu_dmabuf_close in several places as qemu_dmabuf_close is done anyway.) (Daniel P. Berrangé ) v12: --- qemu_dmabuf_free does not include qemu_dmabuf_close as there are cases where fd still needs to be used even after QemuDmaBuf struct is destroyed (virtio-gpu: res->dmabuf_fd) --- 'dmabuf' is now allocated space so it should be freed at the end of dbus_scanout_texture v13: --- Immediately free dmabuf after it is released to prevent possible leaking of the ptr (Marc-André Lureau ) --- Use g_autoptr macro to define *dmabuf for auto clean up instead of calling qemu_dmabuf_free (Marc-André Lureau ) Dongwon Kim (6): ui/gtk: Check if fence_fd is equal to or greater than 0 ui/console: new dmabuf.h and dmabuf.c for QemuDmaBuf struct and helpers ui/console: Use qemu_dmabuf_get_..() helpers instead ui/console: Use qemu_dmabuf_set_..() helpers instead ui/console: Use qemu_dmabuf_new() and free() helpers instead ui/console: move QemuDmaBuf struct def to dmabuf.c include/hw/vfio/vfio-common.h | 2 +- include/hw/virtio/virtio-gpu.h | 4 +- include/ui/console.h| 20 +-- include/ui/dmabuf.h | 49 +++ hw/display/vhost-user-gpu.c | 26 ++-- hw/display/virtio-gpu-udmabuf.c | 27 ++-- hw/vfio/display.c | 32 ++--- ui/console.c| 4 +- ui/dbus-console.c | 9 +- ui/dbus-listener.c | 71 +- ui/dmabuf.c | 229 ui/egl-headless.c | 23 +++- ui/egl-helpers.c| 59 ui/gtk-egl.c| 52 +--- ui/gtk-gl-area.c| 41 -- ui/gtk.c| 12 +- ui/spice-display.c | 50 --- ui/meson.build | 1 + 18 files changed, 518 insertions(+), 193 deletions(-) create mode 100644 include/ui/dmabuf.h create mode 100644 ui/dmabuf.c -- 2.34.1
[PATCH] ui/gtk: Explicitly set the default size of new window when untabifying
From: Dongwon Kim When untabifying, the default size of the new window was inadvertently set to the size smaller than quarter of the primary window size due to lack of explicit configuration. This commit addresses the issue by ensuring that the size of untabified windows is set to match the surface size. Cc: Gerd Hoffmann Cc: Marc-André Lureau Cc: Vivek Kasireddy Signed-off-by: Dongwon Kim --- ui/gtk.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ui/gtk.c b/ui/gtk.c index 810d7fc796..269b8207d7 100644 --- a/ui/gtk.c +++ b/ui/gtk.c @@ -1395,6 +1395,9 @@ static void gd_menu_untabify(GtkMenuItem *item, void *opaque) if (!vc->window) { gtk_widget_set_sensitive(vc->menu_item, false); vc->window = gtk_window_new(GTK_WINDOW_TOPLEVEL); +gtk_window_set_default_size(GTK_WINDOW(vc->window), +surface_width(vc->gfx.ds), +surface_height(vc->gfx.ds)); #if defined(CONFIG_OPENGL) if (vc->gfx.esurface) { eglDestroySurface(qemu_egl_display, vc->gfx.esurface); -- 2.34.1
[PATCH v2] ui/gtk: Draw guest frame at refresh cycle
From: Dongwon Kim Draw routine needs to be manually invoked in the next refresh if there is a scanout blob from the guest. This is to prevent a situation where there is a scheduled draw event but it won't happen bacause the window is currently in inactive state (minimized or tabified). If draw is not done for a long time, gl_block timeout and/or fence timeout (on the guest) will happen eventually. v2: Use gd_gl_area_draw(vc) in gtk-gl-area.c Suggested-by: Vivek Kasireddy Cc: Gerd Hoffmann Cc: Marc-André Lureau Cc: Daniel P. Berrangé Signed-off-by: Dongwon Kim --- ui/gtk-egl.c | 1 + ui/gtk-gl-area.c | 1 + 2 files changed, 2 insertions(+) diff --git a/ui/gtk-egl.c b/ui/gtk-egl.c index 3af5ac5bcf..75f6b9011a 100644 --- a/ui/gtk-egl.c +++ b/ui/gtk-egl.c @@ -150,6 +150,7 @@ void gd_egl_refresh(DisplayChangeListener *dcl) vc, vc->window ? vc->window : vc->gfx.drawing_area); if (vc->gfx.guest_fb.dmabuf && vc->gfx.guest_fb.dmabuf->draw_submitted) { +gd_egl_draw(vc); return; } diff --git a/ui/gtk-gl-area.c b/ui/gtk-gl-area.c index 52dcac161e..4fff957c3f 100644 --- a/ui/gtk-gl-area.c +++ b/ui/gtk-gl-area.c @@ -126,6 +126,7 @@ void gd_gl_area_refresh(DisplayChangeListener *dcl) gd_update_monitor_refresh_rate(vc, vc->window ? vc->window : vc->gfx.drawing_area); if (vc->gfx.guest_fb.dmabuf && vc->gfx.guest_fb.dmabuf->draw_submitted) { +gd_gl_area_draw(vc); return; } -- 2.34.1
[PATCH] ui/gtk: Draw guest frame at refresh cycle
From: Dongwon Kim Draw routine needs to be manually invoked in the next refresh if there is a scanout blob from the guest. This is to prevent a situation where there is a scheduled draw event but it won't happen bacause the window is currently in inactive state (minimized or tabified). If draw is not done for a long time, gl_block timeout and/or fence timeout (on the guest) will happen eventually. Suggested-by: Vivek Kasireddy Cc: Gerd Hoffmann Cc: Marc-André Lureau Cc: Daniel P. Berrangé Signed-off-by: Dongwon Kim --- ui/gtk-egl.c | 1 + ui/gtk-gl-area.c | 1 + 2 files changed, 2 insertions(+) diff --git a/ui/gtk-egl.c b/ui/gtk-egl.c index 3af5ac5bcf..75f6b9011a 100644 --- a/ui/gtk-egl.c +++ b/ui/gtk-egl.c @@ -150,6 +150,7 @@ void gd_egl_refresh(DisplayChangeListener *dcl) vc, vc->window ? vc->window : vc->gfx.drawing_area); if (vc->gfx.guest_fb.dmabuf && vc->gfx.guest_fb.dmabuf->draw_submitted) { +gd_egl_draw(vc); return; } diff --git a/ui/gtk-gl-area.c b/ui/gtk-gl-area.c index 52dcac161e..7b4ba37b78 100644 --- a/ui/gtk-gl-area.c +++ b/ui/gtk-gl-area.c @@ -126,6 +126,7 @@ void gd_gl_area_refresh(DisplayChangeListener *dcl) gd_update_monitor_refresh_rate(vc, vc->window ? vc->window : vc->gfx.drawing_area); if (vc->gfx.guest_fb.dmabuf && vc->gfx.guest_fb.dmabuf->draw_submitted) { +gd_egl_draw(vc); return; } -- 2.34.1
[PATCH v12 4/6] ui/console: Use qemu_dmabuf_set_..() helpers instead
From: Dongwon Kim This commit updates all occurrences where these fields were set directly have been updated to utilize helper functions. v7: removed prefix, "dpy_gl_" from all helpers v8: Introduction of helpers was removed as those were already added by the previous commit Suggested-by: Marc-André Lureau Cc: Philippe Mathieu-Daudé Cc: Daniel P. Berrangé Cc: Vivek Kasireddy Signed-off-by: Dongwon Kim --- ui/egl-helpers.c | 16 +--- ui/gtk-egl.c | 4 ++-- ui/gtk-gl-area.c | 4 ++-- ui/gtk.c | 6 +++--- 4 files changed, 16 insertions(+), 14 deletions(-) diff --git a/ui/egl-helpers.c b/ui/egl-helpers.c index 3f96e63d25..99b2ebbe23 100644 --- a/ui/egl-helpers.c +++ b/ui/egl-helpers.c @@ -348,8 +348,8 @@ void egl_dmabuf_import_texture(QemuDmaBuf *dmabuf) return; } -glGenTextures(1, >texture); -texture = qemu_dmabuf_get_texture(dmabuf); +glGenTextures(1, ); +qemu_dmabuf_set_texture(dmabuf, texture); glBindTexture(GL_TEXTURE_2D, texture); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); @@ -368,7 +368,7 @@ void egl_dmabuf_release_texture(QemuDmaBuf *dmabuf) } glDeleteTextures(1, ); -dmabuf->texture = 0; +qemu_dmabuf_set_texture(dmabuf, 0); } void egl_dmabuf_create_sync(QemuDmaBuf *dmabuf) @@ -382,7 +382,7 @@ void egl_dmabuf_create_sync(QemuDmaBuf *dmabuf) sync = eglCreateSyncKHR(qemu_egl_display, EGL_SYNC_NATIVE_FENCE_ANDROID, NULL); if (sync != EGL_NO_SYNC_KHR) { -dmabuf->sync = sync; +qemu_dmabuf_set_sync(dmabuf, sync); } } } @@ -390,12 +390,14 @@ void egl_dmabuf_create_sync(QemuDmaBuf *dmabuf) void egl_dmabuf_create_fence(QemuDmaBuf *dmabuf) { void *sync = qemu_dmabuf_get_sync(dmabuf); +int fence_fd; if (sync) { -dmabuf->fence_fd = eglDupNativeFenceFDANDROID(qemu_egl_display, - sync); +fence_fd = eglDupNativeFenceFDANDROID(qemu_egl_display, + sync); +qemu_dmabuf_set_fence_fd(dmabuf, fence_fd); eglDestroySyncKHR(qemu_egl_display, sync); -dmabuf->sync = NULL; +qemu_dmabuf_set_sync(dmabuf, NULL); } } diff --git a/ui/gtk-egl.c b/ui/gtk-egl.c index 7a45daefa1..ec0bf45482 100644 --- a/ui/gtk-egl.c +++ b/ui/gtk-egl.c @@ -87,7 +87,7 @@ void gd_egl_draw(VirtualConsole *vc) if (!qemu_dmabuf_get_draw_submitted(dmabuf)) { return; } else { -dmabuf->draw_submitted = false; +qemu_dmabuf_set_draw_submitted(dmabuf, false); } } #endif @@ -381,7 +381,7 @@ void gd_egl_flush(DisplayChangeListener *dcl, if (vc->gfx.guest_fb.dmabuf && !qemu_dmabuf_get_draw_submitted(vc->gfx.guest_fb.dmabuf)) { graphic_hw_gl_block(vc->gfx.dcl.con, true); -vc->gfx.guest_fb.dmabuf->draw_submitted = true; +qemu_dmabuf_set_draw_submitted(vc->gfx.guest_fb.dmabuf, true); gtk_egl_set_scanout_mode(vc, true); gtk_widget_queue_draw_area(area, x, y, w, h); return; diff --git a/ui/gtk-gl-area.c b/ui/gtk-gl-area.c index 2d70280803..9a3f3d0d71 100644 --- a/ui/gtk-gl-area.c +++ b/ui/gtk-gl-area.c @@ -63,7 +63,7 @@ void gd_gl_area_draw(VirtualConsole *vc) if (!qemu_dmabuf_get_draw_submitted(dmabuf)) { return; } else { -dmabuf->draw_submitted = false; +qemu_dmabuf_set_draw_submitted(dmabuf, false); } } #endif @@ -291,7 +291,7 @@ void gd_gl_area_scanout_flush(DisplayChangeListener *dcl, if (vc->gfx.guest_fb.dmabuf && !qemu_dmabuf_get_draw_submitted(vc->gfx.guest_fb.dmabuf)) { graphic_hw_gl_block(vc->gfx.dcl.con, true); -vc->gfx.guest_fb.dmabuf->draw_submitted = true; +qemu_dmabuf_set_draw_submitted(vc->gfx.guest_fb.dmabuf, true); gtk_gl_area_set_scanout_mode(vc, true); } gtk_gl_area_queue_render(GTK_GL_AREA(vc->gfx.drawing_area)); diff --git a/ui/gtk.c b/ui/gtk.c index 237c913b26..3a6832eb1b 100644 --- a/ui/gtk.c +++ b/ui/gtk.c @@ -598,11 +598,11 @@ void gd_hw_gl_flushed(void *vcon) QemuDmaBuf *dmabuf = vc->gfx.guest_fb.dmabuf; int fence_fd; -if (dmabuf->fence_fd >= 0) { -fence_fd = qemu_dmabuf_get_fence_fd(dmabuf); +fence_fd = qemu_dmabuf_get_fence_fd(dmabuf); +if (fence_fd >= 0) { qemu_set_fd_handler(fence_fd, NULL, NULL, NULL); close(fence_fd); -dmabuf->fence_fd = -1; +qemu_dmabuf_set_fence_fd(dmabuf, -1); graphic_hw_gl_block(vc->gfx.dcl.con, false); } } -- 2.34.1
[PATCH v12 2/6] ui/console: new dmabuf.h and dmabuf.c for QemuDmaBuf struct and helpers
From: Dongwon Kim New header and source files are added for containing QemuDmaBuf struct definition and newly introduced helpers for creating/freeing the struct and accessing its data. v10: Change the license type for both dmabuf.h and dmabuf.c from MIT to GPL to be in line with QEMU's default license v11: -- Added new helpers, qemu_dmabuf_close for closing dmabuf->fd, qemu_dmabuf_dup_fd for duplicating dmabuf->fd (Daniel P. Berrangé ) -- Let qemu_dmabuf_fee to call qemu_dmabuf_close before freeing the struct to make sure fd is closed. (Daniel P. Berrangé ) v12: Not closing fd in qemu_dmabuf_free because there are cases fd should still be available even after the struct is destroyed (e.g. virtio-gpu: res->dmabuf_fd). Suggested-by: Marc-André Lureau Cc: Philippe Mathieu-Daudé Cc: Daniel P. Berrangé Cc: Vivek Kasireddy Signed-off-by: Dongwon Kim --- include/ui/console.h | 20 + include/ui/dmabuf.h | 66 ++ ui/dmabuf.c | 210 +++ ui/meson.build | 1 + 4 files changed, 278 insertions(+), 19 deletions(-) create mode 100644 include/ui/dmabuf.h create mode 100644 ui/dmabuf.c diff --git a/include/ui/console.h b/include/ui/console.h index 0bc7a00ac0..a208a68b88 100644 --- a/include/ui/console.h +++ b/include/ui/console.h @@ -7,6 +7,7 @@ #include "qapi/qapi-types-ui.h" #include "ui/input.h" #include "ui/surface.h" +#include "ui/dmabuf.h" #define TYPE_QEMU_CONSOLE "qemu-console" OBJECT_DECLARE_TYPE(QemuConsole, QemuConsoleClass, QEMU_CONSOLE) @@ -185,25 +186,6 @@ struct QEMUGLParams { int minor_ver; }; -typedef struct QemuDmaBuf { -int fd; -uint32_t width; -uint32_t height; -uint32_t stride; -uint32_t fourcc; -uint64_t modifier; -uint32_t texture; -uint32_t x; -uint32_t y; -uint32_t backing_width; -uint32_t backing_height; -bool y0_top; -void *sync; -int fence_fd; -bool allow_fences; -bool draw_submitted; -} QemuDmaBuf; - enum display_scanout { SCANOUT_NONE, SCANOUT_SURFACE, diff --git a/include/ui/dmabuf.h b/include/ui/dmabuf.h new file mode 100644 index 00..4198cdf85a --- /dev/null +++ b/include/ui/dmabuf.h @@ -0,0 +1,66 @@ +/* + * SPDX-License-Identifier: GPL-2.0-or-later + * + * QemuDmaBuf struct and helpers used for accessing its data + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#ifndef DMABUF_H +#define DMABUF_H + +typedef struct QemuDmaBuf { +int fd; +uint32_t width; +uint32_t height; +uint32_t stride; +uint32_t fourcc; +uint64_t modifier; +uint32_t texture; +uint32_t x; +uint32_t y; +uint32_t backing_width; +uint32_t backing_height; +bool y0_top; +void *sync; +int fence_fd; +bool allow_fences; +bool draw_submitted; +} QemuDmaBuf; + +QemuDmaBuf *qemu_dmabuf_new(uint32_t width, uint32_t height, +uint32_t stride, uint32_t x, +uint32_t y, uint32_t backing_width, +uint32_t backing_height, uint32_t fourcc, +uint64_t modifier, int dmabuf_fd, +bool allow_fences, bool y0_top); +void qemu_dmabuf_free(QemuDmaBuf *dmabuf); + +G_DEFINE_AUTOPTR_CLEANUP_FUNC(QemuDmaBuf, qemu_dmabuf_free); + +int qemu_dmabuf_get_fd(QemuDmaBuf *dmabuf); +int qemu_dmabuf_dup_fd(QemuDmaBuf *dmabuf); +void qemu_dmabuf_close(QemuDmaBuf *dmabuf); +uint32_t qemu_dmabuf_get_width(QemuDmaBuf *dmabuf); +uint32_t qemu_dmabuf_get_height(QemuDmaBuf *dmabuf); +uint32_t qemu_dmabuf_get_stride(QemuDmaBuf *dmabuf); +uint32_t qemu_dmabuf_get_fourcc(QemuDmaBuf *dmabuf); +uint64_t qemu_dmabuf_get_modifier(QemuDmaBuf *dmabuf); +uint32_t qemu_dmabuf_get_texture(QemuDmaBuf *dmabuf); +uint32_t qemu_dmabuf_get_x(QemuDmaBuf *dmabuf); +uint32_t qemu_dmabuf_get_y(QemuDmaBuf *dmabuf); +uint32_t qemu_dmabuf_get_backing_width(QemuDmaBuf *dmabuf); +uint32_t qemu_dmabuf_get_backing_height(QemuDmaBuf *dmabuf); +bool qemu_dmabuf_get_y0_top(QemuDmaBuf *dmabuf); +void *qemu_dmabuf_get_sync(QemuDmaBuf *dmabuf); +int32_t qemu_dmabuf_get_fence_fd(QemuDmaBuf *dmabuf); +bool qemu_dmabuf_get_allow_fences(QemuDmaBuf *dmabuf); +bool qemu_dmabuf_get_draw_submitted(QemuDmaBuf *dmabuf); +void qemu_dmabuf_set_texture(QemuDmaBuf *dmabuf, uint32_t texture); +void qemu_dmabuf_set_fence_fd(QemuDmaBuf *dmabuf, int32_t fence_fd); +void qemu_dmabuf_set_sync(QemuDmaBuf *dmabuf, void *sync); +void qemu_dmabuf_set_draw_submitted(QemuDmaBuf *dmabuf, bool draw_submitted); +void qemu_dmabuf_set_fd(QemuDmaBuf *dmabuf, int32_t fd); + +#endif diff --git a/ui/dmabuf.c b/ui/dmabuf.c new file mode 100644 index 00
[PATCH v12 5/6] ui/console: Use qemu_dmabuf_new() and free() helpers instead
From: Dongwon Kim This commit introduces utility functions for the creation and deallocation of QemuDmaBuf instances. Additionally, it updates all relevant sections of the codebase to utilize these new utility functions. v7: remove prefix, "dpy_gl_" from all helpers qemu_dmabuf_free() returns without doing anything if input is null (Daniel P. Berrangé ) call G_DEFINE_AUTOPTR_CLEANUP_FUNC for qemu_dmabuf_free() (Daniel P. Berrangé ) v8: Introduction of helpers was removed as those were already added by the previous commit v9: set dmabuf->allow_fences to 'true' when dmabuf is created in virtio_gpu_create_dmabuf()/virtio-gpu-udmabuf.c removed unnecessary spaces were accidently added in the patch, 'ui/console: Use qemu_dmabuf_new() a...' v11: Calling qemu_dmabuf_close was removed as closing dmabuf->fd will be done in qemu_dmabuf_free anyway. (Daniel P. Berrangé ) v12: --- Calling qemu_dmabuf_close separately as qemu_dmabuf_free doesn't do it. --- 'dmabuf' is now allocated space so it should be freed at the end of dbus_scanout_texture Suggested-by: Marc-André Lureau Cc: Philippe Mathieu-Daudé Cc: Daniel P. Berrangé Cc: Vivek Kasireddy Signed-off-by: Dongwon Kim --- include/hw/vfio/vfio-common.h | 2 +- include/hw/virtio/virtio-gpu.h | 4 ++-- hw/display/vhost-user-gpu.c | 21 +++-- hw/display/virtio-gpu-udmabuf.c | 24 +--- hw/vfio/display.c | 26 -- ui/dbus-listener.c | 29 + 6 files changed, 48 insertions(+), 58 deletions(-) diff --git a/include/hw/vfio/vfio-common.h b/include/hw/vfio/vfio-common.h index b9da6c08ef..d66e27db02 100644 --- a/include/hw/vfio/vfio-common.h +++ b/include/hw/vfio/vfio-common.h @@ -148,7 +148,7 @@ typedef struct VFIOGroup { } VFIOGroup; typedef struct VFIODMABuf { -QemuDmaBuf buf; +QemuDmaBuf *buf; uint32_t pos_x, pos_y, pos_updates; uint32_t hot_x, hot_y, hot_updates; int dmabuf_id; diff --git a/include/hw/virtio/virtio-gpu.h b/include/hw/virtio/virtio-gpu.h index ed44cdad6b..56d6e821bf 100644 --- a/include/hw/virtio/virtio-gpu.h +++ b/include/hw/virtio/virtio-gpu.h @@ -169,7 +169,7 @@ struct VirtIOGPUBaseClass { DEFINE_PROP_UINT32("yres", _state, _conf.yres, 800) typedef struct VGPUDMABuf { -QemuDmaBuf buf; +QemuDmaBuf *buf; uint32_t scanout_id; QTAILQ_ENTRY(VGPUDMABuf) next; } VGPUDMABuf; @@ -238,7 +238,7 @@ struct VhostUserGPU { VhostUserBackend *vhost; int vhost_gpu_fd; /* closed by the chardev */ CharBackend vhost_chr; -QemuDmaBuf dmabuf[VIRTIO_GPU_MAX_SCANOUTS]; +QemuDmaBuf *dmabuf[VIRTIO_GPU_MAX_SCANOUTS]; bool backend_blocked; }; diff --git a/hw/display/vhost-user-gpu.c b/hw/display/vhost-user-gpu.c index 454e5afcff..62e7b4376b 100644 --- a/hw/display/vhost-user-gpu.c +++ b/hw/display/vhost-user-gpu.c @@ -249,6 +249,7 @@ vhost_user_gpu_handle_display(VhostUserGPU *g, VhostUserGpuMsg *msg) case VHOST_USER_GPU_DMABUF_SCANOUT: { VhostUserGpuDMABUFScanout *m = >payload.dmabuf_scanout; int fd = qemu_chr_fe_get_msgfd(>vhost_chr); +uint64_t modifier = 0; QemuDmaBuf *dmabuf; if (m->scanout_id >= g->parent_obj.conf.max_outputs) { @@ -261,27 +262,27 @@ vhost_user_gpu_handle_display(VhostUserGPU *g, VhostUserGpuMsg *msg) g->parent_obj.enable = 1; con = g->parent_obj.scanout[m->scanout_id].con; -dmabuf = >dmabuf[m->scanout_id]; +dmabuf = g->dmabuf[m->scanout_id]; qemu_dmabuf_close(dmabuf); dpy_gl_release_dmabuf(con, dmabuf); +g_clear_pointer(, qemu_dmabuf_free); if (fd == -1) { dpy_gl_scanout_disable(con); break; } -*dmabuf = (QemuDmaBuf) { -.fd = fd, -.width = m->fd_width, -.height = m->fd_height, -.stride = m->fd_stride, -.fourcc = m->fd_drm_fourcc, -.y0_top = m->fd_flags & VIRTIO_GPU_RESOURCE_FLAG_Y_0_TOP, -}; if (msg->request == VHOST_USER_GPU_DMABUF_SCANOUT2) { VhostUserGpuDMABUFScanout2 *m2 = >payload.dmabuf_scanout2; -dmabuf->modifier = m2->modifier; +modifier = m2->modifier; } +dmabuf = qemu_dmabuf_new(m->fd_width, m->fd_height, + m->fd_stride, 0, 0, 0, 0, + m->fd_drm_fourcc, modifier, + fd, false, m->fd_flags & + VIRTIO_GPU_RESOURCE_FLAG_Y_0_TOP); + dpy_gl_scanout_dmabuf(con, dmabuf); +g->dmabuf[m->scanout_id] = dmabuf; break; } case VHOST_USER_GPU_DMABUF_UPDATE: { diff --git a/hw/display/virtio-gpu-udmab
[PATCH v12 6/6] ui/console: move QemuDmaBuf struct def to dmabuf.c
From: Dongwon Kim To complete privatizing process of QemuDmaBuf, QemuDmaBuf struct def is moved to dmabuf.c Suggested-by: Marc-André Lureau Cc: Philippe Mathieu-Daudé Cc: Daniel P. Berrangé Cc: Vivek Kasireddy Signed-off-by: Dongwon Kim --- include/ui/dmabuf.h | 19 +-- ui/dmabuf.c | 19 +++ 2 files changed, 20 insertions(+), 18 deletions(-) diff --git a/include/ui/dmabuf.h b/include/ui/dmabuf.h index 4198cdf85a..dc74ba895a 100644 --- a/include/ui/dmabuf.h +++ b/include/ui/dmabuf.h @@ -10,24 +10,7 @@ #ifndef DMABUF_H #define DMABUF_H -typedef struct QemuDmaBuf { -int fd; -uint32_t width; -uint32_t height; -uint32_t stride; -uint32_t fourcc; -uint64_t modifier; -uint32_t texture; -uint32_t x; -uint32_t y; -uint32_t backing_width; -uint32_t backing_height; -bool y0_top; -void *sync; -int fence_fd; -bool allow_fences; -bool draw_submitted; -} QemuDmaBuf; +typedef struct QemuDmaBuf QemuDmaBuf; QemuDmaBuf *qemu_dmabuf_new(uint32_t width, uint32_t height, uint32_t stride, uint32_t x, diff --git a/ui/dmabuf.c b/ui/dmabuf.c index e047d5ca26..df7a09703f 100644 --- a/ui/dmabuf.c +++ b/ui/dmabuf.c @@ -10,6 +10,25 @@ #include "qemu/osdep.h" #include "ui/dmabuf.h" +struct QemuDmaBuf { +int fd; +uint32_t width; +uint32_t height; +uint32_t stride; +uint32_t fourcc; +uint64_t modifier; +uint32_t texture; +uint32_t x; +uint32_t y; +uint32_t backing_width; +uint32_t backing_height; +bool y0_top; +void *sync; +int fence_fd; +bool allow_fences; +bool draw_submitted; +}; + QemuDmaBuf *qemu_dmabuf_new(uint32_t width, uint32_t height, uint32_t stride, uint32_t x, uint32_t y, uint32_t backing_width, -- 2.34.1
[PATCH v12 0/6] ui/console: Private QemuDmaBuf struct
From: Dongwon Kim This series introduces privacy enhancements to the QemuDmaBuf struct and its contained data to bolster security. it accomplishes this by introducing of helper functions for allocating, deallocating, and accessing individual fields within the struct and replacing all direct references to individual fields in the struct with methods using helpers throughout the codebase. This change was made based on a suggestion from Marc-André Lureau (Resumitting same patch series with this new cover-leter) v6: fixed some typos in patch - ui/console: Introduce dpy_gl_qemu_dmabuf_get_..() helpers) v7: included minor fix (ui/gtk: Check if fence_fd is equal to or greater than 0) (Marc-André Lureau ) migrated all helpers and QemuDmaBuf struct into dmabuf.c and their prototypes to dmabuf.h for better encapsulation (ui/dmabuf: New dmabuf.c and dmabuf.h..) (Daniel P. Berrangé and Marc-André Lureau ) removed 'dpy_gl' from all helpers' names Defined autoptr clean up function for QemuDmaBuf* (Daniel P. Berrangé ) Minor corrections v8: Introduce new dmabuf.c and dmabuf.h and all helper functions in the second patch in the series (ui/console: new dmabuf.h and dmabuf.c for QemuDma) (Philippe Mathieu-Daudé ) v9: set dmabuf->allow_fences true when it is created in virtio-gpu-udmabuf removed unnecessary spaces were added in the patch, 'ui/console: Use qemu_dmabuf_new() a...' v10: Change the license type for both dmabuf.h and dmabuf.c from MIT to GPL to be in line with QEMU's default license (Daniel P. Berrangé ) v11: New helpers added - qemu_dmabuf_dup_fd, qemu_dmabuf_close for duplicating and closing dmabuf->fd. And use them in places where applicable. (Daniel P. Berrangé ) qemu_dmabuf_free helper now close dmabuf->fd before freeing the struct to prevent any potential leakage (This eliminates the need for qemu_dmabuf_close in several places as qemu_dmabuf_close is done anyway.) (Daniel P. Berrangé ) v12: --- qemu_dmabuf_free does not include qemu_dmabuf_close as there are cases where fd still needs to be used even after QemuDmaBuf struct is destroyed (virtio-gpu: res->dmabuf_fd) --- 'dmabuf' is now allocated space so it should be freed at the end of dbus_scanout_texture Dongwon Kim (6): ui/gtk: Check if fence_fd is equal to or greater than 0 ui/console: new dmabuf.h and dmabuf.c for QemuDmaBuf struct and helpers ui/console: Use qemu_dmabuf_get_..() helpers instead ui/console: Use qemu_dmabuf_set_..() helpers instead ui/console: Use qemu_dmabuf_new() and free() helpers instead ui/console: move QemuDmaBuf struct def to dmabuf.c include/hw/vfio/vfio-common.h | 2 +- include/hw/virtio/virtio-gpu.h | 4 +- include/ui/console.h| 20 +-- include/ui/dmabuf.h | 49 +++ hw/display/vhost-user-gpu.c | 26 ++-- hw/display/virtio-gpu-udmabuf.c | 27 ++-- hw/vfio/display.c | 32 ++--- ui/console.c| 4 +- ui/dbus-console.c | 9 +- ui/dbus-listener.c | 72 +- ui/dmabuf.c | 229 ui/egl-headless.c | 23 +++- ui/egl-helpers.c| 59 ui/gtk-egl.c| 52 +--- ui/gtk-gl-area.c| 41 -- ui/gtk.c| 12 +- ui/spice-display.c | 50 --- ui/meson.build | 1 + 18 files changed, 519 insertions(+), 193 deletions(-) create mode 100644 include/ui/dmabuf.h create mode 100644 ui/dmabuf.c -- 2.34.1
[PATCH v12 3/6] ui/console: Use qemu_dmabuf_get_..() helpers instead
From: Dongwon Kim This commit updates all instances where fields within the QemuDmaBuf struct are directly accessed, replacing them with calls to these new helper functions. v6: fix typos in helper names in ui/spice-display.c v7: removed prefix, "dpy_gl_" from all helpers v8: Introduction of helpers was removed as those were already added by the previous commit v11: -- Use new qemu_dmabuf_close() instead of close(qemu_dmabuf_get_fd()). (Daniel P. Berrangé ) -- Use new qemu_dmabuf_dup_fd() instead of dup(qemu_dmabuf_get_fd()). (Daniel P. Berrangé ) Suggested-by: Marc-André Lureau Reviewed-by: Marc-André Lureau Cc: Philippe Mathieu-Daudé Cc: Daniel P. Berrangé Cc: Vivek Kasireddy Signed-off-by: Dongwon Kim --- hw/display/vhost-user-gpu.c | 5 +--- hw/display/virtio-gpu-udmabuf.c | 7 +++-- hw/vfio/display.c | 12 +--- ui/console.c| 4 +-- ui/dbus-console.c | 9 -- ui/dbus-listener.c | 43 +--- ui/egl-headless.c | 23 ++- ui/egl-helpers.c| 47 ++- ui/gtk-egl.c| 48 --- ui/gtk-gl-area.c| 37 ui/gtk.c| 6 ++-- ui/spice-display.c | 50 +++-- 12 files changed, 181 insertions(+), 110 deletions(-) diff --git a/hw/display/vhost-user-gpu.c b/hw/display/vhost-user-gpu.c index 709c8a02a1..454e5afcff 100644 --- a/hw/display/vhost-user-gpu.c +++ b/hw/display/vhost-user-gpu.c @@ -262,10 +262,7 @@ vhost_user_gpu_handle_display(VhostUserGPU *g, VhostUserGpuMsg *msg) g->parent_obj.enable = 1; con = g->parent_obj.scanout[m->scanout_id].con; dmabuf = >dmabuf[m->scanout_id]; -if (dmabuf->fd >= 0) { -close(dmabuf->fd); -dmabuf->fd = -1; -} +qemu_dmabuf_close(dmabuf); dpy_gl_release_dmabuf(con, dmabuf); if (fd == -1) { dpy_gl_scanout_disable(con); diff --git a/hw/display/virtio-gpu-udmabuf.c b/hw/display/virtio-gpu-udmabuf.c index d51184d658..c90eba281e 100644 --- a/hw/display/virtio-gpu-udmabuf.c +++ b/hw/display/virtio-gpu-udmabuf.c @@ -206,6 +206,7 @@ int virtio_gpu_update_dmabuf(VirtIOGPU *g, { struct virtio_gpu_scanout *scanout = >parent_obj.scanout[scanout_id]; VGPUDMABuf *new_primary, *old_primary = NULL; +uint32_t width, height; new_primary = virtio_gpu_create_dmabuf(g, scanout_id, res, fb, r); if (!new_primary) { @@ -216,10 +217,10 @@ int virtio_gpu_update_dmabuf(VirtIOGPU *g, old_primary = g->dmabuf.primary[scanout_id]; } +width = qemu_dmabuf_get_width(_primary->buf); +height = qemu_dmabuf_get_height(_primary->buf); g->dmabuf.primary[scanout_id] = new_primary; -qemu_console_resize(scanout->con, -new_primary->buf.width, -new_primary->buf.height); +qemu_console_resize(scanout->con, width, height); dpy_gl_scanout_dmabuf(scanout->con, _primary->buf); if (old_primary) { diff --git a/hw/vfio/display.c b/hw/vfio/display.c index 1aa440c663..7784502b53 100644 --- a/hw/vfio/display.c +++ b/hw/vfio/display.c @@ -260,8 +260,9 @@ static VFIODMABuf *vfio_display_get_dmabuf(VFIOPCIDevice *vdev, static void vfio_display_free_one_dmabuf(VFIODisplay *dpy, VFIODMABuf *dmabuf) { QTAILQ_REMOVE(>dmabuf.bufs, dmabuf, next); + +qemu_dmabuf_close(>buf); dpy_gl_release_dmabuf(dpy->con, >buf); -close(dmabuf->buf.fd); g_free(dmabuf); } @@ -286,6 +287,7 @@ static void vfio_display_dmabuf_update(void *opaque) VFIOPCIDevice *vdev = opaque; VFIODisplay *dpy = vdev->dpy; VFIODMABuf *primary, *cursor; +uint32_t width, height; bool free_bufs = false, new_cursor = false; primary = vfio_display_get_dmabuf(vdev, DRM_PLANE_TYPE_PRIMARY); @@ -296,10 +298,12 @@ static void vfio_display_dmabuf_update(void *opaque) return; } +width = qemu_dmabuf_get_width(>buf); +height = qemu_dmabuf_get_height(>buf); + if (dpy->dmabuf.primary != primary) { dpy->dmabuf.primary = primary; -qemu_console_resize(dpy->con, -primary->buf.width, primary->buf.height); +qemu_console_resize(dpy->con, width, height); dpy_gl_scanout_dmabuf(dpy->con, >buf); free_bufs = true; } @@ -328,7 +332,7 @@ static void vfio_display_dmabuf_update(void *opaque) cursor->pos_updates = 0; } -dpy_gl_update(dpy->con, 0, 0, primary->buf.width, primary->buf.height); +dpy_gl_update(dpy->con, 0, 0, width, height); if (free_bufs) { vfio_display_free_dmabufs(vdev); diff --git a/ui/console.c b/ui
[PATCH v12 1/6] ui/gtk: Check if fence_fd is equal to or greater than 0
From: Dongwon Kim 'fence_fd' needs to be validated always before being referenced And the passing condition should include '== 0' as 0 is a valid value for the file descriptor. Suggested-by: Marc-André Lureau Reviewed-by: Daniel P. Berrangé Cc: Philippe Mathieu-Daudé Cc: Daniel P. Berrangé Cc: Vivek Kasireddy Signed-off-by: Dongwon Kim --- ui/gtk-egl.c | 2 +- ui/gtk-gl-area.c | 2 +- ui/gtk.c | 10 ++ 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/ui/gtk-egl.c b/ui/gtk-egl.c index 3af5ac5bcf..955234429d 100644 --- a/ui/gtk-egl.c +++ b/ui/gtk-egl.c @@ -99,7 +99,7 @@ void gd_egl_draw(VirtualConsole *vc) #ifdef CONFIG_GBM if (dmabuf) { egl_dmabuf_create_fence(dmabuf); -if (dmabuf->fence_fd > 0) { +if (dmabuf->fence_fd >= 0) { qemu_set_fd_handler(dmabuf->fence_fd, gd_hw_gl_flushed, NULL, vc); return; } diff --git a/ui/gtk-gl-area.c b/ui/gtk-gl-area.c index 52dcac161e..7fffd0544e 100644 --- a/ui/gtk-gl-area.c +++ b/ui/gtk-gl-area.c @@ -86,7 +86,7 @@ void gd_gl_area_draw(VirtualConsole *vc) #ifdef CONFIG_GBM if (dmabuf) { egl_dmabuf_create_fence(dmabuf); -if (dmabuf->fence_fd > 0) { +if (dmabuf->fence_fd >= 0) { qemu_set_fd_handler(dmabuf->fence_fd, gd_hw_gl_flushed, NULL, vc); return; } diff --git a/ui/gtk.c b/ui/gtk.c index 810d7fc796..7819a86321 100644 --- a/ui/gtk.c +++ b/ui/gtk.c @@ -597,10 +597,12 @@ void gd_hw_gl_flushed(void *vcon) VirtualConsole *vc = vcon; QemuDmaBuf *dmabuf = vc->gfx.guest_fb.dmabuf; -qemu_set_fd_handler(dmabuf->fence_fd, NULL, NULL, NULL); -close(dmabuf->fence_fd); -dmabuf->fence_fd = -1; -graphic_hw_gl_block(vc->gfx.dcl.con, false); +if (dmabuf->fence_fd >= 0) { +qemu_set_fd_handler(dmabuf->fence_fd, NULL, NULL, NULL); +close(dmabuf->fence_fd); +dmabuf->fence_fd = -1; +graphic_hw_gl_block(vc->gfx.dcl.con, false); +} } /** DisplayState Callbacks (opengl version) **/ -- 2.34.1
[PATCH v11 2/6] ui/console: new dmabuf.h and dmabuf.c for QemuDmaBuf struct and helpers
From: Dongwon Kim New header and source files are added for containing QemuDmaBuf struct definition and newly introduced helpers for creating/freeing the struct and accessing its data. v10: Change the license type for both dmabuf.h and dmabuf.c from MIT to GPL to be in line with QEMU's default license v11: -- Added new helpers, qemu_dmabuf_close for closing dmabuf->fd, qemu_dmabuf_dup_fd for duplicating dmabuf->fd (Daniel P. Berrangé ) -- Let qemu_dmabuf_fee to call qemu_dmabuf_close before freeing the struct to make sure fd is closed. (Daniel P. Berrangé ) Suggested-by: Marc-André Lureau Cc: Philippe Mathieu-Daudé Cc: Daniel P. Berrangé Cc: Vivek Kasireddy Signed-off-by: Dongwon Kim --- include/ui/console.h | 20 +--- include/ui/dmabuf.h | 66 ++ ui/dmabuf.c | 211 +++ ui/meson.build | 1 + 4 files changed, 279 insertions(+), 19 deletions(-) create mode 100644 include/ui/dmabuf.h create mode 100644 ui/dmabuf.c diff --git a/include/ui/console.h b/include/ui/console.h index 0bc7a00ac0..a208a68b88 100644 --- a/include/ui/console.h +++ b/include/ui/console.h @@ -7,6 +7,7 @@ #include "qapi/qapi-types-ui.h" #include "ui/input.h" #include "ui/surface.h" +#include "ui/dmabuf.h" #define TYPE_QEMU_CONSOLE "qemu-console" OBJECT_DECLARE_TYPE(QemuConsole, QemuConsoleClass, QEMU_CONSOLE) @@ -185,25 +186,6 @@ struct QEMUGLParams { int minor_ver; }; -typedef struct QemuDmaBuf { -int fd; -uint32_t width; -uint32_t height; -uint32_t stride; -uint32_t fourcc; -uint64_t modifier; -uint32_t texture; -uint32_t x; -uint32_t y; -uint32_t backing_width; -uint32_t backing_height; -bool y0_top; -void *sync; -int fence_fd; -bool allow_fences; -bool draw_submitted; -} QemuDmaBuf; - enum display_scanout { SCANOUT_NONE, SCANOUT_SURFACE, diff --git a/include/ui/dmabuf.h b/include/ui/dmabuf.h new file mode 100644 index 00..ba7cd3754a --- /dev/null +++ b/include/ui/dmabuf.h @@ -0,0 +1,66 @@ +/* + * SPDX-License-Identifier: GPL-2.0-or-later + * + * QemuDmaBuf struct and helpers used for accessing its data + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#ifndef DMABUF_H +#define DMABUF_H + +typedef struct QemuDmaBuf { +int fd; +uint32_t width; +uint32_t height; +uint32_t stride; +uint32_t fourcc; +uint64_t modifier; +uint32_t texture; +uint32_t x; +uint32_t y; +uint32_t backing_width; +uint32_t backing_height; +bool y0_top; +void *sync; +int fence_fd; +bool allow_fences; +bool draw_submitted; +} QemuDmaBuf; + +QemuDmaBuf *qemu_dmabuf_new(uint32_t width, uint32_t height, +uint32_t stride, uint32_t x, +uint32_t y, uint32_t backing_width, +uint32_t backing_height, uint32_t fourcc, +uint64_t modifier, int dmabuf_fd, +bool allow_fences, bool y0_top); +void qemu_dmabuf_free(QemuDmaBuf *dmabuf); + +G_DEFINE_AUTOPTR_CLEANUP_FUNC(QemuDmaBuf, qemu_dmabuf_free); + +int qemu_dmabuf_get_fd(QemuDmaBuf *dmabuf); +int qemu_dmabuf_dup_fd(QemuDmaBuf *dmabuf); +void qemu_dmabuf_close(QemuDmaBuf *dmabuf); +uint32_t qemu_dmabuf_get_width(QemuDmaBuf *dmabuf); +uint32_t qemu_dmabuf_get_height(QemuDmaBuf *dmabuf); +uint32_t qemu_dmabuf_get_stride(QemuDmaBuf *dmabuf); +uint32_t qemu_dmabuf_get_fourcc(QemuDmaBuf *dmabuf); +uint64_t qemu_dmabuf_get_modifier(QemuDmaBuf *dmabuf); +uint32_t qemu_dmabuf_get_texture(QemuDmaBuf *dmabuf); +uint32_t qemu_dmabuf_get_x(QemuDmaBuf *dmabuf); +uint32_t qemu_dmabuf_get_y(QemuDmaBuf *dmabuf); +uint32_t qemu_dmabuf_get_backing_width(QemuDmaBuf *dmabuf); +uint32_t qemu_dmabuf_get_backing_height(QemuDmaBuf *dmabuf); +bool qemu_dmabuf_get_y0_top(QemuDmaBuf *dmabuf); +void *qemu_dmabuf_get_sync(QemuDmaBuf *dmabuf); +int32_t qemu_dmabuf_get_fence_fd(QemuDmaBuf *dmabuf); +bool qemu_dmabuf_get_allow_fences(QemuDmaBuf *dmabuf); +bool qemu_dmabuf_get_draw_submitted(QemuDmaBuf *dmabuf); +void qemu_dmabuf_set_texture(QemuDmaBuf *dmabuf, uint32_t texture); +void qemu_dmabuf_set_fence_fd(QemuDmaBuf *dmabuf, int32_t fence_fd); +void qemu_dmabuf_set_sync(QemuDmaBuf *dmabuf, void *sync); +void qemu_dmabuf_set_draw_submitted(QemuDmaBuf *dmabuf, bool draw_submitted); +void qemu_dmabuf_set_fd(QemuDmaBuf *dmabuf, int32_t fd); + +#endif diff --git a/ui/dmabuf.c b/ui/dmabuf.c new file mode 100644 index 00..40f3ed33bf --- /dev/null +++ b/ui/dmabuf.c @@ -0,0 +1,211 @@ +/* + * SPDX-License-Identifier: GPL-2.0-or-later + * + * QemuDmaBuf struct and helpers used for accessing its data + *
[PATCH v11 6/6] ui/console: move QemuDmaBuf struct def to dmabuf.c
From: Dongwon Kim To complete privatizing process of QemuDmaBuf, QemuDmaBuf struct def is moved to dmabuf.c Suggested-by: Marc-André Lureau Cc: Philippe Mathieu-Daudé Cc: Daniel P. Berrangé Cc: Vivek Kasireddy Signed-off-by: Dongwon Kim --- include/ui/dmabuf.h | 19 +-- ui/dmabuf.c | 19 +++ 2 files changed, 20 insertions(+), 18 deletions(-) diff --git a/include/ui/dmabuf.h b/include/ui/dmabuf.h index ba7cd3754a..d1f5a946c0 100644 --- a/include/ui/dmabuf.h +++ b/include/ui/dmabuf.h @@ -10,24 +10,7 @@ #ifndef DMABUF_H #define DMABUF_H -typedef struct QemuDmaBuf { -int fd; -uint32_t width; -uint32_t height; -uint32_t stride; -uint32_t fourcc; -uint64_t modifier; -uint32_t texture; -uint32_t x; -uint32_t y; -uint32_t backing_width; -uint32_t backing_height; -bool y0_top; -void *sync; -int fence_fd; -bool allow_fences; -bool draw_submitted; -} QemuDmaBuf; +typedef struct QemuDmaBuf QemuDmaBuf; QemuDmaBuf *qemu_dmabuf_new(uint32_t width, uint32_t height, uint32_t stride, uint32_t x, diff --git a/ui/dmabuf.c b/ui/dmabuf.c index 40f3ed33bf..411e1b6f97 100644 --- a/ui/dmabuf.c +++ b/ui/dmabuf.c @@ -10,6 +10,25 @@ #include "qemu/osdep.h" #include "ui/dmabuf.h" +struct QemuDmaBuf { +int fd; +uint32_t width; +uint32_t height; +uint32_t stride; +uint32_t fourcc; +uint64_t modifier; +uint32_t texture; +uint32_t x; +uint32_t y; +uint32_t backing_width; +uint32_t backing_height; +bool y0_top; +void *sync; +int fence_fd; +bool allow_fences; +bool draw_submitted; +}; + QemuDmaBuf *qemu_dmabuf_new(uint32_t width, uint32_t height, uint32_t stride, uint32_t x, uint32_t y, uint32_t backing_width, -- 2.34.1
[PATCH v11 5/6] ui/console: Use qemu_dmabuf_new() and free() helpers instead
From: Dongwon Kim This commit introduces utility functions for the creation and deallocation of QemuDmaBuf instances. Additionally, it updates all relevant sections of the codebase to utilize these new utility functions. v7: remove prefix, "dpy_gl_" from all helpers qemu_dmabuf_free() returns without doing anything if input is null (Daniel P. Berrangé ) call G_DEFINE_AUTOPTR_CLEANUP_FUNC for qemu_dmabuf_free() (Daniel P. Berrangé ) v8: Introduction of helpers was removed as those were already added by the previous commit v9: set dmabuf->allow_fences to 'true' when dmabuf is created in virtio_gpu_create_dmabuf()/virtio-gpu-udmabuf.c removed unnecessary spaces were accidently added in the patch, 'ui/console: Use qemu_dmabuf_new() a...' v11: Calling qemu_dmabuf_close was removed as closing dmabuf->fd will be done in qemu_dmabuf_free anyway. (Daniel P. Berrangé ) Suggested-by: Marc-André Lureau Cc: Philippe Mathieu-Daudé Cc: Daniel P. Berrangé Cc: Vivek Kasireddy Signed-off-by: Dongwon Kim --- include/hw/vfio/vfio-common.h | 2 +- include/hw/virtio/virtio-gpu.h | 4 ++-- hw/display/vhost-user-gpu.c | 22 +++--- hw/display/virtio-gpu-udmabuf.c | 24 +--- hw/vfio/display.c | 25 +++-- ui/dbus-listener.c | 28 6 files changed, 46 insertions(+), 59 deletions(-) diff --git a/include/hw/vfio/vfio-common.h b/include/hw/vfio/vfio-common.h index b9da6c08ef..d66e27db02 100644 --- a/include/hw/vfio/vfio-common.h +++ b/include/hw/vfio/vfio-common.h @@ -148,7 +148,7 @@ typedef struct VFIOGroup { } VFIOGroup; typedef struct VFIODMABuf { -QemuDmaBuf buf; +QemuDmaBuf *buf; uint32_t pos_x, pos_y, pos_updates; uint32_t hot_x, hot_y, hot_updates; int dmabuf_id; diff --git a/include/hw/virtio/virtio-gpu.h b/include/hw/virtio/virtio-gpu.h index ed44cdad6b..56d6e821bf 100644 --- a/include/hw/virtio/virtio-gpu.h +++ b/include/hw/virtio/virtio-gpu.h @@ -169,7 +169,7 @@ struct VirtIOGPUBaseClass { DEFINE_PROP_UINT32("yres", _state, _conf.yres, 800) typedef struct VGPUDMABuf { -QemuDmaBuf buf; +QemuDmaBuf *buf; uint32_t scanout_id; QTAILQ_ENTRY(VGPUDMABuf) next; } VGPUDMABuf; @@ -238,7 +238,7 @@ struct VhostUserGPU { VhostUserBackend *vhost; int vhost_gpu_fd; /* closed by the chardev */ CharBackend vhost_chr; -QemuDmaBuf dmabuf[VIRTIO_GPU_MAX_SCANOUTS]; +QemuDmaBuf *dmabuf[VIRTIO_GPU_MAX_SCANOUTS]; bool backend_blocked; }; diff --git a/hw/display/vhost-user-gpu.c b/hw/display/vhost-user-gpu.c index 454e5afcff..173189ae7c 100644 --- a/hw/display/vhost-user-gpu.c +++ b/hw/display/vhost-user-gpu.c @@ -249,6 +249,7 @@ vhost_user_gpu_handle_display(VhostUserGPU *g, VhostUserGpuMsg *msg) case VHOST_USER_GPU_DMABUF_SCANOUT: { VhostUserGpuDMABUFScanout *m = >payload.dmabuf_scanout; int fd = qemu_chr_fe_get_msgfd(>vhost_chr); +uint64_t modifier = 0; QemuDmaBuf *dmabuf; if (m->scanout_id >= g->parent_obj.conf.max_outputs) { @@ -261,27 +262,26 @@ vhost_user_gpu_handle_display(VhostUserGPU *g, VhostUserGpuMsg *msg) g->parent_obj.enable = 1; con = g->parent_obj.scanout[m->scanout_id].con; -dmabuf = >dmabuf[m->scanout_id]; -qemu_dmabuf_close(dmabuf); +dmabuf = g->dmabuf[m->scanout_id]; dpy_gl_release_dmabuf(con, dmabuf); +g_clear_pointer(, qemu_dmabuf_free); if (fd == -1) { dpy_gl_scanout_disable(con); break; } -*dmabuf = (QemuDmaBuf) { -.fd = fd, -.width = m->fd_width, -.height = m->fd_height, -.stride = m->fd_stride, -.fourcc = m->fd_drm_fourcc, -.y0_top = m->fd_flags & VIRTIO_GPU_RESOURCE_FLAG_Y_0_TOP, -}; if (msg->request == VHOST_USER_GPU_DMABUF_SCANOUT2) { VhostUserGpuDMABUFScanout2 *m2 = >payload.dmabuf_scanout2; -dmabuf->modifier = m2->modifier; +modifier = m2->modifier; } +dmabuf = qemu_dmabuf_new(m->fd_width, m->fd_height, + m->fd_stride, 0, 0, 0, 0, + m->fd_drm_fourcc, modifier, + fd, false, m->fd_flags & + VIRTIO_GPU_RESOURCE_FLAG_Y_0_TOP); + dpy_gl_scanout_dmabuf(con, dmabuf); +g->dmabuf[m->scanout_id] = dmabuf; break; } case VHOST_USER_GPU_DMABUF_UPDATE: { diff --git a/hw/display/virtio-gpu-udmabuf.c b/hw/display/virtio-gpu-udmabuf.c index c90eba281e..c02ec6d37d 100644 --- a/hw/display/virtio-gpu-udmabuf.c +++ b/hw/display/virtio-gpu-udmabuf.c @@ -162,7 +162,8 @@ static void virtio_gpu_fre
[PATCH v11 3/6] ui/console: Use qemu_dmabuf_get_..() helpers instead
From: Dongwon Kim This commit updates all instances where fields within the QemuDmaBuf struct are directly accessed, replacing them with calls to these new helper functions. v6: fix typos in helper names in ui/spice-display.c v7: removed prefix, "dpy_gl_" from all helpers v8: Introduction of helpers was removed as those were already added by the previous commit v11: -- Use new qemu_dmabuf_close() instead of close(qemu_dmabuf_get_fd()). (Daniel P. Berrangé ) -- Use new qemu_dmabuf_dup_fd() instead of dup(qemu_dmabuf_get_fd()). (Daniel P. Berrangé ) Suggested-by: Marc-André Lureau Reviewed-by: Marc-André Lureau Cc: Philippe Mathieu-Daudé Cc: Daniel P. Berrangé Cc: Vivek Kasireddy Signed-off-by: Dongwon Kim --- hw/display/vhost-user-gpu.c | 5 +--- hw/display/virtio-gpu-udmabuf.c | 7 +++-- hw/vfio/display.c | 12 +--- ui/console.c| 4 +-- ui/dbus-console.c | 9 -- ui/dbus-listener.c | 43 +--- ui/egl-headless.c | 23 ++- ui/egl-helpers.c| 47 ++- ui/gtk-egl.c| 48 --- ui/gtk-gl-area.c| 37 ui/gtk.c| 6 ++-- ui/spice-display.c | 50 +++-- 12 files changed, 181 insertions(+), 110 deletions(-) diff --git a/hw/display/vhost-user-gpu.c b/hw/display/vhost-user-gpu.c index 709c8a02a1..454e5afcff 100644 --- a/hw/display/vhost-user-gpu.c +++ b/hw/display/vhost-user-gpu.c @@ -262,10 +262,7 @@ vhost_user_gpu_handle_display(VhostUserGPU *g, VhostUserGpuMsg *msg) g->parent_obj.enable = 1; con = g->parent_obj.scanout[m->scanout_id].con; dmabuf = >dmabuf[m->scanout_id]; -if (dmabuf->fd >= 0) { -close(dmabuf->fd); -dmabuf->fd = -1; -} +qemu_dmabuf_close(dmabuf); dpy_gl_release_dmabuf(con, dmabuf); if (fd == -1) { dpy_gl_scanout_disable(con); diff --git a/hw/display/virtio-gpu-udmabuf.c b/hw/display/virtio-gpu-udmabuf.c index d51184d658..c90eba281e 100644 --- a/hw/display/virtio-gpu-udmabuf.c +++ b/hw/display/virtio-gpu-udmabuf.c @@ -206,6 +206,7 @@ int virtio_gpu_update_dmabuf(VirtIOGPU *g, { struct virtio_gpu_scanout *scanout = >parent_obj.scanout[scanout_id]; VGPUDMABuf *new_primary, *old_primary = NULL; +uint32_t width, height; new_primary = virtio_gpu_create_dmabuf(g, scanout_id, res, fb, r); if (!new_primary) { @@ -216,10 +217,10 @@ int virtio_gpu_update_dmabuf(VirtIOGPU *g, old_primary = g->dmabuf.primary[scanout_id]; } +width = qemu_dmabuf_get_width(_primary->buf); +height = qemu_dmabuf_get_height(_primary->buf); g->dmabuf.primary[scanout_id] = new_primary; -qemu_console_resize(scanout->con, -new_primary->buf.width, -new_primary->buf.height); +qemu_console_resize(scanout->con, width, height); dpy_gl_scanout_dmabuf(scanout->con, _primary->buf); if (old_primary) { diff --git a/hw/vfio/display.c b/hw/vfio/display.c index 1aa440c663..7784502b53 100644 --- a/hw/vfio/display.c +++ b/hw/vfio/display.c @@ -260,8 +260,9 @@ static VFIODMABuf *vfio_display_get_dmabuf(VFIOPCIDevice *vdev, static void vfio_display_free_one_dmabuf(VFIODisplay *dpy, VFIODMABuf *dmabuf) { QTAILQ_REMOVE(>dmabuf.bufs, dmabuf, next); + +qemu_dmabuf_close(>buf); dpy_gl_release_dmabuf(dpy->con, >buf); -close(dmabuf->buf.fd); g_free(dmabuf); } @@ -286,6 +287,7 @@ static void vfio_display_dmabuf_update(void *opaque) VFIOPCIDevice *vdev = opaque; VFIODisplay *dpy = vdev->dpy; VFIODMABuf *primary, *cursor; +uint32_t width, height; bool free_bufs = false, new_cursor = false; primary = vfio_display_get_dmabuf(vdev, DRM_PLANE_TYPE_PRIMARY); @@ -296,10 +298,12 @@ static void vfio_display_dmabuf_update(void *opaque) return; } +width = qemu_dmabuf_get_width(>buf); +height = qemu_dmabuf_get_height(>buf); + if (dpy->dmabuf.primary != primary) { dpy->dmabuf.primary = primary; -qemu_console_resize(dpy->con, -primary->buf.width, primary->buf.height); +qemu_console_resize(dpy->con, width, height); dpy_gl_scanout_dmabuf(dpy->con, >buf); free_bufs = true; } @@ -328,7 +332,7 @@ static void vfio_display_dmabuf_update(void *opaque) cursor->pos_updates = 0; } -dpy_gl_update(dpy->con, 0, 0, primary->buf.width, primary->buf.height); +dpy_gl_update(dpy->con, 0, 0, width, height); if (free_bufs) { vfio_display_free_dmabufs(vdev); diff --git a/ui/console.c b/ui
[PATCH v11 1/6] ui/gtk: Check if fence_fd is equal to or greater than 0
From: Dongwon Kim 'fence_fd' needs to be validated always before being referenced And the passing condition should include '== 0' as 0 is a valid value for the file descriptor. Suggested-by: Marc-André Lureau Reviewed-by: Daniel P. Berrangé Cc: Philippe Mathieu-Daudé Cc: Daniel P. Berrangé Cc: Vivek Kasireddy Signed-off-by: Dongwon Kim --- ui/gtk-egl.c | 2 +- ui/gtk-gl-area.c | 2 +- ui/gtk.c | 10 ++ 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/ui/gtk-egl.c b/ui/gtk-egl.c index 3af5ac5bcf..955234429d 100644 --- a/ui/gtk-egl.c +++ b/ui/gtk-egl.c @@ -99,7 +99,7 @@ void gd_egl_draw(VirtualConsole *vc) #ifdef CONFIG_GBM if (dmabuf) { egl_dmabuf_create_fence(dmabuf); -if (dmabuf->fence_fd > 0) { +if (dmabuf->fence_fd >= 0) { qemu_set_fd_handler(dmabuf->fence_fd, gd_hw_gl_flushed, NULL, vc); return; } diff --git a/ui/gtk-gl-area.c b/ui/gtk-gl-area.c index 52dcac161e..7fffd0544e 100644 --- a/ui/gtk-gl-area.c +++ b/ui/gtk-gl-area.c @@ -86,7 +86,7 @@ void gd_gl_area_draw(VirtualConsole *vc) #ifdef CONFIG_GBM if (dmabuf) { egl_dmabuf_create_fence(dmabuf); -if (dmabuf->fence_fd > 0) { +if (dmabuf->fence_fd >= 0) { qemu_set_fd_handler(dmabuf->fence_fd, gd_hw_gl_flushed, NULL, vc); return; } diff --git a/ui/gtk.c b/ui/gtk.c index 810d7fc796..7819a86321 100644 --- a/ui/gtk.c +++ b/ui/gtk.c @@ -597,10 +597,12 @@ void gd_hw_gl_flushed(void *vcon) VirtualConsole *vc = vcon; QemuDmaBuf *dmabuf = vc->gfx.guest_fb.dmabuf; -qemu_set_fd_handler(dmabuf->fence_fd, NULL, NULL, NULL); -close(dmabuf->fence_fd); -dmabuf->fence_fd = -1; -graphic_hw_gl_block(vc->gfx.dcl.con, false); +if (dmabuf->fence_fd >= 0) { +qemu_set_fd_handler(dmabuf->fence_fd, NULL, NULL, NULL); +close(dmabuf->fence_fd); +dmabuf->fence_fd = -1; +graphic_hw_gl_block(vc->gfx.dcl.con, false); +} } /** DisplayState Callbacks (opengl version) **/ -- 2.34.1
[PATCH v11 4/6] ui/console: Use qemu_dmabuf_set_..() helpers instead
From: Dongwon Kim This commit updates all occurrences where these fields were set directly have been updated to utilize helper functions. v7: removed prefix, "dpy_gl_" from all helpers v8: Introduction of helpers was removed as those were already added by the previous commit Suggested-by: Marc-André Lureau Cc: Philippe Mathieu-Daudé Cc: Daniel P. Berrangé Cc: Vivek Kasireddy Signed-off-by: Dongwon Kim --- ui/egl-helpers.c | 16 +--- ui/gtk-egl.c | 4 ++-- ui/gtk-gl-area.c | 4 ++-- ui/gtk.c | 6 +++--- 4 files changed, 16 insertions(+), 14 deletions(-) diff --git a/ui/egl-helpers.c b/ui/egl-helpers.c index 3f96e63d25..99b2ebbe23 100644 --- a/ui/egl-helpers.c +++ b/ui/egl-helpers.c @@ -348,8 +348,8 @@ void egl_dmabuf_import_texture(QemuDmaBuf *dmabuf) return; } -glGenTextures(1, >texture); -texture = qemu_dmabuf_get_texture(dmabuf); +glGenTextures(1, ); +qemu_dmabuf_set_texture(dmabuf, texture); glBindTexture(GL_TEXTURE_2D, texture); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); @@ -368,7 +368,7 @@ void egl_dmabuf_release_texture(QemuDmaBuf *dmabuf) } glDeleteTextures(1, ); -dmabuf->texture = 0; +qemu_dmabuf_set_texture(dmabuf, 0); } void egl_dmabuf_create_sync(QemuDmaBuf *dmabuf) @@ -382,7 +382,7 @@ void egl_dmabuf_create_sync(QemuDmaBuf *dmabuf) sync = eglCreateSyncKHR(qemu_egl_display, EGL_SYNC_NATIVE_FENCE_ANDROID, NULL); if (sync != EGL_NO_SYNC_KHR) { -dmabuf->sync = sync; +qemu_dmabuf_set_sync(dmabuf, sync); } } } @@ -390,12 +390,14 @@ void egl_dmabuf_create_sync(QemuDmaBuf *dmabuf) void egl_dmabuf_create_fence(QemuDmaBuf *dmabuf) { void *sync = qemu_dmabuf_get_sync(dmabuf); +int fence_fd; if (sync) { -dmabuf->fence_fd = eglDupNativeFenceFDANDROID(qemu_egl_display, - sync); +fence_fd = eglDupNativeFenceFDANDROID(qemu_egl_display, + sync); +qemu_dmabuf_set_fence_fd(dmabuf, fence_fd); eglDestroySyncKHR(qemu_egl_display, sync); -dmabuf->sync = NULL; +qemu_dmabuf_set_sync(dmabuf, NULL); } } diff --git a/ui/gtk-egl.c b/ui/gtk-egl.c index 7a45daefa1..ec0bf45482 100644 --- a/ui/gtk-egl.c +++ b/ui/gtk-egl.c @@ -87,7 +87,7 @@ void gd_egl_draw(VirtualConsole *vc) if (!qemu_dmabuf_get_draw_submitted(dmabuf)) { return; } else { -dmabuf->draw_submitted = false; +qemu_dmabuf_set_draw_submitted(dmabuf, false); } } #endif @@ -381,7 +381,7 @@ void gd_egl_flush(DisplayChangeListener *dcl, if (vc->gfx.guest_fb.dmabuf && !qemu_dmabuf_get_draw_submitted(vc->gfx.guest_fb.dmabuf)) { graphic_hw_gl_block(vc->gfx.dcl.con, true); -vc->gfx.guest_fb.dmabuf->draw_submitted = true; +qemu_dmabuf_set_draw_submitted(vc->gfx.guest_fb.dmabuf, true); gtk_egl_set_scanout_mode(vc, true); gtk_widget_queue_draw_area(area, x, y, w, h); return; diff --git a/ui/gtk-gl-area.c b/ui/gtk-gl-area.c index 2d70280803..9a3f3d0d71 100644 --- a/ui/gtk-gl-area.c +++ b/ui/gtk-gl-area.c @@ -63,7 +63,7 @@ void gd_gl_area_draw(VirtualConsole *vc) if (!qemu_dmabuf_get_draw_submitted(dmabuf)) { return; } else { -dmabuf->draw_submitted = false; +qemu_dmabuf_set_draw_submitted(dmabuf, false); } } #endif @@ -291,7 +291,7 @@ void gd_gl_area_scanout_flush(DisplayChangeListener *dcl, if (vc->gfx.guest_fb.dmabuf && !qemu_dmabuf_get_draw_submitted(vc->gfx.guest_fb.dmabuf)) { graphic_hw_gl_block(vc->gfx.dcl.con, true); -vc->gfx.guest_fb.dmabuf->draw_submitted = true; +qemu_dmabuf_set_draw_submitted(vc->gfx.guest_fb.dmabuf, true); gtk_gl_area_set_scanout_mode(vc, true); } gtk_gl_area_queue_render(GTK_GL_AREA(vc->gfx.drawing_area)); diff --git a/ui/gtk.c b/ui/gtk.c index 237c913b26..3a6832eb1b 100644 --- a/ui/gtk.c +++ b/ui/gtk.c @@ -598,11 +598,11 @@ void gd_hw_gl_flushed(void *vcon) QemuDmaBuf *dmabuf = vc->gfx.guest_fb.dmabuf; int fence_fd; -if (dmabuf->fence_fd >= 0) { -fence_fd = qemu_dmabuf_get_fence_fd(dmabuf); +fence_fd = qemu_dmabuf_get_fence_fd(dmabuf); +if (fence_fd >= 0) { qemu_set_fd_handler(fence_fd, NULL, NULL, NULL); close(fence_fd); -dmabuf->fence_fd = -1; +qemu_dmabuf_set_fence_fd(dmabuf, -1); graphic_hw_gl_block(vc->gfx.dcl.con, false); } } -- 2.34.1
[PATCH v11 0/6] ui/console: Private QemuDmaBuf struct
From: Dongwon Kim This series introduces privacy enhancements to the QemuDmaBuf struct and its contained data to bolster security. it accomplishes this by introducing of helper functions for allocating, deallocating, and accessing individual fields within the struct and replacing all direct references to individual fields in the struct with methods using helpers throughout the codebase. This change was made based on a suggestion from Marc-André Lureau (Resumitting same patch series with this new cover-leter) v6: fixed some typos in patch - ui/console: Introduce dpy_gl_qemu_dmabuf_get_..() helpers) v7: included minor fix (ui/gtk: Check if fence_fd is equal to or greater than 0) (Marc-André Lureau ) migrated all helpers and QemuDmaBuf struct into dmabuf.c and their prototypes to dmabuf.h for better encapsulation (ui/dmabuf: New dmabuf.c and dmabuf.h..) (Daniel P. Berrangé and Marc-André Lureau ) removed 'dpy_gl' from all helpers' names Defined autoptr clean up function for QemuDmaBuf* (Daniel P. Berrangé ) Minor corrections v8: Introduce new dmabuf.c and dmabuf.h and all helper functions in the second patch in the series (ui/console: new dmabuf.h and dmabuf.c for QemuDma) (Philippe Mathieu-Daudé ) v9: set dmabuf->allow_fences true when it is created in virtio-gpu-udmabuf removed unnecessary spaces were added in the patch, 'ui/console: Use qemu_dmabuf_new() a...' v10: Change the license type for both dmabuf.h and dmabuf.c from MIT to GPL to be in line with QEMU's default license (Daniel P. Berrangé ) v11: New helpers added - qemu_dmabuf_dup_fd, qemu_dmabuf_close for duplicating and closing dmabuf->fd. And use them in places where applicable. (Daniel P. Berrangé ) qemu_dmabuf_free helper now close dmabuf->fd before freeing the struct to prevent any potential leakage (This eliminates the need for qemu_dmabuf_close in several places as qemu_dmabuf_close is done anyway.) (Daniel P. Berrangé ) Dongwon Kim (6): ui/gtk: Check if fence_fd is equal to or greater than 0 ui/console: new dmabuf.h and dmabuf.c for QemuDmaBuf struct and helpers ui/console: Use qemu_dmabuf_get_..() helpers instead ui/console: Use qemu_dmabuf_set_..() helpers instead ui/console: Use qemu_dmabuf_new() and free() helpers instead ui/console: move QemuDmaBuf struct def to dmabuf.c include/hw/vfio/vfio-common.h | 2 +- include/hw/virtio/virtio-gpu.h | 4 +- include/ui/console.h| 20 +-- include/ui/dmabuf.h | 49 +++ hw/display/vhost-user-gpu.c | 25 ++-- hw/display/virtio-gpu-udmabuf.c | 27 ++-- hw/vfio/display.c | 31 ++--- ui/console.c| 4 +- ui/dbus-console.c | 9 +- ui/dbus-listener.c | 71 +- ui/dmabuf.c | 230 ui/egl-headless.c | 23 +++- ui/egl-helpers.c| 59 ui/gtk-egl.c| 52 +--- ui/gtk-gl-area.c| 41 -- ui/gtk.c| 12 +- ui/spice-display.c | 50 --- ui/meson.build | 1 + 18 files changed, 517 insertions(+), 193 deletions(-) create mode 100644 include/ui/dmabuf.h create mode 100644 ui/dmabuf.c -- 2.34.1
[PATCH v10 3/6] ui/console: Use qemu_dmabuf_get_..() helpers instead
From: Dongwon Kim This commit updates all instances where fields within the QemuDmaBuf struct are directly accessed, replacing them with calls to these new helper functions. v6: fix typos in helper names in ui/spice-display.c v7: removed prefix, "dpy_gl_" from all helpers v8: Introduction of helpers was removed as those were already added by the previous commit Suggested-by: Marc-André Lureau Reviewed-by: Marc-André Lureau Cc: Philippe Mathieu-Daudé Cc: Daniel P. Berrangé Cc: Vivek Kasireddy Signed-off-by: Dongwon Kim --- hw/display/vhost-user-gpu.c | 6 ++-- hw/display/virtio-gpu-udmabuf.c | 7 +++-- hw/vfio/display.c | 15 +++--- ui/console.c| 4 +-- ui/dbus-console.c | 9 -- ui/dbus-listener.c | 43 +--- ui/egl-headless.c | 23 ++- ui/egl-helpers.c| 47 ++- ui/gtk-egl.c| 48 --- ui/gtk-gl-area.c| 37 ui/gtk.c| 6 ++-- ui/spice-display.c | 50 +++-- 12 files changed, 187 insertions(+), 108 deletions(-) diff --git a/hw/display/vhost-user-gpu.c b/hw/display/vhost-user-gpu.c index 709c8a02a1..ea9a6c5d10 100644 --- a/hw/display/vhost-user-gpu.c +++ b/hw/display/vhost-user-gpu.c @@ -249,6 +249,7 @@ vhost_user_gpu_handle_display(VhostUserGPU *g, VhostUserGpuMsg *msg) case VHOST_USER_GPU_DMABUF_SCANOUT: { VhostUserGpuDMABUFScanout *m = >payload.dmabuf_scanout; int fd = qemu_chr_fe_get_msgfd(>vhost_chr); +int old_fd; QemuDmaBuf *dmabuf; if (m->scanout_id >= g->parent_obj.conf.max_outputs) { @@ -262,8 +263,9 @@ vhost_user_gpu_handle_display(VhostUserGPU *g, VhostUserGpuMsg *msg) g->parent_obj.enable = 1; con = g->parent_obj.scanout[m->scanout_id].con; dmabuf = >dmabuf[m->scanout_id]; -if (dmabuf->fd >= 0) { -close(dmabuf->fd); +old_fd = qemu_dmabuf_get_fd(dmabuf); +if (old_fd >= 0) { +close(old_fd); dmabuf->fd = -1; } dpy_gl_release_dmabuf(con, dmabuf); diff --git a/hw/display/virtio-gpu-udmabuf.c b/hw/display/virtio-gpu-udmabuf.c index d51184d658..c90eba281e 100644 --- a/hw/display/virtio-gpu-udmabuf.c +++ b/hw/display/virtio-gpu-udmabuf.c @@ -206,6 +206,7 @@ int virtio_gpu_update_dmabuf(VirtIOGPU *g, { struct virtio_gpu_scanout *scanout = >parent_obj.scanout[scanout_id]; VGPUDMABuf *new_primary, *old_primary = NULL; +uint32_t width, height; new_primary = virtio_gpu_create_dmabuf(g, scanout_id, res, fb, r); if (!new_primary) { @@ -216,10 +217,10 @@ int virtio_gpu_update_dmabuf(VirtIOGPU *g, old_primary = g->dmabuf.primary[scanout_id]; } +width = qemu_dmabuf_get_width(_primary->buf); +height = qemu_dmabuf_get_height(_primary->buf); g->dmabuf.primary[scanout_id] = new_primary; -qemu_console_resize(scanout->con, -new_primary->buf.width, -new_primary->buf.height); +qemu_console_resize(scanout->con, width, height); dpy_gl_scanout_dmabuf(scanout->con, _primary->buf); if (old_primary) { diff --git a/hw/vfio/display.c b/hw/vfio/display.c index 1aa440c663..4861c8161d 100644 --- a/hw/vfio/display.c +++ b/hw/vfio/display.c @@ -259,9 +259,13 @@ static VFIODMABuf *vfio_display_get_dmabuf(VFIOPCIDevice *vdev, static void vfio_display_free_one_dmabuf(VFIODisplay *dpy, VFIODMABuf *dmabuf) { +int fd; + QTAILQ_REMOVE(>dmabuf.bufs, dmabuf, next); + +fd = qemu_dmabuf_get_fd(>buf); dpy_gl_release_dmabuf(dpy->con, >buf); -close(dmabuf->buf.fd); +close(fd); g_free(dmabuf); } @@ -286,6 +290,7 @@ static void vfio_display_dmabuf_update(void *opaque) VFIOPCIDevice *vdev = opaque; VFIODisplay *dpy = vdev->dpy; VFIODMABuf *primary, *cursor; +uint32_t width, height; bool free_bufs = false, new_cursor = false; primary = vfio_display_get_dmabuf(vdev, DRM_PLANE_TYPE_PRIMARY); @@ -296,10 +301,12 @@ static void vfio_display_dmabuf_update(void *opaque) return; } +width = qemu_dmabuf_get_width(>buf); +height = qemu_dmabuf_get_height(>buf); + if (dpy->dmabuf.primary != primary) { dpy->dmabuf.primary = primary; -qemu_console_resize(dpy->con, -primary->buf.width, primary->buf.height); +qemu_console_resize(dpy->con, width, height); dpy_gl_scanout_dmabuf(dpy->con, >buf); free_bufs = true; } @@ -328,7 +335,7 @@ static void vfio_display_dmabuf_update(void *opaque) cursor->pos_updates = 0; } -dpy_
[PATCH v10 5/6] ui/console: Use qemu_dmabuf_new() and free() helpers instead
From: Dongwon Kim This commit introduces utility functions for the creation and deallocation of QemuDmaBuf instances. Additionally, it updates all relevant sections of the codebase to utilize these new utility functions. v7: remove prefix, "dpy_gl_" from all helpers qemu_dmabuf_free() returns without doing anything if input is null (Daniel P. Berrangé ) call G_DEFINE_AUTOPTR_CLEANUP_FUNC for qemu_dmabuf_free() (Daniel P. Berrangé ) v8: Introduction of helpers was removed as those were already added by the previous commit v9: set dmabuf->allow_fences to 'true' when dmabuf is created in virtio_gpu_create_dmabuf()/virtio-gpu-udmabuf.c removed unnecessary spaces were accidently added in the patch, 'ui/console: Use qemu_dmabuf_new() a...' Suggested-by: Marc-André Lureau Cc: Philippe Mathieu-Daudé Cc: Daniel P. Berrangé Cc: Vivek Kasireddy Signed-off-by: Dongwon Kim --- include/hw/vfio/vfio-common.h | 2 +- include/hw/virtio/virtio-gpu.h | 4 ++-- hw/display/vhost-user-gpu.c | 32 ++-- hw/display/virtio-gpu-udmabuf.c | 24 +--- hw/vfio/display.c | 26 -- ui/dbus-listener.c | 28 6 files changed, 54 insertions(+), 62 deletions(-) diff --git a/include/hw/vfio/vfio-common.h b/include/hw/vfio/vfio-common.h index b9da6c08ef..d66e27db02 100644 --- a/include/hw/vfio/vfio-common.h +++ b/include/hw/vfio/vfio-common.h @@ -148,7 +148,7 @@ typedef struct VFIOGroup { } VFIOGroup; typedef struct VFIODMABuf { -QemuDmaBuf buf; +QemuDmaBuf *buf; uint32_t pos_x, pos_y, pos_updates; uint32_t hot_x, hot_y, hot_updates; int dmabuf_id; diff --git a/include/hw/virtio/virtio-gpu.h b/include/hw/virtio/virtio-gpu.h index ed44cdad6b..56d6e821bf 100644 --- a/include/hw/virtio/virtio-gpu.h +++ b/include/hw/virtio/virtio-gpu.h @@ -169,7 +169,7 @@ struct VirtIOGPUBaseClass { DEFINE_PROP_UINT32("yres", _state, _conf.yres, 800) typedef struct VGPUDMABuf { -QemuDmaBuf buf; +QemuDmaBuf *buf; uint32_t scanout_id; QTAILQ_ENTRY(VGPUDMABuf) next; } VGPUDMABuf; @@ -238,7 +238,7 @@ struct VhostUserGPU { VhostUserBackend *vhost; int vhost_gpu_fd; /* closed by the chardev */ CharBackend vhost_chr; -QemuDmaBuf dmabuf[VIRTIO_GPU_MAX_SCANOUTS]; +QemuDmaBuf *dmabuf[VIRTIO_GPU_MAX_SCANOUTS]; bool backend_blocked; }; diff --git a/hw/display/vhost-user-gpu.c b/hw/display/vhost-user-gpu.c index ea9a6c5d10..c91a800455 100644 --- a/hw/display/vhost-user-gpu.c +++ b/hw/display/vhost-user-gpu.c @@ -250,6 +250,7 @@ vhost_user_gpu_handle_display(VhostUserGPU *g, VhostUserGpuMsg *msg) VhostUserGpuDMABUFScanout *m = >payload.dmabuf_scanout; int fd = qemu_chr_fe_get_msgfd(>vhost_chr); int old_fd; +uint64_t modifier = 0; QemuDmaBuf *dmabuf; if (m->scanout_id >= g->parent_obj.conf.max_outputs) { @@ -262,31 +263,34 @@ vhost_user_gpu_handle_display(VhostUserGPU *g, VhostUserGpuMsg *msg) g->parent_obj.enable = 1; con = g->parent_obj.scanout[m->scanout_id].con; -dmabuf = >dmabuf[m->scanout_id]; -old_fd = qemu_dmabuf_get_fd(dmabuf); -if (old_fd >= 0) { -close(old_fd); -dmabuf->fd = -1; +dmabuf = g->dmabuf[m->scanout_id]; +if (dmabuf) { +old_fd = qemu_dmabuf_get_fd(dmabuf); +if (old_fd >= 0) { +close(old_fd); +qemu_dmabuf_set_fd(dmabuf, -1); +} } dpy_gl_release_dmabuf(con, dmabuf); +g_clear_pointer(, qemu_dmabuf_free); if (fd == -1) { dpy_gl_scanout_disable(con); break; } -*dmabuf = (QemuDmaBuf) { -.fd = fd, -.width = m->fd_width, -.height = m->fd_height, -.stride = m->fd_stride, -.fourcc = m->fd_drm_fourcc, -.y0_top = m->fd_flags & VIRTIO_GPU_RESOURCE_FLAG_Y_0_TOP, -}; + if (msg->request == VHOST_USER_GPU_DMABUF_SCANOUT2) { VhostUserGpuDMABUFScanout2 *m2 = >payload.dmabuf_scanout2; -dmabuf->modifier = m2->modifier; +modifier = m2->modifier; } +dmabuf = qemu_dmabuf_new(m->fd_width, m->fd_height, + m->fd_stride, 0, 0, 0, 0, + m->fd_drm_fourcc, modifier, + fd, false, m->fd_flags & + VIRTIO_GPU_RESOURCE_FLAG_Y_0_TOP); + dpy_gl_scanout_dmabuf(con, dmabuf); +g->dmabuf[m->scanout_id] = dmabuf; break; } case VHOST_USER_GPU_DMABUF_UPDATE: { diff --git a/hw/display/virtio-gpu-udmabuf.c b/hw/display/virtio-gpu-udma
[PATCH v10 2/6] ui/console: new dmabuf.h and dmabuf.c for QemuDmaBuf struct and helpers
From: Dongwon Kim New header and source files are added for containing QemuDmaBuf struct definition and newly introduced helpers for creating/freeing the struct and accessing its data. v10: Change the license type for both dmabuf.h and dmabuf.c from MIT to GPL to be in line with QEMU's default license (Daniel P. Berrangé ) Suggested-by: Marc-André Lureau Cc: Philippe Mathieu-Daudé Cc: Daniel P. Berrangé Cc: Vivek Kasireddy Signed-off-by: Dongwon Kim --- include/ui/console.h | 20 + include/ui/dmabuf.h | 64 +++ ui/dmabuf.c | 189 +++ ui/meson.build | 1 + 4 files changed, 255 insertions(+), 19 deletions(-) create mode 100644 include/ui/dmabuf.h create mode 100644 ui/dmabuf.c diff --git a/include/ui/console.h b/include/ui/console.h index 0bc7a00ac0..a208a68b88 100644 --- a/include/ui/console.h +++ b/include/ui/console.h @@ -7,6 +7,7 @@ #include "qapi/qapi-types-ui.h" #include "ui/input.h" #include "ui/surface.h" +#include "ui/dmabuf.h" #define TYPE_QEMU_CONSOLE "qemu-console" OBJECT_DECLARE_TYPE(QemuConsole, QemuConsoleClass, QEMU_CONSOLE) @@ -185,25 +186,6 @@ struct QEMUGLParams { int minor_ver; }; -typedef struct QemuDmaBuf { -int fd; -uint32_t width; -uint32_t height; -uint32_t stride; -uint32_t fourcc; -uint64_t modifier; -uint32_t texture; -uint32_t x; -uint32_t y; -uint32_t backing_width; -uint32_t backing_height; -bool y0_top; -void *sync; -int fence_fd; -bool allow_fences; -bool draw_submitted; -} QemuDmaBuf; - enum display_scanout { SCANOUT_NONE, SCANOUT_SURFACE, diff --git a/include/ui/dmabuf.h b/include/ui/dmabuf.h new file mode 100644 index 00..7a60116ee6 --- /dev/null +++ b/include/ui/dmabuf.h @@ -0,0 +1,64 @@ +/* + * SPDX-License-Identifier: GPL-2.0-or-later + * + * QemuDmaBuf struct and helpers used for accessing its data + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#ifndef DMABUF_H +#define DMABUF_H + +typedef struct QemuDmaBuf { +int fd; +uint32_t width; +uint32_t height; +uint32_t stride; +uint32_t fourcc; +uint64_t modifier; +uint32_t texture; +uint32_t x; +uint32_t y; +uint32_t backing_width; +uint32_t backing_height; +bool y0_top; +void *sync; +int fence_fd; +bool allow_fences; +bool draw_submitted; +} QemuDmaBuf; + +QemuDmaBuf *qemu_dmabuf_new(uint32_t width, uint32_t height, + uint32_t stride, uint32_t x, + uint32_t y, uint32_t backing_width, + uint32_t backing_height, uint32_t fourcc, + uint64_t modifier, int32_t dmabuf_fd, + bool allow_fences, bool y0_top); +void qemu_dmabuf_free(QemuDmaBuf *dmabuf); + +G_DEFINE_AUTOPTR_CLEANUP_FUNC(QemuDmaBuf, qemu_dmabuf_free); + +int32_t qemu_dmabuf_get_fd(QemuDmaBuf *dmabuf); +uint32_t qemu_dmabuf_get_width(QemuDmaBuf *dmabuf); +uint32_t qemu_dmabuf_get_height(QemuDmaBuf *dmabuf); +uint32_t qemu_dmabuf_get_stride(QemuDmaBuf *dmabuf); +uint32_t qemu_dmabuf_get_fourcc(QemuDmaBuf *dmabuf); +uint64_t qemu_dmabuf_get_modifier(QemuDmaBuf *dmabuf); +uint32_t qemu_dmabuf_get_texture(QemuDmaBuf *dmabuf); +uint32_t qemu_dmabuf_get_x(QemuDmaBuf *dmabuf); +uint32_t qemu_dmabuf_get_y(QemuDmaBuf *dmabuf); +uint32_t qemu_dmabuf_get_backing_width(QemuDmaBuf *dmabuf); +uint32_t qemu_dmabuf_get_backing_height(QemuDmaBuf *dmabuf); +bool qemu_dmabuf_get_y0_top(QemuDmaBuf *dmabuf); +void *qemu_dmabuf_get_sync(QemuDmaBuf *dmabuf); +int32_t qemu_dmabuf_get_fence_fd(QemuDmaBuf *dmabuf); +bool qemu_dmabuf_get_allow_fences(QemuDmaBuf *dmabuf); +bool qemu_dmabuf_get_draw_submitted(QemuDmaBuf *dmabuf); +void qemu_dmabuf_set_texture(QemuDmaBuf *dmabuf, uint32_t texture); +void qemu_dmabuf_set_fence_fd(QemuDmaBuf *dmabuf, int32_t fence_fd); +void qemu_dmabuf_set_sync(QemuDmaBuf *dmabuf, void *sync); +void qemu_dmabuf_set_draw_submitted(QemuDmaBuf *dmabuf, bool draw_submitted); +void qemu_dmabuf_set_fd(QemuDmaBuf *dmabuf, int32_t fd); + +#endif diff --git a/ui/dmabuf.c b/ui/dmabuf.c new file mode 100644 index 00..f447cce4fe --- /dev/null +++ b/ui/dmabuf.c @@ -0,0 +1,189 @@ +/* + * SPDX-License-Identifier: GPL-2.0-or-later + * + * QemuDmaBuf struct and helpers used for accessing its data + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#include "qemu/osdep.h" +#include "ui/dmabuf.h" + +QemuDmaBuf *qemu_dmabuf_new(uint32_t width, uint32_t height, +uint32_t stride, uint3
[PATCH v10 4/6] ui/console: Use qemu_dmabuf_set_..() helpers instead
From: Dongwon Kim This commit updates all occurrences where these fields were set directly have been updated to utilize helper functions. v7: removed prefix, "dpy_gl_" from all helpers v8: Introduction of helpers was removed as those were already added by the previous commit Suggested-by: Marc-André Lureau Cc: Philippe Mathieu-Daudé Cc: Daniel P. Berrangé Cc: Vivek Kasireddy Signed-off-by: Dongwon Kim --- ui/egl-helpers.c | 16 +--- ui/gtk-egl.c | 4 ++-- ui/gtk-gl-area.c | 4 ++-- ui/gtk.c | 6 +++--- 4 files changed, 16 insertions(+), 14 deletions(-) diff --git a/ui/egl-helpers.c b/ui/egl-helpers.c index 3f96e63d25..99b2ebbe23 100644 --- a/ui/egl-helpers.c +++ b/ui/egl-helpers.c @@ -348,8 +348,8 @@ void egl_dmabuf_import_texture(QemuDmaBuf *dmabuf) return; } -glGenTextures(1, >texture); -texture = qemu_dmabuf_get_texture(dmabuf); +glGenTextures(1, ); +qemu_dmabuf_set_texture(dmabuf, texture); glBindTexture(GL_TEXTURE_2D, texture); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); @@ -368,7 +368,7 @@ void egl_dmabuf_release_texture(QemuDmaBuf *dmabuf) } glDeleteTextures(1, ); -dmabuf->texture = 0; +qemu_dmabuf_set_texture(dmabuf, 0); } void egl_dmabuf_create_sync(QemuDmaBuf *dmabuf) @@ -382,7 +382,7 @@ void egl_dmabuf_create_sync(QemuDmaBuf *dmabuf) sync = eglCreateSyncKHR(qemu_egl_display, EGL_SYNC_NATIVE_FENCE_ANDROID, NULL); if (sync != EGL_NO_SYNC_KHR) { -dmabuf->sync = sync; +qemu_dmabuf_set_sync(dmabuf, sync); } } } @@ -390,12 +390,14 @@ void egl_dmabuf_create_sync(QemuDmaBuf *dmabuf) void egl_dmabuf_create_fence(QemuDmaBuf *dmabuf) { void *sync = qemu_dmabuf_get_sync(dmabuf); +int fence_fd; if (sync) { -dmabuf->fence_fd = eglDupNativeFenceFDANDROID(qemu_egl_display, - sync); +fence_fd = eglDupNativeFenceFDANDROID(qemu_egl_display, + sync); +qemu_dmabuf_set_fence_fd(dmabuf, fence_fd); eglDestroySyncKHR(qemu_egl_display, sync); -dmabuf->sync = NULL; +qemu_dmabuf_set_sync(dmabuf, NULL); } } diff --git a/ui/gtk-egl.c b/ui/gtk-egl.c index 7a45daefa1..ec0bf45482 100644 --- a/ui/gtk-egl.c +++ b/ui/gtk-egl.c @@ -87,7 +87,7 @@ void gd_egl_draw(VirtualConsole *vc) if (!qemu_dmabuf_get_draw_submitted(dmabuf)) { return; } else { -dmabuf->draw_submitted = false; +qemu_dmabuf_set_draw_submitted(dmabuf, false); } } #endif @@ -381,7 +381,7 @@ void gd_egl_flush(DisplayChangeListener *dcl, if (vc->gfx.guest_fb.dmabuf && !qemu_dmabuf_get_draw_submitted(vc->gfx.guest_fb.dmabuf)) { graphic_hw_gl_block(vc->gfx.dcl.con, true); -vc->gfx.guest_fb.dmabuf->draw_submitted = true; +qemu_dmabuf_set_draw_submitted(vc->gfx.guest_fb.dmabuf, true); gtk_egl_set_scanout_mode(vc, true); gtk_widget_queue_draw_area(area, x, y, w, h); return; diff --git a/ui/gtk-gl-area.c b/ui/gtk-gl-area.c index 2d70280803..9a3f3d0d71 100644 --- a/ui/gtk-gl-area.c +++ b/ui/gtk-gl-area.c @@ -63,7 +63,7 @@ void gd_gl_area_draw(VirtualConsole *vc) if (!qemu_dmabuf_get_draw_submitted(dmabuf)) { return; } else { -dmabuf->draw_submitted = false; +qemu_dmabuf_set_draw_submitted(dmabuf, false); } } #endif @@ -291,7 +291,7 @@ void gd_gl_area_scanout_flush(DisplayChangeListener *dcl, if (vc->gfx.guest_fb.dmabuf && !qemu_dmabuf_get_draw_submitted(vc->gfx.guest_fb.dmabuf)) { graphic_hw_gl_block(vc->gfx.dcl.con, true); -vc->gfx.guest_fb.dmabuf->draw_submitted = true; +qemu_dmabuf_set_draw_submitted(vc->gfx.guest_fb.dmabuf, true); gtk_gl_area_set_scanout_mode(vc, true); } gtk_gl_area_queue_render(GTK_GL_AREA(vc->gfx.drawing_area)); diff --git a/ui/gtk.c b/ui/gtk.c index 237c913b26..3a6832eb1b 100644 --- a/ui/gtk.c +++ b/ui/gtk.c @@ -598,11 +598,11 @@ void gd_hw_gl_flushed(void *vcon) QemuDmaBuf *dmabuf = vc->gfx.guest_fb.dmabuf; int fence_fd; -if (dmabuf->fence_fd >= 0) { -fence_fd = qemu_dmabuf_get_fence_fd(dmabuf); +fence_fd = qemu_dmabuf_get_fence_fd(dmabuf); +if (fence_fd >= 0) { qemu_set_fd_handler(fence_fd, NULL, NULL, NULL); close(fence_fd); -dmabuf->fence_fd = -1; +qemu_dmabuf_set_fence_fd(dmabuf, -1); graphic_hw_gl_block(vc->gfx.dcl.con, false); } } -- 2.34.1
[PATCH v10 0/6] ui/console: Private QemuDmaBuf struct
From: Dongwon Kim This series introduces privacy enhancements to the QemuDmaBuf struct and its contained data to bolster security. it accomplishes this by introducing of helper functions for allocating, deallocating, and accessing individual fields within the struct and replacing all direct references to individual fields in the struct with methods using helpers throughout the codebase. This change was made based on a suggestion from Marc-André Lureau (Resumitting same patch series with this new cover-leter) v6: fixed some typos in patch - ui/console: Introduce dpy_gl_qemu_dmabuf_get_..() helpers) v7: included minor fix (ui/gtk: Check if fence_fd is equal to or greater than 0) (Marc-André Lureau ) migrated all helpers and QemuDmaBuf struct into dmabuf.c and their prototypes to dmabuf.h for better encapsulation (ui/dmabuf: New dmabuf.c and dmabuf.h..) (Daniel P. Berrangé and Marc-André Lureau ) removed 'dpy_gl' from all helpers' names Defined autoptr clean up function for QemuDmaBuf* (Daniel P. Berrangé ) Minor corrections v8: Introduce new dmabuf.c and dmabuf.h and all helper functions in the second patch in the series (ui/console: new dmabuf.h and dmabuf.c for QemuDma) (Philippe Mathieu-Daudé ) v9: set dmabuf->allow_fences true when it is created in virtio-gpu-udmabuf removed unnecessary spaces were added in the patch, 'ui/console: Use qemu_dmabuf_new() a...' v10: Change the license type for both dmabuf.h and dmabuf.c from MIT to GPL to be in line with QEMU's default license (Daniel P. Berrangé ) Dongwon Kim (6): ui/gtk: Check if fence_fd is equal to or greater than 0 ui/console: new dmabuf.h and dmabuf.c for QemuDmaBuf struct and helpers ui/console: Use qemu_dmabuf_get_..() helpers instead ui/console: Use qemu_dmabuf_set_..() helpers instead ui/console: Use qemu_dmabuf_new() and free() helpers instead ui/console: move QemuDmaBuf struct def to dmabuf.c include/hw/vfio/vfio-common.h | 2 +- include/hw/virtio/virtio-gpu.h | 4 +- include/ui/console.h| 20 +-- include/ui/dmabuf.h | 47 hw/display/vhost-user-gpu.c | 32 +++-- hw/display/virtio-gpu-udmabuf.c | 27 ++--- hw/vfio/display.c | 35 +++--- ui/console.c| 4 +- ui/dbus-console.c | 9 +- ui/dbus-listener.c | 71 ++- ui/dmabuf.c | 208 ui/egl-headless.c | 23 ++-- ui/egl-helpers.c| 59 + ui/gtk-egl.c| 52 +--- ui/gtk-gl-area.c| 41 --- ui/gtk.c| 12 +- ui/spice-display.c | 50 ui/meson.build | 1 + 18 files changed, 505 insertions(+), 192 deletions(-) create mode 100644 include/ui/dmabuf.h create mode 100644 ui/dmabuf.c -- 2.34.1
[PATCH v10 1/6] ui/gtk: Check if fence_fd is equal to or greater than 0
From: Dongwon Kim 'fence_fd' needs to be validated always before being referenced And the passing condition should include '== 0' as 0 is a valid value for the file descriptor. Suggested-by: Marc-André Lureau Cc: Philippe Mathieu-Daudé Cc: Daniel P. Berrangé Cc: Vivek Kasireddy Signed-off-by: Dongwon Kim --- ui/gtk-egl.c | 2 +- ui/gtk-gl-area.c | 2 +- ui/gtk.c | 10 ++ 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/ui/gtk-egl.c b/ui/gtk-egl.c index 3af5ac5bcf..955234429d 100644 --- a/ui/gtk-egl.c +++ b/ui/gtk-egl.c @@ -99,7 +99,7 @@ void gd_egl_draw(VirtualConsole *vc) #ifdef CONFIG_GBM if (dmabuf) { egl_dmabuf_create_fence(dmabuf); -if (dmabuf->fence_fd > 0) { +if (dmabuf->fence_fd >= 0) { qemu_set_fd_handler(dmabuf->fence_fd, gd_hw_gl_flushed, NULL, vc); return; } diff --git a/ui/gtk-gl-area.c b/ui/gtk-gl-area.c index 52dcac161e..7fffd0544e 100644 --- a/ui/gtk-gl-area.c +++ b/ui/gtk-gl-area.c @@ -86,7 +86,7 @@ void gd_gl_area_draw(VirtualConsole *vc) #ifdef CONFIG_GBM if (dmabuf) { egl_dmabuf_create_fence(dmabuf); -if (dmabuf->fence_fd > 0) { +if (dmabuf->fence_fd >= 0) { qemu_set_fd_handler(dmabuf->fence_fd, gd_hw_gl_flushed, NULL, vc); return; } diff --git a/ui/gtk.c b/ui/gtk.c index 810d7fc796..7819a86321 100644 --- a/ui/gtk.c +++ b/ui/gtk.c @@ -597,10 +597,12 @@ void gd_hw_gl_flushed(void *vcon) VirtualConsole *vc = vcon; QemuDmaBuf *dmabuf = vc->gfx.guest_fb.dmabuf; -qemu_set_fd_handler(dmabuf->fence_fd, NULL, NULL, NULL); -close(dmabuf->fence_fd); -dmabuf->fence_fd = -1; -graphic_hw_gl_block(vc->gfx.dcl.con, false); +if (dmabuf->fence_fd >= 0) { +qemu_set_fd_handler(dmabuf->fence_fd, NULL, NULL, NULL); +close(dmabuf->fence_fd); +dmabuf->fence_fd = -1; +graphic_hw_gl_block(vc->gfx.dcl.con, false); +} } /** DisplayState Callbacks (opengl version) **/ -- 2.34.1
[PATCH v10 6/6] ui/console: move QemuDmaBuf struct def to dmabuf.c
From: Dongwon Kim To complete privatizing process of QemuDmaBuf, QemuDmaBuf struct def is moved to dmabuf.c Suggested-by: Marc-André Lureau Cc: Philippe Mathieu-Daudé Cc: Daniel P. Berrangé Cc: Vivek Kasireddy Signed-off-by: Dongwon Kim --- include/ui/dmabuf.h | 19 +-- ui/dmabuf.c | 19 +++ 2 files changed, 20 insertions(+), 18 deletions(-) diff --git a/include/ui/dmabuf.h b/include/ui/dmabuf.h index 7a60116ee6..80d89ac461 100644 --- a/include/ui/dmabuf.h +++ b/include/ui/dmabuf.h @@ -10,24 +10,7 @@ #ifndef DMABUF_H #define DMABUF_H -typedef struct QemuDmaBuf { -int fd; -uint32_t width; -uint32_t height; -uint32_t stride; -uint32_t fourcc; -uint64_t modifier; -uint32_t texture; -uint32_t x; -uint32_t y; -uint32_t backing_width; -uint32_t backing_height; -bool y0_top; -void *sync; -int fence_fd; -bool allow_fences; -bool draw_submitted; -} QemuDmaBuf; +typedef struct QemuDmaBuf QemuDmaBuf; QemuDmaBuf *qemu_dmabuf_new(uint32_t width, uint32_t height, uint32_t stride, uint32_t x, diff --git a/ui/dmabuf.c b/ui/dmabuf.c index f447cce4fe..7f092333b4 100644 --- a/ui/dmabuf.c +++ b/ui/dmabuf.c @@ -10,6 +10,25 @@ #include "qemu/osdep.h" #include "ui/dmabuf.h" +struct QemuDmaBuf { +int fd; +uint32_t width; +uint32_t height; +uint32_t stride; +uint32_t fourcc; +uint64_t modifier; +uint32_t texture; +uint32_t x; +uint32_t y; +uint32_t backing_width; +uint32_t backing_height; +bool y0_top; +void *sync; +int fence_fd; +bool allow_fences; +bool draw_submitted; +}; + QemuDmaBuf *qemu_dmabuf_new(uint32_t width, uint32_t height, uint32_t stride, uint32_t x, uint32_t y, uint32_t backing_width, -- 2.34.1
[PATCH v9 2/6] ui/console: new dmabuf.h and dmabuf.c for QemuDmaBuf struct and helpers
From: Dongwon Kim New header and source files are added for containing QemuDmaBuf struct definition and newly introduced helpers for creating/freeing the struct and accessing its data. Suggested-by: Marc-André Lureau Cc: Philippe Mathieu-Daudé Cc: Daniel P. Berrangé Cc: Vivek Kasireddy Signed-off-by: Dongwon Kim --- include/ui/console.h | 20 + include/ui/dmabuf.h | 81 + ui/dmabuf.c | 206 +++ ui/meson.build | 1 + 4 files changed, 289 insertions(+), 19 deletions(-) create mode 100644 include/ui/dmabuf.h create mode 100644 ui/dmabuf.c diff --git a/include/ui/console.h b/include/ui/console.h index 0bc7a00ac0..a208a68b88 100644 --- a/include/ui/console.h +++ b/include/ui/console.h @@ -7,6 +7,7 @@ #include "qapi/qapi-types-ui.h" #include "ui/input.h" #include "ui/surface.h" +#include "ui/dmabuf.h" #define TYPE_QEMU_CONSOLE "qemu-console" OBJECT_DECLARE_TYPE(QemuConsole, QemuConsoleClass, QEMU_CONSOLE) @@ -185,25 +186,6 @@ struct QEMUGLParams { int minor_ver; }; -typedef struct QemuDmaBuf { -int fd; -uint32_t width; -uint32_t height; -uint32_t stride; -uint32_t fourcc; -uint64_t modifier; -uint32_t texture; -uint32_t x; -uint32_t y; -uint32_t backing_width; -uint32_t backing_height; -bool y0_top; -void *sync; -int fence_fd; -bool allow_fences; -bool draw_submitted; -} QemuDmaBuf; - enum display_scanout { SCANOUT_NONE, SCANOUT_SURFACE, diff --git a/include/ui/dmabuf.h b/include/ui/dmabuf.h new file mode 100644 index 00..d01bddf523 --- /dev/null +++ b/include/ui/dmabuf.h @@ -0,0 +1,81 @@ +/* + * SPDX-License-Identifier: MIT + * + * QemuDmaBuf struct and helpers used for accessing its data + * + * Copyright (c) 2024 Dongwon Kim + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef DMABUF_H +#define DMABUF_H + +typedef struct QemuDmaBuf { +int fd; +uint32_t width; +uint32_t height; +uint32_t stride; +uint32_t fourcc; +uint64_t modifier; +uint32_t texture; +uint32_t x; +uint32_t y; +uint32_t backing_width; +uint32_t backing_height; +bool y0_top; +void *sync; +int fence_fd; +bool allow_fences; +bool draw_submitted; +} QemuDmaBuf; + +QemuDmaBuf *qemu_dmabuf_new(uint32_t width, uint32_t height, + uint32_t stride, uint32_t x, + uint32_t y, uint32_t backing_width, + uint32_t backing_height, uint32_t fourcc, + uint64_t modifier, int32_t dmabuf_fd, + bool allow_fences, bool y0_top); +void qemu_dmabuf_free(QemuDmaBuf *dmabuf); + +G_DEFINE_AUTOPTR_CLEANUP_FUNC(QemuDmaBuf, qemu_dmabuf_free); + +int32_t qemu_dmabuf_get_fd(QemuDmaBuf *dmabuf); +uint32_t qemu_dmabuf_get_width(QemuDmaBuf *dmabuf); +uint32_t qemu_dmabuf_get_height(QemuDmaBuf *dmabuf); +uint32_t qemu_dmabuf_get_stride(QemuDmaBuf *dmabuf); +uint32_t qemu_dmabuf_get_fourcc(QemuDmaBuf *dmabuf); +uint64_t qemu_dmabuf_get_modifier(QemuDmaBuf *dmabuf); +uint32_t qemu_dmabuf_get_texture(QemuDmaBuf *dmabuf); +uint32_t qemu_dmabuf_get_x(QemuDmaBuf *dmabuf); +uint32_t qemu_dmabuf_get_y(QemuDmaBuf *dmabuf); +uint32_t qemu_dmabuf_get_backing_width(QemuDmaBuf *dmabuf); +uint32_t qemu_dmabuf_get_backing_height(QemuDmaBuf *dmabuf); +bool qemu_dmabuf_get_y0_top(QemuDmaBuf *dmabuf); +void *qemu_dmabuf_get_sync(QemuDmaBuf *dmabuf); +int32_t qemu_dmabuf_get_fence_fd(QemuDmaBuf *dmabuf); +bool qemu_dmabuf_get_allow_fences(QemuDmaBuf *dmabuf); +bool qemu_dmabuf_get_draw_submitted(QemuDmaBuf *dmabuf); +void qemu_dmabuf_set_texture(QemuDmaBuf *dmabuf, uint32_t texture); +void
[PATCH v9 3/6] ui/console: Use qemu_dmabuf_get_..() helpers instead
From: Dongwon Kim This commit updates all instances where fields within the QemuDmaBuf struct are directly accessed, replacing them with calls to these new helper functions. v6: fix typos in helper names in ui/spice-display.c v7: removed prefix, "dpy_gl_" from all helpers v8: Introduction of helpers was removed as those were already added by the previous commit Suggested-by: Marc-André Lureau Reviewed-by: Marc-André Lureau Cc: Philippe Mathieu-Daudé Cc: Daniel P. Berrangé Cc: Vivek Kasireddy Signed-off-by: Dongwon Kim --- hw/display/vhost-user-gpu.c | 6 ++-- hw/display/virtio-gpu-udmabuf.c | 7 +++-- hw/vfio/display.c | 15 +++--- ui/console.c| 4 +-- ui/dbus-console.c | 9 -- ui/dbus-listener.c | 43 +--- ui/egl-headless.c | 23 ++- ui/egl-helpers.c| 47 ++- ui/gtk-egl.c| 48 --- ui/gtk-gl-area.c| 37 ui/gtk.c| 6 ++-- ui/spice-display.c | 50 +++-- 12 files changed, 187 insertions(+), 108 deletions(-) diff --git a/hw/display/vhost-user-gpu.c b/hw/display/vhost-user-gpu.c index 709c8a02a1..ea9a6c5d10 100644 --- a/hw/display/vhost-user-gpu.c +++ b/hw/display/vhost-user-gpu.c @@ -249,6 +249,7 @@ vhost_user_gpu_handle_display(VhostUserGPU *g, VhostUserGpuMsg *msg) case VHOST_USER_GPU_DMABUF_SCANOUT: { VhostUserGpuDMABUFScanout *m = >payload.dmabuf_scanout; int fd = qemu_chr_fe_get_msgfd(>vhost_chr); +int old_fd; QemuDmaBuf *dmabuf; if (m->scanout_id >= g->parent_obj.conf.max_outputs) { @@ -262,8 +263,9 @@ vhost_user_gpu_handle_display(VhostUserGPU *g, VhostUserGpuMsg *msg) g->parent_obj.enable = 1; con = g->parent_obj.scanout[m->scanout_id].con; dmabuf = >dmabuf[m->scanout_id]; -if (dmabuf->fd >= 0) { -close(dmabuf->fd); +old_fd = qemu_dmabuf_get_fd(dmabuf); +if (old_fd >= 0) { +close(old_fd); dmabuf->fd = -1; } dpy_gl_release_dmabuf(con, dmabuf); diff --git a/hw/display/virtio-gpu-udmabuf.c b/hw/display/virtio-gpu-udmabuf.c index d51184d658..c90eba281e 100644 --- a/hw/display/virtio-gpu-udmabuf.c +++ b/hw/display/virtio-gpu-udmabuf.c @@ -206,6 +206,7 @@ int virtio_gpu_update_dmabuf(VirtIOGPU *g, { struct virtio_gpu_scanout *scanout = >parent_obj.scanout[scanout_id]; VGPUDMABuf *new_primary, *old_primary = NULL; +uint32_t width, height; new_primary = virtio_gpu_create_dmabuf(g, scanout_id, res, fb, r); if (!new_primary) { @@ -216,10 +217,10 @@ int virtio_gpu_update_dmabuf(VirtIOGPU *g, old_primary = g->dmabuf.primary[scanout_id]; } +width = qemu_dmabuf_get_width(_primary->buf); +height = qemu_dmabuf_get_height(_primary->buf); g->dmabuf.primary[scanout_id] = new_primary; -qemu_console_resize(scanout->con, -new_primary->buf.width, -new_primary->buf.height); +qemu_console_resize(scanout->con, width, height); dpy_gl_scanout_dmabuf(scanout->con, _primary->buf); if (old_primary) { diff --git a/hw/vfio/display.c b/hw/vfio/display.c index 1aa440c663..4861c8161d 100644 --- a/hw/vfio/display.c +++ b/hw/vfio/display.c @@ -259,9 +259,13 @@ static VFIODMABuf *vfio_display_get_dmabuf(VFIOPCIDevice *vdev, static void vfio_display_free_one_dmabuf(VFIODisplay *dpy, VFIODMABuf *dmabuf) { +int fd; + QTAILQ_REMOVE(>dmabuf.bufs, dmabuf, next); + +fd = qemu_dmabuf_get_fd(>buf); dpy_gl_release_dmabuf(dpy->con, >buf); -close(dmabuf->buf.fd); +close(fd); g_free(dmabuf); } @@ -286,6 +290,7 @@ static void vfio_display_dmabuf_update(void *opaque) VFIOPCIDevice *vdev = opaque; VFIODisplay *dpy = vdev->dpy; VFIODMABuf *primary, *cursor; +uint32_t width, height; bool free_bufs = false, new_cursor = false; primary = vfio_display_get_dmabuf(vdev, DRM_PLANE_TYPE_PRIMARY); @@ -296,10 +301,12 @@ static void vfio_display_dmabuf_update(void *opaque) return; } +width = qemu_dmabuf_get_width(>buf); +height = qemu_dmabuf_get_height(>buf); + if (dpy->dmabuf.primary != primary) { dpy->dmabuf.primary = primary; -qemu_console_resize(dpy->con, -primary->buf.width, primary->buf.height); +qemu_console_resize(dpy->con, width, height); dpy_gl_scanout_dmabuf(dpy->con, >buf); free_bufs = true; } @@ -328,7 +335,7 @@ static void vfio_display_dmabuf_update(void *opaque) cursor->pos_updates = 0; } -dpy_
[PATCH v9 5/6] ui/console: Use qemu_dmabuf_new() and free() helpers instead
From: Dongwon Kim This commit introduces utility functions for the creation and deallocation of QemuDmaBuf instances. Additionally, it updates all relevant sections of the codebase to utilize these new utility functions. v7: remove prefix, "dpy_gl_" from all helpers qemu_dmabuf_free() returns without doing anything if input is null (Daniel P. Berrangé ) call G_DEFINE_AUTOPTR_CLEANUP_FUNC for qemu_dmabuf_free() (Daniel P. Berrangé ) v8: Introduction of helpers was removed as those were already added by the previous commit v9: set dmabuf->allow_fences to 'true' when dmabuf is created in virtio_gpu_create_dmabuf()/virtio-gpu-udmabuf.c removed unnecessary spaces were accidently added in the patch, 'ui/console: Use qemu_dmabuf_new() a...' Suggested-by: Marc-André Lureau Cc: Philippe Mathieu-Daudé Cc: Daniel P. Berrangé Cc: Vivek Kasireddy Signed-off-by: Dongwon Kim --- include/hw/vfio/vfio-common.h | 2 +- include/hw/virtio/virtio-gpu.h | 4 ++-- hw/display/vhost-user-gpu.c | 32 ++-- hw/display/virtio-gpu-udmabuf.c | 24 +--- hw/vfio/display.c | 26 -- ui/dbus-listener.c | 28 6 files changed, 54 insertions(+), 62 deletions(-) diff --git a/include/hw/vfio/vfio-common.h b/include/hw/vfio/vfio-common.h index b9da6c08ef..d66e27db02 100644 --- a/include/hw/vfio/vfio-common.h +++ b/include/hw/vfio/vfio-common.h @@ -148,7 +148,7 @@ typedef struct VFIOGroup { } VFIOGroup; typedef struct VFIODMABuf { -QemuDmaBuf buf; +QemuDmaBuf *buf; uint32_t pos_x, pos_y, pos_updates; uint32_t hot_x, hot_y, hot_updates; int dmabuf_id; diff --git a/include/hw/virtio/virtio-gpu.h b/include/hw/virtio/virtio-gpu.h index ed44cdad6b..56d6e821bf 100644 --- a/include/hw/virtio/virtio-gpu.h +++ b/include/hw/virtio/virtio-gpu.h @@ -169,7 +169,7 @@ struct VirtIOGPUBaseClass { DEFINE_PROP_UINT32("yres", _state, _conf.yres, 800) typedef struct VGPUDMABuf { -QemuDmaBuf buf; +QemuDmaBuf *buf; uint32_t scanout_id; QTAILQ_ENTRY(VGPUDMABuf) next; } VGPUDMABuf; @@ -238,7 +238,7 @@ struct VhostUserGPU { VhostUserBackend *vhost; int vhost_gpu_fd; /* closed by the chardev */ CharBackend vhost_chr; -QemuDmaBuf dmabuf[VIRTIO_GPU_MAX_SCANOUTS]; +QemuDmaBuf *dmabuf[VIRTIO_GPU_MAX_SCANOUTS]; bool backend_blocked; }; diff --git a/hw/display/vhost-user-gpu.c b/hw/display/vhost-user-gpu.c index ea9a6c5d10..c91a800455 100644 --- a/hw/display/vhost-user-gpu.c +++ b/hw/display/vhost-user-gpu.c @@ -250,6 +250,7 @@ vhost_user_gpu_handle_display(VhostUserGPU *g, VhostUserGpuMsg *msg) VhostUserGpuDMABUFScanout *m = >payload.dmabuf_scanout; int fd = qemu_chr_fe_get_msgfd(>vhost_chr); int old_fd; +uint64_t modifier = 0; QemuDmaBuf *dmabuf; if (m->scanout_id >= g->parent_obj.conf.max_outputs) { @@ -262,31 +263,34 @@ vhost_user_gpu_handle_display(VhostUserGPU *g, VhostUserGpuMsg *msg) g->parent_obj.enable = 1; con = g->parent_obj.scanout[m->scanout_id].con; -dmabuf = >dmabuf[m->scanout_id]; -old_fd = qemu_dmabuf_get_fd(dmabuf); -if (old_fd >= 0) { -close(old_fd); -dmabuf->fd = -1; +dmabuf = g->dmabuf[m->scanout_id]; +if (dmabuf) { +old_fd = qemu_dmabuf_get_fd(dmabuf); +if (old_fd >= 0) { +close(old_fd); +qemu_dmabuf_set_fd(dmabuf, -1); +} } dpy_gl_release_dmabuf(con, dmabuf); +g_clear_pointer(, qemu_dmabuf_free); if (fd == -1) { dpy_gl_scanout_disable(con); break; } -*dmabuf = (QemuDmaBuf) { -.fd = fd, -.width = m->fd_width, -.height = m->fd_height, -.stride = m->fd_stride, -.fourcc = m->fd_drm_fourcc, -.y0_top = m->fd_flags & VIRTIO_GPU_RESOURCE_FLAG_Y_0_TOP, -}; + if (msg->request == VHOST_USER_GPU_DMABUF_SCANOUT2) { VhostUserGpuDMABUFScanout2 *m2 = >payload.dmabuf_scanout2; -dmabuf->modifier = m2->modifier; +modifier = m2->modifier; } +dmabuf = qemu_dmabuf_new(m->fd_width, m->fd_height, + m->fd_stride, 0, 0, 0, 0, + m->fd_drm_fourcc, modifier, + fd, false, m->fd_flags & + VIRTIO_GPU_RESOURCE_FLAG_Y_0_TOP); + dpy_gl_scanout_dmabuf(con, dmabuf); +g->dmabuf[m->scanout_id] = dmabuf; break; } case VHOST_USER_GPU_DMABUF_UPDATE: { diff --git a/hw/display/virtio-gpu-udmabuf.c b/hw/display/virtio-gpu-udma
[PATCH v9 0/6] ui/console: Private QemuDmaBuf struct
From: Dongwon Kim This series introduces privacy enhancements to the QemuDmaBuf struct and its contained data to bolster security. it accomplishes this by introducing of helper functions for allocating, deallocating, and accessing individual fields within the struct and replacing all direct references to individual fields in the struct with methods using helpers throughout the codebase. This change was made based on a suggestion from Marc-André Lureau (Resumitting same patch series with this new cover-leter) v6: fixed some typos in patch - ui/console: Introduce dpy_gl_qemu_dmabuf_get_..() helpers) v7: included minor fix (ui/gtk: Check if fence_fd is equal to or greater than 0) (Marc-André Lureau ) migrated all helpers and QemuDmaBuf struct into dmabuf.c and their prototypes to dmabuf.h for better encapsulation (ui/dmabuf: New dmabuf.c and dmabuf.h..) (Daniel P. Berrangé and Marc-André Lureau ) removed 'dpy_gl' from all helpers' names Defined autoptr clean up function for QemuDmaBuf* (Daniel P. Berrangé ) Minor corrections v8: Introduce new dmabuf.c and dmabuf.h and all helper functions in the second patch in the series (ui/console: new dmabuf.h and dmabuf.c for QemuDma) (Philippe Mathieu-Daudé ) v9: set dmabuf->allow_fences true when it is created in virtio-gpu-udmabuf removed unnecessary spaces were added in the patch, 'ui/console: Use qemu_dmabuf_new() a...' Dongwon Kim (6): ui/gtk: Check if fence_fd is equal to or greater than 0 ui/console: new dmabuf.h and dmabuf.c for QemuDmaBuf struct and helpers ui/console: Use qemu_dmabuf_get_..() helpers instead ui/console: Use qemu_dmabuf_set_..() helpers instead ui/console: Use qemu_dmabuf_new() and free() helpers instead ui/console: move QemuDmaBuf struct def to dmabuf.c include/hw/vfio/vfio-common.h | 2 +- include/hw/virtio/virtio-gpu.h | 4 +- include/ui/console.h| 20 +-- include/ui/dmabuf.h | 64 + hw/display/vhost-user-gpu.c | 32 +++-- hw/display/virtio-gpu-udmabuf.c | 27 ++-- hw/vfio/display.c | 35 ++--- ui/console.c| 4 +- ui/dbus-console.c | 9 +- ui/dbus-listener.c | 71 +- ui/dmabuf.c | 225 ui/egl-headless.c | 23 +++- ui/egl-helpers.c| 59 + ui/gtk-egl.c| 52 +--- ui/gtk-gl-area.c| 41 -- ui/gtk.c| 12 +- ui/spice-display.c | 50 --- ui/meson.build | 1 + 18 files changed, 539 insertions(+), 192 deletions(-) create mode 100644 include/ui/dmabuf.h create mode 100644 ui/dmabuf.c -- 2.34.1
[PATCH v9 6/6] ui/console: move QemuDmaBuf struct def to dmabuf.c
From: Dongwon Kim To complete privatizing process of QemuDmaBuf, QemuDmaBuf struct def is moved to dmabuf.c Suggested-by: Marc-André Lureau Cc: Philippe Mathieu-Daudé Cc: Daniel P. Berrangé Cc: Vivek Kasireddy Signed-off-by: Dongwon Kim --- include/ui/dmabuf.h | 19 +-- ui/dmabuf.c | 19 +++ 2 files changed, 20 insertions(+), 18 deletions(-) diff --git a/include/ui/dmabuf.h b/include/ui/dmabuf.h index d01bddf523..f2026c351a 100644 --- a/include/ui/dmabuf.h +++ b/include/ui/dmabuf.h @@ -27,24 +27,7 @@ #ifndef DMABUF_H #define DMABUF_H -typedef struct QemuDmaBuf { -int fd; -uint32_t width; -uint32_t height; -uint32_t stride; -uint32_t fourcc; -uint64_t modifier; -uint32_t texture; -uint32_t x; -uint32_t y; -uint32_t backing_width; -uint32_t backing_height; -bool y0_top; -void *sync; -int fence_fd; -bool allow_fences; -bool draw_submitted; -} QemuDmaBuf; +typedef struct QemuDmaBuf QemuDmaBuf; QemuDmaBuf *qemu_dmabuf_new(uint32_t width, uint32_t height, uint32_t stride, uint32_t x, diff --git a/ui/dmabuf.c b/ui/dmabuf.c index f0878aa3a1..80169533b6 100644 --- a/ui/dmabuf.c +++ b/ui/dmabuf.c @@ -27,6 +27,25 @@ #include "qemu/osdep.h" #include "ui/dmabuf.h" +struct QemuDmaBuf { +int fd; +uint32_t width; +uint32_t height; +uint32_t stride; +uint32_t fourcc; +uint64_t modifier; +uint32_t texture; +uint32_t x; +uint32_t y; +uint32_t backing_width; +uint32_t backing_height; +bool y0_top; +void *sync; +int fence_fd; +bool allow_fences; +bool draw_submitted; +}; + QemuDmaBuf *qemu_dmabuf_new(uint32_t width, uint32_t height, uint32_t stride, uint32_t x, uint32_t y, uint32_t backing_width, -- 2.34.1
[PATCH v9 1/6] ui/gtk: Check if fence_fd is equal to or greater than 0
From: Dongwon Kim 'fence_fd' needs to be validated always before being referenced And the passing condition should include '== 0' as 0 is a valid value for the file descriptor. Suggested-by: Marc-André Lureau Cc: Philippe Mathieu-Daudé Cc: Daniel P. Berrangé Cc: Vivek Kasireddy Signed-off-by: Dongwon Kim --- ui/gtk-egl.c | 2 +- ui/gtk-gl-area.c | 2 +- ui/gtk.c | 10 ++ 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/ui/gtk-egl.c b/ui/gtk-egl.c index 3af5ac5bcf..955234429d 100644 --- a/ui/gtk-egl.c +++ b/ui/gtk-egl.c @@ -99,7 +99,7 @@ void gd_egl_draw(VirtualConsole *vc) #ifdef CONFIG_GBM if (dmabuf) { egl_dmabuf_create_fence(dmabuf); -if (dmabuf->fence_fd > 0) { +if (dmabuf->fence_fd >= 0) { qemu_set_fd_handler(dmabuf->fence_fd, gd_hw_gl_flushed, NULL, vc); return; } diff --git a/ui/gtk-gl-area.c b/ui/gtk-gl-area.c index 52dcac161e..7fffd0544e 100644 --- a/ui/gtk-gl-area.c +++ b/ui/gtk-gl-area.c @@ -86,7 +86,7 @@ void gd_gl_area_draw(VirtualConsole *vc) #ifdef CONFIG_GBM if (dmabuf) { egl_dmabuf_create_fence(dmabuf); -if (dmabuf->fence_fd > 0) { +if (dmabuf->fence_fd >= 0) { qemu_set_fd_handler(dmabuf->fence_fd, gd_hw_gl_flushed, NULL, vc); return; } diff --git a/ui/gtk.c b/ui/gtk.c index 810d7fc796..7819a86321 100644 --- a/ui/gtk.c +++ b/ui/gtk.c @@ -597,10 +597,12 @@ void gd_hw_gl_flushed(void *vcon) VirtualConsole *vc = vcon; QemuDmaBuf *dmabuf = vc->gfx.guest_fb.dmabuf; -qemu_set_fd_handler(dmabuf->fence_fd, NULL, NULL, NULL); -close(dmabuf->fence_fd); -dmabuf->fence_fd = -1; -graphic_hw_gl_block(vc->gfx.dcl.con, false); +if (dmabuf->fence_fd >= 0) { +qemu_set_fd_handler(dmabuf->fence_fd, NULL, NULL, NULL); +close(dmabuf->fence_fd); +dmabuf->fence_fd = -1; +graphic_hw_gl_block(vc->gfx.dcl.con, false); +} } /** DisplayState Callbacks (opengl version) **/ -- 2.34.1
[PATCH v9 4/6] ui/console: Use qemu_dmabuf_set_..() helpers instead
From: Dongwon Kim This commit updates all occurrences where these fields were set directly have been updated to utilize helper functions. v7: removed prefix, "dpy_gl_" from all helpers v8: Introduction of helpers was removed as those were already added by the previous commit Suggested-by: Marc-André Lureau Cc: Philippe Mathieu-Daudé Cc: Daniel P. Berrangé Cc: Vivek Kasireddy Signed-off-by: Dongwon Kim --- ui/egl-helpers.c | 16 +--- ui/gtk-egl.c | 4 ++-- ui/gtk-gl-area.c | 4 ++-- ui/gtk.c | 6 +++--- 4 files changed, 16 insertions(+), 14 deletions(-) diff --git a/ui/egl-helpers.c b/ui/egl-helpers.c index 3f96e63d25..99b2ebbe23 100644 --- a/ui/egl-helpers.c +++ b/ui/egl-helpers.c @@ -348,8 +348,8 @@ void egl_dmabuf_import_texture(QemuDmaBuf *dmabuf) return; } -glGenTextures(1, >texture); -texture = qemu_dmabuf_get_texture(dmabuf); +glGenTextures(1, ); +qemu_dmabuf_set_texture(dmabuf, texture); glBindTexture(GL_TEXTURE_2D, texture); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); @@ -368,7 +368,7 @@ void egl_dmabuf_release_texture(QemuDmaBuf *dmabuf) } glDeleteTextures(1, ); -dmabuf->texture = 0; +qemu_dmabuf_set_texture(dmabuf, 0); } void egl_dmabuf_create_sync(QemuDmaBuf *dmabuf) @@ -382,7 +382,7 @@ void egl_dmabuf_create_sync(QemuDmaBuf *dmabuf) sync = eglCreateSyncKHR(qemu_egl_display, EGL_SYNC_NATIVE_FENCE_ANDROID, NULL); if (sync != EGL_NO_SYNC_KHR) { -dmabuf->sync = sync; +qemu_dmabuf_set_sync(dmabuf, sync); } } } @@ -390,12 +390,14 @@ void egl_dmabuf_create_sync(QemuDmaBuf *dmabuf) void egl_dmabuf_create_fence(QemuDmaBuf *dmabuf) { void *sync = qemu_dmabuf_get_sync(dmabuf); +int fence_fd; if (sync) { -dmabuf->fence_fd = eglDupNativeFenceFDANDROID(qemu_egl_display, - sync); +fence_fd = eglDupNativeFenceFDANDROID(qemu_egl_display, + sync); +qemu_dmabuf_set_fence_fd(dmabuf, fence_fd); eglDestroySyncKHR(qemu_egl_display, sync); -dmabuf->sync = NULL; +qemu_dmabuf_set_sync(dmabuf, NULL); } } diff --git a/ui/gtk-egl.c b/ui/gtk-egl.c index 7a45daefa1..ec0bf45482 100644 --- a/ui/gtk-egl.c +++ b/ui/gtk-egl.c @@ -87,7 +87,7 @@ void gd_egl_draw(VirtualConsole *vc) if (!qemu_dmabuf_get_draw_submitted(dmabuf)) { return; } else { -dmabuf->draw_submitted = false; +qemu_dmabuf_set_draw_submitted(dmabuf, false); } } #endif @@ -381,7 +381,7 @@ void gd_egl_flush(DisplayChangeListener *dcl, if (vc->gfx.guest_fb.dmabuf && !qemu_dmabuf_get_draw_submitted(vc->gfx.guest_fb.dmabuf)) { graphic_hw_gl_block(vc->gfx.dcl.con, true); -vc->gfx.guest_fb.dmabuf->draw_submitted = true; +qemu_dmabuf_set_draw_submitted(vc->gfx.guest_fb.dmabuf, true); gtk_egl_set_scanout_mode(vc, true); gtk_widget_queue_draw_area(area, x, y, w, h); return; diff --git a/ui/gtk-gl-area.c b/ui/gtk-gl-area.c index 2d70280803..9a3f3d0d71 100644 --- a/ui/gtk-gl-area.c +++ b/ui/gtk-gl-area.c @@ -63,7 +63,7 @@ void gd_gl_area_draw(VirtualConsole *vc) if (!qemu_dmabuf_get_draw_submitted(dmabuf)) { return; } else { -dmabuf->draw_submitted = false; +qemu_dmabuf_set_draw_submitted(dmabuf, false); } } #endif @@ -291,7 +291,7 @@ void gd_gl_area_scanout_flush(DisplayChangeListener *dcl, if (vc->gfx.guest_fb.dmabuf && !qemu_dmabuf_get_draw_submitted(vc->gfx.guest_fb.dmabuf)) { graphic_hw_gl_block(vc->gfx.dcl.con, true); -vc->gfx.guest_fb.dmabuf->draw_submitted = true; +qemu_dmabuf_set_draw_submitted(vc->gfx.guest_fb.dmabuf, true); gtk_gl_area_set_scanout_mode(vc, true); } gtk_gl_area_queue_render(GTK_GL_AREA(vc->gfx.drawing_area)); diff --git a/ui/gtk.c b/ui/gtk.c index 237c913b26..3a6832eb1b 100644 --- a/ui/gtk.c +++ b/ui/gtk.c @@ -598,11 +598,11 @@ void gd_hw_gl_flushed(void *vcon) QemuDmaBuf *dmabuf = vc->gfx.guest_fb.dmabuf; int fence_fd; -if (dmabuf->fence_fd >= 0) { -fence_fd = qemu_dmabuf_get_fence_fd(dmabuf); +fence_fd = qemu_dmabuf_get_fence_fd(dmabuf); +if (fence_fd >= 0) { qemu_set_fd_handler(fence_fd, NULL, NULL, NULL); close(fence_fd); -dmabuf->fence_fd = -1; +qemu_dmabuf_set_fence_fd(dmabuf, -1); graphic_hw_gl_block(vc->gfx.dcl.con, false); } } -- 2.34.1
[PATCH v8 2/6] ui/console: new dmabuf.h and dmabuf.c for QemuDmaBuf struct and helpers
From: Dongwon Kim New header and source files are added for containing QemuDmaBuf struct definition and newly introduced helpers for creating/freeing the struct and accessing its data. Suggested-by: Marc-André Lureau Cc: Philippe Mathieu-Daudé Cc: Daniel P. Berrangé Cc: Vivek Kasireddy Signed-off-by: Dongwon Kim --- include/ui/console.h | 20 + include/ui/dmabuf.h | 81 + ui/dmabuf.c | 206 +++ ui/meson.build | 1 + 4 files changed, 289 insertions(+), 19 deletions(-) create mode 100644 include/ui/dmabuf.h create mode 100644 ui/dmabuf.c diff --git a/include/ui/console.h b/include/ui/console.h index 0bc7a00ac0..a208a68b88 100644 --- a/include/ui/console.h +++ b/include/ui/console.h @@ -7,6 +7,7 @@ #include "qapi/qapi-types-ui.h" #include "ui/input.h" #include "ui/surface.h" +#include "ui/dmabuf.h" #define TYPE_QEMU_CONSOLE "qemu-console" OBJECT_DECLARE_TYPE(QemuConsole, QemuConsoleClass, QEMU_CONSOLE) @@ -185,25 +186,6 @@ struct QEMUGLParams { int minor_ver; }; -typedef struct QemuDmaBuf { -int fd; -uint32_t width; -uint32_t height; -uint32_t stride; -uint32_t fourcc; -uint64_t modifier; -uint32_t texture; -uint32_t x; -uint32_t y; -uint32_t backing_width; -uint32_t backing_height; -bool y0_top; -void *sync; -int fence_fd; -bool allow_fences; -bool draw_submitted; -} QemuDmaBuf; - enum display_scanout { SCANOUT_NONE, SCANOUT_SURFACE, diff --git a/include/ui/dmabuf.h b/include/ui/dmabuf.h new file mode 100644 index 00..e332958c39 --- /dev/null +++ b/include/ui/dmabuf.h @@ -0,0 +1,81 @@ +/* + * SPDX-License-Identifier: MIT + * + * QemuDmaBuf struct and helpers used for accessing its data + * + * Copyright (c) 2024 Dongwon Kim + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef DMABUF_H +#define DMABUF_H + +typedef struct QemuDmaBuf { +int fd; +uint32_t width; +uint32_t height; +uint32_t stride; +uint32_t fourcc; +uint64_t modifier; +uint32_t texture; +uint32_t x; +uint32_t y; +uint32_t backing_width; +uint32_t backing_height; +bool y0_top; +void *sync; +int fence_fd; +bool allow_fences; +bool draw_submitted; +} QemuDmaBuf; + +QemuDmaBuf *qemu_dmabuf_new(uint32_t width, uint32_t height, + uint32_t stride, uint32_t x, + uint32_t y, uint32_t backing_width, + uint32_t backing_height, uint32_t fourcc, + uint64_t modifier, int32_t dmabuf_fd, + bool allow_fences, bool y0_top); +void qemu_dmabuf_free(QemuDmaBuf *dmabuf); + +G_DEFINE_AUTOPTR_CLEANUP_FUNC(QemuDmaBuf, qemu_dmabuf_free); + +int32_t qemu_dmabuf_get_fd(QemuDmaBuf *dmabuf); +uint32_t qemu_dmabuf_get_width(QemuDmaBuf *dmabuf); +uint32_t qemu_dmabuf_get_height(QemuDmaBuf *dmabuf); +uint32_t qemu_dmabuf_get_stride(QemuDmaBuf *dmabuf); +uint32_t qemu_dmabuf_get_fourcc(QemuDmaBuf *dmabuf); +uint64_t qemu_dmabuf_get_modifier(QemuDmaBuf *dmabuf); +uint32_t qemu_dmabuf_get_texture(QemuDmaBuf *dmabuf); +uint32_t qemu_dmabuf_get_x(QemuDmaBuf *dmabuf); +uint32_t qemu_dmabuf_get_y(QemuDmaBuf *dmabuf); +uint32_t qemu_dmabuf_get_backing_width(QemuDmaBuf *dmabuf); +uint32_t qemu_dmabuf_get_backing_height(QemuDmaBuf *dmabuf); +bool qemu_dmabuf_get_y0_top(QemuDmaBuf *dmabuf); +void *qemu_dmabuf_get_sync(QemuDmaBuf *dmabuf); +int32_t qemu_dmabuf_get_fence_fd(QemuDmaBuf *dmabuf); +bool qemu_dmabuf_get_allow_fences(QemuDmaBuf *dmabuf); +bool qemu_dmabuf_get_draw_submitted(QemuDmaBuf *dmabuf); +void qemu_dmabuf_set_texture(QemuDmaBuf *dmabuf, uint32_t texture); +void
[PATCH v8 5/6] ui/console: Use qemu_dmabuf_new() and free() helpers instead
From: Dongwon Kim This commit introduces utility functions for the creation and deallocation of QemuDmaBuf instances. Additionally, it updates all relevant sections of the codebase to utilize these new utility functions. v7: remove prefix, "dpy_gl_" from all helpers qemu_dmabuf_free() returns without doing anything if input is null (Daniel P. Berrangé ) call G_DEFINE_AUTOPTR_CLEANUP_FUNC for qemu_dmabuf_free() (Daniel P. Berrangé ) v8: Introduction of helpers was removed as those were already added by the previous commit Suggested-by: Marc-André Lureau Cc: Philippe Mathieu-Daudé Cc: Daniel P. Berrangé Cc: Vivek Kasireddy Signed-off-by: Dongwon Kim --- include/hw/vfio/vfio-common.h | 2 +- include/hw/virtio/virtio-gpu.h | 4 ++-- hw/display/vhost-user-gpu.c | 32 ++-- hw/display/virtio-gpu-udmabuf.c | 24 +--- hw/vfio/display.c | 26 -- ui/dbus-listener.c | 28 6 files changed, 54 insertions(+), 62 deletions(-) diff --git a/include/hw/vfio/vfio-common.h b/include/hw/vfio/vfio-common.h index b9da6c08ef..d66e27db02 100644 --- a/include/hw/vfio/vfio-common.h +++ b/include/hw/vfio/vfio-common.h @@ -148,7 +148,7 @@ typedef struct VFIOGroup { } VFIOGroup; typedef struct VFIODMABuf { -QemuDmaBuf buf; +QemuDmaBuf *buf; uint32_t pos_x, pos_y, pos_updates; uint32_t hot_x, hot_y, hot_updates; int dmabuf_id; diff --git a/include/hw/virtio/virtio-gpu.h b/include/hw/virtio/virtio-gpu.h index ed44cdad6b..56d6e821bf 100644 --- a/include/hw/virtio/virtio-gpu.h +++ b/include/hw/virtio/virtio-gpu.h @@ -169,7 +169,7 @@ struct VirtIOGPUBaseClass { DEFINE_PROP_UINT32("yres", _state, _conf.yres, 800) typedef struct VGPUDMABuf { -QemuDmaBuf buf; +QemuDmaBuf *buf; uint32_t scanout_id; QTAILQ_ENTRY(VGPUDMABuf) next; } VGPUDMABuf; @@ -238,7 +238,7 @@ struct VhostUserGPU { VhostUserBackend *vhost; int vhost_gpu_fd; /* closed by the chardev */ CharBackend vhost_chr; -QemuDmaBuf dmabuf[VIRTIO_GPU_MAX_SCANOUTS]; +QemuDmaBuf *dmabuf[VIRTIO_GPU_MAX_SCANOUTS]; bool backend_blocked; }; diff --git a/hw/display/vhost-user-gpu.c b/hw/display/vhost-user-gpu.c index ea9a6c5d10..7f8cf38647 100644 --- a/hw/display/vhost-user-gpu.c +++ b/hw/display/vhost-user-gpu.c @@ -250,6 +250,7 @@ vhost_user_gpu_handle_display(VhostUserGPU *g, VhostUserGpuMsg *msg) VhostUserGpuDMABUFScanout *m = >payload.dmabuf_scanout; int fd = qemu_chr_fe_get_msgfd(>vhost_chr); int old_fd; +uint64_t modifier = 0; QemuDmaBuf *dmabuf; if (m->scanout_id >= g->parent_obj.conf.max_outputs) { @@ -262,31 +263,34 @@ vhost_user_gpu_handle_display(VhostUserGPU *g, VhostUserGpuMsg *msg) g->parent_obj.enable = 1; con = g->parent_obj.scanout[m->scanout_id].con; -dmabuf = >dmabuf[m->scanout_id]; -old_fd = qemu_dmabuf_get_fd(dmabuf); -if (old_fd >= 0) { -close(old_fd); -dmabuf->fd = -1; +dmabuf = g->dmabuf[m->scanout_id]; +if (dmabuf) { +old_fd = qemu_dmabuf_get_fd(dmabuf); +if (old_fd >= 0) { +close(old_fd); +qemu_dmabuf_set_fd(dmabuf, -1); +} } dpy_gl_release_dmabuf(con, dmabuf); +g_clear_pointer(, qemu_dmabuf_free); if (fd == -1) { dpy_gl_scanout_disable(con); break; } -*dmabuf = (QemuDmaBuf) { -.fd = fd, -.width = m->fd_width, -.height = m->fd_height, -.stride = m->fd_stride, -.fourcc = m->fd_drm_fourcc, -.y0_top = m->fd_flags & VIRTIO_GPU_RESOURCE_FLAG_Y_0_TOP, -}; + if (msg->request == VHOST_USER_GPU_DMABUF_SCANOUT2) { VhostUserGpuDMABUFScanout2 *m2 = >payload.dmabuf_scanout2; -dmabuf->modifier = m2->modifier; +modifier = m2->modifier; } +dmabuf = qemu_dmabuf_new(m->fd_width, m->fd_height, +m->fd_stride, 0, 0, 0, 0, +m->fd_drm_fourcc, modifier, +fd, false, m->fd_flags & +VIRTIO_GPU_RESOURCE_FLAG_Y_0_TOP); + dpy_gl_scanout_dmabuf(con, dmabuf); +g->dmabuf[m->scanout_id] = dmabuf; break; } case VHOST_USER_GPU_DMABUF_UPDATE: { diff --git a/hw/display/virtio-gpu-udmabuf.c b/hw/display/virtio-gpu-udmabuf.c index c90eba281e..edd7886cf2 100644 --- a/hw/display/virtio-gpu-udmabuf.c +++ b/hw/display/virtio-gpu-udmabuf.c @@ -162,7 +162,8 @@ static void virtio_gpu_free_dmabuf(VirtIOG
[PATCH v8 1/6] ui/gtk: Check if fence_fd is equal to or greater than 0
From: Dongwon Kim 'fence_fd' needs to be validated always before being referenced And the passing condition should include '== 0' as 0 is a valid value for the file descriptor. Suggested-by: Marc-André Lureau Cc: Philippe Mathieu-Daudé Cc: Daniel P. Berrangé Cc: Vivek Kasireddy Signed-off-by: Dongwon Kim --- ui/gtk-egl.c | 2 +- ui/gtk-gl-area.c | 2 +- ui/gtk.c | 10 ++ 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/ui/gtk-egl.c b/ui/gtk-egl.c index 3af5ac5bcf..955234429d 100644 --- a/ui/gtk-egl.c +++ b/ui/gtk-egl.c @@ -99,7 +99,7 @@ void gd_egl_draw(VirtualConsole *vc) #ifdef CONFIG_GBM if (dmabuf) { egl_dmabuf_create_fence(dmabuf); -if (dmabuf->fence_fd > 0) { +if (dmabuf->fence_fd >= 0) { qemu_set_fd_handler(dmabuf->fence_fd, gd_hw_gl_flushed, NULL, vc); return; } diff --git a/ui/gtk-gl-area.c b/ui/gtk-gl-area.c index 52dcac161e..7fffd0544e 100644 --- a/ui/gtk-gl-area.c +++ b/ui/gtk-gl-area.c @@ -86,7 +86,7 @@ void gd_gl_area_draw(VirtualConsole *vc) #ifdef CONFIG_GBM if (dmabuf) { egl_dmabuf_create_fence(dmabuf); -if (dmabuf->fence_fd > 0) { +if (dmabuf->fence_fd >= 0) { qemu_set_fd_handler(dmabuf->fence_fd, gd_hw_gl_flushed, NULL, vc); return; } diff --git a/ui/gtk.c b/ui/gtk.c index 810d7fc796..7819a86321 100644 --- a/ui/gtk.c +++ b/ui/gtk.c @@ -597,10 +597,12 @@ void gd_hw_gl_flushed(void *vcon) VirtualConsole *vc = vcon; QemuDmaBuf *dmabuf = vc->gfx.guest_fb.dmabuf; -qemu_set_fd_handler(dmabuf->fence_fd, NULL, NULL, NULL); -close(dmabuf->fence_fd); -dmabuf->fence_fd = -1; -graphic_hw_gl_block(vc->gfx.dcl.con, false); +if (dmabuf->fence_fd >= 0) { +qemu_set_fd_handler(dmabuf->fence_fd, NULL, NULL, NULL); +close(dmabuf->fence_fd); +dmabuf->fence_fd = -1; +graphic_hw_gl_block(vc->gfx.dcl.con, false); +} } /** DisplayState Callbacks (opengl version) **/ -- 2.34.1
[PATCH v8 6/6] ui/console: move QemuDmaBuf struct def to dmabuf.c
From: Dongwon Kim To complete privatizing process of QemuDmaBuf, QemuDmaBuf struct def is moved to dmabuf.c Suggested-by: Marc-André Lureau Cc: Philippe Mathieu-Daudé Cc: Daniel P. Berrangé Cc: Vivek Kasireddy Signed-off-by: Dongwon Kim --- include/ui/dmabuf.h | 19 +-- ui/dmabuf.c | 19 +++ 2 files changed, 20 insertions(+), 18 deletions(-) diff --git a/include/ui/dmabuf.h b/include/ui/dmabuf.h index e332958c39..0723846a3a 100644 --- a/include/ui/dmabuf.h +++ b/include/ui/dmabuf.h @@ -27,24 +27,7 @@ #ifndef DMABUF_H #define DMABUF_H -typedef struct QemuDmaBuf { -int fd; -uint32_t width; -uint32_t height; -uint32_t stride; -uint32_t fourcc; -uint64_t modifier; -uint32_t texture; -uint32_t x; -uint32_t y; -uint32_t backing_width; -uint32_t backing_height; -bool y0_top; -void *sync; -int fence_fd; -bool allow_fences; -bool draw_submitted; -} QemuDmaBuf; +typedef struct QemuDmaBuf QemuDmaBuf; QemuDmaBuf *qemu_dmabuf_new(uint32_t width, uint32_t height, uint32_t stride, uint32_t x, diff --git a/ui/dmabuf.c b/ui/dmabuf.c index ef3b07956e..7a919160dc 100644 --- a/ui/dmabuf.c +++ b/ui/dmabuf.c @@ -27,6 +27,25 @@ #include "qemu/osdep.h" #include "ui/dmabuf.h" +struct QemuDmaBuf { +int fd; +uint32_t width; +uint32_t height; +uint32_t stride; +uint32_t fourcc; +uint64_t modifier; +uint32_t texture; +uint32_t x; +uint32_t y; +uint32_t backing_width; +uint32_t backing_height; +bool y0_top; +void *sync; +int fence_fd; +bool allow_fences; +bool draw_submitted; +}; + QemuDmaBuf *qemu_dmabuf_new(uint32_t width, uint32_t height, uint32_t stride, uint32_t x, uint32_t y, uint32_t backing_width, -- 2.34.1
[PATCH v8 0/6] ui/console: Private QemuDmaBuf struct
From: Dongwon Kim This series introduces privacy enhancements to the QemuDmaBuf struct and its contained data to bolster security. it accomplishes this by introducing of helper functions for allocating, deallocating, and accessing individual fields within the struct and replacing all direct references to individual fields in the struct with methods using helpers throughout the codebase. This change was made based on a suggestion from Marc-André Lureau (Resumitting same patch series with this new cover-leter) v6: fixed some typos in patch - ui/console: Introduce dpy_gl_qemu_dmabuf_get_..() helpers) v7: included minor fix (ui/gtk: Check if fence_fd is equal to or greater than 0) (Marc-André Lureau ) migrated all helpers and QemuDmaBuf struct into dmabuf.c and their prototypes to dmabuf.h for better encapsulation (ui/dmabuf: New dmabuf.c and dmabuf.h..) (Daniel P. Berrangé and Marc-André Lureau ) removed 'dpy_gl' from all helpers' names Defined autoptr clean up function for QemuDmaBuf* (Daniel P. Berrangé ) Minor corrections v8: Introduce new dmabuf.c and dmabuf.h and all helper functions in the second patch in the series (ui/console: new dmabuf.h and dmabuf.c for QemuDma) (Philippe Mathieu-Daudé ) Move QemuDmaBuf struct definition to dmabuf.c in the last patch in the series (ui/console: move QemuDmaBuf struct def...) to mitigates compilation errors encountered during the midpoint of the series. Dongwon Kim (6): ui/gtk: Check if fence_fd is equal to or greater than 0 ui/console: new dmabuf.h and dmabuf.c for QemuDmaBuf struct and helpers ui/console: Use qemu_dmabuf_get_..() helpers instead ui/console: Use qemu_dmabuf_set_..() helpers instead ui/console: Use qemu_dmabuf_new() and free() helpers instead ui/console: move QemuDmaBuf struct def to dmabuf.c include/hw/vfio/vfio-common.h | 2 +- include/hw/virtio/virtio-gpu.h | 4 +- include/ui/console.h| 20 +-- include/ui/dmabuf.h | 64 + hw/display/vhost-user-gpu.c | 32 +++-- hw/display/virtio-gpu-udmabuf.c | 27 ++-- hw/vfio/display.c | 35 ++--- ui/console.c| 4 +- ui/dbus-console.c | 9 +- ui/dbus-listener.c | 71 +- ui/dmabuf.c | 225 ui/egl-headless.c | 23 +++- ui/egl-helpers.c| 59 + ui/gtk-egl.c| 52 +--- ui/gtk-gl-area.c| 41 -- ui/gtk.c| 12 +- ui/spice-display.c | 50 --- ui/meson.build | 1 + 18 files changed, 539 insertions(+), 192 deletions(-) create mode 100644 include/ui/dmabuf.h create mode 100644 ui/dmabuf.c -- 2.34.1
[PATCH v8 4/6] ui/console: Use qemu_dmabuf_set_..() helpers instead
From: Dongwon Kim This commit updates all occurrences where these fields were set directly have been updated to utilize helper functions. v7: removed prefix, "dpy_gl_" from all helpers v8: Introduction of helpers was removed as those were already added by the previous commit Suggested-by: Marc-André Lureau Cc: Philippe Mathieu-Daudé Cc: Daniel P. Berrangé Cc: Vivek Kasireddy Signed-off-by: Dongwon Kim --- ui/egl-helpers.c | 16 +--- ui/gtk-egl.c | 4 ++-- ui/gtk-gl-area.c | 4 ++-- ui/gtk.c | 6 +++--- 4 files changed, 16 insertions(+), 14 deletions(-) diff --git a/ui/egl-helpers.c b/ui/egl-helpers.c index 3f96e63d25..99b2ebbe23 100644 --- a/ui/egl-helpers.c +++ b/ui/egl-helpers.c @@ -348,8 +348,8 @@ void egl_dmabuf_import_texture(QemuDmaBuf *dmabuf) return; } -glGenTextures(1, >texture); -texture = qemu_dmabuf_get_texture(dmabuf); +glGenTextures(1, ); +qemu_dmabuf_set_texture(dmabuf, texture); glBindTexture(GL_TEXTURE_2D, texture); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); @@ -368,7 +368,7 @@ void egl_dmabuf_release_texture(QemuDmaBuf *dmabuf) } glDeleteTextures(1, ); -dmabuf->texture = 0; +qemu_dmabuf_set_texture(dmabuf, 0); } void egl_dmabuf_create_sync(QemuDmaBuf *dmabuf) @@ -382,7 +382,7 @@ void egl_dmabuf_create_sync(QemuDmaBuf *dmabuf) sync = eglCreateSyncKHR(qemu_egl_display, EGL_SYNC_NATIVE_FENCE_ANDROID, NULL); if (sync != EGL_NO_SYNC_KHR) { -dmabuf->sync = sync; +qemu_dmabuf_set_sync(dmabuf, sync); } } } @@ -390,12 +390,14 @@ void egl_dmabuf_create_sync(QemuDmaBuf *dmabuf) void egl_dmabuf_create_fence(QemuDmaBuf *dmabuf) { void *sync = qemu_dmabuf_get_sync(dmabuf); +int fence_fd; if (sync) { -dmabuf->fence_fd = eglDupNativeFenceFDANDROID(qemu_egl_display, - sync); +fence_fd = eglDupNativeFenceFDANDROID(qemu_egl_display, + sync); +qemu_dmabuf_set_fence_fd(dmabuf, fence_fd); eglDestroySyncKHR(qemu_egl_display, sync); -dmabuf->sync = NULL; +qemu_dmabuf_set_sync(dmabuf, NULL); } } diff --git a/ui/gtk-egl.c b/ui/gtk-egl.c index 7a45daefa1..ec0bf45482 100644 --- a/ui/gtk-egl.c +++ b/ui/gtk-egl.c @@ -87,7 +87,7 @@ void gd_egl_draw(VirtualConsole *vc) if (!qemu_dmabuf_get_draw_submitted(dmabuf)) { return; } else { -dmabuf->draw_submitted = false; +qemu_dmabuf_set_draw_submitted(dmabuf, false); } } #endif @@ -381,7 +381,7 @@ void gd_egl_flush(DisplayChangeListener *dcl, if (vc->gfx.guest_fb.dmabuf && !qemu_dmabuf_get_draw_submitted(vc->gfx.guest_fb.dmabuf)) { graphic_hw_gl_block(vc->gfx.dcl.con, true); -vc->gfx.guest_fb.dmabuf->draw_submitted = true; +qemu_dmabuf_set_draw_submitted(vc->gfx.guest_fb.dmabuf, true); gtk_egl_set_scanout_mode(vc, true); gtk_widget_queue_draw_area(area, x, y, w, h); return; diff --git a/ui/gtk-gl-area.c b/ui/gtk-gl-area.c index 2d70280803..9a3f3d0d71 100644 --- a/ui/gtk-gl-area.c +++ b/ui/gtk-gl-area.c @@ -63,7 +63,7 @@ void gd_gl_area_draw(VirtualConsole *vc) if (!qemu_dmabuf_get_draw_submitted(dmabuf)) { return; } else { -dmabuf->draw_submitted = false; +qemu_dmabuf_set_draw_submitted(dmabuf, false); } } #endif @@ -291,7 +291,7 @@ void gd_gl_area_scanout_flush(DisplayChangeListener *dcl, if (vc->gfx.guest_fb.dmabuf && !qemu_dmabuf_get_draw_submitted(vc->gfx.guest_fb.dmabuf)) { graphic_hw_gl_block(vc->gfx.dcl.con, true); -vc->gfx.guest_fb.dmabuf->draw_submitted = true; +qemu_dmabuf_set_draw_submitted(vc->gfx.guest_fb.dmabuf, true); gtk_gl_area_set_scanout_mode(vc, true); } gtk_gl_area_queue_render(GTK_GL_AREA(vc->gfx.drawing_area)); diff --git a/ui/gtk.c b/ui/gtk.c index 237c913b26..3a6832eb1b 100644 --- a/ui/gtk.c +++ b/ui/gtk.c @@ -598,11 +598,11 @@ void gd_hw_gl_flushed(void *vcon) QemuDmaBuf *dmabuf = vc->gfx.guest_fb.dmabuf; int fence_fd; -if (dmabuf->fence_fd >= 0) { -fence_fd = qemu_dmabuf_get_fence_fd(dmabuf); +fence_fd = qemu_dmabuf_get_fence_fd(dmabuf); +if (fence_fd >= 0) { qemu_set_fd_handler(fence_fd, NULL, NULL, NULL); close(fence_fd); -dmabuf->fence_fd = -1; +qemu_dmabuf_set_fence_fd(dmabuf, -1); graphic_hw_gl_block(vc->gfx.dcl.con, false); } } -- 2.34.1
[PATCH v8 3/6] ui/console: Use qemu_dmabuf_get_..() helpers instead
From: Dongwon Kim This commit updates all instances where fields within the QemuDmaBuf struct are directly accessed, replacing them with calls to these new helper functions. v6: fix typos in helper names in ui/spice-display.c v7: removed prefix, "dpy_gl_" from all helpers v8: Introduction of helpers was removed as those were already added by the previous commit Suggested-by: Marc-André Lureau Reviewed-by: Marc-André Lureau Cc: Philippe Mathieu-Daudé Cc: Daniel P. Berrangé Cc: Vivek Kasireddy Signed-off-by: Dongwon Kim --- hw/display/vhost-user-gpu.c | 6 ++-- hw/display/virtio-gpu-udmabuf.c | 7 +++-- hw/vfio/display.c | 15 +++--- ui/console.c| 4 +-- ui/dbus-console.c | 9 -- ui/dbus-listener.c | 43 +--- ui/egl-headless.c | 23 ++- ui/egl-helpers.c| 47 ++- ui/gtk-egl.c| 48 --- ui/gtk-gl-area.c| 37 ui/gtk.c| 6 ++-- ui/spice-display.c | 50 +++-- 12 files changed, 187 insertions(+), 108 deletions(-) diff --git a/hw/display/vhost-user-gpu.c b/hw/display/vhost-user-gpu.c index 709c8a02a1..ea9a6c5d10 100644 --- a/hw/display/vhost-user-gpu.c +++ b/hw/display/vhost-user-gpu.c @@ -249,6 +249,7 @@ vhost_user_gpu_handle_display(VhostUserGPU *g, VhostUserGpuMsg *msg) case VHOST_USER_GPU_DMABUF_SCANOUT: { VhostUserGpuDMABUFScanout *m = >payload.dmabuf_scanout; int fd = qemu_chr_fe_get_msgfd(>vhost_chr); +int old_fd; QemuDmaBuf *dmabuf; if (m->scanout_id >= g->parent_obj.conf.max_outputs) { @@ -262,8 +263,9 @@ vhost_user_gpu_handle_display(VhostUserGPU *g, VhostUserGpuMsg *msg) g->parent_obj.enable = 1; con = g->parent_obj.scanout[m->scanout_id].con; dmabuf = >dmabuf[m->scanout_id]; -if (dmabuf->fd >= 0) { -close(dmabuf->fd); +old_fd = qemu_dmabuf_get_fd(dmabuf); +if (old_fd >= 0) { +close(old_fd); dmabuf->fd = -1; } dpy_gl_release_dmabuf(con, dmabuf); diff --git a/hw/display/virtio-gpu-udmabuf.c b/hw/display/virtio-gpu-udmabuf.c index d51184d658..c90eba281e 100644 --- a/hw/display/virtio-gpu-udmabuf.c +++ b/hw/display/virtio-gpu-udmabuf.c @@ -206,6 +206,7 @@ int virtio_gpu_update_dmabuf(VirtIOGPU *g, { struct virtio_gpu_scanout *scanout = >parent_obj.scanout[scanout_id]; VGPUDMABuf *new_primary, *old_primary = NULL; +uint32_t width, height; new_primary = virtio_gpu_create_dmabuf(g, scanout_id, res, fb, r); if (!new_primary) { @@ -216,10 +217,10 @@ int virtio_gpu_update_dmabuf(VirtIOGPU *g, old_primary = g->dmabuf.primary[scanout_id]; } +width = qemu_dmabuf_get_width(_primary->buf); +height = qemu_dmabuf_get_height(_primary->buf); g->dmabuf.primary[scanout_id] = new_primary; -qemu_console_resize(scanout->con, -new_primary->buf.width, -new_primary->buf.height); +qemu_console_resize(scanout->con, width, height); dpy_gl_scanout_dmabuf(scanout->con, _primary->buf); if (old_primary) { diff --git a/hw/vfio/display.c b/hw/vfio/display.c index 1aa440c663..4861c8161d 100644 --- a/hw/vfio/display.c +++ b/hw/vfio/display.c @@ -259,9 +259,13 @@ static VFIODMABuf *vfio_display_get_dmabuf(VFIOPCIDevice *vdev, static void vfio_display_free_one_dmabuf(VFIODisplay *dpy, VFIODMABuf *dmabuf) { +int fd; + QTAILQ_REMOVE(>dmabuf.bufs, dmabuf, next); + +fd = qemu_dmabuf_get_fd(>buf); dpy_gl_release_dmabuf(dpy->con, >buf); -close(dmabuf->buf.fd); +close(fd); g_free(dmabuf); } @@ -286,6 +290,7 @@ static void vfio_display_dmabuf_update(void *opaque) VFIOPCIDevice *vdev = opaque; VFIODisplay *dpy = vdev->dpy; VFIODMABuf *primary, *cursor; +uint32_t width, height; bool free_bufs = false, new_cursor = false; primary = vfio_display_get_dmabuf(vdev, DRM_PLANE_TYPE_PRIMARY); @@ -296,10 +301,12 @@ static void vfio_display_dmabuf_update(void *opaque) return; } +width = qemu_dmabuf_get_width(>buf); +height = qemu_dmabuf_get_height(>buf); + if (dpy->dmabuf.primary != primary) { dpy->dmabuf.primary = primary; -qemu_console_resize(dpy->con, -primary->buf.width, primary->buf.height); +qemu_console_resize(dpy->con, width, height); dpy_gl_scanout_dmabuf(dpy->con, >buf); free_bufs = true; } @@ -328,7 +335,7 @@ static void vfio_display_dmabuf_update(void *opaque) cursor->pos_updates = 0; } -dpy_
[PATCH v7 4/5] ui/console: Introduce qemu_dmabuf_new() and free() helpers
From: Dongwon Kim This commit introduces utility functions for the creation and deallocation of QemuDmaBuf instances. Additionally, it updates all relevant sections of the codebase to utilize these new utility functions. v7: remove prefix, "dpy_gl_" from all helpers qemu_dmabuf_free() returns without doing anything if input is null (Daniel P. Berrangé ) call G_DEFINE_AUTOPTR_CLEANUP_FUNC for qemu_dmabuf_free() (Daniel P. Berrangé ) Suggested-by: Marc-André Lureau Cc: Philippe Mathieu-Daudé Cc: Daniel P. Berrangé Cc: Vivek Kasireddy Signed-off-by: Dongwon Kim --- include/hw/vfio/vfio-common.h | 2 +- include/hw/virtio/virtio-gpu.h | 4 ++-- include/ui/console.h| 9 + hw/display/vhost-user-gpu.c | 32 - hw/display/virtio-gpu-udmabuf.c | 24 +- hw/vfio/display.c | 26 +++- ui/console.c| 36 + ui/dbus-listener.c | 28 +++-- 8 files changed, 99 insertions(+), 62 deletions(-) diff --git a/include/hw/vfio/vfio-common.h b/include/hw/vfio/vfio-common.h index b9da6c08ef..d66e27db02 100644 --- a/include/hw/vfio/vfio-common.h +++ b/include/hw/vfio/vfio-common.h @@ -148,7 +148,7 @@ typedef struct VFIOGroup { } VFIOGroup; typedef struct VFIODMABuf { -QemuDmaBuf buf; +QemuDmaBuf *buf; uint32_t pos_x, pos_y, pos_updates; uint32_t hot_x, hot_y, hot_updates; int dmabuf_id; diff --git a/include/hw/virtio/virtio-gpu.h b/include/hw/virtio/virtio-gpu.h index ed44cdad6b..56d6e821bf 100644 --- a/include/hw/virtio/virtio-gpu.h +++ b/include/hw/virtio/virtio-gpu.h @@ -169,7 +169,7 @@ struct VirtIOGPUBaseClass { DEFINE_PROP_UINT32("yres", _state, _conf.yres, 800) typedef struct VGPUDMABuf { -QemuDmaBuf buf; +QemuDmaBuf *buf; uint32_t scanout_id; QTAILQ_ENTRY(VGPUDMABuf) next; } VGPUDMABuf; @@ -238,7 +238,7 @@ struct VhostUserGPU { VhostUserBackend *vhost; int vhost_gpu_fd; /* closed by the chardev */ CharBackend vhost_chr; -QemuDmaBuf dmabuf[VIRTIO_GPU_MAX_SCANOUTS]; +QemuDmaBuf *dmabuf[VIRTIO_GPU_MAX_SCANOUTS]; bool backend_blocked; }; diff --git a/include/ui/console.h b/include/ui/console.h index 92a7d0d468..b47135bc2f 100644 --- a/include/ui/console.h +++ b/include/ui/console.h @@ -358,6 +358,15 @@ void dpy_gl_cursor_dmabuf(QemuConsole *con, QemuDmaBuf *dmabuf, bool have_hot, uint32_t hot_x, uint32_t hot_y); void dpy_gl_cursor_position(QemuConsole *con, uint32_t pos_x, uint32_t pos_y); +QemuDmaBuf *qemu_dmabuf_new(uint32_t width, uint32_t height, + uint32_t stride, uint32_t x, + uint32_t y, uint32_t backing_width, + uint32_t backing_height, uint32_t fourcc, + uint64_t modifier, int32_t dmabuf_fd, + bool allow_fences, bool y0_top); +void qemu_dmabuf_free(QemuDmaBuf *dmabuf); + +G_DEFINE_AUTOPTR_CLEANUP_FUNC(QemuDmaBuf, qemu_dmabuf_free); int32_t qemu_dmabuf_get_fd(QemuDmaBuf *dmabuf); uint32_t qemu_dmabuf_get_width(QemuDmaBuf *dmabuf); diff --git a/hw/display/vhost-user-gpu.c b/hw/display/vhost-user-gpu.c index ea9a6c5d10..7f8cf38647 100644 --- a/hw/display/vhost-user-gpu.c +++ b/hw/display/vhost-user-gpu.c @@ -250,6 +250,7 @@ vhost_user_gpu_handle_display(VhostUserGPU *g, VhostUserGpuMsg *msg) VhostUserGpuDMABUFScanout *m = >payload.dmabuf_scanout; int fd = qemu_chr_fe_get_msgfd(>vhost_chr); int old_fd; +uint64_t modifier = 0; QemuDmaBuf *dmabuf; if (m->scanout_id >= g->parent_obj.conf.max_outputs) { @@ -262,31 +263,34 @@ vhost_user_gpu_handle_display(VhostUserGPU *g, VhostUserGpuMsg *msg) g->parent_obj.enable = 1; con = g->parent_obj.scanout[m->scanout_id].con; -dmabuf = >dmabuf[m->scanout_id]; -old_fd = qemu_dmabuf_get_fd(dmabuf); -if (old_fd >= 0) { -close(old_fd); -dmabuf->fd = -1; +dmabuf = g->dmabuf[m->scanout_id]; +if (dmabuf) { +old_fd = qemu_dmabuf_get_fd(dmabuf); +if (old_fd >= 0) { +close(old_fd); +qemu_dmabuf_set_fd(dmabuf, -1); +} } dpy_gl_release_dmabuf(con, dmabuf); +g_clear_pointer(, qemu_dmabuf_free); if (fd == -1) { dpy_gl_scanout_disable(con); break; } -*dmabuf = (QemuDmaBuf) { -.fd = fd, -.width = m->fd_width, -.height = m->fd_height, -.stride = m->fd_stride, -.fourcc = m->fd_drm_fourcc, -.y0_top = m->fd_flags & VIRTIO_GPU_RESOURCE_FLA
[PATCH v7 5/5] ui/dmabuf: New dmabuf.c and dmabuf.h for QemuDmaBuf struct and helpers
From: Dongwon Kim Create new header and source files to encapsulate QemuDmaBuf struct and its data for privatization. Suggested-by: Marc-André Lureau Cc: Philippe Mathieu-Daudé Cc: Daniel P. Berrangé Cc: Vivek Kasireddy Signed-off-by: Dongwon Kim --- include/ui/console.h | 52 +- include/ui/dmabuf.h | 38 ui/console.c | 179 +- ui/dmabuf.c | 223 +++ ui/meson.build | 1 + 5 files changed, 264 insertions(+), 229 deletions(-) create mode 100644 include/ui/dmabuf.h create mode 100644 ui/dmabuf.c diff --git a/include/ui/console.h b/include/ui/console.h index b47135bc2f..5e5c4b6951 100644 --- a/include/ui/console.h +++ b/include/ui/console.h @@ -7,6 +7,7 @@ #include "qapi/qapi-types-ui.h" #include "ui/input.h" #include "ui/surface.h" +#include "ui/dmabuf.h" #define TYPE_QEMU_CONSOLE "qemu-console" OBJECT_DECLARE_TYPE(QemuConsole, QemuConsoleClass, QEMU_CONSOLE) @@ -185,25 +186,6 @@ struct QEMUGLParams { int minor_ver; }; -typedef struct QemuDmaBuf { -int fd; -uint32_t width; -uint32_t height; -uint32_t stride; -uint32_t fourcc; -uint64_t modifier; -uint32_t texture; -uint32_t x; -uint32_t y; -uint32_t backing_width; -uint32_t backing_height; -bool y0_top; -void *sync; -int fence_fd; -bool allow_fences; -bool draw_submitted; -} QemuDmaBuf; - enum display_scanout { SCANOUT_NONE, SCANOUT_SURFACE, @@ -358,42 +340,10 @@ void dpy_gl_cursor_dmabuf(QemuConsole *con, QemuDmaBuf *dmabuf, bool have_hot, uint32_t hot_x, uint32_t hot_y); void dpy_gl_cursor_position(QemuConsole *con, uint32_t pos_x, uint32_t pos_y); -QemuDmaBuf *qemu_dmabuf_new(uint32_t width, uint32_t height, - uint32_t stride, uint32_t x, - uint32_t y, uint32_t backing_width, - uint32_t backing_height, uint32_t fourcc, - uint64_t modifier, int32_t dmabuf_fd, - bool allow_fences, bool y0_top); -void qemu_dmabuf_free(QemuDmaBuf *dmabuf); - -G_DEFINE_AUTOPTR_CLEANUP_FUNC(QemuDmaBuf, qemu_dmabuf_free); - -int32_t qemu_dmabuf_get_fd(QemuDmaBuf *dmabuf); -uint32_t qemu_dmabuf_get_width(QemuDmaBuf *dmabuf); -uint32_t qemu_dmabuf_get_height(QemuDmaBuf *dmabuf); -uint32_t qemu_dmabuf_get_stride(QemuDmaBuf *dmabuf); -uint32_t qemu_dmabuf_get_fourcc(QemuDmaBuf *dmabuf); -uint64_t qemu_dmabuf_get_modifier(QemuDmaBuf *dmabuf); -uint32_t qemu_dmabuf_get_texture(QemuDmaBuf *dmabuf); -uint32_t qemu_dmabuf_get_x(QemuDmaBuf *dmabuf); -uint32_t qemu_dmabuf_get_y(QemuDmaBuf *dmabuf); -uint32_t qemu_dmabuf_get_backing_width(QemuDmaBuf *dmabuf); -uint32_t qemu_dmabuf_get_backing_height(QemuDmaBuf *dmabuf); -bool qemu_dmabuf_get_y0_top(QemuDmaBuf *dmabuf); -void *qemu_dmabuf_get_sync(QemuDmaBuf *dmabuf); -int32_t qemu_dmabuf_get_fence_fd(QemuDmaBuf *dmabuf); -bool qemu_dmabuf_get_allow_fences(QemuDmaBuf *dmabuf); -bool qemu_dmabuf_get_draw_submitted(QemuDmaBuf *dmabuf); -void qemu_dmabuf_set_texture(QemuDmaBuf *dmabuf, uint32_t texture); -void qemu_dmabuf_set_fence_fd(QemuDmaBuf *dmabuf, int32_t fence_fd); -void qemu_dmabuf_set_sync(QemuDmaBuf *dmabuf, void *sync); -void qemu_dmabuf_set_draw_submitted(QemuDmaBuf *dmabuf, bool draw_submitted); -void qemu_dmabuf_set_fd(QemuDmaBuf *dmabuf, int32_t fd); void dpy_gl_release_dmabuf(QemuConsole *con, QemuDmaBuf *dmabuf); void dpy_gl_update(QemuConsole *con, uint32_t x, uint32_t y, uint32_t w, uint32_t h); - QEMUGLContext dpy_gl_ctx_create(QemuConsole *con, QEMUGLParams *params); void dpy_gl_ctx_destroy(QemuConsole *con, QEMUGLContext ctx); diff --git a/include/ui/dmabuf.h b/include/ui/dmabuf.h new file mode 100644 index 00..8de33cd1ab --- /dev/null +++ b/include/ui/dmabuf.h @@ -0,0 +1,38 @@ +#ifndef DMABUF_H +#define DMABUF_H + +typedef struct QemuDmaBuf QemuDmaBuf; + +QemuDmaBuf *qemu_dmabuf_new(uint32_t width, uint32_t height, + uint32_t stride, uint32_t x, + uint32_t y, uint32_t backing_width, + uint32_t backing_height, uint32_t fourcc, + uint64_t modifier, int32_t dmabuf_fd, + bool allow_fences, bool y0_top); +void qemu_dmabuf_free(QemuDmaBuf *dmabuf); + +G_DEFINE_AUTOPTR_CLEANUP_FUNC(QemuDmaBuf, qemu_dmabuf_free); + +int32_t qemu_dmabuf_get_fd(QemuDmaBuf *dmabuf); +uint32_t qemu_dmabuf_get_width(QemuDmaBuf *dmabuf); +uint32_t qemu_dmabuf_get_height(QemuDmaBuf *dmabuf); +uint32_t qemu_dmabuf_get_stride(QemuDmaBuf *dmabuf); +uint32_t qem
[PATCH v7 2/5] ui/console: Introduce qemu_dmabuf_get_..() helpers
From: Dongwon Kim This commit introduces qemu_dmabuf_get_... helpers to extract specific fields from the QemuDmaBuf struct. It also updates all instances where fields within the QemuDmaBuf struct are directly accessed, replacing them with calls to these new helper functions. v6: fix typos in helper names in ui/spice-display.c v7: removed prefix, "dpy_gl_" from all helpers Suggested-by: Marc-André Lureau Reviewed-by: Marc-André Lureau Cc: Philippe Mathieu-Daudé Cc: Daniel P. Berrangé Cc: Vivek Kasireddy Signed-off-by: Dongwon Kim --- include/ui/console.h| 17 + hw/display/vhost-user-gpu.c | 6 +- hw/display/virtio-gpu-udmabuf.c | 7 +- hw/vfio/display.c | 15 +++-- ui/console.c| 116 +++- ui/dbus-console.c | 9 ++- ui/dbus-listener.c | 43 +++- ui/egl-headless.c | 23 +-- ui/egl-helpers.c| 47 +++-- ui/gtk-egl.c| 48 - ui/gtk-gl-area.c| 37 ++ ui/gtk.c| 6 +- ui/spice-display.c | 50 -- 13 files changed, 316 insertions(+), 108 deletions(-) diff --git a/include/ui/console.h b/include/ui/console.h index 0bc7a00ac0..d845f67182 100644 --- a/include/ui/console.h +++ b/include/ui/console.h @@ -358,6 +358,23 @@ void dpy_gl_cursor_dmabuf(QemuConsole *con, QemuDmaBuf *dmabuf, bool have_hot, uint32_t hot_x, uint32_t hot_y); void dpy_gl_cursor_position(QemuConsole *con, uint32_t pos_x, uint32_t pos_y); + +int32_t qemu_dmabuf_get_fd(QemuDmaBuf *dmabuf); +uint32_t qemu_dmabuf_get_width(QemuDmaBuf *dmabuf); +uint32_t qemu_dmabuf_get_height(QemuDmaBuf *dmabuf); +uint32_t qemu_dmabuf_get_stride(QemuDmaBuf *dmabuf); +uint32_t qemu_dmabuf_get_fourcc(QemuDmaBuf *dmabuf); +uint64_t qemu_dmabuf_get_modifier(QemuDmaBuf *dmabuf); +uint32_t qemu_dmabuf_get_texture(QemuDmaBuf *dmabuf); +uint32_t qemu_dmabuf_get_x(QemuDmaBuf *dmabuf); +uint32_t qemu_dmabuf_get_y(QemuDmaBuf *dmabuf); +uint32_t qemu_dmabuf_get_backing_width(QemuDmaBuf *dmabuf); +uint32_t qemu_dmabuf_get_backing_height(QemuDmaBuf *dmabuf); +bool qemu_dmabuf_get_y0_top(QemuDmaBuf *dmabuf); +void *qemu_dmabuf_get_sync(QemuDmaBuf *dmabuf); +int32_t qemu_dmabuf_get_fence_fd(QemuDmaBuf *dmabuf); +bool qemu_dmabuf_get_allow_fences(QemuDmaBuf *dmabuf); +bool qemu_dmabuf_get_draw_submitted(QemuDmaBuf *dmabuf); void dpy_gl_release_dmabuf(QemuConsole *con, QemuDmaBuf *dmabuf); void dpy_gl_update(QemuConsole *con, diff --git a/hw/display/vhost-user-gpu.c b/hw/display/vhost-user-gpu.c index 709c8a02a1..ea9a6c5d10 100644 --- a/hw/display/vhost-user-gpu.c +++ b/hw/display/vhost-user-gpu.c @@ -249,6 +249,7 @@ vhost_user_gpu_handle_display(VhostUserGPU *g, VhostUserGpuMsg *msg) case VHOST_USER_GPU_DMABUF_SCANOUT: { VhostUserGpuDMABUFScanout *m = >payload.dmabuf_scanout; int fd = qemu_chr_fe_get_msgfd(>vhost_chr); +int old_fd; QemuDmaBuf *dmabuf; if (m->scanout_id >= g->parent_obj.conf.max_outputs) { @@ -262,8 +263,9 @@ vhost_user_gpu_handle_display(VhostUserGPU *g, VhostUserGpuMsg *msg) g->parent_obj.enable = 1; con = g->parent_obj.scanout[m->scanout_id].con; dmabuf = >dmabuf[m->scanout_id]; -if (dmabuf->fd >= 0) { -close(dmabuf->fd); +old_fd = qemu_dmabuf_get_fd(dmabuf); +if (old_fd >= 0) { +close(old_fd); dmabuf->fd = -1; } dpy_gl_release_dmabuf(con, dmabuf); diff --git a/hw/display/virtio-gpu-udmabuf.c b/hw/display/virtio-gpu-udmabuf.c index d51184d658..c90eba281e 100644 --- a/hw/display/virtio-gpu-udmabuf.c +++ b/hw/display/virtio-gpu-udmabuf.c @@ -206,6 +206,7 @@ int virtio_gpu_update_dmabuf(VirtIOGPU *g, { struct virtio_gpu_scanout *scanout = >parent_obj.scanout[scanout_id]; VGPUDMABuf *new_primary, *old_primary = NULL; +uint32_t width, height; new_primary = virtio_gpu_create_dmabuf(g, scanout_id, res, fb, r); if (!new_primary) { @@ -216,10 +217,10 @@ int virtio_gpu_update_dmabuf(VirtIOGPU *g, old_primary = g->dmabuf.primary[scanout_id]; } +width = qemu_dmabuf_get_width(_primary->buf); +height = qemu_dmabuf_get_height(_primary->buf); g->dmabuf.primary[scanout_id] = new_primary; -qemu_console_resize(scanout->con, -new_primary->buf.width, -new_primary->buf.height); +qemu_console_resize(scanout->con, width, height); dpy_gl_scanout_dmabuf(scanout->con, _primary->buf); if (old_primary) { diff --git a/hw/vfio/display.c b/hw/vfio/display.c index 1aa440c663..4861c8161d 100644 --- a/hw/vfio/display.c +++ b/hw/vfio/display.c @@ -259,9 +2
[PATCH v7 3/5] ui/console: Introduce qemu_dmabuf_set_..() helpers
From: Dongwon Kim To enhance security in accessing the QemuDmaBuf struct, new helper functions for setting specific fields within the struct were introduced. And all occurrences where these fields were previously set directly have been updated to utilize these helper functions. v7: removed prefix, "dpy_gl_" from all helpers Suggested-by: Marc-André Lureau Cc: Philippe Mathieu-Daudé Cc: Daniel P. Berrangé Cc: Vivek Kasireddy Signed-off-by: Dongwon Kim --- include/ui/console.h | 5 + ui/console.c | 30 ++ ui/egl-helpers.c | 16 +--- ui/gtk-egl.c | 4 ++-- ui/gtk-gl-area.c | 4 ++-- ui/gtk.c | 6 +++--- 6 files changed, 51 insertions(+), 14 deletions(-) diff --git a/include/ui/console.h b/include/ui/console.h index d845f67182..92a7d0d468 100644 --- a/include/ui/console.h +++ b/include/ui/console.h @@ -375,6 +375,11 @@ void *qemu_dmabuf_get_sync(QemuDmaBuf *dmabuf); int32_t qemu_dmabuf_get_fence_fd(QemuDmaBuf *dmabuf); bool qemu_dmabuf_get_allow_fences(QemuDmaBuf *dmabuf); bool qemu_dmabuf_get_draw_submitted(QemuDmaBuf *dmabuf); +void qemu_dmabuf_set_texture(QemuDmaBuf *dmabuf, uint32_t texture); +void qemu_dmabuf_set_fence_fd(QemuDmaBuf *dmabuf, int32_t fence_fd); +void qemu_dmabuf_set_sync(QemuDmaBuf *dmabuf, void *sync); +void qemu_dmabuf_set_draw_submitted(QemuDmaBuf *dmabuf, bool draw_submitted); +void qemu_dmabuf_set_fd(QemuDmaBuf *dmabuf, int32_t fd); void dpy_gl_release_dmabuf(QemuConsole *con, QemuDmaBuf *dmabuf); void dpy_gl_update(QemuConsole *con, diff --git a/ui/console.c b/ui/console.c index 1bba3324d5..bd16ea7a4a 100644 --- a/ui/console.c +++ b/ui/console.c @@ -1244,6 +1244,36 @@ bool qemu_dmabuf_get_draw_submitted(QemuDmaBuf *dmabuf) return dmabuf->draw_submitted; } +void qemu_dmabuf_set_texture(QemuDmaBuf *dmabuf, uint32_t texture) +{ +assert(dmabuf != NULL); +dmabuf->texture = texture; +} + +void qemu_dmabuf_set_fence_fd(QemuDmaBuf *dmabuf, int32_t fence_fd) +{ +assert(dmabuf != NULL); +dmabuf->fence_fd = fence_fd; +} + +void qemu_dmabuf_set_sync(QemuDmaBuf *dmabuf, void *sync) +{ +assert(dmabuf != NULL); +dmabuf->sync = sync; +} + +void qemu_dmabuf_set_draw_submitted(QemuDmaBuf *dmabuf, bool draw_submitted) +{ +assert(dmabuf != NULL); +dmabuf->draw_submitted = draw_submitted; +} + +void qemu_dmabuf_set_fd(QemuDmaBuf *dmabuf, int32_t fd) +{ +assert(dmabuf != NULL); +dmabuf->fd = fd; +} + void dpy_gl_release_dmabuf(QemuConsole *con, QemuDmaBuf *dmabuf) { diff --git a/ui/egl-helpers.c b/ui/egl-helpers.c index 3f96e63d25..99b2ebbe23 100644 --- a/ui/egl-helpers.c +++ b/ui/egl-helpers.c @@ -348,8 +348,8 @@ void egl_dmabuf_import_texture(QemuDmaBuf *dmabuf) return; } -glGenTextures(1, >texture); -texture = qemu_dmabuf_get_texture(dmabuf); +glGenTextures(1, ); +qemu_dmabuf_set_texture(dmabuf, texture); glBindTexture(GL_TEXTURE_2D, texture); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); @@ -368,7 +368,7 @@ void egl_dmabuf_release_texture(QemuDmaBuf *dmabuf) } glDeleteTextures(1, ); -dmabuf->texture = 0; +qemu_dmabuf_set_texture(dmabuf, 0); } void egl_dmabuf_create_sync(QemuDmaBuf *dmabuf) @@ -382,7 +382,7 @@ void egl_dmabuf_create_sync(QemuDmaBuf *dmabuf) sync = eglCreateSyncKHR(qemu_egl_display, EGL_SYNC_NATIVE_FENCE_ANDROID, NULL); if (sync != EGL_NO_SYNC_KHR) { -dmabuf->sync = sync; +qemu_dmabuf_set_sync(dmabuf, sync); } } } @@ -390,12 +390,14 @@ void egl_dmabuf_create_sync(QemuDmaBuf *dmabuf) void egl_dmabuf_create_fence(QemuDmaBuf *dmabuf) { void *sync = qemu_dmabuf_get_sync(dmabuf); +int fence_fd; if (sync) { -dmabuf->fence_fd = eglDupNativeFenceFDANDROID(qemu_egl_display, - sync); +fence_fd = eglDupNativeFenceFDANDROID(qemu_egl_display, + sync); +qemu_dmabuf_set_fence_fd(dmabuf, fence_fd); eglDestroySyncKHR(qemu_egl_display, sync); -dmabuf->sync = NULL; +qemu_dmabuf_set_sync(dmabuf, NULL); } } diff --git a/ui/gtk-egl.c b/ui/gtk-egl.c index 7a45daefa1..ec0bf45482 100644 --- a/ui/gtk-egl.c +++ b/ui/gtk-egl.c @@ -87,7 +87,7 @@ void gd_egl_draw(VirtualConsole *vc) if (!qemu_dmabuf_get_draw_submitted(dmabuf)) { return; } else { -dmabuf->draw_submitted = false; +qemu_dmabuf_set_draw_submitted(dmabuf, false); } } #endif @@ -381,7 +381,7 @@ void gd_egl_flush(DisplayChangeListener *dcl, if (vc->gfx.guest_fb.dmabuf &&
[PATCH v7 0/5] ui/console: Private QemuDmaBuf struct
From: Dongwon Kim This series introduces privacy enhancements to the QemuDmaBuf struct and its contained data to bolster security. it accomplishes this by introducing of helper functions for allocating, deallocating, and accessing individual fields within the struct and replacing all direct references to individual fields in the struct with methods using helpers throughout the codebase. This change was made based on a suggestion from Marc-André Lureau (Resumitting same patch series with this new cover-leter) v6: fixed some typos in patch - ui/console: Introduce dpy_gl_qemu_dmabuf_get_..() helpers) v7: included minor fix (ui/gtk: Check if fence_fd is equal to or greater than 0) (Marc-André Lureau ) migrated all helpers and QemuDmaBuf struct into dmabuf.c and their prototypes to dmabuf.h for better encapsulation (ui/dmabuf: New dmabuf.c and dmabuf.h..) (Daniel P. Berrangé and Marc-André Lureau ) removed 'dpy_gl' from all helpers' names Defined autoptr clean up function for QemuDmaBuf* (Daniel P. Berrangé ) Minor corrections Dongwon Kim (5): ui/gtk: Check if fence_fd is equal to or greater than 0 ui/console: Introduce qemu_dmabuf_get_..() helpers ui/console: Introduce qemu_dmabuf_set_..() helpers ui/console: Introduce qemu_dmabuf_new() and free() helpers ui/dmabuf: New dmabuf.c and dmabuf.h for QemuDmaBuf struct and helpers include/hw/vfio/vfio-common.h | 2 +- include/hw/virtio/virtio-gpu.h | 4 +- include/ui/console.h| 21 +-- include/ui/dmabuf.h | 38 ++ hw/display/vhost-user-gpu.c | 32 +++-- hw/display/virtio-gpu-udmabuf.c | 27 ++-- hw/vfio/display.c | 35 ++--- ui/console.c| 5 +- ui/dbus-console.c | 9 +- ui/dbus-listener.c | 71 +- ui/dmabuf.c | 223 ui/egl-headless.c | 23 +++- ui/egl-helpers.c| 59 + ui/gtk-egl.c| 52 +--- ui/gtk-gl-area.c| 41 -- ui/gtk.c| 12 +- ui/spice-display.c | 50 --- ui/meson.build | 1 + 18 files changed, 512 insertions(+), 193 deletions(-) create mode 100644 include/ui/dmabuf.h create mode 100644 ui/dmabuf.c -- 2.34.1
[PATCH v7 1/5] ui/gtk: Check if fence_fd is equal to or greater than 0
From: Dongwon Kim 'fence_fd' needs to be validated always before being referenced And the passing condition should include '== 0' as 0 is a valid value for the file descriptor. Suggested-by: Marc-André Lureau Cc: Philippe Mathieu-Daudé Cc: Daniel P. Berrangé Cc: Vivek Kasireddy Signed-off-by: Dongwon Kim --- ui/gtk-egl.c | 2 +- ui/gtk-gl-area.c | 2 +- ui/gtk.c | 10 ++ 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/ui/gtk-egl.c b/ui/gtk-egl.c index 3af5ac5bcf..955234429d 100644 --- a/ui/gtk-egl.c +++ b/ui/gtk-egl.c @@ -99,7 +99,7 @@ void gd_egl_draw(VirtualConsole *vc) #ifdef CONFIG_GBM if (dmabuf) { egl_dmabuf_create_fence(dmabuf); -if (dmabuf->fence_fd > 0) { +if (dmabuf->fence_fd >= 0) { qemu_set_fd_handler(dmabuf->fence_fd, gd_hw_gl_flushed, NULL, vc); return; } diff --git a/ui/gtk-gl-area.c b/ui/gtk-gl-area.c index 52dcac161e..7fffd0544e 100644 --- a/ui/gtk-gl-area.c +++ b/ui/gtk-gl-area.c @@ -86,7 +86,7 @@ void gd_gl_area_draw(VirtualConsole *vc) #ifdef CONFIG_GBM if (dmabuf) { egl_dmabuf_create_fence(dmabuf); -if (dmabuf->fence_fd > 0) { +if (dmabuf->fence_fd >= 0) { qemu_set_fd_handler(dmabuf->fence_fd, gd_hw_gl_flushed, NULL, vc); return; } diff --git a/ui/gtk.c b/ui/gtk.c index 810d7fc796..7819a86321 100644 --- a/ui/gtk.c +++ b/ui/gtk.c @@ -597,10 +597,12 @@ void gd_hw_gl_flushed(void *vcon) VirtualConsole *vc = vcon; QemuDmaBuf *dmabuf = vc->gfx.guest_fb.dmabuf; -qemu_set_fd_handler(dmabuf->fence_fd, NULL, NULL, NULL); -close(dmabuf->fence_fd); -dmabuf->fence_fd = -1; -graphic_hw_gl_block(vc->gfx.dcl.con, false); +if (dmabuf->fence_fd >= 0) { +qemu_set_fd_handler(dmabuf->fence_fd, NULL, NULL, NULL); +close(dmabuf->fence_fd); +dmabuf->fence_fd = -1; +graphic_hw_gl_block(vc->gfx.dcl.con, false); +} } /** DisplayState Callbacks (opengl version) **/ -- 2.34.1
[PATCH v6 2/3] ui/console: Introduce dpy_gl_qemu_dmabuf_set_..() helpers
From: Dongwon Kim To enhance security in accessing the QemuDmaBuf struct, new helper functions for setting specific fields within the struct were introduced. And all occurrences where these fields were previously set directly have been updated to utilize these helper functions. Suggested-by: Marc-André Lureau Cc: Philippe Mathieu-Daudé Cc: Vivek Kasireddy Signed-off-by: Dongwon Kim --- include/ui/console.h | 5 + ui/console.c | 30 ++ ui/egl-helpers.c | 16 +--- ui/gtk-egl.c | 4 ++-- ui/gtk-gl-area.c | 4 ++-- ui/gtk.c | 2 +- 6 files changed, 49 insertions(+), 12 deletions(-) diff --git a/include/ui/console.h b/include/ui/console.h index 6292943a82..3d9d8b9fce 100644 --- a/include/ui/console.h +++ b/include/ui/console.h @@ -375,6 +375,11 @@ void *dpy_gl_qemu_dmabuf_get_sync(QemuDmaBuf *dmabuf); int32_t dpy_gl_qemu_dmabuf_get_fence_fd(QemuDmaBuf *dmabuf); bool dpy_gl_qemu_dmabuf_get_allow_fences(QemuDmaBuf *dmabuf); bool dpy_gl_qemu_dmabuf_get_draw_submitted(QemuDmaBuf *dmabuf); +void dpy_gl_qemu_dmabuf_set_texture(QemuDmaBuf *dmabuf, uint32_t texture); +void dpy_gl_qemu_dmabuf_set_fence_fd(QemuDmaBuf *dmabuf, int32_t fence_fd); +void dpy_gl_qemu_dmabuf_set_sync(QemuDmaBuf *dmabuf, void *sync); +void dpy_gl_qemu_dmabuf_set_draw_submitted(QemuDmaBuf *dmabuf, bool draw_submitted); +void dpy_gl_qemu_dmabuf_set_fd(QemuDmaBuf *dmabuf, int32_t fd); void dpy_gl_release_dmabuf(QemuConsole *con, QemuDmaBuf *dmabuf); void dpy_gl_update(QemuConsole *con, diff --git a/ui/console.c b/ui/console.c index 5d5635f783..d4ca9e6e0f 100644 --- a/ui/console.c +++ b/ui/console.c @@ -1244,6 +1244,36 @@ bool dpy_gl_qemu_dmabuf_get_draw_submitted(QemuDmaBuf *dmabuf) return dmabuf->draw_submitted; } +void dpy_gl_qemu_dmabuf_set_texture(QemuDmaBuf *dmabuf, uint32_t texture) +{ +assert(dmabuf != NULL); +dmabuf->texture = texture; +} + +void dpy_gl_qemu_dmabuf_set_fence_fd(QemuDmaBuf *dmabuf, int32_t fence_fd) +{ +assert(dmabuf != NULL); +dmabuf->fence_fd = fence_fd; +} + +void dpy_gl_qemu_dmabuf_set_sync(QemuDmaBuf *dmabuf, void *sync) +{ +assert(dmabuf != NULL); +dmabuf->sync = sync; +} + +void dpy_gl_qemu_dmabuf_set_draw_submitted(QemuDmaBuf *dmabuf, bool draw_submitted) +{ +assert(dmabuf != NULL); +dmabuf->draw_submitted = draw_submitted; +} + +void dpy_gl_qemu_dmabuf_set_fd(QemuDmaBuf *dmabuf, int32_t fd) +{ +assert(dmabuf != NULL); +dmabuf->fd = fd; +} + void dpy_gl_release_dmabuf(QemuConsole *con, QemuDmaBuf *dmabuf) { diff --git a/ui/egl-helpers.c b/ui/egl-helpers.c index 86d64c68ce..c71a2878c2 100644 --- a/ui/egl-helpers.c +++ b/ui/egl-helpers.c @@ -348,8 +348,8 @@ void egl_dmabuf_import_texture(QemuDmaBuf *dmabuf) return; } -glGenTextures(1, >texture); -texture = dpy_gl_qemu_dmabuf_get_texture(dmabuf); +glGenTextures(1, ); +dpy_gl_qemu_dmabuf_set_texture(dmabuf, texture); glBindTexture(GL_TEXTURE_2D, texture); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); @@ -368,7 +368,7 @@ void egl_dmabuf_release_texture(QemuDmaBuf *dmabuf) } glDeleteTextures(1, ); -dmabuf->texture = 0; +dpy_gl_qemu_dmabuf_set_texture(dmabuf, 0); } void egl_dmabuf_create_sync(QemuDmaBuf *dmabuf) @@ -382,7 +382,7 @@ void egl_dmabuf_create_sync(QemuDmaBuf *dmabuf) sync = eglCreateSyncKHR(qemu_egl_display, EGL_SYNC_NATIVE_FENCE_ANDROID, NULL); if (sync != EGL_NO_SYNC_KHR) { -dmabuf->sync = sync; +dpy_gl_qemu_dmabuf_set_sync(dmabuf, sync); } } } @@ -390,12 +390,14 @@ void egl_dmabuf_create_sync(QemuDmaBuf *dmabuf) void egl_dmabuf_create_fence(QemuDmaBuf *dmabuf) { void *sync = dpy_gl_qemu_dmabuf_get_sync(dmabuf); +int fence_fd; if (sync) { -dmabuf->fence_fd = eglDupNativeFenceFDANDROID(qemu_egl_display, - sync); +fence_fd = eglDupNativeFenceFDANDROID(qemu_egl_display, + sync); +dpy_gl_qemu_dmabuf_set_fence_fd(dmabuf, fence_fd); eglDestroySyncKHR(qemu_egl_display, sync); -dmabuf->sync = NULL; +dpy_gl_qemu_dmabuf_set_sync(dmabuf, NULL); } } diff --git a/ui/gtk-egl.c b/ui/gtk-egl.c index c9469af9ed..7494a34d7c 100644 --- a/ui/gtk-egl.c +++ b/ui/gtk-egl.c @@ -87,7 +87,7 @@ void gd_egl_draw(VirtualConsole *vc) if (!dpy_gl_qemu_dmabuf_get_draw_submitted(dmabuf)) { return; } else { -dmabuf->draw_submitted = false; +dpy_gl_qemu_dmabuf_set_draw_submitted(dmabuf, false); } } #endif @@ -381,7 +381,7 @@ void gd_egl_flush(Dis
[PATCH v6 0/3] ui/console: Private QemuDmaBuf struct
From: Dongwon Kim This series introduces privacy enhancements to the QemuDmaBuf struct and its contained data to bolster security. it accomplishes this by introducing of helper functions for allocating, deallocating, and accessing individual fields within the struct and replacing all direct references to individual fields in the struct with methods using helpers throughout the codebase. This change was made based on a suggestion from Marc-André Lureau (Resumitting same patch series with this new cover-leter) v6: fixed some typos in patch - ui/console: Introduce dpy_gl_qemu_dmabuf_get_..() helpers) Dongwon Kim (3): ui/console: Introduce dpy_gl_qemu_dmabuf_get_..() helpers ui/console: Introduce dpy_gl_qemu_dmabuf_set_..() helpers ui/console: Introduce dpy_gl_qemu_dmabuf_new() and free() helpers include/hw/vfio/vfio-common.h | 2 +- include/hw/virtio/virtio-gpu.h | 4 +- include/ui/console.h| 28 + hw/display/vhost-user-gpu.c | 32 +++--- hw/display/virtio-gpu-udmabuf.c | 27 ++--- hw/vfio/display.c | 35 --- ui/console.c| 180 +++- ui/dbus-console.c | 9 +- ui/dbus-listener.c | 71 +++-- ui/egl-headless.c | 23 ++-- ui/egl-helpers.c| 59 ++- ui/gtk-egl.c| 52 + ui/gtk-gl-area.c| 41 +--- ui/gtk.c| 8 +- ui/spice-display.c | 50 + 15 files changed, 449 insertions(+), 172 deletions(-) -- 2.34.1
[PATCH v6 3/3] ui/console: Introduce dpy_gl_qemu_dmabuf_new() and free() helpers
From: Dongwon Kim This commit introduces utility functions for the creation and deallocation of QemuDmaBuf instances. Additionally, it updates all relevant sections of the codebase to utilize these new utility functions. Suggested-by: Marc-André Lureau Cc: Philippe Mathieu-Daudé Cc: Vivek Kasireddy Signed-off-by: Dongwon Kim --- include/hw/vfio/vfio-common.h | 2 +- include/hw/virtio/virtio-gpu.h | 4 ++-- include/ui/console.h| 8 +++- hw/display/vhost-user-gpu.c | 32 +-- hw/display/virtio-gpu-udmabuf.c | 24 +-- hw/vfio/display.c | 26 - ui/console.c| 34 + ui/dbus-listener.c | 28 --- 8 files changed, 95 insertions(+), 63 deletions(-) diff --git a/include/hw/vfio/vfio-common.h b/include/hw/vfio/vfio-common.h index b9da6c08ef..d66e27db02 100644 --- a/include/hw/vfio/vfio-common.h +++ b/include/hw/vfio/vfio-common.h @@ -148,7 +148,7 @@ typedef struct VFIOGroup { } VFIOGroup; typedef struct VFIODMABuf { -QemuDmaBuf buf; +QemuDmaBuf *buf; uint32_t pos_x, pos_y, pos_updates; uint32_t hot_x, hot_y, hot_updates; int dmabuf_id; diff --git a/include/hw/virtio/virtio-gpu.h b/include/hw/virtio/virtio-gpu.h index ed44cdad6b..56d6e821bf 100644 --- a/include/hw/virtio/virtio-gpu.h +++ b/include/hw/virtio/virtio-gpu.h @@ -169,7 +169,7 @@ struct VirtIOGPUBaseClass { DEFINE_PROP_UINT32("yres", _state, _conf.yres, 800) typedef struct VGPUDMABuf { -QemuDmaBuf buf; +QemuDmaBuf *buf; uint32_t scanout_id; QTAILQ_ENTRY(VGPUDMABuf) next; } VGPUDMABuf; @@ -238,7 +238,7 @@ struct VhostUserGPU { VhostUserBackend *vhost; int vhost_gpu_fd; /* closed by the chardev */ CharBackend vhost_chr; -QemuDmaBuf dmabuf[VIRTIO_GPU_MAX_SCANOUTS]; +QemuDmaBuf *dmabuf[VIRTIO_GPU_MAX_SCANOUTS]; bool backend_blocked; }; diff --git a/include/ui/console.h b/include/ui/console.h index 3d9d8b9fce..6d7c03b7c5 100644 --- a/include/ui/console.h +++ b/include/ui/console.h @@ -358,7 +358,13 @@ void dpy_gl_cursor_dmabuf(QemuConsole *con, QemuDmaBuf *dmabuf, bool have_hot, uint32_t hot_x, uint32_t hot_y); void dpy_gl_cursor_position(QemuConsole *con, uint32_t pos_x, uint32_t pos_y); - +QemuDmaBuf *dpy_gl_qemu_dmabuf_new(uint32_t width, uint32_t height, + uint32_t stride, uint32_t x, + uint32_t y, uint32_t backing_width, + uint32_t backing_height, uint32_t fourcc, + uint64_t modifier, uint32_t dmabuf_fd, + bool allow_fences, bool y0_top); +void dpy_gl_qemu_dmabuf_free(QemuDmaBuf *dmabuf); int32_t dpy_gl_qemu_dmabuf_get_fd(QemuDmaBuf *dmabuf); uint32_t dpy_gl_qemu_dmabuf_get_width(QemuDmaBuf *dmabuf); uint32_t dpy_gl_qemu_dmabuf_get_height(QemuDmaBuf *dmabuf); diff --git a/hw/display/vhost-user-gpu.c b/hw/display/vhost-user-gpu.c index 87dcfbca10..4d8461e94a 100644 --- a/hw/display/vhost-user-gpu.c +++ b/hw/display/vhost-user-gpu.c @@ -250,6 +250,7 @@ vhost_user_gpu_handle_display(VhostUserGPU *g, VhostUserGpuMsg *msg) VhostUserGpuDMABUFScanout *m = >payload.dmabuf_scanout; int fd = qemu_chr_fe_get_msgfd(>vhost_chr); int old_fd; +uint64_t modifier = 0; QemuDmaBuf *dmabuf; if (m->scanout_id >= g->parent_obj.conf.max_outputs) { @@ -262,31 +263,34 @@ vhost_user_gpu_handle_display(VhostUserGPU *g, VhostUserGpuMsg *msg) g->parent_obj.enable = 1; con = g->parent_obj.scanout[m->scanout_id].con; -dmabuf = >dmabuf[m->scanout_id]; -old_fd = dpy_gl_qemu_dmabuf_get_fd(dmabuf); -if (old_fd >= 0) { -close(old_fd); -dmabuf->fd = -1; +dmabuf = g->dmabuf[m->scanout_id]; +if (dmabuf) { +old_fd = dpy_gl_qemu_dmabuf_get_fd(dmabuf); +if (old_fd >= 0) { +close(old_fd); +dpy_gl_qemu_dmabuf_set_fd(dmabuf, -1); +} } dpy_gl_release_dmabuf(con, dmabuf); +g_clear_pointer(, dpy_gl_qemu_dmabuf_free); if (fd == -1) { dpy_gl_scanout_disable(con); break; } -*dmabuf = (QemuDmaBuf) { -.fd = fd, -.width = m->fd_width, -.height = m->fd_height, -.stride = m->fd_stride, -.fourcc = m->fd_drm_fourcc, -.y0_top = m->fd_flags & VIRTIO_GPU_RESOURCE_FLAG_Y_0_TOP, -}; + if (msg->request == VHOST_USER_GPU_DMABUF_SCANOUT2) { VhostUserGpuDMABUFScanout2 *m2 = >payload.dmabuf_scanout2; -dmabuf->modifier
[PATCH v6 1/3] ui/console: Introduce dpy_gl_qemu_dmabuf_get_..() helpers
From: Dongwon Kim This commit introduces dpy_gl_qemu_dmabuf_get_... helpers to extract specific fields from the QemuDmaBuf struct. It also updates all instances where fields within the QemuDmaBuf struct are directly accessed, replacing them with calls to these new helper functions. v6: fix typos in helper names in ui/spice-display.c Suggested-by: Marc-André Lureau Cc: Philippe Mathieu-Daudé Cc: Vivek Kasireddy Signed-off-by: Dongwon Kim --- include/ui/console.h| 17 + hw/display/vhost-user-gpu.c | 6 +- hw/display/virtio-gpu-udmabuf.c | 7 +- hw/vfio/display.c | 15 +++-- ui/console.c| 116 +++- ui/dbus-console.c | 9 ++- ui/dbus-listener.c | 43 +++- ui/egl-headless.c | 23 +-- ui/egl-helpers.c| 47 +++-- ui/gtk-egl.c| 48 - ui/gtk-gl-area.c| 37 ++ ui/gtk.c| 6 +- ui/spice-display.c | 50 -- 13 files changed, 316 insertions(+), 108 deletions(-) diff --git a/include/ui/console.h b/include/ui/console.h index 0bc7a00ac0..6292943a82 100644 --- a/include/ui/console.h +++ b/include/ui/console.h @@ -358,6 +358,23 @@ void dpy_gl_cursor_dmabuf(QemuConsole *con, QemuDmaBuf *dmabuf, bool have_hot, uint32_t hot_x, uint32_t hot_y); void dpy_gl_cursor_position(QemuConsole *con, uint32_t pos_x, uint32_t pos_y); + +int32_t dpy_gl_qemu_dmabuf_get_fd(QemuDmaBuf *dmabuf); +uint32_t dpy_gl_qemu_dmabuf_get_width(QemuDmaBuf *dmabuf); +uint32_t dpy_gl_qemu_dmabuf_get_height(QemuDmaBuf *dmabuf); +uint32_t dpy_gl_qemu_dmabuf_get_stride(QemuDmaBuf *dmabuf); +uint32_t dpy_gl_qemu_dmabuf_get_fourcc(QemuDmaBuf *dmabuf); +uint64_t dpy_gl_qemu_dmabuf_get_modifier(QemuDmaBuf *dmabuf); +uint32_t dpy_gl_qemu_dmabuf_get_texture(QemuDmaBuf *dmabuf); +uint32_t dpy_gl_qemu_dmabuf_get_x(QemuDmaBuf *dmabuf); +uint32_t dpy_gl_qemu_dmabuf_get_y(QemuDmaBuf *dmabuf); +uint32_t dpy_gl_qemu_dmabuf_get_backing_width(QemuDmaBuf *dmabuf); +uint32_t dpy_gl_qemu_dmabuf_get_backing_height(QemuDmaBuf *dmabuf); +bool dpy_gl_qemu_dmabuf_get_y0_top(QemuDmaBuf *dmabuf); +void *dpy_gl_qemu_dmabuf_get_sync(QemuDmaBuf *dmabuf); +int32_t dpy_gl_qemu_dmabuf_get_fence_fd(QemuDmaBuf *dmabuf); +bool dpy_gl_qemu_dmabuf_get_allow_fences(QemuDmaBuf *dmabuf); +bool dpy_gl_qemu_dmabuf_get_draw_submitted(QemuDmaBuf *dmabuf); void dpy_gl_release_dmabuf(QemuConsole *con, QemuDmaBuf *dmabuf); void dpy_gl_update(QemuConsole *con, diff --git a/hw/display/vhost-user-gpu.c b/hw/display/vhost-user-gpu.c index 709c8a02a1..87dcfbca10 100644 --- a/hw/display/vhost-user-gpu.c +++ b/hw/display/vhost-user-gpu.c @@ -249,6 +249,7 @@ vhost_user_gpu_handle_display(VhostUserGPU *g, VhostUserGpuMsg *msg) case VHOST_USER_GPU_DMABUF_SCANOUT: { VhostUserGpuDMABUFScanout *m = >payload.dmabuf_scanout; int fd = qemu_chr_fe_get_msgfd(>vhost_chr); +int old_fd; QemuDmaBuf *dmabuf; if (m->scanout_id >= g->parent_obj.conf.max_outputs) { @@ -262,8 +263,9 @@ vhost_user_gpu_handle_display(VhostUserGPU *g, VhostUserGpuMsg *msg) g->parent_obj.enable = 1; con = g->parent_obj.scanout[m->scanout_id].con; dmabuf = >dmabuf[m->scanout_id]; -if (dmabuf->fd >= 0) { -close(dmabuf->fd); +old_fd = dpy_gl_qemu_dmabuf_get_fd(dmabuf); +if (old_fd >= 0) { +close(old_fd); dmabuf->fd = -1; } dpy_gl_release_dmabuf(con, dmabuf); diff --git a/hw/display/virtio-gpu-udmabuf.c b/hw/display/virtio-gpu-udmabuf.c index d51184d658..e3f358b575 100644 --- a/hw/display/virtio-gpu-udmabuf.c +++ b/hw/display/virtio-gpu-udmabuf.c @@ -206,6 +206,7 @@ int virtio_gpu_update_dmabuf(VirtIOGPU *g, { struct virtio_gpu_scanout *scanout = >parent_obj.scanout[scanout_id]; VGPUDMABuf *new_primary, *old_primary = NULL; +uint32_t width, height; new_primary = virtio_gpu_create_dmabuf(g, scanout_id, res, fb, r); if (!new_primary) { @@ -216,10 +217,10 @@ int virtio_gpu_update_dmabuf(VirtIOGPU *g, old_primary = g->dmabuf.primary[scanout_id]; } +width = dpy_gl_qemu_dmabuf_get_width(_primary->buf); +height = dpy_gl_qemu_dmabuf_get_height(_primary->buf); g->dmabuf.primary[scanout_id] = new_primary; -qemu_console_resize(scanout->con, -new_primary->buf.width, -new_primary->buf.height); +qemu_console_resize(scanout->con, width, height); dpy_gl_scanout_dmabuf(scanout->con, _primary->buf); if (old_primary) { diff --git a/hw/vfio/display.c b/hw/vfio/display.c index 1aa440c663..f9c39cbd51 100644 --- a/hw/vfio/display.c +++ b/hw/vfio/display.c
[PATCH v5 1/3] ui/console: Introduce dpy_gl_qemu_dmabuf_get_..() helpers
From: Dongwon Kim This commit introduces dpy_gl_qemu_dmabuf_get_... helpers to extract specific fields from the QemuDmaBuf struct. It also updates all instances where fields within the QemuDmaBuf struct are directly accessed, replacing them with calls to these new helper functions. Suggested-by: Marc-André Lureau Cc: Philippe Mathieu-Daudé Cc: Vivek Kasireddy Signed-off-by: Dongwon Kim --- include/ui/console.h| 17 + hw/display/vhost-user-gpu.c | 6 +- hw/display/virtio-gpu-udmabuf.c | 7 +- hw/vfio/display.c | 15 +++-- ui/console.c| 116 +++- ui/dbus-console.c | 9 ++- ui/dbus-listener.c | 43 +++- ui/egl-headless.c | 23 +-- ui/egl-helpers.c| 47 +++-- ui/gtk-egl.c| 48 - ui/gtk-gl-area.c| 37 ++ ui/gtk.c| 6 +- ui/spice-display.c | 50 -- 13 files changed, 316 insertions(+), 108 deletions(-) diff --git a/include/ui/console.h b/include/ui/console.h index 0bc7a00ac0..6292943a82 100644 --- a/include/ui/console.h +++ b/include/ui/console.h @@ -358,6 +358,23 @@ void dpy_gl_cursor_dmabuf(QemuConsole *con, QemuDmaBuf *dmabuf, bool have_hot, uint32_t hot_x, uint32_t hot_y); void dpy_gl_cursor_position(QemuConsole *con, uint32_t pos_x, uint32_t pos_y); + +int32_t dpy_gl_qemu_dmabuf_get_fd(QemuDmaBuf *dmabuf); +uint32_t dpy_gl_qemu_dmabuf_get_width(QemuDmaBuf *dmabuf); +uint32_t dpy_gl_qemu_dmabuf_get_height(QemuDmaBuf *dmabuf); +uint32_t dpy_gl_qemu_dmabuf_get_stride(QemuDmaBuf *dmabuf); +uint32_t dpy_gl_qemu_dmabuf_get_fourcc(QemuDmaBuf *dmabuf); +uint64_t dpy_gl_qemu_dmabuf_get_modifier(QemuDmaBuf *dmabuf); +uint32_t dpy_gl_qemu_dmabuf_get_texture(QemuDmaBuf *dmabuf); +uint32_t dpy_gl_qemu_dmabuf_get_x(QemuDmaBuf *dmabuf); +uint32_t dpy_gl_qemu_dmabuf_get_y(QemuDmaBuf *dmabuf); +uint32_t dpy_gl_qemu_dmabuf_get_backing_width(QemuDmaBuf *dmabuf); +uint32_t dpy_gl_qemu_dmabuf_get_backing_height(QemuDmaBuf *dmabuf); +bool dpy_gl_qemu_dmabuf_get_y0_top(QemuDmaBuf *dmabuf); +void *dpy_gl_qemu_dmabuf_get_sync(QemuDmaBuf *dmabuf); +int32_t dpy_gl_qemu_dmabuf_get_fence_fd(QemuDmaBuf *dmabuf); +bool dpy_gl_qemu_dmabuf_get_allow_fences(QemuDmaBuf *dmabuf); +bool dpy_gl_qemu_dmabuf_get_draw_submitted(QemuDmaBuf *dmabuf); void dpy_gl_release_dmabuf(QemuConsole *con, QemuDmaBuf *dmabuf); void dpy_gl_update(QemuConsole *con, diff --git a/hw/display/vhost-user-gpu.c b/hw/display/vhost-user-gpu.c index 709c8a02a1..87dcfbca10 100644 --- a/hw/display/vhost-user-gpu.c +++ b/hw/display/vhost-user-gpu.c @@ -249,6 +249,7 @@ vhost_user_gpu_handle_display(VhostUserGPU *g, VhostUserGpuMsg *msg) case VHOST_USER_GPU_DMABUF_SCANOUT: { VhostUserGpuDMABUFScanout *m = >payload.dmabuf_scanout; int fd = qemu_chr_fe_get_msgfd(>vhost_chr); +int old_fd; QemuDmaBuf *dmabuf; if (m->scanout_id >= g->parent_obj.conf.max_outputs) { @@ -262,8 +263,9 @@ vhost_user_gpu_handle_display(VhostUserGPU *g, VhostUserGpuMsg *msg) g->parent_obj.enable = 1; con = g->parent_obj.scanout[m->scanout_id].con; dmabuf = >dmabuf[m->scanout_id]; -if (dmabuf->fd >= 0) { -close(dmabuf->fd); +old_fd = dpy_gl_qemu_dmabuf_get_fd(dmabuf); +if (old_fd >= 0) { +close(old_fd); dmabuf->fd = -1; } dpy_gl_release_dmabuf(con, dmabuf); diff --git a/hw/display/virtio-gpu-udmabuf.c b/hw/display/virtio-gpu-udmabuf.c index d51184d658..e3f358b575 100644 --- a/hw/display/virtio-gpu-udmabuf.c +++ b/hw/display/virtio-gpu-udmabuf.c @@ -206,6 +206,7 @@ int virtio_gpu_update_dmabuf(VirtIOGPU *g, { struct virtio_gpu_scanout *scanout = >parent_obj.scanout[scanout_id]; VGPUDMABuf *new_primary, *old_primary = NULL; +uint32_t width, height; new_primary = virtio_gpu_create_dmabuf(g, scanout_id, res, fb, r); if (!new_primary) { @@ -216,10 +217,10 @@ int virtio_gpu_update_dmabuf(VirtIOGPU *g, old_primary = g->dmabuf.primary[scanout_id]; } +width = dpy_gl_qemu_dmabuf_get_width(_primary->buf); +height = dpy_gl_qemu_dmabuf_get_height(_primary->buf); g->dmabuf.primary[scanout_id] = new_primary; -qemu_console_resize(scanout->con, -new_primary->buf.width, -new_primary->buf.height); +qemu_console_resize(scanout->con, width, height); dpy_gl_scanout_dmabuf(scanout->con, _primary->buf); if (old_primary) { diff --git a/hw/vfio/display.c b/hw/vfio/display.c index 1aa440c663..f9c39cbd51 100644 --- a/hw/vfio/display.c +++ b/hw/vfio/display.c @@ -259,9 +259,13 @@ static VFIODMABuf *vfio_displa
[PATCH v5 3/3] ui/console: Introduce dpy_gl_qemu_dmabuf_new() and free() helpers
From: Dongwon Kim This commit introduces utility functions for the creation and deallocation of QemuDmaBuf instances. Additionally, it updates all relevant sections of the codebase to utilize these new utility functions. Suggested-by: Marc-André Lureau Cc: Philippe Mathieu-Daudé Cc: Vivek Kasireddy Signed-off-by: Dongwon Kim --- include/hw/vfio/vfio-common.h | 2 +- include/hw/virtio/virtio-gpu.h | 4 ++-- include/ui/console.h| 8 +++- hw/display/vhost-user-gpu.c | 32 +-- hw/display/virtio-gpu-udmabuf.c | 24 +-- hw/vfio/display.c | 26 - ui/console.c| 34 + ui/dbus-listener.c | 28 --- 8 files changed, 95 insertions(+), 63 deletions(-) diff --git a/include/hw/vfio/vfio-common.h b/include/hw/vfio/vfio-common.h index b9da6c08ef..d66e27db02 100644 --- a/include/hw/vfio/vfio-common.h +++ b/include/hw/vfio/vfio-common.h @@ -148,7 +148,7 @@ typedef struct VFIOGroup { } VFIOGroup; typedef struct VFIODMABuf { -QemuDmaBuf buf; +QemuDmaBuf *buf; uint32_t pos_x, pos_y, pos_updates; uint32_t hot_x, hot_y, hot_updates; int dmabuf_id; diff --git a/include/hw/virtio/virtio-gpu.h b/include/hw/virtio/virtio-gpu.h index ed44cdad6b..56d6e821bf 100644 --- a/include/hw/virtio/virtio-gpu.h +++ b/include/hw/virtio/virtio-gpu.h @@ -169,7 +169,7 @@ struct VirtIOGPUBaseClass { DEFINE_PROP_UINT32("yres", _state, _conf.yres, 800) typedef struct VGPUDMABuf { -QemuDmaBuf buf; +QemuDmaBuf *buf; uint32_t scanout_id; QTAILQ_ENTRY(VGPUDMABuf) next; } VGPUDMABuf; @@ -238,7 +238,7 @@ struct VhostUserGPU { VhostUserBackend *vhost; int vhost_gpu_fd; /* closed by the chardev */ CharBackend vhost_chr; -QemuDmaBuf dmabuf[VIRTIO_GPU_MAX_SCANOUTS]; +QemuDmaBuf *dmabuf[VIRTIO_GPU_MAX_SCANOUTS]; bool backend_blocked; }; diff --git a/include/ui/console.h b/include/ui/console.h index 3d9d8b9fce..6d7c03b7c5 100644 --- a/include/ui/console.h +++ b/include/ui/console.h @@ -358,7 +358,13 @@ void dpy_gl_cursor_dmabuf(QemuConsole *con, QemuDmaBuf *dmabuf, bool have_hot, uint32_t hot_x, uint32_t hot_y); void dpy_gl_cursor_position(QemuConsole *con, uint32_t pos_x, uint32_t pos_y); - +QemuDmaBuf *dpy_gl_qemu_dmabuf_new(uint32_t width, uint32_t height, + uint32_t stride, uint32_t x, + uint32_t y, uint32_t backing_width, + uint32_t backing_height, uint32_t fourcc, + uint64_t modifier, uint32_t dmabuf_fd, + bool allow_fences, bool y0_top); +void dpy_gl_qemu_dmabuf_free(QemuDmaBuf *dmabuf); int32_t dpy_gl_qemu_dmabuf_get_fd(QemuDmaBuf *dmabuf); uint32_t dpy_gl_qemu_dmabuf_get_width(QemuDmaBuf *dmabuf); uint32_t dpy_gl_qemu_dmabuf_get_height(QemuDmaBuf *dmabuf); diff --git a/hw/display/vhost-user-gpu.c b/hw/display/vhost-user-gpu.c index 87dcfbca10..4d8461e94a 100644 --- a/hw/display/vhost-user-gpu.c +++ b/hw/display/vhost-user-gpu.c @@ -250,6 +250,7 @@ vhost_user_gpu_handle_display(VhostUserGPU *g, VhostUserGpuMsg *msg) VhostUserGpuDMABUFScanout *m = >payload.dmabuf_scanout; int fd = qemu_chr_fe_get_msgfd(>vhost_chr); int old_fd; +uint64_t modifier = 0; QemuDmaBuf *dmabuf; if (m->scanout_id >= g->parent_obj.conf.max_outputs) { @@ -262,31 +263,34 @@ vhost_user_gpu_handle_display(VhostUserGPU *g, VhostUserGpuMsg *msg) g->parent_obj.enable = 1; con = g->parent_obj.scanout[m->scanout_id].con; -dmabuf = >dmabuf[m->scanout_id]; -old_fd = dpy_gl_qemu_dmabuf_get_fd(dmabuf); -if (old_fd >= 0) { -close(old_fd); -dmabuf->fd = -1; +dmabuf = g->dmabuf[m->scanout_id]; +if (dmabuf) { +old_fd = dpy_gl_qemu_dmabuf_get_fd(dmabuf); +if (old_fd >= 0) { +close(old_fd); +dpy_gl_qemu_dmabuf_set_fd(dmabuf, -1); +} } dpy_gl_release_dmabuf(con, dmabuf); +g_clear_pointer(, dpy_gl_qemu_dmabuf_free); if (fd == -1) { dpy_gl_scanout_disable(con); break; } -*dmabuf = (QemuDmaBuf) { -.fd = fd, -.width = m->fd_width, -.height = m->fd_height, -.stride = m->fd_stride, -.fourcc = m->fd_drm_fourcc, -.y0_top = m->fd_flags & VIRTIO_GPU_RESOURCE_FLAG_Y_0_TOP, -}; + if (msg->request == VHOST_USER_GPU_DMABUF_SCANOUT2) { VhostUserGpuDMABUFScanout2 *m2 = >payload.dmabuf_scanout2; -dmabuf->modifier
[PATCH v5 0/3] ui/console: Private QemuDmaBuf struct
From: Dongwon Kim This series introduces privacy enhancements to the QemuDmaBuf struct and its contained data to bolster security. it accomplishes this by introducing of helper functions for allocating, deallocating, and accessing individual fields within the struct and replacing all direct references to individual fields in the struct with methods using helpers throughout the codebase. This change was made based on a suggestion from Marc-André Lureau (Resumitting same patch series with this new cover-leter) Dongwon Kim (3): ui/console: Introduce dpy_gl_qemu_dmabuf_get_..() helpers ui/console: Introduce dpy_gl_qemu_dmabuf_set_..() helpers ui/console: Introduce dpy_gl_qemu_dmabuf_new() and free() helpers include/hw/vfio/vfio-common.h | 2 +- include/hw/virtio/virtio-gpu.h | 4 +- include/ui/console.h| 28 + hw/display/vhost-user-gpu.c | 32 +++--- hw/display/virtio-gpu-udmabuf.c | 27 ++--- hw/vfio/display.c | 35 --- ui/console.c| 180 +++- ui/dbus-console.c | 9 +- ui/dbus-listener.c | 71 +++-- ui/egl-headless.c | 23 ++-- ui/egl-helpers.c| 59 ++- ui/gtk-egl.c| 52 + ui/gtk-gl-area.c| 41 +--- ui/gtk.c| 8 +- ui/spice-display.c | 50 + 15 files changed, 449 insertions(+), 172 deletions(-) -- 2.34.1
[PATCH v5 2/3] ui/console: Introduce dpy_gl_qemu_dmabuf_set_..() helpers
From: Dongwon Kim To enhance security in accessing the QemuDmaBuf struct, new helper functions for setting specific fields within the struct were introduced. And all occurrences where these fields were previously set directly have been updated to utilize these helper functions. Suggested-by: Marc-André Lureau Cc: Philippe Mathieu-Daudé Cc: Vivek Kasireddy Signed-off-by: Dongwon Kim --- include/ui/console.h | 5 + ui/console.c | 30 ++ ui/egl-helpers.c | 16 +--- ui/gtk-egl.c | 4 ++-- ui/gtk-gl-area.c | 4 ++-- ui/gtk.c | 2 +- 6 files changed, 49 insertions(+), 12 deletions(-) diff --git a/include/ui/console.h b/include/ui/console.h index 6292943a82..3d9d8b9fce 100644 --- a/include/ui/console.h +++ b/include/ui/console.h @@ -375,6 +375,11 @@ void *dpy_gl_qemu_dmabuf_get_sync(QemuDmaBuf *dmabuf); int32_t dpy_gl_qemu_dmabuf_get_fence_fd(QemuDmaBuf *dmabuf); bool dpy_gl_qemu_dmabuf_get_allow_fences(QemuDmaBuf *dmabuf); bool dpy_gl_qemu_dmabuf_get_draw_submitted(QemuDmaBuf *dmabuf); +void dpy_gl_qemu_dmabuf_set_texture(QemuDmaBuf *dmabuf, uint32_t texture); +void dpy_gl_qemu_dmabuf_set_fence_fd(QemuDmaBuf *dmabuf, int32_t fence_fd); +void dpy_gl_qemu_dmabuf_set_sync(QemuDmaBuf *dmabuf, void *sync); +void dpy_gl_qemu_dmabuf_set_draw_submitted(QemuDmaBuf *dmabuf, bool draw_submitted); +void dpy_gl_qemu_dmabuf_set_fd(QemuDmaBuf *dmabuf, int32_t fd); void dpy_gl_release_dmabuf(QemuConsole *con, QemuDmaBuf *dmabuf); void dpy_gl_update(QemuConsole *con, diff --git a/ui/console.c b/ui/console.c index 5d5635f783..d4ca9e6e0f 100644 --- a/ui/console.c +++ b/ui/console.c @@ -1244,6 +1244,36 @@ bool dpy_gl_qemu_dmabuf_get_draw_submitted(QemuDmaBuf *dmabuf) return dmabuf->draw_submitted; } +void dpy_gl_qemu_dmabuf_set_texture(QemuDmaBuf *dmabuf, uint32_t texture) +{ +assert(dmabuf != NULL); +dmabuf->texture = texture; +} + +void dpy_gl_qemu_dmabuf_set_fence_fd(QemuDmaBuf *dmabuf, int32_t fence_fd) +{ +assert(dmabuf != NULL); +dmabuf->fence_fd = fence_fd; +} + +void dpy_gl_qemu_dmabuf_set_sync(QemuDmaBuf *dmabuf, void *sync) +{ +assert(dmabuf != NULL); +dmabuf->sync = sync; +} + +void dpy_gl_qemu_dmabuf_set_draw_submitted(QemuDmaBuf *dmabuf, bool draw_submitted) +{ +assert(dmabuf != NULL); +dmabuf->draw_submitted = draw_submitted; +} + +void dpy_gl_qemu_dmabuf_set_fd(QemuDmaBuf *dmabuf, int32_t fd) +{ +assert(dmabuf != NULL); +dmabuf->fd = fd; +} + void dpy_gl_release_dmabuf(QemuConsole *con, QemuDmaBuf *dmabuf) { diff --git a/ui/egl-helpers.c b/ui/egl-helpers.c index 86d64c68ce..c71a2878c2 100644 --- a/ui/egl-helpers.c +++ b/ui/egl-helpers.c @@ -348,8 +348,8 @@ void egl_dmabuf_import_texture(QemuDmaBuf *dmabuf) return; } -glGenTextures(1, >texture); -texture = dpy_gl_qemu_dmabuf_get_texture(dmabuf); +glGenTextures(1, ); +dpy_gl_qemu_dmabuf_set_texture(dmabuf, texture); glBindTexture(GL_TEXTURE_2D, texture); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); @@ -368,7 +368,7 @@ void egl_dmabuf_release_texture(QemuDmaBuf *dmabuf) } glDeleteTextures(1, ); -dmabuf->texture = 0; +dpy_gl_qemu_dmabuf_set_texture(dmabuf, 0); } void egl_dmabuf_create_sync(QemuDmaBuf *dmabuf) @@ -382,7 +382,7 @@ void egl_dmabuf_create_sync(QemuDmaBuf *dmabuf) sync = eglCreateSyncKHR(qemu_egl_display, EGL_SYNC_NATIVE_FENCE_ANDROID, NULL); if (sync != EGL_NO_SYNC_KHR) { -dmabuf->sync = sync; +dpy_gl_qemu_dmabuf_set_sync(dmabuf, sync); } } } @@ -390,12 +390,14 @@ void egl_dmabuf_create_sync(QemuDmaBuf *dmabuf) void egl_dmabuf_create_fence(QemuDmaBuf *dmabuf) { void *sync = dpy_gl_qemu_dmabuf_get_sync(dmabuf); +int fence_fd; if (sync) { -dmabuf->fence_fd = eglDupNativeFenceFDANDROID(qemu_egl_display, - sync); +fence_fd = eglDupNativeFenceFDANDROID(qemu_egl_display, + sync); +dpy_gl_qemu_dmabuf_set_fence_fd(dmabuf, fence_fd); eglDestroySyncKHR(qemu_egl_display, sync); -dmabuf->sync = NULL; +dpy_gl_qemu_dmabuf_set_sync(dmabuf, NULL); } } diff --git a/ui/gtk-egl.c b/ui/gtk-egl.c index c9469af9ed..7494a34d7c 100644 --- a/ui/gtk-egl.c +++ b/ui/gtk-egl.c @@ -87,7 +87,7 @@ void gd_egl_draw(VirtualConsole *vc) if (!dpy_gl_qemu_dmabuf_get_draw_submitted(dmabuf)) { return; } else { -dmabuf->draw_submitted = false; +dpy_gl_qemu_dmabuf_set_draw_submitted(dmabuf, false); } } #endif @@ -381,7 +381,7 @@ void gd_egl_flush(Dis
[PATCH v5 3/3] ui/console: Introduce dpy_gl_qemu_dmabuf_new() and free() helpers
From: Dongwon Kim This commit introduces utility functions for the creation and deallocation of QemuDmaBuf instances. Additionally, it updates all relevant sections of the codebase to utilize these new utility functions. Suggested-by: Marc-André Lureau Cc: Philippe Mathieu-Daudé Cc: Vivek Kasireddy Signed-off-by: Dongwon Kim --- include/hw/vfio/vfio-common.h | 2 +- include/hw/virtio/virtio-gpu.h | 4 ++-- include/ui/console.h| 8 +++- hw/display/vhost-user-gpu.c | 32 +-- hw/display/virtio-gpu-udmabuf.c | 24 +-- hw/vfio/display.c | 26 - ui/console.c| 34 + ui/dbus-listener.c | 28 --- 8 files changed, 95 insertions(+), 63 deletions(-) diff --git a/include/hw/vfio/vfio-common.h b/include/hw/vfio/vfio-common.h index b9da6c08ef..d66e27db02 100644 --- a/include/hw/vfio/vfio-common.h +++ b/include/hw/vfio/vfio-common.h @@ -148,7 +148,7 @@ typedef struct VFIOGroup { } VFIOGroup; typedef struct VFIODMABuf { -QemuDmaBuf buf; +QemuDmaBuf *buf; uint32_t pos_x, pos_y, pos_updates; uint32_t hot_x, hot_y, hot_updates; int dmabuf_id; diff --git a/include/hw/virtio/virtio-gpu.h b/include/hw/virtio/virtio-gpu.h index ed44cdad6b..56d6e821bf 100644 --- a/include/hw/virtio/virtio-gpu.h +++ b/include/hw/virtio/virtio-gpu.h @@ -169,7 +169,7 @@ struct VirtIOGPUBaseClass { DEFINE_PROP_UINT32("yres", _state, _conf.yres, 800) typedef struct VGPUDMABuf { -QemuDmaBuf buf; +QemuDmaBuf *buf; uint32_t scanout_id; QTAILQ_ENTRY(VGPUDMABuf) next; } VGPUDMABuf; @@ -238,7 +238,7 @@ struct VhostUserGPU { VhostUserBackend *vhost; int vhost_gpu_fd; /* closed by the chardev */ CharBackend vhost_chr; -QemuDmaBuf dmabuf[VIRTIO_GPU_MAX_SCANOUTS]; +QemuDmaBuf *dmabuf[VIRTIO_GPU_MAX_SCANOUTS]; bool backend_blocked; }; diff --git a/include/ui/console.h b/include/ui/console.h index 3d9d8b9fce..6d7c03b7c5 100644 --- a/include/ui/console.h +++ b/include/ui/console.h @@ -358,7 +358,13 @@ void dpy_gl_cursor_dmabuf(QemuConsole *con, QemuDmaBuf *dmabuf, bool have_hot, uint32_t hot_x, uint32_t hot_y); void dpy_gl_cursor_position(QemuConsole *con, uint32_t pos_x, uint32_t pos_y); - +QemuDmaBuf *dpy_gl_qemu_dmabuf_new(uint32_t width, uint32_t height, + uint32_t stride, uint32_t x, + uint32_t y, uint32_t backing_width, + uint32_t backing_height, uint32_t fourcc, + uint64_t modifier, uint32_t dmabuf_fd, + bool allow_fences, bool y0_top); +void dpy_gl_qemu_dmabuf_free(QemuDmaBuf *dmabuf); int32_t dpy_gl_qemu_dmabuf_get_fd(QemuDmaBuf *dmabuf); uint32_t dpy_gl_qemu_dmabuf_get_width(QemuDmaBuf *dmabuf); uint32_t dpy_gl_qemu_dmabuf_get_height(QemuDmaBuf *dmabuf); diff --git a/hw/display/vhost-user-gpu.c b/hw/display/vhost-user-gpu.c index 87dcfbca10..4d8461e94a 100644 --- a/hw/display/vhost-user-gpu.c +++ b/hw/display/vhost-user-gpu.c @@ -250,6 +250,7 @@ vhost_user_gpu_handle_display(VhostUserGPU *g, VhostUserGpuMsg *msg) VhostUserGpuDMABUFScanout *m = >payload.dmabuf_scanout; int fd = qemu_chr_fe_get_msgfd(>vhost_chr); int old_fd; +uint64_t modifier = 0; QemuDmaBuf *dmabuf; if (m->scanout_id >= g->parent_obj.conf.max_outputs) { @@ -262,31 +263,34 @@ vhost_user_gpu_handle_display(VhostUserGPU *g, VhostUserGpuMsg *msg) g->parent_obj.enable = 1; con = g->parent_obj.scanout[m->scanout_id].con; -dmabuf = >dmabuf[m->scanout_id]; -old_fd = dpy_gl_qemu_dmabuf_get_fd(dmabuf); -if (old_fd >= 0) { -close(old_fd); -dmabuf->fd = -1; +dmabuf = g->dmabuf[m->scanout_id]; +if (dmabuf) { +old_fd = dpy_gl_qemu_dmabuf_get_fd(dmabuf); +if (old_fd >= 0) { +close(old_fd); +dpy_gl_qemu_dmabuf_set_fd(dmabuf, -1); +} } dpy_gl_release_dmabuf(con, dmabuf); +g_clear_pointer(, dpy_gl_qemu_dmabuf_free); if (fd == -1) { dpy_gl_scanout_disable(con); break; } -*dmabuf = (QemuDmaBuf) { -.fd = fd, -.width = m->fd_width, -.height = m->fd_height, -.stride = m->fd_stride, -.fourcc = m->fd_drm_fourcc, -.y0_top = m->fd_flags & VIRTIO_GPU_RESOURCE_FLAG_Y_0_TOP, -}; + if (msg->request == VHOST_USER_GPU_DMABUF_SCANOUT2) { VhostUserGpuDMABUFScanout2 *m2 = >payload.dmabuf_scanout2; -dmabuf->modifier
[PATCH v5 2/3] ui/console: Introduce dpy_gl_qemu_dmabuf_set_..() helpers
From: Dongwon Kim To enhance security in accessing the QemuDmaBuf struct, new helper functions for setting specific fields within the struct were introduced. And all occurrences where these fields were previously set directly have been updated to utilize these helper functions. Suggested-by: Marc-André Lureau Cc: Philippe Mathieu-Daudé Cc: Vivek Kasireddy Signed-off-by: Dongwon Kim --- include/ui/console.h | 5 + ui/console.c | 30 ++ ui/egl-helpers.c | 16 +--- ui/gtk-egl.c | 4 ++-- ui/gtk-gl-area.c | 4 ++-- ui/gtk.c | 2 +- 6 files changed, 49 insertions(+), 12 deletions(-) diff --git a/include/ui/console.h b/include/ui/console.h index 6292943a82..3d9d8b9fce 100644 --- a/include/ui/console.h +++ b/include/ui/console.h @@ -375,6 +375,11 @@ void *dpy_gl_qemu_dmabuf_get_sync(QemuDmaBuf *dmabuf); int32_t dpy_gl_qemu_dmabuf_get_fence_fd(QemuDmaBuf *dmabuf); bool dpy_gl_qemu_dmabuf_get_allow_fences(QemuDmaBuf *dmabuf); bool dpy_gl_qemu_dmabuf_get_draw_submitted(QemuDmaBuf *dmabuf); +void dpy_gl_qemu_dmabuf_set_texture(QemuDmaBuf *dmabuf, uint32_t texture); +void dpy_gl_qemu_dmabuf_set_fence_fd(QemuDmaBuf *dmabuf, int32_t fence_fd); +void dpy_gl_qemu_dmabuf_set_sync(QemuDmaBuf *dmabuf, void *sync); +void dpy_gl_qemu_dmabuf_set_draw_submitted(QemuDmaBuf *dmabuf, bool draw_submitted); +void dpy_gl_qemu_dmabuf_set_fd(QemuDmaBuf *dmabuf, int32_t fd); void dpy_gl_release_dmabuf(QemuConsole *con, QemuDmaBuf *dmabuf); void dpy_gl_update(QemuConsole *con, diff --git a/ui/console.c b/ui/console.c index 5d5635f783..d4ca9e6e0f 100644 --- a/ui/console.c +++ b/ui/console.c @@ -1244,6 +1244,36 @@ bool dpy_gl_qemu_dmabuf_get_draw_submitted(QemuDmaBuf *dmabuf) return dmabuf->draw_submitted; } +void dpy_gl_qemu_dmabuf_set_texture(QemuDmaBuf *dmabuf, uint32_t texture) +{ +assert(dmabuf != NULL); +dmabuf->texture = texture; +} + +void dpy_gl_qemu_dmabuf_set_fence_fd(QemuDmaBuf *dmabuf, int32_t fence_fd) +{ +assert(dmabuf != NULL); +dmabuf->fence_fd = fence_fd; +} + +void dpy_gl_qemu_dmabuf_set_sync(QemuDmaBuf *dmabuf, void *sync) +{ +assert(dmabuf != NULL); +dmabuf->sync = sync; +} + +void dpy_gl_qemu_dmabuf_set_draw_submitted(QemuDmaBuf *dmabuf, bool draw_submitted) +{ +assert(dmabuf != NULL); +dmabuf->draw_submitted = draw_submitted; +} + +void dpy_gl_qemu_dmabuf_set_fd(QemuDmaBuf *dmabuf, int32_t fd) +{ +assert(dmabuf != NULL); +dmabuf->fd = fd; +} + void dpy_gl_release_dmabuf(QemuConsole *con, QemuDmaBuf *dmabuf) { diff --git a/ui/egl-helpers.c b/ui/egl-helpers.c index 86d64c68ce..c71a2878c2 100644 --- a/ui/egl-helpers.c +++ b/ui/egl-helpers.c @@ -348,8 +348,8 @@ void egl_dmabuf_import_texture(QemuDmaBuf *dmabuf) return; } -glGenTextures(1, >texture); -texture = dpy_gl_qemu_dmabuf_get_texture(dmabuf); +glGenTextures(1, ); +dpy_gl_qemu_dmabuf_set_texture(dmabuf, texture); glBindTexture(GL_TEXTURE_2D, texture); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); @@ -368,7 +368,7 @@ void egl_dmabuf_release_texture(QemuDmaBuf *dmabuf) } glDeleteTextures(1, ); -dmabuf->texture = 0; +dpy_gl_qemu_dmabuf_set_texture(dmabuf, 0); } void egl_dmabuf_create_sync(QemuDmaBuf *dmabuf) @@ -382,7 +382,7 @@ void egl_dmabuf_create_sync(QemuDmaBuf *dmabuf) sync = eglCreateSyncKHR(qemu_egl_display, EGL_SYNC_NATIVE_FENCE_ANDROID, NULL); if (sync != EGL_NO_SYNC_KHR) { -dmabuf->sync = sync; +dpy_gl_qemu_dmabuf_set_sync(dmabuf, sync); } } } @@ -390,12 +390,14 @@ void egl_dmabuf_create_sync(QemuDmaBuf *dmabuf) void egl_dmabuf_create_fence(QemuDmaBuf *dmabuf) { void *sync = dpy_gl_qemu_dmabuf_get_sync(dmabuf); +int fence_fd; if (sync) { -dmabuf->fence_fd = eglDupNativeFenceFDANDROID(qemu_egl_display, - sync); +fence_fd = eglDupNativeFenceFDANDROID(qemu_egl_display, + sync); +dpy_gl_qemu_dmabuf_set_fence_fd(dmabuf, fence_fd); eglDestroySyncKHR(qemu_egl_display, sync); -dmabuf->sync = NULL; +dpy_gl_qemu_dmabuf_set_sync(dmabuf, NULL); } } diff --git a/ui/gtk-egl.c b/ui/gtk-egl.c index c9469af9ed..7494a34d7c 100644 --- a/ui/gtk-egl.c +++ b/ui/gtk-egl.c @@ -87,7 +87,7 @@ void gd_egl_draw(VirtualConsole *vc) if (!dpy_gl_qemu_dmabuf_get_draw_submitted(dmabuf)) { return; } else { -dmabuf->draw_submitted = false; +dpy_gl_qemu_dmabuf_set_draw_submitted(dmabuf, false); } } #endif @@ -381,7 +381,7 @@ void gd_egl_flush(Dis
[PATCH v5 1/3] ui/console: Introduce dpy_gl_qemu_dmabuf_get_..() helpers
From: Dongwon Kim This commit introduces dpy_gl_qemu_dmabuf_get_... helpers to extract specific fields from the QemuDmaBuf struct. It also updates all instances where fields within the QemuDmaBuf struct are directly accessed, replacing them with calls to these new helper functions. Suggested-by: Marc-André Lureau Cc: Philippe Mathieu-Daudé Cc: Vivek Kasireddy Signed-off-by: Dongwon Kim --- include/ui/console.h| 17 + hw/display/vhost-user-gpu.c | 6 +- hw/display/virtio-gpu-udmabuf.c | 7 +- hw/vfio/display.c | 15 +++-- ui/console.c| 116 +++- ui/dbus-console.c | 9 ++- ui/dbus-listener.c | 43 +++- ui/egl-headless.c | 23 +-- ui/egl-helpers.c| 47 +++-- ui/gtk-egl.c| 48 - ui/gtk-gl-area.c| 37 ++ ui/gtk.c| 6 +- ui/spice-display.c | 50 -- 13 files changed, 316 insertions(+), 108 deletions(-) diff --git a/include/ui/console.h b/include/ui/console.h index 0bc7a00ac0..6292943a82 100644 --- a/include/ui/console.h +++ b/include/ui/console.h @@ -358,6 +358,23 @@ void dpy_gl_cursor_dmabuf(QemuConsole *con, QemuDmaBuf *dmabuf, bool have_hot, uint32_t hot_x, uint32_t hot_y); void dpy_gl_cursor_position(QemuConsole *con, uint32_t pos_x, uint32_t pos_y); + +int32_t dpy_gl_qemu_dmabuf_get_fd(QemuDmaBuf *dmabuf); +uint32_t dpy_gl_qemu_dmabuf_get_width(QemuDmaBuf *dmabuf); +uint32_t dpy_gl_qemu_dmabuf_get_height(QemuDmaBuf *dmabuf); +uint32_t dpy_gl_qemu_dmabuf_get_stride(QemuDmaBuf *dmabuf); +uint32_t dpy_gl_qemu_dmabuf_get_fourcc(QemuDmaBuf *dmabuf); +uint64_t dpy_gl_qemu_dmabuf_get_modifier(QemuDmaBuf *dmabuf); +uint32_t dpy_gl_qemu_dmabuf_get_texture(QemuDmaBuf *dmabuf); +uint32_t dpy_gl_qemu_dmabuf_get_x(QemuDmaBuf *dmabuf); +uint32_t dpy_gl_qemu_dmabuf_get_y(QemuDmaBuf *dmabuf); +uint32_t dpy_gl_qemu_dmabuf_get_backing_width(QemuDmaBuf *dmabuf); +uint32_t dpy_gl_qemu_dmabuf_get_backing_height(QemuDmaBuf *dmabuf); +bool dpy_gl_qemu_dmabuf_get_y0_top(QemuDmaBuf *dmabuf); +void *dpy_gl_qemu_dmabuf_get_sync(QemuDmaBuf *dmabuf); +int32_t dpy_gl_qemu_dmabuf_get_fence_fd(QemuDmaBuf *dmabuf); +bool dpy_gl_qemu_dmabuf_get_allow_fences(QemuDmaBuf *dmabuf); +bool dpy_gl_qemu_dmabuf_get_draw_submitted(QemuDmaBuf *dmabuf); void dpy_gl_release_dmabuf(QemuConsole *con, QemuDmaBuf *dmabuf); void dpy_gl_update(QemuConsole *con, diff --git a/hw/display/vhost-user-gpu.c b/hw/display/vhost-user-gpu.c index 709c8a02a1..87dcfbca10 100644 --- a/hw/display/vhost-user-gpu.c +++ b/hw/display/vhost-user-gpu.c @@ -249,6 +249,7 @@ vhost_user_gpu_handle_display(VhostUserGPU *g, VhostUserGpuMsg *msg) case VHOST_USER_GPU_DMABUF_SCANOUT: { VhostUserGpuDMABUFScanout *m = >payload.dmabuf_scanout; int fd = qemu_chr_fe_get_msgfd(>vhost_chr); +int old_fd; QemuDmaBuf *dmabuf; if (m->scanout_id >= g->parent_obj.conf.max_outputs) { @@ -262,8 +263,9 @@ vhost_user_gpu_handle_display(VhostUserGPU *g, VhostUserGpuMsg *msg) g->parent_obj.enable = 1; con = g->parent_obj.scanout[m->scanout_id].con; dmabuf = >dmabuf[m->scanout_id]; -if (dmabuf->fd >= 0) { -close(dmabuf->fd); +old_fd = dpy_gl_qemu_dmabuf_get_fd(dmabuf); +if (old_fd >= 0) { +close(old_fd); dmabuf->fd = -1; } dpy_gl_release_dmabuf(con, dmabuf); diff --git a/hw/display/virtio-gpu-udmabuf.c b/hw/display/virtio-gpu-udmabuf.c index d51184d658..e3f358b575 100644 --- a/hw/display/virtio-gpu-udmabuf.c +++ b/hw/display/virtio-gpu-udmabuf.c @@ -206,6 +206,7 @@ int virtio_gpu_update_dmabuf(VirtIOGPU *g, { struct virtio_gpu_scanout *scanout = >parent_obj.scanout[scanout_id]; VGPUDMABuf *new_primary, *old_primary = NULL; +uint32_t width, height; new_primary = virtio_gpu_create_dmabuf(g, scanout_id, res, fb, r); if (!new_primary) { @@ -216,10 +217,10 @@ int virtio_gpu_update_dmabuf(VirtIOGPU *g, old_primary = g->dmabuf.primary[scanout_id]; } +width = dpy_gl_qemu_dmabuf_get_width(_primary->buf); +height = dpy_gl_qemu_dmabuf_get_height(_primary->buf); g->dmabuf.primary[scanout_id] = new_primary; -qemu_console_resize(scanout->con, -new_primary->buf.width, -new_primary->buf.height); +qemu_console_resize(scanout->con, width, height); dpy_gl_scanout_dmabuf(scanout->con, _primary->buf); if (old_primary) { diff --git a/hw/vfio/display.c b/hw/vfio/display.c index 1aa440c663..f9c39cbd51 100644 --- a/hw/vfio/display.c +++ b/hw/vfio/display.c @@ -259,9 +259,13 @@ static VFIODMABuf *vfio_displa
[PATCH v4 1/3] ui/console: Introduce dpy_gl_dmabuf_get_height/width() helpers
From: Dongwon Kim dpy_gl_dmabuf_get_height() and dpy_gl_dmabuf_get_width() are helpers for retrieving width and height fields from QemuDmaBuf struct. Cc: Philippe Mathieu-Daudé Cc: Marc-André Lureau Cc: Vivek Kasireddy Signed-off-by: Dongwon Kim --- include/ui/console.h| 2 ++ hw/display/virtio-gpu-udmabuf.c | 7 --- hw/vfio/display.c | 9 ++--- ui/console.c| 18 ++ 4 files changed, 30 insertions(+), 6 deletions(-) diff --git a/include/ui/console.h b/include/ui/console.h index 0bc7a00ac0..6064487fc4 100644 --- a/include/ui/console.h +++ b/include/ui/console.h @@ -358,6 +358,8 @@ void dpy_gl_cursor_dmabuf(QemuConsole *con, QemuDmaBuf *dmabuf, bool have_hot, uint32_t hot_x, uint32_t hot_y); void dpy_gl_cursor_position(QemuConsole *con, uint32_t pos_x, uint32_t pos_y); +uint32_t dpy_gl_dmabuf_get_width(QemuDmaBuf *dmabuf); +uint32_t dpy_gl_dmabuf_get_height(QemuDmaBuf *dmabuf); void dpy_gl_release_dmabuf(QemuConsole *con, QemuDmaBuf *dmabuf); void dpy_gl_update(QemuConsole *con, diff --git a/hw/display/virtio-gpu-udmabuf.c b/hw/display/virtio-gpu-udmabuf.c index d51184d658..a4ebf828ec 100644 --- a/hw/display/virtio-gpu-udmabuf.c +++ b/hw/display/virtio-gpu-udmabuf.c @@ -206,6 +206,7 @@ int virtio_gpu_update_dmabuf(VirtIOGPU *g, { struct virtio_gpu_scanout *scanout = >parent_obj.scanout[scanout_id]; VGPUDMABuf *new_primary, *old_primary = NULL; +uint32_t width, height; new_primary = virtio_gpu_create_dmabuf(g, scanout_id, res, fb, r); if (!new_primary) { @@ -216,10 +217,10 @@ int virtio_gpu_update_dmabuf(VirtIOGPU *g, old_primary = g->dmabuf.primary[scanout_id]; } +width = dpy_gl_dmabuf_get_width(_primary->buf); +height = dpy_gl_dmabuf_get_height(_primary->buf); g->dmabuf.primary[scanout_id] = new_primary; -qemu_console_resize(scanout->con, -new_primary->buf.width, -new_primary->buf.height); +qemu_console_resize(scanout->con, width, height); dpy_gl_scanout_dmabuf(scanout->con, _primary->buf); if (old_primary) { diff --git a/hw/vfio/display.c b/hw/vfio/display.c index 1aa440c663..c962e5f88f 100644 --- a/hw/vfio/display.c +++ b/hw/vfio/display.c @@ -286,6 +286,7 @@ static void vfio_display_dmabuf_update(void *opaque) VFIOPCIDevice *vdev = opaque; VFIODisplay *dpy = vdev->dpy; VFIODMABuf *primary, *cursor; +uint32_t width, height; bool free_bufs = false, new_cursor = false; primary = vfio_display_get_dmabuf(vdev, DRM_PLANE_TYPE_PRIMARY); @@ -296,10 +297,12 @@ static void vfio_display_dmabuf_update(void *opaque) return; } +width = dpy_gl_dmabuf_get_width(>buf); +height = dpy_gl_dmabuf_get_height(>buf); + if (dpy->dmabuf.primary != primary) { dpy->dmabuf.primary = primary; -qemu_console_resize(dpy->con, -primary->buf.width, primary->buf.height); +qemu_console_resize(dpy->con, width, height); dpy_gl_scanout_dmabuf(dpy->con, >buf); free_bufs = true; } @@ -328,7 +331,7 @@ static void vfio_display_dmabuf_update(void *opaque) cursor->pos_updates = 0; } -dpy_gl_update(dpy->con, 0, 0, primary->buf.width, primary->buf.height); +dpy_gl_update(dpy->con, 0, 0, width, height); if (free_bufs) { vfio_display_free_dmabufs(vdev); diff --git a/ui/console.c b/ui/console.c index 43226c5c14..1d0513a733 100644 --- a/ui/console.c +++ b/ui/console.c @@ -1132,6 +1132,24 @@ void dpy_gl_cursor_position(QemuConsole *con, } } +uint32_t dpy_gl_dmabuf_get_width(QemuDmaBuf *dmabuf) +{ +if (dmabuf) { +return dmabuf->width; +} + +return 0; +} + +uint32_t dpy_gl_dmabuf_get_height(QemuDmaBuf *dmabuf) +{ +if (dmabuf) { +return dmabuf->height; +} + +return 0; +} + void dpy_gl_release_dmabuf(QemuConsole *con, QemuDmaBuf *dmabuf) { -- 2.34.1
[PATCH v4 2/3] ui/console: Introduce dpy_gl_dmabuf_get_fd() helper
From: Dongwon Kim dpy_gl_dmabuf_get_fd() is a helper for retrieving FD of the dmabuf from QemuDmaBuf struct. Cc: Philippe Mathieu-Daudé Cc: Marc-André Lureau Cc: Vivek Kasireddy Signed-off-by: Dongwon Kim --- include/ui/console.h | 1 + hw/vfio/display.c| 8 +++- ui/console.c | 9 + 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/include/ui/console.h b/include/ui/console.h index 6064487fc4..d5334a806c 100644 --- a/include/ui/console.h +++ b/include/ui/console.h @@ -360,6 +360,7 @@ void dpy_gl_cursor_position(QemuConsole *con, uint32_t pos_x, uint32_t pos_y); uint32_t dpy_gl_dmabuf_get_width(QemuDmaBuf *dmabuf); uint32_t dpy_gl_dmabuf_get_height(QemuDmaBuf *dmabuf); +int32_t dpy_gl_dmabuf_get_fd(QemuDmaBuf *dmabuf); void dpy_gl_release_dmabuf(QemuConsole *con, QemuDmaBuf *dmabuf); void dpy_gl_update(QemuConsole *con, diff --git a/hw/vfio/display.c b/hw/vfio/display.c index c962e5f88f..676b2fc5f3 100644 --- a/hw/vfio/display.c +++ b/hw/vfio/display.c @@ -259,9 +259,15 @@ static VFIODMABuf *vfio_display_get_dmabuf(VFIOPCIDevice *vdev, static void vfio_display_free_one_dmabuf(VFIODisplay *dpy, VFIODMABuf *dmabuf) { +int fd; + QTAILQ_REMOVE(>dmabuf.bufs, dmabuf, next); +fd = dpy_gl_dmabuf_get_fd(>buf); +if (fd > -1) { +close(fd); +} + dpy_gl_release_dmabuf(dpy->con, >buf); -close(dmabuf->buf.fd); g_free(dmabuf); } diff --git a/ui/console.c b/ui/console.c index 1d0513a733..69560aac7e 100644 --- a/ui/console.c +++ b/ui/console.c @@ -1504,6 +1504,15 @@ int qemu_console_get_height(QemuConsole *con, int fallback) } } +int32_t dpy_gl_dmabuf_get_fd(QemuDmaBuf *dmabuf) +{ +if (dmabuf) { +return dmabuf->fd; +} + +return -1; +} + int qemu_invalidate_text_consoles(void) { QemuConsole *s; -- 2.34.1
[PATCH v4 3/3] ui/console: Introduce dpy_gl_create_dmabuf() helper
From: Dongwon Kim dpy_gl_create_dmabuf() allocates QemuDmaBuf and initialize fields. hw/display modules, hw/vfio and ui/dbus-listener now use this method to create QemuDmaBuf instead of declaring and initializing it on their own. Cc: Philippe Mathieu-Daudé Cc: Marc-André Lureau Cc: Vivek Kasireddy Signed-off-by: Dongwon Kim --- include/hw/vfio/vfio-common.h | 2 +- include/hw/virtio/virtio-gpu.h | 4 ++-- include/ui/console.h| 6 ++ hw/display/vhost-user-gpu.c | 33 ++--- hw/display/virtio-gpu-udmabuf.c | 23 --- hw/vfio/display.c | 26 +++--- ui/console.c| 28 ui/dbus-listener.c | 28 8 files changed, 86 insertions(+), 64 deletions(-) diff --git a/include/hw/vfio/vfio-common.h b/include/hw/vfio/vfio-common.h index b9da6c08ef..d66e27db02 100644 --- a/include/hw/vfio/vfio-common.h +++ b/include/hw/vfio/vfio-common.h @@ -148,7 +148,7 @@ typedef struct VFIOGroup { } VFIOGroup; typedef struct VFIODMABuf { -QemuDmaBuf buf; +QemuDmaBuf *buf; uint32_t pos_x, pos_y, pos_updates; uint32_t hot_x, hot_y, hot_updates; int dmabuf_id; diff --git a/include/hw/virtio/virtio-gpu.h b/include/hw/virtio/virtio-gpu.h index ed44cdad6b..56d6e821bf 100644 --- a/include/hw/virtio/virtio-gpu.h +++ b/include/hw/virtio/virtio-gpu.h @@ -169,7 +169,7 @@ struct VirtIOGPUBaseClass { DEFINE_PROP_UINT32("yres", _state, _conf.yres, 800) typedef struct VGPUDMABuf { -QemuDmaBuf buf; +QemuDmaBuf *buf; uint32_t scanout_id; QTAILQ_ENTRY(VGPUDMABuf) next; } VGPUDMABuf; @@ -238,7 +238,7 @@ struct VhostUserGPU { VhostUserBackend *vhost; int vhost_gpu_fd; /* closed by the chardev */ CharBackend vhost_chr; -QemuDmaBuf dmabuf[VIRTIO_GPU_MAX_SCANOUTS]; +QemuDmaBuf *dmabuf[VIRTIO_GPU_MAX_SCANOUTS]; bool backend_blocked; }; diff --git a/include/ui/console.h b/include/ui/console.h index d5334a806c..01e998264b 100644 --- a/include/ui/console.h +++ b/include/ui/console.h @@ -358,6 +358,12 @@ void dpy_gl_cursor_dmabuf(QemuConsole *con, QemuDmaBuf *dmabuf, bool have_hot, uint32_t hot_x, uint32_t hot_y); void dpy_gl_cursor_position(QemuConsole *con, uint32_t pos_x, uint32_t pos_y); +QemuDmaBuf *dpy_gl_create_dmabuf(uint32_t width, uint32_t height, + uint32_t stride, uint32_t x, + uint32_t y, uint32_t backing_width, + uint32_t backing_height, uint32_t fourcc, + uint64_t modifier, uint32_t dmabuf_fd, + bool allow_fences, bool y0_top); uint32_t dpy_gl_dmabuf_get_width(QemuDmaBuf *dmabuf); uint32_t dpy_gl_dmabuf_get_height(QemuDmaBuf *dmabuf); int32_t dpy_gl_dmabuf_get_fd(QemuDmaBuf *dmabuf); diff --git a/hw/display/vhost-user-gpu.c b/hw/display/vhost-user-gpu.c index 709c8a02a1..0e49a934ed 100644 --- a/hw/display/vhost-user-gpu.c +++ b/hw/display/vhost-user-gpu.c @@ -249,6 +249,7 @@ vhost_user_gpu_handle_display(VhostUserGPU *g, VhostUserGpuMsg *msg) case VHOST_USER_GPU_DMABUF_SCANOUT: { VhostUserGpuDMABUFScanout *m = >payload.dmabuf_scanout; int fd = qemu_chr_fe_get_msgfd(>vhost_chr); +uint64_t modifier = 0; QemuDmaBuf *dmabuf; if (m->scanout_id >= g->parent_obj.conf.max_outputs) { @@ -261,30 +262,32 @@ vhost_user_gpu_handle_display(VhostUserGPU *g, VhostUserGpuMsg *msg) g->parent_obj.enable = 1; con = g->parent_obj.scanout[m->scanout_id].con; -dmabuf = >dmabuf[m->scanout_id]; -if (dmabuf->fd >= 0) { -close(dmabuf->fd); -dmabuf->fd = -1; +dmabuf = g->dmabuf[m->scanout_id]; +if (dmabuf) { +int dmabuf_fd = dpy_gl_dmabuf_get_fd(dmabuf); +if (dmabuf_fd >= 0) { +close(dmabuf_fd); +} +dpy_gl_release_dmabuf(con, dmabuf); } -dpy_gl_release_dmabuf(con, dmabuf); + if (fd == -1) { dpy_gl_scanout_disable(con); break; } -*dmabuf = (QemuDmaBuf) { -.fd = fd, -.width = m->fd_width, -.height = m->fd_height, -.stride = m->fd_stride, -.fourcc = m->fd_drm_fourcc, -.y0_top = m->fd_flags & VIRTIO_GPU_RESOURCE_FLAG_Y_0_TOP, -}; + if (msg->request == VHOST_USER_GPU_DMABUF_SCANOUT2) { VhostUserGpuDMABUFScanout2 *m2 = >payload.dmabuf_scanout2; -dmabuf->modifier = m2->modifier; +modifier = m2->modifier; } -dpy_gl_scanout_dmabuf(con, dmabuf); +dmabuf = dpy_gl_create_dmabu
[PATCH v4 0/3] ui/console: Introduce helpers for creating and
From: Dongwon Kim QemuDmaBuf struct is defined and primarily used by ui/console/gl so it is better to handle its creation, initialization and access within ui/console rather than within hw modules such as hw/display/virtio-gpu, hw/display/vhost-user-gpu and hw/vfio as well as ui/dbus-listener. v4: refactored patches in the previous series made ui/dbus-listener and hw/display/vhost-user-gpu to use the new helpers Dongwon Kim (3): ui/console: Introduce dpy_gl_dmabuf_get_height/width() helpers ui/console: Introduce dpy_gl_dmabuf_get_fd() helper ui/console: Introduce dpy_gl_create_dmabuf() helper include/hw/vfio/vfio-common.h | 2 +- include/hw/virtio/virtio-gpu.h | 2 +- include/ui/console.h| 9 ++ hw/display/vhost-user-gpu.c | 12 +++ hw/display/virtio-gpu-udmabuf.c | 26 ++-- hw/vfio/display.c | 36 +++-- ui/console.c| 55 + ui/dbus-listener.c | 22 ++--- 8 files changed, 109 insertions(+), 55 deletions(-) -- 2.34.1
[PATCH v4] ui/gtk: flush display pipeline before saving vmstate when blob=true
From: Dongwon Kim It is required to ensure the current scanout frame is completed before transitioning guest's run-state to save to prevent potential guest waiting for the response on the resource flush of the old scanout frame upon resume. v2: Giving some time for the fence to be signaled before flushing the pipeline v3: Prevent redudant call of gd_hw_gl_flushed by checking dmabuf and fence_fd >= 0 in it (e.g. during and after eglClientWaitSync in gd_change_runstate) v4: Rewrote the commit msg Creating fence_fd in the same function where sync is created to handle the case where the valid sync is created but fence_fd is failed to be created. 0 is a valid fd so any fence_fd > -1 for the fence in draw function in gtk-egl.c and gtk-gl-area.c will be considered valid egl_sync and fence_fd for it are created in the same function Cc: Marc-André Lureau Cc: Vivek Kasireddy Signed-off-by: Dongwon Kim --- ui/egl-helpers.c | 16 ++-- ui/gtk-egl.c | 10 ++ ui/gtk-gl-area.c | 9 ++--- ui/gtk.c | 31 +++ 4 files changed, 37 insertions(+), 29 deletions(-) diff --git a/ui/egl-helpers.c b/ui/egl-helpers.c index 3d19dbe382..b6a8169ffc 100644 --- a/ui/egl-helpers.c +++ b/ui/egl-helpers.c @@ -376,20 +376,16 @@ void egl_dmabuf_create_sync(QemuDmaBuf *dmabuf) EGL_SYNC_NATIVE_FENCE_ANDROID, NULL); if (sync != EGL_NO_SYNC_KHR) { dmabuf->sync = sync; +dmabuf->fence_fd = eglDupNativeFenceFDANDROID(qemu_egl_display, + dmabuf->sync); +if (dmabuf->fence_fd < 0) { +eglDestroySyncKHR(qemu_egl_display, dmabuf->sync); +dmabuf->sync = NULL; +} } } } -void egl_dmabuf_create_fence(QemuDmaBuf *dmabuf) -{ -if (dmabuf->sync) { -dmabuf->fence_fd = eglDupNativeFenceFDANDROID(qemu_egl_display, - dmabuf->sync); -eglDestroySyncKHR(qemu_egl_display, dmabuf->sync); -dmabuf->sync = NULL; -} -} - #endif /* CONFIG_GBM */ /* -- */ diff --git a/ui/gtk-egl.c b/ui/gtk-egl.c index 3af5ac5bcf..683a87c6b3 100644 --- a/ui/gtk-egl.c +++ b/ui/gtk-egl.c @@ -98,8 +98,8 @@ void gd_egl_draw(VirtualConsole *vc) glFlush(); #ifdef CONFIG_GBM if (dmabuf) { -egl_dmabuf_create_fence(dmabuf); -if (dmabuf->fence_fd > 0) { +egl_dmabuf_create_sync(dmabuf); +if (dmabuf->fence_fd > -1) { qemu_set_fd_handler(dmabuf->fence_fd, gd_hw_gl_flushed, NULL, vc); return; } @@ -348,12 +348,6 @@ void gd_egl_scanout_flush(DisplayChangeListener *dcl, egl_fb_blit(>gfx.win_fb, >gfx.guest_fb, !vc->gfx.y0_top); } -#ifdef CONFIG_GBM -if (vc->gfx.guest_fb.dmabuf) { -egl_dmabuf_create_sync(vc->gfx.guest_fb.dmabuf); -} -#endif - eglSwapBuffers(qemu_egl_display, vc->gfx.esurface); } diff --git a/ui/gtk-gl-area.c b/ui/gtk-gl-area.c index 52dcac161e..7791498646 100644 --- a/ui/gtk-gl-area.c +++ b/ui/gtk-gl-area.c @@ -77,16 +77,11 @@ void gd_gl_area_draw(VirtualConsole *vc) glBlitFramebuffer(0, y1, vc->gfx.w, y2, 0, 0, ww, wh, GL_COLOR_BUFFER_BIT, GL_NEAREST); -#ifdef CONFIG_GBM -if (dmabuf) { -egl_dmabuf_create_sync(dmabuf); -} -#endif glFlush(); #ifdef CONFIG_GBM if (dmabuf) { -egl_dmabuf_create_fence(dmabuf); -if (dmabuf->fence_fd > 0) { +egl_dmabuf_create_sync(dmabuf); +if (dmabuf->fence_fd > -1) { qemu_set_fd_handler(dmabuf->fence_fd, gd_hw_gl_flushed, NULL, vc); return; } diff --git a/ui/gtk.c b/ui/gtk.c index 810d7fc796..bbe05a0baf 100644 --- a/ui/gtk.c +++ b/ui/gtk.c @@ -597,10 +597,14 @@ void gd_hw_gl_flushed(void *vcon) VirtualConsole *vc = vcon; QemuDmaBuf *dmabuf = vc->gfx.guest_fb.dmabuf; -qemu_set_fd_handler(dmabuf->fence_fd, NULL, NULL, NULL); -close(dmabuf->fence_fd); -dmabuf->fence_fd = -1; -graphic_hw_gl_block(vc->gfx.dcl.con, false); +if (dmabuf && dmabuf->fence_fd > -1) { +qemu_set_fd_handler(dmabuf->fence_fd, NULL, NULL, NULL); +close(dmabuf->fence_fd); +dmabuf->fence_fd = -1; +eglDestroySyncKHR(qemu_egl_display, dmabuf->sync); +dmabuf->sync = NULL; +graphic_hw_gl_block(vc->gfx.dcl.con, false); +} } /** DisplayState Callbacks (opengl version) **/ @@ -678,6 +682,25 @@ static const DisplayGLCtxOps egl_ctx_ops = { static void gd_change
[PATCH 1/3] hw/virtio: initialize QemuDmaBuf using the function from ui/console
From: Dongwon Kim QemuDmaBuf is an abstraction of dmabuf specifically for ui/console usage. To enhance safety and maintainability, it is needed to centralizes its creation and initialization within ui/console using newly introduced methods. Cc: Philippe Mathieu-Daudé Cc: Marc-André Lureau Cc: Vivek Kasireddy Signed-off-by: Dongwon Kim --- hw/display/virtio-gpu-udmabuf.c | 27 +++ include/hw/virtio/virtio-gpu.h | 2 +- 2 files changed, 12 insertions(+), 17 deletions(-) diff --git a/hw/display/virtio-gpu-udmabuf.c b/hw/display/virtio-gpu-udmabuf.c index d51184d658..dde6c8e9d9 100644 --- a/hw/display/virtio-gpu-udmabuf.c +++ b/hw/display/virtio-gpu-udmabuf.c @@ -162,7 +162,7 @@ static void virtio_gpu_free_dmabuf(VirtIOGPU *g, VGPUDMABuf *dmabuf) struct virtio_gpu_scanout *scanout; scanout = >parent_obj.scanout[dmabuf->scanout_id]; -dpy_gl_release_dmabuf(scanout->con, >buf); +dpy_gl_release_dmabuf(scanout->con, dmabuf->buf); QTAILQ_REMOVE(>dmabuf.bufs, dmabuf, next); g_free(dmabuf); } @@ -181,17 +181,10 @@ static VGPUDMABuf } dmabuf = g_new0(VGPUDMABuf, 1); -dmabuf->buf.width = r->width; -dmabuf->buf.height = r->height; -dmabuf->buf.stride = fb->stride; -dmabuf->buf.x = r->x; -dmabuf->buf.y = r->y; -dmabuf->buf.backing_width = fb->width; -dmabuf->buf.backing_height = fb->height; -dmabuf->buf.fourcc = qemu_pixman_to_drm_format(fb->format); -dmabuf->buf.fd = res->dmabuf_fd; -dmabuf->buf.allow_fences = true; -dmabuf->buf.draw_submitted = false; +dmabuf->buf = dpy_gl_create_dmabuf(r->width, r->height, fb->stride, + r->x, r->y, fb->width, fb->height, + qemu_pixman_to_drm_format(fb->format), + 0, res->dmabuf_fd, false); dmabuf->scanout_id = scanout_id; QTAILQ_INSERT_HEAD(>dmabuf.bufs, dmabuf, next); @@ -206,21 +199,23 @@ int virtio_gpu_update_dmabuf(VirtIOGPU *g, { struct virtio_gpu_scanout *scanout = >parent_obj.scanout[scanout_id]; VGPUDMABuf *new_primary, *old_primary = NULL; +uint32_t width, height; new_primary = virtio_gpu_create_dmabuf(g, scanout_id, res, fb, r); if (!new_primary) { return -EINVAL; } +width = dpy_gl_dmabuf_get_width(new_primary->buf); +height = dpy_gl_dmabuf_get_height(new_primary->buf); + if (g->dmabuf.primary[scanout_id]) { old_primary = g->dmabuf.primary[scanout_id]; } g->dmabuf.primary[scanout_id] = new_primary; -qemu_console_resize(scanout->con, -new_primary->buf.width, -new_primary->buf.height); -dpy_gl_scanout_dmabuf(scanout->con, _primary->buf); +qemu_console_resize(scanout->con, width, height); +dpy_gl_scanout_dmabuf(scanout->con, new_primary->buf); if (old_primary) { virtio_gpu_free_dmabuf(g, old_primary); diff --git a/include/hw/virtio/virtio-gpu.h b/include/hw/virtio/virtio-gpu.h index ed44cdad6b..010083e8e3 100644 --- a/include/hw/virtio/virtio-gpu.h +++ b/include/hw/virtio/virtio-gpu.h @@ -169,7 +169,7 @@ struct VirtIOGPUBaseClass { DEFINE_PROP_UINT32("yres", _state, _conf.yres, 800) typedef struct VGPUDMABuf { -QemuDmaBuf buf; +QemuDmaBuf *buf; uint32_t scanout_id; QTAILQ_ENTRY(VGPUDMABuf) next; } VGPUDMABuf; -- 2.34.1
[PATCH 2/3] hw/vfio: intialize QemuDmaBuf using the function from ui/console
From: Dongwon Kim QemuDmaBuf is an abstraction of dmabuf specifically for ui/console usage. To enhance safety and maintainability, it is needed to centralizes its creation and initialization within ui/console using newly introduced methods. Cc: Philippe Mathieu-Daudé Cc: Marc-André Lureau Cc: Vivek Kasireddy Signed-off-by: Dongwon Kim --- hw/vfio/display.c | 35 --- include/hw/vfio/vfio-common.h | 2 +- 2 files changed, 21 insertions(+), 16 deletions(-) diff --git a/hw/vfio/display.c b/hw/vfio/display.c index 1aa440c663..a3bdb01789 100644 --- a/hw/vfio/display.c +++ b/hw/vfio/display.c @@ -241,14 +241,10 @@ static VFIODMABuf *vfio_display_get_dmabuf(VFIOPCIDevice *vdev, dmabuf = g_new0(VFIODMABuf, 1); dmabuf->dmabuf_id = plane.dmabuf_id; -dmabuf->buf.width = plane.width; -dmabuf->buf.height = plane.height; -dmabuf->buf.backing_width = plane.width; -dmabuf->buf.backing_height = plane.height; -dmabuf->buf.stride = plane.stride; -dmabuf->buf.fourcc = plane.drm_format; -dmabuf->buf.modifier = plane.drm_format_mod; -dmabuf->buf.fd = fd; +dmabuf->buf = dpy_gl_create_dmabuf(plane.width, plane.height, plane.stride, + 0, 0, plane.width, plane.height, + plane.drm_format, plane.drm_format_mod, + fd, false); if (plane_type == DRM_PLANE_TYPE_CURSOR) { vfio_display_update_cursor(dmabuf, ); } @@ -259,9 +255,15 @@ static VFIODMABuf *vfio_display_get_dmabuf(VFIOPCIDevice *vdev, static void vfio_display_free_one_dmabuf(VFIODisplay *dpy, VFIODMABuf *dmabuf) { +int fd; + QTAILQ_REMOVE(>dmabuf.bufs, dmabuf, next); -dpy_gl_release_dmabuf(dpy->con, >buf); -close(dmabuf->buf.fd); +fd = dpy_gl_dmabuf_get_fd(dmabuf->buf); +if (fd > -1) { +close(fd); +} + +dpy_gl_release_dmabuf(dpy->con, dmabuf->buf); g_free(dmabuf); } @@ -286,6 +288,7 @@ static void vfio_display_dmabuf_update(void *opaque) VFIOPCIDevice *vdev = opaque; VFIODisplay *dpy = vdev->dpy; VFIODMABuf *primary, *cursor; +uint32_t width, height; bool free_bufs = false, new_cursor = false; primary = vfio_display_get_dmabuf(vdev, DRM_PLANE_TYPE_PRIMARY); @@ -296,11 +299,13 @@ static void vfio_display_dmabuf_update(void *opaque) return; } +width = dpy_gl_dmabuf_get_width(primary->buf); +height = dpy_gl_dmabuf_get_height(primary->buf); + if (dpy->dmabuf.primary != primary) { dpy->dmabuf.primary = primary; -qemu_console_resize(dpy->con, -primary->buf.width, primary->buf.height); -dpy_gl_scanout_dmabuf(dpy->con, >buf); +qemu_console_resize(dpy->con, width, height); +dpy_gl_scanout_dmabuf(dpy->con, primary->buf); free_bufs = true; } @@ -314,7 +319,7 @@ static void vfio_display_dmabuf_update(void *opaque) if (cursor && (new_cursor || cursor->hot_updates)) { bool have_hot = (cursor->hot_x != 0x && cursor->hot_y != 0x); -dpy_gl_cursor_dmabuf(dpy->con, >buf, have_hot, +dpy_gl_cursor_dmabuf(dpy->con, cursor->buf, have_hot, cursor->hot_x, cursor->hot_y); cursor->hot_updates = 0; } else if (!cursor && new_cursor) { @@ -328,7 +333,7 @@ static void vfio_display_dmabuf_update(void *opaque) cursor->pos_updates = 0; } -dpy_gl_update(dpy->con, 0, 0, primary->buf.width, primary->buf.height); +dpy_gl_update(dpy->con, 0, 0, width, height); if (free_bufs) { vfio_display_free_dmabufs(vdev); diff --git a/include/hw/vfio/vfio-common.h b/include/hw/vfio/vfio-common.h index b9da6c08ef..d66e27db02 100644 --- a/include/hw/vfio/vfio-common.h +++ b/include/hw/vfio/vfio-common.h @@ -148,7 +148,7 @@ typedef struct VFIOGroup { } VFIOGroup; typedef struct VFIODMABuf { -QemuDmaBuf buf; +QemuDmaBuf *buf; uint32_t pos_x, pos_y, pos_updates; uint32_t hot_x, hot_y, hot_updates; int dmabuf_id; -- 2.34.1
[PATCH 3/3] ui/console: add methods for allocating, intializing and accessing QemuDmaBuf
From: Dongwon Kim This commit introduces new methods within ui/console to handle the allocation, initialization, and field retrieval of QemuDmaBuf. By isolating these operations within ui/console, it enhances safety and encapsulation of the struct. Cc: Philippe Mathieu-Daudé Cc: Marc-André Lureau Cc: Vivek Kasireddy Signed-off-by: Dongwon Kim --- include/ui/console.h | 10 ui/console.c | 55 2 files changed, 65 insertions(+) diff --git a/include/ui/console.h b/include/ui/console.h index 0bc7a00ac0..70903f1b0d 100644 --- a/include/ui/console.h +++ b/include/ui/console.h @@ -279,6 +279,7 @@ typedef struct DisplayChangeListenerOps { /* optional */ void (*dpy_gl_cursor_position)(DisplayChangeListener *dcl, uint32_t pos_x, uint32_t pos_y); + /* optional */ void (*dpy_gl_release_dmabuf)(DisplayChangeListener *dcl, QemuDmaBuf *dmabuf); @@ -358,6 +359,15 @@ void dpy_gl_cursor_dmabuf(QemuConsole *con, QemuDmaBuf *dmabuf, bool have_hot, uint32_t hot_x, uint32_t hot_y); void dpy_gl_cursor_position(QemuConsole *con, uint32_t pos_x, uint32_t pos_y); +QemuDmaBuf *dpy_gl_create_dmabuf(uint32_t width, uint32_t height, + uint32_t stride, uint32_t x, + uint32_t y, uint32_t backing_width, + uint32_t backing_height, uint32_t fourcc, + uint32_t modifier, uint32_t dmabuf_fd, + bool allow_fences); +uint32_t dpy_gl_dmabuf_get_width(QemuDmaBuf *dmabuf); +uint32_t dpy_gl_dmabuf_get_height(QemuDmaBuf *dmabuf); +int32_t dpy_gl_dmabuf_get_fd(QemuDmaBuf *dmabuf); void dpy_gl_release_dmabuf(QemuConsole *con, QemuDmaBuf *dmabuf); void dpy_gl_update(QemuConsole *con, diff --git a/ui/console.c b/ui/console.c index 43226c5c14..bac24756f0 100644 --- a/ui/console.c +++ b/ui/console.c @@ -1132,6 +1132,60 @@ void dpy_gl_cursor_position(QemuConsole *con, } } +QemuDmaBuf *dpy_gl_create_dmabuf(uint32_t width, uint32_t height, + uint32_t stride, uint32_t x, + uint32_t y, uint32_t backing_width, + uint32_t backing_height, uint32_t fourcc, + uint32_t modifier, uint32_t dmabuf_fd, + bool allow_fences) +{ +QemuDmaBuf *dmabuf; + +dmabuf = g_new0(QemuDmaBuf, 1); + +dmabuf->width = width; +dmabuf->height = height; +dmabuf->stride = stride; +dmabuf->x = x; +dmabuf->y = y; +dmabuf->backing_width = backing_width; +dmabuf->backing_height = backing_height; +dmabuf->fourcc = fourcc; +dmabuf->modifier = modifier; +dmabuf->fd = dmabuf_fd; +dmabuf->allow_fences = allow_fences; +dmabuf->fence_fd = -1; + +return dmabuf; +} + +uint32_t dpy_gl_dmabuf_get_width(QemuDmaBuf *dmabuf) +{ +if (dmabuf) { +return dmabuf->width; +} + +return 0; +} + +uint32_t dpy_gl_dmabuf_get_height(QemuDmaBuf *dmabuf) +{ +if (dmabuf) { +return dmabuf->height; +} + +return 0; +} + +int32_t dpy_gl_dmabuf_get_fd(QemuDmaBuf *dmabuf) +{ +if (dmabuf) { +return dmabuf->fd; +} + +return -1; +} + void dpy_gl_release_dmabuf(QemuConsole *con, QemuDmaBuf *dmabuf) { @@ -1145,6 +1199,7 @@ void dpy_gl_release_dmabuf(QemuConsole *con, if (dcl->ops->dpy_gl_release_dmabuf) { dcl->ops->dpy_gl_release_dmabuf(dcl, dmabuf); } +g_free(dmabuf); } } -- 2.34.1
[PATCH 0/3] ui/console: initialize QemuDmaBuf in ui/console
From: Dongwon Kim QemuDmaBuf struct is defined and primarily used by ui/console/gl so it is better to handle its creation, initialization and access within ui/console rather than within hw modules such as hw/display/virtio-gpu and hw/vfio/display. To achieve this, new methods for allocating, initializing the struct, and accessing certain fields necessary for hardware modules have been introduced in ui/console.c. (3rd patch) Furthermore, modifications have been made to hw/display/virtio-gpu and hw/vfio/display to utilize these new methods instead of setting up the struct independently. (1st and 2nd patches) Dongwon Kim (3): hw/virtio: intialize QemuDmaBuf using the function from ui/console hw/vfio: intialize QemuDmaBuf using the function from ui/console ui/console: add methods for allocating, intializing and accessing QemuDmaBuf hw/display/virtio-gpu-udmabuf.c | 27 +++- hw/vfio/display.c | 35 - include/hw/vfio/vfio-common.h | 2 +- include/hw/virtio/virtio-gpu.h | 2 +- include/ui/console.h| 10 ++ ui/console.c| 55 + 6 files changed, 98 insertions(+), 33 deletions(-) -- 2.34.1
[PATCH] ui/console: initialize QemuDmaBuf from ui/console.
From: Dongwon Kim It is safer to create, initialize, and access all the parameters in QemuDmaBuf from a central location, ui/console, instead of hw/virtio-gpu or hw/vfio modules. Cc: Marc-André Lureau Cc: Vivek Kasireddy Signed-off-by: Dongwon Kim --- hw/display/virtio-gpu-udmabuf.c | 27 +++- hw/vfio/display.c | 35 - include/hw/vfio/vfio-common.h | 2 +- include/hw/virtio/virtio-gpu.h | 2 +- include/ui/console.h| 10 ++ ui/console.c| 55 + 6 files changed, 98 insertions(+), 33 deletions(-) diff --git a/hw/display/virtio-gpu-udmabuf.c b/hw/display/virtio-gpu-udmabuf.c index d51184d658..dde6c8e9d9 100644 --- a/hw/display/virtio-gpu-udmabuf.c +++ b/hw/display/virtio-gpu-udmabuf.c @@ -162,7 +162,7 @@ static void virtio_gpu_free_dmabuf(VirtIOGPU *g, VGPUDMABuf *dmabuf) struct virtio_gpu_scanout *scanout; scanout = >parent_obj.scanout[dmabuf->scanout_id]; -dpy_gl_release_dmabuf(scanout->con, >buf); +dpy_gl_release_dmabuf(scanout->con, dmabuf->buf); QTAILQ_REMOVE(>dmabuf.bufs, dmabuf, next); g_free(dmabuf); } @@ -181,17 +181,10 @@ static VGPUDMABuf } dmabuf = g_new0(VGPUDMABuf, 1); -dmabuf->buf.width = r->width; -dmabuf->buf.height = r->height; -dmabuf->buf.stride = fb->stride; -dmabuf->buf.x = r->x; -dmabuf->buf.y = r->y; -dmabuf->buf.backing_width = fb->width; -dmabuf->buf.backing_height = fb->height; -dmabuf->buf.fourcc = qemu_pixman_to_drm_format(fb->format); -dmabuf->buf.fd = res->dmabuf_fd; -dmabuf->buf.allow_fences = true; -dmabuf->buf.draw_submitted = false; +dmabuf->buf = dpy_gl_create_dmabuf(r->width, r->height, fb->stride, + r->x, r->y, fb->width, fb->height, + qemu_pixman_to_drm_format(fb->format), + 0, res->dmabuf_fd, false); dmabuf->scanout_id = scanout_id; QTAILQ_INSERT_HEAD(>dmabuf.bufs, dmabuf, next); @@ -206,21 +199,23 @@ int virtio_gpu_update_dmabuf(VirtIOGPU *g, { struct virtio_gpu_scanout *scanout = >parent_obj.scanout[scanout_id]; VGPUDMABuf *new_primary, *old_primary = NULL; +uint32_t width, height; new_primary = virtio_gpu_create_dmabuf(g, scanout_id, res, fb, r); if (!new_primary) { return -EINVAL; } +width = dpy_gl_dmabuf_get_width(new_primary->buf); +height = dpy_gl_dmabuf_get_height(new_primary->buf); + if (g->dmabuf.primary[scanout_id]) { old_primary = g->dmabuf.primary[scanout_id]; } g->dmabuf.primary[scanout_id] = new_primary; -qemu_console_resize(scanout->con, -new_primary->buf.width, -new_primary->buf.height); -dpy_gl_scanout_dmabuf(scanout->con, _primary->buf); +qemu_console_resize(scanout->con, width, height); +dpy_gl_scanout_dmabuf(scanout->con, new_primary->buf); if (old_primary) { virtio_gpu_free_dmabuf(g, old_primary); diff --git a/hw/vfio/display.c b/hw/vfio/display.c index 1aa440c663..a3bdb01789 100644 --- a/hw/vfio/display.c +++ b/hw/vfio/display.c @@ -241,14 +241,10 @@ static VFIODMABuf *vfio_display_get_dmabuf(VFIOPCIDevice *vdev, dmabuf = g_new0(VFIODMABuf, 1); dmabuf->dmabuf_id = plane.dmabuf_id; -dmabuf->buf.width = plane.width; -dmabuf->buf.height = plane.height; -dmabuf->buf.backing_width = plane.width; -dmabuf->buf.backing_height = plane.height; -dmabuf->buf.stride = plane.stride; -dmabuf->buf.fourcc = plane.drm_format; -dmabuf->buf.modifier = plane.drm_format_mod; -dmabuf->buf.fd = fd; +dmabuf->buf = dpy_gl_create_dmabuf(plane.width, plane.height, plane.stride, + 0, 0, plane.width, plane.height, + plane.drm_format, plane.drm_format_mod, + fd, false); if (plane_type == DRM_PLANE_TYPE_CURSOR) { vfio_display_update_cursor(dmabuf, ); } @@ -259,9 +255,15 @@ static VFIODMABuf *vfio_display_get_dmabuf(VFIOPCIDevice *vdev, static void vfio_display_free_one_dmabuf(VFIODisplay *dpy, VFIODMABuf *dmabuf) { +int fd; + QTAILQ_REMOVE(>dmabuf.bufs, dmabuf, next); -dpy_gl_release_dmabuf(dpy->con, >buf); -close(dmabuf->buf.fd); +fd = dpy_gl_dmabuf_get_fd(dmabuf->buf); +if (fd > -1) { +close(fd); +} + +dpy_gl_release_dmabuf(dpy->con, dmabuf->buf); g_free(dmabuf); } @@ -286,6 +288,7 @@ static void vfio_display_dmabuf_update(void *opaque) VFIOPCIDevice *vdev = opaque; VFIODisplay *dpy = vdev->dpy; VFIODMABuf *primary, *cu
[PATCH v2] virtio-gpu: first surface update with blob scanout after resumed
From: Dongwon Kim The guest surface needs to be updated with a blob scanout after resumed from saved vm state if blob is enabled. v2: Rebased Cc: Marc-André Lureau Cc: Vivek Kasireddy Signed-off-by: Dongwon Kim --- hw/display/virtio-gpu.c | 21 ++--- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c index 1c1ee230b3..01bc4f9565 100644 --- a/hw/display/virtio-gpu.c +++ b/hw/display/virtio-gpu.c @@ -1422,16 +1422,23 @@ static int virtio_gpu_post_load(void *opaque, int version_id) if (!res) { return -EINVAL; } -scanout->ds = qemu_create_displaysurface_pixman(res->image); -if (!scanout->ds) { -return -EINVAL; -} + +if (res->blob_size) { +assert(g->dmabuf.primary[i] != NULL); +g->dmabuf.primary[i]->buf.fd = res->dmabuf_fd; +dpy_gl_scanout_dmabuf(scanout->con, >dmabuf.primary[i]->buf); +} else { +scanout->ds = qemu_create_displaysurface_pixman(res->image); +if (!scanout->ds) { +return -EINVAL; +} #ifdef WIN32 -qemu_displaysurface_win32_set_handle(scanout->ds, res->handle, 0); +qemu_displaysurface_win32_set_handle(scanout->ds, res->handle, 0); #endif +dpy_gfx_replace_surface(scanout->con, scanout->ds); +dpy_gfx_update_full(scanout->con); +} -dpy_gfx_replace_surface(scanout->con, scanout->ds); -dpy_gfx_update_full(scanout->con); if (scanout->cursor.resource_id) { update_cursor(g, >cursor); } -- 2.34.1
[PATCH v3] ui/gtk: flush display pipeline before saving vmstate when blob=true
From: Dongwon Kim If the guest state is paused before it gets a response for the current scanout frame submission (resource-flush), it won't flush new frames after being restored as it still waits for the old response, which is accepted as a scanout render done signal. So it's needed to unblock the current scanout render pipeline before the run state is changed to make sure the guest receives the response for the current frame submission. v2: Giving some time for the fence to be signaled before flushing the pipeline v3: Prevent redundant call of gd_hw_gl_flushed by checking dmabuf and fence_fd >= 0 in it (e.g. during and after eglClientWaitSync in gd_change_runstate). Destroy sync object later in gd_hw_fl_flushed Cc: Marc-André Lureau Cc: Vivek Kasireddy Signed-off-by: Dongwon Kim --- ui/egl-helpers.c | 2 -- ui/gtk.c | 31 +++ 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/ui/egl-helpers.c b/ui/egl-helpers.c index 3d19dbe382..a77f9e57d9 100644 --- a/ui/egl-helpers.c +++ b/ui/egl-helpers.c @@ -385,8 +385,6 @@ void egl_dmabuf_create_fence(QemuDmaBuf *dmabuf) if (dmabuf->sync) { dmabuf->fence_fd = eglDupNativeFenceFDANDROID(qemu_egl_display, dmabuf->sync); -eglDestroySyncKHR(qemu_egl_display, dmabuf->sync); -dmabuf->sync = NULL; } } diff --git a/ui/gtk.c b/ui/gtk.c index 810d7fc796..eaca890cba 100644 --- a/ui/gtk.c +++ b/ui/gtk.c @@ -597,10 +597,14 @@ void gd_hw_gl_flushed(void *vcon) VirtualConsole *vc = vcon; QemuDmaBuf *dmabuf = vc->gfx.guest_fb.dmabuf; -qemu_set_fd_handler(dmabuf->fence_fd, NULL, NULL, NULL); -close(dmabuf->fence_fd); -dmabuf->fence_fd = -1; -graphic_hw_gl_block(vc->gfx.dcl.con, false); +if (dmabuf && dmabuf->fence_fd >= 0) { +qemu_set_fd_handler(dmabuf->fence_fd, NULL, NULL, NULL); +close(dmabuf->fence_fd); +dmabuf->fence_fd = -1; +eglDestroySyncKHR(qemu_egl_display, dmabuf->sync); +dmabuf->sync = NULL; +graphic_hw_gl_block(vc->gfx.dcl.con, false); +} } /** DisplayState Callbacks (opengl version) **/ @@ -678,6 +682,25 @@ static const DisplayGLCtxOps egl_ctx_ops = { static void gd_change_runstate(void *opaque, bool running, RunState state) { GtkDisplayState *s = opaque; +int i; + +if (state == RUN_STATE_SAVE_VM) { +for (i = 0; i < s->nb_vcs; i++) { +VirtualConsole *vc = >vc[i]; + +if (vc->gfx.guest_fb.dmabuf && +vc->gfx.guest_fb.dmabuf->fence_fd >= 0) { +eglClientWaitSync(qemu_egl_display, + vc->gfx.guest_fb.dmabuf->sync, + EGL_SYNC_FLUSH_COMMANDS_BIT_KHR, + 1); + +/* force flushing current scanout blob rendering process + * just in case the fence is still not signaled */ +gd_hw_gl_flushed(vc); +} +} +} gd_update_caption(s); } -- 2.34.1
[PATCH 1/2] ui/gtk: flush display pipeline before saving vmstate when blob=true
From: Dongwon Kim If the guest state is paused before it gets a response for the current scanout frame submission (resource-flush), it won't flush new frames after being restored as it still waits for the old response, which is accepted as a scanout render done signal. So it's needed to unblock the current scanout render pipeline before the run state is changed to make sure the guest receives the response for the current frame submission. v2: Giving some time for the fence to be signaled before flushing the pipeline v3: Prevent redundant call of gd_hw_gl_flushed by checking dmabuf and fence_fd >= 0 in it (e.g. during and after eglClientWaitSync in gd_change_runstate). Destroy sync object later in gd_hw_fl_flushed Cc: Marc-André Lureau Cc: Vivek Kasireddy Signed-off-by: Dongwon Kim --- ui/egl-helpers.c | 2 -- ui/gtk.c | 31 +++ 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/ui/egl-helpers.c b/ui/egl-helpers.c index 3d19dbe382..a77f9e57d9 100644 --- a/ui/egl-helpers.c +++ b/ui/egl-helpers.c @@ -385,8 +385,6 @@ void egl_dmabuf_create_fence(QemuDmaBuf *dmabuf) if (dmabuf->sync) { dmabuf->fence_fd = eglDupNativeFenceFDANDROID(qemu_egl_display, dmabuf->sync); -eglDestroySyncKHR(qemu_egl_display, dmabuf->sync); -dmabuf->sync = NULL; } } diff --git a/ui/gtk.c b/ui/gtk.c index 810d7fc796..eaca890cba 100644 --- a/ui/gtk.c +++ b/ui/gtk.c @@ -597,10 +597,14 @@ void gd_hw_gl_flushed(void *vcon) VirtualConsole *vc = vcon; QemuDmaBuf *dmabuf = vc->gfx.guest_fb.dmabuf; -qemu_set_fd_handler(dmabuf->fence_fd, NULL, NULL, NULL); -close(dmabuf->fence_fd); -dmabuf->fence_fd = -1; -graphic_hw_gl_block(vc->gfx.dcl.con, false); +if (dmabuf && dmabuf->fence_fd >= 0) { +qemu_set_fd_handler(dmabuf->fence_fd, NULL, NULL, NULL); +close(dmabuf->fence_fd); +dmabuf->fence_fd = -1; +eglDestroySyncKHR(qemu_egl_display, dmabuf->sync); +dmabuf->sync = NULL; +graphic_hw_gl_block(vc->gfx.dcl.con, false); +} } /** DisplayState Callbacks (opengl version) **/ @@ -678,6 +682,25 @@ static const DisplayGLCtxOps egl_ctx_ops = { static void gd_change_runstate(void *opaque, bool running, RunState state) { GtkDisplayState *s = opaque; +int i; + +if (state == RUN_STATE_SAVE_VM) { +for (i = 0; i < s->nb_vcs; i++) { +VirtualConsole *vc = >vc[i]; + +if (vc->gfx.guest_fb.dmabuf && +vc->gfx.guest_fb.dmabuf->fence_fd >= 0) { +eglClientWaitSync(qemu_egl_display, + vc->gfx.guest_fb.dmabuf->sync, + EGL_SYNC_FLUSH_COMMANDS_BIT_KHR, + 1); + +/* force flushing current scanout blob rendering process + * just in case the fence is still not signaled */ +gd_hw_gl_flushed(vc); +} +} +} gd_update_caption(s); } -- 2.34.1
[PATCH 2/2] virtio-gpu: first surface update with blob scanout after resumed
From: Dongwon Kim The guest surface needs to be updated with a blob scanout after resumed from saved vm state if blob is enabled. Cc: Marc-André Lureau Cc: Vivek Kasireddy Signed-off-by: Dongwon Kim --- hw/display/virtio-gpu.c | 21 ++--- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c index 1c1ee230b3..01bc4f9565 100644 --- a/hw/display/virtio-gpu.c +++ b/hw/display/virtio-gpu.c @@ -1422,16 +1422,23 @@ static int virtio_gpu_post_load(void *opaque, int version_id) if (!res) { return -EINVAL; } -scanout->ds = qemu_create_displaysurface_pixman(res->image); -if (!scanout->ds) { -return -EINVAL; -} + +if (res->blob_size) { +assert(g->dmabuf.primary[i] != NULL); +g->dmabuf.primary[i]->buf.fd = res->dmabuf_fd; +dpy_gl_scanout_dmabuf(scanout->con, >dmabuf.primary[i]->buf); +} else { +scanout->ds = qemu_create_displaysurface_pixman(res->image); +if (!scanout->ds) { +return -EINVAL; +} #ifdef WIN32 -qemu_displaysurface_win32_set_handle(scanout->ds, res->handle, 0); +qemu_displaysurface_win32_set_handle(scanout->ds, res->handle, 0); #endif +dpy_gfx_replace_surface(scanout->con, scanout->ds); +dpy_gfx_update_full(scanout->con); +} -dpy_gfx_replace_surface(scanout->con, scanout->ds); -dpy_gfx_update_full(scanout->con); if (scanout->cursor.resource_id) { update_cursor(g, >cursor); } -- 2.34.1
[PATCH 0/3] ui/gtk: introducing vc->visible
From: Dongwon Kim Drawing guest display frames can't be completed while the VC is not in visible state, which could result in timeout in both the host and the guest especially when using blob scanout. Therefore it is needed to update and track the visiblity status of the VC and unblock the pipeline in case when VC becomes invisible (e.g. windows minimization, switching among tabs) while processing a guest frame. First patch (0001-ui-gtk-skip...) is introducing a flag 'visible' to VirtualConsole struct then set it only if the VC and its window is visible. Second patch (0002-ui-gtk-set-...) sets the ui size to 0 when VC is invisible when the tab is closed or deactivated. This notifies the guest that the associated guest display is not active anymore. Third patch (0003-ui-gtk-reset-visible...) adds a callback for GTK window-state-event. The flag, 'visible' is updated based on the minization status of the window. Dongwon Kim (3): ui/gtk: skip drawing guest scanout when associated VC is invisible ui/gtk: set the ui size to 0 when invisible ui/gtk: reset visible flag when window is minimized include/ui/gtk.h | 1 + ui/gtk-egl.c | 8 +++ ui/gtk-gl-area.c | 8 +++ ui/gtk.c | 62 ++-- 4 files changed, 77 insertions(+), 2 deletions(-) -- 2.34.1
[PATCH 1/3] ui/gtk: skip drawing guest scanout when associated VC is invisible
From: Dongwon Kim A new flag "visible" is added to show visibility status of the gfx console. The flag is set to 'true' when the VC is visible but set to 'false' when it is hidden or closed. When the VC is invisible, drawing guest frames should be skipped as it will never be completed and it would potentially lock up the guest display especially when blob scanout is used. Cc: Marc-André Lureau Cc: Gerd Hoffmann Cc: Vivek Kasireddy Signed-off-by: Dongwon Kim --- include/ui/gtk.h | 1 + ui/gtk-egl.c | 8 ui/gtk-gl-area.c | 8 ui/gtk.c | 10 +- 4 files changed, 26 insertions(+), 1 deletion(-) diff --git a/include/ui/gtk.h b/include/ui/gtk.h index aa3d637029..2de38e5724 100644 --- a/include/ui/gtk.h +++ b/include/ui/gtk.h @@ -57,6 +57,7 @@ typedef struct VirtualGfxConsole { bool y0_top; bool scanout_mode; bool has_dmabuf; +bool visible; #endif } VirtualGfxConsole; diff --git a/ui/gtk-egl.c b/ui/gtk-egl.c index 3af5ac5bcf..993c283191 100644 --- a/ui/gtk-egl.c +++ b/ui/gtk-egl.c @@ -265,6 +265,10 @@ void gd_egl_scanout_dmabuf(DisplayChangeListener *dcl, #ifdef CONFIG_GBM VirtualConsole *vc = container_of(dcl, VirtualConsole, gfx.dcl); +if (!vc->gfx.visible) { +return; +} + eglMakeCurrent(qemu_egl_display, vc->gfx.esurface, vc->gfx.esurface, vc->gfx.ectx); @@ -363,6 +367,10 @@ void gd_egl_flush(DisplayChangeListener *dcl, VirtualConsole *vc = container_of(dcl, VirtualConsole, gfx.dcl); GtkWidget *area = vc->gfx.drawing_area; +if (!vc->gfx.visible) { +return; +} + if (vc->gfx.guest_fb.dmabuf && !vc->gfx.guest_fb.dmabuf->draw_submitted) { graphic_hw_gl_block(vc->gfx.dcl.con, true); vc->gfx.guest_fb.dmabuf->draw_submitted = true; diff --git a/ui/gtk-gl-area.c b/ui/gtk-gl-area.c index 52dcac161e..04e07bd7ee 100644 --- a/ui/gtk-gl-area.c +++ b/ui/gtk-gl-area.c @@ -285,6 +285,10 @@ void gd_gl_area_scanout_flush(DisplayChangeListener *dcl, { VirtualConsole *vc = container_of(dcl, VirtualConsole, gfx.dcl); +if (!vc->gfx.visible) { +return; +} + if (vc->gfx.guest_fb.dmabuf && !vc->gfx.guest_fb.dmabuf->draw_submitted) { graphic_hw_gl_block(vc->gfx.dcl.con, true); vc->gfx.guest_fb.dmabuf->draw_submitted = true; @@ -299,6 +303,10 @@ void gd_gl_area_scanout_dmabuf(DisplayChangeListener *dcl, #ifdef CONFIG_GBM VirtualConsole *vc = container_of(dcl, VirtualConsole, gfx.dcl); +if (!vc->gfx.visible) { +return; +} + gtk_gl_area_make_current(GTK_GL_AREA(vc->gfx.drawing_area)); egl_dmabuf_import_texture(dmabuf); if (!dmabuf->texture) { diff --git a/ui/gtk.c b/ui/gtk.c index 810d7fc796..02eb667d8a 100644 --- a/ui/gtk.c +++ b/ui/gtk.c @@ -1312,15 +1312,20 @@ static void gd_menu_quit(GtkMenuItem *item, void *opaque) static void gd_menu_switch_vc(GtkMenuItem *item, void *opaque) { GtkDisplayState *s = opaque; -VirtualConsole *vc = gd_vc_find_by_menu(s); +VirtualConsole *vc; GtkNotebook *nb = GTK_NOTEBOOK(s->notebook); gint page; +vc = gd_vc_find_current(s); +vc->gfx.visible = false; + +vc = gd_vc_find_by_menu(s); gtk_release_modifiers(s); if (vc) { page = gtk_notebook_page_num(nb, vc->tab_item); gtk_notebook_set_current_page(nb, page); gtk_widget_grab_focus(vc->focus); +vc->gfx.visible = true; } } @@ -1350,6 +1355,7 @@ static gboolean gd_tab_window_close(GtkWidget *widget, GdkEvent *event, VirtualConsole *vc = opaque; GtkDisplayState *s = vc->s; +vc->gfx.visible = false; gtk_widget_set_sensitive(vc->menu_item, true); gd_widget_reparent(vc->window, s->notebook, vc->tab_item); gtk_notebook_set_tab_label_text(GTK_NOTEBOOK(s->notebook), @@ -1423,6 +1429,7 @@ static void gd_menu_untabify(GtkMenuItem *item, void *opaque) gd_update_geometry_hints(vc); gd_update_caption(s); } +vc->gfx.visible = true; } static void gd_menu_show_menubar(GtkMenuItem *item, void *opaque) @@ -2471,6 +2478,7 @@ static void gtk_display_init(DisplayState *ds, DisplayOptions *opts) #ifdef CONFIG_GTK_CLIPBOARD gd_clipboard_init(s); #endif /* CONFIG_GTK_CLIPBOARD */ +vc->gfx.visible = true; } static void early_gtk_display_init(DisplayOptions *opts) -- 2.34.1
[PATCH 3/3] ui/gtk: reset visible flag when window is minimized
From: Dongwon Kim Adding a callback for window-state-event that resets the flag, 'visible' when associated window is minimized or restored. When minimizing, it cancels any of queued draw events associated with the VC. Cc: Marc-André Lureau Cc: Gerd Hoffmann Cc: Vivek Kasireddy Signed-off-by: Dongwon Kim --- ui/gtk.c | 39 +++ 1 file changed, 39 insertions(+) diff --git a/ui/gtk.c b/ui/gtk.c index 651ed3492f..5bbcb7de62 100644 --- a/ui/gtk.c +++ b/ui/gtk.c @@ -1381,6 +1381,37 @@ static gboolean gd_tab_window_close(GtkWidget *widget, GdkEvent *event, return TRUE; } +static gboolean gd_window_state_event(GtkWidget *widget, GdkEvent *event, + void *opaque) +{ +VirtualConsole *vc = opaque; + +if (!vc) { +return TRUE; +} + +if (event->window_state.new_window_state & GDK_WINDOW_STATE_ICONIFIED) { +vc->gfx.visible = false; +gd_set_ui_size(vc, 0, 0); +if (vc->gfx.guest_fb.dmabuf && +vc->gfx.guest_fb.dmabuf->draw_submitted) { +vc->gfx.guest_fb.dmabuf->draw_submitted = false; +graphic_hw_gl_block(vc->gfx.dcl.con, false); +} +/* Showing the ui only if window exists except for the current vc as GTK + * window for 's' is being used to display the GUI */ +} else if (vc->window || vc == gd_vc_find_current(vc->s)) { +GdkWindow *window; +window = gtk_widget_get_window(vc->gfx.drawing_area); +gd_set_ui_size(vc, gdk_window_get_width(window), + gdk_window_get_height(window)); + +vc->gfx.visible = true; +} + +return TRUE; +} + static gboolean gd_win_grab(void *opaque) { VirtualConsole *vc = opaque; @@ -1422,6 +1453,9 @@ static void gd_menu_untabify(GtkMenuItem *item, void *opaque) g_signal_connect(vc->window, "delete-event", G_CALLBACK(gd_tab_window_close), vc); +g_signal_connect(vc->window, "window-state-event", + G_CALLBACK(gd_window_state_event), vc); + gtk_widget_show_all(vc->window); if (qemu_console_is_graphic(vc->gfx.dcl.con)) { @@ -2470,6 +2504,11 @@ static void gtk_display_init(DisplayState *ds, DisplayOptions *opts) } vc = gd_vc_find_current(s); + +g_signal_connect(s->window, "window-state-event", + G_CALLBACK(gd_window_state_event), + vc); + gtk_widget_set_sensitive(s->view_menu, vc != NULL); #ifdef CONFIG_VTE gtk_widget_set_sensitive(s->copy_item, -- 2.34.1