All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH 0/8] add virtio-gpu
@ 2014-09-23 13:27 Gerd Hoffmann
  2014-09-23 13:28 ` [Qemu-devel] [PATCH 1/8] virtio-gpu/2d: add hardware spec include file Gerd Hoffmann
                   ` (7 more replies)
  0 siblings, 8 replies; 19+ messages in thread
From: Gerd Hoffmann @ 2014-09-23 13:27 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

  Hi,

Initial batch of virtio-gpu patches, covering 2D support.

Patch to the virtio spec has been sent to virtio-dev yesterday,
a formated version can be found here:
    https://www.kraxel.org/virtio/

What is the virtio 1.0 state btw?  Specs are final, do we have
qemu/kernel patches somewhere meanwhile?

please review,
  Gerd

Gerd Hoffmann (8):
  virtio-gpu/2d: add hardware spec include file
  virtio-gpu/2d: add virtio gpu core code
  virtio-gpu-pci: add virtio pci support
  virtio-vga: add virtio gpu device with vga compatibility
  virtio-vga: add '-vga virtio' support
  virtio-vga: add vgabios configuration
  virtio-vga: add vgabios binary
  virtio-gpu: add to display-vga test

 Makefile                           |   2 +-
 default-configs/x86_64-softmmu.mak |   3 +
 hw/display/Makefile.objs           |   4 +
 hw/display/virtio-gpu-pci.c        |  80 ++++
 hw/display/virtio-gpu.c            | 863 +++++++++++++++++++++++++++++++++++++
 hw/display/virtio-vga.c            | 169 ++++++++
 hw/pci/pci.c                       |   2 +
 hw/virtio/virtio-pci.h             |  15 +
 include/hw/pci/pci.h               |   1 +
 include/hw/virtio/virtgpu_hw.h     | 207 +++++++++
 include/hw/virtio/virtio-gpu.h     | 147 +++++++
 include/sysemu/sysemu.h            |   2 +-
 pc-bios/vgabios-virtio.bin         | Bin 0 -> 37376 bytes
 roms/Makefile                      |   2 +-
 roms/config.vga-virtio             |   6 +
 tests/Makefile                     |   3 +
 tests/display-vga-test.c           |  18 +
 trace-events                       |  14 +
 vl.c                               |  13 +
 19 files changed, 1548 insertions(+), 3 deletions(-)
 create mode 100644 hw/display/virtio-gpu-pci.c
 create mode 100644 hw/display/virtio-gpu.c
 create mode 100644 hw/display/virtio-vga.c
 create mode 100644 include/hw/virtio/virtgpu_hw.h
 create mode 100644 include/hw/virtio/virtio-gpu.h
 create mode 100644 pc-bios/vgabios-virtio.bin
 create mode 100644 roms/config.vga-virtio

-- 
1.8.3.1

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

* [Qemu-devel] [PATCH 1/8] virtio-gpu/2d: add hardware spec include file
  2014-09-23 13:27 [Qemu-devel] [PATCH 0/8] add virtio-gpu Gerd Hoffmann
@ 2014-09-23 13:28 ` Gerd Hoffmann
  2014-09-25 15:02   ` Gerd Hoffmann
  2014-10-15 10:05   ` Gerd Hoffmann
  2014-09-23 13:28 ` [Qemu-devel] [PATCH 2/8] virtio-gpu/2d: add virtio gpu core code Gerd Hoffmann
                   ` (6 subsequent siblings)
  7 siblings, 2 replies; 19+ messages in thread
From: Gerd Hoffmann @ 2014-09-23 13:28 UTC (permalink / raw)
  To: qemu-devel; +Cc: Dave Airlie, Gerd Hoffmann

This patch adds the header file with structs and defines for
the virtio based gpu device.  Covers 2d operations only.

Written by Dave Airlie and Gerd Hoffmann.

Signed-off-by: Dave Airlie <airlied@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 include/hw/virtio/virtgpu_hw.h | 207 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 207 insertions(+)
 create mode 100644 include/hw/virtio/virtgpu_hw.h

diff --git a/include/hw/virtio/virtgpu_hw.h b/include/hw/virtio/virtgpu_hw.h
new file mode 100644
index 0000000..b421a4e
--- /dev/null
+++ b/include/hw/virtio/virtgpu_hw.h
@@ -0,0 +1,207 @@
+/*
+ * Virtio GPU Device
+ *
+ * Copyright Red Hat, Inc. 2013-2014
+ *
+ * Authors:
+ *     Dave Airlie <airlied@redhat.com>
+ *     Gerd Hoffmann <kraxel@redhat.com>
+ *
+ * This header is BSD licensed so anyone can use the definitions
+ * to implement compatible drivers/servers:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of IBM nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL IBM OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef VIRTIO_GPU_HW_H
+#define VIRTIO_GPU_HW_H
+
+enum virtio_gpu_ctrl_type {
+    VIRTIO_GPU_UNDEFINED = 0,
+
+    /* 2d commands */
+    VIRTIO_GPU_CMD_GET_DISPLAY_INFO = 0x0100,
+    VIRTIO_GPU_CMD_RESOURCE_CREATE_2D,
+    VIRTIO_GPU_CMD_RESOURCE_UNREF,
+    VIRTIO_GPU_CMD_SET_SCANOUT,
+    VIRTIO_GPU_CMD_RESOURCE_FLUSH,
+    VIRTIO_GPU_CMD_TRANSFER_TO_HOST_2D,
+    VIRTIO_GPU_CMD_RESOURCE_ATTACH_BACKING,
+    VIRTIO_GPU_CMD_RESOURCE_DETACH_BACKING,
+
+    /* cursor commands */
+    VIRTIO_GPU_CMD_UPDATE_CURSOR = 0x0300,
+    VIRTIO_GPU_CMD_MOVE_CURSOR,
+
+    /* success responses */
+    VIRTIO_GPU_RESP_OK_NODATA = 0x1100,
+    VIRTIO_GPU_RESP_OK_DISPLAY_INFO,
+
+    /* error responses */
+    VIRTIO_GPU_RESP_ERR_UNSPEC = 0x1200,
+    VIRTIO_GPU_RESP_ERR_OUT_OF_MEMORY,
+    VIRTIO_GPU_RESP_ERR_INVALID_SCANOUT_ID,
+    VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID,
+    VIRTIO_GPU_RESP_ERR_INVALID_CONTEXT_ID,
+    VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER,
+};
+
+#define VIRTIO_GPU_FLAG_FENCE (1 << 0)
+
+struct virtio_gpu_ctrl_hdr {
+    uint32_t type;
+    uint32_t flags;
+    uint64_t fence_id;
+    uint32_t ctx_id;
+    uint32_t padding;
+};
+
+/* data passed in the cursor vq */
+
+struct virtio_gpu_cursor_pos {
+    uint32_t scanout_id;
+    uint32_t x;
+    uint32_t y;
+    uint32_t padding;
+};
+
+/* VIRTIO_GPU_CMD_UPDATE_CURSOR, VIRTIO_GPU_CMD_MOVE_CURSOR */
+struct virtio_gpu_update_cursor {
+    struct virtio_gpu_ctrl_hdr hdr;
+    struct virtio_gpu_cursor_pos pos;  /* update & move */
+    uint32_t resource_id;           /* update only */
+    uint32_t hot_x;                 /* update only */
+    uint32_t hot_y;                 /* update only */
+    uint32_t padding;
+};
+
+/* data passed in the control vq, 2d related */
+
+/* VIRTIO_GPU_CMD_RESOURCE_UNREF */
+struct virtio_gpu_resource_unref {
+    struct virtio_gpu_ctrl_hdr hdr;
+    uint32_t resource_id;
+    uint32_t padding;
+};
+
+/* VIRTIO_GPU_CMD_RESOURCE_CREATE_2D: create a 2d resource with a format */
+struct virtio_gpu_resource_create_2d {
+    struct virtio_gpu_ctrl_hdr hdr;
+    uint32_t resource_id;
+    uint32_t format;
+    uint32_t width;
+    uint32_t height;
+};
+
+/* VIRTIO_GPU_CMD_SET_SCANOUT */
+struct virtio_gpu_set_scanout {
+    struct virtio_gpu_ctrl_hdr hdr;
+    uint32_t scanout_id;
+    uint32_t resource_id;
+    uint32_t width;
+    uint32_t height;
+    uint32_t x;
+    uint32_t y;
+};
+
+/* VIRTIO_GPU_CMD_RESOURCE_FLUSH */
+struct virtio_gpu_resource_flush {
+    struct virtio_gpu_ctrl_hdr hdr;
+    uint32_t resource_id;
+    uint32_t width;
+    uint32_t height;
+    uint32_t x;
+    uint32_t y;
+    uint32_t padding;
+};
+
+/* VIRTIO_GPU_CMD_TRANSFER_TO_HOST_2D: simple transfer to_host */
+struct virtio_gpu_transfer_to_host_2d {
+    struct virtio_gpu_ctrl_hdr hdr;
+    uint32_t resource_id;
+    uint32_t offset;
+    uint32_t width;
+    uint32_t height;
+    uint32_t x;
+    uint32_t y;
+};
+
+struct virtio_gpu_mem_entry {
+    uint64_t addr;
+    uint32_t length;
+    uint32_t pad;
+};
+
+/* VIRTIO_GPU_CMD_RESOURCE_ATTACH_BACKING */
+struct virtio_gpu_resource_attach_backing {
+    struct virtio_gpu_ctrl_hdr hdr;
+    uint32_t resource_id;
+    uint32_t nr_entries;
+};
+
+/* VIRTIO_GPU_CMD_RESOURCE_DETACH_BACKING */
+struct virtio_gpu_resource_detach_backing {
+    struct virtio_gpu_ctrl_hdr hdr;
+    uint32_t resource_id;
+    uint32_t padding;
+};
+
+/* VIRTIO_GPU_RESP_OK_DISPLAY_INFO */
+#define VIRTIO_GPU_MAX_SCANOUTS 16
+struct virtio_gpu_resp_display_info {
+    struct virtio_gpu_ctrl_hdr hdr;
+    struct virtio_gpu_display_one {
+        uint32_t enabled;
+        uint32_t width;
+        uint32_t height;
+        uint32_t x;
+        uint32_t y;
+        uint32_t flags;
+    } pmodes[VIRTIO_GPU_MAX_SCANOUTS];
+};
+
+#define VIRTIO_GPU_EVENT_DISPLAY (1 << 0)
+
+struct virtio_gpu_config {
+    uint32_t events_read;
+    uint32_t events_clear;
+    uint32_t num_scanouts;
+    uint32_t reserved;
+};
+
+/* simple formats for fbcon/X use */
+enum virtio_gpu_formats {
+    VIRTIO_GPU_FORMAT_B8G8R8A8_UNORM  = 1,
+    VIRTIO_GPU_FORMAT_B8G8R8X8_UNORM  = 2,
+    VIRTIO_GPU_FORMAT_A8R8G8B8_UNORM  = 3,
+    VIRTIO_GPU_FORMAT_X8R8G8B8_UNORM  = 4,
+
+    VIRTIO_GPU_FORMAT_B5G5R5A1_UNORM  = 5,
+    VIRTIO_GPU_FORMAT_B5G6R5_UNORM    = 7,
+
+    VIRTIO_GPU_FORMAT_R8_UNORM        = 64,
+};
+
+#endif
-- 
1.8.3.1

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

* [Qemu-devel] [PATCH 2/8] virtio-gpu/2d: add virtio gpu core code
  2014-09-23 13:27 [Qemu-devel] [PATCH 0/8] add virtio-gpu Gerd Hoffmann
  2014-09-23 13:28 ` [Qemu-devel] [PATCH 1/8] virtio-gpu/2d: add hardware spec include file Gerd Hoffmann
@ 2014-09-23 13:28 ` Gerd Hoffmann
  2014-09-23 13:28 ` [Qemu-devel] [PATCH 3/8] virtio-gpu-pci: add virtio pci support Gerd Hoffmann
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 19+ messages in thread
From: Gerd Hoffmann @ 2014-09-23 13:28 UTC (permalink / raw)
  To: qemu-devel
  Cc: Dave Airlie, Gerd Hoffmann, Anthony Liguori, Michael S. Tsirkin

This patch adds the core code for virtio gpu emulation,
covering 2d support.

Written by Dave Airlie and Gerd Hoffmann.

Signed-off-by: Dave Airlie <airlied@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 default-configs/x86_64-softmmu.mak |   1 +
 hw/display/Makefile.objs           |   2 +
 hw/display/virtio-gpu.c            | 863 +++++++++++++++++++++++++++++++++++++
 include/hw/virtio/virtio-gpu.h     | 147 +++++++
 trace-events                       |  14 +
 5 files changed, 1027 insertions(+)
 create mode 100644 hw/display/virtio-gpu.c
 create mode 100644 include/hw/virtio/virtio-gpu.h

diff --git a/default-configs/x86_64-softmmu.mak b/default-configs/x86_64-softmmu.mak
index 66557ac..75a123a 100644
--- a/default-configs/x86_64-softmmu.mak
+++ b/default-configs/x86_64-softmmu.mak
@@ -9,6 +9,7 @@ CONFIG_VGA_PCI=y
 CONFIG_VGA_ISA=y
 CONFIG_VGA_CIRRUS=y
 CONFIG_VMWARE_VGA=y
+CONFIG_VIRTIO_GPU=y
 CONFIG_VMMOUSE=y
 CONFIG_SERIAL=y
 CONFIG_PARALLEL=y
diff --git a/hw/display/Makefile.objs b/hw/display/Makefile.objs
index 7ed76a9..29f179f 100644
--- a/hw/display/Makefile.objs
+++ b/hw/display/Makefile.objs
@@ -33,3 +33,5 @@ obj-$(CONFIG_CG3) += cg3.o
 obj-$(CONFIG_VGA) += vga.o
 
 common-obj-$(CONFIG_QXL) += qxl.o qxl-logger.o qxl-render.o
