Blame 0007-spice-simple-display.patch

Justin M. Forbes a81953
From 0143117eb5e6233fdeff3b679492b51148cc8f85 Mon Sep 17 00:00:00 2001
Justin M. Forbes a81953
From: Gerd Hoffmann <kraxel@redhat.com>
Justin M. Forbes a81953
Date: Wed, 24 Mar 2010 15:47:18 +0100
Justin M. Forbes a81953
Subject: [PATCH 07/39] spice: simple display
Justin M. Forbes a81953
Justin M. Forbes a81953
With that patch applied you'll actually see the guests screen in the
Justin M. Forbes a81953
spice client.  This does *not* bring qxl and full spice support though.
Justin M. Forbes a81953
This is basically the qxl vga mode made more generic, so it plays
Justin M. Forbes a81953
together with any qemu-emulated gfx card.  You can display stdvga or
Justin M. Forbes a81953
cirrus via spice client.  You can have both vnc and spice enabled and
Justin M. Forbes a81953
clients connected at the same time.
Justin M. Forbes a81953
---
Justin M. Forbes a81953
 Makefile.objs   |    2 +-
Justin M. Forbes a81953
 qemu-spice.h    |    1 +
Justin M. Forbes a81953
 spice-display.c |  394 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
Justin M. Forbes a81953
 spice-display.h |   52 ++++++++
Justin M. Forbes a81953
 vl.c            |    7 +-
Justin M. Forbes a81953
 5 files changed, 454 insertions(+), 2 deletions(-)
Justin M. Forbes a81953
 create mode 100644 spice-display.c
Justin M. Forbes a81953
 create mode 100644 spice-display.h
Justin M. Forbes a81953
Justin M. Forbes a81953
diff --git a/Makefile.objs b/Makefile.objs
Justin M. Forbes a81953
index 023a0dc..d05643f 100644
Justin M. Forbes a81953
--- a/Makefile.objs
Justin M. Forbes a81953
+++ b/Makefile.objs
Justin M. Forbes a81953
@@ -89,7 +89,7 @@ common-obj-y += pflib.o
Justin M. Forbes a81953
 common-obj-$(CONFIG_BRLAPI) += baum.o
Justin M. Forbes a81953
 common-obj-$(CONFIG_POSIX) += migration-exec.o migration-unix.o migration-fd.o
Justin M. Forbes a81953
Justin M. Forbes a81953
-common-obj-$(CONFIG_SPICE) += spice.o spice-input.o
Justin M. Forbes a81953
+common-obj-$(CONFIG_SPICE) += spice.o spice-input.o spice-display.o
Justin M. Forbes a81953
Justin M. Forbes a81953
 audio-obj-y = audio.o noaudio.o wavaudio.o mixeng.o
Justin M. Forbes a81953
 audio-obj-$(CONFIG_SDL) += sdlaudio.o
Justin M. Forbes a81953
diff --git a/qemu-spice.h b/qemu-spice.h
Justin M. Forbes a81953
index ceb3db2..f061004 100644
Justin M. Forbes a81953
--- a/qemu-spice.h
Justin M. Forbes a81953
+++ b/qemu-spice.h
Justin M. Forbes a81953
@@ -13,6 +13,7 @@ extern int using_spice;
Justin M. Forbes a81953
Justin M. Forbes a81953
 void qemu_spice_init(void);
Justin M. Forbes a81953
 void qemu_spice_input_init(void);
Justin M. Forbes a81953
+void qemu_spice_display_init(DisplayState *ds);
Justin M. Forbes a81953
Justin M. Forbes a81953
 #else  /* CONFIG_SPICE */
