All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH 0/9] add virtio-gpu with 2d support
@ 2015-03-13  9:47 Gerd Hoffmann
  2015-03-13  9:47 ` [Qemu-devel] [PATCH] opengl: require glx Gerd Hoffmann
                   ` (10 more replies)
  0 siblings, 11 replies; 25+ messages in thread
From: Gerd Hoffmann @ 2015-03-13  9:47 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

  Hi,

Next round of virtio-gpu patches.  Patches 1-8 are meant to be merged,
patch 9 is a hack to simplify testing with libvirt and will not be
merged.

Changes since the RfC submission earlier this month are a bunch of
sanity checks being added (mostly pointed out by max) and the
virtio-1.0 adaptions are squashed in now.

This series depends on virtio 1.0 patches still not merged.

This series is also available via git:
  git://git.kraxel.org/qemu tags/virtio-gpu-2015-03-13

The virtio patches are here (mst's virtio-1.0 branch, rebased to master):
  git://git.kraxel.org/qemu tags/virtio-mst-rebased-2015-03-13

Guest kernel driver is here:
  git://git.kraxel.org/linux virtio-gpu

Usage:
  qemu-system-x86_64 -vga virtio [ ... ]
  qemu-system-x86_64 -device virtio-vga [ ... ]
  qemu-system-ppc64 -M pseries -device virtio-gpu-pci [ ... ]
  qemu-system-arm -M virt -device virtio-gpu-device [ ... ]

Gerd Hoffmann (9):
  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
  [hack] virtio-gpu: maskerade as -device VGA

 Makefile                           |   2 +-
 default-configs/x86_64-softmmu.mak |   1 +
 hw/display/Makefile.objs           |   4 +
 hw/display/vga-pci.c               |   2 +-
 hw/display/virtio-gpu-pci.c        |  68 +++
 hw/display/virtio-gpu.c            | 923 +++++++++++++++++++++++++++++++++++++
 hw/display/virtio-vga.c            | 152 ++++++
 hw/pci/pci.c                       |   2 +
 hw/virtio/virtio-pci.h             |  15 +
 include/hw/virtio/virtgpu_hw.h     | 203 ++++++++
 include/hw/virtio/virtio-gpu.h     | 147 ++++++
 include/sysemu/sysemu.h            |   2 +-
 pc-bios/vgabios-virtio.bin         | Bin 0 -> 37376 bytes
 qemu-options.hx                    |   4 +-
 roms/Makefile                      |   2 +-
 roms/config.vga-virtio             |   6 +
 tests/Makefile                     |   3 +
 tests/display-vga-test.c           |  18 +
 trace-events                       |  14 +
 vl.c                               |  13 +
 20 files changed, 1576 insertions(+), 5 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] 25+ messages in thread

* [Qemu-devel] [PATCH] opengl: require glx
  2015-03-13  9:47 [Qemu-devel] [PATCH 0/9] add virtio-gpu with 2d support Gerd Hoffmann
@ 2015-03-13  9:47 ` Gerd Hoffmann
  2015-03-13 10:31   ` Gerd Hoffmann
  2015-03-13  9:47 ` [Qemu-devel] [PATCH 1/9] virtio-gpu/2d: add hardware spec include file Gerd Hoffmann
                   ` (9 subsequent siblings)
  10 siblings, 1 reply; 25+ messages in thread
From: Gerd Hoffmann @ 2015-03-13  9:47 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

hw/display/milkymist-tmu2.c uses glx.  That will be replaced with egl in
the future, with qemu getting more opengl support.  But we are not there
yet, so put it back into configure to fix build failures on machines
without glx (i.e. macos, possibly windows too).

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 configure | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/configure b/configure
index bd55786..ed49990 100755
--- a/configure
+++ b/configure
@@ -3120,7 +3120,7 @@ libs_softmmu="$libs_softmmu $fdt_libs"
 ##########################################
 # opengl probe (for sdl2, milkymist-tmu2)
 if test "$opengl" != "no" ; then
-  opengl_pkgs="egl gl glesv2"
+  opengl_pkgs="glx egl gl glesv2"
   if $pkg_config $opengl_pkgs x11; then
     opengl_cflags="$($pkg_config --cflags $opengl_pkgs) $x11_cflags"
     opengl_libs="$($pkg_config --libs $opengl_pkgs) $x11_libs"
-- 
1.8.3.1

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

* [Qemu-devel] [PATCH 1/9] virtio-gpu/2d: add hardware spec include file
  2015-03-13  9:47 [Qemu-devel] [PATCH 0/9] add virtio-gpu with 2d support Gerd Hoffmann
  2015-03-13  9:47 ` [Qemu-devel] [PATCH] opengl: require glx Gerd Hoffmann
@ 2015-03-13  9:47 ` Gerd Hoffmann
  2015-03-16 16:20   ` Max Reitz
  2015-03-13  9:47 ` [Qemu-devel] [PATCH 2/9] virtio-gpu/2d: add virtio gpu core code Gerd Hoffmann
                   ` (8 subsequent siblings)
  10 siblings, 1 reply; 25+ messages in thread
From: Gerd Hoffmann @ 2015-03-13  9:47 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 | 203 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 203 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..d6641e8
--- /dev/null
+++ b/include/hw/virtio/virtgpu_hw.h
@@ -0,0 +1,203 @@
+/*
+ * 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, 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 */
+
+struct virtio_gpu_rect {
+    uint32_t x, y;
+    uint32_t width;
+    uint32_t height;
+};
+
+/* 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;
+    struct virtio_gpu_rect r;
+    uint32_t scanout_id;
+    uint32_t resource_id;
+};
+
+/* VIRTIO_GPU_CMD_RESOURCE_FLUSH */
+struct virtio_gpu_resource_flush {
+    struct virtio_gpu_ctrl_hdr hdr;
+    struct virtio_gpu_rect r;
+    uint32_t resource_id;
+    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;
+    struct virtio_gpu_rect r;
+    uint64_t offset;
+    uint32_t resource_id;
+    uint32_t padding;
+};
+
+struct virtio_gpu_mem_entry {
+    uint64_t addr;
+    uint32_t length;
+    uint32_t padding;
+};
+
+/* 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 {
+        struct virtio_gpu_rect r;
+        uint32_t enabled;
+        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_R8G8B8A8_UNORM  = 67,
+    VIRTIO_GPU_FORMAT_X8B8G8R8_UNORM  = 68,
+
+    VIRTIO_GPU_FORMAT_A8B8G8R8_UNORM  = 121,
+    VIRTIO_GPU_FORMAT_R8G8B8X8_UNORM  = 134,
+
+};
+
+#endif
-- 
1.8.3.1

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

* [Qemu-devel] [PATCH 2/9] virtio-gpu/2d: add virtio gpu core code
  2015-03-13  9:47 [Qemu-devel] [PATCH 0/9] add virtio-gpu with 2d support Gerd Hoffmann
  2015-03-13  9:47 ` [Qemu-devel] [PATCH] opengl: require glx Gerd Hoffmann
  2015-03-13  9:47 ` [Qemu-devel] [PATCH 1/9] virtio-gpu/2d: add hardware spec include file Gerd Hoffmann
@ 2015-03-13  9:47 ` Gerd Hoffmann
  2015-03-16 18:28   ` Max Reitz
  2015-03-16 20:15   ` Max Reitz
  2015-03-13  9:47 ` [Qemu-devel] [PATCH 3/9] virtio-gpu-pci: add virtio pci support Gerd Hoffmann
                   ` (7 subsequent siblings)
  10 siblings, 2 replies; 25+ messages in thread
