All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/2] Add emulation for VirtIO Frame Buffer device
@ 2009-11-02 22:11 ` Alexander Graf
  0 siblings, 0 replies; 8+ messages in thread
From: Alexander Graf @ 2009-11-02 22:11 UTC (permalink / raw)
  To: kvm; +Cc: qemu-devel, linux-fbdev-devel, anthony

Since Linux now understands how to talk to us graphics over VirtIO, let's
add support for it in qemu.

The good part about graphics over VirtIO is that you don't need PCI to use
it. So if there's any platform out there trying to use graphics, but not
capable of MMIO, it can use this one!

Signed-off-by: Alexander Graf <agraf@suse.de>
---
 Makefile.target |    1 +
 hw/virtio-fb.c  |  434 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 hw/virtio.h     |    1 +
 3 files changed, 436 insertions(+), 0 deletions(-)
 create mode 100644 hw/virtio-fb.c

diff --git a/Makefile.target b/Makefile.target
index fefd7ac..260a6a8 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -158,6 +158,7 @@ obj-y = vl.o async.o monitor.o pci.o machine.o gdbstub.o
 # virtio has to be here due to weird dependency between PCI and virtio-net.
 # need to fix this properly
 obj-y += virtio-blk.o virtio-balloon.o virtio-net.o virtio-console.o virtio-pci.o
+obj-y += virtio-fb.o
 obj-$(CONFIG_KVM) += kvm.o kvm-all.o
 obj-$(CONFIG_ISA_MMIO) += isa_mmio.o
 LIBS+=-lz
diff --git a/hw/virtio-fb.c b/hw/virtio-fb.c
new file mode 100644
index 0000000..c41d3bb
--- /dev/null
+++ b/hw/virtio-fb.c
@@ -0,0 +1,434 @@
+/*
+ * Virtio Frame Buffer Device
+ *
+ * Copyright (c) 2009 Alexander Graf <agraf@suse.de>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ *
+ */
+
+#include "hw.h"
+#include "console.h"
+#include "virtio.h"
+
+#define VIRTIO_ID_FB			6
+
+typedef struct VirtIOFB
+{
+    VirtIODevice vdev;
+    DisplayState *ds;
+    VirtQueue    *vq_in;
+    VirtQueue    *vq_out;
+} VirtIOFB;
+
+/* guest -> Host commands */
+#define VIRTIO_FB_CMD_RESIZE            0x01
+#define VIRTIO_FB_CMD_FILL              0x02
+#define VIRTIO_FB_CMD_BLIT              0x03
+#define VIRTIO_FB_CMD_COPY              0x04
+#define VIRTIO_FB_CMD_WRITE             0x05
+
+/* host -> guest commands */
+#define VIRTIO_FB_CMD_REFRESH           0x81
+
+#define ROP_COPY 0
+#define ROP_XOR  1
+
+#define BITS_PER_PIXEL			32
+#define BYTES_PER_PIXEL			(BITS_PER_PIXEL / 8)
+
+struct virtio_fb_cmd {
+    uint8_t              cmd;
+    union {
+        struct {
+            uint16_t     width;
+            uint16_t     height;
+        } resize __attribute__ ((packed));
+        struct {
+            uint16_t     x;
+            uint16_t     y;
+            uint16_t     width;
+            uint16_t     height;
+        } blit __attribute__ ((packed));
+        struct {
+            uint16_t     x1;
+            uint16_t     y1;
+            uint16_t     x2;
+            uint16_t     y2;
+            uint16_t     width;
+            uint16_t     height;
+        } copy_area __attribute__ ((packed));
+        struct {
+            uint8_t      rop;
+            uint16_t     x;
+            uint16_t     y;
+            uint16_t     width;
+            uint16_t     height;
+            uint32_t     color;
+        } fill __attribute__ ((packed));
+        struct {
+            uint64_t     offset;
+            uint64_t     count;
+        } write __attribute__ ((packed));
+        uint8_t          pad[31];
+    };
+
+    uint8_t              data[];
+} __attribute__ ((packed));
+
+static VirtIOFB *to_virtio_fb(VirtIODevice *vdev)
+{
+    return (VirtIOFB *)vdev;
+}
+
+static uint32_t virtio_fb_get_features(VirtIODevice *vdev)
+{
+    return 0;
+}
+
+static int virtio_fb_send(struct VirtIOFB *s, struct virtio_fb_cmd *cmd,
+                          uint8_t *data, int len_data)
+{
+    int len_cmd = sizeof(*cmd);
+    int len_all = len_cmd + len_data;
+    VirtQueueElement elem;
+    int i = 0;
+
+    if (!virtio_queue_ready(s->vq_in))
+        return -1;
+
+    if (!virtqueue_pop(s->vq_in, &elem)) {
+        fprintf(stderr, "virtio-fb: queue lacking elements\n");
+        return -1;
+    }
+
+    if (elem.in_num < 1) {
+        fprintf(stderr, "virtio-fb: queue lacking sg's\n");
+        return -1;
+    }
+
+    if (elem.in_sg[i].iov_len < len_all) {
+        fprintf(stderr, "virtio-fb: buffer too small\n");
+        return -1;
+    }
+
+    if (len_data && !data) {
+        fprintf(stderr, "virtio-fb: passed no data but data length?!\n");
+        return -EINVAL;
+    }
+
+    memcpy(elem.in_sg[i].iov_base, cmd, len_cmd);
+    if (len_data)
+        memcpy(elem.in_sg[i].iov_base + len_cmd, data, len_data);
+
+    virtqueue_push(s->vq_in, &elem, len_all);
+    virtio_notify(&s->vdev, s->vq_in);
+
+    return 0;
+}
+
+/* QEMU display state changed, so refresh the framebuffer copy */
+static void virtio_fb_invalidate(void *opaque)
+{
+    struct VirtIOFB *s = opaque;
+    struct virtio_fb_cmd cmd;
+
+    memset(&cmd, 0, sizeof(cmd));
+    cmd.cmd = VIRTIO_FB_CMD_REFRESH;
+
+    virtio_fb_send(s, &cmd, NULL, 0);
+    dpy_update(s->ds, 0, 0, ds_get_width(s->ds), ds_get_width(s->ds));
+}
+
+static void virtio_fb_save(QEMUFile *f, void *opaque)
+{
+    VirtIOFB *s = opaque;
+
+    virtio_save(&s->vdev, f);
+}
+
+static int virtio_fb_load(QEMUFile *f, void *opaque, int version_id)
+{
+    VirtIOFB *s = opaque;
+
+    if (version_id != 1)
+        return -EINVAL;
+
+    virtio_load(&s->vdev, f);
+    return 0;
+}
+
+static void virtio_fb_handle_input(VirtIODevice *vdev, VirtQueue *vq)
+{
+}
+
+static void virtio_fb_handle_resize(VirtIOFB *s, struct virtio_fb_cmd *cmd)
+{
+    uint16_t width = tswap16(cmd->resize.width);
+    uint16_t height = tswap16(cmd->resize.height);
+
+    qemu_free_displaysurface(s->ds);
+    s->ds->surface = qemu_create_displaysurface_from(width, height,
+                        sizeof(uint32_t) * 8, width * sizeof(uint32_t),
+                        qemu_malloc(width * height * BYTES_PER_PIXEL));
+    s->ds->surface->flags |= QEMU_ALLOCATED_FLAG;
+    
+    dpy_resize(s->ds);
+
+    if (s->ds->surface->pf.bits_per_pixel != 32) {
+        fprintf(stderr, "virtio-fb only supports 32 bit ...\n");
+        exit(1);
+    }
+}
+
+static void virtio_fb_handle_fill(VirtIOFB *s, struct virtio_fb_cmd *cmd)
+{
+    uint16_t x = tswap16(cmd->fill.x);
+    uint16_t y = tswap16(cmd->fill.y);
+    uint16_t width = tswap16(cmd->fill.width);
+    uint16_t height = tswap16(cmd->fill.height);
+    uint32_t color = tswap32(cmd->fill.color);
+    uint8_t rop = cmd->fill.rop;
+
+    int ds_depth = ds_get_bytes_per_pixel(s->ds);
+    int ds_linesize = ds_get_linesize(s->ds);
+
+    uint8_t *ds_data = ds_get_data(s->ds);
+    uint32_t *src32;
+    uint8_t *src;
+    uint8_t *dst;
+
+    int i, len;
+
+    if (ds_depth != sizeof(uint32_t)) {
+        fprintf(stderr, "ds depth invalid\n");
+        exit(1);
+    }
+
+    if (rop == ROP_XOR) {
+        fprintf(stderr, "XOR\n");
+        exit(1);
+    }
+
+    if (x > ds_get_width(s->ds))
+        return;
+
+    if (y > ds_get_height(s->ds))
+        return;
+
+    if ((x + width) > ds_get_width(s->ds))
+        return;
+
+    if ((y + height) > ds_get_height(s->ds))
+        return;
+
+    len = width * ds_depth;
+    src = qemu_malloc(width * ds_depth);
+    src32 = (uint32_t *)src;
+
+    for (i = 0; i < width; i++) {
+        src32[i] = color;
+    }
+
+    dst = ds_data + (y * ds_linesize) + (x * ds_depth);
+
+    for (i = 0; i < height; i++) {
+        memcpy(dst, src, len);
+        dst += ds_linesize;
+    }
+
+    qemu_free(src);
+
+    dpy_update(s->ds, x, y, width, height);
+}
+
+static void virtio_fb_handle_blit(VirtIOFB *s, struct virtio_fb_cmd *cmd,
+                                  int len)
+{
+    uint16_t x = tswap16(cmd->blit.x);
+    uint16_t y = tswap16(cmd->blit.y);
+    uint16_t width = tswap16(cmd->blit.width);
+    uint16_t height = tswap16(cmd->blit.height);
+
+    int ds_linesize = ds_get_linesize(s->ds);
+    int ds_bpp = ds_get_bytes_per_pixel(s->ds);
+
+    int linesize = width * ds_bpp;
+    uint8_t *ds_data = ds_get_data(s->ds);
+    uint8_t *dst, *src;
+    int i;
+
+    if (x > ds_get_width(s->ds))              return;
+    if (y > ds_get_height(s->ds))             return;
+    if ((x + width) > ds_get_width(s->ds))    return;
+    if ((y + height) > ds_get_height(s->ds))  return;
+    if ((height * linesize) > len)            return;
+
+    dst = ds_data + (y * ds_linesize) + (x * ds_bpp);
+    src = cmd->data;
+
+    for (i = 0; i < height; i++) {
+        memcpy(dst, src, linesize);
+        dst += ds_linesize;
+        src += linesize;
+    }
+
+    dpy_update(s->ds, x, y, width, height);
+}
+
+static void virtio_fb_handle_copy(VirtIOFB *s, struct virtio_fb_cmd *cmd)
+{
+    uint16_t x1 = tswap16(cmd->copy_area.x1);
+    uint16_t y1 = tswap16(cmd->copy_area.y1);
+    uint16_t x2 = tswap16(cmd->copy_area.x2);
+    uint16_t y2 = tswap16(cmd->copy_area.y2);
+    uint16_t width = tswap16(cmd->copy_area.width);
+    uint16_t height = tswap16(cmd->copy_area.height);
+
+    int ds_width = ds_get_width(s->ds);
+    int ds_depth = ds_get_bytes_per_pixel(s->ds);
+    int ds_linesize = ds_get_linesize(s->ds);
+    uint8_t *ds_data = ds_get_data(s->ds);
+    uint8_t *bkp;
+    uint8_t *dst;
+    uint8_t *src;
+    int i, len;
+
+    if (ds_depth != sizeof(uint32_t)) {
+        fprintf(stderr, "ds depth invalid\n");
+        exit(1);
+    }
+
+    if (x1 > ds_get_width(s->ds))              return;
+    if (y1 > ds_get_height(s->ds))             return;
+    if (x2 > ds_get_width(s->ds))              return;
+    if (y2 > ds_get_height(s->ds))             return;
+    if ((x1 + width) > ds_get_width(s->ds))    return;
+    if ((y1 + height) > ds_get_height(s->ds))  return;
+    if ((x2 + width) > ds_get_width(s->ds))    return;
+    if ((y2 + height) > ds_get_height(s->ds))  return;
+
+    len = (ds_width * ds_depth) + (height * ds_linesize);
+    bkp = qemu_malloc(len);
+    memcpy(bkp, ds_data + (x1 * ds_depth) + (y1 * ds_linesize), len);
+
+    src = bkp;
+    dst = ds_data + (x2 * ds_depth) + (y2 * ds_linesize);
+
+    for (i = 0; i < height; i++) {
+        memcpy(dst, src, width * ds_depth);
+        dst += ds_linesize;
+        src += ds_linesize;
+    }
+
+    qemu_console_copy(s->ds, x1, y1, x2, y2, width, height);
+    dpy_update(s->ds, x2, y2, width, height);
+
+    qemu_free(bkp);
+}
+
+static void virtio_fb_handle_write(VirtIOFB *s, struct virtio_fb_cmd *cmd,
+                                   int len)
+{
+    uint64_t offset = tswap64(cmd->write.offset);
+    uint64_t count = tswap64(cmd->write.count);
+    uint8_t *ds_data = ds_get_data(s->ds);
+    int ds_width = ds_get_width(s->ds);
+    int ds_size = ds_width * ds_get_height(s->ds) * ds_get_bytes_per_pixel(s->ds);
+
+    uint16_t y1 = (offset / sizeof(uint32_t)) / ds_width;
+    uint16_t y2 = (((offset + count) / sizeof(uint32_t)) / ds_width) + 2;
+
+    if ((offset > ds_size) || (count > len))
+        return;
+
+    if ((offset + count) > ds_size)
+        count = ds_size - offset;
+
+    memcpy(ds_data + offset, cmd->data, count);
+
+    dpy_update(s->ds, 0, y1, ds_get_width(s->ds), y2 - y1);
+}
+
+static void virtio_fb_handle_output(VirtIODevice *vdev, VirtQueue *vq)
+{
+    VirtIOFB *s = to_virtio_fb(vdev);
+    VirtQueueElement elem;
+    bool notify = false;
+
+    if (!virtio_queue_ready(vq))
+        return;
+
+    while (virtqueue_pop(vq, &elem)) {
+        int d;
+        struct virtio_fb_cmd *cmd;
+        char *data, *p;
+        int data_len = 0;
+
+        for (d = 0; d < elem.out_num; d++) {
+            data_len += elem.out_sg[d].iov_len;
+        }
+
+        data = qemu_malloc(data_len);
+        p = data;
+
+        for (d = 0; d < elem.out_num; d++) {
+            memcpy(p, elem.out_sg[d].iov_base, elem.out_sg[d].iov_len);
+            p += elem.out_sg[d].iov_len;
+        }
+
+        data_len -= sizeof(*cmd);
+        cmd = (struct virtio_fb_cmd *)data;
+
+        /* We can have a text console on our display. Don't draw then */
+        if (!is_graphic_console()) {
+            goto next_item;
+        }
+
+        switch (cmd->cmd) {
+            case VIRTIO_FB_CMD_RESIZE:
+                virtio_fb_handle_resize(s, cmd);
+                break;
+            case VIRTIO_FB_CMD_FILL:
+                virtio_fb_handle_fill(s, cmd);
+                break;
+            case VIRTIO_FB_CMD_BLIT:
+                virtio_fb_handle_blit(s, cmd, data_len);
+                break;
+            case VIRTIO_FB_CMD_COPY:
+                virtio_fb_handle_copy(s, cmd);
+                break;
+            case VIRTIO_FB_CMD_WRITE:
+                virtio_fb_handle_write(s, cmd, data_len);
+                break;
+        }
+
+next_item:
+
+        qemu_free(data);
+        virtqueue_push(vq, &elem, 0);
+        notify = true;
+    }
+
+    if (notify)
+        virtio_notify(vdev, vq);
+}
+
+VirtIODevice *virtio_fb_init(DeviceState *dev)
+{
+    VirtIOFB *s;
+    s = (VirtIOFB *)virtio_common_init("virtio-fb", VIRTIO_ID_FB,
+                                       0, sizeof(VirtIOFB));
+    s->vdev.get_features = virtio_fb_get_features;
+
+    s->vq_in = virtio_add_queue(&s->vdev, 128, virtio_fb_handle_input);
+    s->vq_out = virtio_add_queue(&s->vdev, 512, virtio_fb_handle_output);
+
+    s->ds = graphic_console_init(NULL, virtio_fb_invalidate,
+                                 NULL, NULL, s);
+
+    register_savevm("virtio-fb", -1, 1, virtio_fb_save, virtio_fb_load, s);
+
+    return &s->vdev;
+}
diff --git a/hw/virtio.h b/hw/virtio.h
index 15ad910..9055f60 100644
--- a/hw/virtio.h
+++ b/hw/virtio.h
@@ -167,6 +167,7 @@ VirtIODevice *virtio_blk_init(DeviceState *dev, DriveInfo *dinfo);
 VirtIODevice *virtio_net_init(DeviceState *dev, NICConf *conf);
 VirtIODevice *virtio_console_init(DeviceState *dev);
 VirtIODevice *virtio_balloon_init(DeviceState *dev);
+VirtIODevice *virtio_fb_init(DeviceState *dev);
 
 void virtio_net_exit(VirtIODevice *vdev);
 
-- 
1.6.0.2


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [Qemu-devel] [PATCH 1/2] Add emulation for VirtIO Frame Buffer device
@ 2009-11-02 22:11 ` Alexander Graf
  0 siblings, 0 replies; 8+ messages in thread