Justin M. Forbes a81953
Justin M. Forbes a81953
diff --git a/spice-display.c b/spice-display.c
Justin M. Forbes a81953
new file mode 100644
Justin M. Forbes a81953
index 0000000..13a620e
Justin M. Forbes a81953
--- /dev/null
Justin M. Forbes a81953
+++ b/spice-display.c
Justin M. Forbes a81953
@@ -0,0 +1,394 @@
Justin M. Forbes a81953
+#include <stdio.h>
Justin M. Forbes a81953
+#include <stdlib.h>
Justin M. Forbes a81953
+#include <stdbool.h>
Justin M. Forbes a81953
+#include <stdint.h>
Justin M. Forbes a81953
+#include <string.h>
Justin M. Forbes a81953
+#include <pthread.h>
Justin M. Forbes a81953
+
Justin M. Forbes a81953
+#include "qemu-common.h"
Justin M. Forbes a81953
+#include "qemu-spice.h"
Justin M. Forbes a81953
+#include "qemu-timer.h"
Justin M. Forbes a81953
+#include "qemu-queue.h"
Justin M. Forbes a81953
+#include "monitor.h"
Justin M. Forbes a81953
+#include "console.h"
Justin M. Forbes a81953
+#include "sysemu.h"
Justin M. Forbes a81953
+
Justin M. Forbes a81953
+#include "spice-display.h"
Justin M. Forbes a81953
+
Justin M. Forbes a81953
+static int debug = 1;
Justin M. Forbes a81953
+
Justin M. Forbes a81953
+int qemu_spice_rect_is_empty(const QXLRect* r)
Justin M. Forbes a81953
+{
Justin M. Forbes a81953
+    return r->top == r->bottom || r->left == r->right;
Justin M. Forbes a81953
+}
Justin M. Forbes a81953
+
Justin M. Forbes a81953
+void qemu_spice_rect_union(QXLRect *dest, const QXLRect *r)
Justin M. Forbes a81953
+{
Justin M. Forbes a81953
+    if (qemu_spice_rect_is_empty(r)) {
Justin M. Forbes a81953
+        return;
Justin M. Forbes a81953
+    }
Justin M. Forbes a81953
+
Justin M. Forbes a81953
+    if (qemu_spice_rect_is_empty(dest)) {
Justin M. Forbes a81953
+        *dest = *r;
Justin M. Forbes a81953
+        return;
Justin M. Forbes a81953
+    }
Justin M. Forbes a81953
+
Justin M. Forbes a81953
+    dest->top = MIN(dest->top, r->top);
Justin M. Forbes a81953
+    dest->left = MIN(dest->left, r->left);
Justin M. Forbes a81953
+    dest->bottom = MAX(dest->bottom, r->bottom);
Justin M. Forbes a81953
+    dest->right = MAX(dest->right, r->right);
Justin M. Forbes a81953
+}
Justin M. Forbes a81953
+
Justin M. Forbes a81953
+SimpleSpiceUpdate *qemu_spice_create_update(SimpleSpiceDisplay *ssd)
Justin M. Forbes a81953
+{
Justin M. Forbes a81953
+    SimpleSpiceUpdate *update;
Justin M. Forbes a81953
+    QXLDrawable *drawable;
Justin M. Forbes a81953
+    QXLImage *image;
Justin M. Forbes a81953
+    QXLCommand *cmd;
Justin M. Forbes a81953
+    uint8_t *src, *dst;
Justin M. Forbes a81953
+    int by, bw, bh;
Justin M. Forbes a81953
+
Justin M. Forbes a81953
+    if (qemu_spice_rect_is_empty(&ssd->dirty)) {
Justin M. Forbes a81953
+        return NULL;
Justin M. Forbes a81953
+    };
Justin M. Forbes a81953
+
Justin M. Forbes a81953
+    pthread_mutex_lock(&ssd->lock);
Justin M. Forbes a81953
+    if (debug > 1)
Justin M. Forbes a81953
+        fprintf(stderr, "%s: lr %d -> %d,  tb -> %d -> %d\n", __FUNCTION__,
Justin M. Forbes a81953
+                ssd->dirty.left, ssd->dirty.right,
Justin M. Forbes a81953
+                ssd->dirty.top, ssd->dirty.bottom);
Justin M. Forbes a81953
+
Justin M. Forbes a81953
+    update   = qemu_mallocz(sizeof(*update));
Justin M. Forbes a81953
+    drawable = &update->drawable;
Justin M. Forbes a81953
+    image    = &update->image;
Justin M. Forbes a81953
+    cmd      = &update->ext.cmd;
Justin M. Forbes a81953
+
Justin M. Forbes a81953
+    bw       = ssd->dirty.right - ssd->dirty.left;
Justin M. Forbes a81953
+    bh       = ssd->dirty.bottom - ssd->dirty.top;
Justin M. Forbes a81953
+    update->bitmap = qemu_malloc(bw * bh * 4);
Justin M. Forbes a81953
+
Justin M. Forbes a81953
+    drawable->bbox            = ssd->dirty;
Justin M. Forbes a81953
+    drawable->clip.type       = SPICE_CLIP_TYPE_NONE;
Justin M. Forbes a81953
+    drawable->effect          = QXL_EFFECT_OPAQUE;
Justin M. Forbes a81953
+    drawable->release_info.id = (intptr_t)update;
Justin M. Forbes a81953
+    drawable->type            = QXL_DRAW_COPY;
Justin M. Forbes a81953
+
Justin M. Forbes a81953
+    drawable->u.copy.rop_descriptor  = SPICE_ROPD_OP_PUT;
Justin M. Forbes a81953
+    drawable->u.copy.src_bitmap      = (intptr_t)image;
Justin M. Forbes a81953
+    drawable->u.copy.src_area.right  = bw;
Justin M. Forbes a81953
+    drawable->u.copy.src_area.bottom = bh;
Justin M. Forbes a81953
+
Justin M. Forbes a81953
+    QXL_SET_IMAGE_ID(image, QXL_IMAGE_GROUP_DEVICE, ssd->unique++);
Justin M. Forbes a81953
+    image->descriptor.type   = SPICE_IMAGE_TYPE_BITMAP;
Justin M. Forbes a81953
+    image->bitmap.flags      = QXL_BITMAP_DIRECT | QXL_BITMAP_TOP_DOWN;
Justin M. Forbes a81953
+    image->bitmap.stride     = bw * 4;
Justin M. Forbes a81953
+    image->descriptor.width  = image->bitmap.x = bw;
Justin M. Forbes a81953
+    image->descriptor.height = image->bitmap.y = bh;
Justin M. Forbes a81953
+    image->bitmap.data = (intptr_t)(update->bitmap);
Justin M. Forbes a81953
+    image->bitmap.palette = 0;
Justin M. Forbes a81953
+    image->bitmap.format = SPICE_BITMAP_FMT_32BIT;
Justin M. Forbes a81953
+
Justin M. Forbes a81953
+    if (ssd->conv == NULL) {
Justin M. Forbes a81953
+        PixelFormat dst = qemu_default_pixelformat(32);
Justin M. Forbes a81953
+        ssd->conv = qemu_pf_conv_get(&dst, &ssd->ds->surface->pf);
Justin M. Forbes a81953
+        assert(ssd->conv);
Justin M. Forbes a81953
+    }
Justin M. Forbes a81953
+
Justin M. Forbes a81953
+    src = ds_get_data(ssd->ds) +
Justin M. Forbes a81953
+        ssd->dirty.top * ds_get_linesize(ssd->ds) +
Justin M. Forbes a81953
+        ssd->dirty.left * ds_get_bytes_per_pixel(ssd->ds);
Justin M. Forbes a81953
+    dst = update->bitmap;
Justin M. Forbes a81953
+    for (by = 0; by < bh; by++) {
Justin M. Forbes a81953
+        qemu_pf_conv_run(ssd->conv, dst, src, bw);
Justin M. Forbes a81953
+        src += ds_get_linesize(ssd->ds);
Justin M. Forbes a81953
+        dst += image->bitmap.stride;
Justin M. Forbes a81953
+    }
Justin M. Forbes a81953
+
Justin M. Forbes a81953
+    cmd->type = QXL_CMD_DRAW;
Justin M. Forbes a81953
+    cmd->data = (intptr_t)drawable;
Justin M. Forbes a81953
+
Justin M. Forbes a81953
+    memset(&ssd->dirty, 0, sizeof(ssd->dirty));
Justin M. Forbes a81953
+    pthread_mutex_unlock(&ssd->lock);
Justin M. Forbes a81953
+    return update;
Justin M. Forbes a81953
+}
Justin M. Forbes a81953
+
Justin M. Forbes a81953
+void qemu_spice_destroy_update(SimpleSpiceDisplay *sdpy, SimpleSpiceUpdate *update)
Justin M. Forbes a81953
+{
Justin M. Forbes a81953
+    qemu_free(update->bitmap);
Justin M. Forbes a81953
+    qemu_free(update);
Justin M. Forbes a81953
+}
Justin M. Forbes a81953
+
Justin M. Forbes a81953
+void qemu_spice_create_host_memslot(SimpleSpiceDisplay *ssd)
Justin M. Forbes a81953
+{
Justin M. Forbes a81953
+    QXLDevMemSlot memslot;
Justin M. Forbes a81953
+
Justin M. Forbes a81953
+    if (debug)
Justin M. Forbes a81953
+        fprintf(stderr, "%s:\n", __FUNCTION__);
Justin M. Forbes a81953
+
Justin M. Forbes a81953
+    memset(&memslot, 0, sizeof(memslot));
Justin M. Forbes a81953
+    memslot.slot_group_id = MEMSLOT_GROUP_HOST;
Justin M. Forbes a81953
+    memslot.virt_end = ~0;
Justin M. Forbes a81953
+    ssd->worker->add_memslot(ssd->worker, &memslot);
Justin M. Forbes a81953
+}
Justin M. Forbes a81953
+
Justin M. Forbes a81953
+void qemu_spice_create_host_primary(SimpleSpiceDisplay *ssd)
Justin M. Forbes a81953
+{
Justin M. Forbes a81953
+    QXLDevSurfaceCreate surface;
Justin M. Forbes a81953
+
Justin M. Forbes a81953
+    if (debug)
Justin M. Forbes a81953
+        fprintf(stderr, "%s: %dx%d\n", __FUNCTION__,
Justin M. Forbes a81953
+                ds_get_width(ssd->ds), ds_get_height(ssd->ds));
Justin M. Forbes a81953
+
Justin M. Forbes a81953
+    surface.format     = SPICE_SURFACE_FMT_32_xRGB;
Justin M. Forbes a81953
+    surface.width      = ds_get_width(ssd->ds);
Justin M. Forbes a81953
+    surface.height     = ds_get_height(ssd->ds);
Justin M. Forbes a81953
+    surface.stride     = -surface.width * 4;
Justin M. Forbes a81953
+    surface.mouse_mode = 0;
Justin M. Forbes a81953
+    surface.flags      = 0;
Justin M. Forbes a81953
+    surface.type       = 0;
Justin M. Forbes a81953
+    surface.mem        = (intptr_t)ssd->buf;
Justin M. Forbes a81953
+    surface.group_id   = MEMSLOT_GROUP_HOST;
Justin M. Forbes a81953
+    ssd->worker->create_primary_surface(ssd->worker, 0, &surface);
Justin M. Forbes a81953
+}
Justin M. Forbes a81953
+
Justin M. Forbes a81953
+void qemu_spice_destroy_host_primary(SimpleSpiceDisplay *ssd)
Justin M. Forbes a81953
+{
Justin M. Forbes a81953
+    if (debug)
Justin M. Forbes a81953
+        fprintf(stderr, "%s:\n", __FUNCTION__);
Justin M. Forbes a81953
+
Justin M. Forbes a81953
+    ssd->worker->destroy_primary_surface(ssd->worker, 0);
Justin M. Forbes a81953
+}
Justin M. Forbes a81953
+
Justin M. Forbes a81953
+void qemu_spice_vm_change_state_handler(void *opaque, int running, int reason)
Justin M. Forbes a81953
+{
Justin M. Forbes a81953
+    SimpleSpiceDisplay *ssd = opaque;
Justin M. Forbes a81953
+
Justin M. Forbes a81953
+    if (running) {
Justin M. Forbes a81953
+        ssd->worker->start(ssd->worker);
Justin M. Forbes a81953
+    } else {
Justin M. Forbes a81953
+        ssd->worker->stop(ssd->worker);
Justin M. Forbes a81953
+    }
Justin M. Forbes a81953
+    ssd->running = running;
Justin M. Forbes a81953
+}
Justin M. Forbes a81953
+
Justin M. Forbes a81953
+/* display listener callbacks */
Justin M. Forbes a81953
+
Justin M. Forbes a81953
+void qemu_spice_display_update(SimpleSpiceDisplay *ssd,
Justin M. Forbes a81953
+                               int x, int y, int w, int h)
Justin M. Forbes a81953
+{
Justin M. Forbes a81953
+    QXLRect update_area;
Justin M. Forbes a81953
+
Justin M. Forbes a81953
+    if (debug > 1)
Justin M. Forbes a81953
+        fprintf(stderr, "%s: x %d y %d w %d h %d\n", __FUNCTION__, x, y, w, h);
Justin M. Forbes a81953
+    update_area.left = x,
Justin M. Forbes a81953
+    update_area.right = x + w;
Justin M. Forbes a81953
+    update_area.top = y;
Justin M. Forbes a81953
+    update_area.bottom = y + h;
Justin M. Forbes a81953
+
Justin M. Forbes a81953
+    pthread_mutex_lock(&ssd->lock);
Justin M. Forbes a81953
+    if (qemu_spice_rect_is_empty(&ssd->dirty)) {
Justin M. Forbes a81953
+        ssd->notify++;
Justin M. Forbes a81953
+    }
Justin M. Forbes a81953
+    qemu_spice_rect_union(&ssd->dirty, &update_area);
Justin M. Forbes a81953
+    pthread_mutex_unlock(&ssd->lock);
Justin M. Forbes a81953
+}
Justin M. Forbes a81953
+
Justin M. Forbes a81953
+void qemu_spice_display_resize(SimpleSpiceDisplay *ssd)
Justin M. Forbes a81953
+{
Justin M. Forbes a81953
+    if (debug)
Justin M. Forbes a81953
+        fprintf(stderr, "%s:\n", __FUNCTION__);
Justin M. Forbes a81953
+
Justin M. Forbes a81953
+    pthread_mutex_lock(&ssd->lock);
Justin M. Forbes a81953
+    memset(&ssd->dirty, 0, sizeof(ssd->dirty));
Justin M. Forbes a81953
+    pthread_mutex_unlock(&ssd->lock);
Justin M. Forbes a81953
+
Justin M. Forbes a81953
+    qemu_spice_destroy_host_primary(ssd);
Justin M. Forbes a81953
+    qemu_spice_create_host_primary(ssd);
Justin M. Forbes a81953
+    qemu_pf_conv_put(ssd->conv);
Justin M. Forbes a81953
+    ssd->conv = NULL;
Justin M. Forbes a81953
+
Justin M. Forbes a81953
+    pthread_mutex_lock(&ssd->lock);
Justin M. Forbes a81953
+    ssd->dirty.left   = 0;
Justin M. Forbes a81953
+    ssd->dirty.right  = ds_get_width(ssd->ds);
Justin M. Forbes a81953
+    ssd->dirty.top    = 0;
Justin M. Forbes a81953
+    ssd->dirty.bottom = ds_get_height(ssd->ds);
Justin M. Forbes a81953
+    ssd->notify++;
Justin M. Forbes a81953
+    pthread_mutex_unlock(&ssd->lock);
Justin M. Forbes a81953
+}
Justin M. Forbes a81953
+
Justin M. Forbes a81953
+void qemu_spice_display_refresh(SimpleSpiceDisplay *ssd)
Justin M. Forbes a81953
+{
Justin M. Forbes a81953
+    if (debug > 2)
Justin M. Forbes a81953
+        fprintf(stderr, "%s:\n", __FUNCTION__);
Justin M. Forbes a81953
+    vga_hw_update();
Justin M. Forbes a81953
+    if (ssd->notify) {
Justin M. Forbes a81953
+        ssd->notify = 0;
Justin M. Forbes a81953
+        ssd->worker->wakeup(ssd->worker);
Justin M. Forbes a81953
+        if (debug > 1)
Justin M. Forbes a81953
+            fprintf(stderr, "%s: notify\n", __FUNCTION__);
Justin M. Forbes a81953
+    }
Justin M. Forbes a81953
+}
Justin M. Forbes a81953
+
Justin M. Forbes a81953
+/* spice display interface callbacks */
Justin M. Forbes a81953
+
Justin M. Forbes a81953
+static void interface_attach_worker(QXLInstance *sin, QXLWorker *qxl_worker)
Justin M. Forbes a81953
+{
Justin M. Forbes a81953
+    SimpleSpiceDisplay *ssd = container_of(sin, SimpleSpiceDisplay, qxl);
Justin M. Forbes a81953
+
Justin M. Forbes a81953
+    if (debug)
Justin M. Forbes a81953
+        fprintf(stderr, "%s:\n", __FUNCTION__);
Justin M. Forbes a81953
+    ssd->worker = qxl_worker;
Justin M. Forbes a81953
+}
Justin M. Forbes a81953
+
Justin M. Forbes a81953
+static void interface_set_compression_level(QXLInstance *sin, int level)
Justin M. Forbes a81953
+{
Justin M. Forbes a81953
+    if (debug)
Justin M. Forbes a81953
+        fprintf(stderr, "%s:\n", __FUNCTION__);
Justin M. Forbes a81953
+    /* nothing to do */
Justin M. Forbes a81953
+}
Justin M. Forbes a81953
+
Justin M. Forbes a81953
+static void interface_set_mm_time(QXLInstance *sin, uint32_t mm_time)
Justin M. Forbes a81953
+{
Justin M. Forbes a81953
+    if (debug > 2)
Justin M. Forbes a81953
+        fprintf(stderr, "%s:\n", __FUNCTION__);
Justin M. Forbes a81953
+    /* nothing to do */
Justin M. Forbes a81953
+}
Justin M. Forbes a81953
+
Justin M. Forbes a81953
+static void interface_get_init_info(QXLInstance *sin, QXLDevInitInfo *info)
Justin M. Forbes a81953
+{
Justin M. Forbes a81953
+    SimpleSpiceDisplay *ssd = container_of(sin, SimpleSpiceDisplay, qxl);
Justin M. Forbes a81953
+
Justin M. Forbes a81953
+    info->memslot_gen_bits = MEMSLOT_GENERATION_BITS;
Justin M. Forbes a81953
+    info->memslot_id_bits  = MEMSLOT_SLOT_BITS;
Justin M. Forbes a81953
+    info->num_memslots = NUM_MEMSLOTS;
Justin M. Forbes a81953
+    info->num_memslots_groups = NUM_MEMSLOTS_GROUPS;
Justin M. Forbes a81953
+    info->internal_groupslot_id = 0;
Justin M. Forbes a81953
+    info->qxl_ram_size = ssd->bufsize;
Justin M. Forbes a81953
+    info->n_surfaces = NUM_SURFACES;
Justin M. Forbes a81953
+}
Justin M. Forbes a81953
+
Justin M. Forbes a81953
+static int interface_get_command(QXLInstance *sin, struct QXLCommandExt *ext)
Justin M. Forbes a81953
+{
Justin M. Forbes a81953
+    SimpleSpiceDisplay *ssd = container_of(sin, SimpleSpiceDisplay, qxl);
Justin M. Forbes a81953
+    SimpleSpiceUpdate *update;
Justin M. Forbes a81953
+
Justin M. Forbes a81953
+    if (debug > 2)
Justin M. Forbes a81953
+        fprintf(stderr, "%s:\n", __FUNCTION__);
Justin M. Forbes a81953
+    update = qemu_spice_create_update(ssd);
Justin M. Forbes a81953
+    if (update == NULL) {
Justin M. Forbes a81953
+        return false;
Justin M. Forbes a81953
+    }
Justin M. Forbes a81953
+    *ext = update->ext;
Justin M. Forbes a81953
+    return true;
Justin M. Forbes a81953
+}
Justin M. Forbes a81953
+
Justin M. Forbes a81953
+static int interface_req_cmd_notification(QXLInstance *sin)
Justin M. Forbes a81953
+{
Justin M. Forbes a81953
+    if (debug)
Justin M. Forbes a81953
+        fprintf(stderr, "%s:\n", __FUNCTION__);
Justin M. Forbes a81953
+    return 1;
Justin M. Forbes a81953
+}
Justin M. Forbes a81953
+
Justin M. Forbes a81953
+static void interface_release_resource(QXLInstance *sin,
Justin M. Forbes a81953
+                                       struct QXLReleaseInfoExt ext)
Justin M. Forbes a81953
+{
Justin M. Forbes a81953
+    SimpleSpiceDisplay *ssd = container_of(sin, SimpleSpiceDisplay, qxl);
Justin M. Forbes a81953
+    uintptr_t id;
Justin M. Forbes a81953
+
Justin M. Forbes a81953
+    if (debug > 1)
Justin M. Forbes a81953
+        fprintf(stderr, "%s:\n", __FUNCTION__);
Justin M. Forbes a81953
+    id = ext.info->id;
Justin M. Forbes a81953
+    qemu_spice_destroy_update(ssd, (void*)id);
Justin M. Forbes a81953
+}
Justin M. Forbes a81953
+
Justin M. Forbes a81953
+static int interface_get_cursor_command(QXLInstance *sin, struct QXLCommandExt *ext)
Justin M. Forbes a81953
+{
Justin M. Forbes a81953
+    if (debug > 2)
Justin M. Forbes a81953
+        fprintf(stderr, "%s:\n", __FUNCTION__);
Justin M. Forbes a81953
+    return false;
Justin M. Forbes a81953
+}
Justin M. Forbes a81953
+
Justin M. Forbes a81953
+static int interface_req_cursor_notification(QXLInstance *sin)
Justin M. Forbes a81953
+{
Justin M. Forbes a81953
+    if (debug)
Justin M. Forbes a81953
+        fprintf(stderr, "%s:\n", __FUNCTION__);
Justin M. Forbes a81953
+    return 1;
Justin M. Forbes a81953
+}
Justin M. Forbes a81953
+
Justin M. Forbes a81953
+static void interface_notify_update(QXLInstance *sin, uint32_t update_id)
Justin M. Forbes a81953
+{
Justin M. Forbes a81953
+    fprintf(stderr, "%s: abort()\n", __FUNCTION__);
Justin M. Forbes a81953
+    abort();
Justin M. Forbes a81953
+}
Justin M. Forbes a81953
+
Justin M. Forbes a81953
+static int interface_flush_resources(QXLInstance *sin)
Justin M. Forbes a81953
+{
Justin M. Forbes a81953
+    fprintf(stderr, "%s: abort()\n", __FUNCTION__);
Justin M. Forbes a81953
+    abort();
Justin M. Forbes a81953
+    return 0;
Justin M. Forbes a81953
+}
Justin M. Forbes a81953
+
Justin M. Forbes a81953
+static const QXLInterface dpy_interface = {
Justin M. Forbes a81953
+    .base.type               = SPICE_INTERFACE_QXL,
Justin M. Forbes a81953
+    .base.description        = "qemu simple display",
Justin M. Forbes a81953
+    .base.major_version      = SPICE_INTERFACE_QXL_MAJOR,
Justin M. Forbes a81953
+    .base.minor_version      = SPICE_INTERFACE_QXL_MINOR,
Justin M. Forbes a81953
+
Justin M. Forbes a81953
+    .pci_vendor              = REDHAT_PCI_VENDOR_ID,
Justin M. Forbes a81953
+    .pci_id                  = QXL_DEVICE_ID,
Justin M. Forbes a81953
+    .pci_revision            = QXL_REVISION,
Justin M. Forbes a81953
+
Justin M. Forbes a81953
+    .attache_worker          = interface_attach_worker,
Justin M. Forbes a81953
+    .set_compression_level   = interface_set_compression_level,
Justin M. Forbes a81953
+    .set_mm_time             = interface_set_mm_time,
Justin M. Forbes a81953
+
Justin M. Forbes a81953
+    .get_init_info           = interface_get_init_info,
Justin M. Forbes a81953
+    .get_command             = interface_get_command,
Justin M. Forbes a81953
+    .req_cmd_notification    = interface_req_cmd_notification,
Justin M. Forbes a81953
+    .release_resource        = interface_release_resource,
Justin M. Forbes a81953
+    .get_cursor_command      = interface_get_cursor_command,
Justin M. Forbes a81953
+    .req_cursor_notification = interface_req_cursor_notification,
Justin M. Forbes a81953
+    .notify_update           = interface_notify_update,
Justin M. Forbes a81953
+    .flush_resources         = interface_flush_resources,
Justin M. Forbes a81953
+};
Justin M. Forbes a81953
+
Justin M. Forbes a81953
+static SimpleSpiceDisplay sdpy;
Justin M. Forbes a81953
+
Justin M. Forbes a81953
+static void display_update(struct DisplayState *ds, int x, int y, int w, int h)
Justin M. Forbes a81953
+{
Justin M. Forbes a81953
+    qemu_spice_display_update(&sdpy, x, y, w, h);
Justin M. Forbes a81953
+}
Justin M. Forbes a81953
+
Justin M. Forbes a81953
+static void display_resize(struct DisplayState *ds)
Justin M. Forbes a81953
+{
Justin M. Forbes a81953
+    qemu_spice_display_resize(&sdpy);
Justin M. Forbes a81953
+}
Justin M. Forbes a81953
+
Justin M. Forbes a81953
+static void display_refresh(struct DisplayState *ds)
Justin M. Forbes a81953
+{
Justin M. Forbes a81953
+    qemu_spice_display_refresh(&sdpy);
Justin M. Forbes a81953
+}
Justin M. Forbes a81953
+
Justin M. Forbes a81953
+static DisplayChangeListener display_listener = {
Justin M. Forbes a81953
+    .dpy_update  = display_update,
Justin M. Forbes a81953
+    .dpy_resize  = display_resize,
Justin M. Forbes a81953
+    .dpy_refresh = display_refresh,
Justin M. Forbes a81953
+};
Justin M. Forbes a81953
+
Justin M. Forbes a81953
+void qemu_spice_display_init(DisplayState *ds)
Justin M. Forbes a81953
+{
Justin M. Forbes a81953
+    assert(sdpy.ds == NULL);
Justin M. Forbes a81953
+    sdpy.ds = ds;
Justin M. Forbes a81953
+    sdpy.bufsize = (16 * 1024 * 1024);
Justin M. Forbes a81953
+    sdpy.buf = qemu_malloc(sdpy.bufsize);
Justin M. Forbes a81953
+    pthread_mutex_init(&sdpy.lock, NULL);
Justin M. Forbes a81953
+    register_displaychangelistener(ds, &display_listener);
Justin M. Forbes a81953
+
Justin M. Forbes a81953
+    sdpy.qxl.base.sif = &dpy_interface.base;
Justin M. Forbes a81953
+    spice_server_add_interface(spice_server, &sdpy.qxl.base);
Justin M. Forbes a81953
+    assert(sdpy.worker);
Justin M. Forbes a81953
+
Justin M. Forbes a81953
+    qemu_add_vm_change_state_handler(qemu_spice_vm_change_state_handler, &sdpy);
Justin M. Forbes a81953
+    qemu_spice_create_host_memslot(&sdpy);
Justin M. Forbes a81953
+    qemu_spice_create_host_primary(&sdpy);
Justin M. Forbes a81953
+}
Justin M. Forbes a81953
diff --git a/spice-display.h b/spice-display.h
Justin M. Forbes a81953
new file mode 100644
Justin M. Forbes a81953
index 0000000..70a7be4
Justin M. Forbes a81953
--- /dev/null
Justin M. Forbes a81953
+++ b/spice-display.h
Justin M. Forbes a81953
@@ -0,0 +1,52 @@
Justin M. Forbes a81953
+#include <spice/ipc_ring.h>
Justin M. Forbes a81953
+#include <spice/draw.h>
Justin M. Forbes a81953
+#include <spice/qxl_dev.h>
Justin M. Forbes a81953
+
Justin M. Forbes a81953
+#include "pflib.h"
Justin M. Forbes a81953
+
Justin M. Forbes a81953
+#define NUM_MEMSLOTS 8
Justin M. Forbes a81953
+#define MEMSLOT_GENERATION_BITS 8
Justin M. Forbes a81953
+#define MEMSLOT_SLOT_BITS 8
Justin M. Forbes a81953
+
Justin M. Forbes a81953
+#define MEMSLOT_GROUP_HOST  0
Justin M. Forbes a81953
+#define MEMSLOT_GROUP_GUEST 1
Justin M. Forbes a81953
+#define NUM_MEMSLOTS_GROUPS 2
Justin M. Forbes a81953
+
Justin M. Forbes a81953
+#define NUM_SURFACES 1024
Justin M. Forbes a81953
+
Justin M. Forbes a81953
+typedef struct SimpleSpiceDisplay {
Justin M. Forbes a81953
+    DisplayState *ds;
Justin M. Forbes a81953
+    void *buf;
Justin M. Forbes a81953
+    int bufsize;
Justin M. Forbes a81953
+    QXLWorker *worker;
Justin M. Forbes a81953
+    QXLInstance qxl;
Justin M. Forbes a81953
+    uint32_t unique;
Justin M. Forbes a81953
+    QemuPfConv *conv;
Justin M. Forbes a81953
+
Justin M. Forbes a81953
+    pthread_mutex_t lock;
Justin M. Forbes a81953
+    QXLRect dirty;
Justin M. Forbes a81953
+    int notify;
Justin M. Forbes a81953
+    int running;
Justin M. Forbes a81953
+} SimpleSpiceDisplay;
Justin M. Forbes a81953
+
Justin M. Forbes a81953
+typedef struct SimpleSpiceUpdate {
Justin M. Forbes a81953
+    QXLDrawable drawable;
Justin M. Forbes a81953
+    QXLImage image;
Justin M. Forbes a81953
+    QXLCommandExt ext;
Justin M. Forbes a81953
+    uint8_t *bitmap;
Justin M. Forbes a81953
+} SimpleSpiceUpdate;
Justin M. Forbes a81953
+
Justin M. Forbes a81953
+int qemu_spice_rect_is_empty(const QXLRect* r);
Justin M. Forbes a81953
+void qemu_spice_rect_union(QXLRect *dest, const QXLRect *r);
Justin M. Forbes a81953
+
Justin M. Forbes a81953
+SimpleSpiceUpdate *qemu_spice_create_update(SimpleSpiceDisplay *sdpy);
Justin M. Forbes a81953
+void qemu_spice_destroy_update(SimpleSpiceDisplay *sdpy, SimpleSpiceUpdate *update);
Justin M. Forbes a81953
+void qemu_spice_create_host_memslot(SimpleSpiceDisplay *ssd);
Justin M. Forbes a81953
+void qemu_spice_create_host_primary(SimpleSpiceDisplay *ssd);
Justin M. Forbes a81953
+void qemu_spice_destroy_host_primary(SimpleSpiceDisplay *ssd);
Justin M. Forbes a81953
+void qemu_spice_vm_change_state_handler(void *opaque, int running, int reason);
Justin M. Forbes a81953
+
Justin M. Forbes a81953
+void qemu_spice_display_update(SimpleSpiceDisplay *ssd,
Justin M. Forbes a81953
+                               int x, int y, int w, int h);
Justin M. Forbes a81953
+void qemu_spice_display_resize(SimpleSpiceDisplay *ssd);
Justin M. Forbes a81953
+void qemu_spice_display_refresh(SimpleSpiceDisplay *ssd);
Justin M. Forbes a81953
diff --git a/vl.c b/vl.c
Justin M. Forbes a81953
index 97897e0..2ccebc8 100644
Justin M. Forbes a81953
--- a/vl.c
Justin M. Forbes a81953
+++ b/vl.c
Justin M. Forbes a81953
@@ -2993,7 +2993,7 @@ int main(int argc, char **argv, char **envp)
Justin M. Forbes a81953
     /* just use the first displaystate for the moment */
