qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [PATCH RFC 0/7] virtio-gpu-virgl: introduce Venus support for macOS
@ 2025-12-03  4:07 Joelle van Dyne
  2025-12-03  4:07 ` [PATCH RFC 1/7] egl-helpers: store handle to native device Joelle van Dyne
                   ` (6 more replies)
  0 siblings, 7 replies; 19+ messages in thread
From: Joelle van Dyne @ 2025-12-03  4:07 UTC (permalink / raw)
  To: qemu-devel

This brings Vulkan guest paravirtualization to macOS hosts. The bulk of the work
is being submitted to the virglrenderer project so this is a RFC for now.

In addition to Vulkan, we also introduce Metal texture scanout for GLES guests
as well. We also added Metal texture rendering in the Cocoa backend but that
builds upon the GLES work by Akihiko Odaki which is not currently upstream.

Fork with all dependent changes:
  https://github.com/utmapp/qemu/tree/submit/macos-venus
Instructions for building and testing with all related projects:
  https://gist.github.com/osy/a8f705050eed1c8421ad1a0855a8faa9

Joelle van Dyne (7):
  egl-helpers: store handle to native device
  virtio-gpu-virgl: check page alignment of blob mapping
  console: rename `d3d_tex2d` to `native`
  virtio-gpu-virgl: update virglrenderer defines
  virtio-gpu-virgl: support scanout of Metal textures
  console: add cleanup callback for ScanoutTexture
  virtio-gpu-virgl: add support for native blob scanout

 meson.build                   |   9 +++
 include/ui/console.h          |  31 ++++++++-
 include/ui/egl-helpers.h      |   2 +-
 include/ui/gtk.h              |   4 +-
 include/ui/sdl2.h             |   2 +-
 hw/display/virtio-gpu-virgl.c | 126 +++++++++++++++++++++++++++++++---
 hw/display/virtio-gpu.c       |   2 +
 ui/console.c                  |  60 +++++++++++++---
 ui/dbus-console.c             |   2 +-
 ui/dbus-listener.c            |   8 +--
 ui/egl-headless.c             |   2 +-
 ui/egl-helpers.c              |   4 +-
 ui/gtk-egl.c                  |   2 +-
 ui/gtk-gl-area.c              |   2 +-
 ui/sdl2-gl.c                  |   2 +-
 ui/spice-display.c            |   2 +-
 16 files changed, 225 insertions(+), 35 deletions(-)

-- 
2.41.0



^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH RFC 1/7] egl-helpers: store handle to native device
  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 ` 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
                   ` (5 subsequent siblings)
  6 siblings, 1 reply; 19+ messages in thread
From: Joelle van Dyne @ 2025-12-03  4:07 UTC (permalink / raw)
  To: qemu-devel
  Cc: Joelle van Dyne, Michael S. Tsirkin, Alex Bennée,
	Akihiko Odaki, Dmitry Osipenko, Marc-André Lureau

Make way for other platforms by making the variable more general. Also we
will be using the device in the future so let's save the pointer in the
global instead of just a boolean flag.

Signed-off-by: Joelle van Dyne <j@getutm.app>
---
 include/ui/egl-helpers.h      | 2 +-
 hw/display/virtio-gpu-virgl.c | 2 +-
 ui/egl-helpers.c              | 4 ++--
 3 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/include/ui/egl-helpers.h b/include/ui/egl-helpers.h
index acf993fcf5..c239d32317 100644
--- a/include/ui/egl-helpers.h
+++ b/include/ui/egl-helpers.h
@@ -12,7 +12,7 @@
 extern EGLDisplay *qemu_egl_display;
 extern EGLConfig qemu_egl_config;
 extern DisplayGLMode qemu_egl_mode;
-extern bool qemu_egl_angle_d3d;
+extern void *qemu_egl_angle_native_device;
 
 typedef struct egl_fb {
     int width;
diff --git a/hw/display/virtio-gpu-virgl.c b/hw/display/virtio-gpu-virgl.c
index 07f6355ad6..20c856c04e 100644
--- a/hw/display/virtio-gpu-virgl.c
+++ b/hw/display/virtio-gpu-virgl.c
@@ -1152,7 +1152,7 @@ int virtio_gpu_virgl_init(VirtIOGPU *g)
     }
 #endif
 #ifdef VIRGL_RENDERER_D3D11_SHARE_TEXTURE
-    if (qemu_egl_angle_d3d) {
+    if (qemu_egl_angle_native_device) {
         flags |= VIRGL_RENDERER_D3D11_SHARE_TEXTURE;
     }
 #endif
diff --git a/ui/egl-helpers.c b/ui/egl-helpers.c
index e3f2872cc1..57bcf99498 100644
--- a/ui/egl-helpers.c
+++ b/ui/egl-helpers.c
@@ -28,7 +28,7 @@
 EGLDisplay *qemu_egl_display;
 EGLConfig qemu_egl_config;
 DisplayGLMode qemu_egl_mode;
-bool qemu_egl_angle_d3d;
+void *qemu_egl_angle_native_device;
 
 /* ------------------------------------------------------------------ */
 
@@ -651,7 +651,7 @@ int qemu_egl_init_dpy_win32(EGLNativeDisplayType dpy, DisplayGLMode mode)
         }
 
         trace_egl_init_d3d11_device(device);
-        qemu_egl_angle_d3d = device != NULL;
+        qemu_egl_angle_native_device = d3d11_device;
     }
 #endif
 
-- 
2.41.0



^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH RFC 2/7] virtio-gpu-virgl: check page alignment of blob mapping
  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-03  4:07 ` Joelle van Dyne
  2025-12-04  2:55   ` 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
                   ` (4 subsequent siblings)
  6 siblings, 2 replies; 19+ messages in thread
From: Joelle van Dyne @ 2025-12-03  4:07 UTC (permalink / raw)
  To: qemu-devel
  Cc: Joelle van Dyne, Alex Bennée, Akihiko Odaki, Dmitry Osipenko,
	Michael S. Tsirkin

Currently if a mapping is not page aligned, it will sliently fail and the
guest, assuming it is mapped, will attempt to access the memory and fail.
This is particularly an issue on macOS when the host page size is 16KiB and
the guest page size is 4KiB.

Signed-off-by: Joelle van Dyne <j@getutm.app>
---
 hw/display/virtio-gpu-virgl.c | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/hw/display/virtio-gpu-virgl.c b/hw/display/virtio-gpu-virgl.c
index 20c856c04e..adf02ac22b 100644
--- a/hw/display/virtio-gpu-virgl.c
+++ b/hw/display/virtio-gpu-virgl.c
@@ -116,6 +116,20 @@ virtio_gpu_virgl_map_resource_blob(VirtIOGPU *g,
         return ret;
     }
 
+    if (!QEMU_IS_ALIGNED((uintptr_t)data, qemu_real_host_page_size())) {
+        virgl_renderer_resource_unmap(res->base.resource_id);
+        qemu_log_mask(LOG_GUEST_ERROR, "%s: address %p is not aligned to page size\n",
+                      __func__, data);
+        return -ENOMEM;
+    }
+
+    if (!QEMU_IS_ALIGNED(size, qemu_real_host_page_size())) {
+        virgl_renderer_resource_unmap(res->base.resource_id);
+        qemu_log_mask(LOG_GUEST_ERROR, "%s: size 0x%llx is not aligned to page size\n",
+                      __func__, size);
+        return -ENOMEM;
+    }
+
     vmr = g_new0(struct virtio_gpu_virgl_hostmem_region, 1);
     vmr->g = g;
 
-- 
2.41.0



^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH RFC 3/7] console: rename `d3d_tex2d` to `native`
  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-03  4:07 ` [PATCH RFC 2/7] virtio-gpu-virgl: check page alignment of blob mapping Joelle van Dyne
@ 2025-12-03  4:07 ` 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
                   ` (3 subsequent siblings)
  6 siblings, 2 replies; 19+ messages in thread
From: Joelle van Dyne @ 2025-12-03  4:07 UTC (permalink / raw)
  To: qemu-devel
  Cc: Joelle van Dyne, Alex Bennée, Akihiko Odaki, Dmitry Osipenko,
	Michael S. Tsirkin, Marc-André Lureau

In order to support native texture scanout beyond D3D, we make this more
generic allowing for multiple native texture handle types.

Signed-off-by: Joelle van Dyne <j@getutm.app>
---
 include/ui/console.h          | 22 +++++++++++++++++++---
 include/ui/gtk.h              |  4 ++--
 include/ui/sdl2.h             |  2 +-
 hw/display/virtio-gpu-virgl.c | 10 +++++++---
 ui/console.c                  |  8 ++++----
 ui/dbus-console.c             |  2 +-
 ui/dbus-listener.c            |  8 ++++----
 ui/egl-headless.c             |  2 +-
 ui/gtk-egl.c                  |  2 +-
 ui/gtk-gl-area.c              |  2 +-
 ui/sdl2-gl.c                  |  2 +-
 ui/spice-display.c            |  2 +-
 12 files changed, 43 insertions(+), 23 deletions(-)

diff --git a/include/ui/console.h b/include/ui/console.h
index 98feaa58bd..25e45295d4 100644
--- a/include/ui/console.h
+++ b/include/ui/console.h
@@ -131,6 +131,22 @@ struct QemuConsoleClass {
     ObjectClass parent_class;
 };
 
+typedef enum ScanoutTextureNativeType {
+    SCANOUT_TEXTURE_NATIVE_TYPE_NONE,
+    SCANOUT_TEXTURE_NATIVE_TYPE_D3D,
+} ScanoutTextureNativeType;
+
+typedef struct ScanoutTextureNative {
+    ScanoutTextureNativeType type;
+    union {
+        void *d3d_tex2d;
+    } u;
+} ScanoutTextureNative;
+
+#define NO_NATIVE_TEXTURE ((ScanoutTextureNative){ \
+    .type = SCANOUT_TEXTURE_NATIVE_TYPE_NONE \
+})
+
 typedef struct ScanoutTexture {
     uint32_t backing_id;
     bool backing_y_0_top;
@@ -140,7 +156,7 @@ typedef struct ScanoutTexture {
     uint32_t y;
     uint32_t width;
     uint32_t height;
-    void *d3d_tex2d;
+    ScanoutTextureNative native;
 } ScanoutTexture;
 
 typedef struct QemuUIInfo {
@@ -245,7 +261,7 @@ typedef struct DisplayChangeListenerOps {
                                    uint32_t backing_height,
                                    uint32_t x, uint32_t y,
                                    uint32_t w, uint32_t h,
-                                   void *d3d_tex2d);
+                                   ScanoutTextureNative native);
     /* optional (default to true if has dpy_gl_scanout_dmabuf) */
     bool (*dpy_has_dmabuf)(DisplayChangeListener *dcl);
     /* optional */
@@ -329,7 +345,7 @@ 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,
-                            void *d3d_tex2d);
+                            ScanoutTextureNative native);
 void dpy_gl_scanout_dmabuf(QemuConsole *con,
                            QemuDmaBuf *dmabuf);
 void dpy_gl_cursor_dmabuf(QemuConsole *con, QemuDmaBuf *dmabuf,
diff --git a/include/ui/gtk.h b/include/ui/gtk.h
index 3e6ce3cb48..f88e2b281d 100644
--- a/include/ui/gtk.h
+++ b/include/ui/gtk.h
@@ -178,7 +178,7 @@ void gd_egl_scanout_texture(DisplayChangeListener *dcl,
                             uint32_t backing_height,
                             uint32_t x, uint32_t y,
                             uint32_t w, uint32_t h,
-                            void *d3d_tex2d);
+                            ScanoutTextureNative native);
 void gd_egl_scanout_dmabuf(DisplayChangeListener *dcl,
                            QemuDmaBuf *dmabuf);
 void gd_egl_cursor_dmabuf(DisplayChangeListener *dcl,
@@ -215,7 +215,7 @@ void gd_gl_area_scanout_texture(DisplayChangeListener *dcl,
                                 uint32_t backing_height,
                                 uint32_t x, uint32_t y,
                                 uint32_t w, uint32_t h,
-                                void *d3d_tex2d);
+                                ScanoutTextureNative native);
 void gd_gl_area_scanout_disable(DisplayChangeListener *dcl);
 void gd_gl_area_scanout_flush(DisplayChangeListener *dcl,
                               uint32_t x, uint32_t y, uint32_t w, uint32_t h);
diff --git a/include/ui/sdl2.h b/include/ui/sdl2.h
index dbe6e3d973..fdefb88229 100644
--- a/include/ui/sdl2.h
+++ b/include/ui/sdl2.h
@@ -93,7 +93,7 @@ void sdl2_gl_scanout_texture(DisplayChangeListener *dcl,
                              uint32_t backing_height,
                              uint32_t x, uint32_t y,
                              uint32_t w, uint32_t h,
-                             void *d3d_tex2d);
+                             ScanoutTextureNative native);
 void sdl2_gl_scanout_flush(DisplayChangeListener *dcl,
                            uint32_t x, uint32_t y, uint32_t w, uint32_t h);
 
