Commit 592fb176 authored by Peter Maydell's avatar Peter Maydell
Browse files

Merge remote-tracking branch 'remotes/spice/tags/pull-spice-20140613-1' into staging



spice: add mouse cursor support
qxl-render: add sanity check

# gpg: Signature made Fri 13 Jun 2014 12:22:45 BST using RSA key ID D3E87138
# gpg: Good signature from "Gerd Hoffmann (work) <kraxel@redhat.com>"
# gpg:                 aka "Gerd Hoffmann <gerd@kraxel.org>"
# gpg:                 aka "Gerd Hoffmann (private) <kraxel@gmail.com>"

* remotes/spice/tags/pull-spice-20140613-1:
  qxl-render: add sanity check
  spice: add mouse cursor support

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parents 7d5bef08 788fbf04
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -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,
+5 −1
Original line number Diff line number Diff line
@@ -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;
    }

+14 −0
Original line number Diff line number Diff line
@@ -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);

+118 −11
Original line number Diff line number Diff line
@@ -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_mouse_set     = display_mouse_set,
    .dpy_cursor_define = display_mouse_define,
};

static void qemu_spice_display_init_one(QemuConsole *con)