+
+obj-$(CONFIG_VIRTIO_GPU) += virtio-gpu.o
diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
new file mode 100644
index 0000000..2f1cbd4
--- /dev/null
+++ b/hw/display/virtio-gpu.c
@@ -0,0 +1,863 @@
+/*
+ * Virtio GPU Device
+ *
+ * Copyright Red Hat, Inc. 2013-2014
+ *
+ * Authors:
+ *     Dave Airlie <airlied@redhat.com>
+ *     Gerd Hoffmann <kraxel@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu-common.h"
+#include "qemu/iov.h"
+#include "ui/console.h"
+#include "trace.h"
+#include "hw/virtio/virtio.h"
+#include "hw/virtio/virtio-gpu.h"
+#include "hw/virtio/virtio-bus.h"
+
+static struct virtio_gpu_simple_resource*
+virtio_gpu_find_resource(VirtIOGPU *g, uint32_t resource_id);
+
+static void update_cursor_data_simple(VirtIOGPU *g,
+                                      struct virtio_gpu_scanout *s,
+                                      uint32_t resource_id)
+{
+    struct virtio_gpu_simple_resource *res;
+    uint32_t pixels;
+
+    res = virtio_gpu_find_resource(g, resource_id);
+    if (!res) {
+        return;
+    }
+
+    pixels = s->current_cursor->width * s->current_cursor->height;
+    memcpy(s->current_cursor->data,
+           pixman_image_get_data(res->image),
+           pixels * sizeof(uint32_t));
+}
+
+static void update_cursor(VirtIOGPU *g, struct virtio_gpu_update_cursor *cursor)
+{
+    struct virtio_gpu_scanout *s;
+
+    if (cursor->pos.scanout_id >= g->conf.max_outputs) {
+        return;
+    }
+    s = &g->scanout[cursor->pos.scanout_id];
+
+    if (cursor->hdr.type != VIRTIO_GPU_CMD_MOVE_CURSOR) {
+        if (!s->current_cursor) {
+            s->current_cursor = cursor_alloc(64, 64);
+        }
+
+        s->current_cursor->hot_x = cursor->hot_x;
+        s->current_cursor->hot_y = cursor->hot_y;
+
+        if (cursor->resource_id > 0) {
+            update_cursor_data_simple(g, s, cursor->resource_id);
+        }
+        dpy_cursor_define(s->con, s->current_cursor);
+    }
+    dpy_mouse_set(s->con, cursor->pos.x, cursor->pos.y,
+                  cursor->resource_id ? 1 : 0);
+}
+
+static void virtio_gpu_get_config(VirtIODevice *vdev, uint8_t *config)
+{
+    VirtIOGPU *g = VIRTIO_GPU(vdev);
+    memcpy(config, &g->virtio_config, sizeof(g->virtio_config));
+}
+
+static void virtio_gpu_set_config(VirtIODevice *vdev, const uint8_t *config)
+{
+    VirtIOGPU *g = VIRTIO_GPU(vdev);
+    struct virtio_gpu_config vgconfig;
+
+    memcpy(&vgconfig, config, sizeof(g->virtio_config));
+
+    if (vgconfig.events_clear) {
+        g->virtio_config.events_read &= ~vgconfig.events_clear;
+    }
+}
+
+static uint32_t virtio_gpu_get_features(VirtIODevice *vdev, uint32_t features)
+{
+    return features;
+}
+
+static void virtio_gpu_set_features(VirtIODevice *vdev, uint32_t features)
+{
+}
+
+static void virtio_gpu_notify_event(VirtIOGPU *g, uint32_t event_type)
+{
+    g->virtio_config.events_read |= event_type;
+    virtio_notify_config(&g->parent_obj);
+}
+
+static struct virtio_gpu_simple_resource *
+virtio_gpu_find_resource(VirtIOGPU *g, uint32_t resource_id)
+{
+    struct virtio_gpu_simple_resource *res;
+
+    QTAILQ_FOREACH(res, &g->reslist, next) {
+        if (res->resource_id == resource_id) {
+            return res;
+        }
+    }
+    return NULL;
+}
+
+void virtio_gpu_ctrl_response(VirtIOGPU *g,
+                              struct virtio_gpu_ctrl_command *cmd,
+                              struct virtio_gpu_ctrl_hdr *resp,
+                              size_t resp_len)
+{
+    size_t s;
+
+    if (cmd->cmd_hdr.flags & VIRTIO_GPU_FLAG_FENCE) {
+        resp->flags |= VIRTIO_GPU_FLAG_FENCE;
+        resp->fence_id = cmd->cmd_hdr.fence_id;
+        resp->ctx_id = cmd->cmd_hdr.ctx_id;
+    }
+    s = iov_from_buf(cmd->elem.in_sg, cmd->elem.in_num, 0, resp, resp_len);
+    if (s != resp_len) {
+        qemu_log_mask(LOG_GUEST_ERROR,
+                      "%s: response size incorrect %zu vs %zu\n",
+                      __func__, s, resp_len);
+    }
+    virtqueue_push(cmd->vq, &cmd->elem, s);
+    virtio_notify(VIRTIO_DEVICE(g), cmd->vq);
+    cmd->finished = true;
+}
+
+void virtio_gpu_ctrl_response_nodata(VirtIOGPU *g,
+                                     struct virtio_gpu_ctrl_command *cmd,
+                                     enum virtio_gpu_ctrl_type type)
+{
+    struct virtio_gpu_ctrl_hdr resp;
+
+    memset(&resp, 0, sizeof(resp));
+    resp.type = type;
+    virtio_gpu_ctrl_response(g, cmd, &resp, sizeof(resp));
+}
+
+static void
+virtio_gpu_fill_display_info(VirtIOGPU *g,
+                             struct virtio_gpu_resp_display_info *dpy_info)
+{
+    int i;
+
+    for (i = 0; i < g->conf.max_outputs; i++) {
+        if (g->enabled_output_bitmask & (1 << i)) {
+            dpy_info->pmodes[i].enabled = 1;
+            dpy_info->pmodes[i].width = g->req_state[i].width;
+            dpy_info->pmodes[i].height = g->req_state[i].height;
+        }
+    }
+}
+
+void virtio_gpu_get_display_info(VirtIOGPU *g,
+                                 struct virtio_gpu_ctrl_command *cmd)
+{
+    struct virtio_gpu_resp_display_info display_info;
+
+    trace_virtio_gpu_cmd_get_display_info();
+    memset(&display_info, 0, sizeof(display_info));
+    display_info.hdr.type = VIRTIO_GPU_RESP_OK_DISPLAY_INFO;
+    virtio_gpu_fill_display_info(g, &display_info);
+    virtio_gpu_ctrl_response(g, cmd, &display_info.hdr,
+                             sizeof(display_info));
+}
+
+static pixman_format_code_t get_pixman_format(uint32_t virtio_gpu_format)
+{
+    switch (virtio_gpu_format) {
+    case VIRTIO_GPU_FORMAT_B8G8R8X8_UNORM:
+        return PIXMAN_x8r8g8b8;
+    case VIRTIO_GPU_FORMAT_B8G8R8A8_UNORM:
+        return PIXMAN_a8r8g8b8;
+    case VIRTIO_GPU_FORMAT_B5G6R5_UNORM:
+        return PIXMAN_r5g6b5;
+    default:
+        break;
+    }
+    return 0;
+}
+
+static void virtio_gpu_resource_create_2d(VirtIOGPU *g,
+                                          struct virtio_gpu_ctrl_command *cmd)
+{
+    pixman_format_code_t pformat;
+    struct virtio_gpu_simple_resource *res;
+    struct virtio_gpu_resource_create_2d c2d;
+
+    VIRTIO_GPU_FILL_CMD(c2d);
+    trace_virtio_gpu_cmd_res_create_2d(c2d.resource_id, c2d.format,
+                                       c2d.width, c2d.height);
+
+    res = virtio_gpu_find_resource(g, c2d.resource_id);
+    if (res) {
+        qemu_log_mask(LOG_GUEST_ERROR, "%s: resource already exists %d\n",
+                      __func__, c2d.resource_id);
+        cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID;
+        return;
+    }
+
+    res = g_new0(struct virtio_gpu_simple_resource, 1);
+
+    res->width = c2d.width;
+    res->height = c2d.height;
+    res->format = c2d.format;
+    res->resource_id = c2d.resource_id;
+
+    pformat = get_pixman_format(c2d.format);
+    if (!pformat) {
+        qemu_log_mask(LOG_GUEST_ERROR,
+                      "%s: host couldn't handle guest format %d\n",
+                      __func__, c2d.format);
+        cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER;
+        return;
+    }
+    res->image = pixman_image_create_bits(pformat,
+                                          c2d.width,
+                                          c2d.height,
+                                          NULL, 0);
+
+    if (!res->image) {
+        qemu_log_mask(LOG_GUEST_ERROR,
+                      "%s: resource creation failed %d %d %d\n",
+                      __func__, c2d.resource_id, c2d.width, c2d.height);
+        g_free(res);
+        cmd->error = VIRTIO_GPU_RESP_ERR_OUT_OF_MEMORY;
+        return;
+    }
+
+    QTAILQ_INSERT_HEAD(&g->reslist, res, next);
+}
+
+static void virtio_gpu_resource_destroy(VirtIOGPU *g,
+                                        struct virtio_gpu_simple_resource *res)
+{
+    pixman_image_unref(res->image);
+    QTAILQ_REMOVE(&g->reslist, res, next);
+    g_free(res);
+}
+
+static void virtio_gpu_resource_unref(VirtIOGPU *g,
+                                      struct virtio_gpu_ctrl_command *cmd)
+{
+    struct virtio_gpu_simple_resource *res;
+    struct virtio_gpu_resource_unref unref;
+
+    VIRTIO_GPU_FILL_CMD(unref);
+    trace_virtio_gpu_cmd_res_unref(unref.resource_id);
+
+    res = virtio_gpu_find_resource(g, unref.resource_id);
+    if (!res) {
+        qemu_log_mask(LOG_GUEST_ERROR, "%s: illegal resource specified %d\n",
+                      __func__, unref.resource_id);
+        cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID;
+        return;
+    }
+    virtio_gpu_resource_destroy(g, res);
+}
+
+static void virtio_gpu_transfer_to_host_2d(VirtIOGPU *g,
+                                           struct virtio_gpu_ctrl_command *cmd)
+{
+    struct virtio_gpu_simple_resource *res;
+    int h;
+    uint32_t src_offset, dst_offset, stride;
+    int bpp;
+    pixman_format_code_t format;
+    struct virtio_gpu_transfer_to_host_2d t2d;
+
+    VIRTIO_GPU_FILL_CMD(t2d);
+    trace_virtio_gpu_cmd_res_xfer_toh_2d(t2d.resource_id);
+
+    res = virtio_gpu_find_resource(g, t2d.resource_id);
+    if (!res || !res->iov) {
+        qemu_log_mask(LOG_GUEST_ERROR, "%s: illegal resource specified %d\n",
+                      __func__, t2d.resource_id);
+        cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID;
+        return;
+    }
+
+    if (t2d.x > res->width ||
+        t2d.y > res->height ||
+        t2d.width > res->width ||
+        t2d.height > res->height ||
+        t2d.x + t2d.width > res->width ||
+        t2d.y + t2d.height > res->height) {
+        qemu_log_mask(LOG_GUEST_ERROR, "%s: transfer bounds outside resource"
+                      " bounds for resource %d: %d %d %d %d vs %d %d\n",
+                      __func__, t2d.resource_id, t2d.x, t2d.y,
+                      t2d.width, t2d.height, res->width, res->height);
+        cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER;
+        return;
+    }
+
+    format = pixman_image_get_format(res->image);
+    bpp = (PIXMAN_FORMAT_BPP(format) + 7) / 8;
+    stride = pixman_image_get_stride(res->image);
+
+    if (t2d.offset || t2d.x || t2d.y ||
+        t2d.width != pixman_image_get_width(res->image)) {
+        void *img_data = pixman_image_get_data(res->image);
+        for (h = 0; h < t2d.height; h++) {
+            src_offset = t2d.offset + stride * h;
+            dst_offset = (t2d.y + h) * stride + (t2d.x * bpp);
+
+            iov_to_buf(res->iov, res->iov_cnt, src_offset,
+                       (uint8_t *)img_data
+                       + dst_offset, t2d.width * bpp);
+        }
+    } else {
+        iov_to_buf(res->iov, res->iov_cnt, 0,
+                   pixman_image_get_data(res->image),
+                   pixman_image_get_stride(res->image)
+                   * pixman_image_get_height(res->image));
+    }
+}
+
+static void virtio_gpu_resource_flush(VirtIOGPU *g,
+                                      struct virtio_gpu_ctrl_command *cmd)
+{
+    struct virtio_gpu_simple_resource *res;
+    struct virtio_gpu_resource_flush rf;
+    pixman_region16_t flush_region;
+    int i;
+
+    VIRTIO_GPU_FILL_CMD(rf);
+    trace_virtio_gpu_cmd_res_flush(rf.resource_id,
+                                   rf.width, rf.height, rf.x, rf.y);
+
+    res = virtio_gpu_find_resource(g, rf.resource_id);
+    if (!res) {
+        qemu_log_mask(LOG_GUEST_ERROR, "%s: illegal resource specified %d\n",
+                      __func__, rf.resource_id);
+        cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID;
+        return;
+    }
+
+    if (rf.x > res->width ||
+        rf.y > res->height ||
+        rf.width > res->width ||
+        rf.height > res->height ||
+        rf.x + rf.width > res->width ||
+        rf.y + rf.height > res->height) {
+        qemu_log_mask(LOG_GUEST_ERROR, "%s: flush bounds outside resource"
+                      " bounds for resource %d: %d %d %d %d vs %d %d\n",
+                      __func__, rf.resource_id, rf.x, rf.y,
+                      rf.width, rf.height, res->width, res->height);
+        cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER;
+        return;
+    }
+
+    pixman_region_init_rect(&flush_region,
+                            rf.x, rf.y, rf.width, rf.height);
+    for (i = 0; i < VIRTIO_GPU_MAX_SCANOUT; i++) {
+        struct virtio_gpu_scanout *scanout;
+        pixman_region16_t region, finalregion;
+        pixman_box16_t *extents;
+
+        if (!(res->scanout_bitmask & (1 << i))) {
+            continue;
+        }
+        scanout = &g->scanout[i];
+
+        pixman_region_init(&finalregion);
+        pixman_region_init_rect(&region, scanout->x, scanout->y,
+                                scanout->width, scanout->height);
+
+        pixman_region_intersect(&finalregion, &flush_region, &region);
+        pixman_region_translate(&finalregion, -scanout->x, -scanout->y);
+        extents = pixman_region_extents(&finalregion);
+        /* work out the area we need to update for each console */
+        dpy_gfx_update(g->scanout[i].con,
+                       extents->x1, extents->y1,
+                       extents->x2 - extents->x1,
+                       extents->y2 - extents->y1);
+
+        pixman_region_fini(&region);
+        pixman_region_fini(&finalregion);
+    }
+    pixman_region_fini(&flush_region);
+}
+
+static void virtio_gpu_set_scanout(VirtIOGPU *g,
+                                   struct virtio_gpu_ctrl_command *cmd)
+{
+    struct virtio_gpu_simple_resource *res;
+    struct virtio_gpu_scanout *scanout;
+    pixman_format_code_t format;
+    uint32_t offset;
+    int bpp;
+    struct virtio_gpu_set_scanout ss;
+
+    VIRTIO_GPU_FILL_CMD(ss);
+    trace_virtio_gpu_cmd_set_scanout(ss.scanout_id, ss.resource_id,
+                                     ss.width, ss.height, ss.x, ss.y);
+
+    res = virtio_gpu_find_resource(g, ss.resource_id);
+    g->enable = 1;
+    if (ss.resource_id == 0) {
+        scanout = &g->scanout[ss.scanout_id];
+        if (g->scanout[ss.scanout_id].resource_id) {
+            res = virtio_gpu_find_resource(g, scanout->resource_id);
+            if (res) {
+                res->scanout_bitmask &= ~(1 << ss.scanout_id);
+            }
+        }
+        if (ss.scanout_id == 0 ||
+            ss.scanout_id >= g->conf.max_outputs) {
+            qemu_log_mask(LOG_GUEST_ERROR,
+                          "%s: illegal scanout id specified %d",
+                          __func__, ss.scanout_id);
+            cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_SCANOUT_ID;
+            return;
+        }
+        dpy_gfx_replace_surface(g->scanout[ss.scanout_id].con, NULL);
+        scanout->ds = NULL;
+        scanout->width = 0;
+        scanout->height = 0;
+        return;
+    }
+
+    /* create a surface for this scanout */
+    if (ss.scanout_id >= VIRTIO_GPU_MAX_SCANOUT ||
+        ss.scanout_id >= g->conf.max_outputs) {
+        qemu_log_mask(LOG_GUEST_ERROR, "%s: illegal scanout id specified %d",
+                      __func__, ss.scanout_id);
+        cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_SCANOUT_ID;
+        return;
+    }
+    if (!res) {
+        qemu_log_mask(LOG_GUEST_ERROR, "%s: illegal resource specified %d\n",
+                      __func__, ss.resource_id);
+        cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID;
+        return;
+    }
+
+    if (ss.x > res->width ||
+        ss.y > res->height ||
+        ss.width > res->width ||
+        ss.height > res->height ||
+        ss.x + ss.width > res->width ||
+        ss.y + ss.height > res->height) {
+        qemu_log_mask(LOG_GUEST_ERROR, "%s: illegal scanout %d bounds for"
+                      " resource %d, (%d,%d)+%d,%d vs %d %d\n",
+                      __func__, ss.scanout_id, ss.resource_id, ss.x, ss.y,
+                      ss.width, ss.height, res->width, res->height);
+        cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER;
+        return;
+    }
+
+    scanout = &g->scanout[ss.scanout_id];
+
+    format = pixman_image_get_format(res->image);
+    bpp = (PIXMAN_FORMAT_BPP(format) + 7) / 8;
+    offset = (ss.x * bpp) + ss.y * pixman_image_get_stride(res->image);
+    if (!scanout->ds || surface_data(scanout->ds)
+        != ((uint8_t *)pixman_image_get_data(res->image) + offset) ||
+        scanout->width != ss.width ||
+        scanout->height != ss.height) {
+        /* realloc the surface ptr */
+        scanout->ds = qemu_create_displaysurface_from
+            (ss.width, ss.height, format, pixman_image_get_stride(res->image),
+             (uint8_t *)pixman_image_get_data(res->image) + offset);
+        if (!scanout->ds) {
+            cmd->error = VIRTIO_GPU_RESP_ERR_UNSPEC;
+            return;
+        }
+        dpy_gfx_replace_surface(g->scanout[ss.scanout_id].con, scanout->ds);
+    }
+
+    res->scanout_bitmask |= (1 << ss.scanout_id);
+    scanout->resource_id = ss.resource_id;
+    scanout->x = ss.x;
+    scanout->y = ss.y;
+    scanout->width = ss.width;
+    scanout->height = ss.height;
+}
+
+int virtio_gpu_create_mapping_iov(struct virtio_gpu_resource_attach_backing *ab,
+                                  struct virtio_gpu_ctrl_command *cmd,
+                                  struct iovec **iov)
+{
+    struct virtio_gpu_mem_entry *ents;
+    size_t esize, s;
+    int i;
+
+    esize = sizeof(*ents) * ab->nr_entries;
+    ents = g_malloc(esize);
+    s = iov_to_buf(cmd->elem.out_sg, cmd->elem.out_num,
+                   sizeof(*ab), ents, esize);
+    if (s != esize) {
+        qemu_log_mask(LOG_GUEST_ERROR,
+                      "%s: command data size incorrect %zu vs %zu\n",
+                      __func__, s, esize);
+        g_free(ents);
+        return -1;
+    }
+
+    *iov = g_malloc0(sizeof(struct iovec) * ab->nr_entries);
+    for (i = 0; i < ab->nr_entries; i++) {
+        hwaddr len = ents[i].length;
+        (*iov)[i].iov_len = ents[i].length;
+        (*iov)[i].iov_base = cpu_physical_memory_map(ents[i].addr, &len, 1);
+        if (!(*iov)[i].iov_base || len != ents[i].length) {
+            qemu_log_mask(LOG_GUEST_ERROR, "%s: failed to map MMIO memory for"
+                          " resource %d element %d\n",
+                          __func__, ab->resource_id, i);
+            virtio_gpu_cleanup_mapping_iov(*iov, i);
+            g_free(ents);
+            g_free(*iov);
+            *iov = NULL;
+            return -1;
+        }
+    }
+    g_free(ents);
+    return 0;
+}
+
+void virtio_gpu_cleanup_mapping_iov(struct iovec *iov, uint32_t count)
+{
+    int i;
+
+    for (i = 0; i < count; i++) {
+        cpu_physical_memory_unmap(iov[i].iov_base, iov[i].iov_len, 1,
+                                  iov[i].iov_len);
+    }
+}
+
+static void virtio_gpu_cleanup_mapping(struct virtio_gpu_simple_resource *res)
+{
+    virtio_gpu_cleanup_mapping_iov(res->iov, res->iov_cnt);
+    g_free(res->iov);
+    res->iov = NULL;
+    res->iov_cnt = 0;
+}
+
+static void
+virtio_gpu_resource_attach_backing(VirtIOGPU *g,
+                                   struct virtio_gpu_ctrl_command *cmd)
+{
+    struct virtio_gpu_simple_resource *res;
+    struct virtio_gpu_resource_attach_backing ab;
+    int ret;
+
+    VIRTIO_GPU_FILL_CMD(ab);
+    trace_virtio_gpu_cmd_res_back_attach(ab.resource_id);
+
+    res = virtio_gpu_find_resource(g, ab.resource_id);
+    if (!res) {
+        qemu_log_mask(LOG_GUEST_ERROR, "%s: illegal resource specified %d\n",
+                      __func__, ab.resource_id);
+        cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID;
+        return;
+    }
+
+    ret = virtio_gpu_create_mapping_iov(&ab, cmd, &res->iov);
+    if (ret != 0) {
+        cmd->error = VIRTIO_GPU_RESP_ERR_UNSPEC;
+        return;
+    }
+
+    res->iov_cnt = ab.nr_entries;
+}
+
+static void
+virtio_gpu_resource_detach_backing(VirtIOGPU *g,
+                                   struct virtio_gpu_ctrl_command *cmd)
+{
+    struct virtio_gpu_simple_resource *res;
+    struct virtio_gpu_resource_detach_backing detach;
+
+    VIRTIO_GPU_FILL_CMD(detach);
+    trace_virtio_gpu_cmd_res_back_detach(detach.resource_id);
+
+    res = virtio_gpu_find_resource(g, detach.resource_id);
+    if (!res || !res->iov) {
+        qemu_log_mask(LOG_GUEST_ERROR, "%s: illegal resource specified %d\n",
+                      __func__, detach.resource_id);
+        cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID;
+        return;
+    }
+    virtio_gpu_cleanup_mapping(res);
+}
+
+static void virtio_gpu_simple_process_cmd(VirtIOGPU *g,
+                                          struct virtio_gpu_ctrl_command *cmd)
+{
+    VIRTIO_GPU_FILL_CMD(cmd->cmd_hdr);
+
+    switch (cmd->cmd_hdr.type) {
+    case VIRTIO_GPU_CMD_GET_DISPLAY_INFO:
+        virtio_gpu_get_display_info(g, cmd);
+        break;
+    case VIRTIO_GPU_CMD_RESOURCE_CREATE_2D:
+        virtio_gpu_resource_create_2d(g, cmd);
+        break;
+    case VIRTIO_GPU_CMD_RESOURCE_UNREF:
+        virtio_gpu_resource_unref(g, cmd);
+        break;
+    case VIRTIO_GPU_CMD_RESOURCE_FLUSH:
+        virtio_gpu_resource_flush(g, cmd);
+        break;
+    case VIRTIO_GPU_CMD_TRANSFER_TO_HOST_2D:
+        virtio_gpu_transfer_to_host_2d(g, cmd);
+        break;
+    case VIRTIO_GPU_CMD_SET_SCANOUT:
+        virtio_gpu_set_scanout(g, cmd);
+        break;
+    case VIRTIO_GPU_CMD_RESOURCE_ATTACH_BACKING:
+        virtio_gpu_resource_attach_backing(g, cmd);
+        break;
+    case VIRTIO_GPU_CMD_RESOURCE_DETACH_BACKING:
+        virtio_gpu_resource_detach_backing(g, cmd);
+        break;
+    default:
+        cmd->error = VIRTIO_GPU_RESP_ERR_UNSPEC;
+        break;
+    }
+    if (!cmd->finished) {
+        virtio_gpu_ctrl_response_nodata(g, cmd, cmd->error ? cmd->error :
+                                        VIRTIO_GPU_RESP_OK_NODATA);
+    }
+}
+
+static void virtio_gpu_handle_ctrl_cb(VirtIODevice *vdev, VirtQueue *vq)
+{
+    VirtIOGPU *g = VIRTIO_GPU(vdev);
+    qemu_bh_schedule(g->ctrl_bh);
+}
+
+static void virtio_gpu_handle_cursor_cb(VirtIODevice *vdev, VirtQueue *vq)
+{
+    VirtIOGPU *g = VIRTIO_GPU(vdev);
+    qemu_bh_schedule(g->cursor_bh);
+}
+
+static void virtio_gpu_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq)
+{
+    VirtIOGPU *g = VIRTIO_GPU(vdev);
+    struct virtio_gpu_ctrl_command *cmd;
+
+    if (!virtio_queue_ready(vq)) {
+        return;
+    }
+
+    cmd = g_new(struct virtio_gpu_ctrl_command, 1);
+    while (virtqueue_pop(vq, &cmd->elem)) {
+        cmd->vq = vq;
+        cmd->error = 0;
+        cmd->finished = false;
+        g->stats.requests++;
+
+        virtio_gpu_simple_process_cmd(g, cmd);
+        if (!cmd->finished) {
+            QTAILQ_INSERT_TAIL(&g->fenceq, cmd, next);
+            g->stats.inflight++;
+            if (g->stats.max_inflight < g->stats.inflight) {
+                g->stats.max_inflight = g->stats.inflight;
+            }
+            fprintf(stderr, "inflight: %3d (+)\r", g->stats.inflight);
+            cmd = g_new(struct virtio_gpu_ctrl_command, 1);
+        }
+    }
+    g_free(cmd);
+}
+
+static void virtio_gpu_ctrl_bh(void *opaque)
+{
+    VirtIOGPU *g = opaque;
+    virtio_gpu_handle_ctrl(&g->parent_obj, g->ctrl_vq);
+}
+
+static void virtio_gpu_handle_cursor(VirtIODevice *vdev, VirtQueue *vq)
+{
+    VirtIOGPU *g = VIRTIO_GPU(vdev);
+    VirtQueueElement elem;
+    size_t s;
+    struct virtio_gpu_update_cursor cursor_info;
+
+    if (!virtio_queue_ready(vq)) {
+        return;
+    }
+    while (virtqueue_pop(vq, &elem)) {
+        s = iov_to_buf(elem.out_sg, elem.out_num, 0,
+                       &cursor_info, sizeof(cursor_info));
+        if (s != sizeof(cursor_info)) {
+            qemu_log_mask(LOG_GUEST_ERROR,
+                          "%s: cursor size incorrect %zu vs %zu\n",
+                          __func__, s, sizeof(cursor_info));
+        } else {
+            update_cursor(g, &cursor_info);
+        }
+        virtqueue_push(vq, &elem, 0);
+        virtio_notify(vdev, vq);
+    }
+}
+
+static void virtio_gpu_cursor_bh(void *opaque)
+{
+    VirtIOGPU *g = opaque;
+    virtio_gpu_handle_cursor(&g->parent_obj, g->cursor_vq);
+}
+
+static void virtio_gpu_invalidate_display(void *opaque)
+{
+}
+
+static void virtio_gpu_update_display(void *opaque)
+{
+}
+
+static void virtio_gpu_text_update(void *opaque, console_ch_t *chardata)
+{
+}
+
+static int virtio_gpu_ui_info(void *opaque, uint32_t idx, QemuUIInfo *info)
+{
+    VirtIOGPU *g = opaque;
+
+    if (idx > g->conf.max_outputs) {
+        return -1;
+    }
+
+    g->req_state[idx].x = info->xoff;
+    g->req_state[idx].y = info->yoff;
+    g->req_state[idx].width = info->width;
+    g->req_state[idx].height = info->height;
+
+    if (info->width && info->height) {
+        g->enabled_output_bitmask |= (1 << idx);
+    } else {
+        g->enabled_output_bitmask &= ~(1 << idx);
+    }
+
+    /* send event to guest */
+    virtio_gpu_notify_event(g, VIRTIO_GPU_EVENT_DISPLAY);
+    return 0;
+}
+
+const GraphicHwOps virtio_gpu_ops = {
+    .invalidate = virtio_gpu_invalidate_display,
+    .gfx_update = virtio_gpu_update_display,
+    .text_update = virtio_gpu_text_update,
+    .ui_info = virtio_gpu_ui_info,
+};
+
+static void virtio_gpu_device_realize(DeviceState *qdev, Error **errp)
+{
+    VirtIODevice *vdev = VIRTIO_DEVICE(qdev);
+    VirtIOGPU *g = VIRTIO_GPU(qdev);
+
+    g->config_size = sizeof(struct virtio_gpu_config);
+    g->virtio_config.num_scanouts = g->conf.max_outputs;
+    virtio_init(VIRTIO_DEVICE(g), "virtio-gpu", VIRTIO_ID_GPU,
+                g->config_size);
+
+    g->req_state[0].width = 1024;
+    g->req_state[0].height = 768;
+
+    g->ctrl_vq   = virtio_add_queue(vdev, 256, virtio_gpu_handle_ctrl_cb);
+    g->cursor_vq = virtio_add_queue(vdev, 256, virtio_gpu_handle_cursor_cb);
+
+    g->ctrl_bh = qemu_bh_new(virtio_gpu_ctrl_bh, g);
+    g->cursor_bh = qemu_bh_new(virtio_gpu_cursor_bh, g);
+    QTAILQ_INIT(&g->reslist);
+    QTAILQ_INIT(&g->fenceq);
+
+    g->enabled_output_bitmask = 1;
+    g->qdev = qdev;
+}
+
+static void virtio_gpu_instance_init(Object *obj)
+{
+}
+
+static void virtio_gpu_reset(VirtIODevice *vdev)
+{
+    VirtIOGPU *g = VIRTIO_GPU(vdev);
+    struct virtio_gpu_simple_resource *res, *tmp;
+    int i;
+
+    g->enable = 0;
+
+    QTAILQ_FOREACH_SAFE(res, &g->reslist, next, tmp) {
+        virtio_gpu_resource_destroy(g, res);
+    }
+    for (i = 0; i < g->conf.max_outputs; i++) {
+        g->req_state[i].x = 0;
+        g->req_state[i].y = 0;
+        if (i == 0) {
+            g->req_state[0].width = 1024;
+            g->req_state[0].height = 768;
+        } else {
+            g->req_state[i].width = 0;
+            g->req_state[i].height = 0;
+        }
+        g->scanout[i].resource_id = 0;
+        g->scanout[i].width = 0;
+        g->scanout[i].height = 0;
+        g->scanout[i].x = 0;
+        g->scanout[i].y = 0;
+        g->scanout[i].ds = NULL;
+    }
+    g->enabled_output_bitmask = 1;
+}
+
+static Property virtio_gpu_properties[] = {
+    DEFINE_VIRTIO_GPU_PROPERTIES(VirtIOGPU, conf),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void virtio_gpu_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
+
+    vdc->realize = virtio_gpu_device_realize;
+    vdc->get_config = virtio_gpu_get_config;
+    vdc->set_config = virtio_gpu_set_config;
+    vdc->get_features = virtio_gpu_get_features;
+    vdc->set_features = virtio_gpu_set_features;
+
+    vdc->reset = virtio_gpu_reset;
+
+    dc->props = virtio_gpu_properties;
+}
+
+static const TypeInfo virtio_gpu_info = {
+    .name = TYPE_VIRTIO_GPU,
+    .parent = TYPE_VIRTIO_DEVICE,
+    .instance_size = sizeof(VirtIOGPU),
+    .instance_init = virtio_gpu_instance_init,
+    .class_init = virtio_gpu_class_init,
+};
+
+static void virtio_register_types(void)
+{
+    type_register_static(&virtio_gpu_info);
+}
+
+type_init(virtio_register_types)
+
+QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_ctrl_hdr)                != 24);
+QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_update_cursor)           != 56);
+QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_resource_unref)          != 32);
+QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_resource_create_2d)      != 40);
+QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_set_scanout)             != 48);
+QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_resource_flush)          != 48);
+QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_transfer_to_host_2d)     != 48);
+QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_mem_entry)               != 16);
+QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_resource_attach_backing) != 32);
+QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_resource_detach_backing) != 32);
+QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_resp_display_info)       != 408);
diff --git a/include/hw/virtio/virtio-gpu.h b/include/hw/virtio/virtio-gpu.h
new file mode 100644
index 0000000..e24df45
--- /dev/null
+++ b/include/hw/virtio/virtio-gpu.h
@@ -0,0 +1,147 @@
+/*
+ * Virtio GPU Device
+ *
+ * Copyright Red Hat, Inc. 2013-2014
+ *
+ * Authors:
+ *     Dave Airlie <airlied@redhat.com>
+ *     Gerd Hoffmann <kraxel@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.
+ * See the COPYING file in the top-level directory.
+ */
+
+#ifndef _QEMU_VIRTIO_VGA_H
+#define _QEMU_VIRTIO_VGA_H
+
+#include "qemu/queue.h"
+#include "ui/qemu-pixman.h"
+#include "ui/console.h"
+#include "hw/virtio/virtio.h"
+#include "hw/pci/pci.h"
+
+#include "hw/virtio/virtgpu_hw.h"
+#define TYPE_VIRTIO_GPU "virtio-gpu-device"
+#define VIRTIO_GPU(obj)                                        \
+        OBJECT_CHECK(VirtIOGPU, (obj), TYPE_VIRTIO_GPU)
+
+#define VIRTIO_ID_GPU 16
+
+#define VIRTIO_GPU_MAX_RES 16
+
+#define VIRTIO_GPU_MAX_SCANOUT 4
+
+struct virtio_gpu_simple_resource {
+    uint32_t resource_id;
+    uint32_t width;
+    uint32_t height;
+    uint32_t format;
+    struct iovec *iov;
+    unsigned int iov_cnt;
+    uint32_t scanout_bitmask;
+    pixman_image_t *image;
+    QTAILQ_ENTRY(virtio_gpu_simple_resource) next;
+};
+
+struct virtio_gpu_scanout {
+    QemuConsole *con;
+    DisplaySurface *ds;
+    uint32_t width, height;
+    int x, y;
+    int invalidate;
+    uint32_t resource_id;
+    QEMUCursor *current_cursor;
+};
+
+struct virtio_gpu_requested_state {
+    uint32_t width, height;
+    int x, y;
+};
+
+struct virtio_gpu_conf {
+    uint32_t max_outputs;
+};
+
+struct virtio_gpu_ctrl_command {
+    VirtQueueElement elem;
+    VirtQueue *vq;
+    struct virtio_gpu_ctrl_hdr cmd_hdr;
+    uint32_t error;
+    bool finished;
+    QTAILQ_ENTRY(virtio_gpu_ctrl_command) next;
+};
+
+typedef struct VirtIOGPU {
+    VirtIODevice parent_obj;
+
+    QEMUBH *ctrl_bh;
+    QEMUBH *cursor_bh;
+    VirtQueue *ctrl_vq;
+    VirtQueue *cursor_vq;
+
+    int enable;
+
+    int config_size;
+    DeviceState *qdev;
+
+    QTAILQ_HEAD(, virtio_gpu_simple_resource) reslist;
+    QTAILQ_HEAD(, virtio_gpu_ctrl_command) fenceq;
+
+    struct virtio_gpu_scanout scanout[VIRTIO_GPU_MAX_SCANOUT];
+    struct virtio_gpu_requested_state req_state[VIRTIO_GPU_MAX_SCANOUT];
+
+    struct virtio_gpu_conf conf;
+    int enabled_output_bitmask;
+    struct virtio_gpu_config virtio_config;
+
+    QEMUTimer *fence_poll;
+    QEMUTimer *print_stats;
+
+    struct {
+        uint32_t inflight;
+        uint32_t max_inflight;
+        uint32_t requests;
+        uint32_t req_3d;
+        uint32_t bytes_3d;
+    } stats;
+} VirtIOGPU;
+
+extern const GraphicHwOps virtio_gpu_ops;
+
+/* to share between PCI and VGA */
+#define DEFINE_VIRTIO_GPU_PCI_PROPERTIES(_state)               \
+    DEFINE_PROP_BIT("ioeventfd", _state, flags,                \
+                    VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, false), \
+    DEFINE_PROP_UINT32("vectors", _state, nvectors, 4)
+
+#define DEFINE_VIRTIO_GPU_PROPERTIES(_state, _conf_field)               \
+    DEFINE_PROP_UINT32("max_outputs", _state, _conf_field.max_outputs, 2)
+
+#define VIRTIO_GPU_FILL_CMD(out) do {                                   \
+        size_t s;                                                       \
+        s = iov_to_buf(cmd->elem.out_sg, cmd->elem.out_num, 0,          \
+                       &out, sizeof(out));                              \
+        if (s != sizeof(out)) {                                         \
+            qemu_log_mask(LOG_GUEST_ERROR,                              \
+                          "%s: command size incorrect %zu vs %zu\n",    \
+                          __func__, s, sizeof(out));                    \
+            return;                                                     \
+        }                                                               \
+    } while (0)
+
+/* virtio-gpu.c */
+void virtio_gpu_ctrl_response(VirtIOGPU *g,
+                              struct virtio_gpu_ctrl_command *cmd,
+                              struct virtio_gpu_ctrl_hdr *resp,
+                              size_t resp_len);
+void virtio_gpu_ctrl_response_nodata(VirtIOGPU *g,
+                                     struct virtio_gpu_ctrl_command *cmd,
+                                     enum virtio_gpu_ctrl_type type);
+void virtio_gpu_get_display_info(VirtIOGPU *g,
+                                 struct virtio_gpu_ctrl_command *cmd);
+int virtio_gpu_create_mapping_iov(struct virtio_gpu_resource_attach_backing *ab,
+                                  struct virtio_gpu_ctrl_command *cmd,
+                                  struct iovec **iov);
+void virtio_gpu_cleanup_mapping_iov(struct iovec *iov, uint32_t count);
+
+#endif
diff --git a/trace-events b/trace-events
index fb58963..a2c25b8 100644
--- a/trace-events
+++ b/trace-events
@@ -1083,6 +1083,20 @@ vmware_scratch_read(uint32_t index, uint32_t value) "index %d, value 0x%x"
 vmware_scratch_write(uint32_t index, uint32_t value) "index %d, value 0x%x"
 vmware_setmode(uint32_t w, uint32_t h, uint32_t bpp) "%dx%d @ %d bpp"
 