diff --git a/hw/display/virtio-gpu-virgl.c b/hw/display/virtio-gpu-virgl.c
index adf02ac22b..d0e6ad4b17 100644
--- a/hw/display/virtio-gpu-virgl.c
+++ b/hw/display/virtio-gpu-virgl.c
@@ -434,14 +434,18 @@ static void virgl_cmd_set_scanout(VirtIOGPU *g,
 
     if (ss.resource_id && ss.r.width && ss.r.height) {
         struct virgl_renderer_resource_info info;
-        void *d3d_tex2d = NULL;
+        ScanoutTextureNative native = { .type = SCANOUT_TEXTURE_NATIVE_TYPE_NONE };
 
 #if VIRGL_VERSION_MAJOR >= 1
         struct virgl_renderer_resource_info_ext ext;
         memset(&ext, 0, sizeof(ext));
         ret = virgl_renderer_resource_get_info_ext(ss.resource_id, &ext);
         info = ext.base;
-        d3d_tex2d = ext.d3d_tex2d;
+        native = (ScanoutTextureNative){
+            .type = ext.d3d_tex2d ? SCANOUT_TEXTURE_NATIVE_TYPE_D3D :
+                                    SCANOUT_TEXTURE_NATIVE_TYPE_NONE,
+            .u.d3d_tex2d = ext.d3d_tex2d,
+        };
 #else
         memset(&info, 0, sizeof(info));
         ret = virgl_renderer_resource_get_info(ss.resource_id, &info);
@@ -461,7 +465,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,
-            d3d_tex2d);
+            native);
     } 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 2d00828c53..9378afd53d 100644
--- a/ui/console.c
+++ b/ui/console.c
@@ -295,7 +295,7 @@ static void displaychangelistener_display_console(DisplayChangeListener *dcl,
                                          con->scanout.texture.y,
                                          con->scanout.texture.width,
                                          con->scanout.texture.height,
-                                         con->scanout.texture.d3d_tex2d);
+                                         con->scanout.texture.native);
     }
 }
 
@@ -1023,7 +1023,7 @@ void dpy_gl_scanout_texture(QemuConsole *con,
                             uint32_t backing_height,
                             uint32_t x, uint32_t y,
                             uint32_t width, uint32_t height,
-                            void *d3d_tex2d)
+                            ScanoutTextureNative native)
 {
     DisplayState *s = con->ds;
     DisplayChangeListener *dcl;
@@ -1031,7 +1031,7 @@ void dpy_gl_scanout_texture(QemuConsole *con,
     con->scanout.kind = SCANOUT_TEXTURE;
     con->scanout.texture = (ScanoutTexture) {
         backing_id, backing_y_0_top, backing_width, backing_height,
-        x, y, width, height, d3d_tex2d,
+        x, y, width, height, native,
     };
     QLIST_FOREACH(dcl, &s->listeners, next) {
         if (con != dcl->con) {
@@ -1042,7 +1042,7 @@ void dpy_gl_scanout_texture(QemuConsole *con,
                                              backing_y_0_top,
                                              backing_width, backing_height,
                                              x, y, width, height,
-                                             d3d_tex2d);
+                                             native);
         }
     }
 }