From: Alexander Graf @ 2009-11-02 22:11 UTC (permalink / raw)
  To: kvm; +Cc: linux-fbdev-devel, qemu-devel

Since Linux now understands how to talk to us graphics over VirtIO, let's
add support for it in qemu.

The good part about graphics over VirtIO is that you don't need PCI to use
it. So if there's any platform out there trying to use graphics, but not
capable of MMIO, it can use this one!

Signed-off-by: Alexander Graf <agraf@suse.de>
---
 Makefile.target |    1 +
 hw/virtio-fb.c  |  434 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 hw/virtio.h     |    1 +
 3 files changed, 436 insertions(+), 0 deletions(-)
 create mode 100644 hw/virtio-fb.c

diff --git a/Makefile.target b/Makefile.target
index fefd7ac..260a6a8 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -158,6 +158,7 @@ obj-y = vl.o async.o monitor.o pci.o machine.o gdbstub.o
 # virtio has to be here due to weird dependency between PCI and virtio-net.
 # need to fix this properly
 obj-y += virtio-blk.o virtio-balloon.o virtio-net.o virtio-console.o virtio-pci.o
+obj-y += virtio-fb.o
 obj-$(CONFIG_KVM) += kvm.o kvm-all.o
 obj-$(CONFIG_ISA_MMIO) += isa_mmio.o
 LIBS+=-lz