+# hw/display/virtio-gpu.c
+virtio_gpu_cmd_get_display_info(void) ""
+virtio_gpu_cmd_get_caps(void) ""
+virtio_gpu_cmd_set_scanout(uint32_t id, uint32_t res, uint32_t w, uint32_t h, uint32_t x, uint32_t y) "id %d, res 0x%x, w %d, h %d, x %d, y %d"
+virtio_gpu_cmd_res_create_2d(uint32_t res, uint32_t fmt, uint32_t w, uint32_t h) "res 0x%x, fmt 0x%x, w %d, h %d"
+virtio_gpu_cmd_res_create_3d(uint32_t res, uint32_t fmt, uint32_t w, uint32_t h, uint32_t d) "res 0x%x, fmt 0x%x, w %d, h %d, d %d"
+virtio_gpu_cmd_res_unref(uint32_t res) "res 0x%x"
+virtio_gpu_cmd_res_back_attach(uint32_t res) "res 0x%x"
+virtio_gpu_cmd_res_back_detach(uint32_t res) "res 0x%x"
+virtio_gpu_cmd_res_xfer_toh_2d(uint32_t res) "res 0x%x"
+virtio_gpu_cmd_res_flush(uint32_t res, uint32_t w, uint32_t h, uint32_t x, uint32_t y) "res 0x%x, w %d, h %d, x %d, y %d"
+virtio_gpu_fence_ctrl(uint64_t fence, uint32_t type) "fence 0x%" PRIx64 ", type 0x%x"
+virtio_gpu_fence_resp(uint64_t fence) "fence 0x%" PRIx64
+
 # savevm.c
 savevm_section_start(const char *id, unsigned int section_id) "%s, section_id %u"
 savevm_section_end(const char *id, unsigned int section_id) "%s, section_id %u"