From: Gerd Hoffmann @ 2015-03-13  9:47 UTC (permalink / raw)
  To: qemu-devel; +Cc: Dave Airlie, Gerd Hoffmann, 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>
---
 hw/display/Makefile.objs       |   2 +
 hw/display/virtio-gpu.c        | 923 +++++++++++++++++++++++++++++++++++++++++
 include/hw/virtio/virtio-gpu.h | 147 +++++++
 trace-events                   |  14 +
 4 files changed, 1086 insertions(+)
 create mode 100644 hw/display/virtio-gpu.c
 create mode 100644 include/hw/virtio/virtio-gpu.h

diff --git a/hw/display/Makefile.objs b/hw/display/Makefile.objs
index 7ed76a9..6990634 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) += virtio-gpu.o
diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
new file mode 100644
index 0000000..ab71291
--- /dev/null
+++ b/hw/display/virtio-gpu.c
@@ -0,0 +1,923 @@
+/*
+ * 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;
+    }
+
+    if (pixman_image_get_width(res->image)  != s->current_cursor->width ||
+        pixman_image_get_height(res->image) != s->current_cursor->height) {
+        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 uint64_t virtio_gpu_get_features(VirtIODevice *vdev, uint64_t features)
+{
+    return features;
+}
+
+static void virtio_gpu_set_features(VirtIODevice *vdev, uint64_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].r.width = g->req_state[i].width;
+            dpy_info->pmodes[i].r.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) {
+#ifdef HOST_WORDS_BIGENDIAN
+    case VIRTIO_GPU_FORMAT_B8G8R8X8_UNORM:
+        return PIXMAN_b8g8r8x8;
+    case VIRTIO_GPU_FORMAT_B8G8R8A8_UNORM:
+        return PIXMAN_b8g8r8a8;
+    case VIRTIO_GPU_FORMAT_X8R8G8B8_UNORM:
+        return PIXMAN_x8r8g8b8;
+    case VIRTIO_GPU_FORMAT_A8R8G8B8_UNORM:
+        return PIXMAN_a8r8g8b8;
+    case VIRTIO_GPU_FORMAT_R8G8B8X8_UNORM:
+        return PIXMAN_r8g8b8x8;
+    case VIRTIO_GPU_FORMAT_R8G8B8A8_UNORM:
+        return PIXMAN_r8g8b8a8;
+    case VIRTIO_GPU_FORMAT_X8B8G8R8_UNORM:
+        return PIXMAN_x8b8g8r8;
+    case VIRTIO_GPU_FORMAT_A8B8G8R8_UNORM:
+        return PIXMAN_a8b8g8r8;
+#else
+    case VIRTIO_GPU_FORMAT_B8G8R8X8_UNORM:
+        return PIXMAN_x8r8g8b8;
+    case VIRTIO_GPU_FORMAT_B8G8R8A8_UNORM:
+        return PIXMAN_a8r8g8b8;
+    case VIRTIO_GPU_FORMAT_X8R8G8B8_UNORM:
+        return PIXMAN_b8g8r8x8;
+    case VIRTIO_GPU_FORMAT_A8R8G8B8_UNORM:
+        return PIXMAN_b8g8r8a8;
+    case VIRTIO_GPU_FORMAT_R8G8B8X8_UNORM:
+        return PIXMAN_x8b8g8r8;
+    case VIRTIO_GPU_FORMAT_R8G8B8A8_UNORM:
+        return PIXMAN_a8b8g8r8;
+    case VIRTIO_GPU_FORMAT_X8B8G8R8_UNORM:
+        return PIXMAN_r8g8b8x8;
+    case VIRTIO_GPU_FORMAT_A8B8G8R8_UNORM:
+        return PIXMAN_r8g8b8a8;
+#endif
+    default:
+        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);
+
+    if (c2d.resource_id == 0) {
+        qemu_log_mask(LOG_GUEST_ERROR, "%s: resource id 0 is not allowed\n",
+                      __func__);
+        cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID;
+        return;
+    }
+
+    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.r.x > res->width ||
+        t2d.r.y > res->height ||
+        t2d.r.width > res->width ||
+        t2d.r.height > res->height ||
+        t2d.r.x + t2d.r.width > res->width ||
+        t2d.r.y + t2d.r.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.r.x, t2d.r.y,
+                      t2d.r.width, t2d.r.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.r.x || t2d.r.y ||
+        t2d.r.width != pixman_image_get_width(res->image)) {
+        void *img_data = pixman_image_get_data(res->image);
+        for (h = 0; h < t2d.r.height; h++) {
+            src_offset = t2d.offset + stride * h;
+            dst_offset = (t2d.r.y + h) * stride + (t2d.r.x * bpp);
+
+            iov_to_buf(res->iov, res->iov_cnt, src_offset,
+                       (uint8_t *)img_data
+                       + dst_offset, t2d.r.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.r.width, rf.r.height, rf.r.x, rf.r.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.r.x > res->width ||
+        rf.r.y > res->height ||
+        rf.r.width > res->width ||
+        rf.r.height > res->height ||
+        rf.r.x + rf.r.width > res->width ||
+        rf.r.y + rf.r.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.r.x, rf.r.y,
+                      rf.r.width, rf.r.height, res->width, res->height);
+        cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER;
+        return;
+    }
+
+    pixman_region_init_rect(&flush_region,
+                            rf.r.x, rf.r.y, rf.r.width, rf.r.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.r.width, ss.r.height, ss.r.x, ss.r.y);
+
+    g->enable = 1;
+    if (ss.resource_id == 0) {
+        scanout = &g->scanout[ss.scanout_id];
+        if (scanout->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;
+    }
+
+    res = virtio_gpu_find_resource(g, ss.resource_id);
+    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.r.x > res->width ||
+        ss.r.y > res->height ||
+        ss.r.width > res->width ||
+        ss.r.height > res->height ||
+        ss.r.x + ss.r.width > res->width ||
+        ss.r.y + ss.r.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.r.x, ss.r.y,
+                      ss.r.width, ss.r.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.r.x * bpp) + ss.r.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.r.width ||
+        scanout->height != ss.r.height) {
+        /* realloc the surface ptr */
+        scanout->ds = qemu_create_displaysurface_from
+            (ss.r.width, ss.r.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.r.x;
+    scanout->y = ss.r.y;
+    scanout->width = ss.r.width;
+    scanout->height = ss.r.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;
+
+    if (ab->nr_entries > 1024) {
+        qemu_log_mask(LOG_GUEST_ERROR,
+                      "%s: nr_entries is too big (%d > 1024)\n",
+                      __func__, ab->nr_entries);
+        return -1;
+    }
+
+    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);
+    int i;
+
+    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;
+
+    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);
+        }
+    }
+}
+
+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++) {
+#if 0
+        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;
+        }
+#endif
+        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)     != 56);
+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..5d26ca9
--- /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, 3)
+
+#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 30eba92..a3d6fff 100644
--- a/trace-events
+++ b/trace-events
@@ -1167,6 +1167,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
 qemu_loadvm_state_section(unsigned int section_type) "%d"
 qemu_loadvm_state_section_partend(uint32_t section_id) "%u"