diff --git a/hw/virtio-fb.c b/hw/virtio-fb.c
new file mode 100644
index 0000000..c41d3bb
--- /dev/null
+++ b/hw/virtio-fb.c
@@ -0,0 +1,434 @@
+/*
+ * Virtio Frame Buffer Device
+ *
+ * Copyright (c) 2009 Alexander Graf <agraf@suse.de>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ *
+ */
+
+#include "hw.h"
+#include "console.h"
+#include "virtio.h"
+
+#define VIRTIO_ID_FB			6
+
+typedef struct VirtIOFB
+{
+    VirtIODevice vdev;
+    DisplayState *ds;
+    VirtQueue    *vq_in;
+    VirtQueue    *vq_out;
+} VirtIOFB;
+
+/* guest -> Host commands */
+#define VIRTIO_FB_CMD_RESIZE            0x01
+#define VIRTIO_FB_CMD_FILL              0x02
+#define VIRTIO_FB_CMD_BLIT              0x03
+#define VIRTIO_FB_CMD_COPY              0x04
+#define VIRTIO_FB_CMD_WRITE             0x05
+
+/* host -> guest commands */
+#define VIRTIO_FB_CMD_REFRESH           0x81
+
+#define ROP_COPY 0
+#define ROP_XOR  1
+
+#define BITS_PER_PIXEL			32
+#define BYTES_PER_PIXEL			(BITS_PER_PIXEL / 8)
+
+struct virtio_fb_cmd {
+    uint8_t              cmd;
+    union {
+        struct {
+            uint16_t     width;
+            uint16_t     height;
+        } resize __attribute__ ((packed));
+        struct {
+            uint16_t     x;
+            uint16_t     y;
+            uint16_t     width;
+            uint16_t     height;
+        } blit __attribute__ ((packed));
+        struct {
+            uint16_t     x1;
+            uint16_t     y1;
+            uint16_t     x2;
+            uint16_t     y2;
+            uint16_t     width;
+            uint16_t     height;
+        } copy_area __attribute__ ((packed));
+        struct {
+            uint8_t      rop;
+            uint16_t     x;
+            uint16_t     y;
+            uint16_t     width;
+            uint16_t     height;
+            uint32_t     color;
+        } fill __attribute__ ((packed));
+        struct {
+            uint64_t     offset;
+            uint64_t     count;
+        } write __attribute__ ((packed));
+        uint8_t          pad[31];
+    };
+
+    uint8_t              data[];
+} __attribute__ ((packed));
+
+static VirtIOFB *to_virtio_fb(VirtIODevice *vdev)
+{
+    return (VirtIOFB *)vdev;
+}
+
+static uint32_t virtio_fb_get_features(VirtIODevice *vdev)
+{
+    return 0;
+}
+
+static int virtio_fb_send(struct VirtIOFB *s, struct virtio_fb_cmd *cmd,
+                          uint8_t *data, int len_data)
+{
+    int len_cmd = sizeof(*cmd);
+    int len_all = len_cmd + len_data;
+    VirtQueueElement elem;
+    int i = 0;
+
+    if (!virtio_queue_ready(s->vq_in))
+        return -1;
+
+    if (!virtqueue_pop(s->vq_in, &elem)) {
+        fprintf(stderr, "virtio-fb: queue lacking elements\n");
+        return -1;
+    }
+
+    if (elem.in_num < 1) {
+        fprintf(stderr, "virtio-fb: queue lacking sg's\n");
+        return -1;
+    }
+
+    if (elem.in_sg[i].iov_len < len_all) {
+        fprintf(stderr, "virtio-fb: buffer too small\n");
+        return -1;
+    }
+
+    if (len_data && !data) {
+        fprintf(stderr, "virtio-fb: passed no data but data length?!\n");
+        return -EINVAL;
+    }
+
+    memcpy(elem.in_sg[i].iov_base, cmd, len_cmd);
+    if (len_data)
+        memcpy(elem.in_sg[i].iov_base + len_cmd, data, len_data);
+
+    virtqueue_push(s->vq_in, &elem, len_all);
+    virtio_notify(&s->vdev, s->vq_in);
+
+    return 0;
+}
+
+/* QEMU display state changed, so refresh the framebuffer copy */
+static void virtio_fb_invalidate(void *opaque)
+{
+    struct VirtIOFB *s = opaque;
+    struct virtio_fb_cmd cmd;
+
+    memset(&cmd, 0, sizeof(cmd));
+    cmd.cmd = VIRTIO_FB_CMD_REFRESH;
+
+    virtio_fb_send(s, &cmd, NULL, 0);
+    dpy_update(s->ds, 0, 0, ds_get_width(s->ds), ds_get_width(s->ds));
+}
+
+static void virtio_fb_save(QEMUFile *f, void *opaque)
+{
+    VirtIOFB *s = opaque;
+
+    virtio_save(&s->vdev, f);
+}
+
+static int virtio_fb_load(QEMUFile *f, void *opaque, int version_id)
+{
+    VirtIOFB *s = opaque;
+
+    if (version_id != 1)
+        return -EINVAL;
+
+    virtio_load(&s->vdev, f);
+    return 0;
+}
+
+static void virtio_fb_handle_input(VirtIODevice *vdev, VirtQueue *vq)
+{
+}
+
+static void virtio_fb_handle_resize(VirtIOFB *s, struct virtio_fb_cmd *cmd)
+{
+    uint16_t width = tswap16(cmd->resize.width);
+    uint16_t height = tswap16(cmd->resize.height);
+
+    qemu_free_displaysurface(s->ds);
+    s->ds->surface = qemu_create_displaysurface_from(width, height,
+                        sizeof(uint32_t) * 8, width * sizeof(uint32_t),
+                        qemu_malloc(width * height * BYTES_PER_PIXEL));
+    s->ds->surface->flags |= QEMU_ALLOCATED_FLAG;
+    
+    dpy_resize(s->ds);
+
+    if (s->ds->surface->pf.bits_per_pixel != 32) {
+        fprintf(stderr, "virtio-fb only supports 32 bit ...\n");
+        exit(1);
+    }
+}
+
+static void virtio_fb_handle_fill(VirtIOFB *s, struct virtio_fb_cmd *cmd)
+{
+    uint16_t x = tswap16(cmd->fill.x);
+    uint16_t y = tswap16(cmd->fill.y);
+    uint16_t width = tswap16(cmd->fill.width);
+    uint16_t height = tswap16(cmd->fill.height);
+    uint32_t color = tswap32(cmd->fill.color);
+    uint8_t rop = cmd->fill.rop;
+
+    int ds_depth = ds_get_bytes_per_pixel(s->ds);
+    int ds_linesize = ds_get_linesize(s->ds);
+
+    uint8_t *ds_data = ds_get_data(s->ds);
+    uint32_t *src32;
+    uint8_t *src;
+    uint8_t *dst;
+
+    int i, len;
+
+    if (ds_depth != sizeof(uint32_t)) {
+        fprintf(stderr, "ds depth invalid\n");
+        exit(1);
+    }
+
+    if (rop == ROP_XOR) {
+        fprintf(stderr, "XOR\n");
+        exit(1);
+    }
+
+    if (x > ds_get_width(s->ds))
+        return;
+
+    if (y > ds_get_height(s->ds))
+        return;
+
+    if ((x + width) > ds_get_width(s->ds))
+        return;
+
+    if ((y + height) > ds_get_height(s->ds))
+        return;
+
+    len = width * ds_depth;
+    src = qemu_malloc(width * ds_depth);
+    src32 = (uint32_t *)src;
+
+    for (i = 0; i < width; i++) {
+        src32[i] = color;
+    }
+
+    dst = ds_data + (y * ds_linesize) + (x * ds_depth);
+
+    for (i = 0; i < height; i++) {
+        memcpy(dst, src, len);
+        dst += ds_linesize;
+    }
+
+    qemu_free(src);
+
+    dpy_update(s->ds, x, y, width, height);
+}
+
+static void virtio_fb_handle_blit(VirtIOFB *s, struct virtio_fb_cmd *cmd,
+                                  int len)
+{
+    uint16_t x = tswap16(cmd->blit.x);
+    uint16_t y = tswap16(cmd->blit.y);
+    uint16_t width = tswap16(cmd->blit.width);
+    uint16_t height = tswap16(cmd->blit.height);
+
+    int ds_linesize = ds_get_linesize(s->ds);
+    int ds_bpp = ds_get_bytes_per_pixel(s->ds);
+
+    int linesize = width * ds_bpp;
+    uint8_t *ds_data = ds_get_data(s->ds);
+    uint8_t *dst, *src;
+    int i;
+
+    if (x > ds_get_width(s->ds))              return;
+    if (y > ds_get_height(s->ds))             return;
+    if ((x + width) > ds_get_width(s->ds))    return;
+    if ((y + height) > ds_get_height(s->ds))  return;
+    if ((height * linesize) > len)            return;
+
+    dst = ds_data + (y * ds_linesize) + (x * ds_bpp);
+    src = cmd->data;
+
+    for (i = 0; i < height; i++) {
+        memcpy(dst, src, linesize);
+        dst += ds_linesize;
+        src += linesize;
+    }
+
+    dpy_update(s->ds, x, y, width, height);
+}
+
+static void virtio_fb_handle_copy(VirtIOFB *s, struct virtio_fb_cmd *cmd)
+{
+    uint16_t x1 = tswap16(cmd->copy_area.x1);
+    uint16_t y1 = tswap16(cmd->copy_area.y1);
+    uint16_t x2 = tswap16(cmd->copy_area.x2);
+    uint16_t y2 = tswap16(cmd->copy_area.y2);
+    uint16_t width = tswap16(cmd->copy_area.width);
+    uint16_t height = tswap16(cmd->copy_area.height);
+
+    int ds_width = ds_get_width(s->ds);
+    int ds_depth = ds_get_bytes_per_pixel(s->ds);
+    int ds_linesize = ds_get_linesize(s->ds);
+    uint8_t *ds_data = ds_get_data(s->ds);
+    uint8_t *bkp;
+    uint8_t *dst;
+    uint8_t *src;
+    int i, len;
+
+    if (ds_depth != sizeof(uint32_t)) {
+        fprintf(stderr, "ds depth invalid\n");
+        exit(1);
+    }
+
+    if (x1 > ds_get_width(s->ds))              return;
+    if (y1 > ds_get_height(s->ds))             return;
+    if (x2 > ds_get_width(s->ds))              return;
+    if (y2 > ds_get_height(s->ds))             return;
+    if ((x1 + width) > ds_get_width(s->ds))    return;
+    if ((y1 + height) > ds_get_height(s->ds))  return;
+    if ((x2 + width) > ds_get_width(s->ds))    return;
+    if ((y2 + height) > ds_get_height(s->ds))  return;
+
+    len = (ds_width * ds_depth) + (height * ds_linesize);
+    bkp = qemu_malloc(len);
+    memcpy(bkp, ds_data + (x1 * ds_depth) + (y1 * ds_linesize), len);
+
+    src = bkp;
+    dst = ds_data + (x2 * ds_depth) + (y2 * ds_linesize);
+
+    for (i = 0; i < height; i++) {
+        memcpy(dst, src, width * ds_depth);
+        dst += ds_linesize;
+        src += ds_linesize;
+    }
+
+    qemu_console_copy(s->ds, x1, y1, x2, y2, width, height);
+    dpy_update(s->ds, x2, y2, width, height);
+
+    qemu_free(bkp);
+}
+
+static void virtio_fb_handle_write(VirtIOFB *s, struct virtio_fb_cmd *cmd,
+                                   int len)
+{
+    uint64_t offset = tswap64(cmd->write.offset);
+    uint64_t count = tswap64(cmd->write.count);
+    uint8_t *ds_data = ds_get_data(s->ds);
+    int ds_width = ds_get_width(s->ds);
+    int ds_size = ds_width * ds_get_height(s->ds) * ds_get_bytes_per_pixel(s->ds);
+
+    uint16_t y1 = (offset / sizeof(uint32_t)) / ds_width;
+    uint16_t y2 = (((offset + count) / sizeof(uint32_t)) / ds_width) + 2;
+
+    if ((offset > ds_size) || (count > len))
+        return;
+
+    if ((offset + count) > ds_size)
+        count = ds_size - offset;
+
+    memcpy(ds_data + offset, cmd->data, count);
+
+    dpy_update(s->ds, 0, y1, ds_get_width(s->ds), y2 - y1);
+}
+
+static void virtio_fb_handle_output(VirtIODevice *vdev, VirtQueue *vq)
+{
+    VirtIOFB *s = to_virtio_fb(vdev);
+    VirtQueueElement elem;
+    bool notify = false;
+
+    if (!virtio_queue_ready(vq))
+        return;
+
+    while (virtqueue_pop(vq, &elem)) {
+        int d;
+        struct virtio_fb_cmd *cmd;
+        char *data, *p;
+        int data_len = 0;
+
+        for (d = 0; d < elem.out_num; d++) {
+            data_len += elem.out_sg[d].iov_len;
+        }
+
+        data = qemu_malloc(data_len);
+        p = data;
+
+        for (d = 0; d < elem.out_num; d++) {
+            memcpy(p, elem.out_sg[d].iov_base, elem.out_sg[d].iov_len);
+            p += elem.out_sg[d].iov_len;
+        }
+
+        data_len -= sizeof(*cmd);
+        cmd = (struct virtio_fb_cmd *)data;
+
+        /* We can have a text console on our display. Don't draw then */
+        if (!is_graphic_console()) {
+            goto next_item;
+        }
+
+        switch (cmd->cmd) {
+            case VIRTIO_FB_CMD_RESIZE:
+                virtio_fb_handle_resize(s, cmd);
+                break;
+            case VIRTIO_FB_CMD_FILL:
+                virtio_fb_handle_fill(s, cmd);
+                break;
+            case VIRTIO_FB_CMD_BLIT:
+                virtio_fb_handle_blit(s, cmd, data_len);
+                break;
+            case VIRTIO_FB_CMD_COPY:
+                virtio_fb_handle_copy(s, cmd);
+                break;
+            case VIRTIO_FB_CMD_WRITE:
+                virtio_fb_handle_write(s, cmd, data_len);
+                break;
+        }
+
+next_item:
+
+        qemu_free(data);
+        virtqueue_push(vq, &elem, 0);
+        notify = true;
+    }
+
+    if (notify)
+        virtio_notify(vdev, vq);
+}
+
+VirtIODevice *virtio_fb_init(DeviceState *dev)
+{
+    VirtIOFB *s;
+    s = (VirtIOFB *)virtio_common_init("virtio-fb", VIRTIO_ID_FB,
+                                       0, sizeof(VirtIOFB));
+    s->vdev.get_features = virtio_fb_get_features;
+
+    s->vq_in = virtio_add_queue(&s->vdev, 128, virtio_fb_handle_input);
+    s->vq_out = virtio_add_queue(&s->vdev, 512, virtio_fb_handle_output);
+
+    s->ds = graphic_console_init(NULL, virtio_fb_invalidate,
+                                 NULL, NULL, s);
+
+    register_savevm("virtio-fb", -1, 1, virtio_fb_save, virtio_fb_load, s);
+
+    return &s->vdev;
+}
diff --git a/hw/virtio.h b/hw/virtio.h
index 15ad910..9055f60 100644
--- a/hw/virtio.h
+++ b/hw/virtio.h
@@ -167,6 +167,7 @@ VirtIODevice *virtio_blk_init(DeviceState *dev, DriveInfo *dinfo);
 VirtIODevice *virtio_net_init(DeviceState *dev, NICConf *conf);
 VirtIODevice *virtio_console_init(DeviceState *dev);
 VirtIODevice *virtio_balloon_init(DeviceState *dev);