-- 
1.8.3.1

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

* [Qemu-devel] [PATCH 3/8] virtio-gpu-pci: add virtio pci support
  2014-09-23 13:27 [Qemu-devel] [PATCH 0/8] add virtio-gpu Gerd Hoffmann
  2014-09-23 13:28 ` [Qemu-devel] [PATCH 1/8] virtio-gpu/2d: add hardware spec include file Gerd Hoffmann
  2014-09-23 13:28 ` [Qemu-devel] [PATCH 2/8] virtio-gpu/2d: add virtio gpu core code Gerd Hoffmann
@ 2014-09-23 13:28 ` Gerd Hoffmann
  2014-09-23 13:28 ` [Qemu-devel] [PATCH 4/8] virtio-vga: add virtio gpu device with vga compatibility Gerd Hoffmann
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 19+ messages in thread
From: Gerd Hoffmann @ 2014-09-23 13:28 UTC (permalink / raw)
  To: qemu-devel
  Cc: Dave Airlie, Gerd Hoffmann, Anthony Liguori, Michael S. Tsirkin

This patch adds virtio-gpu-pci, which is the pci proxy for the virtio
gpu device.  With this patch in place virtio-gpu is functional.  You
need a linux guest with a virtio-gpu driver though, and output will
appear pretty late in boot, once the kernel initialized drm and fbcon.

Written by Dave Airlie and Gerd Hoffmann.

Signed-off-by: Dave Airlie <airlied@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 default-configs/x86_64-softmmu.mak |  1 +
 hw/display/Makefile.objs           |  1 +
 hw/display/virtio-gpu-pci.c        | 80 ++++++++++++++++++++++++++++++++++++++
 hw/virtio/virtio-pci.h             | 15 +++++++
 include/hw/pci/pci.h               |  1 +
 5 files changed, 98 insertions(+)
 create mode 100644 hw/display/virtio-gpu-pci.c

