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