+VirtIODevice *virtio_fb_init(DeviceState *dev);
 
 void virtio_net_exit(VirtIODevice *vdev);
 
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 2/2] Add PCI virtio support for frame buffer
  2009-11-02 22:11 ` [Qemu-devel] " Alexander Graf
@ 2009-11-02 22:11   ` Alexander Graf
  -1 siblings, 0 replies; 8+ messages in thread
From: Alexander Graf @ 2009-11-02 22:11 UTC (permalink / raw)
  To: kvm; +Cc: qemu-devel, linux-fbdev-devel, anthony

We now know how to use a frame buffer on VirtIO, but we still can't use it on
x86. In order to leverage the power of VirtIO FB, we need to wrap it through
virtio-pci.

So let's add all the shiny wrappers and add a -vga option.

Signed-off-by: Alexander Graf <agraf@suse.de>
---
 hw/pc.c         |    5 +++++
 hw/pci.h        |    1 +
 hw/virtio-pci.c |   29 +++++++++++++++++++++++++++++
 sysemu.h        |    3 ++-
 vl.c            |    2 ++
 5 files changed, 39 insertions(+), 1 deletions(-)

diff --git a/hw/pc.c b/hw/pc.c
index bf4718e..4b0d019 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -1190,6 +1190,11 @@ static void pc_init1(ram_addr_t ram_size,
         } else {
             isa_vga_init();
         }