-- 
1.8.3.1

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

* [Qemu-devel] [PATCH 3/9] virtio-gpu-pci: add virtio pci support
  2015-03-13  9:47 [Qemu-devel] [PATCH 0/9] add virtio-gpu with 2d support Gerd Hoffmann
                   ` (2 preceding siblings ...)
  2015-03-13  9:47 ` [Qemu-devel] [PATCH 2/9] virtio-gpu/2d: add virtio gpu core code Gerd Hoffmann
@ 2015-03-13  9:47 ` Gerd Hoffmann
  2015-03-16 18:49   ` Max Reitz
  2015-03-13  9:47 ` [Qemu-devel] [PATCH 4/9] virtio-vga: add virtio gpu device with vga compatibility Gerd Hoffmann
                   ` (6 subsequent siblings)
  10 siblings, 1 reply; 25+ messages in thread
From: Gerd Hoffmann @ 2015-03-13  9:47 UTC (permalink / raw)
  To: qemu-devel; +Cc: Dave Airlie, Gerd Hoffmann, 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>
---
 hw/display/Makefile.objs    |  1 +
 hw/display/virtio-gpu-pci.c | 68 +++++++++++++++++++++++++++++++++++++++++++++
 hw/virtio/virtio-pci.h      | 15 ++++++++++
 3 files changed, 84 insertions(+)
 create mode 100644 hw/display/virtio-gpu-pci.c

diff --git a/hw/display/Makefile.objs b/hw/display/Makefile.objs
index 6990634..ab6b791 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) += virtio-gpu.o
+obj-$(CONFIG_VIRTIO_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..f0f25c7
--- /dev/null
+++ b/hw/display/virtio-gpu-pci.c
@@ -0,0 +1,68 @@
+/*
+ * 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_PROPERTIES(VirtIOGPUPCI, vdev.conf),
+    DEFINE_VIRTIO_GPU_PCI_PROPERTIES(VirtIOPCIProxy),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void virtio_gpu_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp)
+{
+    VirtIOGPUPCI *vgpu = VIRTIO_GPU_PCI(vpci_dev);
+    DeviceState *vdev = DEVICE(&vgpu->vdev);
+
+    qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus));
+    /* force virtio-1.0 */
+    vpci_dev->flags &= ~VIRTIO_PCI_FLAG_DISABLE_MODERN;
+    vpci_dev->flags |= VIRTIO_PCI_FLAG_DISABLE_LEGACY;
+    object_property_set_bool(OBJECT(vdev), true, "realized", errp);
+}
+
+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->realize = virtio_gpu_pci_realize;
+    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 b382688..efe8d31 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 */
 
@@ -225,6 +227,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
 
-- 
1.8.3.1

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

* [Qemu-devel] [PATCH 4/9] virtio-vga: add virtio gpu device with vga compatibility
  2015-03-13  9:47 [Qemu-devel] [PATCH 0/9] add virtio-gpu with 2d support Gerd Hoffmann
                   ` (3 preceding siblings ...)
  2015-03-13  9:47 ` [Qemu-devel] [PATCH 3/9] virtio-gpu-pci: add virtio pci support Gerd Hoffmann
@ 2015-03-13  9:47 ` Gerd Hoffmann
  2015-03-16 19:17   ` Max Reitz
  2015-03-13  9:47 ` [Qemu-devel] [PATCH 5/9] virtio-vga: add '-vga virtio' support Gerd Hoffmann
                   ` (5 subsequent siblings)
  10 siblings, 1 reply; 25+ messages in thread
From: Gerd Hoffmann @ 2015-03-13  9:47 UTC (permalink / raw)
  To: qemu-devel; +Cc: Dave Airlie, Gerd Hoffmann, 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            | 150 +++++++++++++++++++++++++++++++++++++
 3 files changed, 152 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 46b87dd..9a313d9 100644