diff --git a/ui/dbus-console.c b/ui/dbus-console.c
index 85e215ef23..651f0daeaf 100644
--- a/ui/dbus-console.c
+++ b/ui/dbus-console.c
@@ -99,7 +99,7 @@ dbus_gl_scanout_texture(DisplayChangeListener *dcl,
                         uint32_t backing_height,
                         uint32_t x, uint32_t y,
                         uint32_t w, uint32_t h,
-                        void *d3d_tex2d)
+                        ScanoutTextureNative native)
 {
     DBusDisplayConsole *ddc = container_of(dcl, DBusDisplayConsole, dcl);
 
diff --git a/ui/dbus-listener.c b/ui/dbus-listener.c
index 52e041edb0..a737752996 100644
--- a/ui/dbus-listener.c
+++ b/ui/dbus-listener.c
@@ -587,7 +587,7 @@ static void dbus_scanout_texture(DisplayChangeListener *dcl,
                                  uint32_t backing_height,
                                  uint32_t x, uint32_t y,
                                  uint32_t w, uint32_t h,
-                                 void *d3d_tex2d)
+                                 ScanoutTextureNative native)
 {
     trace_dbus_scanout_texture(tex_id, backing_y_0_top,
                                backing_width, backing_height, x, y, w, h);
@@ -618,8 +618,8 @@ static void dbus_scanout_texture(DisplayChangeListener *dcl,
     assert(surface_width(ddl->ds) == w);
     assert(surface_height(ddl->ds) == h);
 
-    if (d3d_tex2d) {
-        dbus_scanout_share_d3d_texture(ddl, d3d_tex2d, backing_y_0_top,
+    if (native.type == SCANOUT_TEXTURE_NATIVE_TYPE_D3d) {
+        dbus_scanout_share_d3d_texture(ddl, native.u.d3d_tex2d, backing_y_0_top,
                                        backing_width, backing_height, x, y, w, h);
     } else {
         dbus_scanout_map(ddl);
@@ -868,7 +868,7 @@ static void dbus_gl_gfx_switch(DisplayChangeListener *dcl,
 
         /* TODO: lazy send dmabuf (there are unnecessary sent otherwise) */
         dbus_scanout_texture(&ddl->dcl, ddl->ds->texture, false,
-                             width, height, 0, 0, width, height, NULL);
+                             width, height, 0, 0, width, height, NO_NATIVE_TEXTURE);
     }
 }
 #endif
diff --git a/ui/egl-headless.c b/ui/egl-headless.c
index 1f6b845500..e36778bd48 100644
--- a/ui/egl-headless.c
+++ b/ui/egl-headless.c
@@ -62,7 +62,7 @@ static void egl_scanout_texture(DisplayChangeListener *dcl,
                                 uint32_t backing_height,
                                 uint32_t x, uint32_t y,
                                 uint32_t w, uint32_t h,
-                                void *d3d_tex2d)
+                                ScanoutTextureNative native)
 {
     egl_dpy *edpy = container_of(dcl, egl_dpy, dcl);
 
diff --git a/ui/gtk-egl.c b/ui/gtk-egl.c
index ae9239999c..7933237d45 100644
--- a/ui/gtk-egl.c
+++ b/ui/gtk-egl.c
@@ -239,7 +239,7 @@ void gd_egl_scanout_texture(DisplayChangeListener *dcl,
                             uint32_t backing_width, uint32_t backing_height,
                             uint32_t x, uint32_t y,
                             uint32_t w, uint32_t h,
-                            void *d3d_tex2d)
+                            ScanoutTextureNative native)
 {
     VirtualConsole *vc = container_of(dcl, VirtualConsole, gfx.dcl);
 
diff --git a/ui/gtk-gl-area.c b/ui/gtk-gl-area.c
index cd86022d26..f2ed543d6a 100644
--- a/ui/gtk-gl-area.c
+++ b/ui/gtk-gl-area.c
@@ -306,7 +306,7 @@ void gd_gl_area_scanout_texture(DisplayChangeListener *dcl,
                                 uint32_t backing_height,
                                 uint32_t x, uint32_t y,
                                 uint32_t w, uint32_t h,
-                                void *d3d_tex2d)
+                                ScanoutTextureNative native)
 {
     VirtualConsole *vc = container_of(dcl, VirtualConsole, gfx.dcl);
 
diff --git a/ui/sdl2-gl.c b/ui/sdl2-gl.c
index 3be17d1079..b15db86f24 100644
--- a/ui/sdl2-gl.c
+++ b/ui/sdl2-gl.c
@@ -206,7 +206,7 @@ void sdl2_gl_scanout_texture(DisplayChangeListener *dcl,
                              uint32_t backing_height,
                              uint32_t x, uint32_t y,
                              uint32_t w, uint32_t h,
-                             void *d3d_tex2d)
+                             ScanoutTextureNative native)
 {
     struct sdl2_console *scon = container_of(dcl, struct sdl2_console, dcl);
 
diff --git a/ui/spice-display.c b/ui/spice-display.c
index db71e866f8..2a2285cb1f 100644
--- a/ui/spice-display.c
+++ b/ui/spice-display.c
@@ -1084,7 +1084,7 @@ static void qemu_spice_gl_scanout_texture(DisplayChangeListener *dcl,
                                           uint32_t backing_height,
                                           uint32_t x, uint32_t y,
                                           uint32_t w, uint32_t h,
-                                          void *d3d_tex2d)
+                                          ScanoutTextureNative native)
 {
     SimpleSpiceDisplay *ssd = container_of(dcl, SimpleSpiceDisplay, dcl);
     EGLint offset[DMABUF_MAX_PLANES], stride[DMABUF_MAX_PLANES], fourcc = 0;
-- 
2.41.0



^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH RFC 4/7] virtio-gpu-virgl: update virglrenderer defines
  2025-12-03  4:07 [PATCH RFC 0/7] virtio-gpu-virgl: introduce Venus support for macOS Joelle van Dyne
                   ` (2 preceding siblings ...)
  2025-12-03  4:07 ` [PATCH RFC 3/7] console: rename `d3d_tex2d` to `native` Joelle van Dyne
@ 2025-12-03  4:07 ` 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
                   ` (2 subsequent siblings)
  6 siblings, 2 replies; 19+ messages in thread
From: Joelle van Dyne @ 2025-12-03  4:07 UTC (permalink / raw)
  To: qemu-devel
  Cc: Joelle van Dyne, Michael S. Tsirkin, Alex Bennée,
	Akihiko Odaki, Dmitry Osipenko

In order to support additional native texture types, we need to update the
defines in virglrenderer. The changes are backwards compatible and so
builds should work with either the new version or the old version.

Signed-off-by: Joelle van Dyne <j@getutm.app>
---
 hw/display/virtio-gpu-virgl.c | 28 +++++++++++++++++++++++++---
 1 file changed, 25 insertions(+), 3 deletions(-)

diff --git a/hw/display/virtio-gpu-virgl.c b/hw/display/virtio-gpu-virgl.c
index d0e6ad4b17..36c670f988 100644
--- a/hw/display/virtio-gpu-virgl.c
+++ b/hw/display/virtio-gpu-virgl.c
@@ -24,6 +24,8 @@
 
 #include <virglrenderer.h>
 
+#define SUPPORTED_VIRGL_INFO_EXT_VERSION (1)
+
 struct virtio_gpu_virgl_resource {
     struct virtio_gpu_simple_resource base;
     MemoryRegion *mr;
@@ -441,12 +443,30 @@ static void virgl_cmd_set_scanout(VirtIOGPU *g,
         memset(&ext, 0, sizeof(ext));
         ret = virgl_renderer_resource_get_info_ext(ss.resource_id, &ext);
         info = ext.base;
+        /* fallback to older version */
         native = (ScanoutTextureNative){
             .type = ext.d3d_tex2d ? SCANOUT_TEXTURE_NATIVE_TYPE_D3D :
                                     SCANOUT_TEXTURE_NATIVE_TYPE_NONE,
             .u.d3d_tex2d = ext.d3d_tex2d,
         };
-#else
+#if VIRGL_RENDERER_RESOURCE_INFO_EXT_VERSION >= SUPPORTED_VIRGL_INFO_EXT_VERSION
+        if (ext.version >= VIRGL_RENDERER_RESOURCE_INFO_EXT_VERSION) {
+            switch (ext.native_type) {
+            case VIRGL_NATIVE_HANDLE_NONE:
+            case VIRGL_NATIVE_HANDLE_D3D_TEX2D: {
+                /* already handled above */
+                break;
+            }
+            default: {
+                qemu_log_mask(LOG_GUEST_ERROR,
+                            "%s: unsupported native texture type %d\n",
+                            __func__, ext.native_type);
+                break;
+            }
+            }
+        }
+#endif
+#else /* VIRGL_VERSION_MAJOR < 1 */
         memset(&info, 0, sizeof(info));
         ret = virgl_renderer_resource_get_info(ss.resource_id, &info);
 #endif
@@ -1169,11 +1189,13 @@ int virtio_gpu_virgl_init(VirtIOGPU *g)
         virtio_gpu_3d_cbs.get_egl_display = virgl_get_egl_display;
     }
 #endif
-#ifdef VIRGL_RENDERER_D3D11_SHARE_TEXTURE
     if (qemu_egl_angle_native_device) {
+#if defined(VIRGL_RENDERER_NATIVE_SHARE_TEXTURE)
+        flags |= VIRGL_RENDERER_NATIVE_SHARE_TEXTURE;
+#elif defined(VIRGL_RENDERER_D3D11_SHARE_TEXTURE) && defined(WIN32)
         flags |= VIRGL_RENDERER_D3D11_SHARE_TEXTURE;
-    }
 #endif
+    }
 #if VIRGL_VERSION_MAJOR >= 1
     if (virtio_gpu_venus_enabled(g->parent_obj.conf)) {
         flags |= VIRGL_RENDERER_VENUS | VIRGL_RENDERER_RENDER_SERVER;
-- 
2.41.0



^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH RFC 5/7] virtio-gpu-virgl: support scanout of Metal textures
  2025-12-03  4:07 [PATCH RFC 0/7] virtio-gpu-virgl: introduce Venus support for macOS Joelle van Dyne
                   ` (3 preceding siblings ...)
  2025-12-03  4:07 ` [PATCH RFC 4/7] virtio-gpu-virgl: update virglrenderer defines Joelle van Dyne
@ 2025-12-03  4:07 ` Joelle van Dyne
  2025-12-04  3:06   ` Akihiko Odaki
  2025-12-03  4:07 ` [PATCH RFC 6/7] console: add cleanup callback for ScanoutTexture Joelle van Dyne
  2025-12-03  4:07 ` [PATCH RFC 7/7] virtio-gpu-virgl: add support for native blob scanout Joelle van Dyne
  6 siblings, 1 reply; 19+ messages in thread
From: Joelle van Dyne @ 2025-12-03  4:07 UTC (permalink / raw)
  To: qemu-devel
  Cc: Joelle van Dyne, Michael S. Tsirkin, Alex Bennée,
	Akihiko Odaki, Dmitry Osipenko, Marc-André Lureau,
	Paolo Bonzini, Daniel P. Berrangé,
	Philippe Mathieu-Daudé

When supported, virglrenderer will return a MTLTexture handle that can be
directly used for scanout.

Signed-off-by: Joelle van Dyne <j@getutm.app>
---
 meson.build                   |  4 ++++
 include/ui/console.h          |  2 ++
 hw/display/virtio-gpu-virgl.c | 12 +++++++++++-
 hw/display/virtio-gpu.c       |  2 ++
 4 files changed, 19 insertions(+), 1 deletion(-)

diff --git a/meson.build b/meson.build
index d9293294d8..05bad66376 100644
--- a/meson.build
+++ b/meson.build
@@ -832,6 +832,7 @@ version_res = []
 coref = []
 iokit = []
 pvg = not_found
+metal = not_found
 emulator_link_args = []
 midl = not_found
 widl = not_found
@@ -859,6 +860,7 @@ elif host_os == 'darwin'
   host_dsosuf = '.dylib'
   pvg = dependency('appleframeworks', modules: ['ParavirtualizedGraphics', 'Metal'],
                    required: get_option('pvg'))
+  metal = dependency('appleframeworks', modules: 'Metal', required: false)
 elif host_os == 'sunos'
   socket = [cc.find_library('socket'),
             cc.find_library('nsl'),
@@ -2591,6 +2593,7 @@ if xen.found()
     ('0' + xen_version[2]).substring(-2)
   config_host_data.set('CONFIG_XEN_CTRL_INTERFACE_VERSION', xen_ctrl_version)
 endif
+config_host_data.set('CONFIG_METAL', metal.found())
 config_host_data.set('QEMU_VERSION', '"@0@"'.format(meson.project_version()))
 config_host_data.set('QEMU_VERSION_MAJOR', meson.project_version().split('.')[0])
 config_host_data.set('QEMU_VERSION_MINOR', meson.project_version().split('.')[1])
@@ -4874,6 +4877,7 @@ summary(summary_info, bool_yn: true, section: 'Crypto')
 summary_info = {}
 if host_os == 'darwin'
   summary_info += {'Cocoa support':           cocoa}
+  summary_info += {'Metal support':           metal}
 endif
 summary_info += {'D-Bus display':     dbus_display}
 summary_info += {'SDL support':       sdl}
diff --git a/include/ui/console.h b/include/ui/console.h
index 25e45295d4..a45b524c57 100644
--- a/include/ui/console.h
+++ b/include/ui/console.h
@@ -134,12 +134,14 @@ struct QemuConsoleClass {
 typedef enum ScanoutTextureNativeType {
     SCANOUT_TEXTURE_NATIVE_TYPE_NONE,
     SCANOUT_TEXTURE_NATIVE_TYPE_D3D,
+    SCANOUT_TEXTURE_NATIVE_TYPE_METAL,
 } ScanoutTextureNativeType;
 
 typedef struct ScanoutTextureNative {
     ScanoutTextureNativeType type;
     union {
         void *d3d_tex2d;
+        void *metal_texture;
     } u;
 } ScanoutTextureNative;
 
diff --git a/hw/display/virtio-gpu-virgl.c b/hw/display/virtio-gpu-virgl.c
index 36c670f988..e091eb0c76 100644
--- a/hw/display/virtio-gpu-virgl.c
+++ b/hw/display/virtio-gpu-virgl.c
@@ -452,6 +452,13 @@ static void virgl_cmd_set_scanout(VirtIOGPU *g,
 #if VIRGL_RENDERER_RESOURCE_INFO_EXT_VERSION >= SUPPORTED_VIRGL_INFO_EXT_VERSION
         if (ext.version >= VIRGL_RENDERER_RESOURCE_INFO_EXT_VERSION) {
             switch (ext.native_type) {
+#ifdef CONFIG_METAL
+            case VIRGL_NATIVE_HANDLE_METAL_TEXTURE: {
+                native.type = SCANOUT_TEXTURE_NATIVE_TYPE_METAL;
+                native.u.metal_texture = ext.native_handle;
+                break;
+            }
+#endif
             case VIRGL_NATIVE_HANDLE_NONE:
             case VIRGL_NATIVE_HANDLE_D3D_TEX2D: {
                 /* already handled above */
@@ -1198,7 +1205,10 @@ int virtio_gpu_virgl_init(VirtIOGPU *g)
     }
 #if VIRGL_VERSION_MAJOR >= 1
     if (virtio_gpu_venus_enabled(g->parent_obj.conf)) {
-        flags |= VIRGL_RENDERER_VENUS | VIRGL_RENDERER_RENDER_SERVER;
+        flags |= VIRGL_RENDERER_VENUS;
+#ifndef CONFIG_METAL /* Metal does not support render server */
+        flags |= VIRGL_RENDERER_RENDER_SERVER;
+#endif
     }
 #endif
 
diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
index 43e88a4daf..9cf2c15a43 100644
--- a/hw/display/virtio-gpu.c
+++ b/hw/display/virtio-gpu.c
@@ -1485,12 +1485,14 @@ void virtio_gpu_device_realize(DeviceState *qdev, Error **errp)
     VirtIOGPU *g = VIRTIO_GPU(qdev);
 
     if (virtio_gpu_blob_enabled(g->parent_obj.conf)) {
+#ifndef CONFIG_METAL
         if (!virtio_gpu_rutabaga_enabled(g->parent_obj.conf) &&
             !virtio_gpu_virgl_enabled(g->parent_obj.conf) &&
             !virtio_gpu_have_udmabuf()) {
             error_setg(errp, "need rutabaga or udmabuf for blob resources");
             return;
         }
+#endif
 
 #ifdef VIRGL_VERSION_MAJOR
     #if VIRGL_VERSION_MAJOR < 1
-- 
2.41.0



^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH RFC 6/7] console: add cleanup callback for ScanoutTexture
  2025-12-03  4:07 [PATCH RFC 0/7] virtio-gpu-virgl: introduce Venus support for macOS Joelle van Dyne
                   ` (4 preceding siblings ...)
  2025-12-03  4:07 ` [PATCH RFC 5/7] virtio-gpu-virgl: support scanout of Metal textures Joelle van Dyne
@ 2025-12-03  4:07 ` Joelle van Dyne
  2025-12-04  6:23   ` Akihiko Odaki
  2025-12-03  4:07 ` [PATCH RFC 7/7] virtio-gpu-virgl: add support for native blob scanout Joelle van Dyne
  6 siblings, 1 reply; 19+ messages in thread
From: Joelle van Dyne @ 2025-12-03  4:07 UTC (permalink / raw)
  To: qemu-devel
  Cc: Joelle van Dyne, Michael S. Tsirkin, Alex Bennée,
	Akihiko Odaki, Dmitry Osipenko, Marc-André Lureau

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



^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH RFC 7/7] virtio-gpu-virgl: add support for native blob scanout
  2025-12-03  4:07 [PATCH RFC 0/7] virtio-gpu-virgl: introduce Venus support for macOS Joelle van Dyne
                   ` (5 preceding siblings ...)
  2025-12-03  4:07 ` [PATCH RFC 6/7] console: add cleanup callback for ScanoutTexture Joelle van Dyne
@ 2025-12-03  4:07 ` Joelle van Dyne
  6 siblings, 0 replies; 19+ messages in thread
From: Joelle van Dyne @ 2025-12-03  4:07 UTC (permalink / raw)
  To: qemu-devel
  Cc: Joelle van Dyne, Michael S. Tsirkin, Alex Bennée,
	Akihiko Odaki, Dmitry Osipenko, Paolo Bonzini,
	Marc-André Lureau, Daniel P. Berrangé,
	Philippe Mathieu-Daudé

On macOS we do not have dmabuf and so we use MTLTexture as our scanout
source. For blob scanout, the buffer is untyped and so we cannot get a
MTLTexture until we pass more information to virglrenderer (surface size,
pixel format, etc). The new API to do this is currently unstable so we
need to define `VIRGL_RENDERER_UNSTABLE_APIS`. This should be removed after
the ABI becomes stable.

Signed-off-by: Joelle van Dyne <j@getutm.app>
---
 meson.build                   |  5 +++
 hw/display/virtio-gpu-virgl.c | 60 +++++++++++++++++++++++++++++++++++
 2 files changed, 65 insertions(+)

diff --git a/meson.build b/meson.build
index 05bad66376..8917aff044 100644
--- a/meson.build
+++ b/meson.build
@@ -2549,6 +2549,11 @@ config_host_data.set('CONFIG_VNC', vnc.found())
 config_host_data.set('CONFIG_VNC_JPEG', jpeg.found())
 config_host_data.set('CONFIG_VNC_SASL', sasl.found())
 if virgl.found()
+  config_host_data.set('HAVE_VIRGL_RENDERER_NATIVE_SCANOUT',
+                        cc.has_function('virgl_renderer_create_handle_for_scanout',
+                                        args: '-DVIRGL_RENDERER_UNSTABLE_APIS',
+                                        prefix: '#include <virglrenderer.h>',
+                                        dependencies: virgl))
   config_host_data.set('VIRGL_VERSION_MAJOR', virgl.version().split('.')[0])
 endif
 config_host_data.set('CONFIG_VIRTFS', have_virtfs)
diff --git a/hw/display/virtio-gpu-virgl.c b/hw/display/virtio-gpu-virgl.c
index b7bc095676..3ef37645ca 100644
--- a/hw/display/virtio-gpu-virgl.c
+++ b/hw/display/virtio-gpu-virgl.c
@@ -22,6 +22,7 @@
 
 #include "ui/egl-helpers.h"
 
+#define VIRGL_RENDERER_UNSTABLE_APIS
 #include <virglrenderer.h>
 
 #define SUPPORTED_VIRGL_INFO_EXT_VERSION (1)
@@ -848,6 +849,59 @@ static void virgl_cmd_resource_unmap_blob(VirtIOGPU *g,
     }
 }
 
+#if defined(HAVE_VIRGL_RENDERER_NATIVE_SCANOUT)
+static void virgl_scanout_native_blob_cleanup(ScanoutTextureNative *native)
+{
+    assert(native->type == SCANOUT_TEXTURE_NATIVE_TYPE_METAL);
+    virgl_renderer_release_handle_for_scanout(VIRGL_NATIVE_HANDLE_METAL_TEXTURE,
+                                              native->u.metal_texture);
+}
+
+static bool virgl_scanout_native_blob(VirtIOGPU *g,
+                                      struct virtio_gpu_set_scanout_blob *ss)
+{
+    struct virtio_gpu_scanout *scanout = &g->parent_obj.scanout[ss->scanout_id];
+    enum virgl_renderer_native_handle_type type;
+    virgl_renderer_native_handle handle;
+    ScanoutTextureNative native;
+
+    type = virgl_renderer_create_handle_for_scanout(ss->resource_id,
+                                                    ss->width,
+                                                    ss->height,
+                                                    ss->format,
+                                                    ss->padding,
+                                                    ss->strides[0],
+                                                    ss->offsets[0],
+                                                    &handle);
+#ifdef CONFIG_METAL
+    if (type == VIRGL_NATIVE_HANDLE_METAL_TEXTURE) {
+        native = (ScanoutTextureNative){
+            .type = SCANOUT_TEXTURE_NATIVE_TYPE_METAL,
+            .u.metal_texture = handle,
+        };
+        qemu_console_resize(scanout->con,
+                            ss->r.width, ss->r.height);
+        dpy_gl_scanout_texture(
+            scanout->con, 0,
+            false,
+            ss->width, ss->height,
+            ss->r.x, ss->r.y, ss->r.width, ss->r.height,
+            native, virgl_scanout_native_blob_cleanup);
+        scanout->resource_id = ss->resource_id;
+
+        return true;
+    }
+#endif
+
+    /* don't leak memory if handle type is unknown */
+    if (type != VIRGL_NATIVE_HANDLE_NONE) {
+        virgl_renderer_release_handle_for_scanout(type, handle);
+    }
+
+    return false;
+}
+#endif
+
 static void virgl_cmd_set_scanout_blob(VirtIOGPU *g,
                                        struct virtio_gpu_ctrl_command *cmd)
 {
@@ -886,6 +940,12 @@ static void virgl_cmd_set_scanout_blob(VirtIOGPU *g,
         return;
     }
 
+#if defined(HAVE_VIRGL_RENDERER_NATIVE_SCANOUT)
+    if (virgl_scanout_native_blob(g, &ss)) {
+        return;
+    }
+#endif
+
     res = virtio_gpu_virgl_find_resource(g, ss.resource_id);
     if (!res) {
         qemu_log_mask(LOG_GUEST_ERROR, "%s: resource does not exist %d\n",
-- 
2.41.0



^ permalink raw reply related	[flat|nested] 19+ messages in thread

* Re: [PATCH RFC 2/7] virtio-gpu-virgl: check page alignment of blob mapping
  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-11  4:09   ` Mohamed Mediouni
  1 sibling, 1 reply; 19+ messages in thread
From: Akihiko Odaki @ 2025-12-04  2:55 UTC (permalink / raw)
  To: Joelle van Dyne, qemu-devel
  Cc: Alex Bennée, Dmitry Osipenko, Michael S. Tsirkin

On 2025/12/03 13:07, Joelle van Dyne wrote:
> Currently if a mapping is not page aligned, it will sliently fail and the
> guest, assuming it is mapped, will attempt to access the memory and fail.
> This is particularly an issue on macOS when the host page size is 16KiB and
> the guest page size is 4KiB.

It should work. If I understand correctly, tcg doesn't care the host 
page size. hvf will not call hv_vm_map() for misaligned regions and that 
causes Data Abort, but it is handled by QEMU to perform memory access. I 
think it needs more debugging.

Regards,
Akihiko Odaki

> 
> Signed-off-by: Joelle van Dyne <j@getutm.app>
> ---
>   hw/display/virtio-gpu-virgl.c | 14 ++++++++++++++
>   1 file changed, 14 insertions(+)
> 
> diff --git a/hw/display/virtio-gpu-virgl.c b/hw/display/virtio-gpu-virgl.c
> index 20c856c04e..adf02ac22b 100644
> --- a/hw/display/virtio-gpu-virgl.c
> +++ b/hw/display/virtio-gpu-virgl.c
> @@ -116,6 +116,20 @@ virtio_gpu_virgl_map_resource_blob(VirtIOGPU *g,
>           return ret;
>       }
>   
> +    if (!QEMU_IS_ALIGNED((uintptr_t)data, qemu_real_host_page_size())) {
> +        virgl_renderer_resource_unmap(res->base.resource_id);
> +        qemu_log_mask(LOG_GUEST_ERROR, "%s: address %p is not aligned to page size\n",
> +                      __func__, data);
> +        return -ENOMEM;
> +    }
> +
> +    if (!QEMU_IS_ALIGNED(size, qemu_real_host_page_size())) {
> +        virgl_renderer_resource_unmap(res->base.resource_id);
> +        qemu_log_mask(LOG_GUEST_ERROR, "%s: size 0x%llx is not aligned to page size\n",
> +                      __func__, size);
> +        return -ENOMEM;
> +    }
> +
>       vmr = g_new0(struct virtio_gpu_virgl_hostmem_region, 1);
>       vmr->g = g;
>   



^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH RFC 5/7] virtio-gpu-virgl: support scanout of Metal textures
  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
  0 siblings, 0 replies; 19+ messages in thread
From: Akihiko Odaki @ 2025-12-04  3:06 UTC (permalink / raw)
  To: Joelle van Dyne, qemu-devel
  Cc: Michael S. Tsirkin, Alex Bennée, Dmitry Osipenko,
	Marc-André Lureau, Paolo Bonzini, Daniel P. Berrangé,
	Philippe Mathieu-Daudé

On 2025/12/03 13:07, Joelle van Dyne wrote:
> When supported, virglrenderer will return a MTLTexture handle that can be
> directly used for scanout.
> 
> Signed-off-by: Joelle van Dyne <j@getutm.app>
> ---
>   meson.build                   |  4 ++++
>   include/ui/console.h          |  2 ++
>   hw/display/virtio-gpu-virgl.c | 12 +++++++++++-
>   hw/display/virtio-gpu.c       |  2 ++
>   4 files changed, 19 insertions(+), 1 deletion(-)
> 
> diff --git a/meson.build b/meson.build
> index d9293294d8..05bad66376 100644
> --- a/meson.build
> +++ b/meson.build
> @@ -832,6 +832,7 @@ version_res = []
>   coref = []
>   iokit = []
>   pvg = not_found
> +metal = not_found
>   emulator_link_args = []
>   midl = not_found
>   widl = not_found
> @@ -859,6 +860,7 @@ elif host_os == 'darwin'
>     host_dsosuf = '.dylib'
>     pvg = dependency('appleframeworks', modules: ['ParavirtualizedGraphics', 'Metal'],
>                      required: get_option('pvg'))
> +  metal = dependency('appleframeworks', modules: 'Metal', required: false)
>   elif host_os == 'sunos'
>     socket = [cc.find_library('socket'),
>               cc.find_library('nsl'),
> @@ -2591,6 +2593,7 @@ if xen.found()
>       ('0' + xen_version[2]).substring(-2)
>     config_host_data.set('CONFIG_XEN_CTRL_INTERFACE_VERSION', xen_ctrl_version)
>   endif
> +config_host_data.set('CONFIG_METAL', metal.found())
>   config_host_data.set('QEMU_VERSION', '"@0@"'.format(meson.project_version()))
>   config_host_data.set('QEMU_VERSION_MAJOR', meson.project_version().split('.')[0])
>   config_host_data.set('QEMU_VERSION_MINOR', meson.project_version().split('.')[1])
> @@ -4874,6 +4877,7 @@ summary(summary_info, bool_yn: true, section: 'Crypto')
>   summary_info = {}
>   if host_os == 'darwin'
>     summary_info += {'Cocoa support':           cocoa}
> +  summary_info += {'Metal support':           metal}
>   endif
>   summary_info += {'D-Bus display':     dbus_display}
>   summary_info += {'SDL support':       sdl}
> diff --git a/include/ui/console.h b/include/ui/console.h
> index 25e45295d4..a45b524c57 100644
> --- a/include/ui/console.h
> +++ b/include/ui/console.h
> @@ -134,12 +134,14 @@ struct QemuConsoleClass {
>   typedef enum ScanoutTextureNativeType {
>       SCANOUT_TEXTURE_NATIVE_TYPE_NONE,
>       SCANOUT_TEXTURE_NATIVE_TYPE_D3D,
> +    SCANOUT_TEXTURE_NATIVE_TYPE_METAL,
>   } ScanoutTextureNativeType;
>   
>   typedef struct ScanoutTextureNative {
>       ScanoutTextureNativeType type;
>       union {
>           void *d3d_tex2d;
> +        void *metal_texture;
>       } u;
>   } ScanoutTextureNative;
>   
> diff --git a/hw/display/virtio-gpu-virgl.c b/hw/display/virtio-gpu-virgl.c
> index 36c670f988..e091eb0c76 100644
> --- a/hw/display/virtio-gpu-virgl.c
> +++ b/hw/display/virtio-gpu-virgl.c
> @@ -452,6 +452,13 @@ static void virgl_cmd_set_scanout(VirtIOGPU *g,
>   #if VIRGL_RENDERER_RESOURCE_INFO_EXT_VERSION >= SUPPORTED_VIRGL_INFO_EXT_VERSION
>           if (ext.version >= VIRGL_RENDERER_RESOURCE_INFO_EXT_VERSION) {
>               switch (ext.native_type) {
> +#ifdef CONFIG_METAL
> +            case VIRGL_NATIVE_HANDLE_METAL_TEXTURE: {
> +                native.type = SCANOUT_TEXTURE_NATIVE_TYPE_METAL;
> +                native.u.metal_texture = ext.native_handle;
> +                break;
> +            }
> +#endif
>               case VIRGL_NATIVE_HANDLE_NONE:
>               case VIRGL_NATIVE_HANDLE_D3D_TEX2D: {
>                   /* already handled above */
> @@ -1198,7 +1205,10 @@ int virtio_gpu_virgl_init(VirtIOGPU *g)
>       }
>   #if VIRGL_VERSION_MAJOR >= 1
>       if (virtio_gpu_venus_enabled(g->parent_obj.conf)) {
> -        flags |= VIRGL_RENDERER_VENUS | VIRGL_RENDERER_RENDER_SERVER;
> +        flags |= VIRGL_RENDERER_VENUS;
> +#ifndef CONFIG_METAL /* Metal does not support render server */
> +        flags |= VIRGL_RENDERER_RENDER_SERVER;
> +#endif
>       }
>   #endif
>   
> diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
> index 43e88a4daf..9cf2c15a43 100644
> --- a/hw/display/virtio-gpu.c
> +++ b/hw/display/virtio-gpu.c
> @@ -1485,12 +1485,14 @@ void virtio_gpu_device_realize(DeviceState *qdev, Error **errp)
>       VirtIOGPU *g = VIRTIO_GPU(qdev);
>   
>       if (virtio_gpu_blob_enabled(g->parent_obj.conf)) {
> +#ifndef CONFIG_METAL
>           if (!virtio_gpu_rutabaga_enabled(g->parent_obj.conf) &&
>               !virtio_gpu_virgl_enabled(g->parent_obj.conf) &&
>               !virtio_gpu_have_udmabuf()) {
>               error_setg(errp, "need rutabaga or udmabuf for blob resources");
>               return;
>           }
> +#endif

This check should be kept enabled. Blob resources cannot be created if 
none of Rutabaga, virgl or udmabuf is enabled.

Regards,
Akihiko Odaki


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH RFC 2/7] virtio-gpu-virgl: check page alignment of blob mapping
  2025-12-04  2:55   ` Akihiko Odaki
@ 2025-12-04  4:01     ` Joelle van Dyne
  2025-12-04  5:31       ` Akihiko Odaki
  0 siblings, 1 reply; 19+ messages in thread
From: Joelle van Dyne @ 2025-12-04  4:01 UTC (permalink / raw)
  To: Akihiko Odaki
  Cc: Joelle van Dyne, qemu-devel, Alex Bennée, Dmitry Osipenko,
	Michael S. Tsirkin

The problem specifically with how Mesa uses it is that
virtgpu_ioctl_map calls the IOCTL DRM_IOCTL_VIRTGPU_MAP which performs
the VIRTIO_GPU_CMD_RESOURCE_MAP_BLOB with an unaligned offset.
virtio_gpu_virgl_map_resource_blob does not error and hv_vm_map
returns silently without doing any maps. Once that makes it to Mesa,
it will try to mmap() and then use the region with vector instructions
that are not supported by HVF because HVF does not emulate
instructions when ISV=0 (this was a topic of discussion many times for
other features like TPM emulation).

On Wed, Dec 3, 2025 at 6:56 PM Akihiko Odaki
<odaki@rsg.ci.i.u-tokyo.ac.jp> wrote:
>
> On 2025/12/03 13:07, Joelle van Dyne wrote:
> > Currently if a mapping is not page aligned, it will sliently fail and the
> > guest, assuming it is mapped, will attempt to access the memory and fail.
> > This is particularly an issue on macOS when the host page size is 16KiB and
> > the guest page size is 4KiB.
>
> It should work. If I understand correctly, tcg doesn't care the host
> page size. hvf will not call hv_vm_map() for misaligned regions and that
> causes Data Abort, but it is handled by QEMU to perform memory access. I
> think it needs more debugging.
>
> Regards,
> Akihiko Odaki
>
> >
> > Signed-off-by: Joelle van Dyne <j@getutm.app>
> > ---
> >   hw/display/virtio-gpu-virgl.c | 14 ++++++++++++++
> >   1 file changed, 14 insertions(+)
> >
> > diff --git a/hw/display/virtio-gpu-virgl.c b/hw/display/virtio-gpu-virgl.c
> > index 20c856c04e..adf02ac22b 100644
> > --- a/hw/display/virtio-gpu-virgl.c
> > +++ b/hw/display/virtio-gpu-virgl.c
> > @@ -116,6 +116,20 @@ virtio_gpu_virgl_map_resource_blob(VirtIOGPU *g,
> >           return ret;
> >       }
> >
> > +    if (!QEMU_IS_ALIGNED((uintptr_t)data, qemu_real_host_page_size())) {
> > +        virgl_renderer_resource_unmap(res->base.resource_id);
> > +        qemu_log_mask(LOG_GUEST_ERROR, "%s: address %p is not aligned to page size\n",
> > +                      __func__, data);
> > +        return -ENOMEM;
> > +    }
> > +
> > +    if (!QEMU_IS_ALIGNED(size, qemu_real_host_page_size())) {
> > +        virgl_renderer_resource_unmap(res->base.resource_id);
> > +        qemu_log_mask(LOG_GUEST_ERROR, "%s: size 0x%llx is not aligned to page size\n",
> > +                      __func__, size);
> > +        return -ENOMEM;
> > +    }
> > +
> >       vmr = g_new0(struct virtio_gpu_virgl_hostmem_region, 1);
> >       vmr->g = g;
> >
>


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH RFC 2/7] virtio-gpu-virgl: check page alignment of blob mapping
  2025-12-04  4:01     ` Joelle van Dyne
@ 2025-12-04  5:31       ` Akihiko Odaki
  0 siblings, 0 replies; 19+ messages in thread
From: Akihiko Odaki @ 2025-12-04  5:31 UTC (permalink / raw)
  To: Joelle van Dyne
  Cc: qemu-devel, Alex Bennée, Dmitry Osipenko, Michael S. Tsirkin

On 2025/12/04 13:01, Joelle van Dyne wrote:
> The problem specifically with how Mesa uses it is that
> virtgpu_ioctl_map calls the IOCTL DRM_IOCTL_VIRTGPU_MAP which performs
> the VIRTIO_GPU_CMD_RESOURCE_MAP_BLOB with an unaligned offset.

The kernel is the one who determines the offset, not Mesa. And I cannot 
blame the kernel either because the virtio specification says nothing 
about the alignment requirement.

> virtio_gpu_virgl_map_resource_blob does not error and hv_vm_map
> returns silently without doing any maps. Once that makes it to Mesa,
> it will try to mmap() and then use the region with vector instructions
> that are not supported by HVF because HVF does not emulate
> instructions when ISV=0 (this was a topic of discussion many times for
> other features like TPM emulation).

This explains the situation well. Please add a comment with a similar 
explanation and change this to perform the check only if
!IS_ENABLED(HOST_AARCH64) && tcg_enabled() (apparently kvm and whpx[1] 
have the same issue) so that it won't break other configurations.

[1] 
https://lore.kernel.org/qemu-devel/20251121100240.89117-1-mohamed@unpredictable.fr/

Regards,
Akihiko Odaki

> 
> On Wed, Dec 3, 2025 at 6:56 PM Akihiko Odaki
> <odaki@rsg.ci.i.u-tokyo.ac.jp> wrote:
>>
>> On 2025/12/03 13:07, Joelle van Dyne wrote:
>>> Currently if a mapping is not page aligned, it will sliently fail and the
>>> guest, assuming it is mapped, will attempt to access the memory and fail.
>>> This is particularly an issue on macOS when the host page size is 16KiB and
>>> the guest page size is 4KiB.
>>
>> It should work. If I understand correctly, tcg doesn't care the host
>> page size. hvf will not call hv_vm_map() for misaligned regions and that
>> causes Data Abort, but it is handled by QEMU to perform memory access. I
>> think it needs more debugging.
>>
>> Regards,
>> Akihiko Odaki
>>
>>>
>>> Signed-off-by: Joelle van Dyne <j@getutm.app>
>>> ---
>>>    hw/display/virtio-gpu-virgl.c | 14 ++++++++++++++
>>>    1 file changed, 14 insertions(+)
>>>
>>> diff --git a/hw/display/virtio-gpu-virgl.c b/hw/display/virtio-gpu-virgl.c
>>> index 20c856c04e..adf02ac22b 100644
>>> --- a/hw/display/virtio-gpu-virgl.c
>>> +++ b/hw/display/virtio-gpu-virgl.c
>>> @@ -116,6 +116,20 @@ virtio_gpu_virgl_map_resource_blob(VirtIOGPU *g,
>>>            return ret;
>>>        }
>>>
>>> +    if (!QEMU_IS_ALIGNED((uintptr_t)data, qemu_real_host_page_size())) {
>>> +        virgl_renderer_resource_unmap(res->base.resource_id);
>>> +        qemu_log_mask(LOG_GUEST_ERROR, "%s: address %p is not aligned to page size\n",
>>> +                      __func__, data);
>>> +        return -ENOMEM;
>>> +    }
>>> +
>>> +    if (!QEMU_IS_ALIGNED(size, qemu_real_host_page_size())) {
>>> +        virgl_renderer_resource_unmap(res->base.resource_id);
>>> +        qemu_log_mask(LOG_GUEST_ERROR, "%s: size 0x%llx is not aligned to page size\n",
>>> +                      __func__, size);
>>> +        return -ENOMEM;
>>> +    }
>>> +
>>>        vmr = g_new0(struct virtio_gpu_virgl_hostmem_region, 1);
>>>        vmr->g = g;
>>>
>>



^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH RFC 6/7] console: add cleanup callback for ScanoutTexture
  2025-12-03  4:07 ` [PATCH RFC 6/7] console: add cleanup callback for ScanoutTexture Joelle van Dyne
@ 2025-12-04  6:23   ` Akihiko Odaki
  0 siblings, 0 replies; 19+ messages in thread
From: Akihiko Odaki @ 2025-12-04  6:23 UTC (permalink / raw)
  To: Joelle van Dyne, qemu-devel
  Cc: Michael S. Tsirkin, Alex Bennée, Dmitry Osipenko,
	Marc-André Lureau

On 2025/12/03 13:07, Joelle van Dyne wrote:
> 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);

Please name this typedef CamelCase as like others.

> +
>   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;
> +};

Struct should have typedef according to: docs/devel/style.rst

Regards,
Akihiko Odaki

> +
> +#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,



^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH RFC 1/7] egl-helpers: store handle to native device
  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
  0 siblings, 0 replies; 19+ messages in thread
From: Akihiko Odaki @ 2025-12-04  6:29 UTC (permalink / raw)
  To: Joelle van Dyne, qemu-devel
  Cc: Michael S. Tsirkin, Alex Bennée, Dmitry Osipenko,
	Marc-André Lureau

On 2025/12/03 13:07, Joelle van Dyne wrote:
> Make way for other platforms by making the variable more general. Also we
> will be using the device in the future so let's save the pointer in the
> global instead of just a boolean flag.
> 
> Signed-off-by: Joelle van Dyne <j@getutm.app>
> ---
>   include/ui/egl-helpers.h      | 2 +-
>   hw/display/virtio-gpu-virgl.c | 2 +-
>   ui/egl-helpers.c              | 4 ++--
>   3 files changed, 4 insertions(+), 4 deletions(-)
> 
> diff --git a/include/ui/egl-helpers.h b/include/ui/egl-helpers.h
> index acf993fcf5..c239d32317 100644
> --- a/include/ui/egl-helpers.h
> +++ b/include/ui/egl-helpers.h
> @@ -12,7 +12,7 @@
>   extern EGLDisplay *qemu_egl_display;
>   extern EGLConfig qemu_egl_config;
>   extern DisplayGLMode qemu_egl_mode;
> -extern bool qemu_egl_angle_d3d;
> +extern void *qemu_egl_angle_native_device;

I guess ANGLE will not be relevant for Metal and leaving it will be 
misleading.

Regards,
Akihiko Odaki

>   
>   typedef struct egl_fb {
>       int width;
> diff --git a/hw/display/virtio-gpu-virgl.c b/hw/display/virtio-gpu-virgl.c
> index 07f6355ad6..20c856c04e 100644
> --- a/hw/display/virtio-gpu-virgl.c
> +++ b/hw/display/virtio-gpu-virgl.c
> @@ -1152,7 +1152,7 @@ int virtio_gpu_virgl_init(VirtIOGPU *g)
>       }
>   #endif
>   #ifdef VIRGL_RENDERER_D3D11_SHARE_TEXTURE
> -    if (qemu_egl_angle_d3d) {
> +    if (qemu_egl_angle_native_device) {
>           flags |= VIRGL_RENDERER_D3D11_SHARE_TEXTURE;
>       }
>   #endif
> diff --git a/ui/egl-helpers.c b/ui/egl-helpers.c
> index e3f2872cc1..57bcf99498 100644
> --- a/ui/egl-helpers.c
> +++ b/ui/egl-helpers.c
> @@ -28,7 +28,7 @@
>   EGLDisplay *qemu_egl_display;
>   EGLConfig qemu_egl_config;
>   DisplayGLMode qemu_egl_mode;
> -bool qemu_egl_angle_d3d;
> +void *qemu_egl_angle_native_device;
>   
>   /* ------------------------------------------------------------------ */
>   
> @@ -651,7 +651,7 @@ int qemu_egl_init_dpy_win32(EGLNativeDisplayType dpy, DisplayGLMode mode)
>           }
>   
>           trace_egl_init_d3d11_device(device);
> -        qemu_egl_angle_d3d = device != NULL;
> +        qemu_egl_angle_native_device = d3d11_device;
>       }
>   #endif
>   



^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH RFC 3/7] console: rename `d3d_tex2d` to `native`
  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
  1 sibling, 0 replies; 19+ messages in thread
From: Akihiko Odaki @ 2025-12-04  6:40 UTC (permalink / raw)
  To: Joelle van Dyne, qemu-devel
  Cc: Alex Bennée, Dmitry Osipenko, Michael S. Tsirkin,
	Marc-André Lureau

On 2025/12/03 13:07, Joelle van Dyne wrote:
> In order to support native texture scanout beyond D3D, we make this more
> generic allowing for multiple native texture handle types.
> 
> Signed-off-by: Joelle van Dyne <j@getutm.app>
> ---
>   include/ui/console.h          | 22 +++++++++++++++++++---
>   include/ui/gtk.h              |  4 ++--
>   include/ui/sdl2.h             |  2 +-
>   hw/display/virtio-gpu-virgl.c | 10 +++++++---
>   ui/console.c                  |  8 ++++----
>   ui/dbus-console.c             |  2 +-
>   ui/dbus-listener.c            |  8 ++++----
>   ui/egl-headless.c             |  2 +-
>   ui/gtk-egl.c                  |  2 +-
>   ui/gtk-gl-area.c              |  2 +-
>   ui/sdl2-gl.c                  |  2 +-
>   ui/spice-display.c            |  2 +-
>   12 files changed, 43 insertions(+), 23 deletions(-)
> 
> diff --git a/include/ui/console.h b/include/ui/console.h
> index 98feaa58bd..25e45295d4 100644
> --- a/include/ui/console.h
> +++ b/include/ui/console.h
> @@ -131,6 +131,22 @@ struct QemuConsoleClass {
>       ObjectClass parent_class;
>   };
>   
> +typedef enum ScanoutTextureNativeType {
> +    SCANOUT_TEXTURE_NATIVE_TYPE_NONE,
> +    SCANOUT_TEXTURE_NATIVE_TYPE_D3D,
> +} ScanoutTextureNativeType;
> +
> +typedef struct ScanoutTextureNative {
> +    ScanoutTextureNativeType type;
> +    union {
> +        void *d3d_tex2d;
> +    } u;> +} ScanoutTextureNative;

Instead, I suggest:

typedef struct ScanoutTextureNative {
     ScanoutTextureNativeType type;
     void *handle;
} ScanoutTextureNative;

...to align with the definition of struct 
virgl_renderer_resource_info_ext and 
virgl_renderer_create_handle_for_scanout(), which do not add a field for 
each type (except the one for the backward compatibility).

Regards,
Akihiko Odaki

> +
> +#define NO_NATIVE_TEXTURE ((ScanoutTextureNative){ \
> +    .type = SCANOUT_TEXTURE_NATIVE_TYPE_NONE \
> +})
> +
>   typedef struct ScanoutTexture {
>       uint32_t backing_id;
>       bool backing_y_0_top;
> @@ -140,7 +156,7 @@ typedef struct ScanoutTexture {
>       uint32_t y;
>       uint32_t width;
>       uint32_t height;
> -    void *d3d_tex2d;
> +    ScanoutTextureNative native;
>   } ScanoutTexture;
>   
>   typedef struct QemuUIInfo {
> @@ -245,7 +261,7 @@ typedef struct DisplayChangeListenerOps {
>                                      uint32_t backing_height,
>                                      uint32_t x, uint32_t y,
>                                      uint32_t w, uint32_t h,
> -                                   void *d3d_tex2d);
> +                                   ScanoutTextureNative native);
>       /* optional (default to true if has dpy_gl_scanout_dmabuf) */
>       bool (*dpy_has_dmabuf)(DisplayChangeListener *dcl);
>       /* optional */
> @@ -329,7 +345,7 @@ 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,
> -                            void *d3d_tex2d);
> +                            ScanoutTextureNative native);
>   void dpy_gl_scanout_dmabuf(QemuConsole *con,
>                              QemuDmaBuf *dmabuf);
>   void dpy_gl_cursor_dmabuf(QemuConsole *con, QemuDmaBuf *dmabuf,
> diff --git a/include/ui/gtk.h b/include/ui/gtk.h
> index 3e6ce3cb48..f88e2b281d 100644
> --- a/include/ui/gtk.h
> +++ b/include/ui/gtk.h
> @@ -178,7 +178,7 @@ void gd_egl_scanout_texture(DisplayChangeListener *dcl,
>                               uint32_t backing_height,
>                               uint32_t x, uint32_t y,
>                               uint32_t w, uint32_t h,
> -                            void *d3d_tex2d);
> +                            ScanoutTextureNative native);
>   void gd_egl_scanout_dmabuf(DisplayChangeListener *dcl,
>                              QemuDmaBuf *dmabuf);
>   void gd_egl_cursor_dmabuf(DisplayChangeListener *dcl,
> @@ -215,7 +215,7 @@ void gd_gl_area_scanout_texture(DisplayChangeListener *dcl,
>                                   uint32_t backing_height,
>                                   uint32_t x, uint32_t y,
>                                   uint32_t w, uint32_t h,
> -                                void *d3d_tex2d);
> +                                ScanoutTextureNative native);
>   void gd_gl_area_scanout_disable(DisplayChangeListener *dcl);
>   void gd_gl_area_scanout_flush(DisplayChangeListener *dcl,
>                                 uint32_t x, uint32_t y, uint32_t w, uint32_t h);
> diff --git a/include/ui/sdl2.h b/include/ui/sdl2.h
> index dbe6e3d973..fdefb88229 100644
> --- a/include/ui/sdl2.h
> +++ b/include/ui/sdl2.h
> @@ -93,7 +93,7 @@ void sdl2_gl_scanout_texture(DisplayChangeListener *dcl,
>                                uint32_t backing_height,
>                                uint32_t x, uint32_t y,
>                                uint32_t w, uint32_t h,
> -                             void *d3d_tex2d);
> +                             ScanoutTextureNative native);
>   void sdl2_gl_scanout_flush(DisplayChangeListener *dcl,
>                              uint32_t x, uint32_t y, uint32_t w, uint32_t h);
>   
> diff --git a/hw/display/virtio-gpu-virgl.c b/hw/display/virtio-gpu-virgl.c
> index adf02ac22b..d0e6ad4b17 100644
> --- a/hw/display/virtio-gpu-virgl.c
> +++ b/hw/display/virtio-gpu-virgl.c
> @@ -434,14 +434,18 @@ static void virgl_cmd_set_scanout(VirtIOGPU *g,
>   
>       if (ss.resource_id && ss.r.width && ss.r.height) {
>           struct virgl_renderer_resource_info info;
> -        void *d3d_tex2d = NULL;
> +        ScanoutTextureNative native = { .type = SCANOUT_TEXTURE_NATIVE_TYPE_NONE };
>   
>   #if VIRGL_VERSION_MAJOR >= 1
>           struct virgl_renderer_resource_info_ext ext;
>           memset(&ext, 0, sizeof(ext));
>           ret = virgl_renderer_resource_get_info_ext(ss.resource_id, &ext);
>           info = ext.base;
> -        d3d_tex2d = ext.d3d_tex2d;
> +        native = (ScanoutTextureNative){
> +            .type = ext.d3d_tex2d ? SCANOUT_TEXTURE_NATIVE_TYPE_D3D :
> +                                    SCANOUT_TEXTURE_NATIVE_TYPE_NONE,
> +            .u.d3d_tex2d = ext.d3d_tex2d,
> +        };
>   #else
>           memset(&info, 0, sizeof(info));
>           ret = virgl_renderer_resource_get_info(ss.resource_id, &info);
> @@ -461,7 +465,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,
> -            d3d_tex2d);
> +            native);
>       } 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 2d00828c53..9378afd53d 100644
> --- a/ui/console.c
> +++ b/ui/console.c
> @@ -295,7 +295,7 @@ static void displaychangelistener_display_console(DisplayChangeListener *dcl,
>                                            con->scanout.texture.y,
>                                            con->scanout.texture.width,
>                                            con->scanout.texture.height,
> -                                         con->scanout.texture.d3d_tex2d);
> +                                         con->scanout.texture.native);
>       }
>   }
>   
> @@ -1023,7 +1023,7 @@ void dpy_gl_scanout_texture(QemuConsole *con,
>                               uint32_t backing_height,
>                               uint32_t x, uint32_t y,
>                               uint32_t width, uint32_t height,
> -                            void *d3d_tex2d)
> +                            ScanoutTextureNative native)
>   {
>       DisplayState *s = con->ds;
>       DisplayChangeListener *dcl;
> @@ -1031,7 +1031,7 @@ void dpy_gl_scanout_texture(QemuConsole *con,
>       con->scanout.kind = SCANOUT_TEXTURE;
>       con->scanout.texture = (ScanoutTexture) {
>           backing_id, backing_y_0_top, backing_width, backing_height,
> -        x, y, width, height, d3d_tex2d,
> +        x, y, width, height, native,
>       };
>       QLIST_FOREACH(dcl, &s->listeners, next) {
>           if (con != dcl->con) {
> @@ -1042,7 +1042,7 @@ void dpy_gl_scanout_texture(QemuConsole *con,
>                                                backing_y_0_top,
>                                                backing_width, backing_height,
>                                                x, y, width, height,
> -                                             d3d_tex2d);
> +                                             native);
>           }
>       }
>   }
> diff --git a/ui/dbus-console.c b/ui/dbus-console.c
> index 85e215ef23..651f0daeaf 100644
> --- a/ui/dbus-console.c
> +++ b/ui/dbus-console.c
> @@ -99,7 +99,7 @@ dbus_gl_scanout_texture(DisplayChangeListener *dcl,
>                           uint32_t backing_height,
>                           uint32_t x, uint32_t y,
>                           uint32_t w, uint32_t h,
> -                        void *d3d_tex2d)
> +                        ScanoutTextureNative native)
>   {
>       DBusDisplayConsole *ddc = container_of(dcl, DBusDisplayConsole, dcl);
>   
> diff --git a/ui/dbus-listener.c b/ui/dbus-listener.c
> index 52e041edb0..a737752996 100644
> --- a/ui/dbus-listener.c
> +++ b/ui/dbus-listener.c
> @@ -587,7 +587,7 @@ static void dbus_scanout_texture(DisplayChangeListener *dcl,
>                                    uint32_t backing_height,
>                                    uint32_t x, uint32_t y,
>                                    uint32_t w, uint32_t h,
> -                                 void *d3d_tex2d)
> +                                 ScanoutTextureNative native)
>   {
>       trace_dbus_scanout_texture(tex_id, backing_y_0_top,
>                                  backing_width, backing_height, x, y, w, h);
> @@ -618,8 +618,8 @@ static void dbus_scanout_texture(DisplayChangeListener *dcl,
>       assert(surface_width(ddl->ds) == w);
>       assert(surface_height(ddl->ds) == h);
>   
> -    if (d3d_tex2d) {
> -        dbus_scanout_share_d3d_texture(ddl, d3d_tex2d, backing_y_0_top,
> +    if (native.type == SCANOUT_TEXTURE_NATIVE_TYPE_D3d) {

s/SCANOUT_TEXTURE_NATIVE_TYPE_D3d/SCANOUT_TEXTURE_NATIVE_TYPE_D3D/

Regards,
Akihiko Odaki

> +        dbus_scanout_share_d3d_texture(ddl, native.u.d3d_tex2d, backing_y_0_top,
>                                          backing_width, backing_height, x, y, w, h);
>       } else {
>           dbus_scanout_map(ddl);
> @@ -868,7 +868,7 @@ static void dbus_gl_gfx_switch(DisplayChangeListener *dcl,
>   
>           /* TODO: lazy send dmabuf (there are unnecessary sent otherwise) */
>           dbus_scanout_texture(&ddl->dcl, ddl->ds->texture, false,
> -                             width, height, 0, 0, width, height, NULL);
> +                             width, height, 0, 0, width, height, NO_NATIVE_TEXTURE);
>       }
>   }
>   #endif
> diff --git a/ui/egl-headless.c b/ui/egl-headless.c
> index 1f6b845500..e36778bd48 100644
> --- a/ui/egl-headless.c
> +++ b/ui/egl-headless.c
> @@ -62,7 +62,7 @@ static void egl_scanout_texture(DisplayChangeListener *dcl,
>                                   uint32_t backing_height,
>                                   uint32_t x, uint32_t y,
>                                   uint32_t w, uint32_t h,
> -                                void *d3d_tex2d)
> +                                ScanoutTextureNative native)
>   {
>       egl_dpy *edpy = container_of(dcl, egl_dpy, dcl);
>   
> diff --git a/ui/gtk-egl.c b/ui/gtk-egl.c
> index ae9239999c..7933237d45 100644
> --- a/ui/gtk-egl.c
> +++ b/ui/gtk-egl.c
> @@ -239,7 +239,7 @@ void gd_egl_scanout_texture(DisplayChangeListener *dcl,
>                               uint32_t backing_width, uint32_t backing_height,
>                               uint32_t x, uint32_t y,
>                               uint32_t w, uint32_t h,
> -                            void *d3d_tex2d)
> +                            ScanoutTextureNative native)
>   {
>       VirtualConsole *vc = container_of(dcl, VirtualConsole, gfx.dcl);
>   
> diff --git a/ui/gtk-gl-area.c b/ui/gtk-gl-area.c
> index cd86022d26..f2ed543d6a 100644
> --- a/ui/gtk-gl-area.c
> +++ b/ui/gtk-gl-area.c
> @@ -306,7 +306,7 @@ void gd_gl_area_scanout_texture(DisplayChangeListener *dcl,
>                                   uint32_t backing_height,
>                                   uint32_t x, uint32_t y,
>                                   uint32_t w, uint32_t h,
> -                                void *d3d_tex2d)
> +                                ScanoutTextureNative native)
>   {
>       VirtualConsole *vc = container_of(dcl, VirtualConsole, gfx.dcl);
>   
> diff --git a/ui/sdl2-gl.c b/ui/sdl2-gl.c
> index 3be17d1079..b15db86f24 100644
> --- a/ui/sdl2-gl.c
> +++ b/ui/sdl2-gl.c
> @@ -206,7 +206,7 @@ void sdl2_gl_scanout_texture(DisplayChangeListener *dcl,
>                                uint32_t backing_height,
>                                uint32_t x, uint32_t y,
>                                uint32_t w, uint32_t h,
> -                             void *d3d_tex2d)
> +                             ScanoutTextureNative native)
>   {
>       struct sdl2_console *scon = container_of(dcl, struct sdl2_console, dcl);
>   
> diff --git a/ui/spice-display.c b/ui/spice-display.c
> index db71e866f8..2a2285cb1f 100644
> --- a/ui/spice-display.c
> +++ b/ui/spice-display.c
> @@ -1084,7 +1084,7 @@ static void qemu_spice_gl_scanout_texture(DisplayChangeListener *dcl,
>                                             uint32_t backing_height,
>                                             uint32_t x, uint32_t y,
>                                             uint32_t w, uint32_t h,
> -                                          void *d3d_tex2d)
> +                                          ScanoutTextureNative native)
>   {
>       SimpleSpiceDisplay *ssd = container_of(dcl, SimpleSpiceDisplay, dcl);
>       EGLint offset[DMABUF_MAX_PLANES], stride[DMABUF_MAX_PLANES], fourcc = 0;



^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH RFC 4/7] virtio-gpu-virgl: update virglrenderer defines
  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
  1 sibling, 0 replies; 19+ messages in thread
From: Akihiko Odaki @ 2025-12-04  7:13 UTC (permalink / raw)
  To: Joelle van Dyne, qemu-devel
  Cc: Michael S. Tsirkin, Alex Bennée, Dmitry Osipenko

On 2025/12/03 13:07, Joelle van Dyne wrote:
> In order to support additional native texture types, we need to update the
> defines in virglrenderer. The changes are backwards compatible and so
> builds should work with either the new version or the old version.
> 
> Signed-off-by: Joelle van Dyne <j@getutm.app>
> ---
>   hw/display/virtio-gpu-virgl.c | 28 +++++++++++++++++++++++++---
>   1 file changed, 25 insertions(+), 3 deletions(-)
> 
> diff --git a/hw/display/virtio-gpu-virgl.c b/hw/display/virtio-gpu-virgl.c
> index d0e6ad4b17..36c670f988 100644
> --- a/hw/display/virtio-gpu-virgl.c
> +++ b/hw/display/virtio-gpu-virgl.c
> @@ -24,6 +24,8 @@
>   
>   #include <virglrenderer.h>
>   
> +#define SUPPORTED_VIRGL_INFO_EXT_VERSION (1)

This naming is a bit confusing because version 0 is also supported.

> +
>   struct virtio_gpu_virgl_resource {
>       struct virtio_gpu_simple_resource base;
>       MemoryRegion *mr;
> @@ -441,12 +443,30 @@ static void virgl_cmd_set_scanout(VirtIOGPU *g,
>           memset(&ext, 0, sizeof(ext));
>           ret = virgl_renderer_resource_get_info_ext(ss.resource_id, &ext);
>           info = ext.base;
> +        /* fallback to older version */
>           native = (ScanoutTextureNative){
>               .type = ext.d3d_tex2d ? SCANOUT_TEXTURE_NATIVE_TYPE_D3D :
>                                       SCANOUT_TEXTURE_NATIVE_TYPE_NONE,
>               .u.d3d_tex2d = ext.d3d_tex2d,
>           };
> -#else
> +#if VIRGL_RENDERER_RESOURCE_INFO_EXT_VERSION >= SUPPORTED_VIRGL_INFO_EXT_VERSION
> +        if (ext.version >= VIRGL_RENDERER_RESOURCE_INFO_EXT_VERSION) {
> +            switch (ext.native_type) {
> +            case VIRGL_NATIVE_HANDLE_NONE:
> +            case VIRGL_NATIVE_HANDLE_D3D_TEX2D: {
> +                /* already handled above */
> +                break;
> +            }
> +            default: {
> +                qemu_log_mask(LOG_GUEST_ERROR,
> +                            "%s: unsupported native texture type %d\n",
> +                            __func__, ext.native_type);

It is not an error condition; the d3d_tex2d field is an optional hint 
that allows zero-copy inter-process sharing and the tex_id field is used 
if it is missing or inter-process sharing is unnecessary. It should be 
fine to dismiss the native handle unless the semantic changes.

Regards,
Akihiko Odaki

> +                break;
> +            }
> +            }
> +        }
> +#endif
> +#else /* VIRGL_VERSION_MAJOR < 1 */
>           memset(&info, 0, sizeof(info));
>           ret = virgl_renderer_resource_get_info(ss.resource_id, &info);
>   #endif
> @@ -1169,11 +1189,13 @@ int virtio_gpu_virgl_init(VirtIOGPU *g)
>           virtio_gpu_3d_cbs.get_egl_display = virgl_get_egl_display;
>       }
>   #endif
> -#ifdef VIRGL_RENDERER_D3D11_SHARE_TEXTURE
>       if (qemu_egl_angle_native_device) {
> +#if defined(VIRGL_RENDERER_NATIVE_SHARE_TEXTURE)
> +        flags |= VIRGL_RENDERER_NATIVE_SHARE_TEXTURE;
> +#elif defined(VIRGL_RENDERER_D3D11_SHARE_TEXTURE) && defined(WIN32)
>           flags |= VIRGL_RENDERER_D3D11_SHARE_TEXTURE;
> -    }
>   #endif
> +    }
>   #if VIRGL_VERSION_MAJOR >= 1
>       if (virtio_gpu_venus_enabled(g->parent_obj.conf)) {
>           flags |= VIRGL_RENDERER_VENUS | VIRGL_RENDERER_RENDER_SERVER;



^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH RFC 3/7] console: rename `d3d_tex2d` to `native`
  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
  1 sibling, 0 replies; 19+ messages in thread
From: Marc-André Lureau @ 2025-12-04 10:53 UTC (permalink / raw)
  To: Joelle van Dyne
  Cc: qemu-devel, Alex Bennée, Akihiko Odaki, Dmitry Osipenko,
	Michael S. Tsirkin

Hi

On Wed, Dec 3, 2025 at 8:09 AM Joelle van Dyne <j@getutm.app> wrote:
>
> In order to support native texture scanout beyond D3D, we make this more
> generic allowing for multiple native texture handle types.
>
> Signed-off-by: Joelle van Dyne <j@getutm.app>

../ui/egl-headless.c:100:40: error: incompatible type for argument 10
of ‘egl_scanout_texture’
../ui/gtk-gl-area.c:377:53: error: incompatible type for argument 10
of ‘gd_gl_area_scanout_texture’
../ui/gtk-egl.c:293:49: error: incompatible type for argument 10 of
‘gd_egl_scanout_texture’

all like:
 note: expected ‘ScanoutTextureNative’ but argument is of type ‘void *’


> ---
>  include/ui/console.h          | 22 +++++++++++++++++++---
>  include/ui/gtk.h              |  4 ++--
>  include/ui/sdl2.h             |  2 +-
>  hw/display/virtio-gpu-virgl.c | 10 +++++++---
>  ui/console.c                  |  8 ++++----
>  ui/dbus-console.c             |  2 +-
>  ui/dbus-listener.c            |  8 ++++----
>  ui/egl-headless.c             |  2 +-
>  ui/gtk-egl.c                  |  2 +-
>  ui/gtk-gl-area.c              |  2 +-
>  ui/sdl2-gl.c                  |  2 +-
>  ui/spice-display.c            |  2 +-
>  12 files changed, 43 insertions(+), 23 deletions(-)
>
> diff --git a/include/ui/console.h b/include/ui/console.h
> index 98feaa58bd..25e45295d4 100644
> --- a/include/ui/console.h
> +++ b/include/ui/console.h
> @@ -131,6 +131,22 @@ struct QemuConsoleClass {
>      ObjectClass parent_class;
>  };
>
> +typedef enum ScanoutTextureNativeType {
> +    SCANOUT_TEXTURE_NATIVE_TYPE_NONE,
> +    SCANOUT_TEXTURE_NATIVE_TYPE_D3D,
> +} ScanoutTextureNativeType;
> +
> +typedef struct ScanoutTextureNative {
> +    ScanoutTextureNativeType type;
> +    union {
> +        void *d3d_tex2d;
> +    } u;
> +} ScanoutTextureNative;
> +
> +#define NO_NATIVE_TEXTURE ((ScanoutTextureNative){ \
> +    .type = SCANOUT_TEXTURE_NATIVE_TYPE_NONE \
> +})
> +
>  typedef struct ScanoutTexture {
>      uint32_t backing_id;
>      bool backing_y_0_top;
> @@ -140,7 +156,7 @@ typedef struct ScanoutTexture {
>      uint32_t y;
>      uint32_t width;
>      uint32_t height;
> -    void *d3d_tex2d;
> +    ScanoutTextureNative native;
>  } ScanoutTexture;
>
>  typedef struct QemuUIInfo {
> @@ -245,7 +261,7 @@ typedef struct DisplayChangeListenerOps {
>                                     uint32_t backing_height,
>                                     uint32_t x, uint32_t y,
>                                     uint32_t w, uint32_t h,
> -                                   void *d3d_tex2d);
> +                                   ScanoutTextureNative native);
>      /* optional (default to true if has dpy_gl_scanout_dmabuf) */
>      bool (*dpy_has_dmabuf)(DisplayChangeListener *dcl);
>      /* optional */
> @@ -329,7 +345,7 @@ 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,
> -                            void *d3d_tex2d);
> +                            ScanoutTextureNative native);
>  void dpy_gl_scanout_dmabuf(QemuConsole *con,
>                             QemuDmaBuf *dmabuf);
>  void dpy_gl_cursor_dmabuf(QemuConsole *con, QemuDmaBuf *dmabuf,
> diff --git a/include/ui/gtk.h b/include/ui/gtk.h
> index 3e6ce3cb48..f88e2b281d 100644
> --- a/include/ui/gtk.h
> +++ b/include/ui/gtk.h
> @@ -178,7 +178,7 @@ void gd_egl_scanout_texture(DisplayChangeListener *dcl,
>                              uint32_t backing_height,
>                              uint32_t x, uint32_t y,
>                              uint32_t w, uint32_t h,
> -                            void *d3d_tex2d);
> +                            ScanoutTextureNative native);
>  void gd_egl_scanout_dmabuf(DisplayChangeListener *dcl,
>                             QemuDmaBuf *dmabuf);
>  void gd_egl_cursor_dmabuf(DisplayChangeListener *dcl,
> @@ -215,7 +215,7 @@ void gd_gl_area_scanout_texture(DisplayChangeListener *dcl,
>                                  uint32_t backing_height,
>                                  uint32_t x, uint32_t y,
>                                  uint32_t w, uint32_t h,
> -                                void *d3d_tex2d);
> +                                ScanoutTextureNative native);
>  void gd_gl_area_scanout_disable(DisplayChangeListener *dcl);
>  void gd_gl_area_scanout_flush(DisplayChangeListener *dcl,
>                                uint32_t x, uint32_t y, uint32_t w, uint32_t h);
> diff --git a/include/ui/sdl2.h b/include/ui/sdl2.h
> index dbe6e3d973..fdefb88229 100644
> --- a/include/ui/sdl2.h
> +++ b/include/ui/sdl2.h
> @@ -93,7 +93,7 @@ void sdl2_gl_scanout_texture(DisplayChangeListener *dcl,
>                               uint32_t backing_height,
>                               uint32_t x, uint32_t y,
>                               uint32_t w, uint32_t h,
> -                             void *d3d_tex2d);
> +                             ScanoutTextureNative native);
>  void sdl2_gl_scanout_flush(DisplayChangeListener *dcl,
>                             uint32_t x, uint32_t y, uint32_t w, uint32_t h);
>
> diff --git a/hw/display/virtio-gpu-virgl.c b/hw/display/virtio-gpu-virgl.c
> index adf02ac22b..d0e6ad4b17 100644
> --- a/hw/display/virtio-gpu-virgl.c
> +++ b/hw/display/virtio-gpu-virgl.c
> @@ -434,14 +434,18 @@ static void virgl_cmd_set_scanout(VirtIOGPU *g,
>
>      if (ss.resource_id && ss.r.width && ss.r.height) {
>          struct virgl_renderer_resource_info info;
> -        void *d3d_tex2d = NULL;
> +        ScanoutTextureNative native = { .type = SCANOUT_TEXTURE_NATIVE_TYPE_NONE };
>
>  #if VIRGL_VERSION_MAJOR >= 1
>          struct virgl_renderer_resource_info_ext ext;
>          memset(&ext, 0, sizeof(ext));
>          ret = virgl_renderer_resource_get_info_ext(ss.resource_id, &ext);
>          info = ext.base;
> -        d3d_tex2d = ext.d3d_tex2d;
> +        native = (ScanoutTextureNative){
> +            .type = ext.d3d_tex2d ? SCANOUT_TEXTURE_NATIVE_TYPE_D3D :
> +                                    SCANOUT_TEXTURE_NATIVE_TYPE_NONE,
> +            .u.d3d_tex2d = ext.d3d_tex2d,
> +        };
>  #else
>          memset(&info, 0, sizeof(info));
>          ret = virgl_renderer_resource_get_info(ss.resource_id, &info);
> @@ -461,7 +465,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,
> -            d3d_tex2d);
> +            native);
>      } 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 2d00828c53..9378afd53d 100644
> --- a/ui/console.c
> +++ b/ui/console.c
> @@ -295,7 +295,7 @@ static void displaychangelistener_display_console(DisplayChangeListener *dcl,
>                                           con->scanout.texture.y,
>                                           con->scanout.texture.width,
>                                           con->scanout.texture.height,
> -                                         con->scanout.texture.d3d_tex2d);
> +                                         con->scanout.texture.native);
>      }
>  }
>
> @@ -1023,7 +1023,7 @@ void dpy_gl_scanout_texture(QemuConsole *con,
>                              uint32_t backing_height,
>                              uint32_t x, uint32_t y,
>                              uint32_t width, uint32_t height,
> -                            void *d3d_tex2d)
> +                            ScanoutTextureNative native)
>  {
>      DisplayState *s = con->ds;
>      DisplayChangeListener *dcl;
> @@ -1031,7 +1031,7 @@ void dpy_gl_scanout_texture(QemuConsole *con,
>      con->scanout.kind = SCANOUT_TEXTURE;
>      con->scanout.texture = (ScanoutTexture) {
>          backing_id, backing_y_0_top, backing_width, backing_height,
> -        x, y, width, height, d3d_tex2d,
> +        x, y, width, height, native,
>      };
>      QLIST_FOREACH(dcl, &s->listeners, next) {
>          if (con != dcl->con) {
> @@ -1042,7 +1042,7 @@ void dpy_gl_scanout_texture(QemuConsole *con,
>                                               backing_y_0_top,
>                                               backing_width, backing_height,
>                                               x, y, width, height,
> -                                             d3d_tex2d);
> +                                             native);
>          }
>      }
>  }
> diff --git a/ui/dbus-console.c b/ui/dbus-console.c
> index 85e215ef23..651f0daeaf 100644
> --- a/ui/dbus-console.c
> +++ b/ui/dbus-console.c
> @@ -99,7 +99,7 @@ dbus_gl_scanout_texture(DisplayChangeListener *dcl,
>                          uint32_t backing_height,
>                          uint32_t x, uint32_t y,
>                          uint32_t w, uint32_t h,
> -                        void *d3d_tex2d)
> +                        ScanoutTextureNative native)
>  {
>      DBusDisplayConsole *ddc = container_of(dcl, DBusDisplayConsole, dcl);
>
> diff --git a/ui/dbus-listener.c b/ui/dbus-listener.c
> index 52e041edb0..a737752996 100644
> --- a/ui/dbus-listener.c
> +++ b/ui/dbus-listener.c
> @@ -587,7 +587,7 @@ static void dbus_scanout_texture(DisplayChangeListener *dcl,
>                                   uint32_t backing_height,
>                                   uint32_t x, uint32_t y,
>                                   uint32_t w, uint32_t h,
> -                                 void *d3d_tex2d)
> +                                 ScanoutTextureNative native)
>  {
>      trace_dbus_scanout_texture(tex_id, backing_y_0_top,
>                                 backing_width, backing_height, x, y, w, h);
> @@ -618,8 +618,8 @@ static void dbus_scanout_texture(DisplayChangeListener *dcl,
>      assert(surface_width(ddl->ds) == w);
>      assert(surface_height(ddl->ds) == h);
>
> -    if (d3d_tex2d) {
> -        dbus_scanout_share_d3d_texture(ddl, d3d_tex2d, backing_y_0_top,
> +    if (native.type == SCANOUT_TEXTURE_NATIVE_TYPE_D3d) {
> +        dbus_scanout_share_d3d_texture(ddl, native.u.d3d_tex2d, backing_y_0_top,
>                                         backing_width, backing_height, x, y, w, h);
>      } else {
>          dbus_scanout_map(ddl);
> @@ -868,7 +868,7 @@ static void dbus_gl_gfx_switch(DisplayChangeListener *dcl,
>
>          /* TODO: lazy send dmabuf (there are unnecessary sent otherwise) */
>          dbus_scanout_texture(&ddl->dcl, ddl->ds->texture, false,
> -                             width, height, 0, 0, width, height, NULL);
> +                             width, height, 0, 0, width, height, NO_NATIVE_TEXTURE);
>      }
>  }
>  #endif
> diff --git a/ui/egl-headless.c b/ui/egl-headless.c
> index 1f6b845500..e36778bd48 100644
> --- a/ui/egl-headless.c
> +++ b/ui/egl-headless.c
> @@ -62,7 +62,7 @@ static void egl_scanout_texture(DisplayChangeListener *dcl,
>                                  uint32_t backing_height,
>                                  uint32_t x, uint32_t y,
>                                  uint32_t w, uint32_t h,
> -                                void *d3d_tex2d)
> +                                ScanoutTextureNative native)
>  {
>      egl_dpy *edpy = container_of(dcl, egl_dpy, dcl);
>
> diff --git a/ui/gtk-egl.c b/ui/gtk-egl.c
> index ae9239999c..7933237d45 100644
> --- a/ui/gtk-egl.c
> +++ b/ui/gtk-egl.c
> @@ -239,7 +239,7 @@ void gd_egl_scanout_texture(DisplayChangeListener *dcl,
>                              uint32_t backing_width, uint32_t backing_height,
>                              uint32_t x, uint32_t y,
>                              uint32_t w, uint32_t h,
> -                            void *d3d_tex2d)
> +                            ScanoutTextureNative native)
>  {
>      VirtualConsole *vc = container_of(dcl, VirtualConsole, gfx.dcl);
>
> diff --git a/ui/gtk-gl-area.c b/ui/gtk-gl-area.c
> index cd86022d26..f2ed543d6a 100644
> --- a/ui/gtk-gl-area.c
> +++ b/ui/gtk-gl-area.c
> @@ -306,7 +306,7 @@ void gd_gl_area_scanout_texture(DisplayChangeListener *dcl,
>                                  uint32_t backing_height,
>                                  uint32_t x, uint32_t y,
>                                  uint32_t w, uint32_t h,
> -                                void *d3d_tex2d)
> +                                ScanoutTextureNative native)
>  {
>      VirtualConsole *vc = container_of(dcl, VirtualConsole, gfx.dcl);
>
> diff --git a/ui/sdl2-gl.c b/ui/sdl2-gl.c
> index 3be17d1079..b15db86f24 100644
> --- a/ui/sdl2-gl.c
> +++ b/ui/sdl2-gl.c
> @@ -206,7 +206,7 @@ void sdl2_gl_scanout_texture(DisplayChangeListener *dcl,
>                               uint32_t backing_height,
>                               uint32_t x, uint32_t y,
>                               uint32_t w, uint32_t h,
> -                             void *d3d_tex2d)
> +                             ScanoutTextureNative native)
>  {
>      struct sdl2_console *scon = container_of(dcl, struct sdl2_console, dcl);
>
> diff --git a/ui/spice-display.c b/ui/spice-display.c
> index db71e866f8..2a2285cb1f 100644
> --- a/ui/spice-display.c
> +++ b/ui/spice-display.c
> @@ -1084,7 +1084,7 @@ static void qemu_spice_gl_scanout_texture(DisplayChangeListener *dcl,
>                                            uint32_t backing_height,
>                                            uint32_t x, uint32_t y,
>                                            uint32_t w, uint32_t h,
> -                                          void *d3d_tex2d)
> +                                          ScanoutTextureNative native)
>  {
>      SimpleSpiceDisplay *ssd = container_of(dcl, SimpleSpiceDisplay, dcl);
>      EGLint offset[DMABUF_MAX_PLANES], stride[DMABUF_MAX_PLANES], fourcc = 0;
> --
> 2.41.0
>
>


-- 
Marc-André Lureau


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH RFC 4/7] virtio-gpu-virgl: update virglrenderer defines
  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
  1 sibling, 0 replies; 19+ messages in thread
From: Marc-André Lureau @ 2025-12-04 10:57 UTC (permalink / raw)
  To: Joelle van Dyne
  Cc: qemu-devel, Michael S. Tsirkin, Alex Bennée, Akihiko Odaki,
	Dmitry Osipenko

Hi

On Wed, Dec 3, 2025 at 8:10 AM Joelle van Dyne <j@getutm.app> wrote:
>
> In order to support additional native texture types, we need to update the
> defines in virglrenderer. The changes are backwards compatible and so
> builds should work with either the new version or the old version.
>
> Signed-off-by: Joelle van Dyne <j@getutm.app>

Please add a link to the pending MR.

> ---
>  hw/display/virtio-gpu-virgl.c | 28 +++++++++++++++++++++++++---
>  1 file changed, 25 insertions(+), 3 deletions(-)
>
> diff --git a/hw/display/virtio-gpu-virgl.c b/hw/display/virtio-gpu-virgl.c
> index d0e6ad4b17..36c670f988 100644
> --- a/hw/display/virtio-gpu-virgl.c
> +++ b/hw/display/virtio-gpu-virgl.c
> @@ -24,6 +24,8 @@
>
>  #include <virglrenderer.h>
>
> +#define SUPPORTED_VIRGL_INFO_EXT_VERSION (1)
> +
>  struct virtio_gpu_virgl_resource {
>      struct virtio_gpu_simple_resource base;
>      MemoryRegion *mr;
> @@ -441,12 +443,30 @@ static void virgl_cmd_set_scanout(VirtIOGPU *g,
>          memset(&ext, 0, sizeof(ext));
>          ret = virgl_renderer_resource_get_info_ext(ss.resource_id, &ext);
>          info = ext.base;
> +        /* fallback to older version */
>          native = (ScanoutTextureNative){
>              .type = ext.d3d_tex2d ? SCANOUT_TEXTURE_NATIVE_TYPE_D3D :
>                                      SCANOUT_TEXTURE_NATIVE_TYPE_NONE,
>              .u.d3d_tex2d = ext.d3d_tex2d,
>          };
> -#else
> +#if VIRGL_RENDERER_RESOURCE_INFO_EXT_VERSION >= SUPPORTED_VIRGL_INFO_EXT_VERSION
> +        if (ext.version >= VIRGL_RENDERER_RESOURCE_INFO_EXT_VERSION) {
> +            switch (ext.native_type) {
> +            case VIRGL_NATIVE_HANDLE_NONE:
> +            case VIRGL_NATIVE_HANDLE_D3D_TEX2D: {
> +                /* already handled above */
> +                break;
> +            }
> +            default: {
> +                qemu_log_mask(LOG_GUEST_ERROR,
> +                            "%s: unsupported native texture type %d\n",
> +                            __func__, ext.native_type);
> +                break;
> +            }
> +            }
> +        }
> +#endif
> +#else /* VIRGL_VERSION_MAJOR < 1 */
>          memset(&info, 0, sizeof(info));
>          ret = virgl_renderer_resource_get_info(ss.resource_id, &info);
>  #endif
> @@ -1169,11 +1189,13 @@ int virtio_gpu_virgl_init(VirtIOGPU *g)
>          virtio_gpu_3d_cbs.get_egl_display = virgl_get_egl_display;
>      }
>  #endif
> -#ifdef VIRGL_RENDERER_D3D11_SHARE_TEXTURE
>      if (qemu_egl_angle_native_device) {
> +#if defined(VIRGL_RENDERER_NATIVE_SHARE_TEXTURE)
> +        flags |= VIRGL_RENDERER_NATIVE_SHARE_TEXTURE;
> +#elif defined(VIRGL_RENDERER_D3D11_SHARE_TEXTURE) && defined(WIN32)
>          flags |= VIRGL_RENDERER_D3D11_SHARE_TEXTURE;
> -    }
>  #endif
> +    }
>  #if VIRGL_VERSION_MAJOR >= 1
>      if (virtio_gpu_venus_enabled(g->parent_obj.conf)) {
>          flags |= VIRGL_RENDERER_VENUS | VIRGL_RENDERER_RENDER_SERVER;
> --
> 2.41.0
>
>


-- 
Marc-André Lureau


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH RFC 2/7] virtio-gpu-virgl: check page alignment of blob mapping
  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-11  4:09   ` Mohamed Mediouni
  1 sibling, 0 replies; 19+ messages in thread
From: Mohamed Mediouni @ 2025-12-11  4:09 UTC (permalink / raw)
  To: Joelle van Dyne
  Cc: qemu-devel, Alex Bennée, Akihiko Odaki, Dmitry Osipenko,
	Michael S. Tsirkin



> On 3. Dec 2025, at 05:07, Joelle van Dyne <j@getutm.app> wrote:
> 
> Currently if a mapping is not page aligned, it will sliently fail and the
> guest, assuming it is mapped, will attempt to access the memory and fail.
> This is particularly an issue on macOS when the host page size is 16KiB and
> the guest page size is 4KiB.
> 
> Signed-off-by: Joelle van Dyne <j@getutm.app>
> ---
> hw/display/virtio-gpu-virgl.c | 14 ++++++++++++++
> 1 file changed, 14 insertions(+)
> 
> diff --git a/hw/display/virtio-gpu-virgl.c b/hw/display/virtio-gpu-virgl.c
> index 20c856c04e..adf02ac22b 100644
> --- a/hw/display/virtio-gpu-virgl.c
> +++ b/hw/display/virtio-gpu-virgl.c
> @@ -116,6 +116,20 @@ virtio_gpu_virgl_map_resource_blob(VirtIOGPU *g,
>         return ret;
>     }
> 
> +    if (!QEMU_IS_ALIGNED((uintptr_t)data, qemu_real_host_page_size())) {
> +        virgl_renderer_resource_unmap(res->base.resource_id);
> +        qemu_log_mask(LOG_GUEST_ERROR, "%s: address %p is not aligned to page size\n",
> +                      __func__, data);
> +        return -ENOMEM;
> +    }
> +
> +    if (!QEMU_IS_ALIGNED(size, qemu_real_host_page_size())) {
> +        virgl_renderer_resource_unmap(res->base.resource_id);
> +        qemu_log_mask(LOG_GUEST_ERROR, "%s: size 0x%llx is not aligned to page size\n",
> +                      __func__, size);
> +        return -ENOMEM;
> +    }
> +
>     vmr = g_new0(struct virtio_gpu_virgl_hostmem_region, 1);
>     vmr->g = g;
> 
> -- 
> 2.41.0
> 
> 

Hello,

There’s a better way to handle this without guest breakage.

Please use hv_vm_config_set_ipa_granule, it’ll allow to have 4KB granule allocations as the IPA.

Note: This might have some impact on performance so we might to want to enable it only when virtio-gpu is used.

Thank you,






^ permalink raw reply	[flat|nested] 19+ messages in thread

end of thread, other threads:[~2025-12-11  4:10 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
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 ` [PATCH RFC 6/7] console: add cleanup callback for ScanoutTexture Joelle van Dyne
2025-12-04  6:23   ` Akihiko Odaki
2025-12-03  4:07 ` [PATCH RFC 7/7] virtio-gpu-virgl: add support for native blob scanout Joelle van Dyne

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).