diff --git a/default-configs/x86_64-softmmu.mak b/default-configs/x86_64-softmmu.mak
index 75a123a..1027916 100644
--- a/default-configs/x86_64-softmmu.mak
+++ b/default-configs/x86_64-softmmu.mak
@@ -10,6 +10,7 @@ CONFIG_VGA_ISA=y
 CONFIG_VGA_CIRRUS=y
 CONFIG_VMWARE_VGA=y
 CONFIG_VIRTIO_GPU=y
+CONFIG_VIRTIO_GPU_PCI=y
 CONFIG_VMMOUSE=y
 CONFIG_SERIAL=y
 CONFIG_PARALLEL=y
diff --git a/hw/display/Makefile.objs b/hw/display/Makefile.objs
index 29f179f..df51ec2 100644
--- a/hw/display/Makefile.objs
+++ b/hw/display/Makefile.objs
@@ -35,3 +35,4 @@ obj-$(CONFIG_VGA) += vga.o
 common-obj-$(CONFIG_QXL) += qxl.o qxl-logger.o qxl-render.o
 
 obj-$(CONFIG_VIRTIO_GPU) += virtio-gpu.o
+obj-$(CONFIG_VIRTIO_GPU_PCI) += virtio-gpu-pci.o
diff --git a/hw/display/virtio-gpu-pci.c b/hw/display/virtio-gpu-pci.c
new file mode 100644
index 0000000..0b7304e
--- /dev/null
+++ b/hw/display/virtio-gpu-pci.c
@@ -0,0 +1,80 @@
+/*
+ * Virtio video device
+ *
+ * Copyright Red Hat
+ *
+ * Authors:
+ *  Dave Airlie
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ *
+ */
+#include "hw/pci/pci.h"
+#include "hw/virtio/virtio.h"
+#include "hw/virtio/virtio-bus.h"
+#include "hw/virtio/virtio-pci.h"
+#include "hw/virtio/virtio-gpu.h"
+
+static Property virtio_gpu_pci_properties[] = {
+    DEFINE_VIRTIO_GPU_PCI_PROPERTIES(VirtIOPCIProxy),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static int virtio_gpu_pci_init(VirtIOPCIProxy *vpci_dev)
+{
+    VirtIOGPUPCI *vgpu = VIRTIO_GPU_PCI(vpci_dev);
+    DeviceState *vdev = DEVICE(&vgpu->vdev);
+    VirtIOGPU *g = &vgpu->vdev;
+    int i;
+
+    qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus));
+    if (qdev_init(vdev) < 0) {
+        return -1;
+    }
+
+    for (i = 0; i < g->conf.max_outputs; i++) {
+        g->scanout[i].con =
+            graphic_console_init(DEVICE(g), i, &virtio_gpu_ops, g);
+        if (i > 0) {
+            dpy_gfx_replace_surface(g->scanout[i].con, NULL);
+        }
+    }
+    return 0;
+}
+
+static void virtio_gpu_pci_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    VirtioPCIClass *k = VIRTIO_PCI_CLASS(klass);
+    PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass);
+
+    set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories);
+    dc->props = virtio_gpu_pci_properties;
+    k->init = virtio_gpu_pci_init;
+    pcidev_k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
+    pcidev_k->device_id = PCI_DEVICE_ID_VIRTIO_GPU;
+    pcidev_k->revision = VIRTIO_PCI_ABI_VERSION;
+    pcidev_k->class_id = PCI_CLASS_DISPLAY_OTHER;
+}
+
+static void virtio_gpu_initfn(Object *obj)
+{
+    VirtIOGPUPCI *dev = VIRTIO_GPU_PCI(obj);
+    object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_GPU);
+    object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
+}
+
+static const TypeInfo virtio_gpu_pci_info = {
+    .name = TYPE_VIRTIO_GPU_PCI,
+    .parent = TYPE_VIRTIO_PCI,
+    .instance_size = sizeof(VirtIOGPUPCI),
+    .instance_init = virtio_gpu_initfn,
+    .class_init = virtio_gpu_pci_class_init,
+};
+
+static void virtio_gpu_pci_register_types(void)
+{
+    type_register_static(&virtio_gpu_pci_info);
+}
+type_init(virtio_gpu_pci_register_types)
diff --git a/hw/virtio/virtio-pci.h b/hw/virtio/virtio-pci.h
index 1cea157..3e7fcd5 100644
--- a/hw/virtio/virtio-pci.h
+++ b/hw/virtio/virtio-pci.h
@@ -24,6 +24,7 @@
 #include "hw/virtio/virtio-balloon.h"
 #include "hw/virtio/virtio-bus.h"
 #include "hw/virtio/virtio-9p.h"
+#include "hw/virtio/virtio-gpu.h"
 #ifdef CONFIG_VIRTFS
 #include "hw/9pfs/virtio-9p.h"
 #endif
@@ -39,6 +40,7 @@ typedef struct VirtIOSerialPCI VirtIOSerialPCI;
 typedef struct VirtIONetPCI VirtIONetPCI;
 typedef struct VHostSCSIPCI VHostSCSIPCI;
 typedef struct VirtIORngPCI VirtIORngPCI;
+typedef struct VirtIOGPUPCI VirtIOGPUPCI;
 
 /* virtio-pci-bus */
 
@@ -198,6 +200,19 @@ struct VirtIORngPCI {
     VirtIORNG vdev;
 };
 
+/*
+ * virtio-gpu-pci: This extends VirtioPCIProxy.
+ */
+#define TYPE_VIRTIO_GPU_PCI "virtio-gpu-pci"
+#define VIRTIO_GPU_PCI(obj) \
+        OBJECT_CHECK(VirtIOGPUPCI, (obj), TYPE_VIRTIO_GPU_PCI)
+
+struct VirtIOGPUPCI {
+    VirtIOPCIProxy parent_obj;
+    VirtIOGPU vdev;
+};
+
+
 /* Virtio ABI version, if we increment this, we break the guest driver. */
 #define VIRTIO_PCI_ABI_VERSION          0
 
diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h
index c352c7b..a55d8b3 100644
--- a/include/hw/pci/pci.h
+++ b/include/hw/pci/pci.h
@@ -81,6 +81,7 @@
 #define PCI_DEVICE_ID_VIRTIO_SCSI        0x1004
 #define PCI_DEVICE_ID_VIRTIO_RNG         0x1005
 #define PCI_DEVICE_ID_VIRTIO_9P          0x1009
+#define PCI_DEVICE_ID_VIRTIO_GPU         0x1010
 
 #define PCI_VENDOR_ID_REDHAT             0x1b36
 #define PCI_DEVICE_ID_REDHAT_BRIDGE      0x0001
-- 
1.8.3.1

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

* [Qemu-devel] [PATCH 4/8] virtio-vga: add virtio gpu device with vga compatibility
  2014-09-23 13:27 [Qemu-devel] [PATCH 0/8] add virtio-gpu Gerd Hoffmann
                   ` (2 preceding siblings ...)
  2014-09-23 13:28 ` [Qemu-devel] [PATCH 3/8] virtio-gpu-pci: add virtio pci support Gerd Hoffmann
@ 2014-09-23 13:28 ` Gerd Hoffmann
  2014-09-23 13:28 ` [Qemu-devel] [PATCH 5/8] virtio-vga: add '-vga virtio' support Gerd Hoffmann
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 19+ messages in thread
From: Gerd Hoffmann @ 2014-09-23 13:28 UTC (permalink / raw)
  To: qemu-devel
  Cc: Dave Airlie, Gerd Hoffmann, Anthony Liguori, Michael S. Tsirkin

This patch adds a virtio-vga device.  It is simliar to virtio-gpu-pci,
but it also adds in vga compatibility, so guests without native
virtio-gpu support can drive the device in vga mode.

Written by Dave Airlie and Gerd Hoffmann.

Signed-off-by: Dave Airlie <airlied@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 default-configs/x86_64-softmmu.mak |   1 +
 hw/display/Makefile.objs           |   1 +
 hw/display/virtio-vga.c            | 169 +++++++++++++++++++++++++++++++++++++
 3 files changed, 171 insertions(+)
 create mode 100644 hw/display/virtio-vga.c

diff --git a/default-configs/x86_64-softmmu.mak b/default-configs/x86_64-softmmu.mak
index 1027916..ca04470 100644
--- a/default-configs/x86_64-softmmu.mak
+++ b/default-configs/x86_64-softmmu.mak
@@ -11,6 +11,7 @@ CONFIG_VGA_CIRRUS=y
 CONFIG_VMWARE_VGA=y
 CONFIG_VIRTIO_GPU=y
 CONFIG_VIRTIO_GPU_PCI=y
+CONFIG_VIRTIO_VGA=y
 CONFIG_VMMOUSE=y
 CONFIG_SERIAL=y
 CONFIG_PARALLEL=y
diff --git a/hw/display/Makefile.objs b/hw/display/Makefile.objs
index df51ec2..31e0216 100644
--- a/hw/display/Makefile.objs
+++ b/hw/display/Makefile.objs
@@ -36,3 +36,4 @@ common-obj-$(CONFIG_QXL) += qxl.o qxl-logger.o qxl-render.o
 
 obj-$(CONFIG_VIRTIO_GPU) += virtio-gpu.o
 obj-$(CONFIG_VIRTIO_GPU_PCI) += virtio-gpu-pci.o
+obj-$(CONFIG_VIRTIO_VGA) += virtio-vga.o
diff --git a/hw/display/virtio-vga.c b/hw/display/virtio-vga.c
new file mode 100644
index 0000000..83eda0d
--- /dev/null
+++ b/hw/display/virtio-vga.c
@@ -0,0 +1,169 @@
+#include "hw/hw.h"
+#include "hw/pci/pci.h"
+#include "ui/console.h"
+#include "vga_int.h"
+#include "hw/virtio/virtio-pci.h"
+
+/*
+ * virtio-vga: This extends VirtioPCIProxy.
+ */
+#define TYPE_VIRTIO_VGA "virtio-vga"
+#define VIRTIO_VGA(obj) \
+        OBJECT_CHECK(VirtIOVGA, (obj), TYPE_VIRTIO_VGA)
+
+typedef struct VirtIOVGA {
+    VirtIOPCIProxy parent_obj;
+    VirtIOGPU      vdev;
+    VGACommonState vga;
+} VirtIOVGA;
+
+static void virtio_vga_invalidate_display(void *opaque)
+{
+    VirtIOVGA *vvga = opaque;
+
+    if (vvga->vdev.enable) {
+        virtio_gpu_ops.invalidate(&vvga->vdev);
+    } else {
+        vvga->vga.hw_ops->invalidate(&vvga->vga);
+    }
+}
+
+static void virtio_vga_update_display(void *opaque)
+{
+    VirtIOVGA *vvga = opaque;
+
+    if (vvga->vdev.enable) {
+        virtio_gpu_ops.gfx_update(&vvga->vdev);
+    } else {
+        vvga->vga.hw_ops->gfx_update(&vvga->vga);
+    }
+}
+
+static void virtio_vga_text_update(void *opaque, console_ch_t *chardata)
+{
+    VirtIOVGA *vvga = opaque;
+
+    if (vvga->vdev.enable) {
+        if (virtio_gpu_ops.text_update) {
+            virtio_gpu_ops.text_update(&vvga->vdev, chardata);
+        }
+    } else {
+        if (vvga->vga.hw_ops->text_update) {
+            vvga->vga.hw_ops->text_update(&vvga->vga, chardata);
+        }
+    }
+}
+
+static int virtio_vga_ui_info(void *opaque, uint32_t idx, QemuUIInfo *info)
+{
+    VirtIOVGA *vvga = opaque;
+
+    if (vvga->vdev.enable) {
+        if (virtio_gpu_ops.ui_info) {
+            return virtio_gpu_ops.ui_info(&vvga->vdev, idx, info);
+        }
+    } else {
+        if (vvga->vga.hw_ops->ui_info) {
+            return vvga->vga.hw_ops->ui_info(&vvga->vga, idx, info);
+        }
+    }
+    return -1;
+}
+
+static const GraphicHwOps virtio_vga_ops = {
+    .invalidate = virtio_vga_invalidate_display,
+    .gfx_update = virtio_vga_update_display,
+    .text_update = virtio_vga_text_update,
+    .ui_info = virtio_vga_ui_info,
+};
+
+/* VGA device wrapper around PCI device around virtio GPU */
+static int virtio_vga_init(VirtIOPCIProxy *vpci_dev)
+{
+    VirtIOVGA *vvga = VIRTIO_VGA(vpci_dev);
+    VirtIOGPU *g = &vvga->vdev;
+    VGACommonState *vga = &vvga->vga;
+    int i;
+
+    qdev_set_parent_bus(DEVICE(g), BUS(&vpci_dev->bus));
+    if (qdev_init(DEVICE(g)) < 0) {
+        return -1;
+    }
+
+    vga_common_init(vga, OBJECT(vpci_dev), false);
+    vga_init(vga, OBJECT(vpci_dev), pci_address_space(&vpci_dev->pci_dev),
+             pci_address_space_io(&vpci_dev->pci_dev), true);
+
+    for (i = 0; i < g->conf.max_outputs; i++) {
+        if (i == 0) {
+            g->scanout[i].con =
+                graphic_console_init(DEVICE(g), i, &virtio_vga_ops, vvga);
+            vga->con = g->scanout[i].con;
+        } else {
+            g->scanout[i].con =
+                graphic_console_init(DEVICE(g), i, &virtio_gpu_ops, g);
+            dpy_gfx_replace_surface(g->scanout[i].con, NULL);
+        }
+    }
+
+    pci_register_bar(&vpci_dev->pci_dev, 2,
+                     PCI_BASE_ADDRESS_MEM_PREFETCH, &vga->vram);
+
+    return 0;
+}
+
+static void virtio_vga_reset(DeviceState *dev)
+{
+    VirtIOVGA *vvga = VIRTIO_VGA(dev);
+    vvga->vdev.enable = 0;
+
+    vga_dirty_log_start(&vvga->vga);
+}
+
+static Property virtio_vga_properties[] = {
+    DEFINE_VIRTIO_GPU_PROPERTIES(VirtIOVGA, vdev.conf),
+    DEFINE_VIRTIO_GPU_PCI_PROPERTIES(VirtIOPCIProxy),
+    DEFINE_PROP_UINT32("vgamem_mb", VirtIOVGA, vga.vram_size_mb, 16),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void virtio_vga_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    VirtioPCIClass *k = VIRTIO_PCI_CLASS(klass);
+    PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass);
+
+    set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories);
+    dc->props = virtio_vga_properties;
+    dc->reset = virtio_vga_reset;
+    dc->hotpluggable = false;
+
+    k->init = virtio_vga_init;
+    pcidev_k->romfile = "vgabios-virtio.bin";
+    pcidev_k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
+    pcidev_k->device_id = PCI_DEVICE_ID_VIRTIO_GPU;
+    pcidev_k->revision = VIRTIO_PCI_ABI_VERSION;
+    pcidev_k->class_id = PCI_CLASS_DISPLAY_VGA;
+}
+
+static void virtio_vga_inst_initfn(Object *obj)
+{
+    VirtIOVGA *dev = VIRTIO_VGA(obj);
+    object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_GPU);
+    object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
+}
+
+static TypeInfo virtio_vga_info = {
+    .name          = TYPE_VIRTIO_VGA,
+    .parent        = TYPE_VIRTIO_PCI,
+    .instance_size = sizeof(struct VirtIOVGA),
+    .instance_init = virtio_vga_inst_initfn,
+    .class_init    = virtio_vga_class_init,
+};
+
+static void virtio_vga_register_types(void)
+{
+    type_register_static(&virtio_vga_info);
+}
+
+type_init(virtio_vga_register_types)
-- 
1.8.3.1

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