+    } else if (virtio_fb_enabled) {
+        if (pci_enabled)
+            pci_create_simple(pci_bus, -1, "virtio-fb-pci");
+        else
+            fprintf(stderr, "%s: virtio_fb: no PCI bus\n", __FUNCTION__);
     }
 
     rtc_state = rtc_init(2000);
diff --git a/hw/pci.h b/hw/pci.h
index 93f93fb..b65a6df 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -70,6 +70,7 @@ extern target_phys_addr_t pci_mem_base;
 #define PCI_DEVICE_ID_VIRTIO_BLOCK       0x1001
 #define PCI_DEVICE_ID_VIRTIO_BALLOON     0x1002
 #define PCI_DEVICE_ID_VIRTIO_CONSOLE     0x1003
+#define PCI_DEVICE_ID_VIRTIO_FB          0x1004
 
 typedef void PCIConfigWriteFunc(PCIDevice *pci_dev,
                                 uint32_t address, uint32_t data, int len);
diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
index 1665b59..34937de 100644
--- a/hw/virtio-pci.c
+++ b/hw/virtio-pci.c
@@ -490,6 +490,25 @@ static int virtio_console_init_pci(PCIDevice *pci_dev)
     return 0;
 }
 
+static int virtio_fb_init_pci(PCIDevice *pci_dev)
+{
+    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
+    VirtIODevice *vdev;
+
+    if (proxy->class_code != PCI_CLASS_DISPLAY_OTHER)
+        proxy->class_code = PCI_CLASS_DISPLAY_OTHER;
+
+    vdev = virtio_fb_init(&pci_dev->qdev);
+    if (!vdev) {
+        return -1;
+    }
+    virtio_init_pci(proxy, vdev,
+                    PCI_VENDOR_ID_REDHAT_QUMRANET,
+                    PCI_DEVICE_ID_VIRTIO_FB,
+                    proxy->class_code, 0x00);
+    return 0;
+}
+
 static int virtio_net_init_pci(PCIDevice *pci_dev)
 {
     VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
@@ -574,6 +593,16 @@ static PCIDeviceInfo virtio_info[] = {
         },
         .qdev.reset = virtio_pci_reset,
     },{
+        .qdev.name = "virtio-fb-pci",
+        .qdev.size = sizeof(VirtIOPCIProxy),
+        .init      = virtio_fb_init_pci,
+        .exit      = virtio_exit_pci,
+        .qdev.props = (Property[]) {
+            DEFINE_PROP_HEX32("class", VirtIOPCIProxy, class_code, 0),
+            DEFINE_PROP_END_OF_LIST(),
+        },
+        .qdev.reset = virtio_pci_reset,
+    },{
         .qdev.name = "virtio-balloon-pci",
         .qdev.size = sizeof(VirtIOPCIProxy),
         .init      = virtio_balloon_init_pci,
diff --git a/sysemu.h b/sysemu.h
index 96804b4..c1bc5a3 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -104,13 +104,14 @@ extern int autostart;
 extern int bios_size;
 
 typedef enum {
-    VGA_NONE, VGA_STD, VGA_CIRRUS, VGA_VMWARE, VGA_XENFB
+    VGA_NONE, VGA_STD, VGA_CIRRUS, VGA_VMWARE, VGA_XENFB, VGA_VIRTIO
 } VGAInterfaceType;
 
 extern int vga_interface_type;
 #define cirrus_vga_enabled (vga_interface_type == VGA_CIRRUS)
 #define std_vga_enabled (vga_interface_type == VGA_STD)
 #define xenfb_enabled (vga_interface_type == VGA_XENFB)
+#define virtio_fb_enabled (vga_interface_type == VGA_VIRTIO)
 #define vmsvga_enabled (vga_interface_type == VGA_VMWARE)
 
 extern int graphic_width;
diff --git a/vl.c b/vl.c
index e57f58f..f999514 100644
--- a/vl.c
+++ b/vl.c
@@ -4297,6 +4297,8 @@ static void select_vgahw (const char *p)
         vga_interface_type = VGA_VMWARE;
     } else if (strstart(p, "xenfb", &opts)) {
         vga_interface_type = VGA_XENFB;
+    } else if (strstart(p, "virtio", &opts)) {
+        vga_interface_type = VGA_VIRTIO;
     } else if (!strstart(p, "none", &opts)) {
     invalid_vga:
         fprintf(stderr, "Unknown vga type: %s\n", p);
-- 
1.6.0.2


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [Qemu-devel] [PATCH 2/2] Add PCI virtio support for frame buffer
@ 2009-11-02 22:11   ` Alexander Graf
  0 siblings, 0 replies; 8+ messages in thread
From: Alexander Graf @ 2009-11-02 22:11 UTC (permalink / raw)
  To: kvm; +Cc: linux-fbdev-devel, qemu-devel

We now know how to use a frame buffer on VirtIO, but we still can't use it on
x86. In order to leverage the power of VirtIO FB, we need to wrap it through
virtio-pci.

So let's add all the shiny wrappers and add a -vga option.

Signed-off-by: Alexander Graf <agraf@suse.de>
---
 hw/pc.c         |    5 +++++
 hw/pci.h        |    1 +
 hw/virtio-pci.c |   29 +++++++++++++++++++++++++++++
 sysemu.h        |    3 ++-
 vl.c            |    2 ++
 5 files changed, 39 insertions(+), 1 deletions(-)

diff --git a/hw/pc.c b/hw/pc.c
index bf4718e..4b0d019 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -1190,6 +1190,11 @@ static void pc_init1(ram_addr_t ram_size,
         } else {
             isa_vga_init();
         }
+    } else if (virtio_fb_enabled) {
+        if (pci_enabled)
+            pci_create_simple(pci_bus, -1, "virtio-fb-pci");
+        else
+            fprintf(stderr, "%s: virtio_fb: no PCI bus\n", __FUNCTION__);
     }
 
     rtc_state = rtc_init(2000);
diff --git a/hw/pci.h b/hw/pci.h
index 93f93fb..b65a6df 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -70,6 +70,7 @@ extern target_phys_addr_t pci_mem_base;
 #define PCI_DEVICE_ID_VIRTIO_BLOCK       0x1001
 #define PCI_DEVICE_ID_VIRTIO_BALLOON     0x1002
 #define PCI_DEVICE_ID_VIRTIO_CONSOLE     0x1003
+#define PCI_DEVICE_ID_VIRTIO_FB          0x1004
 
 typedef void PCIConfigWriteFunc(PCIDevice *pci_dev,
                                 uint32_t address, uint32_t data, int len);
diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
index 1665b59..34937de 100644
--- a/hw/virtio-pci.c
+++ b/hw/virtio-pci.c
@@ -490,6 +490,25 @@ static int virtio_console_init_pci(PCIDevice *pci_dev)
     return 0;
 }
 
+static int virtio_fb_init_pci(PCIDevice *pci_dev)
+{
+    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
+    VirtIODevice *vdev;
+
+    if (proxy->class_code != PCI_CLASS_DISPLAY_OTHER)
+        proxy->class_code = PCI_CLASS_DISPLAY_OTHER;
+
+    vdev = virtio_fb_init(&pci_dev->qdev);
+    if (!vdev) {
+        return -1;
+    }
+    virtio_init_pci(proxy, vdev,
+                    PCI_VENDOR_ID_REDHAT_QUMRANET,
+                    PCI_DEVICE_ID_VIRTIO_FB,
+                    proxy->class_code, 0x00);
+    return 0;
+}
+
 static int virtio_net_init_pci(PCIDevice *pci_dev)
 {
     VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
@@ -574,6 +593,16 @@ static PCIDeviceInfo virtio_info[] = {
         },
         .qdev.reset = virtio_pci_reset,
     },{
+        .qdev.name = "virtio-fb-pci",
+        .qdev.size = sizeof(VirtIOPCIProxy),
+        .init      = virtio_fb_init_pci,
+        .exit      = virtio_exit_pci,
+        .qdev.props = (Property[]) {
+            DEFINE_PROP_HEX32("class", VirtIOPCIProxy, class_code, 0),
+            DEFINE_PROP_END_OF_LIST(),
+        },
+        .qdev.reset = virtio_pci_reset,
+    },{
         .qdev.name = "virtio-balloon-pci",
         .qdev.size = sizeof(VirtIOPCIProxy),
         .init      = virtio_balloon_init_pci,
diff --git a/sysemu.h b/sysemu.h
index 96804b4..c1bc5a3 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -104,13 +104,14 @@ extern int autostart;
 extern int bios_size;
 
 typedef enum {
-    VGA_NONE, VGA_STD, VGA_CIRRUS, VGA_VMWARE, VGA_XENFB
+    VGA_NONE, VGA_STD, VGA_CIRRUS, VGA_VMWARE, VGA_XENFB, VGA_VIRTIO
 } VGAInterfaceType;
 
 extern int vga_interface_type;
 #define cirrus_vga_enabled (vga_interface_type == VGA_CIRRUS)
 #define std_vga_enabled (vga_interface_type == VGA_STD)
 #define xenfb_enabled (vga_interface_type == VGA_XENFB)
+#define virtio_fb_enabled (vga_interface_type == VGA_VIRTIO)
 #define vmsvga_enabled (vga_interface_type == VGA_VMWARE)
 
 extern int graphic_width;
diff --git a/vl.c b/vl.c
index e57f58f..f999514 100644
--- a/vl.c
+++ b/vl.c
@@ -4297,6 +4297,8 @@ static void select_vgahw (const char *p)
         vga_interface_type = VGA_VMWARE;
     } else if (strstart(p, "xenfb", &opts)) {
         vga_interface_type = VGA_XENFB;
+    } else if (strstart(p, "virtio", &opts)) {
+        vga_interface_type = VGA_VIRTIO;
     } else if (!strstart(p, "none", &opts)) {
     invalid_vga:
         fprintf(stderr, "Unknown vga type: %s\n", p);
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [PATCH 1/2] Add emulation for VirtIO Frame Buffer device
  2009-11-02 22:11 ` [Qemu-devel] " Alexander Graf
@ 2009-11-03  6:22   ` Avi Kivity
  -1 siblings, 0 replies; 8+ messages in thread
From: Avi Kivity @ 2009-11-03  6:22 UTC (permalink / raw)
  To: Alexander Graf; +Cc: kvm, qemu-devel, linux-fbdev-devel, anthony

On 11/03/2009 12:11 AM, Alexander Graf wrote:
> Since Linux now understands how to talk to us graphics over VirtIO, let's
> add support for it in qemu.
>
> The good part about graphics over VirtIO is that you don't need PCI to use
> it. So if there's any platform out there trying to use graphics, but not
> capable of MMIO, it can use this one!
>    

Which platforms are these?

-- 
Do not meddle in the internals of kernels, for they are subtle and quick to panic.


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [Qemu-devel] Re: [PATCH 1/2] Add emulation for VirtIO Frame Buffer device
@ 2009-11-03  6:22   ` Avi Kivity
  0 siblings, 0 replies; 8+ messages in thread
From: Avi Kivity @ 2009-11-03  6:22 UTC (permalink / raw)
  To: Alexander Graf; +Cc: linux-fbdev-devel, qemu-devel, kvm

On 11/03/2009 12:11 AM, Alexander Graf wrote:
> Since Linux now understands how to talk to us graphics over VirtIO, let's
> add support for it in qemu.
>
> The good part about graphics over VirtIO is that you don't need PCI to use
> it. So if there's any platform out there trying to use graphics, but not
> capable of MMIO, it can use this one!
>    

Which platforms are these?

-- 
Do not meddle in the internals of kernels, for they are subtle and quick to panic.

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH 1/2] Add emulation for VirtIO Frame Buffer device
  2009-11-03  6:22   ` [Qemu-devel] " Avi Kivity
@ 2009-11-03  6:23     ` Alexander Graf
  -1 siblings, 0 replies; 8+ messages in thread