--- a/default-configs/x86_64-softmmu.mak
+++ b/default-configs/x86_64-softmmu.mak
@@ -7,6 +7,7 @@ CONFIG_QXL=$(CONFIG_SPICE)
 CONFIG_VGA_ISA=y
 CONFIG_VGA_CIRRUS=y
 CONFIG_VMWARE_VGA=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 ab6b791..3da3f6c 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) += virtio-gpu.o
 obj-$(CONFIG_VIRTIO_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..bbde750
--- /dev/null
+++ b/hw/display/virtio-vga.c
@@ -0,0 +1,150 @@
+#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 (virtio_gpu_ops.ui_info) {
+        return virtio_gpu_ops.ui_info(&vvga->vdev, 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 void virtio_vga_realize(VirtIOPCIProxy *vpci_dev, Error **errp)
+{
+    VirtIOVGA *vvga = VIRTIO_VGA(vpci_dev);
+    VirtIOGPU *g = &vvga->vdev;
+    VGACommonState *vga = &vvga->vga;
+
+    /* init vga compat bits */
+    vga->vram_size_mb = 8;
+    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);
+    pci_register_bar(&vpci_dev->pci_dev, 2,
+                     PCI_BASE_ADDRESS_MEM_PREFETCH, &vga->vram);
+
+    /* init virtio bits */
+    qdev_set_parent_bus(DEVICE(g), BUS(&vpci_dev->bus));
+    /* force virtio-1.0 */
+    vpci_dev->flags &= ~VIRTIO_PCI_FLAG_DISABLE_MODERN;
+    vpci_dev->flags |= VIRTIO_PCI_FLAG_DISABLE_LEGACY;
+    object_property_set_bool(OBJECT(g), true, "realized", errp);
+
+    vga->con = g->scanout[0].con;
+    graphic_console_set_hwops(vga->con, &virtio_vga_ops, vvga);
+}
+
+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_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->realize = virtio_vga_realize;
+    pcidev_k->romfile = "vgabios-virtio.bin";
+    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] 25+ messages in thread

* [Qemu-devel] [PATCH 5/9] virtio-vga: add '-vga virtio' support
  2015-03-13  9:47 [Qemu-devel] [PATCH 0/9] add virtio-gpu with 2d support Gerd Hoffmann
                   ` (4 preceding siblings ...)
  2015-03-13  9:47 ` [Qemu-devel] [PATCH 4/9] virtio-vga: add virtio gpu device with vga compatibility Gerd Hoffmann
@ 2015-03-13  9:47 ` Gerd Hoffmann
  2015-03-16 19:30   ` Max Reitz
  2015-03-13  9:47 ` [Qemu-devel] [PATCH 6/9] virtio-vga: add vgabios configuration Gerd Hoffmann
                   ` (4 subsequent siblings)
  10 siblings, 1 reply; 25+ messages in thread
From: Gerd Hoffmann @ 2015-03-13  9:47 UTC (permalink / raw)
  To: qemu-devel; +Cc: Dave Airlie, Paolo Bonzini, Gerd Hoffmann, 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 +-
 qemu-options.hx         |  4 +++-
 vl.c                    | 13 +++++++++++++
 4 files changed, 19 insertions(+), 2 deletions(-)

diff --git a/hw/pci/pci.c b/hw/pci/pci.c
index 6941a82..f6eeaa9 100644
--- a/hw/pci/pci.c
+++ b/hw/pci/pci.c
@@ -1677,6 +1677,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 6e85097..4ee32bf 100644
--- a/include/sysemu/sysemu.h
+++ b/include/sysemu/sysemu.h
@@ -104,7 +104,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/qemu-options.hx b/qemu-options.hx
index 837624d..49b0f8f 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -1089,7 +1089,7 @@ Rotate graphical output some deg left (only PXA LCD).
 ETEXI
 
 DEF("vga", HAS_ARG, QEMU_OPTION_vga,
-    "-vga [std|cirrus|vmware|qxl|xenfb|tcx|cg3|none]\n"
+    "-vga [std|cirrus|vmware|qxl|xenfb|tcx|cg3|virtio|none]\n"
     "                select video card type\n", QEMU_ARCH_ALL)
 STEXI
 @item -vga @var{type}
@@ -1122,6 +1122,8 @@ fixed resolution of 1024x768.
 (sun4m only) Sun cgthree framebuffer. This is a simple 8-bit framebuffer
 for sun4m machines available in both 1024x768 (OpenBIOS) and 1152x900 (OBP)
 resolutions aimed at people wishing to run older Solaris versions.
+@item virtio
+Virtio VGA card.
 @item none
 Disable VGA card.
 @end table
diff --git a/vl.c b/vl.c
index eba5d4c..7f903a5 100644
--- a/vl.c
+++ b/vl.c
@@ -231,6 +231,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 = {
@@ -1871,6 +1872,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;
@@ -1897,6 +1903,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] 25+ messages in thread

* [Qemu-devel] [PATCH 6/9] virtio-vga: add vgabios configuration
  2015-03-13  9:47 [Qemu-devel] [PATCH 0/9] add virtio-gpu with 2d support Gerd Hoffmann
                   ` (5 preceding siblings ...)
  2015-03-13  9:47 ` [Qemu-devel] [PATCH 5/9] virtio-vga: add '-vga virtio' support Gerd Hoffmann
@ 2015-03-13  9:47 ` Gerd Hoffmann
  2015-03-16 19:38   ` Max Reitz
  2015-03-13  9:47 ` [Qemu-devel] [PATCH 7/9] virtio-vga: add vgabios binary Gerd Hoffmann
                   ` (3 subsequent siblings)
  10 siblings, 1 reply; 25+ messages in thread
From: Gerd Hoffmann @ 2015-03-13  9:47 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 884b59d..16899cc 100644
--- a/Makefile
+++ b/Makefile
@@ -340,7 +340,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..aa7a15b
--- /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=0x1050
-- 
1.8.3.1

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

* [Qemu-devel] [PATCH 7/9] virtio-vga: add vgabios binary
  2015-03-13  9:47 [Qemu-devel] [PATCH 0/9] add virtio-gpu with 2d support Gerd Hoffmann
                   ` (6 preceding siblings ...)
  2015-03-13  9:47 ` [Qemu-devel] [PATCH 6/9] virtio-vga: add vgabios configuration Gerd Hoffmann
@ 2015-03-13  9:47 ` Gerd Hoffmann
  2015-03-16 19:39   ` Max Reitz
  2015-03-13  9:47 ` [Qemu-devel] [PATCH 8/9] virtio-gpu: add to display-vga test Gerd Hoffmann
                   ` (2 subsequent siblings)
  10 siblings, 1 reply; 25+ messages in thread
From: Gerd Hoffmann @ 2015-03-13  9:47 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] 25+ messages in thread

* [Qemu-devel] [PATCH 8/9] virtio-gpu: add to display-vga test
  2015-03-13  9:47 [Qemu-devel] [PATCH 0/9] add virtio-gpu with 2d support Gerd Hoffmann
                   ` (7 preceding siblings ...)
  2015-03-13  9:47 ` [Qemu-devel] [PATCH 7/9] virtio-vga: add vgabios binary Gerd Hoffmann