* [Qemu-devel] [PATCH 5/8] virtio-vga: add '-vga virtio' support
  2014-09-23 13:27 [Qemu-devel] [PATCH 0/8] add virtio-gpu Gerd Hoffmann
                   ` (3 preceding siblings ...)
  2014-09-23 13:28 ` [Qemu-devel] [PATCH 4/8] virtio-vga: add virtio gpu device with vga compatibility Gerd Hoffmann
@ 2014-09-23 13:28 ` Gerd Hoffmann
  2014-09-23 13:28 ` [Qemu-devel] [PATCH 6/8] virtio-vga: add vgabios configuration Gerd Hoffmann
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 19+ messages in thread
From: Gerd Hoffmann @ 2014-09-23 13:28 UTC (permalink / raw)
  To: qemu-devel
  Cc: Dave Airlie, Gerd Hoffmann, Anthony Liguori, Michael S. Tsirkin

Some convinience fluff:  Add support for '-vga virtio', also add
virtio-vga to the list of vga cards so '-device virtio-vga' will
turn off the default vga.

Written by Dave Airlie and Gerd Hoffmann.

Signed-off-by: Dave Airlie <airlied@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/pci/pci.c            |  2 ++
 include/sysemu/sysemu.h |  2 +-
 vl.c                    | 13 +++++++++++++
 3 files changed, 16 insertions(+), 1 deletion(-)

diff --git a/hw/pci/pci.c b/hw/pci/pci.c
index 6ce75aa..3328d98 100644
--- a/hw/pci/pci.c
+++ b/hw/pci/pci.c
@@ -1653,6 +1653,8 @@ PCIDevice *pci_vga_init(PCIBus *bus)
         return pci_create_simple(bus, -1, "VGA");
     case VGA_VMWARE:
         return pci_create_simple(bus, -1, "vmware-svga");
+    case VGA_VIRTIO:
+        return pci_create_simple(bus, -1, "virtio-vga");
     case VGA_NONE:
     default: /* Other non-PCI types. Checking for unsupported types is already
                 done in vl.c. */
diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h
index d8539fd..3741855 100644
--- a/include/sysemu/sysemu.h
+++ b/include/sysemu/sysemu.h
@@ -107,7 +107,7 @@ extern int autostart;
 
 typedef enum {
     VGA_NONE, VGA_STD, VGA_CIRRUS, VGA_VMWARE, VGA_XENFB, VGA_QXL,
-    VGA_TCX, VGA_CG3, VGA_DEVICE
+    VGA_TCX, VGA_CG3, VGA_DEVICE, VGA_VIRTIO,
 } VGAInterfaceType;
 
 extern int vga_interface_type;
diff --git a/vl.c b/vl.c
index dc792fe..4cbd401 100644
--- a/vl.c
+++ b/vl.c
@@ -249,6 +249,7 @@ static struct {
     { .driver = "isa-cirrus-vga",       .flag = &default_vga       },
     { .driver = "vmware-svga",          .flag = &default_vga       },
     { .driver = "qxl-vga",              .flag = &default_vga       },
+    { .driver = "virtio-vga",           .flag = &default_vga       },
 };
 
 static QemuOptsList qemu_rtc_opts = {
@@ -2108,6 +2109,11 @@ static bool cg3_vga_available(void)
     return object_class_by_name("cgthree");
 }
 
+static bool virtio_vga_available(void)
+{
+    return object_class_by_name("virtio-vga");
+}
+
 static void select_vgahw (const char *p)
 {
     const char *opts;
@@ -2134,6 +2140,13 @@ static void select_vgahw (const char *p)
             fprintf(stderr, "Error: VMWare SVGA not available\n");
             exit(0);
         }
+    } else if (strstart(p, "virtio", &opts)) {
+        if (virtio_vga_available()) {
+            vga_interface_type = VGA_VIRTIO;
+        } else {
+            fprintf(stderr, "Error: Virtio VGA not available\n");
+            exit(0);
+        }
     } else if (strstart(p, "xenfb", &opts)) {
         vga_interface_type = VGA_XENFB;
     } else if (strstart(p, "qxl", &opts)) {
-- 
1.8.3.1

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

* [Qemu-devel] [PATCH 6/8] virtio-vga: add vgabios configuration
  2014-09-23 13:27 [Qemu-devel] [PATCH 0/8] add virtio-gpu Gerd Hoffmann
                   ` (4 preceding siblings ...)
  2014-09-23 13:28 ` [Qemu-devel] [PATCH 5/8] virtio-vga: add '-vga virtio' support Gerd Hoffmann
@ 2014-09-23 13:28 ` Gerd Hoffmann
  2014-09-23 13:28 ` [Qemu-devel] [PATCH 7/8] virtio-vga: add vgabios binary Gerd Hoffmann
  2014-09-23 13:28 ` [Qemu-devel] [PATCH 8/8] virtio-gpu: add to display-vga test Gerd Hoffmann
  7 siblings, 0 replies; 19+ messages in thread
From: Gerd Hoffmann @ 2014-09-23 13:28 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

Add seavgabios configuration for virtio-vga,
hook up the new vgabios in the makefiles.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 Makefile               | 2 +-
 roms/Makefile          | 2 +-
 roms/config.vga-virtio | 6 ++++++
 3 files changed, 8 insertions(+), 2 deletions(-)
 create mode 100644 roms/config.vga-virtio

diff --git a/Makefile b/Makefile
index b33aaac..27aa63f 100644
--- a/Makefile
+++ b/Makefile
@@ -337,7 +337,7 @@ bepo    cz
 
 ifdef INSTALL_BLOBS
 BLOBS=bios.bin bios-256k.bin sgabios.bin vgabios.bin vgabios-cirrus.bin \
-vgabios-stdvga.bin vgabios-vmware.bin vgabios-qxl.bin \
+vgabios-stdvga.bin vgabios-vmware.bin vgabios-qxl.bin vgabios-virtio.bin \
 acpi-dsdt.aml q35-acpi-dsdt.aml \
 ppc_rom.bin openbios-sparc32 openbios-sparc64 openbios-ppc QEMU,tcx.bin QEMU,cgthree.bin \
 pxe-e1000.rom pxe-eepro100.rom pxe-ne2k_pci.rom \
diff --git a/roms/Makefile b/roms/Makefile
index 610b534..c76cd5b 100644
--- a/roms/Makefile
+++ b/roms/Makefile
@@ -1,5 +1,5 @@
 
-vgabios_variants := stdvga cirrus vmware qxl isavga
+vgabios_variants := stdvga cirrus vmware qxl isavga virtio
 vgabios_targets  := $(subst -isavga,,$(patsubst %,vgabios-%.bin,$(vgabios_variants)))
 pxerom_variants  := e1000 eepro100 ne2k_pci pcnet rtl8139 virtio
 pxerom_targets   := 8086100e 80861209 10500940 10222000 10ec8139 1af41000
diff --git a/roms/config.vga-virtio b/roms/config.vga-virtio
new file mode 100644
index 0000000..9a78983
--- /dev/null
+++ b/roms/config.vga-virtio
@@ -0,0 +1,6 @@
+CONFIG_BUILD_VGABIOS=y
+CONFIG_VGA_BOCHS=y
+CONFIG_VGA_PCI=y
+CONFIG_OVERRIDE_PCI_ID=y
+CONFIG_VGA_VID=0x1af4
+CONFIG_VGA_DID=0x1010
-- 
1.8.3.1

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

* [Qemu-devel] [PATCH 7/8] virtio-vga: add vgabios binary
  2014-09-23 13:27 [Qemu-devel] [PATCH 0/8] add virtio-gpu Gerd Hoffmann
                   ` (5 preceding siblings ...)
  2014-09-23 13:28 ` [Qemu-devel] [PATCH 6/8] virtio-vga: add vgabios configuration Gerd Hoffmann
@ 2014-09-23 13:28 ` Gerd Hoffmann
  2014-09-23 13:28 ` [Qemu-devel] [PATCH 8/8] virtio-gpu: add to display-vga test Gerd Hoffmann
  7 siblings, 0 replies; 19+ messages in thread
From: Gerd Hoffmann @ 2014-09-23 13:28 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

Add prebuilt vgabios-virtio.bin binary.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 pc-bios/vgabios-virtio.bin | Bin 0 -> 37376 bytes
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 pc-bios/vgabios-virtio.bin

diff --git a/pc-bios/vgabios-virtio.bin b/pc-bios/vgabios-virtio.bin
new file mode 100644
index 0000000000000000000000000000000000000000..7febcb660b23ba1fb6d0d52d9f08458b86cd8c15
GIT binary patch
literal 37376
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

literal 0
HcmV?d00001

-- 
1.8.3.1

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

* [Qemu-devel] [PATCH 8/8] virtio-gpu: add to display-vga test
  2014-09-23 13:27 [Qemu-devel] [PATCH 0/8] add virtio-gpu Gerd Hoffmann
                   ` (6 preceding siblings ...)
  2014-09-23 13:28 ` [Qemu-devel] [PATCH 7/8] virtio-vga: add vgabios binary Gerd Hoffmann
@ 2014-09-23 13:28 ` Gerd Hoffmann
  7 siblings, 0 replies; 19+ messages in thread
From: Gerd Hoffmann @ 2014-09-23 13:28 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 tests/Makefile           |  3 +++
 tests/display-vga-test.c | 18 ++++++++++++++++++
 2 files changed, 21 insertions(+)

diff --git a/tests/Makefile b/tests/Makefile
index a5e3d0c..27edb2c 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -125,6 +125,9 @@ check-qtest-pci-y += tests/display-vga-test$(EXESUF)
 gcov-files-pci-y += hw/display/vga.c
 gcov-files-pci-y += hw/display/cirrus_vga.c
 gcov-files-pci-y += hw/display/vga-pci.c
+gcov-files-pci-y += hw/display/virtio-gpu.c
+gcov-files-pci-y += hw/display/virtio-gpu-pci.c
+gcov-files-pci-y += hw/display/virtio-vga.c
 check-qtest-pci-y += tests/intel-hda-test$(EXESUF)
 gcov-files-pci-y += hw/audio/intel-hda.c hw/audio/hda-codec.c
 
diff --git a/tests/display-vga-test.c b/tests/display-vga-test.c
index 17f5910..cd0b873 100644
--- a/tests/display-vga-test.c
+++ b/tests/display-vga-test.c
@@ -36,6 +36,20 @@ static void pci_multihead(void)
     qtest_end();
 }
 