From: Alexander Graf @ 2009-11-03  6:23 UTC (permalink / raw)
  To: Avi Kivity; +Cc: kvm, qemu-devel, linux-fbdev-devel, anthony


On 03.11.2009, at 07:22, Avi Kivity wrote:

> On 11/03/2009 12:11 AM, Alexander Graf wrote:
>> Since Linux now understands how to talk to us graphics over VirtIO,  
>> let's
>> add support for it in qemu.
>>
>> The good part about graphics over VirtIO is that you don't need PCI  
>> to use
>> it. So if there's any platform out there trying to use graphics,  
>> but not
>> capable of MMIO, it can use this one!
>>
>
> Which platforms are these?

For now S390 comes to mind first ... :-). I'd use and improve the  
spice stuff, but that hasn't exactly been open-source friendly so far...

Alex


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [Qemu-devel] Re: [PATCH 1/2] Add emulation for VirtIO Frame Buffer device
@ 2009-11-03  6:23     ` Alexander Graf
  0 siblings, 0 replies; 8+ messages in thread
From: Alexander Graf @ 2009-11-03  6:23 UTC (permalink / raw)
  To: Avi Kivity; +Cc: linux-fbdev-devel, qemu-devel, kvm


On 03.11.2009, at 07:22, Avi Kivity wrote:

> On 11/03/2009 12:11 AM, Alexander Graf wrote:
>> Since Linux now understands how to talk to us graphics over VirtIO,  
>> let's
>> add support for it in qemu.
>>
>> The good part about graphics over VirtIO is that you don't need PCI  
>> to use
>> it. So if there's any platform out there trying to use graphics,  
>> but not
>> capable of MMIO, it can use this one!
>>
>
> Which platforms are these?

For now S390 comes to mind first ... :-). I'd use and improve the  
spice stuff, but that hasn't exactly been open-source friendly so far...

Alex

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2009-11-03  6:24 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-11-02 22:11 [PATCH 1/2] Add emulation for VirtIO Frame Buffer device Alexander Graf
2009-11-02 22:11 ` [Qemu-devel] " Alexander Graf
2009-11-02 22:11 ` [PATCH 2/2] Add PCI virtio support for frame buffer Alexander Graf
2009-11-02 22:11   ` [Qemu-devel] " Alexander Graf
2009-11-03  6:22 ` [PATCH 1/2] Add emulation for VirtIO Frame Buffer device Avi Kivity
2009-11-03  6:22   ` [Qemu-devel] " Avi Kivity
2009-11-03  6:23   ` Alexander Graf
2009-11-03  6:23     ` [Qemu-devel] " Alexander Graf

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.