Justin M. Forbes a81953
     ds = get_displaystate();
Justin M. Forbes a81953
Justin M. Forbes a81953
-    if (display_type == DT_DEFAULT) {
Justin M. Forbes a81953
+    if (display_type == DT_DEFAULT && !using_spice) {
Justin M. Forbes a81953
 #if defined(CONFIG_SDL) || defined(CONFIG_COCOA)
Justin M. Forbes a81953
         display_type = DT_SDL;
Justin M. Forbes a81953
 #else
Justin M. Forbes a81953
@@ -3033,6 +3033,11 @@ int main(int argc, char **argv, char **envp)
Justin M. Forbes a81953
     default:
Justin M. Forbes a81953
         break;
Justin M. Forbes a81953
     }
Justin M. Forbes a81953
+#ifdef CONFIG_SPICE
Justin M. Forbes a81953
+    if (using_spice) {
Justin M. Forbes a81953
+        qemu_spice_display_init(ds);
Justin M. Forbes a81953
+    }
Justin M. Forbes a81953
+#endif
Justin M. Forbes a81953
     dpy_resize(ds);
Justin M. Forbes a81953
Justin M. Forbes a81953
     dcl = ds->listeners;
Justin M. Forbes a81953
-- 
Justin M. Forbes a81953
1.7.2.3
Justin M. Forbes a81953