@ 2015-03-13  9:47 ` Gerd Hoffmann
  2015-03-16 17:16   ` Paolo Bonzini
  2015-03-13  9:47 ` [Qemu-devel] [PATCH 9/9] [hack] virtio-gpu: maskerade as -device VGA Gerd Hoffmann
  2015-03-23 20:19 ` [Qemu-devel] [PATCH 0/9] add virtio-gpu with 2d support Christopher Covington
  10 siblings, 1 reply; 25+ messages in thread
From: Gerd Hoffmann @ 2015-03-13  9:47 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 588f438..55ad89f 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -133,6 +133,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] 25+ messages in thread

* [Qemu-devel] [PATCH 9/9] [hack] virtio-gpu: maskerade as -device VGA
  2015-03-13  9:47 [Qemu-devel] [PATCH 0/9] add virtio-gpu with 2d support Gerd Hoffmann
                   ` (8 preceding siblings ...)
  2015-03-13  9:47 ` [Qemu-devel] [PATCH 8/9] virtio-gpu: add to display-vga test Gerd Hoffmann
@ 2015-03-13  9:47 ` Gerd Hoffmann
  2015-03-23 20:19 ` [Qemu-devel] [PATCH 0/9] add virtio-gpu with 2d support Christopher Covington
  10 siblings, 0 replies; 25+ messages in thread
From: Gerd Hoffmann @ 2015-03-13  9:47 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann, Michael S. Tsirkin

Newer libvirt versions start looking up VGA in the QOM tree.
So tricking libvirt this way ...

    <qemu:arg value='-set'/>
    <qemu:arg value='device.video0.driver=virtio-vga'/>

... to test virtio-vga stopped working.

Lets rename VGA to stdvga and virtio-vga to VGA to get things going
again.  A simple ...

      <model type='vga' vram='16384' heads='1'/>

... will give you virtio-vga when building qemu with this patch applied.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/display/vga-pci.c    | 2 +-
 hw/display/virtio-vga.c | 4 +++-
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/hw/display/vga-pci.c b/hw/display/vga-pci.c
index aabfc23..8ed1ebd 100644
--- a/hw/display/vga-pci.c
+++ b/hw/display/vga-pci.c
@@ -349,7 +349,7 @@ static void secondary_class_init(ObjectClass *klass, void *data)
 }
 
 static const TypeInfo vga_info = {
-    .name          = "VGA",
+    .name          = "stdvga",
     .parent        = TYPE_PCI_DEVICE,
     .instance_init = pci_std_vga_init,
     .instance_size = sizeof(PCIVGAState),
diff --git a/hw/display/virtio-vga.c b/hw/display/virtio-vga.c
index bbde750..ded28c1 100644
--- a/hw/display/virtio-vga.c
+++ b/hw/display/virtio-vga.c
@@ -7,7 +7,7 @@
 /*
  * virtio-vga: This extends VirtioPCIProxy.
  */
-#define TYPE_VIRTIO_VGA "virtio-vga"
+#define TYPE_VIRTIO_VGA "VGA"
 #define VIRTIO_VGA(obj) \
         OBJECT_CHECK(VirtIOVGA, (obj), TYPE_VIRTIO_VGA)
 
@@ -15,6 +15,7 @@ typedef struct VirtIOVGA {
     VirtIOPCIProxy parent_obj;
     VirtIOGPU      vdev;
     VGACommonState vga;
+    uint32_t       dummy;
 } VirtIOVGA;
 
 static void virtio_vga_invalidate_display(void *opaque)
@@ -108,6 +109,7 @@ static void virtio_vga_reset(DeviceState *dev)
 static Property virtio_vga_properties[] = {
     DEFINE_VIRTIO_GPU_PROPERTIES(VirtIOVGA, vdev.conf),
     DEFINE_VIRTIO_GPU_PCI_PROPERTIES(VirtIOPCIProxy),
+    DEFINE_PROP_UINT32("vgamem_mb", VirtIOVGA, dummy, 16),
     DEFINE_PROP_END_OF_LIST(),
 };
 
-- 
1.8.3.1

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

* Re: [Qemu-devel] [PATCH] opengl: require glx
  2015-03-13  9:47 ` [Qemu-devel] [PATCH] opengl: require glx Gerd Hoffmann
@ 2015-03-13 10:31   ` Gerd Hoffmann
  0 siblings, 0 replies; 25+ messages in thread
From: Gerd Hoffmann @ 2015-03-13 10:31 UTC (permalink / raw)
  To: qemu-devel

On Fr, 2015-03-13 at 10:47 +0100, Gerd Hoffmann wrote:
> hw/display/milkymist-tmu2.c uses glx.  That will be replaced with egl in
> the future, with qemu getting more opengl support.  But we are not there
> yet, so put it back into configure to fix build failures on machines
> without glx (i.e. macos, possibly windows too).

Oops, scratch that one, old leftover *.patch file.

sorry,
  Gerd

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

* Re: [Qemu-devel] [PATCH 1/9] virtio-gpu/2d: add hardware spec include file
  2015-03-13  9:47 ` [Qemu-devel] [PATCH 1/9] virtio-gpu/2d: add hardware spec include file Gerd Hoffmann
@ 2015-03-16 16:20   ` Max Reitz
  2015-03-17  7:54     ` Gerd Hoffmann
  0 siblings, 1 reply; 25+ messages in thread
From: Max Reitz @ 2015-03-16 16:20 UTC (permalink / raw)
  To: Gerd Hoffmann, qemu-devel; +Cc: Dave Airlie

On 2015-03-13 at 05:47, Gerd Hoffmann wrote:
> 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 | 203 +++++++++++++++++++++++++++++++++++++++++
>   1 file changed, 203 insertions(+)
>   create mode 100644 include/hw/virtio/virtgpu_hw.h

There are some conflicts with the latest specification I was able to 
obtain 
(https://www.kraxel.org/virtio/virtio-v1.0-csprd03-virtio-gpu.pdf); for 
instance, the ordering of the fields in virtio_gpu_resp_display_info is 
different there, some GPU formats are different (but no conflict), and 
so on.

However, I guess this file will be pretty much the specification for the 
interface, so as long as it makes sense and it compiles, it's correct.

Reviewed-by: Max Reitz <mreitz@redhat.com>

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

* Re: [Qemu-devel] [PATCH 8/9] virtio-gpu: add to display-vga test
  2015-03-13  9:47 ` [Qemu-devel] [PATCH 8/9] virtio-gpu: add to display-vga test Gerd Hoffmann
@ 2015-03-16 17:16   ` Paolo Bonzini
  2015-03-17  8:25     ` Gerd Hoffmann
  0 siblings, 1 reply; 25+ messages in thread
From: Paolo Bonzini @ 2015-03-16 17:16 UTC (permalink / raw)
  To: Gerd Hoffmann, qemu-devel



On 13/03/2015 10:47, Gerd Hoffmann wrote:
> 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 588f438..55ad89f 100644
> --- a/tests/Makefile
> +++ b/tests/Makefile
> @@ -133,6 +133,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;
> 

Which config file is defining this?

Paolo

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

* Re: [Qemu-devel] [PATCH 2/9] virtio-gpu/2d: add virtio gpu core code
  2015-03-13  9:47 ` [Qemu-devel] [PATCH 2/9] virtio-gpu/2d: add virtio gpu core code Gerd Hoffmann
@ 2015-03-16 18:28   ` Max Reitz
  2015-03-16 20:15   ` Max Reitz
  1 sibling, 0 replies; 25+ messages in thread
From: Max Reitz @ 2015-03-16 18:28 UTC (permalink / raw)
  To: Gerd Hoffmann, qemu-devel; +Cc: Dave Airlie, Michael S. Tsirkin

On 2015-03-13 at 05:47, Gerd Hoffmann wrote:
> 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>
> ---
>   hw/display/Makefile.objs       |   2 +
>   hw/display/virtio-gpu.c        | 923 +++++++++++++++++++++++++++++++++++++++++
>   include/hw/virtio/virtio-gpu.h | 147 +++++++
>   trace-events                   |  14 +
>   4 files changed, 1086 insertions(+)
>   create mode 100644 hw/display/virtio-gpu.c
>   create mode 100644 include/hw/virtio/virtio-gpu.h
>
> diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
> new file mode 100644
> index 0000000..ab71291
> --- /dev/null
> +++ b/hw/display/virtio-gpu.c

[snip]

> +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;
> +
> +    if (ab->nr_entries > 1024) {
> +        qemu_log_mask(LOG_GUEST_ERROR,
> +                      "%s: nr_entries is too big (%d > 1024)\n",
> +                      __func__, ab->nr_entries);

You said that maybe you wanted to go for 16384 instead of 1024.

[snip]

> diff --git a/include/hw/virtio/virtio-gpu.h b/include/hw/virtio/virtio-gpu.h
> new file mode 100644
> index 0000000..5d26ca9
> --- /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

Unused in this series. Is that intentional?

Independent of whether you keep it or remove it, and independent of 
whether you increase the ab->nr_entries limit:

Reviewed-by: Max Reitz <mreitz@redhat.com>

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

* Re: [Qemu-devel] [PATCH 3/9] virtio-gpu-pci: add virtio pci support
  2015-03-13  9:47 ` [Qemu-devel] [PATCH 3/9] virtio-gpu-pci: add virtio pci support Gerd Hoffmann
@ 2015-03-16 18:49   ` Max Reitz
  0 siblings, 0 replies; 25+ messages in thread
From: Max Reitz @ 2015-03-16 18:49 UTC (permalink / raw)
  To: Gerd Hoffmann, qemu-devel; +Cc: Dave Airlie, Michael S. Tsirkin

On 2015-03-13 at 05:47, Gerd Hoffmann wrote:
> 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>
> ---
>   hw/display/Makefile.objs    |  1 +
>   hw/display/virtio-gpu-pci.c | 68 +++++++++++++++++++++++++++++++++++++++++++++
>   hw/virtio/virtio-pci.h      | 15 ++++++++++
>   3 files changed, 84 insertions(+)
>   create mode 100644 hw/display/virtio-gpu-pci.c

Reviewed-by: Max Reitz <mreitz@redhat.com>

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

* Re: [Qemu-devel] [PATCH 4/9] virtio-vga: add virtio gpu device with vga compatibility
  2015-03-13  9:47 ` [Qemu-devel] [PATCH 4/9] virtio-vga: add virtio gpu device with vga compatibility Gerd Hoffmann
@ 2015-03-16 19:17   ` Max Reitz
  0 siblings, 0 replies; 25+ messages in thread
From: Max Reitz @ 2015-03-16 19:17 UTC (permalink / raw)
  To: Gerd Hoffmann, qemu-devel; +Cc: Dave Airlie, Michael S. Tsirkin

On 2015-03-13 at 05:47, Gerd Hoffmann wrote:
> 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            | 150 +++++++++++++++++++++++++++++++++++++
>   3 files changed, 152 insertions(+)
>   create mode 100644 hw/display/virtio-vga.c

Looks good to me, but I can't really give an R-b because I'm really 
unfamiliar with all things concerning VGA.

Max

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

* Re: [Qemu-devel] [PATCH 5/9] virtio-vga: add '-vga virtio' support
  2015-03-13  9:47 ` [Qemu-devel] [PATCH 5/9] virtio-vga: add '-vga virtio' support Gerd Hoffmann
@ 2015-03-16 19:30   ` Max Reitz
  0 siblings, 0 replies; 25+ messages in thread
From: Max Reitz @ 2015-03-16 19:30 UTC (permalink / raw)
  To: Gerd Hoffmann, qemu-devel; +Cc: Dave Airlie, Michael S. Tsirkin, Paolo Bonzini

On 2015-03-13 at 05:47, Gerd Hoffmann wrote:
> 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 +-
>   qemu-options.hx         |  4 +++-
>   vl.c                    | 13 +++++++++++++
>   4 files changed, 19 insertions(+), 2 deletions(-)

Hm, the other VGA devices which support only PCI ("vmware" and "qxl") 
emit explicit error messages in isa_vga_init(). Maybe we should do the 
same? Without, the initialization fails silently and qemu starts, but 
there is no display ("-machine isapc -display virtio").

Max

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

* Re: [Qemu-devel] [PATCH 6/9] virtio-vga: add vgabios configuration
  2015-03-13  9:47 ` [Qemu-devel] [PATCH 6/9] virtio-vga: add vgabios configuration Gerd Hoffmann
@ 2015-03-16 19:38   ` Max Reitz
  0 siblings, 0 replies; 25+ messages in thread
From: Max Reitz @ 2015-03-16 19:38 UTC (permalink / raw)
  To: Gerd Hoffmann, qemu-devel

On 2015-03-13 at 05:47, Gerd Hoffmann wrote:
> 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

Reviewed-by: Max Reitz <mreitz@redhat.com>

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

* Re: [Qemu-devel] [PATCH 7/9] virtio-vga: add vgabios binary
  2015-03-13  9:47 ` [Qemu-devel] [PATCH 7/9] virtio-vga: add vgabios binary Gerd Hoffmann
@ 2015-03-16 19:39   ` Max Reitz
  0 siblings, 0 replies; 25+ messages in thread
From: Max Reitz @ 2015-03-16 19:39 UTC (permalink / raw)
  To: Gerd Hoffmann, qemu-devel

On 2015-03-13 at 05:47, Gerd Hoffmann wrote:
> 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

Well, I can't really review this, sorry...

Max

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

* Re: [Qemu-devel] [PATCH 2/9] virtio-gpu/2d: add virtio gpu core code
  2015-03-13  9:47 ` [Qemu-devel] [PATCH 2/9] virtio-gpu/2d: add virtio gpu core code Gerd Hoffmann
  2015-03-16 18:28   ` Max Reitz
@ 2015-03-16 20:15   ` Max Reitz
  2015-03-17  8:21     ` Gerd Hoffmann
  1 sibling, 1 reply; 25+ messages in thread
From: Max Reitz @ 2015-03-16 20:15 UTC (permalink / raw)
  To: Gerd Hoffmann, qemu-devel; +Cc: Dave Airlie, Michael S. Tsirkin

On 2015-03-13 at 05:47, Gerd Hoffmann wrote:
> 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>
> ---
>   hw/display/Makefile.objs       |   2 +
>   hw/display/virtio-gpu.c        | 923 +++++++++++++++++++++++++++++++++++++++++
>   include/hw/virtio/virtio-gpu.h | 147 +++++++
>   trace-events                   |  14 +
>   4 files changed, 1086 insertions(+)
>   create mode 100644 hw/display/virtio-gpu.c
>   create mode 100644 include/hw/virtio/virtio-gpu.h
>
> diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
> new file mode 100644
> index 0000000..ab71291
> --- /dev/null
> +++ b/hw/display/virtio-gpu.c

[snip]

> +static void virtio_gpu_device_realize(DeviceState *qdev, Error **errp)
> +{
> +    VirtIODevice *vdev = VIRTIO_DEVICE(qdev);
> +    VirtIOGPU *g = VIRTIO_GPU(qdev);
> +    int i;
> +
> +    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;
> +
> +    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);

GTK can't cope very well with NULL surfaces (read: after patch 7 (when 
using -vga virtio finally works) "x86_64-softmmu/qemu-system-x86_64 -vga 
virtio -display gtk" segfaults). With SDL (SDL2), it works fine.

A simple block like "if (!surface) { if (vc->gfx.surface) { 
cairo_surface_destroy(vc->gfx.surface); } vc->gfx.surface = NULL; 
return; }" at the beginning of gd_switch() in ui/gtk.c seems to work for 
me, though.

A similar problem exists with SDL1: Using Ctrl-Alt-2 segfaults (which is 
due to new_surface being NULL in sdl_switch(), and thus 
new_surface->format in the very first statement failing).

Max

> +        }
> +    }
> +}
> +
> +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++) {
> +#if 0
> +        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;
> +        }
> +#endif
> +        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)     != 56);
> +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..5d26ca9
> --- /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, 3)
> +
> +#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 30eba92..a3d6fff 100644
> --- a/trace-events
> +++ b/trace-events
> @@ -1167,6 +1167,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
>   qemu_loadvm_state_section(unsigned int section_type) "%d"
>   qemu_loadvm_state_section_partend(uint32_t section_id) "%u"

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

* Re: [Qemu-devel] [PATCH 1/9] virtio-gpu/2d: add hardware spec include file
  2015-03-16 16:20   ` Max Reitz
@ 2015-03-17  7:54     ` Gerd Hoffmann
  0 siblings, 0 replies; 25+ messages in thread
From: Gerd Hoffmann @ 2015-03-17  7:54 UTC (permalink / raw)
  To: Max Reitz; +Cc: Dave Airlie, qemu-devel

  Hi,

> There are some conflicts with the latest specification I was able to 
> obtain 
> (https://www.kraxel.org/virtio/virtio-v1.0-csprd03-virtio-gpu.pdf); for 
> instance, the ordering of the fields in virtio_gpu_resp_display_info is 
> different there, some GPU formats are different (but no conflict), and 
> so on.

Good point, I should update the specs.

thanks,
  Gerd

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

* Re: [Qemu-devel] [PATCH 2/9] virtio-gpu/2d: add virtio gpu core code
  2015-03-16 20:15   ` Max Reitz
@ 2015-03-17  8:21     ` Gerd Hoffmann
  0 siblings, 0 replies; 25+ messages in thread
From: Gerd Hoffmann @ 2015-03-17  8:21 UTC (permalink / raw)
  To: Max Reitz; +Cc: Dave Airlie, qemu-devel, Michael S. Tsirkin

  Hi,

> > +    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);
> 
> GTK can't cope very well with NULL surfaces (read: after patch 7 (when 
> using -vga virtio finally works) "x86_64-softmmu/qemu-system-x86_64 -vga 
> virtio -display gtk" segfaults). With SDL (SDL2), it works fine.

Yes, I know.  I have a gtk patch for that in the pipeline.

But that alone doesn't get multihead work sanely as there is at least
one more problem to tackle:  Mouse coordinates are not correct.  Our
options are:

 (a) Have guest notify host about screen arrangement, then transform
     coordinates in qemu.  Dave did that initially.
 (b) Have a guest agent (spice style).
 (c) Have one tablet per head and link them.  That is very simliar to
     physical hardware (think touchscreen).

I think (c) will work best long-term, but it is also the most difficult
one as various projects are involved here to get the guest-side
configuration done.

I've changed the number of heads to be 1 by default, we better sort all
those issues before we flip the multihead default switch.

cheers,
  Gerd

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

* Re: [Qemu-devel] [PATCH 8/9] virtio-gpu: add to display-vga test
  2015-03-16 17:16   ` Paolo Bonzini
@ 2015-03-17  8:25     ` Gerd Hoffmann
  0 siblings, 0 replies; 25+ messages in thread
From: Gerd Hoffmann @ 2015-03-17  8:25 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: qemu-devel

  Hi,

> > +#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;
> > 
> 
> Which config file is defining this?

Ahem, good point, CONFIG_VIRTIO_GPU used to be there but is gone now.
I'll fixup the test.

thanks,
  Gerd

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

* Re: [Qemu-devel] [PATCH 0/9] add virtio-gpu with 2d support
  2015-03-13  9:47 [Qemu-devel] [PATCH 0/9] add virtio-gpu with 2d support Gerd Hoffmann
                   ` (9 preceding siblings ...)
  2015-03-13  9:47 ` [Qemu-devel] [PATCH 9/9] [hack] virtio-gpu: maskerade as -device VGA Gerd Hoffmann
@ 2015-03-23 20:19 ` Christopher Covington
  10 siblings, 0 replies; 25+ messages in thread
From: Christopher Covington @ 2015-03-23 20:19 UTC (permalink / raw)
  To: Gerd Hoffmann, qemu-devel, Alex Bennée

Hi Gerd,

This looks great, thanks for your work on this. Unfortunately, I'm seeing the
segfault below.

Alex, do you have any thoughts on how well this might be able to replace the
Goldfish Framebuffer on the Android Emulator?

On 03/13/2015 05:47 AM, Gerd Hoffmann wrote:
>   Hi,
> 
> Next round of virtio-gpu patches.  Patches 1-8 are meant to be merged,
> patch 9 is a hack to simplify testing with libvirt and will not be
> merged.
> 
> Changes since the RfC submission earlier this month are a bunch of
> sanity checks being added (mostly pointed out by max) and the
> virtio-1.0 adaptions are squashed in now.
> 
> This series depends on virtio 1.0 patches still not merged.
> 
> This series is also available via git:
>   git://git.kraxel.org/qemu tags/virtio-gpu-2015-03-13
> 
> The virtio patches are here (mst's virtio-1.0 branch, rebased to master):
>   git://git.kraxel.org/qemu tags/virtio-mst-rebased-2015-03-13
> 
> Guest kernel driver is here:
>   git://git.kraxel.org/linux virtio-gpu
> 
> Usage:
>   qemu-system-x86_64 -vga virtio [ ... ]
>   qemu-system-x86_64 -device virtio-vga [ ... ]
>   qemu-system-ppc64 -M pseries -device virtio-gpu-pci [ ... ]
>   qemu-system-arm -M virt -device virtio-gpu-device [ ... ]

git remote add kraxel git://git.kraxel.org/qemu
git fetch kraxel
git checkout tags/virtio-gpu-2015-03-13
./configure --target-list=aarch64-softmmu
make -j 12
gdb --args aarch64-softmmu/qemu-system-aarch64 -M virt -cpu cortex-a57 \
  -device virtio-gpu-device
[...]
Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x7ffff7fb0ac0 (LWP 26568)]
gd_switch (dcl=0x5555563285d0, surface=0x0) at ui/gtk.c:565
565         trace_gd_switch(vc->label, surface_width(surface), surface_heigh
t(surface));
(gdb) bt
#0  gd_switch (dcl=0x5555563285d0, surface=0x0) at ui/gtk.c:565
#1  0x00005555558ba706 in register_displaychangelistener (
    dcl=0x5555563285d0) at ui/console.c:1353