+#ifdef CONFIG_VIRTIO_GPU
+static void pci_virtio_gpu(void)
+{
+    qtest_start("-vga none -device virtio-gpu-pci");
+    qtest_end();
+}
+
+static void pci_virtio_vga(void)
+{
+    qtest_start("-vga none -device virtio-vga");
+    qtest_end();
+}
+#endif
+
 int main(int argc, char **argv)
 {
     int ret;
@@ -46,6 +60,10 @@ int main(int argc, char **argv)
     qtest_add_func("/display/pci/stdvga", pci_stdvga);
     qtest_add_func("/display/pci/secondary", pci_secondary);
     qtest_add_func("/display/pci/multihead", pci_multihead);
+#ifdef CONFIG_VIRTIO_GPU
+    qtest_add_func("/display/pci/virtio-gpu", pci_virtio_gpu);
+    qtest_add_func("/display/pci/virtio-vga", pci_virtio_vga);
+#endif
     ret = g_test_run();
 
     return ret;
-- 
1.8.3.1

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

* Re: [Qemu-devel] [PATCH 1/8] virtio-gpu/2d: add hardware spec include file
  2014-09-23 13:28 ` [Qemu-devel] [PATCH 1/8] virtio-gpu/2d: add hardware spec include file Gerd Hoffmann
@ 2014-09-25 15:02   ` Gerd Hoffmann
  2014-09-30  0:27     ` Dave Airlie
  2014-10-15 10:05   ` Gerd Hoffmann
  1 sibling, 1 reply; 19+ messages in thread
From: Gerd Hoffmann @ 2014-09-25 15:02 UTC (permalink / raw)
  To: qemu-devel; +Cc: Dave Airlie

  Hi Dave,

Triggered by the framebuffer endian issues we have with stdvga I've
started to check where we stand with virtio-gpu and whenever we have to
fix something in the virtio protocol before setting in stone with the
upstream merge.

Fixed the protocol.  Basically s/uint32_t/__le32/g.  No changes on
x86_64 obviously.

Fixed the kernel driver to byteswap values when needed.  See
https://www.kraxel.org/cgit/linux/log/?h=virtio-gpu-rebase

Result is bigendian guest on little endian host boots fine (without
virgl).  Colors are wrong though.  Other way around still needs a bunch
of fixes in qemu so virtio-gpu works correctly on bigendian hosts.  To
be done.

So, on the color issue:  How are these defined exactly?

> +    VIRTIO_GPU_FORMAT_B8G8R8A8_UNORM  = 1,
> +    VIRTIO_GPU_FORMAT_B8G8R8X8_UNORM  = 2,
> +    VIRTIO_GPU_FORMAT_A8R8G8B8_UNORM  = 3,
> +    VIRTIO_GPU_FORMAT_X8R8G8B8_UNORM  = 4,

Looking at the code it seems the name defines the byte ordering in
memory, i.e. "B8G8R8A8" means blue first, then red, then green, then
alpha.  Or DRM_FORMAT_ARGB8888 on little endian / DRM_FORMAT_BGRX8888 on
big endian.  Correct?  Easy fix in the guest driver then ...

> +    VIRTIO_GPU_FORMAT_B5G5R5A1_UNORM  = 5,
> +    VIRTIO_GPU_FORMAT_B5G6R5_UNORM    = 7,

Do we really wanna go down this route?  I'm inclined to just zap 16bpp
support.

> +    VIRTIO_GPU_FORMAT_R8_UNORM        = 64,

What is this btw?  Looks like gray or alpha, but why "R8" not "G8" or
"A8" then?  Why the gap in the enumeration?

With the formats being clarified fixed we are settled for 2d mode I
think.

What about 3d mode?  We are passing blobs between virglrenderer and
guest driver:  capabilities and gallium 3d command stream.  What happens
to them in case host and guest endianness don't match?  I think at least
the capabilities have 32bit values which need to be swapped.  Dunno
about the gallium commands ...

cheers,
  Gerd

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

* Re: [Qemu-devel] [PATCH 1/8] virtio-gpu/2d: add hardware spec include file
  2014-09-25 15:02   ` Gerd Hoffmann
@ 2014-09-30  0:27     ` Dave Airlie
  2014-09-30  7:54       ` Gerd Hoffmann
  2014-09-30  7:55       ` Gerd Hoffmann
  0 siblings, 2 replies; 19+ messages in thread
From: Dave Airlie @ 2014-09-30  0:27 UTC (permalink / raw)
  To: Gerd Hoffmann; +Cc: Dave Airlie, qemu-devel

> Triggered by the framebuffer endian issues we have with stdvga I've
> started to check where we stand with virtio-gpu and whenever we have to
> fix something in the virtio protocol before setting in stone with the
> upstream merge.

Let me start by saying its not that I don't care about endianness, but
its a mess I had hoped to avoid until someone else care more about it.

We haven't even managed to get endianness fixed for real 3D gpu hardware yet,

We sort of have decent endianness support for the llvmpipe sw driver now, after
I spent a week trawling patches and fixing up the results.

So before we try fixing things, we probably need to design something
that defines
where all the swapping happens, and what formats the virgl "hw" device supports.
The main problem is getting an efficient solution that avoids double swapping
of the major items like texture and vertex data if we can in some scenarios.

Currently the virgl "hw" supports little endian defined formats, as
per the gallium
interface, i.e. B8G8R8A8 means blue/red/green/alpha,

http://gallium.readthedocs.org/en/latest/format.html
is the documentation.

>
>> +    VIRTIO_GPU_FORMAT_B5G5R5A1_UNORM  = 5,
>> +    VIRTIO_GPU_FORMAT_B5G6R5_UNORM    = 7,
>
> Do we really wanna go down this route?  I'm inclined to just zap 16bpp
> support.

We have to support 16bpp as an OpenGL format no matter what, and this
is why endianness sucks, we have lots of strange ass formats we need
to send over the wire, that have no nicely defined endianness, like Z24S8.

>
>> +    VIRTIO_GPU_FORMAT_R8_UNORM        = 64,
>
> What is this btw?  Looks like gray or alpha, but why "R8" not "G8" or
> "A8" then?  Why the gap in the enumeration?

Red 8, the enumeration is taken from the gallium formats list, rather than
reinventing our own. Most modern GPU hardware doesn't really have
A8 texture support, as it was deprecated in newer OpenGL.

>
> What about 3d mode?  We are passing blobs between virglrenderer and
> guest driver:  capabilities and gallium 3d command stream.  What happens
> to them in case host and guest endianness don't match?  I think at least
> the capabilities have 32bit values which need to be swapped.  Dunno
> about the gallium commands ...

For 3D we probably need to define the gallium command streams to be
little endian, however the big problem is the data that is stored
inside objects.
Texture and vertex, constants, indices etc. How do we decide to swap these,
when do we swap things, on the DMA transfers to the host, do we just
swap the formats on the host side etc.

I probably need to spend some time working this out with BenH, but
I'm not really sure how we can avoid backing ourselves into a large inefficent
hole at some point.

Dave.

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

* Re: [Qemu-devel] [PATCH 1/8] virtio-gpu/2d: add hardware spec include file
  2014-09-30  0:27     ` Dave Airlie
@ 2014-09-30  7:54       ` Gerd Hoffmann
  2014-09-30  7:55       ` Gerd Hoffmann
  1 sibling, 0 replies; 19+ messages in thread
From: Gerd Hoffmann @ 2014-09-30  7:54 UTC (permalink / raw)
  To: Dave Airlie; +Cc: Dave Airlie, qemu-devel


On Di, 2014-09-30 at 10:27 +1000, Dave Airlie wrote:
> > Triggered by the framebuffer endian issues we have with stdvga I've
> > started to check where we stand with virtio-gpu and whenever we have to
> > fix something in the virtio protocol before setting in stone with the
> > upstream merge.
> 
> Let me start by saying its not that I don't care about endianness, but
> its a mess I had hoped to avoid until someone else care more about it.

Understood.  It's a big mess indeed.

> So before we try fixing things, we probably need to design something
> that defines
> where all the swapping happens, and what formats the virgl "hw" device supports.

2D case is easy.  Everything is little endian.  kernel driver / qemu are
doing the byteswaps for the structs sent over the control pipe.

Problem with 3D is that both qemu and kernel driver passing through data
where they don't even know what is inside, so they can't do the
byteswapping.

> The main problem is getting an efficient solution that avoids double swapping
> of the major items like texture and vertex data if we can in some scenarios.

Yes.

> 
> Currently the virgl "hw" supports little endian defined formats, as
> per the gallium
> interface, i.e. B8G8R8A8 means blue/red/green/alpha,
> 
> http://gallium.readthedocs.org/en/latest/format.html
> is the documentation.

Thanks.

> >> +    VIRTIO_GPU_FORMAT_B5G5R5A1_UNORM  = 5,
> >> +    VIRTIO_GPU_FORMAT_B5G6R5_UNORM    = 7,
> >
> > Do we really wanna go down this route?  I'm inclined to just zap 16bpp
> > support.
> 
> We have to support 16bpp as an OpenGL format no matter what, and this
> is why endianness sucks, we have lots of strange ass formats we need
> to send over the wire, that have no nicely defined endianness, like Z24S8.

Ok.  But for 2D we can just not support it, right?

> > What about 3d mode?  We are passing blobs between virglrenderer and
> > guest driver:  capabilities and gallium 3d command stream.  What happens
> > to them in case host and guest endianness don't match?  I think at least
> > the capabilities have 32bit values which need to be swapped.  Dunno
> > about the gallium commands ...
> 
> For 3D we probably need to define the gallium command streams to be
> little endian, however the big problem is the data that is stored
> inside objects.
> Texture and vertex, constants, indices etc. How do we decide to swap these,
> when do we swap things, on the DMA transfers to the host, do we just
> swap the formats on the host side etc.
> 
> I probably need to spend some time working this out with BenH, but
> I'm not really sure how we can avoid backing ourselves into a large inefficent
> hole at some point.

I surely don't wanna go down that route, and I think it is reasonable to
just not support 3D/virgl mode if we would have to swap data.


So, we could define *two* virgl feature bits.  One for little endian,
one for bigendian.  endianness applies to the gallium command stream and
to gallium formats using integers in host endianess.

On the host side we'll go set the feature bit matching host endianness.
qemu handles the virtqueue command struct swapping, and virglrenderer
should only see native endian.

On the guest side we'll look for the feature bit matching guest
endianness, and if it isn't set due to guest + host having different
byte order you'll get 2D support only.

The endianness negotiation is a bit iffy, but that way it is possible to
have virgl on bigendian without swapping everything twice.


The other reasonable way would be to simply define virgl being little
endian.  Bigendian guests / hosts would either simply not support 3D
then, or implement swapping.  But in the bigendian-guest on
bigendian-host case we'll swap everything twice then ...

cheers,
  Gerd

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

* Re: [Qemu-devel] [PATCH 1/8] virtio-gpu/2d: add hardware spec include file
  2014-09-30  0:27     ` Dave Airlie
  2014-09-30  7:54       ` Gerd Hoffmann
@ 2014-09-30  7:55       ` Gerd Hoffmann
  2014-10-03  4:38         ` Dave Airlie
  1 sibling, 1 reply; 19+ messages in thread
From: Gerd Hoffmann @ 2014-09-30  7:55 UTC (permalink / raw)
  To: Dave Airlie; +Cc: Dave Airlie, qemu-devel


On Di, 2014-09-30 at 10:27 +1000, Dave Airlie wrote:
> > Triggered by the framebuffer endian issues we have with stdvga I've
> > started to check where we stand with virtio-gpu and whenever we have to
> > fix something in the virtio protocol before setting in stone with the
> > upstream merge.
> 
> Let me start by saying its not that I don't care about endianness, but
> its a mess I had hoped to avoid until someone else care more about it.

Understood.  It's a big mess indeed.

> So before we try fixing things, we probably need to design something
> that defines
> where all the swapping happens, and what formats the virgl "hw" device supports.

2D case is easy.  Everything is little endian.  kernel driver / qemu are
doing the byteswaps for the structs sent over the control pipe.

Problem with 3D is that both qemu and kernel driver passing through data
where they don't even know what is inside, so they can't do the
byteswapping.

> The main problem is getting an efficient solution that avoids double swapping
> of the major items like texture and vertex data if we can in some scenarios.

Yes.

> 
> Currently the virgl "hw" supports little endian defined formats, as
> per the gallium
> interface, i.e. B8G8R8A8 means blue/red/green/alpha,
> 
> http://gallium.readthedocs.org/en/latest/format.html
> is the documentation.

Thanks.

> >> +    VIRTIO_GPU_FORMAT_B5G5R5A1_UNORM  = 5,
> >> +    VIRTIO_GPU_FORMAT_B5G6R5_UNORM    = 7,
> >
> > Do we really wanna go down this route?  I'm inclined to just zap 16bpp
> > support.
> 
> We have to support 16bpp as an OpenGL format no matter what, and this
> is why endianness sucks, we have lots of strange ass formats we need
> to send over the wire, that have no nicely defined endianness, like Z24S8.

Ok.  But for 2D we can just not support it, right?

> > What about 3d mode?  We are passing blobs between virglrenderer and
> > guest driver:  capabilities and gallium 3d command stream.  What happens
> > to them in case host and guest endianness don't match?  I think at least
> > the capabilities have 32bit values which need to be swapped.  Dunno
> > about the gallium commands ...
> 
> For 3D we probably need to define the gallium command streams to be
> little endian, however the big problem is the data that is stored
> inside objects.
> Texture and vertex, constants, indices etc. How do we decide to swap these,
> when do we swap things, on the DMA transfers to the host, do we just
> swap the formats on the host side etc.
> 
> I probably need to spend some time working this out with BenH, but
> I'm not really sure how we can avoid backing ourselves into a large inefficent
> hole at some point.

I surely don't wanna go down that route, and I think it is reasonable to
just not support 3D/virgl mode if we would have to swap data.


So, we could define *two* virgl feature bits.  One for little endian,
one for bigendian.  endianness applies to the gallium command stream and
to gallium formats using integers in host endianess.

On the host side we'll go set the feature bit matching host endianness.
qemu handles the virtqueue command struct swapping, and virglrenderer
should only see native endian.

On the guest side we'll look for the feature bit matching guest
endianness, and if it isn't set due to guest + host having different
byte order you'll get 2D support only.

The endianness negotiation is a bit iffy, but that way it is possible to
have virgl on bigendian without swapping everything twice.


The other reasonable way would be to simply define virgl being little
endian.  Bigendian guests / hosts would either simply not support 3D
then, or implement swapping.  But in the bigendian-guest on
bigendian-host case we'll swap everything twice then ...

cheers,
  Gerd

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

* Re: [Qemu-devel] [PATCH 1/8] virtio-gpu/2d: add hardware spec include file
  2014-09-30  7:55       ` Gerd Hoffmann
@ 2014-10-03  4:38         ` Dave Airlie
  2014-10-06  9:20           ` Gerd Hoffmann
  0 siblings, 1 reply; 19+ messages in thread
From: Dave Airlie @ 2014-10-03  4:38 UTC (permalink / raw)
  To: Gerd Hoffmann; +Cc: Dave Airlie, qemu-devel

On 30 September 2014 17:55, Gerd Hoffmann <kraxel@redhat.com> wrote:
>
> On Di, 2014-09-30 at 10:27 +1000, Dave Airlie wrote:
>> > Triggered by the framebuffer endian issues we have with stdvga I've
>> > started to check where we stand with virtio-gpu and whenever we have to
>> > fix something in the virtio protocol before setting in stone with the
>> > upstream merge.
>>
>> Let me start by saying its not that I don't care about endianness, but
>> its a mess I had hoped to avoid until someone else care more about it.
>
> Understood.  It's a big mess indeed.
>
>> So before we try fixing things, we probably need to design something
>> that defines
>> where all the swapping happens, and what formats the virgl "hw" device supports.
>
> 2D case is easy.  Everything is little endian.  kernel driver / qemu are
> doing the byteswaps for the structs sent over the control pipe.
>
> Problem with 3D is that both qemu and kernel driver passing through data
> where they don't even know what is inside, so they can't do the
> byteswapping.
>
>> The main problem is getting an efficient solution that avoids double swapping
>> of the major items like texture and vertex data if we can in some scenarios.
>
> Yes.
>
>>
>> Currently the virgl "hw" supports little endian defined formats, as
>> per the gallium
>> interface, i.e. B8G8R8A8 means blue/red/green/alpha,
>>
>> http://gallium.readthedocs.org/en/latest/format.html
>> is the documentation.
>
> Thanks.
>
>> >> +    VIRTIO_GPU_FORMAT_B5G5R5A1_UNORM  = 5,
>> >> +    VIRTIO_GPU_FORMAT_B5G6R5_UNORM    = 7,
>> >
>> > Do we really wanna go down this route?  I'm inclined to just zap 16bpp
>> > support.
>>
>> We have to support 16bpp as an OpenGL format no matter what, and this
>> is why endianness sucks, we have lots of strange ass formats we need
>> to send over the wire, that have no nicely defined endianness, like Z24S8.
>
> Ok.  But for 2D we can just not support it, right?

We can, I expect some pushback at some point, people still want to
test with 16bpp
for other areas, and it would be nice to know they can. But I don't really care
about it personally. I just though we should provide at least a basic
number of working
bpps (8,16,32).


>> > What about 3d mode?  We are passing blobs between virglrenderer and
>> > guest driver:  capabilities and gallium 3d command stream.  What happens
>> > to them in case host and guest endianness don't match?  I think at least
>> > the capabilities have 32bit values which need to be swapped.  Dunno
>> > about the gallium commands ...
>>
>> For 3D we probably need to define the gallium command streams to be
>> little endian, however the big problem is the data that is stored
>> inside objects.
>> Texture and vertex, constants, indices etc. How do we decide to swap these,
>> when do we swap things, on the DMA transfers to the host, do we just
>> swap the formats on the host side etc.
>>
>> I probably need to spend some time working this out with BenH, but
>> I'm not really sure how we can avoid backing ourselves into a large inefficent
>> hole at some point.
>
> I surely don't wanna go down that route, and I think it is reasonable to
> just not support 3D/virgl mode if we would have to swap data.

I think initially not support 3D mode is the way to go until we can work it out.

>
>
> So, we could define *two* virgl feature bits.  One for little endian,
> one for bigendian.  endianness applies to the gallium command stream and
> to gallium formats using integers in host endianess.
>
> On the host side we'll go set the feature bit matching host endianness.
> qemu handles the virtqueue command struct swapping, and virglrenderer
> should only see native endian.
>
> On the guest side we'll look for the feature bit matching guest
> endianness, and if it isn't set due to guest + host having different
> byte order you'll get 2D support only.
>
> The endianness negotiation is a bit iffy, but that way it is possible to
> have virgl on bigendian without swapping everything twice.
>
>
> The other reasonable way would be to simply define virgl being little
> endian.  Bigendian guests / hosts would either simply not support 3D
> then, or implement swapping.  But in the bigendian-guest on
> bigendian-host case we'll swap everything twice then ...
>

I think we should probably move a few more formats from the 3D side
into the 2D side, so we can have the guests just pick the LE format
it requires

http://cgit.freedesktop.org/mesa/mesa/tree/src/gallium/include/pipe/p_format.h#n354

is what gallium currently does, and we could just provide XRGB, XBGR
formats in both endianness
and have the guest pick the one it wants to use.

The 2D pixman code would need updating to provide 2D support for these
formats as well.

I suspect I could add an endian cap for the 3D bits that I could pass
through from guest to host.

How do you test guests with big endian? Isn't it really slow?

Dave.

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

* Re: [Qemu-devel] [PATCH 1/8] virtio-gpu/2d: add hardware spec include file
  2014-10-03  4:38         ` Dave Airlie
@ 2014-10-06  9:20           ` Gerd Hoffmann
  2014-10-16  3:53             ` Dave Airlie
  0 siblings, 1 reply; 19+ messages in thread
From: Gerd Hoffmann @ 2014-10-06  9:20 UTC (permalink / raw)
  To: Dave Airlie; +Cc: Dave Airlie, qemu-devel

  Hi,

> >> >> +    VIRTIO_GPU_FORMAT_B5G5R5A1_UNORM  = 5,
> >> >> +    VIRTIO_GPU_FORMAT_B5G6R5_UNORM    = 7,
> >> >
> > Ok.  But for 2D we can just not support it, right?
> 
> We can, I expect some pushback at some point, people still want to
> test with 16bpp for other areas, and it would be nice to know they
> can. But I don't really care about it personally. I just though we
> should provide at least a basic number of working bpps (8,16,32).

Lets try to get away with 32bpp only in 2d mode then.

bochsdrm likewise supports 32bpp only and I yet have to see a request
for 16bpp or even 8bpp support.

> I think we should probably move a few more formats from the 3D side
> into the 2D side, so we can have the guests just pick the LE format
> it requires
> 
> http://cgit.freedesktop.org/mesa/mesa/tree/src/gallium/include/pipe/p_format.h#n354
> 
> is what gallium currently does, and we could just provide XRGB, XBGR
> formats in both endianness
> and have the guest pick the one it wants to use.

   PIPE_FORMAT_R8G8B8A8_UNORM          = 67,
   PIPE_FORMAT_X8B8G8R8_UNORM          = 68,

   PIPE_FORMAT_A8B8G8R8_UNORM          = 121,
   PIPE_FORMAT_R8G8B8X8_UNORM          = 134,

With the last two ones being in a /* TODO: re-order these */ block.
How stable are these numbers?

> The 2D pixman code would need updating to provide 2D support for these
> formats as well.

Yep.  Mapping the 32bpp formats to pixmap formats is easy.

> I suspect I could add an endian cap for the 3D bits that I could pass
> through from guest to host.

I was thinking about using virtio feature bit.  Advantage is that the
guest will tell the host which features it'll use.

Initially this doesn't matter much as the host will support only one
endianness anyway. 

But in case we get the byteswapping work reasonable well some day and
the host supports both be and le virgl we'll know that way which
endianness the guest is using.

> How do you test guests with big endian? Isn't it really slow?

emulated pseries machine with fedora ppc64.  Yes, it is slow.  Building
a kernel with virtio-gpu driver takes a day or so.

cheers,
  Gerd

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

* Re: [Qemu-devel] [PATCH 1/8] virtio-gpu/2d: add hardware spec include file
  2014-09-23 13:28 ` [Qemu-devel] [PATCH 1/8] virtio-gpu/2d: add hardware spec include file Gerd Hoffmann
  2014-09-25 15:02   ` Gerd Hoffmann
@ 2014-10-15 10:05   ` Gerd Hoffmann
  2014-10-16  3:55     ` Dave Airlie
  1 sibling, 1 reply; 19+ messages in thread
From: Gerd Hoffmann @ 2014-10-15 10:05 UTC (permalink / raw)
  To: qemu-devel; +Cc: Dave Airlie

  Hi,

> +/* VIRTIO_GPU_RESP_OK_DISPLAY_INFO */
> +#define VIRTIO_GPU_MAX_SCANOUTS 16
> +struct virtio_gpu_resp_display_info {
> +    struct virtio_gpu_ctrl_hdr hdr;
> +    struct virtio_gpu_display_one {
> +        uint32_t enabled;
> +        uint32_t width;
> +        uint32_t height;
> +        uint32_t x;
> +        uint32_t y;
> +        uint32_t flags;
> +    } pmodes[VIRTIO_GPU_MAX_SCANOUTS];

One more thing: I think it would be a good idea to add the display
resolution here.  We start seeing highres displays on desktops, and the
guest should know whenever the host display runs at 100 or 300 dpi ...

What do you think?

cheers,
  Gerd 

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

* Re: [Qemu-devel] [PATCH 1/8] virtio-gpu/2d: add hardware spec include file
  2014-10-06  9:20           ` Gerd Hoffmann
@ 2014-10-16  3:53             ` Dave Airlie
  2014-10-16 12:18               ` Gerd Hoffmann
  0 siblings, 1 reply; 19+ messages in thread
From: Dave Airlie @ 2014-10-16  3:53 UTC (permalink / raw)
  To: Gerd Hoffmann; +Cc: Dave Airlie, qemu-devel

>
> Lets try to get away with 32bpp only in 2d mode then.
>
> bochsdrm likewise supports 32bpp only and I yet have to see a request
> for 16bpp or even 8bpp support.
>
>> I think we should probably move a few more formats from the 3D side
>> into the 2D side, so we can have the guests just pick the LE format
>> it requires
>>
>> http://cgit.freedesktop.org/mesa/mesa/tree/src/gallium/include/pipe/p_format.h#n354
>>
>> is what gallium currently does, and we could just provide XRGB, XBGR
>> formats in both endianness
>> and have the guest pick the one it wants to use.
>
>    PIPE_FORMAT_R8G8B8A8_UNORM          = 67,
>    PIPE_FORMAT_X8B8G8R8_UNORM          = 68,
>
>    PIPE_FORMAT_A8B8G8R8_UNORM          = 121,
>    PIPE_FORMAT_R8G8B8X8_UNORM          = 134,
>
> With the last two ones being in a /* TODO: re-order these */ block.
> How stable are these numbers?

In theory the mesa/gallium numbers aren't stable, though I've never
seen them change yet,

If they diverge in the future I'll just provide a remapping table
inside the guest driver.

So it should be fine to expose these formats for 2D use.

> Initially this doesn't matter much as the host will support only one
> endianness anyway.
>
> But in case we get the byteswapping work reasonable well some day and
> the host supports both be and le virgl we'll know that way which
> endianness the guest is using.
>
>> How do you test guests with big endian? Isn't it really slow?
>
> emulated pseries machine with fedora ppc64.  Yes, it is slow.  Building
> a kernel with virtio-gpu driver takes a day or so.

I spent a little while trying to get a ppc64 f20 install to complete, just
using the F20 qemu ppc64 system package but hit a bug I
think is related to missing SIMD instructions, so I'm not sure how best
to move forward with getting a test platform here.

Dave.

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

* Re: [Qemu-devel] [PATCH 1/8] virtio-gpu/2d: add hardware spec include file
  2014-10-15 10:05   ` Gerd Hoffmann
@ 2014-10-16  3:55     ` Dave Airlie
  0 siblings, 0 replies; 19+ messages in thread
From: Dave Airlie @ 2014-10-16  3:55 UTC (permalink / raw)
  To: Gerd Hoffmann; +Cc: Dave Airlie, qemu-devel

On 15 October 2014 20:05, Gerd Hoffmann <kraxel@redhat.com> wrote:
>   Hi,
>
>> +/* VIRTIO_GPU_RESP_OK_DISPLAY_INFO */
>> +#define VIRTIO_GPU_MAX_SCANOUTS 16
>> +struct virtio_gpu_resp_display_info {
>> +    struct virtio_gpu_ctrl_hdr hdr;
>> +    struct virtio_gpu_display_one {
>> +        uint32_t enabled;
>> +        uint32_t width;
>> +        uint32_t height;
>> +        uint32_t x;
>> +        uint32_t y;
>> +        uint32_t flags;
>> +    } pmodes[VIRTIO_GPU_MAX_SCANOUTS];
>
> One more thing: I think it would be a good idea to add the display
> resolution here.  We start seeing highres displays on desktops, and the
> guest should know whenever the host display runs at 100 or 300 dpi ...
>
> What do you think?

Passing host display side into the guest isn't going to help, unless
you are running in full screen,

I suppose the guest could adjust the numbers, but what happens with
viewers, if I connect on a hidpi and move to a lodpi screen.

I think this would require a lot more thought in how it would work in
some use-cases.

That said reserving 2 32 bit fields for possible screen measurements
might future proof things a little, though most OSes use EDID to detect
this sort of thing, so we might not find a great use for it later.

Dave.

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

* Re: [Qemu-devel] [PATCH 1/8] virtio-gpu/2d: add hardware spec include file
  2014-10-16  3:53             ` Dave Airlie
@ 2014-10-16 12:18               ` Gerd Hoffmann
  0 siblings, 0 replies; 19+ messages in thread
From: Gerd Hoffmann @ 2014-10-16 12:18 UTC (permalink / raw)
  To: Dave Airlie; +Cc: Dave Airlie, qemu-devel

  Hi,

> > How stable are these numbers?
> 
> In theory the mesa/gallium numbers aren't stable, though I've never
> seen them change yet,
> 
> If they diverge in the future I'll just provide a remapping table
> inside the guest driver.
> 
> So it should be fine to expose these formats for 2D use.

Good.

> >> How do you test guests with big endian? Isn't it really slow?
> >
> > emulated pseries machine with fedora ppc64.  Yes, it is slow.  Building
> > a kernel with virtio-gpu driver takes a day or so.
> 
> I spent a little while trying to get a ppc64 f20 install to complete, just
> using the F20 qemu ppc64 system package but hit a bug I
> think is related to missing SIMD instructions, so I'm not sure how best
> to move forward with getting a test platform here.

I'm using self-compiled qemu 2.1 which works fine, so it looks like this
issue has been fixed meanwhile.

If you want something newer without manually building it you can try the
virt-preview repo (see
https://fedoraproject.org/wiki/Virtualization_Preview_Repository).

cheers,
  Gerd

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

end of thread, other threads:[~2014-10-16 12:18 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-09-23 13:27 [Qemu-devel] [PATCH 0/8] add virtio-gpu Gerd Hoffmann
2014-09-23 13:28 ` [Qemu-devel] [PATCH 1/8] virtio-gpu/2d: add hardware spec include file Gerd Hoffmann
2014-09-25 15:02   ` Gerd Hoffmann
2014-09-30  0:27     ` Dave Airlie
2014-09-30  7:54       ` Gerd Hoffmann
2014-09-30  7:55       ` Gerd Hoffmann
2014-10-03  4:38         ` Dave Airlie
2014-10-06  9:20           ` Gerd Hoffmann
2014-10-16  3:53             ` Dave Airlie
2014-10-16 12:18               ` Gerd Hoffmann
2014-10-15 10:05   ` Gerd Hoffmann
2014-10-16  3:55     ` Dave Airlie
2014-09-23 13:28 ` [Qemu-devel] [PATCH 2/8] virtio-gpu/2d: add virtio gpu core code Gerd Hoffmann
2014-09-23 13:28 ` [Qemu-devel] [PATCH 3/8] virtio-gpu-pci: add virtio pci support Gerd Hoffmann
2014-09-23 13:28 ` [Qemu-devel] [PATCH 4/8] virtio-vga: add virtio gpu device with vga compatibility Gerd Hoffmann
2014-09-23 13:28 ` [Qemu-devel] [PATCH 5/8] virtio-vga: add '-vga virtio' support Gerd Hoffmann
2014-09-23 13:28 ` [Qemu-devel] [PATCH 6/8] virtio-vga: add vgabios configuration Gerd Hoffmann
2014-09-23 13:28 ` [Qemu-devel] [PATCH 7/8] virtio-vga: add vgabios binary Gerd Hoffmann
2014-09-23 13:28 ` [Qemu-devel] [PATCH 8/8] virtio-gpu: add to display-vga test Gerd Hoffmann

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.