aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--audio/alsaaudio.c12
-rw-r--r--audio/audio_template.h15
-rw-r--r--audio/ossaudio.c6
-rw-r--r--hw/audio/adlib.c4
-rw-r--r--hw/display/qxl-render.c6
-rw-r--r--hw/display/qxl.c6
-rw-r--r--include/ui/spice-display.h14
-rw-r--r--qemu-char.c8
-rw-r--r--ui/spice-display.c129
-rw-r--r--util/qemu-sockets.c15
10 files changed, 174 insertions, 41 deletions
diff --git a/audio/alsaaudio.c b/audio/alsaaudio.c
index e4e5442..74ead97 100644
--- a/audio/alsaaudio.c
+++ b/audio/alsaaudio.c
@@ -815,10 +815,8 @@ static void alsa_fini_out (HWVoiceOut *hw)
ldebug ("alsa_fini\n");
alsa_anal_close (&alsa->handle, &alsa->pollhlp);
- if (alsa->pcm_buf) {
- g_free (alsa->pcm_buf);
- alsa->pcm_buf = NULL;
- }
+ g_free(alsa->pcm_buf);
+ alsa->pcm_buf = NULL;
}
static int alsa_init_out (HWVoiceOut *hw, struct audsettings *as)
@@ -978,10 +976,8 @@ static void alsa_fini_in (HWVoiceIn *hw)
alsa_anal_close (&alsa->handle, &alsa->pollhlp);
- if (alsa->pcm_buf) {
- g_free (alsa->pcm_buf);
- alsa->pcm_buf = NULL;
- }
+ g_free(alsa->pcm_buf);
+ alsa->pcm_buf = NULL;
}
static int alsa_run_in (HWVoiceIn *hw)
diff --git a/audio/audio_template.h b/audio/audio_template.h
index 16f7880..8173188 100644
--- a/audio/audio_template.h
+++ b/audio/audio_template.h
@@ -71,10 +71,7 @@ static void glue (audio_init_nb_voices_, TYPE) (struct audio_driver *drv)
static void glue (audio_pcm_hw_free_resources_, TYPE) (HW *hw)
{
- if (HWBUF) {
- g_free (HWBUF);
- }
-
+ g_free (HWBUF);
HWBUF = NULL;
}
@@ -92,9 +89,7 @@ static int glue (audio_pcm_hw_alloc_resources_, TYPE) (HW *hw)
static void glue (audio_pcm_sw_free_resources_, TYPE) (SW *sw)
{
- if (sw->buf) {
- g_free (sw->buf);
- }
+ g_free (sw->buf);
if (sw->rate) {
st_rate_stop (sw->rate);
@@ -172,10 +167,8 @@ static int glue (audio_pcm_sw_init_, TYPE) (
static void glue (audio_pcm_sw_fini_, TYPE) (SW *sw)
{
glue (audio_pcm_sw_free_resources_, TYPE) (sw);
- if (sw->name) {
- g_free (sw->name);
- sw->name = NULL;
- }
+ g_free (sw->name);
+ sw->name = NULL;
}
static void glue (audio_pcm_hw_add_sw_, TYPE) (HW *hw, SW *sw)
diff --git a/audio/ossaudio.c b/audio/ossaudio.c
index 5a73716..4db2ca6 100644
--- a/audio/ossaudio.c
+++ b/audio/ossaudio.c
@@ -736,10 +736,8 @@ static void oss_fini_in (HWVoiceIn *hw)
oss_anal_close (&oss->fd);
- if (oss->pcm_buf) {
- g_free (oss->pcm_buf);
- oss->pcm_buf = NULL;
- }
+ g_free(oss->pcm_buf);
+ oss->pcm_buf = NULL;
}
static int oss_run_in (HWVoiceIn *hw)
diff --git a/hw/audio/adlib.c b/hw/audio/adlib.c
index 5dd739e..656eb37 100644
--- a/hw/audio/adlib.c
+++ b/hw/audio/adlib.c
@@ -275,9 +275,7 @@ static void Adlib_fini (AdlibState *s)
}
#endif
- if (s->mixbuf) {
- g_free (s->mixbuf);
- }
+ g_free(s->mixbuf);
s->active = 0;
s->enabled = 0;
diff --git a/hw/display/qxl-render.c b/hw/display/qxl-render.c
index 84f1367..cc2c2b1 100644
--- a/hw/display/qxl-render.c
+++ b/hw/display/qxl-render.c
@@ -138,6 +138,12 @@ static void qxl_render_update_area_unlocked(PCIQXLDevice *qxl)
if (qemu_spice_rect_is_empty(qxl->dirty+i)) {
break;
}
+ if (qxl->dirty[i].left > qxl->dirty[i].right ||
+ qxl->dirty[i].top > qxl->dirty[i].bottom ||
+ qxl->dirty[i].right > qxl->guest_primary.surface.width ||
+ qxl->dirty[i].bottom > qxl->guest_primary.surface.height) {
+ continue;
+ }
qxl_blit(qxl, qxl->dirty+i);
dpy_gfx_update(vga->con,
qxl->dirty[i].left, qxl->dirty[i].top,
diff --git a/hw/display/qxl.c b/hw/display/qxl.c
index 7fb83e4..736fd3c 100644
--- a/hw/display/qxl.c
+++ b/hw/display/qxl.c
@@ -710,7 +710,11 @@ static void interface_release_resource(QXLInstance *sin,
if (ext.group_id == MEMSLOT_GROUP_HOST) {
/* host group -> vga mode update request */
- qemu_spice_destroy_update(&qxl->ssd, (void *)(intptr_t)ext.info->id);
+ QXLCommandExt *cmdext = (void *)(ext.info->id);
+ SimpleSpiceUpdate *update;
+ g_assert(cmdext->cmd.type == QXL_CMD_DRAW);
+ update = container_of(cmdext, SimpleSpiceUpdate, ext);
+ qemu_spice_destroy_update(&qxl->ssd, update);
return;
}
diff --git a/include/ui/spice-display.h b/include/ui/spice-display.h
index a46bc80..4252ab8 100644
--- a/include/ui/spice-display.h
+++ b/include/ui/spice-display.h
@@ -69,6 +69,7 @@ QXLCookie *qxl_cookie_new(int type, uint64_t io);
typedef struct SimpleSpiceDisplay SimpleSpiceDisplay;
typedef struct SimpleSpiceUpdate SimpleSpiceUpdate;
+typedef struct SimpleSpiceCursor SimpleSpiceCursor;
struct SimpleSpiceDisplay {
DisplaySurface *ds;
@@ -92,6 +93,13 @@ struct SimpleSpiceDisplay {
*/
QemuMutex lock;
QTAILQ_HEAD(, SimpleSpiceUpdate) updates;
+
+ /* cursor (without qxl): displaychangelistener -> spice server */
+ SimpleSpiceCursor *ptr_define;
+ SimpleSpiceCursor *ptr_move;
+ uint16_t ptr_x, ptr_y;
+
+ /* cursor (with qxl): qxl local renderer -> displaychangelistener */
QEMUCursor *cursor;
int mouse_x, mouse_y;
};
@@ -104,6 +112,12 @@ struct SimpleSpiceUpdate {
QTAILQ_ENTRY(SimpleSpiceUpdate) next;
};
+struct SimpleSpiceCursor {
+ QXLCursorCmd cmd;
+ QXLCommandExt ext;
+ QXLCursor cursor;
+};
+
int qemu_spice_rect_is_empty(const QXLRect* r);
void qemu_spice_rect_union(QXLRect *dest, const QXLRect *r);
diff --git a/qemu-char.c b/qemu-char.c
index 4c04bbc..f918f90 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -2493,7 +2493,13 @@ static gboolean tcp_chr_read(GIOChannel *chan, GIOCondition cond, void *opaque)
#ifndef _WIN32
CharDriverState *qemu_chr_open_eventfd(int eventfd)
{
- return qemu_chr_open_fd(eventfd, eventfd);
+ CharDriverState *chr = qemu_chr_open_fd(eventfd, eventfd);
+
+ if (chr) {
+ chr->avail_connections = 1;
+ }
+
+ return chr;
}
#endif
diff --git a/ui/spice-display.c b/ui/spice-display.c
index ce6b220..03040b1 100644
--- a/ui/spice-display.c
+++ b/ui/spice-display.c
@@ -153,7 +153,7 @@ static void qemu_spice_create_one_update(SimpleSpiceDisplay *ssd,
drawable->bbox = *rect;
drawable->clip.type = SPICE_CLIP_TYPE_NONE;
drawable->effect = QXL_EFFECT_OPAQUE;
- drawable->release_info.id = (uintptr_t)update;
+ drawable->release_info.id = (uintptr_t)(&update->ext);
drawable->type = QXL_DRAW_COPY;
drawable->surfaces_dest[0] = -1;
drawable->surfaces_dest[1] = -1;
@@ -264,6 +264,49 @@ static void qemu_spice_create_update(SimpleSpiceDisplay *ssd)
memset(&ssd->dirty, 0, sizeof(ssd->dirty));
}
+static SimpleSpiceCursor*
+qemu_spice_create_cursor_update(SimpleSpiceDisplay *ssd,
+ QEMUCursor *c)
+{
+ size_t size = c ? c->width * c->height * 4 : 0;
+ SimpleSpiceCursor *update;
+ QXLCursorCmd *ccmd;
+ QXLCursor *cursor;
+ QXLCommand *cmd;
+
+ update = g_malloc0(sizeof(*update) + size);
+ ccmd = &update->cmd;
+ cursor = &update->cursor;
+ cmd = &update->ext.cmd;
+
+ if (c) {
+ ccmd->type = QXL_CURSOR_SET;
+ ccmd->u.set.position.x = ssd->ptr_x;
+ ccmd->u.set.position.y = ssd->ptr_y;
+ ccmd->u.set.visible = true;
+ ccmd->u.set.shape = (uintptr_t)cursor;
+ cursor->header.unique = ssd->unique++;
+ cursor->header.type = SPICE_CURSOR_TYPE_ALPHA;
+ cursor->header.width = c->width;
+ cursor->header.height = c->height;
+ cursor->header.hot_spot_x = c->hot_x;
+ cursor->header.hot_spot_y = c->hot_y;
+ cursor->data_size = size;
+ cursor->chunk.data_size = size;
+ memcpy(cursor->chunk.data, c->data, size);
+ } else {
+ ccmd->type = QXL_CURSOR_MOVE;
+ ccmd->u.position.x = ssd->ptr_x;
+ ccmd->u.position.y = ssd->ptr_y;
+ }
+ ccmd->release_info.id = (uintptr_t)(&update->ext);
+
+ cmd->type = QXL_CMD_CURSOR;
+ cmd->data = (uintptr_t)ccmd;
+
+ return update;
+}
+
/*
* Called from spice server thread context (via interface_release_resource)
* We do *not* hold the global qemu mutex here, so extra care is needed
@@ -483,20 +526,50 @@ static int interface_req_cmd_notification(QXLInstance *sin)
}
static void interface_release_resource(QXLInstance *sin,
- struct QXLReleaseInfoExt ext)
+ struct QXLReleaseInfoExt rext)
{
SimpleSpiceDisplay *ssd = container_of(sin, SimpleSpiceDisplay, qxl);
- uintptr_t id;
+ SimpleSpiceUpdate *update;
+ SimpleSpiceCursor *cursor;
+ QXLCommandExt *ext;
dprint(2, "%s/%d:\n", __func__, ssd->qxl.id);
- id = ext.info->id;
- qemu_spice_destroy_update(ssd, (void*)id);
+ ext = (void *)(rext.info->id);
+ switch (ext->cmd.type) {
+ case QXL_CMD_DRAW:
+ update = container_of(ext, SimpleSpiceUpdate, ext);
+ qemu_spice_destroy_update(ssd, update);
+ break;
+ case QXL_CMD_CURSOR:
+ cursor = container_of(ext, SimpleSpiceCursor, ext);
+ g_free(cursor);
+ break;
+ default:
+ g_assert_not_reached();
+ }
}
static int interface_get_cursor_command(QXLInstance *sin, struct QXLCommandExt *ext)
{
- dprint(3, "%s:\n", __FUNCTION__);
- return false;
+ SimpleSpiceDisplay *ssd = container_of(sin, SimpleSpiceDisplay, qxl);
+ int ret;
+
+ dprint(3, "%s/%d:\n", __func__, ssd->qxl.id);
+
+ qemu_mutex_lock(&ssd->lock);
+ if (ssd->ptr_define) {
+ *ext = ssd->ptr_define->ext;
+ ssd->ptr_define = NULL;
+ ret = true;
+ } else if (ssd->ptr_move) {
+ *ext = ssd->ptr_move->ext;
+ ssd->ptr_move = NULL;
+ ret = true;
+ } else {
+ ret = false;
+ }
+ qemu_mutex_unlock(&ssd->lock);
+ return ret;
}
static int interface_req_cursor_notification(QXLInstance *sin)
@@ -617,11 +690,45 @@ static void display_refresh(DisplayChangeListener *dcl)
qemu_spice_display_refresh(ssd);
}
+static void display_mouse_set(DisplayChangeListener *dcl,
+ int x, int y, int on)
+{
+ SimpleSpiceDisplay *ssd = container_of(dcl, SimpleSpiceDisplay, dcl);
+
+ qemu_mutex_lock(&ssd->lock);
+ ssd->ptr_x = x;
+ ssd->ptr_y = x;
+ if (ssd->ptr_move) {
+ g_free(ssd->ptr_move);
+ }
+ ssd->ptr_move = qemu_spice_create_cursor_update(ssd, NULL);
+ qemu_mutex_unlock(&ssd->lock);
+}
+
+static void display_mouse_define(DisplayChangeListener *dcl,
+ QEMUCursor *c)
+{
+ SimpleSpiceDisplay *ssd = container_of(dcl, SimpleSpiceDisplay, dcl);
+
+ qemu_mutex_lock(&ssd->lock);
+ if (ssd->ptr_move) {
+ g_free(ssd->ptr_move);
+ ssd->ptr_move = NULL;
+ }
+ if (ssd->ptr_define) {
+ g_free(ssd->ptr_define);
+ }
+ ssd->ptr_define = qemu_spice_create_cursor_update(ssd, c);
+ qemu_mutex_unlock(&ssd->lock);
+}
+
static const DisplayChangeListenerOps display_listener_ops = {
- .dpy_name = "spice",
- .dpy_gfx_update = display_update,
- .dpy_gfx_switch = display_switch,
- .dpy_refresh = display_refresh,
+ .dpy_name = "spice",
+ .dpy_gfx_update = display_update,
+ .dpy_gfx_switch = display_switch,
+ .dpy_refresh = display_refresh,
+ .dpy_mouse_set = display_mouse_set,
+ .dpy_cursor_define = display_mouse_define,
};
static void qemu_spice_display_init_one(QemuConsole *con)
diff --git a/util/qemu-sockets.c b/util/qemu-sockets.c
index e3d29ee..a4a1e9d 100644
--- a/util/qemu-sockets.c
+++ b/util/qemu-sockets.c
@@ -131,8 +131,19 @@ int inet_listen_opts(QemuOpts *opts, int port_offset, Error **errp)
ai.ai_family = PF_INET6;
/* lookup */
- if (port_offset)
- snprintf(port, sizeof(port), "%d", atoi(port) + port_offset);
+ if (port_offset) {
+ unsigned long long baseport;
+ if (parse_uint_full(port, &baseport, 10) < 0) {
+ error_setg(errp, "can't convert to a number: %s", port);
+ return -1;
+ }
+ if (baseport > 65535 ||
+ baseport + port_offset > 65535) {
+ error_setg(errp, "port %s out of range", port);
+ return -1;
+ }
+ snprintf(port, sizeof(port), "%d", (int)baseport + port_offset);
+ }
rc = getaddrinfo(strlen(addr) ? addr : NULL, port, &ai, &res);
if (rc != 0) {
error_setg(errp, "address resolution failed for %s:%s: %s", addr, port,