Loading hw/display/qxl.c +5 −1 Original line number Diff line number Diff line Loading @@ -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; } Loading include/ui/spice-display.h +14 −0 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; }; Loading @@ -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); Loading ui/spice-display.c +118 −11 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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 Loading Loading @@ -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) Loading Loading @@ -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_mouse_set = display_mouse_set, .dpy_cursor_define = display_mouse_define, }; static void qemu_spice_display_init_one(QemuConsole *con) Loading Loading
hw/display/qxl.c +5 −1 Original line number Diff line number Diff line Loading @@ -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; } Loading
include/ui/spice-display.h +14 −0 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; }; Loading @@ -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); Loading
ui/spice-display.c +118 −11 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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 Loading Loading @@ -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) Loading Loading @@ -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_mouse_set = display_mouse_set, .dpy_cursor_define = display_mouse_define, }; static void qemu_spice_display_init_one(QemuConsole *con) Loading