From: Joelle van Dyne <j@getutm.app>
To: qemu-devel@nongnu.org
Cc: "Joelle van Dyne" <j@getutm.app>,
"Michael S. Tsirkin" <mst@redhat.com>,
"Alex Bennée" <alex.bennee@linaro.org>,
"Akihiko Odaki" <odaki@rsg.ci.i.u-tokyo.ac.jp>,
"Dmitry Osipenko" <dmitry.osipenko@collabora.com>,
"Marc-André Lureau" <marcandre.lureau@redhat.com>
Subject: [PATCH RFC 6/7] console: add cleanup callback for ScanoutTexture
Date: Tue, 2 Dec 2025 20:07:53 -0800 [thread overview]
Message-ID: <20251203040754.94487-7-j@getutm.app> (raw)
In-Reply-To: <20251203040754.94487-1-j@getutm.app>
Before we introduce changes that allow for QemuConsole to take ownership
of a texture handle, we need scaffolding that will allow us to callback
into a cleanup function any time the ScanoutTexture becomes invalid, which
is whenever the `scanout.kind` or `scanout.texture` gets updated.
The ordering is important: we need to first update the DisplayScanout,
then we need to notify all the listeners, and once all the listeners have
had the chance to finish using the previous native texture, we are safe to
call the cleanup function. This means we need to hold on to the previous
scanout native handle locally until all listeners are notified.
Signed-off-by: Joelle van Dyne <j@getutm.app>
---
include/ui/console.h | 9 +++++-
hw/display/virtio-gpu-virgl.c | 2 +-
ui/console.c | 56 +++++++++++++++++++++++++++++++----
3 files changed, 59 insertions(+), 8 deletions(-)
diff --git a/include/ui/console.h b/include/ui/console.h
index a45b524c57..df9c083a16 100644
--- a/include/ui/console.h
+++ b/include/ui/console.h
@@ -149,6 +149,11 @@ typedef struct ScanoutTextureNative {
.type = SCANOUT_TEXTURE_NATIVE_TYPE_NONE \
})
+/**
+ * Cleanup callback function when ScanoutTexture is about to be destroyed
+ */
+typedef void (*dpy_cleanup_texture)(ScanoutTextureNative *native);
+
typedef struct ScanoutTexture {
uint32_t backing_id;
bool backing_y_0_top;
@@ -159,6 +164,7 @@ typedef struct ScanoutTexture {
uint32_t width;
uint32_t height;
ScanoutTextureNative native;
+ dpy_cleanup_texture cb_cleanup;
} ScanoutTexture;
typedef struct QemuUIInfo {
@@ -347,7 +353,8 @@ void dpy_gl_scanout_texture(QemuConsole *con,
uint32_t backing_id, bool backing_y_0_top,
uint32_t backing_width, uint32_t backing_height,
uint32_t x, uint32_t y, uint32_t w, uint32_t h,
- ScanoutTextureNative native);
+ ScanoutTextureNative native,
+ dpy_cleanup_texture cb_cleanup);
void dpy_gl_scanout_dmabuf(QemuConsole *con,
QemuDmaBuf *dmabuf);
void dpy_gl_cursor_dmabuf(QemuConsole *con, QemuDmaBuf *dmabuf,
diff --git a/hw/display/virtio-gpu-virgl.c b/hw/display/virtio-gpu-virgl.c
index e091eb0c76..b7bc095676 100644
--- a/hw/display/virtio-gpu-virgl.c
+++ b/hw/display/virtio-gpu-virgl.c
@@ -492,7 +492,7 @@ static void virgl_cmd_set_scanout(VirtIOGPU *g,
info.flags & VIRTIO_GPU_RESOURCE_FLAG_Y_0_TOP,
info.width, info.height,
ss.r.x, ss.r.y, ss.r.width, ss.r.height,
- native);
+ native, NULL);
} else {
dpy_gfx_replace_surface(
g->parent_obj.scanout[ss.scanout_id].con, NULL);
diff --git a/ui/console.c b/ui/console.c
index 9378afd53d..8271c36586 100644
--- a/ui/console.c
+++ b/ui/console.c
@@ -808,6 +808,41 @@ void dpy_gfx_update_full(QemuConsole *con)
dpy_gfx_update(con, 0, 0, w, h);
}
+struct scanout_change {
+ ScanoutTextureNative native;
+ dpy_cleanup_texture cb_cleanup;
+};
+
+#define SCANOUT_CHANGE_NONE ((struct scanout_change){ NO_NATIVE_TEXTURE })
+
+static struct scanout_change dpy_change_scanout_kind(DisplayScanout *scanout,
+ enum display_scanout kind)
+{
+ struct scanout_change change = SCANOUT_CHANGE_NONE;
+
+ /**
+ * We cannot cleanup until the resource is no longer in use, so we record it
+ * You MUST call dpy_complete_scanout_change after all listeners are updated
+ */
+ if (scanout->kind == SCANOUT_TEXTURE && scanout->texture.cb_cleanup) {
+ change.native = scanout->texture.native;
+ change.cb_cleanup = scanout->texture.cb_cleanup;
+ }
+ scanout->kind = kind;
+
+ return change;
+}
+
+static void dpy_complete_scanout_change(struct scanout_change *change)
+{
+ /**
+ * If we previously have a texture and cleanup is required, we call it now
+ */
+ if (change->native.type != SCANOUT_TEXTURE_NATIVE_TYPE_NONE && change->cb_cleanup) {
+ change->cb_cleanup(&change->native);
+ }
+}
+
void dpy_gfx_replace_surface(QemuConsole *con,
DisplaySurface *surface)
{
@@ -818,6 +853,7 @@ void dpy_gfx_replace_surface(QemuConsole *con,
DisplayChangeListener *dcl;
int width;
int height;
+ struct scanout_change change = SCANOUT_CHANGE_NONE;
if (!surface) {
if (old_surface) {
@@ -833,7 +869,7 @@ void dpy_gfx_replace_surface(QemuConsole *con,
assert(old_surface != new_surface);
- con->scanout.kind = SCANOUT_SURFACE;
+ change = dpy_change_scanout_kind(&con->scanout, SCANOUT_SURFACE);
con->surface = new_surface;
dpy_gfx_create_texture(con, new_surface);
QLIST_FOREACH(dcl, &s->listeners, next) {
@@ -844,6 +880,7 @@ void dpy_gfx_replace_surface(QemuConsole *con,
}
dpy_gfx_destroy_texture(con, old_surface);
qemu_free_displaysurface(old_surface);
+ dpy_complete_scanout_change(&change);
}
bool dpy_gfx_check_format(QemuConsole *con,
@@ -1002,9 +1039,10 @@ void dpy_gl_scanout_disable(QemuConsole *con)
{
DisplayState *s = con->ds;
DisplayChangeListener *dcl;
+ struct scanout_change change = SCANOUT_CHANGE_NONE;
if (con->scanout.kind != SCANOUT_SURFACE) {
- con->scanout.kind = SCANOUT_NONE;
+ change = dpy_change_scanout_kind(&con->scanout, SCANOUT_NONE);
}
QLIST_FOREACH(dcl, &s->listeners, next) {
if (con != dcl->con) {
@@ -1014,6 +1052,7 @@ void dpy_gl_scanout_disable(QemuConsole *con)
dcl->ops->dpy_gl_scanout_disable(dcl);
}
}
+ dpy_complete_scanout_change(&change);
}
void dpy_gl_scanout_texture(QemuConsole *con,
@@ -1023,15 +1062,17 @@ void dpy_gl_scanout_texture(QemuConsole *con,
uint32_t backing_height,
uint32_t x, uint32_t y,
uint32_t width, uint32_t height,
- ScanoutTextureNative native)
+ ScanoutTextureNative native,
+ dpy_cleanup_texture cb_cleanup)
{
DisplayState *s = con->ds;
DisplayChangeListener *dcl;
+ struct scanout_change change = SCANOUT_CHANGE_NONE;
- con->scanout.kind = SCANOUT_TEXTURE;
+ change = dpy_change_scanout_kind(&con->scanout, SCANOUT_TEXTURE);
con->scanout.texture = (ScanoutTexture) {
backing_id, backing_y_0_top, backing_width, backing_height,
- x, y, width, height, native,
+ x, y, width, height, native, cb_cleanup
};
QLIST_FOREACH(dcl, &s->listeners, next) {
if (con != dcl->con) {
@@ -1045,6 +1086,7 @@ void dpy_gl_scanout_texture(QemuConsole *con,
native);
}
}
+ dpy_complete_scanout_change(&change);
}
void dpy_gl_scanout_dmabuf(QemuConsole *con,
@@ -1052,8 +1094,9 @@ void dpy_gl_scanout_dmabuf(QemuConsole *con,
{
DisplayState *s = con->ds;
DisplayChangeListener *dcl;
+ struct scanout_change change = SCANOUT_CHANGE_NONE;
- con->scanout.kind = SCANOUT_DMABUF;
+ change = dpy_change_scanout_kind(&con->scanout, SCANOUT_DMABUF);
con->scanout.dmabuf = dmabuf;
QLIST_FOREACH(dcl, &s->listeners, next) {
if (con != dcl->con) {
@@ -1063,6 +1106,7 @@ void dpy_gl_scanout_dmabuf(QemuConsole *con,
dcl->ops->dpy_gl_scanout_dmabuf(dcl, dmabuf);
}
}
+ dpy_complete_scanout_change(&change);
}
void dpy_gl_cursor_dmabuf(QemuConsole *con, QemuDmaBuf *dmabuf,
--
2.41.0
next prev parent reply other threads:[~2025-12-03 4:09 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-12-03 4:07 [PATCH RFC 0/7] virtio-gpu-virgl: introduce Venus support for macOS Joelle van Dyne
2025-12-03 4:07 ` [PATCH RFC 1/7] egl-helpers: store handle to native device Joelle van Dyne
2025-12-04 6:29 ` Akihiko Odaki
2025-12-03 4:07 ` [PATCH RFC 2/7] virtio-gpu-virgl: check page alignment of blob mapping Joelle van Dyne
2025-12-04 2:55 ` Akihiko Odaki
2025-12-04 4:01 ` Joelle van Dyne
2025-12-04 5:31 ` Akihiko Odaki
2025-12-11 4:09 ` Mohamed Mediouni
2025-12-03 4:07 ` [PATCH RFC 3/7] console: rename `d3d_tex2d` to `native` Joelle van Dyne
2025-12-04 6:40 ` Akihiko Odaki
2025-12-04 10:53 ` Marc-André Lureau
2025-12-03 4:07 ` [PATCH RFC 4/7] virtio-gpu-virgl: update virglrenderer defines Joelle van Dyne
2025-12-04 7:13 ` Akihiko Odaki
2025-12-04 10:57 ` Marc-André Lureau
2025-12-03 4:07 ` [PATCH RFC 5/7] virtio-gpu-virgl: support scanout of Metal textures Joelle van Dyne
2025-12-04 3:06 ` Akihiko Odaki
2025-12-03 4:07 ` Joelle van Dyne [this message]
2025-12-04 6:23 ` [PATCH RFC 6/7] console: add cleanup callback for ScanoutTexture Akihiko Odaki
2025-12-03 4:07 ` [PATCH RFC 7/7] virtio-gpu-virgl: add support for native blob scanout Joelle van Dyne
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20251203040754.94487-7-j@getutm.app \
--to=j@getutm.app \
--cc=alex.bennee@linaro.org \
--cc=dmitry.osipenko@collabora.com \
--cc=marcandre.lureau@redhat.com \
--cc=mst@redhat.com \
--cc=odaki@rsg.ci.i.u-tokyo.ac.jp \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).