* [PULL 00/16] ui/audio/dump patches for 11.0-rc
@ 2026-03-17 17:19 marcandre.lureau
2026-03-17 17:19 ` [PULL 01/16] audio/mixeng: drop some needless checks marcandre.lureau
` (16 more replies)
0 siblings, 17 replies; 18+ messages in thread
From: marcandre.lureau @ 2026-03-17 17:19 UTC (permalink / raw)
To: qemu-devel
Cc: Dmitry Osipenko, Marc-André Lureau, Michael S. Tsirkin,
Christian Schoenebeck, Ani Sinha, Alex Bennée,
Philippe Mathieu-Daudé, Gerd Hoffmann, Zhao Liu,
Marcel Apfelbaum, Yanan Wang, Akihiko Odaki
From: Marc-André Lureau <marcandre.lureau@redhat.com>
The following changes since commit 559919ce54927d59b215a4665eda7ab6118a48aa:
Merge tag 'pull-trivial-patches' of https://gitlab.com/mjt0k/qemu into staging (2026-03-16 13:07:33 +0000)
are available in the Git repository at:
https://gitlab.com/marcandre.lureau/qemu.git tags/for-11.0-pull-request
for you to fetch changes up to 461632f0b1cb2c5c29ba9875857637e3356b903c:
coreaudio: Initialize the buffer for device change (2026-03-17 21:15:10 +0400)
----------------------------------------------------------------
Gather various audio/ui/dump patches for 11.0-rc
----------------------------------------------------------------
Akihiko Odaki (7):
ui/console: Unify pixman-OpenGL format mapping
ui/console: Remove DisplaySurface::mem_obj
ui/surface: Avoid including epoxy/gl.h in header files
coreaudio: Improve naming
coreaudio: Commit the result of init in the end
audio: Add functions to initialize buffers
coreaudio: Initialize the buffer for device change
Dongwon Kim (1):
ui/gtk-egl: Ensure EGL surface is available before drawing
Fiona Ebner (1):
ui/vdagent: add migration blocker when machine version < 10.1
Marc-André Lureau (6):
audio/mixeng: drop some needless checks
rutabaga: improve error handling, fix potential crash during init
virtio-gpu: fix overflow check when allocating 2d image
virtio-gpu: use computed rowstride instead of deriving it from hostmem
ui/dbus-listener: Fix FBO leak in dbus_cursor_dmabuf
ui/dbus-listener: remove dbus_filter on connection close
Nikolai Barybin (1):
dump: enhance dump_state_prepare fd initialization
audio/audio_int.h | 2 +
audio/audio_template.h | 6 -
include/ui/console.h | 4 +-
include/ui/shader.h | 2 -
include/ui/spice-display.h | 1 +
include/ui/surface.h | 6 +-
audio/audio-mixeng-be.c | 24 +++-
dump/dump.c | 9 +-
hw/core/machine.c | 1 +
hw/display/virtio-gpu-rutabaga.c | 19 ++-
hw/display/virtio-gpu.c | 43 +++++--
ui/console-gl.c | 74 ++++++-----
ui/dbus-listener.c | 16 +++
ui/gtk-egl.c | 12 +-
ui/shader.c | 1 +
ui/spice-display.c | 9 +-
ui/vdagent.c | 46 +++++++
audio/coreaudio.m | 204 ++++++++++++++++---------------
18 files changed, 288 insertions(+), 191 deletions(-)
--
2.53.0
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PULL 01/16] audio/mixeng: drop some needless checks
2026-03-17 17:19 [PULL 00/16] ui/audio/dump patches for 11.0-rc marcandre.lureau
@ 2026-03-17 17:19 ` marcandre.lureau
2026-03-17 17:19 ` [PULL 02/16] rutabaga: improve error handling, fix potential crash during init marcandre.lureau
` (15 subsequent siblings)
16 siblings, 0 replies; 18+ messages in thread
From: marcandre.lureau @ 2026-03-17 17:19 UTC (permalink / raw)
To: qemu-devel
Cc: Dmitry Osipenko, Marc-André Lureau, Michael S. Tsirkin,
Christian Schoenebeck, Ani Sinha, Alex Bennée,
Philippe Mathieu-Daudé, Gerd Hoffmann, Zhao Liu,
Marcel Apfelbaum, Yanan Wang, Akihiko Odaki
From: Marc-André Lureau <marcandre.lureau@redhat.com>
The NULL checks for be, name, callback_fn, and as in
audio_mixeng_backend_open_{in,out} are redundant: the callers
audio_be_open_{in,out} already assert that name, callback_fn, and as
are non-NULL, and dereference be unconditionally via
AUDIO_BACKEND_GET_CLASS(be) before the call.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Message-Id: <20260224163229.2918858-1-marcandre.lureau@redhat.com>
---
audio/audio_template.h | 6 ------
1 file changed, 6 deletions(-)
diff --git a/audio/audio_template.h b/audio/audio_template.h
index 228369cf9a1..fe769cde667 100644
--- a/audio/audio_template.h
+++ b/audio/audio_template.h
@@ -497,12 +497,6 @@ static SW *glue(audio_mixeng_backend_open_, TYPE) (
AudioMixengBackendClass *k;
AudiodevPerDirectionOptions *pdo;
- if (!be || !name || !callback_fn || !as) {
- audio_bug("backend=%p name=%p callback_fn=%p as=%p",
- be, name, callback_fn, as);
- goto fail;
- }
-
k = AUDIO_MIXENG_BACKEND_GET_CLASS(s);
pdo = glue(audio_get_pdo_, TYPE)(s->dev);
--
2.53.0
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PULL 02/16] rutabaga: improve error handling, fix potential crash during init
2026-03-17 17:19 [PULL 00/16] ui/audio/dump patches for 11.0-rc marcandre.lureau
2026-03-17 17:19 ` [PULL 01/16] audio/mixeng: drop some needless checks marcandre.lureau
@ 2026-03-17 17:19 ` marcandre.lureau
2026-03-17 17:19 ` [PULL 03/16] ui/vdagent: add migration blocker when machine version < 10.1 marcandre.lureau
` (14 subsequent siblings)
16 siblings, 0 replies; 18+ messages in thread
From: marcandre.lureau @ 2026-03-17 17:19 UTC (permalink / raw)
To: qemu-devel
Cc: Dmitry Osipenko, Marc-André Lureau, Michael S. Tsirkin,
Christian Schoenebeck, Ani Sinha, Alex Bennée,
Philippe Mathieu-Daudé, Gerd Hoffmann, Zhao Liu,
Marcel Apfelbaum, Yanan Wang, Akihiko Odaki
From: Marc-André Lureau <marcandre.lureau@redhat.com>
When virtio_gpu_rutabaga_get_num_capsets() returns 0, virtio_init()
isn't called and the device later crashes during realize.
==72545==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000 (pc 0x556ad6f7ba9e bp 0x7ffe6958f810 sp 0x7ffe6958f7e0 T0)
==72545==The signal is caused by a READ memory access.
==72545==Hint: address points to the zero page.
#0 0x556ad6f7ba9e in virtio_memory_listener_commit ../hw/virtio/virtio.c:4034
#1 0x556ad6a24c96 in listener_add_address_space ../system/memory.c:3128
#2 0x556ad6a25d15 in memory_listener_register ../system/memory.c:3216
#3 0x556ad6f7bf11 in virtio_device_realize ../hw/virtio/virtio.c:4075
Rework error handling of the function to set Error appropriately. 0
capset may be ok now.
Reviewed-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
hw/display/virtio-gpu-rutabaga.c | 19 +++++++++----------
1 file changed, 9 insertions(+), 10 deletions(-)
diff --git a/hw/display/virtio-gpu-rutabaga.c b/hw/display/virtio-gpu-rutabaga.c
index ed5ae52acbe..ebb6c783fb0 100644
--- a/hw/display/virtio-gpu-rutabaga.c
+++ b/hw/display/virtio-gpu-rutabaga.c
@@ -1032,19 +1032,19 @@ static bool virtio_gpu_rutabaga_init(VirtIOGPU *g, Error **errp)
return true;
}
-static int virtio_gpu_rutabaga_get_num_capsets(VirtIOGPU *g)
+static bool
+virtio_gpu_rutabaga_get_num_capsets(VirtIOGPU *g, uint32_t *num_capsets, Error **errp)
{
int result;
- uint32_t num_capsets;
VirtIOGPURutabaga *vr = VIRTIO_GPU_RUTABAGA(g);
- result = rutabaga_get_num_capsets(vr->rutabaga, &num_capsets);
+ result = rutabaga_get_num_capsets(vr->rutabaga, num_capsets);
if (result) {
- error_report("Failed to get capsets");
- return 0;
+ error_setg_errno(errp, -result, "Failed to get num_capsets");
+ return false;
}
- vr->num_capsets = num_capsets;
- return num_capsets;
+ vr->num_capsets = *num_capsets;
+ return true;
}
static void virtio_gpu_rutabaga_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq)
@@ -1070,7 +1070,7 @@ static void virtio_gpu_rutabaga_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq)
static void virtio_gpu_rutabaga_realize(DeviceState *qdev, Error **errp)
{
- int num_capsets;
+ uint32_t num_capsets;
VirtIOGPUBase *bdev = VIRTIO_GPU_BASE(qdev);
VirtIOGPU *gpudev = VIRTIO_GPU(qdev);
@@ -1083,8 +1083,7 @@ static void virtio_gpu_rutabaga_realize(DeviceState *qdev, Error **errp)
return;
}
- num_capsets = virtio_gpu_rutabaga_get_num_capsets(gpudev);
- if (!num_capsets) {
+ if (!virtio_gpu_rutabaga_get_num_capsets(gpudev, &num_capsets, errp)) {
return;
}
--
2.53.0
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PULL 03/16] ui/vdagent: add migration blocker when machine version < 10.1
2026-03-17 17:19 [PULL 00/16] ui/audio/dump patches for 11.0-rc marcandre.lureau
2026-03-17 17:19 ` [PULL 01/16] audio/mixeng: drop some needless checks marcandre.lureau
2026-03-17 17:19 ` [PULL 02/16] rutabaga: improve error handling, fix potential crash during init marcandre.lureau
@ 2026-03-17 17:19 ` marcandre.lureau
2026-03-17 17:19 ` [PULL 04/16] virtio-gpu: fix overflow check when allocating 2d image marcandre.lureau
` (13 subsequent siblings)
16 siblings, 0 replies; 18+ messages in thread
From: marcandre.lureau @ 2026-03-17 17:19 UTC (permalink / raw)
To: qemu-devel
Cc: Dmitry Osipenko, Marc-André Lureau, Michael S. Tsirkin,
Christian Schoenebeck, Ani Sinha, Alex Bennée,
Philippe Mathieu-Daudé, Gerd Hoffmann, Zhao Liu,
Marcel Apfelbaum, Yanan Wang, Akihiko Odaki, Fiona Ebner,
qemu-stable
From: Fiona Ebner <f.ebner@proxmox.com>
In QEMU 10.1, commit 5d56bff11e ("ui/vdagent: add migration support")
added migration support for the vdagent chardev and commit 42000e0013
("ui/vdagent: remove migration blocker") removed the migration
blocker. No compat for older machine versions was added, so migration
with pre-10.1 machine version, from a 10.1 binary to a pre-10.1 binary
will result in a failure when loading the VM state in the target
instance:
> Unknown savevm section or instance 'vdagent' 0. Make sure that your
> current VM setup matches your saved VM setup, including any
> hotplugged devices
Add a compat flag to block migration when the machine version is less
than 10.1 to avoid this.
Cc: qemu-stable@nongnu.org
Fixes: 42000e0013 ("ui/vdagent: remove migration blocker")
Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
Reviewed-by: Fabiano Rosas <farosas@suse.de>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-Id: <20260310142552.240877-1-f.ebner@proxmox.com>
---
hw/core/machine.c | 1 +
ui/vdagent.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 47 insertions(+)
diff --git a/hw/core/machine.c b/hw/core/machine.c
index a14ad05b9a6..6cf0e2f404e 100644
--- a/hw/core/machine.c
+++ b/hw/core/machine.c
@@ -57,6 +57,7 @@ GlobalProperty hw_compat_10_0[] = {
{ "vfio-pci", "x-migration-load-config-after-iter", "off" },
{ "ramfb", "use-legacy-x86-rom", "true"},
{ "vfio-pci-nohotplug", "use-legacy-x86-rom", "true" },
+ { "chardev-qemu-vdagent", "x-migration-blocked", "true" },
};
const size_t hw_compat_10_0_len = G_N_ELEMENTS(hw_compat_10_0);
diff --git a/ui/vdagent.c b/ui/vdagent.c
index 5a5e4bf6818..bb0c4aa14ca 100644
--- a/ui/vdagent.c
+++ b/ui/vdagent.c
@@ -6,6 +6,8 @@
#include "qemu/option.h"
#include "qemu/units.h"
#include "hw/core/qdev.h"
+#include "hw/core/qdev-properties.h"
+#include "migration/blocker.h"
#include "ui/clipboard.h"
#include "ui/console.h"
#include "ui/input.h"
@@ -24,6 +26,10 @@
struct VDAgentChardev {
Chardev parent;
+ /* needed for machine versions < 10.1 when migration was not supported */
+ Error *migration_blocker;
+ bool migration_blocked;
+
/* config */
bool mouse;
bool clipboard;
@@ -657,6 +663,12 @@ static bool vdagent_chr_open(Chardev *chr, ChardevBackend *backend,
return false;
#endif
+ if (vd->migration_blocked) {
+ if (migrate_add_blocker(&vd->migration_blocker, errp) != 0) {
+ return false;
+ }
+ }
+
vd->mouse = VDAGENT_MOUSE_DEFAULT;
if (cfg->has_mouse) {
vd->mouse = cfg->mouse;
@@ -901,6 +913,19 @@ static void vdagent_chr_parse(QemuOpts *opts, ChardevBackend *backend,
/* ------------------------------------------------------------------ */
+static bool get_migration_blocked(Object *o, Error **errp)
+{
+ VDAgentChardev *vd = QEMU_VDAGENT_CHARDEV(o);
+ return vd->migration_blocked;
+}
+
+static void set_migration_blocked(Object *o, bool migration_blocked,
+ Error **errp)
+{
+ VDAgentChardev *vd = QEMU_VDAGENT_CHARDEV(o);
+ vd->migration_blocked = migration_blocked;
+}
+
static void vdagent_chr_class_init(ObjectClass *oc, const void *data)
{
ChardevClass *cc = CHARDEV_CLASS(oc);
@@ -910,6 +935,10 @@ static void vdagent_chr_class_init(ObjectClass *oc, const void *data)
cc->chr_write = vdagent_chr_write;
cc->chr_set_fe_open = vdagent_chr_set_fe_open;
cc->chr_accept_input = vdagent_chr_accept_input;
+
+ object_class_property_add_bool(oc, "x-migration-blocked",
+ get_migration_blocked,
+ set_migration_blocked);
}
static int post_load(void *opaque, int version_id)
@@ -1064,10 +1093,26 @@ static void vdagent_chr_instance_init(Object *obj)
vmstate_register_any(NULL, &vmstate_vdagent, vd);
}
+static void vdagent_post_init(Object *obj)
+{
+ VDAgentChardev *vd = QEMU_VDAGENT_CHARDEV(obj);
+
+ object_apply_compat_props(obj);
+
+ if (vd->migration_blocked) {
+ error_setg(&vd->migration_blocker,
+ "The vdagent chardev doesn't support migration with machine"
+ " version less than 10.1");
+ }
+}
+
static void vdagent_chr_fini(Object *obj)
{
VDAgentChardev *vd = QEMU_VDAGENT_CHARDEV(obj);
+ if (vd->migration_blocked) {
+ migrate_del_blocker(&vd->migration_blocker);
+ }
vdagent_disconnect(vd);
if (vd->mouse_hs) {
qemu_input_handler_unregister(vd->mouse_hs);
@@ -1080,6 +1125,7 @@ static const TypeInfo vdagent_chr_type_info = {
.parent = TYPE_CHARDEV,
.instance_size = sizeof(VDAgentChardev),
.instance_init = vdagent_chr_instance_init,
+ .instance_post_init = vdagent_post_init,
.instance_finalize = vdagent_chr_fini,
.class_init = vdagent_chr_class_init,
};
--
2.53.0
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PULL 04/16] virtio-gpu: fix overflow check when allocating 2d image
2026-03-17 17:19 [PULL 00/16] ui/audio/dump patches for 11.0-rc marcandre.lureau
` (2 preceding siblings ...)
2026-03-17 17:19 ` [PULL 03/16] ui/vdagent: add migration blocker when machine version < 10.1 marcandre.lureau
@ 2026-03-17 17:19 ` marcandre.lureau
2026-03-17 17:19 ` [PULL 05/16] virtio-gpu: use computed rowstride instead of deriving it from hostmem marcandre.lureau
` (12 subsequent siblings)
16 siblings, 0 replies; 18+ messages in thread
From: marcandre.lureau @ 2026-03-17 17:19 UTC (permalink / raw)
To: qemu-devel
Cc: Dmitry Osipenko, Marc-André Lureau, Michael S. Tsirkin,
Christian Schoenebeck, Ani Sinha, Alex Bennée,
Philippe Mathieu-Daudé, Gerd Hoffmann, Zhao Liu,
Marcel Apfelbaum, Yanan Wang, Akihiko Odaki
From: Marc-André Lureau <marcandre.lureau@redhat.com>
The calc_image_hostmem() comment says pixman_image_create_bits() checks
for overflow. However, this relied on the facts that "bits" was NULL and
it performed it when it was introduced. Since commit 9462ff4695aa, the
"bits" argument can be provided and the check is no longer applied.
Promotes the computation to uint64_t and adds an explicit overflow check
to avoid potential later OOB read/write on the image data.
Fixes: CVE-2026-3886
Fixes: ZDI-CAN-27578
Fixes: 9462ff4695aa ("virtio-gpu/win32: allocate shareable 2d resources/images")
Reported-by: Zero Day Initiative <zdi-disclosures@trendmicro.com>
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
Message-Id: <20260311-cve-v1-1-f72b4c7c1ab2@redhat.com>
---
hw/display/virtio-gpu.c | 36 +++++++++++++++++++++++++-----------
1 file changed, 25 insertions(+), 11 deletions(-)
diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
index de7a86a73d2..468ea6ab0fb 100644
--- a/hw/display/virtio-gpu.c
+++ b/hw/display/virtio-gpu.c
@@ -227,16 +227,20 @@ void virtio_gpu_get_edid(VirtIOGPU *g,
virtio_gpu_ctrl_response(g, cmd, &edid.hdr, sizeof(edid));
}
-static uint32_t calc_image_hostmem(pixman_format_code_t pformat,
- uint32_t width, uint32_t height)
+static bool calc_image_hostmem(pixman_format_code_t pformat,
+ uint32_t width, uint32_t height,
+ uint32_t *hostmem)
{
- /* Copied from pixman/pixman-bits-image.c, skip integer overflow check.
- * pixman_image_create_bits will fail in case it overflow.
- */
+ uint64_t bpp = PIXMAN_FORMAT_BPP(pformat);
+ uint64_t stride = (((uint64_t)width * bpp + 0x1f) >> 5) * sizeof(uint32_t);
+ uint64_t size = (uint64_t)height * stride;
- int bpp = PIXMAN_FORMAT_BPP(pformat);
- int stride = ((width * bpp + 0x1f) >> 5) * sizeof(uint32_t);
- return height * stride;
+ if (size > UINT32_MAX) {
+ return false;
+ }
+
+ *hostmem = size;
+ return true;
}
static void virtio_gpu_resource_create_2d(VirtIOGPU *g,
@@ -246,6 +250,7 @@ static void virtio_gpu_resource_create_2d(VirtIOGPU *g,
pixman_format_code_t pformat;
struct virtio_gpu_simple_resource *res;
struct virtio_gpu_resource_create_2d c2d;
+ uint32_t hostmem;
VIRTIO_GPU_FILL_CMD(c2d);
virtio_gpu_bswap_32(&c2d, sizeof(c2d));
@@ -284,7 +289,12 @@ static void virtio_gpu_resource_create_2d(VirtIOGPU *g,
return;
}
- res->hostmem = calc_image_hostmem(pformat, c2d.width, c2d.height);
+ if (!calc_image_hostmem(pformat, c2d.width, c2d.height, &hostmem)) {
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: image dimensions overflow\n",
+ __func__);
+ goto end;
+ }
+ res->hostmem = hostmem;
if (res->hostmem + g->hostmem < g->conf_max_hostmem) {
if (!qemu_pixman_image_new_shareable(
&res->image,
@@ -1292,7 +1302,7 @@ static int virtio_gpu_load(QEMUFile *f, void *opaque, size_t size,
VirtIOGPU *g = opaque;
Error *err = NULL;
struct virtio_gpu_simple_resource *res;
- uint32_t resource_id, pformat;
+ uint32_t resource_id, pformat, hostmem;
int i, ret;
g->hostmem = 0;
@@ -1318,7 +1328,11 @@ static int virtio_gpu_load(QEMUFile *f, void *opaque, size_t size,
return -EINVAL;
}
- res->hostmem = calc_image_hostmem(pformat, res->width, res->height);
+ if (!calc_image_hostmem(pformat, res->width, res->height, &hostmem)) {
+ g_free(res);
+ return -EINVAL;
+ }
+ res->hostmem = hostmem;
if (!qemu_pixman_image_new_shareable(&res->image,
&res->share_handle,
"virtio-gpu res",
--
2.53.0
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PULL 05/16] virtio-gpu: use computed rowstride instead of deriving it from hostmem
2026-03-17 17:19 [PULL 00/16] ui/audio/dump patches for 11.0-rc marcandre.lureau
` (3 preceding siblings ...)
2026-03-17 17:19 ` [PULL 04/16] virtio-gpu: fix overflow check when allocating 2d image marcandre.lureau
@ 2026-03-17 17:19 ` marcandre.lureau
2026-03-17 17:19 ` [PULL 06/16] ui/dbus-listener: Fix FBO leak in dbus_cursor_dmabuf marcandre.lureau
` (11 subsequent siblings)
16 siblings, 0 replies; 18+ messages in thread
From: marcandre.lureau @ 2026-03-17 17:19 UTC (permalink / raw)
To: qemu-devel
Cc: Dmitry Osipenko, Marc-André Lureau, Michael S. Tsirkin,
Christian Schoenebeck, Ani Sinha, Alex Bennée,
Philippe Mathieu-Daudé, Gerd Hoffmann, Zhao Liu,
Marcel Apfelbaum, Yanan Wang, Akihiko Odaki
From: Marc-André Lureau <marcandre.lureau@redhat.com>
Since calc_image_hostmem() already computes the stride, return it and
use it directly. This is both simpler and more correct.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
Message-Id: <20260311-cve-v1-2-f72b4c7c1ab2@redhat.com>
---
hw/display/virtio-gpu.c | 17 ++++++++++-------
1 file changed, 10 insertions(+), 7 deletions(-)
diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
index 468ea6ab0fb..b998ce8324d 100644
--- a/hw/display/virtio-gpu.c
+++ b/hw/display/virtio-gpu.c
@@ -229,7 +229,7 @@ void virtio_gpu_get_edid(VirtIOGPU *g,
static bool calc_image_hostmem(pixman_format_code_t pformat,
uint32_t width, uint32_t height,
- uint32_t *hostmem)
+ uint32_t *hostmem, uint32_t *rowstride_bytes)
{
uint64_t bpp = PIXMAN_FORMAT_BPP(pformat);
uint64_t stride = (((uint64_t)width * bpp + 0x1f) >> 5) * sizeof(uint32_t);
@@ -240,6 +240,7 @@ static bool calc_image_hostmem(pixman_format_code_t pformat,
}
*hostmem = size;
+ *rowstride_bytes = stride;
return true;
}
@@ -250,7 +251,7 @@ static void virtio_gpu_resource_create_2d(VirtIOGPU *g,
pixman_format_code_t pformat;
struct virtio_gpu_simple_resource *res;
struct virtio_gpu_resource_create_2d c2d;
- uint32_t hostmem;
+ uint32_t hostmem, rowstride_bytes;
VIRTIO_GPU_FILL_CMD(c2d);
virtio_gpu_bswap_32(&c2d, sizeof(c2d));
@@ -289,7 +290,8 @@ static void virtio_gpu_resource_create_2d(VirtIOGPU *g,
return;
}
- if (!calc_image_hostmem(pformat, c2d.width, c2d.height, &hostmem)) {
+ if (!calc_image_hostmem(pformat, c2d.width, c2d.height,
+ &hostmem, &rowstride_bytes)) {
qemu_log_mask(LOG_GUEST_ERROR, "%s: image dimensions overflow\n",
__func__);
goto end;
@@ -303,7 +305,7 @@ static void virtio_gpu_resource_create_2d(VirtIOGPU *g,
pformat,
c2d.width,
c2d.height,
- c2d.height ? res->hostmem / c2d.height : 0,
+ rowstride_bytes,
&err)) {
warn_report_err(err);
goto end;
@@ -1302,7 +1304,7 @@ static int virtio_gpu_load(QEMUFile *f, void *opaque, size_t size,
VirtIOGPU *g = opaque;
Error *err = NULL;
struct virtio_gpu_simple_resource *res;
- uint32_t resource_id, pformat, hostmem;
+ uint32_t resource_id, pformat, hostmem, rowstride_bytes;
int i, ret;
g->hostmem = 0;
@@ -1328,7 +1330,8 @@ static int virtio_gpu_load(QEMUFile *f, void *opaque, size_t size,
return -EINVAL;
}
- if (!calc_image_hostmem(pformat, res->width, res->height, &hostmem)) {
+ if (!calc_image_hostmem(pformat, res->width, res->height,
+ &hostmem, &rowstride_bytes)) {
g_free(res);
return -EINVAL;
}
@@ -1339,7 +1342,7 @@ static int virtio_gpu_load(QEMUFile *f, void *opaque, size_t size,
pformat,
res->width,
res->height,
- res->height ? res->hostmem / res->height : 0,
+ rowstride_bytes,
&err)) {
warn_report_err(err);
g_free(res);
--
2.53.0
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PULL 06/16] ui/dbus-listener: Fix FBO leak in dbus_cursor_dmabuf
2026-03-17 17:19 [PULL 00/16] ui/audio/dump patches for 11.0-rc marcandre.lureau
` (4 preceding siblings ...)
2026-03-17 17:19 ` [PULL 05/16] virtio-gpu: use computed rowstride instead of deriving it from hostmem marcandre.lureau
@ 2026-03-17 17:19 ` marcandre.lureau
2026-03-17 17:19 ` [PULL 07/16] ui/dbus-listener: remove dbus_filter on connection close marcandre.lureau
` (10 subsequent siblings)
16 siblings, 0 replies; 18+ messages in thread
From: marcandre.lureau @ 2026-03-17 17:19 UTC (permalink / raw)
To: qemu-devel
Cc: Dmitry Osipenko, Marc-André Lureau, Michael S. Tsirkin,
Christian Schoenebeck, Ani Sinha, Alex Bennée,
Philippe Mathieu-Daudé, Gerd Hoffmann, Zhao Liu,
Marcel Apfelbaum, Yanan Wang, Akihiko Odaki
From: Marc-André Lureau <marcandre.lureau@redhat.com>
cursor_fb is a local egl_fb that gets an FBO allocated via
egl_fb_setup_for_tex but is never destroyed, leaking the
framebuffer object on every cursor update.
Add egl_fb_destroy() after the cursor data has been read.
Fixes: commit 142ca628a7 ("ui: add a D-Bus display backend")
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
ui/dbus-listener.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/ui/dbus-listener.c b/ui/dbus-listener.c
index 3e2b4adf41f..fff7cf83274 100644
--- a/ui/dbus-listener.c
+++ b/ui/dbus-listener.c
@@ -660,6 +660,7 @@ static void dbus_cursor_dmabuf(DisplayChangeListener *dcl,
egl_fb_setup_for_tex(&cursor_fb, width, height, texture, false);
ds = qemu_create_displaysurface(width, height);
egl_fb_read(ds, &cursor_fb);
+ egl_fb_destroy(&cursor_fb);
v_data = g_variant_new_from_data(
G_VARIANT_TYPE("ay"),
--
2.53.0
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PULL 07/16] ui/dbus-listener: remove dbus_filter on connection close
2026-03-17 17:19 [PULL 00/16] ui/audio/dump patches for 11.0-rc marcandre.lureau
` (5 preceding siblings ...)
2026-03-17 17:19 ` [PULL 06/16] ui/dbus-listener: Fix FBO leak in dbus_cursor_dmabuf marcandre.lureau
@ 2026-03-17 17:19 ` marcandre.lureau
2026-03-17 17:19 ` [PULL 08/16] ui/gtk-egl: Ensure EGL surface is available before drawing marcandre.lureau
` (9 subsequent siblings)
16 siblings, 0 replies; 18+ messages in thread
From: marcandre.lureau @ 2026-03-17 17:19 UTC (permalink / raw)
To: qemu-devel
Cc: Dmitry Osipenko, Marc-André Lureau, Michael S. Tsirkin,
Christian Schoenebeck, Ani Sinha, Alex Bennée,
Philippe Mathieu-Daudé, Gerd Hoffmann, Zhao Liu,
Marcel Apfelbaum, Yanan Wang, Akihiko Odaki
From: Marc-André Lureau <marcandre.lureau@redhat.com>
The dbus filter holds a strong reference to the DBusDisplayListener
(via GDestroyNotify) to ensure the listener remains alive while the
filter may still be running in another thread. This creates a
reference cycle (ddl -> conn -> filter -> ddl) that prevents the
listener from being freed.
Break the cycle by connecting to the connection's "closed" signal
and removing the filter when the connection closes.
Fixes: commit fa88b85dea96 ("ui/dbus: filter out pending messages when scanout")
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
ui/dbus-listener.c | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/ui/dbus-listener.c b/ui/dbus-listener.c
index fff7cf83274..37945236e11 100644
--- a/ui/dbus-listener.c
+++ b/ui/dbus-listener.c
@@ -1181,6 +1181,20 @@ static void dbus_display_listener_setup_scanout_dmabuf_v2(DBusDisplayListener *d
#endif
}
+static void
+dbus_conn_closed(GDBusConnection *conn,
+ gboolean remote_peer_vanished,
+ GError *error,
+ gpointer user_data)
+{
+ DBusDisplayListener *ddl = DBUS_DISPLAY_LISTENER(user_data);
+
+ if (ddl->dbus_filter) {
+ g_dbus_connection_remove_filter(ddl->conn, ddl->dbus_filter);
+ ddl->dbus_filter = 0;
+ }
+}
+
static GDBusMessage *
dbus_filter(GDBusConnection *connection,
GDBusMessage *message,
@@ -1262,6 +1276,7 @@ dbus_display_listener_new(const char *bus_name,
}
ddl->dbus_filter = g_dbus_connection_add_filter(conn, dbus_filter, g_object_ref(ddl), g_object_unref);
+ g_signal_connect(conn, "closed", G_CALLBACK(dbus_conn_closed), ddl);
ddl->bus_name = g_strdup(bus_name);
ddl->conn = conn;
ddl->console = console;
--
2.53.0
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PULL 08/16] ui/gtk-egl: Ensure EGL surface is available before drawing
2026-03-17 17:19 [PULL 00/16] ui/audio/dump patches for 11.0-rc marcandre.lureau
` (6 preceding siblings ...)
2026-03-17 17:19 ` [PULL 07/16] ui/dbus-listener: remove dbus_filter on connection close marcandre.lureau
@ 2026-03-17 17:19 ` marcandre.lureau
2026-03-17 17:19 ` [PULL 09/16] dump: enhance dump_state_prepare fd initialization marcandre.lureau
` (8 subsequent siblings)
16 siblings, 0 replies; 18+ messages in thread
From: marcandre.lureau @ 2026-03-17 17:19 UTC (permalink / raw)
To: qemu-devel
Cc: Dmitry Osipenko, Marc-André Lureau, Michael S. Tsirkin,
Christian Schoenebeck, Ani Sinha, Alex Bennée,
Philippe Mathieu-Daudé, Gerd Hoffmann, Zhao Liu,
Marcel Apfelbaum, Yanan Wang, Akihiko Odaki, Dongwon Kim,
Vivek Kasireddy
From: Dongwon Kim <dongwon.kim@intel.com>
The EGL surface and context are destroyed when a new GTK window is
created. We must ensure these are recreated and initialized before
any rendering happens in gd_egl_refresh.
Currently, the check for a pending draw is performed before the
surface initialization block. This can result in an attempt to
draw when the EGL surface (vc->gfx.esurface) is not yet available.
This patch moves the drawing check after the surface initialization
to ensure a valid surface exists before rendering in gd_egl_refresh.
Cc: Gerd Hoffmann <kraxel@redhat.com>
Cc: Marc-André Lureau <marcandre.lureau@redhat.com>
Signed-off-by: Vivek Kasireddy <vivek.kasireddy@intel.com>
Signed-off-by: Dongwon Kim <dongwon.kim@intel.com>
Acked-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-Id: <20260303011151.1925827-1-dongwon.kim@intel.com>
---
ui/gtk-egl.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/ui/gtk-egl.c b/ui/gtk-egl.c
index 1b5c1d4533c..fa8fe8970c1 100644
--- a/ui/gtk-egl.c
+++ b/ui/gtk-egl.c
@@ -152,12 +152,6 @@ void gd_egl_refresh(DisplayChangeListener *dcl)
gd_update_monitor_refresh_rate(
vc, vc->window ? vc->window : vc->gfx.drawing_area);
- if (vc->gfx.guest_fb.dmabuf &&
- qemu_dmabuf_get_draw_submitted(vc->gfx.guest_fb.dmabuf)) {
- gd_egl_draw(vc);
- return;
- }
-
if (!vc->gfx.esurface) {
gd_egl_init(vc);
if (!vc->gfx.esurface) {
@@ -176,6 +170,12 @@ void gd_egl_refresh(DisplayChangeListener *dcl)
#endif
}
+ if (vc->gfx.guest_fb.dmabuf &&
+ qemu_dmabuf_get_draw_submitted(vc->gfx.guest_fb.dmabuf)) {
+ gd_egl_draw(vc);
+ return;
+ }
+
graphic_hw_update(dcl->con);
if (vc->gfx.glupdates) {
--
2.53.0
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PULL 09/16] dump: enhance dump_state_prepare fd initialization
2026-03-17 17:19 [PULL 00/16] ui/audio/dump patches for 11.0-rc marcandre.lureau
` (7 preceding siblings ...)
2026-03-17 17:19 ` [PULL 08/16] ui/gtk-egl: Ensure EGL surface is available before drawing marcandre.lureau
@ 2026-03-17 17:19 ` marcandre.lureau
2026-03-17 17:19 ` [PULL 10/16] ui/console: Unify pixman-OpenGL format mapping marcandre.lureau
` (7 subsequent siblings)
16 siblings, 0 replies; 18+ messages in thread
From: marcandre.lureau @ 2026-03-17 17:19 UTC (permalink / raw)
To: qemu-devel
Cc: Dmitry Osipenko, Marc-André Lureau, Michael S. Tsirkin,
Christian Schoenebeck, Ani Sinha, Alex Bennée,
Philippe Mathieu-Daudé, Gerd Hoffmann, Zhao Liu,
Marcel Apfelbaum, Yanan Wang, Akihiko Odaki, Nikolai Barybin
From: Nikolai Barybin <nikolai.barybin@virtuozzo.com>
Initializing descriptor with zero is unsafe: during cleanup we risk to
unconditional close of fd == 0 in case dump state wasn't fully
initialized. Thus, let's init fd with -1 value and check its value
before closing it.
Signed-off-by: Nikolai Barybin <nikolai.barybin@virtuozzo.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-Id: <20250911123656.413160-2-nikolai.barybin@virtuozzo.com>
---
dump/dump.c | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/dump/dump.c b/dump/dump.c
index 80ed6c8d219..1f216e74f5f 100644
--- a/dump/dump.c
+++ b/dump/dump.c
@@ -104,7 +104,10 @@ static int dump_cleanup(DumpState *s)
guest_phys_blocks_free(&s->guest_phys_blocks);
memory_mapping_list_free(&s->list);
- close(s->fd);
+ if (s->fd != -1) {
+ close(s->fd);
+ }
+ s->fd = -1;
g_free(s->guest_note);
g_clear_pointer(&s->string_table_buf, g_array_unref);
s->guest_note = NULL;
@@ -1709,8 +1712,8 @@ static DumpState dump_state_global = { .status = DUMP_STATUS_NONE };
static void dump_state_prepare(DumpState *s)
{
- /* zero the struct, setting status to active */
- *s = (DumpState) { .status = DUMP_STATUS_ACTIVE };
+ /* zero the struct, setting status to active and fd to -1 */
+ *s = (DumpState) { .fd = -1, .status = DUMP_STATUS_ACTIVE };
}
bool qemu_system_dump_in_progress(void)
--
2.53.0
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PULL 10/16] ui/console: Unify pixman-OpenGL format mapping
2026-03-17 17:19 [PULL 00/16] ui/audio/dump patches for 11.0-rc marcandre.lureau
` (8 preceding siblings ...)
2026-03-17 17:19 ` [PULL 09/16] dump: enhance dump_state_prepare fd initialization marcandre.lureau
@ 2026-03-17 17:19 ` marcandre.lureau
2026-03-17 17:19 ` [PULL 11/16] ui/console: Remove DisplaySurface::mem_obj marcandre.lureau
` (6 subsequent siblings)
16 siblings, 0 replies; 18+ messages in thread
From: marcandre.lureau @ 2026-03-17 17:19 UTC (permalink / raw)
To: qemu-devel
Cc: Dmitry Osipenko, Marc-André Lureau, Michael S. Tsirkin,
Christian Schoenebeck, Ani Sinha, Alex Bennée,
Philippe Mathieu-Daudé, Gerd Hoffmann, Zhao Liu,
Marcel Apfelbaum, Yanan Wang, Akihiko Odaki
From: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
console_gl_check_format() was supposed to check if the pixman format is
supported by surface_gl_create_texture(), but it missed
PIXMAN_BE_x8r8g8b8 and PIXMAN_BE_a8r8g8b8, which are properly mapped to
OpenGL formats by surface_gl_create_texture().
Fix the discrepancy of the two functions by sharing the code to map
pixman formats to OpenGL ones.
Signed-off-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-Id: <20260303-gl-v1-1-d90f0a237a52@rsg.ci.i.u-tokyo.ac.jp>
---
ui/console-gl.c | 43 ++++++++++++++++++++++---------------------
1 file changed, 22 insertions(+), 21 deletions(-)
diff --git a/ui/console-gl.c b/ui/console-gl.c
index 403fc36fbdf..22e9787c415 100644
--- a/ui/console-gl.c
+++ b/ui/console-gl.c
@@ -31,19 +31,38 @@
/* ---------------------------------------------------------------------- */
-bool console_gl_check_format(DisplayChangeListener *dcl,
- pixman_format_code_t format)
+static bool map_format(pixman_format_code_t format,
+ GLenum *glformat, GLenum *gltype)
{
switch (format) {
case PIXMAN_BE_b8g8r8x8:
case PIXMAN_BE_b8g8r8a8:
+ *glformat = GL_BGRA_EXT;
+ *gltype = GL_UNSIGNED_BYTE;
+ return true;
+ case PIXMAN_BE_x8r8g8b8:
+ case PIXMAN_BE_a8r8g8b8:
+ *glformat = GL_RGBA;
+ *gltype = GL_UNSIGNED_BYTE;
+ return true;
case PIXMAN_r5g6b5:
+ *glformat = GL_RGB;
+ *gltype = GL_UNSIGNED_SHORT_5_6_5;
return true;
default:
return false;
}
}
+bool console_gl_check_format(DisplayChangeListener *dcl,
+ pixman_format_code_t format)
+{
+ GLenum glformat;
+ GLenum gltype;
+
+ return map_format(format, &glformat, &gltype);
+}
+
void surface_gl_create_texture(QemuGLShader *gls,
DisplaySurface *surface)
{
@@ -54,25 +73,7 @@ void surface_gl_create_texture(QemuGLShader *gls,
return;
}
- switch (surface_format(surface)) {
- case PIXMAN_BE_b8g8r8x8:
- case PIXMAN_BE_b8g8r8a8:
- surface->glformat = GL_BGRA_EXT;
- surface->gltype = GL_UNSIGNED_BYTE;
- break;
- case PIXMAN_BE_x8r8g8b8:
- case PIXMAN_BE_a8r8g8b8:
- surface->glformat = GL_RGBA;
- surface->gltype = GL_UNSIGNED_BYTE;
- break;
- case PIXMAN_r5g6b5:
- surface->glformat = GL_RGB;
- surface->gltype = GL_UNSIGNED_SHORT_5_6_5;
- break;
- default:
- g_assert_not_reached();
- }
-
+ assert(map_format(surface_format(surface), &surface->glformat, &surface->gltype));
glGenTextures(1, &surface->texture);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, surface->texture);
--
2.53.0
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PULL 11/16] ui/console: Remove DisplaySurface::mem_obj
2026-03-17 17:19 [PULL 00/16] ui/audio/dump patches for 11.0-rc marcandre.lureau
` (9 preceding siblings ...)
2026-03-17 17:19 ` [PULL 10/16] ui/console: Unify pixman-OpenGL format mapping marcandre.lureau
@ 2026-03-17 17:19 ` marcandre.lureau
2026-03-17 17:19 ` [PULL 12/16] ui/surface: Avoid including epoxy/gl.h in header files marcandre.lureau
` (5 subsequent siblings)
16 siblings, 0 replies; 18+ messages in thread
From: marcandre.lureau @ 2026-03-17 17:19 UTC (permalink / raw)
To: qemu-devel
Cc: Dmitry Osipenko, Marc-André Lureau, Michael S. Tsirkin,
Christian Schoenebeck, Ani Sinha, Alex Bennée,
Philippe Mathieu-Daudé, Gerd Hoffmann, Zhao Liu,
Marcel Apfelbaum, Yanan Wang, Akihiko Odaki
From: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
Only spice uses it so move it to spice.
Signed-off-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-Id: <20260303-gl-v1-2-d90f0a237a52@rsg.ci.i.u-tokyo.ac.jp>
---
include/ui/spice-display.h | 1 +
include/ui/surface.h | 1 -
ui/console-gl.c | 6 ------
ui/spice-display.c | 9 ++++++++-
4 files changed, 9 insertions(+), 8 deletions(-)
diff --git a/include/ui/spice-display.h b/include/ui/spice-display.h
index 690ece73801..a382553fa8e 100644
--- a/include/ui/spice-display.h
+++ b/include/ui/spice-display.h
@@ -121,6 +121,7 @@ struct SimpleSpiceDisplay {
QEMUBH *gl_unblock_bh;
QEMUTimer *gl_unblock_timer;
QemuGLShader *gls;
+ GLuint gl_surface_mem_obj;
int gl_updates;
bool have_scanout;
bool have_surface;
diff --git a/include/ui/surface.h b/include/ui/surface.h
index 006b1986bb9..f16f7be8be8 100644
--- a/include/ui/surface.h
+++ b/include/ui/surface.h
@@ -22,7 +22,6 @@ typedef struct DisplaySurface {
GLenum glformat;
GLenum gltype;
GLuint texture;
- GLuint mem_obj;
#endif
qemu_pixman_shareable share_handle;
uint32_t share_handle_offset;
diff --git a/ui/console-gl.c b/ui/console-gl.c
index 22e9787c415..73be35c1fc7 100644
--- a/ui/console-gl.c
+++ b/ui/console-gl.c
@@ -185,12 +185,6 @@ void surface_gl_destroy_texture(QemuGLShader *gls,
}
glDeleteTextures(1, &surface->texture);
surface->texture = 0;
-#ifdef GL_EXT_memory_object_fd
- if (surface->mem_obj) {
- glDeleteMemoryObjectsEXT(1, &surface->mem_obj);
- surface->mem_obj = 0;
- }
-#endif
}
void surface_gl_setup_viewport(QemuGLShader *gls,
diff --git a/ui/spice-display.c b/ui/spice-display.c
index 5052f371f44..87cc193cdee 100644
--- a/ui/spice-display.c
+++ b/ui/spice-display.c
@@ -950,7 +950,14 @@ static bool spice_gl_replace_fd_texture(SimpleSpiceDisplay *ssd,
} else {
surface_gl_destroy_texture(ssd->gls, ssd->ds);
ssd->ds->texture = texture;
- ssd->ds->mem_obj = mem_obj;
+
+#ifdef GL_EXT_memory_object_fd
+ if (ssd->gl_surface_mem_obj) {
+ glDeleteMemoryObjectsEXT(1, &ssd->gl_surface_mem_obj);
+ }
+
+ ssd->gl_surface_mem_obj = mem_obj;
+#endif
}
return ret;
}
--
2.53.0
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PULL 12/16] ui/surface: Avoid including epoxy/gl.h in header files
2026-03-17 17:19 [PULL 00/16] ui/audio/dump patches for 11.0-rc marcandre.lureau
` (10 preceding siblings ...)
2026-03-17 17:19 ` [PULL 11/16] ui/console: Remove DisplaySurface::mem_obj marcandre.lureau
@ 2026-03-17 17:19 ` marcandre.lureau
2026-03-17 17:19 ` [PULL 13/16] coreaudio: Improve naming marcandre.lureau
` (4 subsequent siblings)
16 siblings, 0 replies; 18+ messages in thread
From: marcandre.lureau @ 2026-03-17 17:19 UTC (permalink / raw)
To: qemu-devel
Cc: Dmitry Osipenko, Marc-André Lureau, Michael S. Tsirkin,
Christian Schoenebeck, Ani Sinha, Alex Bennée,
Philippe Mathieu-Daudé, Gerd Hoffmann, Zhao Liu,
Marcel Apfelbaum, Yanan Wang, Akihiko Odaki
From: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
include/ui/shader.h and include/ui/surface.h are included by files that
do not depend on Epoxy so they shouldn't include epoxy/gl.h. Otherwise,
compilations of these files can fail because the path to the directory
containing epoxy/gl.h may not be passed to the compiler.
Signed-off-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-Id: <20260303-gl-v1-3-d90f0a237a52@rsg.ci.i.u-tokyo.ac.jp>
---
include/ui/console.h | 4 ++--
include/ui/shader.h | 2 --
include/ui/surface.h | 5 +----
ui/console-gl.c | 27 ++++++++++++++-------------
ui/shader.c | 1 +
5 files changed, 18 insertions(+), 21 deletions(-)
diff --git a/include/ui/console.h b/include/ui/console.h
index 3677a9d334d..08082389f71 100644
--- a/include/ui/console.h
+++ b/include/ui/console.h
@@ -423,8 +423,8 @@ bool console_gl_check_format(DisplayChangeListener *dcl,
void surface_gl_create_texture(QemuGLShader *gls,
DisplaySurface *surface);
bool surface_gl_create_texture_from_fd(DisplaySurface *surface,
- int fd, GLuint *texture,
- GLuint *mem_obj);
+ int fd, uint32_t *texture,
+ uint32_t *mem_obj);
void surface_gl_update_texture(QemuGLShader *gls,
DisplaySurface *surface,
int x, int y, int w, int h);
diff --git a/include/ui/shader.h b/include/ui/shader.h
index 4c5acb2ce8b..e82213263c4 100644
--- a/include/ui/shader.h
+++ b/include/ui/shader.h
@@ -1,8 +1,6 @@
#ifndef QEMU_SHADER_H
#define QEMU_SHADER_H
-#include <epoxy/gl.h>
-
typedef struct QemuGLShader QemuGLShader;
void qemu_gl_run_texture_blit(QemuGLShader *gls, bool flip);
diff --git a/include/ui/surface.h b/include/ui/surface.h
index f16f7be8be8..d2542d3ace5 100644
--- a/include/ui/surface.h
+++ b/include/ui/surface.h
@@ -8,7 +8,6 @@
#include "ui/qemu-pixman.h"
#ifdef CONFIG_OPENGL
-# include <epoxy/gl.h>
# include "ui/shader.h"
#endif
@@ -19,9 +18,7 @@ typedef struct DisplaySurface {
pixman_image_t *image;
uint8_t flags;
#ifdef CONFIG_OPENGL
- GLenum glformat;
- GLenum gltype;
- GLuint texture;
+ uint32_t texture;
#endif
qemu_pixman_shareable share_handle;
uint32_t share_handle_offset;
diff --git a/ui/console-gl.c b/ui/console-gl.c
index 73be35c1fc7..d4b9017b53d 100644
--- a/ui/console-gl.c
+++ b/ui/console-gl.c
@@ -25,6 +25,7 @@
* THE SOFTWARE.
*/
#include "qemu/osdep.h"
+#include <epoxy/gl.h>
#include "qemu/error-report.h"
#include "ui/console.h"
#include "ui/shader.h"
@@ -66,6 +67,9 @@ bool console_gl_check_format(DisplayChangeListener *dcl,
void surface_gl_create_texture(QemuGLShader *gls,
DisplaySurface *surface)
{
+ GLenum glformat;
+ GLenum gltype;
+
assert(gls);
assert(QEMU_IS_ALIGNED(surface_stride(surface), surface_bytes_per_pixel(surface)));
@@ -73,7 +77,7 @@ void surface_gl_create_texture(QemuGLShader *gls,
return;
}
- assert(map_format(surface_format(surface), &surface->glformat, &surface->gltype));
+ assert(map_format(surface_format(surface), &glformat, &gltype));
glGenTextures(1, &surface->texture);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, surface->texture);
@@ -81,16 +85,12 @@ void surface_gl_create_texture(QemuGLShader *gls,
surface_stride(surface) / surface_bytes_per_pixel(surface));
if (epoxy_is_desktop_gl()) {
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB,
- surface_width(surface),
- surface_height(surface),
- 0, surface->glformat, surface->gltype,
- surface_data(surface));
+ surface_width(surface), surface_height(surface), 0,
+ glformat, gltype, surface_data(surface));
} else {
- glTexImage2D(GL_TEXTURE_2D, 0, surface->glformat,
- surface_width(surface),
- surface_height(surface),
- 0, surface->glformat, surface->gltype,
- surface_data(surface));
+ glTexImage2D(GL_TEXTURE_2D, 0, glformat,
+ surface_width(surface), surface_height(surface), 0,
+ glformat, gltype, surface_data(surface));
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, GL_ONE);
}
@@ -150,17 +150,18 @@ void surface_gl_update_texture(QemuGLShader *gls,
int x, int y, int w, int h)
{
uint8_t *data = (void *)surface_data(surface);
+ GLenum glformat;
+ GLenum gltype;
assert(gls);
+ assert(map_format(surface_format(surface), &glformat, &gltype));
if (surface->texture) {
glBindTexture(GL_TEXTURE_2D, surface->texture);
glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT,
surface_stride(surface)
/ surface_bytes_per_pixel(surface));
- glTexSubImage2D(GL_TEXTURE_2D, 0,
- x, y, w, h,
- surface->glformat, surface->gltype,
+ glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h, glformat, gltype,
data + surface_stride(surface) * y
+ surface_bytes_per_pixel(surface) * x);
}
diff --git a/ui/shader.c b/ui/shader.c
index ab448c41d4c..76ee4c32785 100644
--- a/ui/shader.c
+++ b/ui/shader.c
@@ -25,6 +25,7 @@
* THE SOFTWARE.
*/
#include "qemu/osdep.h"
+#include <epoxy/gl.h>
#include "ui/shader.h"
#include "ui/shader/texture-blit-vert.h"
--
2.53.0
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PULL 13/16] coreaudio: Improve naming
2026-03-17 17:19 [PULL 00/16] ui/audio/dump patches for 11.0-rc marcandre.lureau
` (11 preceding siblings ...)
2026-03-17 17:19 ` [PULL 12/16] ui/surface: Avoid including epoxy/gl.h in header files marcandre.lureau
@ 2026-03-17 17:19 ` marcandre.lureau
2026-03-17 17:19 ` [PULL 14/16] coreaudio: Commit the result of init in the end marcandre.lureau
` (3 subsequent siblings)
16 siblings, 0 replies; 18+ messages in thread
From: marcandre.lureau @ 2026-03-17 17:19 UTC (permalink / raw)
To: qemu-devel
Cc: Dmitry Osipenko, Marc-André Lureau, Michael S. Tsirkin,
Christian Schoenebeck, Ani Sinha, Alex Bennée,
Philippe Mathieu-Daudé, Gerd Hoffmann, Zhao Liu,
Marcel Apfelbaum, Yanan Wang, Akihiko Odaki
From: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
coreaudio had names that are not conforming to QEMU codding style.
coreaudioVoiceOut also had some members that are prefixed with redundant
words like "output" or "audio".
Global names included "out" to tell they are specific to output devices,
but this rule was not completely enforced.
The frame size had three different names "frameSize", "bufferFrameSize",
and "frameCount".
Replace identifiers to fix these problems.
Signed-off-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-Id: <20260304-coreaudio-v8-3-bf1d40731e73@rsg.ci.i.u-tokyo.ac.jp>
---
audio/coreaudio.m | 188 +++++++++++++++++++++++-----------------------
1 file changed, 95 insertions(+), 93 deletions(-)
diff --git a/audio/coreaudio.m b/audio/coreaudio.m
index bc9ab7477b6..736227eb2b7 100644
--- a/audio/coreaudio.m
+++ b/audio/coreaudio.m
@@ -43,34 +43,34 @@
typedef struct coreaudioVoiceOut {
HWVoiceOut hw;
pthread_mutex_t buf_mutex;
- AudioDeviceID outputDeviceID;
- int frameSizeSetting;
- uint32_t bufferCount;
- UInt32 audioDevicePropertyBufferFrameSize;
+ AudioDeviceID device_id;
+ int frame_size_setting;
+ uint32_t buffer_count;
+ UInt32 device_frame_size;
AudioDeviceIOProcID ioprocid;
bool enabled;
-} coreaudioVoiceOut;
+} CoreaudioVoiceOut;
-static const AudioObjectPropertyAddress voice_addr = {
+static const AudioObjectPropertyAddress voice_out_addr = {
kAudioHardwarePropertyDefaultOutputDevice,
kAudioObjectPropertyScopeGlobal,
kAudioObjectPropertyElementMain
};
-static OSStatus coreaudio_get_voice(AudioDeviceID *id)
+static OSStatus coreaudio_get_voice_out(AudioDeviceID *id)
{
UInt32 size = sizeof(*id);
return AudioObjectGetPropertyData(kAudioObjectSystemObject,
- &voice_addr,
+ &voice_out_addr,
0,
NULL,
&size,
id);
}
-static OSStatus coreaudio_get_framesizerange(AudioDeviceID id,
- AudioValueRange *framerange)
+static OSStatus coreaudio_get_out_framesizerange(AudioDeviceID id,
+ AudioValueRange *framerange)
{
UInt32 size = sizeof(*framerange);
AudioObjectPropertyAddress addr = {
@@ -87,7 +87,7 @@ static OSStatus coreaudio_get_framesizerange(AudioDeviceID id,
framerange);
}
-static OSStatus coreaudio_get_framesize(AudioDeviceID id, UInt32 *framesize)
+static OSStatus coreaudio_get_out_framesize(AudioDeviceID id, UInt32 *framesize)
{
UInt32 size = sizeof(*framesize);
AudioObjectPropertyAddress addr = {
@@ -104,7 +104,7 @@ static OSStatus coreaudio_get_framesize(AudioDeviceID id, UInt32 *framesize)
framesize);
}
-static OSStatus coreaudio_set_framesize(AudioDeviceID id, UInt32 *framesize)
+static OSStatus coreaudio_set_out_framesize(AudioDeviceID id, UInt32 *framesize)
{
UInt32 size = sizeof(*framesize);
AudioObjectPropertyAddress addr = {
@@ -121,8 +121,8 @@ static OSStatus coreaudio_set_framesize(AudioDeviceID id, UInt32 *framesize)
framesize);
}
-static OSStatus coreaudio_set_streamformat(AudioDeviceID id,
- AudioStreamBasicDescription *d)
+static OSStatus coreaudio_set_out_streamformat(AudioDeviceID id,
+ AudioStreamBasicDescription *d)
{
UInt32 size = sizeof(*d);
AudioObjectPropertyAddress addr = {
@@ -139,7 +139,7 @@ static OSStatus coreaudio_set_streamformat(AudioDeviceID id,
d);
}
-static OSStatus coreaudio_get_isrunning(AudioDeviceID id, UInt32 *result)
+static OSStatus coreaudio_get_out_isrunning(AudioDeviceID id, UInt32 *result)
{
UInt32 size = sizeof(*result);
AudioObjectPropertyAddress addr = {
@@ -243,7 +243,8 @@ static void G_GNUC_PRINTF(3, 4) coreaudio_logerr2(OSStatus status,
#define coreaudio_playback_logerr(status, ...) \
coreaudio_logerr2(status, "playback", __VA_ARGS__)
-static int coreaudio_buf_lock(coreaudioVoiceOut *core, const char *fn_name)
+static int coreaudio_voice_out_buf_lock(CoreaudioVoiceOut *core,
+ const char *fn_name)
{
int err;
@@ -256,7 +257,8 @@ static int coreaudio_buf_lock(coreaudioVoiceOut *core, const char *fn_name)
return 0;
}
-static int coreaudio_buf_unlock(coreaudioVoiceOut *core, const char *fn_name)
+static int coreaudio_voice_out_buf_unlock(CoreaudioVoiceOut *core,
+ const char *fn_name)
{
int err;
@@ -269,20 +271,20 @@ static int coreaudio_buf_unlock(coreaudioVoiceOut *core, const char *fn_name)
return 0;
}
-#define COREAUDIO_WRAPPER_FUNC(name, ret_type, args_decl, args) \
- static ret_type glue(coreaudio_, name)args_decl \
- { \
- coreaudioVoiceOut *core = (coreaudioVoiceOut *)hw; \
- ret_type ret; \
- \
- if (coreaudio_buf_lock(core, "coreaudio_" #name)) { \
- return 0; \
- } \
- \
- ret = glue(audio_generic_, name)args; \
- \
- coreaudio_buf_unlock(core, "coreaudio_" #name); \
- return ret; \
+#define COREAUDIO_WRAPPER_FUNC(name, ret_type, args_decl, args) \
+ static ret_type glue(coreaudio_, name)args_decl \
+ { \
+ CoreaudioVoiceOut *core = (CoreaudioVoiceOut *)hw; \
+ ret_type ret; \
+ \
+ if (coreaudio_voice_out_buf_lock(core, "coreaudio_" #name)) { \
+ return 0; \
+ } \
+ \
+ ret = glue(audio_generic_, name)args; \
+ \
+ coreaudio_voice_out_buf_unlock(core, "coreaudio_" #name); \
+ return ret; \
}
COREAUDIO_WRAPPER_FUNC(buffer_get_free, size_t, (HWVoiceOut *hw), (hw))
COREAUDIO_WRAPPER_FUNC(get_buffer_out, void *, (HWVoiceOut *hw, size_t *size),
@@ -298,7 +300,7 @@ static ret_type glue(coreaudio_, name)args_decl \
* callback to feed audiooutput buffer. called without BQL.
* allowed to lock "buf_mutex", but disallowed to have any other locks.
*/
-static OSStatus audioDeviceIOProc(
+static OSStatus out_device_ioproc(
AudioDeviceID inDevice,
const AudioTimeStamp *inNow,
const AudioBufferList *inInputData,
@@ -307,33 +309,33 @@ static OSStatus audioDeviceIOProc(
const AudioTimeStamp *inOutputTime,
void *hwptr)
{
- UInt32 frameCount, pending_frames;
+ UInt32 frame_size, pending_frames;
void *out = outOutputData->mBuffers[0].mData;
HWVoiceOut *hw = hwptr;
- coreaudioVoiceOut *core = hwptr;
+ CoreaudioVoiceOut *core = hwptr;
size_t len;
- if (coreaudio_buf_lock(core, "audioDeviceIOProc")) {
+ if (coreaudio_voice_out_buf_lock(core, "out_device_ioproc")) {
inInputTime = 0;
return 0;
}
- if (inDevice != core->outputDeviceID) {
- coreaudio_buf_unlock(core, "audioDeviceIOProc(old device)");
+ if (inDevice != core->device_id) {
+ coreaudio_voice_out_buf_unlock(core, "out_device_ioproc(old device)");
return 0;
}
- frameCount = core->audioDevicePropertyBufferFrameSize;
+ frame_size = core->device_frame_size;
pending_frames = hw->pending_emul / hw->info.bytes_per_frame;
/* if there are not enough samples, set signal and return */
- if (pending_frames < frameCount) {
+ if (pending_frames < frame_size) {
inInputTime = 0;
- coreaudio_buf_unlock(core, "audioDeviceIOProc(empty)");
+ coreaudio_voice_out_buf_unlock(core, "out_device_ioproc(empty)");
return 0;
}
- len = frameCount * hw->info.bytes_per_frame;
+ len = frame_size * hw->info.bytes_per_frame;
while (len) {
size_t write_len, start;
@@ -349,16 +351,16 @@ static OSStatus audioDeviceIOProc(
out += write_len;
}
- coreaudio_buf_unlock(core, "audioDeviceIOProc");
+ coreaudio_voice_out_buf_unlock(core, "out_device_ioproc");
return 0;
}
-static OSStatus init_out_device(coreaudioVoiceOut *core)
+static OSStatus init_out_device(CoreaudioVoiceOut *core)
{
+ AudioValueRange value_range;
OSStatus status;
- AudioValueRange frameRange;
- AudioStreamBasicDescription streamBasicDescription = {
+ AudioStreamBasicDescription stream_basic_description = {
.mBitsPerChannel = audio_format_bits(core->hw.info.af),
.mBytesPerFrame = core->hw.info.bytes_per_frame,
.mBytesPerPacket = core->hw.info.bytes_per_frame,
@@ -369,21 +371,20 @@ static OSStatus init_out_device(coreaudioVoiceOut *core)
.mSampleRate = core->hw.info.freq
};
- status = coreaudio_get_voice(&core->outputDeviceID);
+ status = coreaudio_get_voice_out(&core->device_id);
if (status != kAudioHardwareNoError) {
coreaudio_playback_logerr(status,
"Could not get default output device");
return status;
}
- if (core->outputDeviceID == kAudioDeviceUnknown) {
+ if (core->device_id == kAudioDeviceUnknown) {
error_report("coreaudio: Could not initialize playback: "
"Unknown audio device");
return status;
}
/* get minimum and maximum buffer frame sizes */
- status = coreaudio_get_framesizerange(core->outputDeviceID,
- &frameRange);
+ status = coreaudio_get_out_framesizerange(core->device_id, &value_range);
if (status == kAudioHardwareBadObjectError) {
return 0;
}
@@ -393,34 +394,34 @@ static OSStatus init_out_device(coreaudioVoiceOut *core)
return status;
}
- if (frameRange.mMinimum > core->frameSizeSetting) {
- core->audioDevicePropertyBufferFrameSize = frameRange.mMinimum;
+ if (value_range.mMinimum > core->frame_size_setting) {
+ core->device_frame_size = value_range.mMinimum;
warn_report("coreaudio: Upsizing buffer frames to %f",
- frameRange.mMinimum);
- } else if (frameRange.mMaximum < core->frameSizeSetting) {
- core->audioDevicePropertyBufferFrameSize = frameRange.mMaximum;
+ value_range.mMinimum);
+ } else if (value_range.mMaximum < core->frame_size_setting) {
+ core->device_frame_size = value_range.mMaximum;
warn_report("coreaudio: Downsizing buffer frames to %f",
- frameRange.mMaximum);
+ value_range.mMaximum);
} else {
- core->audioDevicePropertyBufferFrameSize = core->frameSizeSetting;
+ core->device_frame_size = core->frame_size_setting;
}
/* set Buffer Frame Size */
- status = coreaudio_set_framesize(core->outputDeviceID,
- &core->audioDevicePropertyBufferFrameSize);
+ status = coreaudio_set_out_framesize(core->device_id,
+ &core->device_frame_size);
if (status == kAudioHardwareBadObjectError) {
return 0;
}
if (status != kAudioHardwareNoError) {
coreaudio_playback_logerr(status,
"Could not set device buffer frame size %" PRIu32,
- (uint32_t)core->audioDevicePropertyBufferFrameSize);
+ (uint32_t)core->device_frame_size);
return status;
}
/* get Buffer Frame Size */
- status = coreaudio_get_framesize(core->outputDeviceID,
- &core->audioDevicePropertyBufferFrameSize);
+ status = coreaudio_get_out_framesize(core->device_id,
+ &core->device_frame_size);
if (status == kAudioHardwareBadObjectError) {
return 0;
}
@@ -429,19 +430,19 @@ static OSStatus init_out_device(coreaudioVoiceOut *core)
"Could not get device buffer frame size");
return status;
}
- core->hw.samples = core->bufferCount * core->audioDevicePropertyBufferFrameSize;
+ core->hw.samples = core->buffer_count * core->device_frame_size;
/* set Samplerate */
- status = coreaudio_set_streamformat(core->outputDeviceID,
- &streamBasicDescription);
+ status = coreaudio_set_out_streamformat(core->device_id,
+ &stream_basic_description);
if (status == kAudioHardwareBadObjectError) {
return 0;
}
if (status != kAudioHardwareNoError) {
coreaudio_playback_logerr(status,
"Could not set samplerate %lf",
- streamBasicDescription.mSampleRate);
- core->outputDeviceID = kAudioDeviceUnknown;
+ stream_basic_description.mSampleRate);
+ core->device_id = kAudioDeviceUnknown;
return status;
}
@@ -456,8 +457,8 @@ static OSStatus init_out_device(coreaudioVoiceOut *core)
* with the callers of AudioObjectGetPropertyData.
*/
core->ioprocid = NULL;
- status = AudioDeviceCreateIOProcID(core->outputDeviceID,
- audioDeviceIOProc,
+ status = AudioDeviceCreateIOProcID(core->device_id,
+ out_device_ioproc,
&core->hw,
&core->ioprocid);
if (status == kAudioHardwareBadDeviceError) {
@@ -465,20 +466,20 @@ static OSStatus init_out_device(coreaudioVoiceOut *core)
}
if (status != kAudioHardwareNoError || core->ioprocid == NULL) {
coreaudio_playback_logerr(status, "Could not set IOProc");
- core->outputDeviceID = kAudioDeviceUnknown;
+ core->device_id = kAudioDeviceUnknown;
return status;
}
return 0;
}
-static void fini_out_device(coreaudioVoiceOut *core)
+static void fini_out_device(CoreaudioVoiceOut *core)
{
OSStatus status;
UInt32 isrunning;
/* stop playback */
- status = coreaudio_get_isrunning(core->outputDeviceID, &isrunning);
+ status = coreaudio_get_out_isrunning(core->device_id, &isrunning);
if (status != kAudioHardwareBadObjectError) {
if (status != kAudioHardwareNoError) {
coreaudio_logerr(status,
@@ -486,7 +487,7 @@ static void fini_out_device(coreaudioVoiceOut *core)
}
if (isrunning) {
- status = AudioDeviceStop(core->outputDeviceID, core->ioprocid);
+ status = AudioDeviceStop(core->device_id, core->ioprocid);
if (status != kAudioHardwareBadDeviceError && status != kAudioHardwareNoError) {
coreaudio_logerr(status, "Could not stop playback");
}
@@ -494,20 +495,20 @@ static void fini_out_device(coreaudioVoiceOut *core)
}
/* remove callback */
- status = AudioDeviceDestroyIOProcID(core->outputDeviceID,
+ status = AudioDeviceDestroyIOProcID(core->device_id,
core->ioprocid);
if (status != kAudioHardwareBadDeviceError && status != kAudioHardwareNoError) {
coreaudio_logerr(status, "Could not remove IOProc");
}
- core->outputDeviceID = kAudioDeviceUnknown;
+ core->device_id = kAudioDeviceUnknown;
}
-static void update_device_playback_state(coreaudioVoiceOut *core)
+static void update_out_device_playback_state(CoreaudioVoiceOut *core)
{
OSStatus status;
UInt32 isrunning;
- status = coreaudio_get_isrunning(core->outputDeviceID, &isrunning);
+ status = coreaudio_get_out_isrunning(core->device_id, &isrunning);
if (status != kAudioHardwareNoError) {
if (status != kAudioHardwareBadObjectError) {
coreaudio_logerr(status,
@@ -520,7 +521,7 @@ static void update_device_playback_state(coreaudioVoiceOut *core)
if (core->enabled) {
/* start playback */
if (!isrunning) {
- status = AudioDeviceStart(core->outputDeviceID, core->ioprocid);
+ status = AudioDeviceStart(core->device_id, core->ioprocid);
if (status != kAudioHardwareBadDeviceError && status != kAudioHardwareNoError) {
coreaudio_logerr(status, "Could not resume playback");
}
@@ -528,7 +529,7 @@ static void update_device_playback_state(coreaudioVoiceOut *core)
} else {
/* stop playback */
if (isrunning) {
- status = AudioDeviceStop(core->outputDeviceID,
+ status = AudioDeviceStop(core->device_id,
core->ioprocid);
if (status != kAudioHardwareBadDeviceError && status != kAudioHardwareNoError) {
coreaudio_logerr(status, "Could not pause playback");
@@ -538,22 +539,22 @@ static void update_device_playback_state(coreaudioVoiceOut *core)
}
/* called without BQL. */
-static OSStatus handle_voice_change(
+static OSStatus handle_voice_out_change(
AudioObjectID in_object_id,
UInt32 in_number_addresses,
const AudioObjectPropertyAddress *in_addresses,
void *in_client_data)
{
- coreaudioVoiceOut *core = in_client_data;
+ CoreaudioVoiceOut *core = in_client_data;
bql_lock();
- if (core->outputDeviceID) {
+ if (core->device_id) {
fini_out_device(core);
}
if (!init_out_device(core)) {
- update_device_playback_state(core);
+ update_out_device_playback_state(core);
}
bql_unlock();
@@ -563,7 +564,7 @@ static OSStatus handle_voice_change(
static int coreaudio_init_out(HWVoiceOut *hw, struct audsettings *as)
{
OSStatus status;
- coreaudioVoiceOut *core = (coreaudioVoiceOut *)hw;
+ CoreaudioVoiceOut *core = (CoreaudioVoiceOut *)hw;
int err;
Audiodev *dev = hw->s->dev;
AudiodevCoreaudioPerDirectionOptions *cpdo = dev->u.coreaudio.out;
@@ -581,13 +582,14 @@ static int coreaudio_init_out(HWVoiceOut *hw, struct audsettings *as)
as->fmt = AUDIO_FORMAT_F32;
audio_pcm_init_info(&hw->info, as);
- core->frameSizeSetting = audio_buffer_frames(
+ core->frame_size_setting = audio_buffer_frames(
qapi_AudiodevCoreaudioPerDirectionOptions_base(cpdo), as, 11610);
- core->bufferCount = cpdo->has_buffer_count ? cpdo->buffer_count : 4;
+ core->buffer_count = cpdo->has_buffer_count ? cpdo->buffer_count : 4;
status = AudioObjectAddPropertyListener(kAudioObjectSystemObject,
- &voice_addr, handle_voice_change,
+ &voice_out_addr,
+ handle_voice_out_change,
core);
if (status != kAudioHardwareNoError) {
coreaudio_playback_logerr(status,
@@ -597,8 +599,8 @@ static int coreaudio_init_out(HWVoiceOut *hw, struct audsettings *as)
if (init_out_device(core)) {
status = AudioObjectRemovePropertyListener(kAudioObjectSystemObject,
- &voice_addr,
- handle_voice_change,
+ &voice_out_addr,
+ handle_voice_out_change,
core);
if (status != kAudioHardwareNoError) {
coreaudio_playback_logerr(status,
@@ -615,11 +617,11 @@ static void coreaudio_fini_out (HWVoiceOut *hw)
{
OSStatus status;
int err;
- coreaudioVoiceOut *core = (coreaudioVoiceOut *)hw;
+ CoreaudioVoiceOut *core = (CoreaudioVoiceOut *)hw;
status = AudioObjectRemovePropertyListener(kAudioObjectSystemObject,
- &voice_addr,
- handle_voice_change,
+ &voice_out_addr,
+ handle_voice_out_change,
core);
if (status != kAudioHardwareNoError) {
coreaudio_logerr(status, "Could not remove voice property change listener");
@@ -636,10 +638,10 @@ static void coreaudio_fini_out (HWVoiceOut *hw)
static void coreaudio_enable_out(HWVoiceOut *hw, bool enable)
{
- coreaudioVoiceOut *core = (coreaudioVoiceOut *)hw;
+ CoreaudioVoiceOut *core = (CoreaudioVoiceOut *)hw;
core->enabled = enable;
- update_device_playback_state(core);
+ update_out_device_playback_state(core);
}
static void audio_coreaudio_class_init(ObjectClass *klass, const void *data)
--
2.53.0
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PULL 14/16] coreaudio: Commit the result of init in the end
2026-03-17 17:19 [PULL 00/16] ui/audio/dump patches for 11.0-rc marcandre.lureau
` (12 preceding siblings ...)
2026-03-17 17:19 ` [PULL 13/16] coreaudio: Improve naming marcandre.lureau
@ 2026-03-17 17:19 ` marcandre.lureau
2026-03-17 17:19 ` [PULL 15/16] audio: Add functions to initialize buffers marcandre.lureau
` (2 subsequent siblings)
16 siblings, 0 replies; 18+ messages in thread
From: marcandre.lureau @ 2026-03-17 17:19 UTC (permalink / raw)
To: qemu-devel
Cc: Dmitry Osipenko, Marc-André Lureau, Michael S. Tsirkin,
Christian Schoenebeck, Ani Sinha, Alex Bennée,
Philippe Mathieu-Daudé, Gerd Hoffmann, Zhao Liu,
Marcel Apfelbaum, Yanan Wang, Akihiko Odaki
From: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
init_out_device may only commit some part of the result and leave the
state inconsistent when it encounters a fatal error or the device gets
unplugged during the operation, which is expressed by
kAudioHardwareBadObjectError or kAudioHardwareBadDeviceError. Commit the
result in the end of the function so that it commits the result iff it
sees no fatal error and the device remains plugged.
With this change, handle_voice_change can rely on core->outputDeviceID
to know whether the output device is initialized after calling
init_out_device.
Signed-off-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
Acked-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-Id: <20260304-coreaudio-v8-4-bf1d40731e73@rsg.ci.i.u-tokyo.ac.jp>
---
audio/coreaudio.m | 47 ++++++++++++++++++++++++++---------------------
1 file changed, 26 insertions(+), 21 deletions(-)
diff --git a/audio/coreaudio.m b/audio/coreaudio.m
index 736227eb2b7..23c3d1f80ac 100644
--- a/audio/coreaudio.m
+++ b/audio/coreaudio.m
@@ -357,8 +357,11 @@ static OSStatus out_device_ioproc(
static OSStatus init_out_device(CoreaudioVoiceOut *core)
{
+ AudioDeviceID device_id;
+ AudioDeviceIOProcID ioprocid;
AudioValueRange value_range;
OSStatus status;
+ UInt32 device_frame_size;
AudioStreamBasicDescription stream_basic_description = {
.mBitsPerChannel = audio_format_bits(core->hw.info.af),
@@ -371,20 +374,20 @@ static OSStatus init_out_device(CoreaudioVoiceOut *core)
.mSampleRate = core->hw.info.freq
};
- status = coreaudio_get_voice_out(&core->device_id);
+ status = coreaudio_get_voice_out(&device_id);
if (status != kAudioHardwareNoError) {
coreaudio_playback_logerr(status,
"Could not get default output device");
return status;
}
- if (core->device_id == kAudioDeviceUnknown) {
+ if (device_id == kAudioDeviceUnknown) {
error_report("coreaudio: Could not initialize playback: "
"Unknown audio device");
return status;
}
/* get minimum and maximum buffer frame sizes */
- status = coreaudio_get_out_framesizerange(core->device_id, &value_range);
+ status = coreaudio_get_out_framesizerange(device_id, &value_range);
if (status == kAudioHardwareBadObjectError) {
return 0;
}
@@ -395,33 +398,31 @@ static OSStatus init_out_device(CoreaudioVoiceOut *core)
}
if (value_range.mMinimum > core->frame_size_setting) {
- core->device_frame_size = value_range.mMinimum;
+ device_frame_size = value_range.mMinimum;
warn_report("coreaudio: Upsizing buffer frames to %f",
value_range.mMinimum);
} else if (value_range.mMaximum < core->frame_size_setting) {
- core->device_frame_size = value_range.mMaximum;
+ device_frame_size = value_range.mMaximum;
warn_report("coreaudio: Downsizing buffer frames to %f",
value_range.mMaximum);
} else {
- core->device_frame_size = core->frame_size_setting;
+ device_frame_size = core->frame_size_setting;
}
/* set Buffer Frame Size */
- status = coreaudio_set_out_framesize(core->device_id,
- &core->device_frame_size);
+ status = coreaudio_set_out_framesize(device_id, &device_frame_size);
if (status == kAudioHardwareBadObjectError) {
return 0;
}
if (status != kAudioHardwareNoError) {
coreaudio_playback_logerr(status,
"Could not set device buffer frame size %" PRIu32,
- (uint32_t)core->device_frame_size);
+ (uint32_t)device_frame_size);
return status;
}
/* get Buffer Frame Size */
- status = coreaudio_get_out_framesize(core->device_id,
- &core->device_frame_size);
+ status = coreaudio_get_out_framesize(device_id, &device_frame_size);
if (status == kAudioHardwareBadObjectError) {
return 0;
}
@@ -430,10 +431,9 @@ static OSStatus init_out_device(CoreaudioVoiceOut *core)
"Could not get device buffer frame size");
return status;
}
- core->hw.samples = core->buffer_count * core->device_frame_size;
/* set Samplerate */
- status = coreaudio_set_out_streamformat(core->device_id,
+ status = coreaudio_set_out_streamformat(device_id,
&stream_basic_description);
if (status == kAudioHardwareBadObjectError) {
return 0;
@@ -442,7 +442,6 @@ static OSStatus init_out_device(CoreaudioVoiceOut *core)
coreaudio_playback_logerr(status,
"Could not set samplerate %lf",
stream_basic_description.mSampleRate);
- core->device_id = kAudioDeviceUnknown;
return status;
}
@@ -456,20 +455,24 @@ static OSStatus init_out_device(CoreaudioVoiceOut *core)
* Therefore, the specified callback must be designed to avoid a deadlock
* with the callers of AudioObjectGetPropertyData.
*/
- core->ioprocid = NULL;
- status = AudioDeviceCreateIOProcID(core->device_id,
+ ioprocid = NULL;
+ status = AudioDeviceCreateIOProcID(device_id,
out_device_ioproc,
&core->hw,
- &core->ioprocid);
+ &ioprocid);
if (status == kAudioHardwareBadDeviceError) {
return 0;
}
- if (status != kAudioHardwareNoError || core->ioprocid == NULL) {
+ if (status != kAudioHardwareNoError || ioprocid == NULL) {
coreaudio_playback_logerr(status, "Could not set IOProc");
- core->device_id = kAudioDeviceUnknown;
return status;
}
+ core->device_id = device_id;
+ core->device_frame_size = device_frame_size;
+ core->hw.samples = core->buffer_count * core->device_frame_size;
+ core->ioprocid = ioprocid;
+
return 0;
}
@@ -553,7 +556,9 @@ static OSStatus handle_voice_out_change(
fini_out_device(core);
}
- if (!init_out_device(core)) {
+ init_out_device(core);
+
+ if (core->device_id) {
update_out_device_playback_state(core);
}
@@ -650,7 +655,7 @@ static void audio_coreaudio_class_init(ObjectClass *klass, const void *data)
k->max_voices_out = 1;
k->max_voices_in = 0;
- k->voice_size_out = sizeof(coreaudioVoiceOut);
+ k->voice_size_out = sizeof(CoreaudioVoiceOut);
k->voice_size_in = 0;
k->init_out = coreaudio_init_out;
--
2.53.0
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PULL 15/16] audio: Add functions to initialize buffers
2026-03-17 17:19 [PULL 00/16] ui/audio/dump patches for 11.0-rc marcandre.lureau
` (13 preceding siblings ...)
2026-03-17 17:19 ` [PULL 14/16] coreaudio: Commit the result of init in the end marcandre.lureau
@ 2026-03-17 17:19 ` marcandre.lureau
2026-03-17 17:19 ` [PULL 16/16] coreaudio: Initialize the buffer for device change marcandre.lureau
2026-03-18 10:11 ` [PULL 00/16] ui/audio/dump patches for 11.0-rc Peter Maydell
16 siblings, 0 replies; 18+ messages in thread
From: marcandre.lureau @ 2026-03-17 17:19 UTC (permalink / raw)
To: qemu-devel
Cc: Dmitry Osipenko, Marc-André Lureau, Michael S. Tsirkin,
Christian Schoenebeck, Ani Sinha, Alex Bennée,
Philippe Mathieu-Daudé, Gerd Hoffmann, Zhao Liu,
Marcel Apfelbaum, Yanan Wang, Akihiko Odaki
From: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
These functions can be used to re-initialize buffers when hardware
parameters change due to device hotplug, for example.
Signed-off-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
Reviewed-by: Phil Dennis-Jordan <phil@philjordan.eu>
Reviewed-by: Christian Schoenebeck <qemu_oss@crudebyte.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-Id: <20260304-coreaudio-v8-5-bf1d40731e73@rsg.ci.i.u-tokyo.ac.jp>
---
audio/audio_int.h | 2 ++
audio/audio-mixeng-be.c | 24 ++++++++++++++++++------
2 files changed, 20 insertions(+), 6 deletions(-)
diff --git a/audio/audio_int.h b/audio/audio_int.h
index 06f79ade6b0..290cf373b49 100644
--- a/audio/audio_int.h
+++ b/audio/audio_int.h
@@ -141,9 +141,11 @@ static inline void *advance(void *p, size_t incr)
int wav_start_capture(AudioBackend *state, CaptureState *s, const char *path,
int freq, int bits, int nchannels);
+void audio_generic_initialize_buffer_in(HWVoiceIn *hw);
void audio_generic_run_buffer_in(HWVoiceIn *hw);
void *audio_generic_get_buffer_in(HWVoiceIn *hw, size_t *size);
void audio_generic_put_buffer_in(HWVoiceIn *hw, void *buf, size_t size);
+void audio_generic_initialize_buffer_out(HWVoiceOut *hw);
void audio_generic_run_buffer_out(HWVoiceOut *hw);
size_t audio_generic_buffer_get_free(HWVoiceOut *hw);
void *audio_generic_get_buffer_out(HWVoiceOut *hw, size_t *size);
diff --git a/audio/audio-mixeng-be.c b/audio/audio-mixeng-be.c
index 5878b23e04e..f7d73d85608 100644
--- a/audio/audio-mixeng-be.c
+++ b/audio/audio-mixeng-be.c
@@ -1187,14 +1187,20 @@ void audio_run(AudioMixengBackend *s, const char *msg)
}
}
+void audio_generic_initialize_buffer_in(HWVoiceIn *hw)
+{
+ g_free(hw->buf_emul);
+ hw->size_emul = hw->samples * hw->info.bytes_per_frame;
+ hw->buf_emul = g_malloc(hw->size_emul);
+ hw->pos_emul = hw->pending_emul = 0;
+}
+
void audio_generic_run_buffer_in(HWVoiceIn *hw)
{
AudioMixengBackendClass *k = AUDIO_MIXENG_BACKEND_GET_CLASS(hw->s);
if (unlikely(!hw->buf_emul)) {
- hw->size_emul = hw->samples * hw->info.bytes_per_frame;
- hw->buf_emul = g_malloc(hw->size_emul);
- hw->pos_emul = hw->pending_emul = 0;
+ audio_generic_initialize_buffer_in(hw);
}
while (hw->pending_emul < hw->size_emul) {
@@ -1227,6 +1233,14 @@ void audio_generic_put_buffer_in(HWVoiceIn *hw, void *buf, size_t size)
hw->pending_emul -= size;
}
+void audio_generic_initialize_buffer_out(HWVoiceOut *hw)
+{
+ g_free(hw->buf_emul);
+ hw->size_emul = hw->samples * hw->info.bytes_per_frame;
+ hw->buf_emul = g_malloc(hw->size_emul);
+ hw->pos_emul = hw->pending_emul = 0;
+}
+
size_t audio_generic_buffer_get_free(HWVoiceOut *hw)
{
if (hw->buf_emul) {
@@ -1260,9 +1274,7 @@ void audio_generic_run_buffer_out(HWVoiceOut *hw)
void *audio_generic_get_buffer_out(HWVoiceOut *hw, size_t *size)
{
if (unlikely(!hw->buf_emul)) {
- hw->size_emul = hw->samples * hw->info.bytes_per_frame;
- hw->buf_emul = g_malloc(hw->size_emul);
- hw->pos_emul = hw->pending_emul = 0;
+ audio_generic_initialize_buffer_out(hw);
}
*size = MIN(hw->size_emul - hw->pending_emul,
--
2.53.0
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PULL 16/16] coreaudio: Initialize the buffer for device change
2026-03-17 17:19 [PULL 00/16] ui/audio/dump patches for 11.0-rc marcandre.lureau
` (14 preceding siblings ...)
2026-03-17 17:19 ` [PULL 15/16] audio: Add functions to initialize buffers marcandre.lureau
@ 2026-03-17 17:19 ` marcandre.lureau
2026-03-18 10:11 ` [PULL 00/16] ui/audio/dump patches for 11.0-rc Peter Maydell
16 siblings, 0 replies; 18+ messages in thread
From: marcandre.lureau @ 2026-03-17 17:19 UTC (permalink / raw)
To: qemu-devel
Cc: Dmitry Osipenko, Marc-André Lureau, Michael S. Tsirkin,
Christian Schoenebeck, Ani Sinha, Alex Bennée,
Philippe Mathieu-Daudé, Gerd Hoffmann, Zhao Liu,
Marcel Apfelbaum, Yanan Wang, Akihiko Odaki
From: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
Reallocate buffers when the active device change as the required buffer
size may differ.
Signed-off-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
Reviewed-by: Phil Dennis-Jordan <phil@philjordan.eu>
Acked-by: Christian Schoenebeck <qemu_oss@crudebyte.com>
Reviewed-by: Christian Schoenebeck <qemu_oss@crudebyte.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-Id: <20260304-coreaudio-v8-6-bf1d40731e73@rsg.ci.i.u-tokyo.ac.jp>
---
audio/coreaudio.m | 1 +
1 file changed, 1 insertion(+)
diff --git a/audio/coreaudio.m b/audio/coreaudio.m
index 23c3d1f80ac..e4ec1df971c 100644
--- a/audio/coreaudio.m
+++ b/audio/coreaudio.m
@@ -471,6 +471,7 @@ static OSStatus init_out_device(CoreaudioVoiceOut *core)
core->device_id = device_id;
core->device_frame_size = device_frame_size;
core->hw.samples = core->buffer_count * core->device_frame_size;
+ audio_generic_initialize_buffer_out(&core->hw);
core->ioprocid = ioprocid;
return 0;
--
2.53.0
^ permalink raw reply related [flat|nested] 18+ messages in thread
* Re: [PULL 00/16] ui/audio/dump patches for 11.0-rc
2026-03-17 17:19 [PULL 00/16] ui/audio/dump patches for 11.0-rc marcandre.lureau
` (15 preceding siblings ...)
2026-03-17 17:19 ` [PULL 16/16] coreaudio: Initialize the buffer for device change marcandre.lureau
@ 2026-03-18 10:11 ` Peter Maydell
16 siblings, 0 replies; 18+ messages in thread
From: Peter Maydell @ 2026-03-18 10:11 UTC (permalink / raw)
To: marcandre.lureau
Cc: qemu-devel, Dmitry Osipenko, Michael S. Tsirkin,
Christian Schoenebeck, Ani Sinha, Alex Bennée,
Philippe Mathieu-Daudé, Gerd Hoffmann, Zhao Liu,
Marcel Apfelbaum, Yanan Wang, Akihiko Odaki
On Tue, 17 Mar 2026 at 17:20, <marcandre.lureau@redhat.com> wrote:
>
> From: Marc-André Lureau <marcandre.lureau@redhat.com>
>
> The following changes since commit 559919ce54927d59b215a4665eda7ab6118a48aa:
>
> Merge tag 'pull-trivial-patches' of https://gitlab.com/mjt0k/qemu into staging (2026-03-16 13:07:33 +0000)
>
> are available in the Git repository at:
>
> https://gitlab.com/marcandre.lureau/qemu.git tags/for-11.0-pull-request
>
> for you to fetch changes up to 461632f0b1cb2c5c29ba9875857637e3356b903c:
>
> coreaudio: Initialize the buffer for device change (2026-03-17 21:15:10 +0400)
>
> ----------------------------------------------------------------
> Gather various audio/ui/dump patches for 11.0-rc
>
Applied, thanks.
Please update the changelog at https://wiki.qemu.org/ChangeLog/11.0
for any user-visible changes.
-- PMM
^ permalink raw reply [flat|nested] 18+ messages in thread
end of thread, other threads:[~2026-03-18 10:11 UTC | newest]
Thread overview: 18+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-03-17 17:19 [PULL 00/16] ui/audio/dump patches for 11.0-rc marcandre.lureau
2026-03-17 17:19 ` [PULL 01/16] audio/mixeng: drop some needless checks marcandre.lureau
2026-03-17 17:19 ` [PULL 02/16] rutabaga: improve error handling, fix potential crash during init marcandre.lureau
2026-03-17 17:19 ` [PULL 03/16] ui/vdagent: add migration blocker when machine version < 10.1 marcandre.lureau
2026-03-17 17:19 ` [PULL 04/16] virtio-gpu: fix overflow check when allocating 2d image marcandre.lureau
2026-03-17 17:19 ` [PULL 05/16] virtio-gpu: use computed rowstride instead of deriving it from hostmem marcandre.lureau
2026-03-17 17:19 ` [PULL 06/16] ui/dbus-listener: Fix FBO leak in dbus_cursor_dmabuf marcandre.lureau
2026-03-17 17:19 ` [PULL 07/16] ui/dbus-listener: remove dbus_filter on connection close marcandre.lureau
2026-03-17 17:19 ` [PULL 08/16] ui/gtk-egl: Ensure EGL surface is available before drawing marcandre.lureau
2026-03-17 17:19 ` [PULL 09/16] dump: enhance dump_state_prepare fd initialization marcandre.lureau
2026-03-17 17:19 ` [PULL 10/16] ui/console: Unify pixman-OpenGL format mapping marcandre.lureau
2026-03-17 17:19 ` [PULL 11/16] ui/console: Remove DisplaySurface::mem_obj marcandre.lureau
2026-03-17 17:19 ` [PULL 12/16] ui/surface: Avoid including epoxy/gl.h in header files marcandre.lureau
2026-03-17 17:19 ` [PULL 13/16] coreaudio: Improve naming marcandre.lureau
2026-03-17 17:19 ` [PULL 14/16] coreaudio: Commit the result of init in the end marcandre.lureau
2026-03-17 17:19 ` [PULL 15/16] audio: Add functions to initialize buffers marcandre.lureau
2026-03-17 17:19 ` [PULL 16/16] coreaudio: Initialize the buffer for device change marcandre.lureau
2026-03-18 10:11 ` [PULL 00/16] ui/audio/dump patches for 11.0-rc Peter Maydell
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox