mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
Merge tag 'ui-pull-request' of https://gitlab.com/marcandre.lureau/qemu into staging
ui & audio fixes # -----BEGIN PGP SIGNATURE----- # # iQJQBAABCAA6FiEEh6m9kz+HxgbSdvYt2ujhCXWWnOUFAmS1N6IcHG1hcmNhbmRy # ZS5sdXJlYXVAcmVkaGF0LmNvbQAKCRDa6OEJdZac5SYsD/44+FIoik9v478pZDTp # CpaezX+DfsW1zee4Ana5eKJkrVld/xEa6i9/msfUHy12bha+kiJ4a6wLu3H4KRZc # vX/t6sehG2wNcsV5wLhfcjsKzaNUkYpnxLhIZ0fOYXKA0fSBuM/Bsj6zzGTG6kQA # nt/cK58r1wy63V7werZbA7BI8PF0opDUw5SrZqN0GeoN5clbdyLdcXvD50ibvkDf # eOVjNQ3QH8IbihmgBVm1wUV8hTuvYRpBmeLJyk7NeR4bnPl3XGIAgtAY8hJL5LdY # Bm+I3AuxMSskVcag/22QR8mGR0HhDbf3NZauw4ND3LhSctvNN5syaKHVnY5a9aGe # QLVEV9pxXGfqzWQcsD2HmbupRoBihmp6+WsIpV8ZtuSfeD6slyObw+lqarSQL9b5 # 2C4UFmGCsCOk8rrczZRDp9IWbm23toc/QcQZtg/LhdlCr8nM+7m0XtyEY5WtT3U1 # 8rJEmjOHHqlD4cVBathc8+ZRjKr8HFRRo1ed6WKMoP6voTsw2fiR7I3Vdc7jO7h9 # A1lMiMoLdAXi0Q2VqbmBdLMgb4fXtLzYl2mcbzW0aEUm8uyUfDy2bkVIIUopu40M # pROmLjaUzUVE3CruckBUCvoYZtJ5hBtvy3W2k8drBNylnP5B8tEqpxpPb+tSFk82 # xgT6oLp8En8asE293eaACbswuw== # =W2Xa # -----END PGP SIGNATURE----- # gpg: Signature made Mon 17 Jul 2023 01:44:18 PM BST # gpg: using RSA key 87A9BD933F87C606D276F62DDAE8E10975969CE5 # gpg: issuer "marcandre.lureau@redhat.com" # gpg: Good signature from "Marc-André Lureau <marcandre.lureau@redhat.com>" [full] # gpg: aka "Marc-André Lureau <marcandre.lureau@gmail.com>" [full] * tag 'ui-pull-request' of https://gitlab.com/marcandre.lureau/qemu: audio/pw: improve channel position code audio/pw: remove wrong comment audio/pw: simplify error reporting in stream creation audio/pw: add more error reporting audio/pw: factorize some common code audio/pw: add more details on error audio/pw: trace during init before calling pipewire API audio/pw: needless check for NULL audio/pw: drop needless case statement audio/pw: Pipewire->PipeWire case fix for user-visible text tests/lcitool: add pipewire libvirt-ci: update submodule to cover pipewire ui/gtk: skip refresh if new dmabuf has been submitted ui/gtk: set scanout-mode right before scheduling draw virtio-gpu-udmabuf: correct naming of QemuDmaBuf size properties virtio-gpu: replace the surface with null surface when resetting ui/gtk: Make sure the right EGL context is currently bound ui/vnc-clipboard: fix infinite loop in inflate_buffer (CVE-2023-3255) virtio-gpu: fix potential divide-by-zero regression Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
+93
-151
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* QEMU Pipewire audio driver
|
||||
* QEMU PipeWire audio driver
|
||||
*
|
||||
* Copyright (c) 2023 Red Hat Inc.
|
||||
*
|
||||
@@ -66,6 +66,9 @@ typedef struct PWVoiceIn {
|
||||
PWVoice v;
|
||||
} PWVoiceIn;
|
||||
|
||||
#define PW_VOICE_IN(v) ((PWVoiceIn *)v)
|
||||
#define PW_VOICE_OUT(v) ((PWVoiceOut *)v)
|
||||
|
||||
static void
|
||||
stream_destroy(void *data)
|
||||
{
|
||||
@@ -197,16 +200,6 @@ on_stream_state_changed(void *data, enum pw_stream_state old,
|
||||
|
||||
trace_pw_state_changed(pw_stream_get_node_id(v->stream),
|
||||
pw_stream_state_as_string(state));
|
||||
|
||||
switch (state) {
|
||||
case PW_STREAM_STATE_ERROR:
|
||||
case PW_STREAM_STATE_UNCONNECTED:
|
||||
break;
|
||||
case PW_STREAM_STATE_PAUSED:
|
||||
case PW_STREAM_STATE_CONNECTING:
|
||||
case PW_STREAM_STATE_STREAMING:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static const struct pw_stream_events capture_stream_events = {
|
||||
@@ -424,8 +417,8 @@ pw_to_audfmt(enum spa_audio_format fmt, int *endianness,
|
||||
}
|
||||
|
||||
static int
|
||||
create_stream(pwaudio *c, PWVoice *v, const char *stream_name,
|
||||
const char *name, enum spa_direction dir)
|
||||
qpw_stream_new(pwaudio *c, PWVoice *v, const char *stream_name,
|
||||
const char *name, enum spa_direction dir)
|
||||
{
|
||||
int res;
|
||||
uint32_t n_params;
|
||||
@@ -436,6 +429,10 @@ create_stream(pwaudio *c, PWVoice *v, const char *stream_name,
|
||||
struct pw_properties *props;
|
||||
|
||||
props = pw_properties_new(NULL, NULL);
|
||||
if (!props) {
|
||||
error_report("Failed to create PW properties: %s", g_strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* 75% of the timer period for faster updates */
|
||||
buf_samples = (uint64_t)v->g->dev->timer_period * v->info.rate
|
||||
@@ -448,8 +445,8 @@ create_stream(pwaudio *c, PWVoice *v, const char *stream_name,
|
||||
pw_properties_set(props, PW_KEY_TARGET_OBJECT, name);
|
||||
}
|
||||
v->stream = pw_stream_new(c->core, stream_name, props);
|
||||
|
||||
if (v->stream == NULL) {
|
||||
error_report("Failed to create PW stream: %s", g_strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -477,6 +474,7 @@ create_stream(pwaudio *c, PWVoice *v, const char *stream_name,
|
||||
PW_STREAM_FLAG_MAP_BUFFERS |
|
||||
PW_STREAM_FLAG_RT_PROCESS, params, n_params);
|
||||
if (res < 0) {
|
||||
error_report("Failed to connect PW stream: %s", g_strerror(errno));
|
||||
pw_stream_destroy(v->stream);
|
||||
return -1;
|
||||
}
|
||||
@@ -484,71 +482,37 @@ create_stream(pwaudio *c, PWVoice *v, const char *stream_name,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
qpw_stream_new(pwaudio *c, PWVoice *v, const char *stream_name,
|
||||
const char *name, enum spa_direction dir)
|
||||
static void
|
||||
qpw_set_position(uint32_t channels, uint32_t position[SPA_AUDIO_MAX_CHANNELS])
|
||||
{
|
||||
int r;
|
||||
|
||||
switch (v->info.channels) {
|
||||
memcpy(position, (uint32_t[SPA_AUDIO_MAX_CHANNELS]) { SPA_AUDIO_CHANNEL_UNKNOWN, },
|
||||
sizeof(uint32_t) * SPA_AUDIO_MAX_CHANNELS);
|
||||
/*
|
||||
* TODO: This currently expects the only frontend supporting more than 2
|
||||
* channels is the usb-audio. We will need some means to set channel
|
||||
* order when a new frontend gains multi-channel support.
|
||||
*/
|
||||
switch (channels) {
|
||||
case 8:
|
||||
v->info.position[0] = SPA_AUDIO_CHANNEL_FL;
|
||||
v->info.position[1] = SPA_AUDIO_CHANNEL_FR;
|
||||
v->info.position[2] = SPA_AUDIO_CHANNEL_FC;
|
||||
v->info.position[3] = SPA_AUDIO_CHANNEL_LFE;
|
||||
v->info.position[4] = SPA_AUDIO_CHANNEL_RL;
|
||||
v->info.position[5] = SPA_AUDIO_CHANNEL_RR;
|
||||
v->info.position[6] = SPA_AUDIO_CHANNEL_SL;
|
||||
v->info.position[7] = SPA_AUDIO_CHANNEL_SR;
|
||||
break;
|
||||
position[6] = SPA_AUDIO_CHANNEL_SL;
|
||||
position[7] = SPA_AUDIO_CHANNEL_SR;
|
||||
/* fallthrough */
|
||||
case 6:
|
||||
v->info.position[0] = SPA_AUDIO_CHANNEL_FL;
|
||||
v->info.position[1] = SPA_AUDIO_CHANNEL_FR;
|
||||
v->info.position[2] = SPA_AUDIO_CHANNEL_FC;
|
||||
v->info.position[3] = SPA_AUDIO_CHANNEL_LFE;
|
||||
v->info.position[4] = SPA_AUDIO_CHANNEL_RL;
|
||||
v->info.position[5] = SPA_AUDIO_CHANNEL_RR;
|
||||
break;
|
||||
case 5:
|
||||
v->info.position[0] = SPA_AUDIO_CHANNEL_FL;
|
||||
v->info.position[1] = SPA_AUDIO_CHANNEL_FR;
|
||||
v->info.position[2] = SPA_AUDIO_CHANNEL_FC;
|
||||
v->info.position[3] = SPA_AUDIO_CHANNEL_LFE;
|
||||
v->info.position[4] = SPA_AUDIO_CHANNEL_RC;
|
||||
break;
|
||||
case 4:
|
||||
v->info.position[0] = SPA_AUDIO_CHANNEL_FL;
|
||||
v->info.position[1] = SPA_AUDIO_CHANNEL_FR;
|
||||
v->info.position[2] = SPA_AUDIO_CHANNEL_FC;
|
||||
v->info.position[3] = SPA_AUDIO_CHANNEL_RC;
|
||||
break;
|
||||
case 3:
|
||||
v->info.position[0] = SPA_AUDIO_CHANNEL_FL;
|
||||
v->info.position[1] = SPA_AUDIO_CHANNEL_FR;
|
||||
v->info.position[2] = SPA_AUDIO_CHANNEL_LFE;
|
||||
break;
|
||||
position[2] = SPA_AUDIO_CHANNEL_FC;
|
||||
position[3] = SPA_AUDIO_CHANNEL_LFE;
|
||||
position[4] = SPA_AUDIO_CHANNEL_RL;
|
||||
position[5] = SPA_AUDIO_CHANNEL_RR;
|
||||
/* fallthrough */
|
||||
case 2:
|
||||
v->info.position[0] = SPA_AUDIO_CHANNEL_FL;
|
||||
v->info.position[1] = SPA_AUDIO_CHANNEL_FR;
|
||||
position[0] = SPA_AUDIO_CHANNEL_FL;
|
||||
position[1] = SPA_AUDIO_CHANNEL_FR;
|
||||
break;
|
||||
case 1:
|
||||
v->info.position[0] = SPA_AUDIO_CHANNEL_MONO;
|
||||
position[0] = SPA_AUDIO_CHANNEL_MONO;
|
||||
break;
|
||||
default:
|
||||
for (size_t i = 0; i < v->info.channels; i++) {
|
||||
v->info.position[i] = SPA_AUDIO_CHANNEL_UNKNOWN;
|
||||
}
|
||||
break;
|
||||
dolog("Internal error: unsupported channel count %d\n", channels);
|
||||
}
|
||||
|
||||
/* create a new unconnected pwstream */
|
||||
r = create_stream(c, v, stream_name, name, dir);
|
||||
if (r < 0) {
|
||||
AUD_log(AUDIO_CAP, "Failed to create stream.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -566,6 +530,7 @@ qpw_init_out(HWVoiceOut *hw, struct audsettings *as, void *drv_opaque)
|
||||
|
||||
v->info.format = audfmt_to_pw(as->fmt, as->endianness);
|
||||
v->info.channels = as->nchannels;
|
||||
qpw_set_position(as->nchannels, v->info.position);
|
||||
v->info.rate = as->freq;
|
||||
|
||||
obt_as.fmt =
|
||||
@@ -579,7 +544,6 @@ qpw_init_out(HWVoiceOut *hw, struct audsettings *as, void *drv_opaque)
|
||||
r = qpw_stream_new(c, v, ppdo->stream_name ? : c->dev->id,
|
||||
ppdo->name, SPA_DIRECTION_OUTPUT);
|
||||
if (r < 0) {
|
||||
error_report("qpw_stream_new for playback failed");
|
||||
pw_thread_loop_unlock(c->thread_loop);
|
||||
return -1;
|
||||
}
|
||||
@@ -613,6 +577,7 @@ qpw_init_in(HWVoiceIn *hw, struct audsettings *as, void *drv_opaque)
|
||||
|
||||
v->info.format = audfmt_to_pw(as->fmt, as->endianness);
|
||||
v->info.channels = as->nchannels;
|
||||
qpw_set_position(as->nchannels, v->info.position);
|
||||
v->info.rate = as->freq;
|
||||
|
||||
obt_as.fmt =
|
||||
@@ -623,7 +588,6 @@ qpw_init_in(HWVoiceIn *hw, struct audsettings *as, void *drv_opaque)
|
||||
r = qpw_stream_new(c, v, ppdo->stream_name ? : c->dev->id,
|
||||
ppdo->name, SPA_DIRECTION_INPUT);
|
||||
if (r < 0) {
|
||||
error_report("qpw_stream_new for recording failed");
|
||||
pw_thread_loop_unlock(c->thread_loop);
|
||||
return -1;
|
||||
}
|
||||
@@ -639,106 +603,86 @@ qpw_init_in(HWVoiceIn *hw, struct audsettings *as, void *drv_opaque)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
qpw_voice_fini(PWVoice *v)
|
||||
{
|
||||
pwaudio *c = v->g;
|
||||
|
||||
if (!v->stream) {
|
||||
return;
|
||||
}
|
||||
pw_thread_loop_lock(c->thread_loop);
|
||||
pw_stream_destroy(v->stream);
|
||||
v->stream = NULL;
|
||||
pw_thread_loop_unlock(c->thread_loop);
|
||||
}
|
||||
|
||||
static void
|
||||
qpw_fini_out(HWVoiceOut *hw)
|
||||
{
|
||||
PWVoiceOut *pw = (PWVoiceOut *) hw;
|
||||
PWVoice *v = &pw->v;
|
||||
|
||||
if (v->stream) {
|
||||
pwaudio *c = v->g;
|
||||
pw_thread_loop_lock(c->thread_loop);
|
||||
pw_stream_destroy(v->stream);
|
||||
v->stream = NULL;
|
||||
pw_thread_loop_unlock(c->thread_loop);
|
||||
}
|
||||
qpw_voice_fini(&PW_VOICE_OUT(hw)->v);
|
||||
}
|
||||
|
||||
static void
|
||||
qpw_fini_in(HWVoiceIn *hw)
|
||||
{
|
||||
PWVoiceIn *pw = (PWVoiceIn *) hw;
|
||||
PWVoice *v = &pw->v;
|
||||
|
||||
if (v->stream) {
|
||||
pwaudio *c = v->g;
|
||||
pw_thread_loop_lock(c->thread_loop);
|
||||
pw_stream_destroy(v->stream);
|
||||
v->stream = NULL;
|
||||
pw_thread_loop_unlock(c->thread_loop);
|
||||
}
|
||||
qpw_voice_fini(&PW_VOICE_IN(hw)->v);
|
||||
}
|
||||
|
||||
static void
|
||||
qpw_enable_out(HWVoiceOut *hw, bool enable)
|
||||
qpw_voice_set_enabled(PWVoice *v, bool enable)
|
||||
{
|
||||
PWVoiceOut *po = (PWVoiceOut *) hw;
|
||||
PWVoice *v = &po->v;
|
||||
pwaudio *c = v->g;
|
||||
pw_thread_loop_lock(c->thread_loop);
|
||||
pw_stream_set_active(v->stream, enable);
|
||||
pw_thread_loop_unlock(c->thread_loop);
|
||||
}
|
||||
|
||||
static void
|
||||
qpw_enable_out(HWVoiceOut *hw, bool enable)
|
||||
{
|
||||
qpw_voice_set_enabled(&PW_VOICE_OUT(hw)->v, enable);
|
||||
}
|
||||
|
||||
static void
|
||||
qpw_enable_in(HWVoiceIn *hw, bool enable)
|
||||
{
|
||||
PWVoiceIn *pi = (PWVoiceIn *) hw;
|
||||
PWVoice *v = &pi->v;
|
||||
qpw_voice_set_enabled(&PW_VOICE_IN(hw)->v, enable);
|
||||
}
|
||||
|
||||
static void
|
||||
qpw_voice_set_volume(PWVoice *v, Volume *vol)
|
||||
{
|
||||
pwaudio *c = v->g;
|
||||
int i, ret;
|
||||
|
||||
pw_thread_loop_lock(c->thread_loop);
|
||||
pw_stream_set_active(v->stream, enable);
|
||||
v->volume.channels = vol->channels;
|
||||
|
||||
for (i = 0; i < vol->channels; ++i) {
|
||||
v->volume.values[i] = (float)vol->vol[i] / 255;
|
||||
}
|
||||
|
||||
ret = pw_stream_set_control(v->stream,
|
||||
SPA_PROP_channelVolumes, v->volume.channels, v->volume.values, 0);
|
||||
trace_pw_vol(ret == 0 ? "success" : "failed");
|
||||
|
||||
v->muted = vol->mute;
|
||||
float val = v->muted ? 1.f : 0.f;
|
||||
ret = pw_stream_set_control(v->stream, SPA_PROP_mute, 1, &val, 0);
|
||||
pw_thread_loop_unlock(c->thread_loop);
|
||||
}
|
||||
|
||||
static void
|
||||
qpw_volume_out(HWVoiceOut *hw, Volume *vol)
|
||||
{
|
||||
PWVoiceOut *pw = (PWVoiceOut *) hw;
|
||||
PWVoice *v = &pw->v;
|
||||
pwaudio *c = v->g;
|
||||
int i, ret;
|
||||
|
||||
pw_thread_loop_lock(c->thread_loop);
|
||||
v->volume.channels = vol->channels;
|
||||
|
||||
for (i = 0; i < vol->channels; ++i) {
|
||||
v->volume.values[i] = (float)vol->vol[i] / 255;
|
||||
}
|
||||
|
||||
ret = pw_stream_set_control(v->stream,
|
||||
SPA_PROP_channelVolumes, v->volume.channels, v->volume.values, 0);
|
||||
trace_pw_vol(ret == 0 ? "success" : "failed");
|
||||
|
||||
v->muted = vol->mute;
|
||||
float val = v->muted ? 1.f : 0.f;
|
||||
ret = pw_stream_set_control(v->stream, SPA_PROP_mute, 1, &val, 0);
|
||||
pw_thread_loop_unlock(c->thread_loop);
|
||||
qpw_voice_set_volume(&PW_VOICE_OUT(hw)->v, vol);
|
||||
}
|
||||
|
||||
static void
|
||||
qpw_volume_in(HWVoiceIn *hw, Volume *vol)
|
||||
{
|
||||
PWVoiceIn *pw = (PWVoiceIn *) hw;
|
||||
PWVoice *v = &pw->v;
|
||||
pwaudio *c = v->g;
|
||||
int i, ret;
|
||||
|
||||
pw_thread_loop_lock(c->thread_loop);
|
||||
v->volume.channels = vol->channels;
|
||||
|
||||
for (i = 0; i < vol->channels; ++i) {
|
||||
v->volume.values[i] = (float)vol->vol[i] / 255;
|
||||
}
|
||||
|
||||
ret = pw_stream_set_control(v->stream,
|
||||
SPA_PROP_channelVolumes, v->volume.channels, v->volume.values, 0);
|
||||
trace_pw_vol(ret == 0 ? "success" : "failed");
|
||||
|
||||
v->muted = vol->mute;
|
||||
float val = v->muted ? 1.f : 0.f;
|
||||
ret = pw_stream_set_control(v->stream, SPA_PROP_mute, 1, &val, 0);
|
||||
pw_thread_loop_unlock(c->thread_loop);
|
||||
qpw_voice_set_volume(&PW_VOICE_IN(hw)->v, vol);
|
||||
}
|
||||
|
||||
static int wait_resync(pwaudio *pw)
|
||||
@@ -760,6 +704,7 @@ static int wait_resync(pwaudio *pw)
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
on_core_error(void *data, uint32_t id, int seq, int res, const char *message)
|
||||
{
|
||||
@@ -794,27 +739,28 @@ static void *
|
||||
qpw_audio_init(Audiodev *dev)
|
||||
{
|
||||
g_autofree pwaudio *pw = g_new0(pwaudio, 1);
|
||||
|
||||
assert(dev->driver == AUDIODEV_DRIVER_PIPEWIRE);
|
||||
trace_pw_audio_init();
|
||||
|
||||
pw_init(NULL, NULL);
|
||||
|
||||
trace_pw_audio_init();
|
||||
assert(dev->driver == AUDIODEV_DRIVER_PIPEWIRE);
|
||||
|
||||
pw->dev = dev;
|
||||
pw->thread_loop = pw_thread_loop_new("Pipewire thread loop", NULL);
|
||||
pw->thread_loop = pw_thread_loop_new("PipeWire thread loop", NULL);
|
||||
if (pw->thread_loop == NULL) {
|
||||
error_report("Could not create Pipewire loop");
|
||||
error_report("Could not create PipeWire loop: %s", g_strerror(errno));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
pw->context =
|
||||
pw_context_new(pw_thread_loop_get_loop(pw->thread_loop), NULL, 0);
|
||||
if (pw->context == NULL) {
|
||||
error_report("Could not create Pipewire context");
|
||||
error_report("Could not create PipeWire context: %s", g_strerror(errno));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (pw_thread_loop_start(pw->thread_loop) < 0) {
|
||||
error_report("Could not start Pipewire loop");
|
||||
error_report("Could not start PipeWire loop: %s", g_strerror(errno));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
@@ -844,12 +790,8 @@ fail:
|
||||
if (pw->thread_loop) {
|
||||
pw_thread_loop_stop(pw->thread_loop);
|
||||
}
|
||||
if (pw->context) {
|
||||
g_clear_pointer(&pw->context, pw_context_destroy);
|
||||
}
|
||||
if (pw->thread_loop) {
|
||||
g_clear_pointer(&pw->thread_loop, pw_thread_loop_destroy);
|
||||
}
|
||||
g_clear_pointer(&pw->context, pw_context_destroy);
|
||||
g_clear_pointer(&pw->thread_loop, pw_thread_loop_destroy);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -24,7 +24,7 @@ pw_read(int32_t avail, uint32_t index, size_t len) "avail=%d index=%u len=%zu"
|
||||
pw_write(int32_t filled, int32_t avail, uint32_t index, size_t len) "filled=%d avail=%d index=%u len=%zu"
|
||||
pw_vol(const char *ret) "set volume: %s"
|
||||
pw_period(uint64_t quantum, uint32_t rate) "period =%" PRIu64 "/%u"
|
||||
pw_audio_init(void) "Initialize Pipewire context"
|
||||
pw_audio_init(void) "Initialize PipeWire context"
|
||||
|
||||
# audio.c
|
||||
audio_timer_start(int interval) "interval %d ms"
|
||||
|
||||
@@ -181,13 +181,13 @@ static VGPUDMABuf
|
||||
}
|
||||
|
||||
dmabuf = g_new0(VGPUDMABuf, 1);
|
||||
dmabuf->buf.width = fb->width;
|
||||
dmabuf->buf.height = fb->height;
|
||||
dmabuf->buf.width = r->width;
|
||||
dmabuf->buf.height = r->height;
|
||||
dmabuf->buf.stride = fb->stride;
|
||||
dmabuf->buf.x = r->x;
|
||||
dmabuf->buf.y = r->y;
|
||||
dmabuf->buf.scanout_width = r->width;
|
||||
dmabuf->buf.scanout_height = r->height;
|
||||
dmabuf->buf.backing_width = fb->width;
|
||||
dmabuf->buf.backing_height = fb->height;
|
||||
dmabuf->buf.fourcc = qemu_pixman_to_drm_format(fb->format);
|
||||
dmabuf->buf.fd = res->dmabuf_fd;
|
||||
dmabuf->buf.allow_fences = true;
|
||||
@@ -218,8 +218,8 @@ int virtio_gpu_update_dmabuf(VirtIOGPU *g,
|
||||
|
||||
g->dmabuf.primary[scanout_id] = new_primary;
|
||||
qemu_console_resize(scanout->con,
|
||||
new_primary->buf.scanout_width,
|
||||
new_primary->buf.scanout_height);
|
||||
new_primary->buf.width,
|
||||
new_primary->buf.height);
|
||||
dpy_gl_scanout_dmabuf(scanout->con, &new_primary->buf);
|
||||
|
||||
if (old_primary) {
|
||||
|
||||
+14
-7
@@ -303,10 +303,11 @@ static void virtio_gpu_resource_create_2d(VirtIOGPU *g,
|
||||
goto end;
|
||||
}
|
||||
#endif
|
||||
res->image = pixman_image_create_bits(pformat,
|
||||
c2d.width,
|
||||
c2d.height,
|
||||
bits, res->hostmem / c2d.height);
|
||||
res->image = pixman_image_create_bits(
|
||||
pformat,
|
||||
c2d.width,
|
||||
c2d.height,
|
||||
bits, c2d.height ? res->hostmem / c2d.height : 0);
|
||||
#ifdef WIN32
|
||||
if (res->image) {
|
||||
pixman_image_set_destroy_function(res->image, win32_pixman_image_destroy, res->handle);
|
||||
@@ -1272,9 +1273,10 @@ static int virtio_gpu_load(QEMUFile *f, void *opaque, size_t size,
|
||||
return -EINVAL;
|
||||
}
|
||||
#endif
|
||||
res->image = pixman_image_create_bits(pformat,
|
||||
res->width, res->height,
|
||||
bits, res->hostmem / res->height);
|
||||
res->image = pixman_image_create_bits(
|
||||
pformat,
|
||||
res->width, res->height,
|
||||
bits, res->height ? res->hostmem / res->height : 0);
|
||||
if (!res->image) {
|
||||
g_free(res);
|
||||
return -EINVAL;
|
||||
@@ -1395,6 +1397,7 @@ void virtio_gpu_reset(VirtIODevice *vdev)
|
||||
VirtIOGPU *g = VIRTIO_GPU(vdev);
|
||||
struct virtio_gpu_simple_resource *res, *tmp;
|
||||
struct virtio_gpu_ctrl_command *cmd;
|
||||
int i = 0;
|
||||
|
||||
QTAILQ_FOREACH_SAFE(res, &g->reslist, next, tmp) {
|
||||
virtio_gpu_resource_destroy(g, res);
|
||||
@@ -1413,6 +1416,10 @@ void virtio_gpu_reset(VirtIODevice *vdev)
|
||||
g_free(cmd);
|
||||
}
|
||||
|
||||
for (i = 0; i < g->parent_obj.conf.max_outputs; i++) {
|
||||
dpy_gfx_replace_surface(g->parent_obj.scanout[i].con, NULL);
|
||||
}
|
||||
|
||||
virtio_gpu_base_reset(VIRTIO_GPU_BASE(vdev));
|
||||
}
|
||||
|
||||
|
||||
@@ -201,8 +201,8 @@ typedef struct QemuDmaBuf {
|
||||
uint32_t texture;
|
||||
uint32_t x;
|
||||
uint32_t y;
|
||||
uint32_t scanout_width;
|
||||
uint32_t scanout_height;
|
||||
uint32_t backing_width;
|
||||
uint32_t backing_height;
|
||||
bool y0_top;
|
||||
void *sync;
|
||||
int fence_fd;
|
||||
|
||||
+1
-1
@@ -4251,7 +4251,7 @@ if targetos == 'linux'
|
||||
summary_info += {'ALSA support': alsa}
|
||||
summary_info += {'PulseAudio support': pulse}
|
||||
endif
|
||||
summary_info += {'Pipewire support': pipewire}
|
||||
summary_info += {'PipeWire support': pipewire}
|
||||
summary_info += {'JACK support': jack}
|
||||
summary(summary_info, bool_yn: true, section: 'Audio backends')
|
||||
|
||||
|
||||
+1
-1
@@ -267,7 +267,7 @@ option('oss', type: 'feature', value: 'auto',
|
||||
option('pa', type: 'feature', value: 'auto',
|
||||
description: 'PulseAudio sound support')
|
||||
option('pipewire', type: 'feature', value: 'auto',
|
||||
description: 'Pipewire sound support')
|
||||
description: 'PipeWire sound support')
|
||||
option('sndio', type: 'feature', value: 'auto',
|
||||
description: 'sndio sound support')
|
||||
|
||||
|
||||
+6
-6
@@ -328,17 +328,17 @@
|
||||
##
|
||||
# @AudiodevPipewirePerDirectionOptions:
|
||||
#
|
||||
# Options of the Pipewire backend that are used for both playback and
|
||||
# Options of the PipeWire backend that are used for both playback and
|
||||
# recording.
|
||||
#
|
||||
# @name: name of the sink/source to use
|
||||
#
|
||||
# @stream-name: name of the Pipewire stream created by qemu. Can be
|
||||
# used to identify the stream in Pipewire when you create multiple
|
||||
# Pipewire devices or run multiple qemu instances (default:
|
||||
# @stream-name: name of the PipeWire stream created by qemu. Can be
|
||||
# used to identify the stream in PipeWire when you create multiple
|
||||
# PipeWire devices or run multiple qemu instances (default:
|
||||
# audiodev's id)
|
||||
#
|
||||
# @latency: latency you want Pipewire to achieve in microseconds
|
||||
# @latency: latency you want PipeWire to achieve in microseconds
|
||||
# (default 46000)
|
||||
#
|
||||
# Since: 8.1
|
||||
@@ -353,7 +353,7 @@
|
||||
##
|
||||
# @AudiodevPipewireOptions:
|
||||
#
|
||||
# Options of the Pipewire audio backend.
|
||||
# Options of the PipeWire audio backend.
|
||||
#
|
||||
# @in: options of the capture stream
|
||||
#
|
||||
|
||||
+2
-2
@@ -963,10 +963,10 @@ SRST
|
||||
to honor this value but actual latencies may be lower or higher.
|
||||
|
||||
``-audiodev pipewire,id=id[,prop[=value][,...]]``
|
||||
Creates a backend using Pipewire. This backend is available on
|
||||
Creates a backend using PipeWire. This backend is available on
|
||||
most systems.
|
||||
|
||||
Pipewire specific options are:
|
||||
PipeWire specific options are:
|
||||
|
||||
``in|out.latency=usecs``
|
||||
Desired latency in microseconds.
|
||||
|
||||
@@ -145,7 +145,7 @@ meson_options_help() {
|
||||
printf "%s\n" ' oss OSS sound support'
|
||||
printf "%s\n" ' pa PulseAudio sound support'
|
||||
printf "%s\n" ' parallels parallels image format support'
|
||||
printf "%s\n" ' pipewire Pipewire sound support'
|
||||
printf "%s\n" ' pipewire PipeWire sound support'
|
||||
printf "%s\n" ' png PNG support with libpng'
|
||||
printf "%s\n" ' pvrdma Enable PVRDMA support'
|
||||
printf "%s\n" ' qcow1 qcow1 image format support'
|
||||
|
||||
@@ -77,6 +77,7 @@ RUN apk update && \
|
||||
numactl-dev \
|
||||
openssh-client \
|
||||
pcre-dev \
|
||||
pipewire-dev \
|
||||
pixman-dev \
|
||||
pkgconf \
|
||||
pulseaudio-dev \
|
||||
|
||||
@@ -90,6 +90,7 @@ RUN dnf distro-sync -y && \
|
||||
openssh-clients \
|
||||
pam-devel \
|
||||
pcre-static \
|
||||
pipewire-devel \
|
||||
pixman-devel \
|
||||
pkgconfig \
|
||||
pulseaudio-libs-devel \
|
||||
|
||||
@@ -116,6 +116,7 @@ RUN export DEBIAN_FRONTEND=noninteractive && \
|
||||
libnfs-dev:amd64 \
|
||||
libnuma-dev:amd64 \
|
||||
libpam0g-dev:amd64 \
|
||||
libpipewire-0.3-dev:amd64 \
|
||||
libpixman-1-dev:amd64 \
|
||||
libpmem-dev:amd64 \
|
||||
libpng-dev:amd64 \
|
||||
|
||||
@@ -69,6 +69,7 @@ RUN export DEBIAN_FRONTEND=noninteractive && \
|
||||
libnuma-dev \
|
||||
libpam0g-dev \
|
||||
libpcre2-dev \
|
||||
libpipewire-0.3-dev \
|
||||
libpixman-1-dev \
|
||||
libpmem-dev \
|
||||
libpng-dev \
|
||||
|
||||
@@ -116,6 +116,7 @@ RUN export DEBIAN_FRONTEND=noninteractive && \
|
||||
libnfs-dev:arm64 \
|
||||
libnuma-dev:arm64 \
|
||||
libpam0g-dev:arm64 \
|
||||
libpipewire-0.3-dev:arm64 \
|
||||
libpixman-1-dev:arm64 \
|
||||
libpng-dev:arm64 \
|
||||
libpulse-dev:arm64 \
|
||||
|
||||
@@ -116,6 +116,7 @@ RUN export DEBIAN_FRONTEND=noninteractive && \
|
||||
libnfs-dev:armel \
|
||||
libnuma-dev:armel \
|
||||
libpam0g-dev:armel \
|
||||
libpipewire-0.3-dev:armel \
|
||||
libpixman-1-dev:armel \
|
||||
libpng-dev:armel \
|
||||
libpulse-dev:armel \
|
||||
|
||||
@@ -116,6 +116,7 @@ RUN export DEBIAN_FRONTEND=noninteractive && \
|
||||
libnfs-dev:armhf \
|
||||
libnuma-dev:armhf \
|
||||
libpam0g-dev:armhf \
|
||||
libpipewire-0.3-dev:armhf \
|
||||
libpixman-1-dev:armhf \
|
||||
libpng-dev:armhf \
|
||||
libpulse-dev:armhf \
|
||||
|
||||
@@ -115,6 +115,7 @@ RUN export DEBIAN_FRONTEND=noninteractive && \
|
||||
libnfs-dev:mips64el \
|
||||
libnuma-dev:mips64el \
|
||||
libpam0g-dev:mips64el \
|
||||
libpipewire-0.3-dev:mips64el \
|
||||
libpixman-1-dev:mips64el \
|
||||
libpng-dev:mips64el \
|
||||
libpulse-dev:mips64el \
|
||||
|
||||
@@ -115,6 +115,7 @@ RUN export DEBIAN_FRONTEND=noninteractive && \
|
||||
libnfs-dev:mipsel \
|
||||
libnuma-dev:mipsel \
|
||||
libpam0g-dev:mipsel \
|
||||
libpipewire-0.3-dev:mipsel \
|
||||
libpixman-1-dev:mipsel \
|
||||
libpng-dev:mipsel \
|
||||
libpulse-dev:mipsel \
|
||||
|
||||
@@ -116,6 +116,7 @@ RUN export DEBIAN_FRONTEND=noninteractive && \
|
||||
libnfs-dev:ppc64el \
|
||||
libnuma-dev:ppc64el \
|
||||
libpam0g-dev:ppc64el \
|
||||
libpipewire-0.3-dev:ppc64el \
|
||||
libpixman-1-dev:ppc64el \
|
||||
libpng-dev:ppc64el \
|
||||
libpulse-dev:ppc64el \
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user