#2  0x00005555558dcd80 in gd_vc_gfx_init (view_menu=0x555556bf4220,
    group=<optimized out>, idx=<optimized out>, con=0x555556333de0,
    vc=0x555556328598, s=0x555556328470) at ui/gtk.c:1705
#3  gd_create_menu_view (s=0x555556328470) at ui/gtk.c:1781
#4  gd_create_menus (s=0x555556328470) at ui/gtk.c:1807
#5  gtk_display_init (ds=<optimized out>, full_screen=false,
    grab_on_hover=false) at ui/gtk.c:1894
#6  0x0000555555609247 in main (argc=<optimized out>,
    argv=<optimized out>, envp=<optimized out>) at vl.c:4292

Thanks,
Chris

-- 
Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

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

end of thread, other threads:[~2015-03-23 20:19 UTC | newest]

Thread overview: 25+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-03-13  9:47 [Qemu-devel] [PATCH 0/9] add virtio-gpu with 2d support Gerd Hoffmann
2015-03-13  9:47 ` [Qemu-devel] [PATCH] opengl: require glx Gerd Hoffmann
2015-03-13 10:31   ` Gerd Hoffmann
2015-03-13  9:47 ` [Qemu-devel] [PATCH 1/9] virtio-gpu/2d: add hardware spec include file Gerd Hoffmann
2015-03-16 16:20   ` Max Reitz
2015-03-17  7:54     ` Gerd Hoffmann
2015-03-13  9:47 ` [Qemu-devel] [PATCH 2/9] virtio-gpu/2d: add virtio gpu core code Gerd Hoffmann
2015-03-16 18:28   ` Max Reitz
2015-03-16 20:15   ` Max Reitz
2015-03-17  8:21     ` Gerd Hoffmann
2015-03-13  9:47 ` [Qemu-devel] [PATCH 3/9] virtio-gpu-pci: add virtio pci support Gerd Hoffmann
2015-03-16 18:49   ` Max Reitz
2015-03-13  9:47 ` [Qemu-devel] [PATCH 4/9] virtio-vga: add virtio gpu device with vga compatibility Gerd Hoffmann
2015-03-16 19:17   ` Max Reitz
2015-03-13  9:47 ` [Qemu-devel] [PATCH 5/9] virtio-vga: add '-vga virtio' support Gerd Hoffmann
2015-03-16 19:30   ` Max Reitz
2015-03-13  9:47 ` [Qemu-devel] [PATCH 6/9] virtio-vga: add vgabios configuration Gerd Hoffmann
2015-03-16 19:38   ` Max Reitz
2015-03-13  9:47 ` [Qemu-devel] [PATCH 7/9] virtio-vga: add vgabios binary Gerd Hoffmann
2015-03-16 19:39   ` Max Reitz
2015-03-13  9:47 ` [Qemu-devel] [PATCH 8/9] virtio-gpu: add to display-vga test Gerd Hoffmann
2015-03-16 17:16   ` Paolo Bonzini
2015-03-17  8:25     ` Gerd Hoffmann
2015-03-13  9:47 ` [Qemu-devel] [PATCH 9/9] [hack] virtio-gpu: maskerade as -device VGA Gerd Hoffmann
2015-03-23 20:19 ` [Qemu-devel] [PATCH 0/9] add virtio-gpu with 2d support Christopher Covington

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.