[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH v4 27/29] virtio-gpu: split virtio-gpu, introduce vi
From: |
Marc-André Lureau |
Subject: |
[Qemu-devel] [PATCH v4 27/29] virtio-gpu: split virtio-gpu, introduce virtio-gpu-base |
Date: |
Fri, 13 Jul 2018 15:09:14 +0200 |
Add a base class that is common to virtio-gpu and vhost-user-gpu
devices.
The VirtIOGPUBase base class provides common functionalities necessary
for both virtio-gpu and vhost-user-gpu:
- common configuration (max-outputs, initial resolution, flags)
- virtio device initialization, including queue setup
- device pre-conditions checks (iommu)
- migration blocker
- virtio device callbacks
- hooking up to qemu display subsystem
- a few common helper functions to reset the device, retrieve display
informations
- a class callback to unblock the rendering (for GL updates)
What is left to the virtio-gpu subdevice to take care of, in short,
are all the virtio queues handling, command processing and migration.
Signed-off-by: Marc-André Lureau <address@hidden>
---
include/hw/virtio/virtio-gpu.h | 72 +++++--
hw/display/virtio-gpu-3d.c | 49 ++---
hw/display/virtio-gpu-base.c | 292 +++++++++++++++++++++++++++++
hw/display/virtio-gpu-pci.c | 2 +-
hw/display/virtio-gpu.c | 332 ++++++---------------------------
hw/display/virtio-vga.c | 15 +-
hw/display/Makefile.objs | 2 +-
7 files changed, 447 insertions(+), 317 deletions(-)
create mode 100644 hw/display/virtio-gpu-base.c
diff --git a/include/hw/virtio/virtio-gpu.h b/include/hw/virtio/virtio-gpu.h
index 6b07efc4f7..2edf47e9ab 100644
--- a/include/hw/virtio/virtio-gpu.h
+++ b/include/hw/virtio/virtio-gpu.h
@@ -22,6 +22,14 @@
#include "standard-headers/linux/virtio_gpu.h"
+#define TYPE_VIRTIO_GPU_BASE "virtio-gpu-base"
+#define VIRTIO_GPU_BASE(obj) \
+ OBJECT_CHECK(VirtIOGPUBase, (obj), TYPE_VIRTIO_GPU_BASE)
+#define VIRTIO_GPU_BASE_GET_CLASS(obj) \
+ OBJECT_GET_CLASS(VirtIOGPUBaseClass, obj, TYPE_VIRTIO_GPU_BASE)
+#define VIRTIO_GPU_BASE_CLASS(klass) \
+ OBJECT_CLASS_CHECK(VirtIOGPUBaseClass, klass, TYPE_VIRTIO_GPU_BASE)
+
#define TYPE_VIRTIO_GPU "virtio-gpu-device"
#define VIRTIO_GPU(obj) \
OBJECT_CHECK(VirtIOGPU, (obj), TYPE_VIRTIO_GPU)
@@ -58,7 +66,7 @@ struct virtio_gpu_requested_state {
int x, y;
};
-enum virtio_gpu_conf_flags {
+enum virtio_gpu_base_conf_flags {
VIRTIO_GPU_FLAG_VIRGL_ENABLED = 1,
VIRTIO_GPU_FLAG_STATS_ENABLED,
};
@@ -68,8 +76,7 @@ enum virtio_gpu_conf_flags {
#define virtio_gpu_stats_enabled(_cfg) \
(_cfg.flags & (1 << VIRTIO_GPU_FLAG_STATS_ENABLED))
-struct virtio_gpu_conf {
- uint64_t max_hostmem;
+struct virtio_gpu_base_conf {
uint32_t max_outputs;
uint32_t flags;
uint32_t xres;
@@ -85,31 +92,53 @@ struct virtio_gpu_ctrl_command {
QTAILQ_ENTRY(virtio_gpu_ctrl_command) next;
};
-typedef struct VirtIOGPU {
+typedef struct VirtIOGPUBase {
VirtIODevice parent_obj;
- QEMUBH *ctrl_bh;
- QEMUBH *cursor_bh;
+ Error *migration_blocker;
+
+ struct virtio_gpu_base_conf conf;
+ struct virtio_gpu_config virtio_config;
+
+ bool use_virgl_renderer;
+ int renderer_blocked;
+ int enable;
+
+ struct virtio_gpu_scanout scanout[VIRTIO_GPU_MAX_SCANOUTS];
+
+ int enabled_output_bitmask;
+ struct virtio_gpu_requested_state req_state[VIRTIO_GPU_MAX_SCANOUTS];
+} VirtIOGPUBase;
+
+typedef struct VirtIOGPUBaseClass {
+ VirtioDeviceClass parent;
+
+ void (*gl_unblock)(VirtIOGPUBase *g);
+} VirtIOGPUBaseClass;
+
+#define VIRTIO_GPU_BASE_PROPERTIES(_state, _conf) \
+ DEFINE_PROP_UINT32("max_outputs", _state, _conf.max_outputs, 1), \
+ DEFINE_PROP_UINT32("xres", _state, _conf.xres, 1024), \
+ DEFINE_PROP_UINT32("yres", _state, _conf.yres, 768)
+
+typedef struct VirtIOGPU {
+ VirtIOGPUBase parent_obj;
+
+ uint64_t conf_max_hostmem;
+
VirtQueue *ctrl_vq;
VirtQueue *cursor_vq;
- int enable;
+ QEMUBH *ctrl_bh;
+ QEMUBH *cursor_bh;
QTAILQ_HEAD(, virtio_gpu_simple_resource) reslist;
QTAILQ_HEAD(, virtio_gpu_ctrl_command) cmdq;
QTAILQ_HEAD(, virtio_gpu_ctrl_command) fenceq;
- struct virtio_gpu_scanout scanout[VIRTIO_GPU_MAX_SCANOUTS];
- struct virtio_gpu_requested_state req_state[VIRTIO_GPU_MAX_SCANOUTS];
-
- struct virtio_gpu_conf conf;
uint64_t hostmem;
- int enabled_output_bitmask;
- struct virtio_gpu_config virtio_config;
- bool use_virgl_renderer;
bool renderer_inited;
- int renderer_blocked;
QEMUTimer *fence_poll;
QEMUTimer *print_stats;
@@ -120,8 +149,6 @@ typedef struct VirtIOGPU {
uint32_t req_3d;
uint32_t bytes_3d;
} stats;
-
- Error *migration_blocker;
} VirtIOGPU;
extern const GraphicHwOps virtio_gpu_ops;
@@ -144,6 +171,16 @@ extern const GraphicHwOps virtio_gpu_ops;
} \
} while (0)
+/* virtio-gpu-base.c */
+bool virtio_gpu_base_device_realize(DeviceState *qdev,
+ int num_capsets,
+ VirtIOHandleOutput ctrl_cb,
+ VirtIOHandleOutput cursor_cb,
+ Error **errp);
+void virtio_gpu_base_reset(VirtIOGPUBase *g);
+void virtio_gpu_base_fill_display_info(VirtIOGPUBase *g,
+ struct virtio_gpu_resp_display_info *dpy_info);
+
/* virtio-gpu.c */
void virtio_gpu_ctrl_response(VirtIOGPU *g,
struct virtio_gpu_ctrl_command *cmd,
@@ -167,4 +204,5 @@ void virtio_gpu_virgl_fence_poll(VirtIOGPU *g);
void virtio_gpu_virgl_reset(VirtIOGPU *g);
int virtio_gpu_virgl_init(VirtIOGPU *g);
int virtio_gpu_virgl_get_num_capsets(VirtIOGPU *g);
+
#endif
diff --git a/hw/display/virtio-gpu-3d.c b/hw/display/virtio-gpu-3d.c
index 6fee0e8582..173c9d21e5 100644
--- a/hw/display/virtio-gpu-3d.c
+++ b/hw/display/virtio-gpu-3d.c
@@ -118,11 +118,11 @@ static void virgl_cmd_context_destroy(VirtIOGPU *g,
static void virtio_gpu_rect_update(VirtIOGPU *g, int idx, int x, int y,
int width, int height)
{
- if (!g->scanout[idx].con) {
+ if (!g->parent_obj.scanout[idx].con) {
return;
}
- dpy_gl_update(g->scanout[idx].con, x, y, width, height);
+ dpy_gl_update(g->parent_obj.scanout[idx].con, x, y, width, height);
}
static void virgl_cmd_resource_flush(VirtIOGPU *g,
@@ -135,8 +135,8 @@ static void virgl_cmd_resource_flush(VirtIOGPU *g,
trace_virtio_gpu_cmd_res_flush(rf.resource_id,
rf.r.width, rf.r.height, rf.r.x, rf.r.y);
- for (i = 0; i < g->conf.max_outputs; i++) {
- if (g->scanout[i].resource_id != rf.resource_id) {
+ for (i = 0; i < g->parent_obj.conf.max_outputs; i++) {
+ if (g->parent_obj.scanout[i].resource_id != rf.resource_id) {
continue;
}
virtio_gpu_rect_update(g, i, rf.r.x, rf.r.y, rf.r.width, rf.r.height);
@@ -154,13 +154,13 @@ static void virgl_cmd_set_scanout(VirtIOGPU *g,
trace_virtio_gpu_cmd_set_scanout(ss.scanout_id, ss.resource_id,
ss.r.width, ss.r.height, ss.r.x, ss.r.y);
- if (ss.scanout_id >= g->conf.max_outputs) {
+ if (ss.scanout_id >= g->parent_obj.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;
}
- g->enable = 1;
+ g->parent_obj.enable = 1;
memset(&info, 0, sizeof(info));
@@ -173,20 +173,22 @@ static void virgl_cmd_set_scanout(VirtIOGPU *g,
cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID;
return;
}
- qemu_console_resize(g->scanout[ss.scanout_id].con,
+ qemu_console_resize(g->parent_obj.scanout[ss.scanout_id].con,
ss.r.width, ss.r.height);
virgl_renderer_force_ctx_0();
- dpy_gl_scanout_texture(g->scanout[ss.scanout_id].con, info.tex_id,
- info.flags & 1 /* FIXME: Y_0_TOP */,
- info.width, info.height,
- ss.r.x, ss.r.y, ss.r.width, ss.r.height);
+ dpy_gl_scanout_texture(
+ g->parent_obj.scanout[ss.scanout_id].con, info.tex_id,
+ info.flags & 1 /* FIXME: Y_0_TOP */,
+ info.width, info.height,
+ ss.r.x, ss.r.y, ss.r.width, ss.r.height);
} else {
if (ss.scanout_id != 0) {
- dpy_gfx_replace_surface(g->scanout[ss.scanout_id].con, NULL);
+ dpy_gfx_replace_surface(
+ g->parent_obj.scanout[ss.scanout_id].con, NULL);
}
- dpy_gl_scanout_disable(g->scanout[ss.scanout_id].con);
+ dpy_gl_scanout_disable(g->parent_obj.scanout[ss.scanout_id].con);
}
- g->scanout[ss.scanout_id].resource_id = ss.resource_id;
+ g->parent_obj.scanout[ss.scanout_id].resource_id = ss.resource_id;
}
static void virgl_cmd_submit_3d(VirtIOGPU *g,
@@ -209,7 +211,7 @@ static void virgl_cmd_submit_3d(VirtIOGPU *g,
goto out;
}
- if (virtio_gpu_stats_enabled(g->conf)) {
+ if (virtio_gpu_stats_enabled(g->parent_obj.conf)) {
g->stats.req_3d++;
g->stats.bytes_3d += cs.size;
}
@@ -504,7 +506,7 @@ static void virgl_write_fence(void *opaque, uint32_t fence)
QTAILQ_REMOVE(&g->fenceq, cmd, next);
g_free(cmd);
g->inflight--;
- if (virtio_gpu_stats_enabled(g->conf)) {
+ if (virtio_gpu_stats_enabled(g->parent_obj.conf)) {
fprintf(stderr, "inflight: %3d (-)\r", g->inflight);
}
}
@@ -521,7 +523,7 @@ virgl_create_context(void *opaque, int scanout_idx,
qparams.major_ver = params->major_ver;
qparams.minor_ver = params->minor_ver;
- ctx = dpy_gl_ctx_create(g->scanout[scanout_idx].con, &qparams);
+ ctx = dpy_gl_ctx_create(g->parent_obj.scanout[scanout_idx].con, &qparams);
return (virgl_renderer_gl_context)ctx;
}
@@ -530,7 +532,7 @@ static void virgl_destroy_context(void *opaque,
virgl_renderer_gl_context ctx)
VirtIOGPU *g = opaque;
QEMUGLContext qctx = (QEMUGLContext)ctx;
- dpy_gl_ctx_destroy(g->scanout[0].con, qctx);
+ dpy_gl_ctx_destroy(g->parent_obj.scanout[0].con, qctx);
}
static int virgl_make_context_current(void *opaque, int scanout_idx,
@@ -539,7 +541,8 @@ static int virgl_make_context_current(void *opaque, int
scanout_idx,
VirtIOGPU *g = opaque;
QEMUGLContext qctx = (QEMUGLContext)ctx;
- return dpy_gl_ctx_make_current(g->scanout[scanout_idx].con, qctx);
+ return dpy_gl_ctx_make_current(g->parent_obj.scanout[scanout_idx].con,
+ qctx);
}
static struct virgl_renderer_callbacks virtio_gpu_3d_cbs = {
@@ -591,11 +594,11 @@ void virtio_gpu_virgl_reset(VirtIOGPU *g)
int i;
/* virgl_renderer_reset() ??? */
- for (i = 0; i < g->conf.max_outputs; i++) {
+ for (i = 0; i < g->parent_obj.conf.max_outputs; i++) {
if (i != 0) {
- dpy_gfx_replace_surface(g->scanout[i].con, NULL);
+ dpy_gfx_replace_surface(g->parent_obj.scanout[i].con, NULL);
}
- dpy_gl_scanout_disable(g->scanout[i].con);
+ dpy_gl_scanout_disable(g->parent_obj.scanout[i].con);
}
}
@@ -611,7 +614,7 @@ int virtio_gpu_virgl_init(VirtIOGPU *g)
g->fence_poll = timer_new_ms(QEMU_CLOCK_VIRTUAL,
virtio_gpu_fence_poll, g);
- if (virtio_gpu_stats_enabled(g->conf)) {
+ if (virtio_gpu_stats_enabled(g->parent_obj.conf)) {
g->print_stats = timer_new_ms(QEMU_CLOCK_VIRTUAL,
virtio_gpu_print_stats, g);
timer_mod(g->print_stats, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) +
1000);
diff --git a/hw/display/virtio-gpu-base.c b/hw/display/virtio-gpu-base.c
new file mode 100644
index 0000000000..2619e94304
--- /dev/null
+++ b/hw/display/virtio-gpu-base.c
@@ -0,0 +1,292 @@
+/*
+ * Virtio GPU Device
+ *
+ * Copyright Red Hat, Inc. 2013-2014
+ *
+ * Authors:
+ * Dave Airlie <address@hidden>
+ * Gerd Hoffmann <address@hidden>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+
+#include "hw/virtio/virtio-gpu.h"
+#include "migration/blocker.h"
+#include "qapi/error.h"
+#include "qemu/error-report.h"
+#include "trace.h"
+
+void
+virtio_gpu_base_reset(VirtIOGPUBase *g)
+{
+ int i;
+
+ g->enable = 0;
+ g->use_virgl_renderer = false;
+
+ for (i = 0; i < g->conf.max_outputs; i++) {
+ 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;
+ }
+}
+
+void
+virtio_gpu_base_fill_display_info(VirtIOGPUBase *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 = cpu_to_le32(g->req_state[i].width);
+ dpy_info->pmodes[i].r.height = cpu_to_le32(g->req_state[i].height);
+ }
+ }
+}
+
+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 void virtio_gpu_notify_event(VirtIOGPUBase *g, uint32_t event_type)
+{
+ g->virtio_config.events_read |= event_type;
+ virtio_notify_config(&g->parent_obj);
+}
+
+static int virtio_gpu_ui_info(void *opaque, uint32_t idx, QemuUIInfo *info)
+{
+ VirtIOGPUBase *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;
+}
+
+static void
+virtio_gpu_gl_block(void *opaque, bool block)
+{
+ VirtIOGPUBase *g = opaque;
+ VirtIOGPUBaseClass *vgc = VIRTIO_GPU_BASE_GET_CLASS(g);
+
+ if (block) {
+ g->renderer_blocked++;
+ } else {
+ g->renderer_blocked--;
+ }
+ assert(g->renderer_blocked >= 0);
+ if (g->renderer_blocked == 0) {
+ vgc->gl_unblock(g);
+ }
+}
+
+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,
+ .gl_block = virtio_gpu_gl_block,
+};
+
+bool
+virtio_gpu_base_device_realize(DeviceState *qdev,
+ int num_capsets,
+ VirtIOHandleOutput ctrl_cb,
+ VirtIOHandleOutput cursor_cb,
+ Error **errp)
+{
+ VirtIODevice *vdev = VIRTIO_DEVICE(qdev);
+ VirtIOGPUBase *g = VIRTIO_GPU_BASE(qdev);
+ Error *local_err = NULL;
+ int i;
+
+ if (virtio_host_has_feature(vdev, VIRTIO_F_IOMMU_PLATFORM)) {
+ error_setg(errp, "virtio-gpu does not support vIOMMU yet");
+ return false;
+ }
+
+ if (g->conf.max_outputs > VIRTIO_GPU_MAX_SCANOUTS) {
+ error_setg(errp, "invalid max_outputs > %d", VIRTIO_GPU_MAX_SCANOUTS);
+ return false;
+ }
+
+ g->use_virgl_renderer = false;
+ if (virtio_gpu_virgl_enabled(g->conf)) {
+ error_setg(&g->migration_blocker, "virgl is not yet migratable");
+ migrate_add_blocker(g->migration_blocker, &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ error_free(g->migration_blocker);
+ return false;
+ }
+ }
+
+ g->virtio_config.num_scanouts = cpu_to_le32(g->conf.max_outputs);
+ virtio_init(VIRTIO_DEVICE(g), "virtio-gpu", VIRTIO_ID_GPU,
+ sizeof(struct virtio_gpu_config));
+
+ if (virtio_gpu_virgl_enabled(g->conf)) {
+ /* use larger control queue in 3d mode */
+ virtio_add_queue(vdev, 256, ctrl_cb);
+ virtio_add_queue(vdev, 16, cursor_cb);
+ g->virtio_config.num_capsets = num_capsets;
+ } else {
+ virtio_add_queue(vdev, 64, ctrl_cb);
+ virtio_add_queue(vdev, 16, cursor_cb);
+ }
+
+ g->enabled_output_bitmask = 1;
+
+ g->req_state[0].width = g->conf.xres;
+ g->req_state[0].height = g->conf.yres;
+
+ for (i = 0; i < g->conf.max_outputs; i++) {
+ g->scanout[i].con =
+ graphic_console_init(DEVICE(g), i, &virtio_gpu_ops, g);
+ if (i > 0) {
+ dpy_gfx_replace_surface(g->scanout[i].con, NULL);
+ }
+ }
+
+ return true;
+}
+
+static void
+virtio_gpu_base_get_config(VirtIODevice *vdev, uint8_t *config)
+{
+ VirtIOGPUBase *g = VIRTIO_GPU_BASE(vdev);
+ memcpy(config, &g->virtio_config, sizeof(g->virtio_config));
+}
+
+static void
+virtio_gpu_base_set_config(VirtIODevice *vdev, const uint8_t *config)
+{
+ VirtIOGPUBase *g = VIRTIO_GPU_BASE(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_base_get_features(VirtIODevice *vdev, uint64_t features,
+ Error **errp)
+{
+ VirtIOGPUBase *g = VIRTIO_GPU_BASE(vdev);
+
+ if (virtio_gpu_virgl_enabled(g->conf)) {
+ features |= (1 << VIRTIO_GPU_F_VIRGL);
+ }
+ return features;
+}
+
+static void
+virtio_gpu_base_set_features(VirtIODevice *vdev, uint64_t features)
+{
+ static const uint32_t virgl = (1 << VIRTIO_GPU_F_VIRGL);
+ VirtIOGPUBase *g = VIRTIO_GPU_BASE(vdev);
+
+ g->use_virgl_renderer = ((features & virgl) == virgl);
+ trace_virtio_gpu_features(g->use_virgl_renderer);
+}
+
+static void
+virtio_gpu_base_device_unrealize(DeviceState *qdev, Error **errp)
+{
+ VirtIOGPUBase *g = VIRTIO_GPU_BASE(qdev);
+
+ if (g->migration_blocker) {
+ migrate_del_blocker(g->migration_blocker);
+ error_free(g->migration_blocker);
+ }
+}
+
+static void
+virtio_gpu_base_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
+
+ vdc->unrealize = virtio_gpu_base_device_unrealize;
+ vdc->get_features = virtio_gpu_base_get_features;
+ vdc->set_features = virtio_gpu_base_set_features;
+ vdc->get_config = virtio_gpu_base_get_config;
+ vdc->set_config = virtio_gpu_base_set_config;
+
+ set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories);
+ dc->hotpluggable = false;
+}
+
+static const TypeInfo virtio_gpu_base_info = {
+ .name = TYPE_VIRTIO_GPU_BASE,
+ .parent = TYPE_VIRTIO_DEVICE,
+ .instance_size = sizeof(VirtIOGPUBase),
+ .class_size = sizeof(VirtIOGPUBaseClass),
+ .class_init = virtio_gpu_base_class_init,
+ .abstract = true
+};
+
+static void
+virtio_register_types(void)
+{
+ type_register_static(&virtio_gpu_base_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);
+
+QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_transfer_host_3d) != 72);
+QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_resource_create_3d) != 72);
+QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_ctx_create) != 96);
+QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_ctx_destroy) != 24);
+QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_ctx_resource) != 32);
+QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_cmd_submit) != 32);
+QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_get_capset_info) != 32);
+QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_resp_capset_info) != 40);
+QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_get_capset) != 32);
+QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_resp_capset) != 24);
diff --git a/hw/display/virtio-gpu-pci.c b/hw/display/virtio-gpu-pci.c
index cece4aa495..741badd909 100644
--- a/hw/display/virtio-gpu-pci.c
+++ b/hw/display/virtio-gpu-pci.c
@@ -27,7 +27,7 @@ static Property virtio_gpu_pci_properties[] = {
static void virtio_gpu_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp)
{
VirtIOGPUPCI *vgpu = VIRTIO_GPU_PCI(vpci_dev);
- VirtIOGPU *g = &vgpu->vdev;
+ VirtIOGPUBase *g = VIRTIO_GPU_BASE(&vgpu->vdev);
DeviceState *vdev = DEVICE(&vgpu->vdev);
int i;
Error *local_error = NULL;
diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
index b83982b0a3..8609cb6eeb 100644
--- a/hw/display/virtio-gpu.c
+++ b/hw/display/virtio-gpu.c
@@ -21,9 +21,9 @@
#include "hw/virtio/virtio-gpu.h"
#include "hw/virtio/virtio-gpu-bswap.h"
#include "hw/virtio/virtio-bus.h"
-#include "migration/blocker.h"
#include "qemu/log.h"
#include "qapi/error.h"
+#include "qemu/error-report.h"
#define VIRTIO_GPU_VM_VERSION 1
@@ -36,7 +36,7 @@ static void virtio_gpu_cleanup_mapping(struct
virtio_gpu_simple_resource *res);
#include <virglrenderer.h>
#define VIRGL(_g, _virgl, _simple, ...) \
do { \
- if (_g->use_virgl_renderer) { \
+ if (_g->parent_obj.use_virgl_renderer) { \
_virgl(__VA_ARGS__); \
} else { \
_simple(__VA_ARGS__); \
@@ -104,10 +104,10 @@ static void update_cursor(VirtIOGPU *g, struct
virtio_gpu_update_cursor *cursor)
struct virtio_gpu_scanout *s;
bool move = cursor->hdr.type == VIRTIO_GPU_CMD_MOVE_CURSOR;
- if (cursor->pos.scanout_id >= g->conf.max_outputs) {
+ if (cursor->pos.scanout_id >= g->parent_obj.conf.max_outputs) {
return;
}
- s = &g->scanout[cursor->pos.scanout_id];
+ s = &g->parent_obj.scanout[cursor->pos.scanout_id];
trace_virtio_gpu_update_cursor(cursor->pos.scanout_id,
cursor->pos.x,
@@ -138,50 +138,6 @@ static void update_cursor(VirtIOGPU *g, struct
virtio_gpu_update_cursor *cursor)
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,
- Error **errp)
-{
- VirtIOGPU *g = VIRTIO_GPU(vdev);
-
- if (virtio_gpu_virgl_enabled(g->conf)) {
- features |= (1 << VIRTIO_GPU_F_VIRGL);
- }
- return features;
-}
-
-static void virtio_gpu_set_features(VirtIODevice *vdev, uint64_t features)
-{
- static const uint32_t virgl = (1 << VIRTIO_GPU_F_VIRGL);
- VirtIOGPU *g = VIRTIO_GPU(vdev);
-
- g->use_virgl_renderer = ((features & virgl) == virgl);
- trace_virtio_gpu_features(g->use_virgl_renderer);
-}
-
-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)
{
@@ -230,21 +186,6 @@ void virtio_gpu_ctrl_response_nodata(VirtIOGPU *g,
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 = cpu_to_le32(g->req_state[i].width);
- dpy_info->pmodes[i].r.height = cpu_to_le32(g->req_state[i].height);
- }
- }
-}
-
void virtio_gpu_get_display_info(VirtIOGPU *g,
struct virtio_gpu_ctrl_command *cmd)
{
@@ -253,7 +194,7 @@ void virtio_gpu_get_display_info(VirtIOGPU *g,
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_base_fill_display_info(VIRTIO_GPU_BASE(g), &display_info);
virtio_gpu_ctrl_response(g, cmd, &display_info.hdr,
sizeof(display_info));
}
@@ -339,7 +280,7 @@ static void virtio_gpu_resource_create_2d(VirtIOGPU *g,
}
res->hostmem = calc_image_hostmem(pformat, c2d.width, c2d.height);
- if (res->hostmem + g->hostmem < g->conf.max_hostmem) {
+ if (res->hostmem + g->hostmem < g->conf_max_hostmem) {
res->image = pixman_image_create_bits(pformat,
c2d.width,
c2d.height,
@@ -361,7 +302,7 @@ static void virtio_gpu_resource_create_2d(VirtIOGPU *g,
static void virtio_gpu_disable_scanout(VirtIOGPU *g, int scanout_id)
{
- struct virtio_gpu_scanout *scanout = &g->scanout[scanout_id];
+ struct virtio_gpu_scanout *scanout = &g->parent_obj.scanout[scanout_id];
struct virtio_gpu_simple_resource *res;
DisplaySurface *ds = NULL;
@@ -393,7 +334,7 @@ static void virtio_gpu_resource_destroy(VirtIOGPU *g,
int i;
if (res->scanout_bitmask) {
- for (i = 0; i < g->conf.max_outputs; i++) {
+ for (i = 0; i < g->parent_obj.conf.max_outputs; i++) {
if (res->scanout_bitmask & (1 << i)) {
virtio_gpu_disable_scanout(g, i);
}
@@ -523,7 +464,7 @@ static void virtio_gpu_resource_flush(VirtIOGPU *g,
pixman_region_init_rect(&flush_region,
rf.r.x, rf.r.y, rf.r.width, rf.r.height);
- for (i = 0; i < g->conf.max_outputs; i++) {
+ for (i = 0; i < g->parent_obj.conf.max_outputs; i++) {
struct virtio_gpu_scanout *scanout;
pixman_region16_t region, finalregion;
pixman_box16_t *extents;
@@ -531,7 +472,7 @@ static void virtio_gpu_resource_flush(VirtIOGPU *g,
if (!(res->scanout_bitmask & (1 << i))) {
continue;
}
- scanout = &g->scanout[i];
+ scanout = &g->parent_obj.scanout[i];
pixman_region_init(&finalregion);
pixman_region_init_rect(®ion, scanout->x, scanout->y,
@@ -541,7 +482,7 @@ static void virtio_gpu_resource_flush(VirtIOGPU *g,
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,
+ dpy_gfx_update(g->parent_obj.scanout[i].con,
extents->x1, extents->y1,
extents->x2 - extents->x1,
extents->y2 - extents->y1);
@@ -572,14 +513,14 @@ static void virtio_gpu_set_scanout(VirtIOGPU *g,
trace_virtio_gpu_cmd_set_scanout(ss.scanout_id, ss.resource_id,
ss.r.width, ss.r.height, ss.r.x, ss.r.y);
- if (ss.scanout_id >= g->conf.max_outputs) {
+ if (ss.scanout_id >= g->parent_obj.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;
}
- g->enable = 1;
+ g->parent_obj.enable = 1;
if (ss.resource_id == 0) {
virtio_gpu_disable_scanout(g, ss.scanout_id);
return;
@@ -608,7 +549,7 @@ static void virtio_gpu_set_scanout(VirtIOGPU *g,
return;
}
- scanout = &g->scanout[ss.scanout_id];
+ scanout = &g->parent_obj.scanout[ss.scanout_id];
format = pixman_image_get_format(res->image);
bpp = DIV_ROUND_UP(PIXMAN_FORMAT_BPP(format), 8);
@@ -631,7 +572,8 @@ static void virtio_gpu_set_scanout(VirtIOGPU *g,
return;
}
pixman_image_unref(rect);
- dpy_gfx_replace_surface(g->scanout[ss.scanout_id].con, scanout->ds);
+ dpy_gfx_replace_surface(g->parent_obj.scanout[ss.scanout_id].con,
+ scanout->ds);
}
ores = virtio_gpu_find_resource(g, scanout->resource_id);
@@ -840,7 +782,7 @@ void virtio_gpu_process_cmdq(VirtIOGPU *g)
while (!QTAILQ_EMPTY(&g->cmdq)) {
cmd = QTAILQ_FIRST(&g->cmdq);
- if (g->renderer_blocked) {
+ if (g->parent_obj.renderer_blocked) {
break;
}
@@ -849,14 +791,14 @@ void virtio_gpu_process_cmdq(VirtIOGPU *g)
g, cmd);
QTAILQ_REMOVE(&g->cmdq, cmd, next);
- if (virtio_gpu_stats_enabled(g->conf)) {
+ if (virtio_gpu_stats_enabled(g->parent_obj.conf)) {
g->stats.requests++;
}
if (!cmd->finished) {
QTAILQ_INSERT_TAIL(&g->fenceq, cmd, next);
g->inflight++;
- if (virtio_gpu_stats_enabled(g->conf)) {
+ if (virtio_gpu_stats_enabled(g->parent_obj.conf)) {
if (g->stats.max_inflight < g->inflight) {
g->stats.max_inflight = g->inflight;
}
@@ -868,6 +810,11 @@ void virtio_gpu_process_cmdq(VirtIOGPU *g)
}
}
+static void virtio_gpu_gl_unblock(VirtIOGPUBase *g)
+{
+ virtio_gpu_process_cmdq(VIRTIO_GPU(g));
+}
+
static void virtio_gpu_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq)
{
VirtIOGPU *g = VIRTIO_GPU(vdev);
@@ -878,7 +825,7 @@ static void virtio_gpu_handle_ctrl(VirtIODevice *vdev,
VirtQueue *vq)
}
#ifdef CONFIG_VIRGL
- if (!g->renderer_inited && g->use_virgl_renderer) {
+ if (!g->renderer_inited && g->parent_obj.use_virgl_renderer) {
virtio_gpu_virgl_init(g);
g->renderer_inited = true;
}
@@ -896,7 +843,7 @@ static void virtio_gpu_handle_ctrl(VirtIODevice *vdev,
VirtQueue *vq)
virtio_gpu_process_cmdq(g);
#ifdef CONFIG_VIRGL
- if (g->use_virgl_renderer) {
+ if (g->parent_obj.use_virgl_renderer) {
virtio_gpu_virgl_fence_poll(g);
}
#endif
@@ -905,7 +852,7 @@ static void virtio_gpu_handle_ctrl(VirtIODevice *vdev,
VirtQueue *vq)
static void virtio_gpu_ctrl_bh(void *opaque)
{
VirtIOGPU *g = opaque;
- virtio_gpu_handle_ctrl(&g->parent_obj, g->ctrl_vq);
+ virtio_gpu_handle_ctrl(&g->parent_obj.parent_obj, g->ctrl_vq);
}
static void virtio_gpu_handle_cursor(VirtIODevice *vdev, VirtQueue *vq)
@@ -943,71 +890,9 @@ static void virtio_gpu_handle_cursor(VirtIODevice *vdev,
VirtQueue *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;
+ virtio_gpu_handle_cursor(&g->parent_obj.parent_obj, g->cursor_vq);
}
-static void virtio_gpu_gl_block(void *opaque, bool block)
-{
- VirtIOGPU *g = opaque;
-
- if (block) {
- g->renderer_blocked++;
- } else {
- g->renderer_blocked--;
- }
- assert(g->renderer_blocked >= 0);
-
- if (g->renderer_blocked == 0) {
- virtio_gpu_process_cmdq(g);
- }
-}
-
-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,
-#ifdef CONFIG_VIRGL
- .gl_block = virtio_gpu_gl_block,
-#endif
-};
-
static const VMStateDescription vmstate_virtio_gpu_scanout = {
.name = "virtio-gpu-one-scanout",
.version_id = 1,
@@ -1030,10 +915,11 @@ static const VMStateDescription
vmstate_virtio_gpu_scanouts = {
.name = "virtio-gpu-scanouts",
.version_id = 1,
.fields = (VMStateField[]) {
- VMSTATE_INT32(enable, struct VirtIOGPU),
- VMSTATE_UINT32_EQUAL(conf.max_outputs, struct VirtIOGPU, NULL),
- VMSTATE_STRUCT_VARRAY_UINT32(scanout, struct VirtIOGPU,
- conf.max_outputs, 1,
+ VMSTATE_INT32(parent_obj.enable, struct VirtIOGPU),
+ VMSTATE_UINT32_EQUAL(parent_obj.conf.max_outputs,
+ struct VirtIOGPU, NULL),
+ VMSTATE_STRUCT_VARRAY_UINT32(parent_obj.scanout, struct VirtIOGPU,
+ parent_obj.conf.max_outputs, 1,
vmstate_virtio_gpu_scanout,
struct virtio_gpu_scanout),
VMSTATE_END_OF_LIST()
@@ -1143,8 +1029,8 @@ static int virtio_gpu_load(QEMUFile *f, void *opaque,
size_t size,
/* load & apply scanout state */
vmstate_load_state(f, &vmstate_virtio_gpu_scanouts, g, 1);
- for (i = 0; i < g->conf.max_outputs; i++) {
- scanout = &g->scanout[i];
+ for (i = 0; i < g->parent_obj.conf.max_outputs; i++) {
+ scanout = &g->parent_obj.scanout[i];
if (!scanout->resource_id) {
continue;
}
@@ -1173,117 +1059,54 @@ static void virtio_gpu_device_realize(DeviceState
*qdev, Error **errp)
VirtIODevice *vdev = VIRTIO_DEVICE(qdev);
VirtIOGPU *g = VIRTIO_GPU(qdev);
bool have_virgl;
- Error *local_err = NULL;
- int i;
+ int num_capsets = 0;
- if (virtio_host_has_feature(vdev, VIRTIO_F_IOMMU_PLATFORM)) {
- error_setg(errp, "virtio-gpu does not support vIOMMU yet");
- return;
- }
-
- if (g->conf.max_outputs > VIRTIO_GPU_MAX_SCANOUTS) {
- error_setg(errp, "invalid max_outputs > %d", VIRTIO_GPU_MAX_SCANOUTS);
- return;
- }
-
- g->use_virgl_renderer = false;
#if !defined(CONFIG_VIRGL) || defined(HOST_WORDS_BIGENDIAN)
have_virgl = false;
#else
have_virgl = display_opengl;
#endif
if (!have_virgl) {
- g->conf.flags &= ~(1 << VIRTIO_GPU_FLAG_VIRGL_ENABLED);
- }
-
- if (virtio_gpu_virgl_enabled(g->conf)) {
- error_setg(&g->migration_blocker, "virgl is not yet migratable");
- migrate_add_blocker(g->migration_blocker, &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
- error_free(g->migration_blocker);
- return;
- }
+ g->parent_obj.conf.flags &= ~(1 << VIRTIO_GPU_FLAG_VIRGL_ENABLED);
}
- g->virtio_config.num_scanouts = cpu_to_le32(g->conf.max_outputs);
- virtio_init(VIRTIO_DEVICE(g), "virtio-gpu", VIRTIO_ID_GPU,
- sizeof(struct virtio_gpu_config));
-
- g->req_state[0].width = g->conf.xres;
- g->req_state[0].height = g->conf.yres;
-
- if (virtio_gpu_virgl_enabled(g->conf)) {
- /* use larger control queue in 3d mode */
- g->ctrl_vq = virtio_add_queue(vdev, 256, virtio_gpu_handle_ctrl_cb);
- g->cursor_vq = virtio_add_queue(vdev, 16, virtio_gpu_handle_cursor_cb);
-
#if defined(CONFIG_VIRGL)
- g->virtio_config.num_capsets = virtio_gpu_virgl_get_num_capsets(g);
-#else
- g->virtio_config.num_capsets = 0;
+ num_capsets = virtio_gpu_virgl_get_num_capsets(g);
#endif
- } else {
- g->ctrl_vq = virtio_add_queue(vdev, 64, virtio_gpu_handle_ctrl_cb);
- g->cursor_vq = virtio_add_queue(vdev, 16, virtio_gpu_handle_cursor_cb);
+
+ if (!virtio_gpu_base_device_realize(qdev,
+ num_capsets,
+ virtio_gpu_handle_ctrl_cb,
+ virtio_gpu_handle_cursor_cb,
+ errp)) {
+ return;
}
+ g->ctrl_vq = virtio_get_queue(vdev, 0);
+ g->cursor_vq = virtio_get_queue(vdev, 1);
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->cmdq);
QTAILQ_INIT(&g->fenceq);
-
- g->enabled_output_bitmask = 1;
-
- for (i = 0; i < g->conf.max_outputs; i++) {
- g->scanout[i].con =
- graphic_console_init(DEVICE(g), i, &virtio_gpu_ops, g);
- if (i > 0) {
- dpy_gfx_replace_surface(g->scanout[i].con, NULL);
- }
- }
-}
-
-static void virtio_gpu_device_unrealize(DeviceState *qdev, Error **errp)
-{
- VirtIOGPU *g = VIRTIO_GPU(qdev);
- if (g->migration_blocker) {
- migrate_del_blocker(g->migration_blocker);
- error_free(g->migration_blocker);
- }
-}
-
-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;
+#ifdef CONFIG_VIRGL
+ if (g->parent_obj.use_virgl_renderer) {
+ virtio_gpu_virgl_reset(g);
+ }
+#endif
QTAILQ_FOREACH_SAFE(res, &g->reslist, next, tmp) {
virtio_gpu_resource_destroy(g, res);
}
- for (i = 0; i < g->conf.max_outputs; i++) {
- 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;
- }
-#ifdef CONFIG_VIRGL
- if (g->use_virgl_renderer) {
- virtio_gpu_virgl_reset(g);
- g->use_virgl_renderer = 0;
- }
-#endif
+ virtio_gpu_base_reset(VIRTIO_GPU_BASE(vdev));
}
/*
@@ -1314,16 +1137,15 @@ static const VMStateDescription vmstate_virtio_gpu = {
};
static Property virtio_gpu_properties[] = {
- DEFINE_PROP_UINT32("max_outputs", VirtIOGPU, conf.max_outputs, 1),
- DEFINE_PROP_SIZE("max_hostmem", VirtIOGPU, conf.max_hostmem, 256 * MiB),
+ VIRTIO_GPU_BASE_PROPERTIES(VirtIOGPU, parent_obj.conf),
+ DEFINE_PROP_SIZE("max_hostmem", VirtIOGPU, conf_max_hostmem,
+ 256 * MiB),
#ifdef CONFIG_VIRGL
- DEFINE_PROP_BIT("virgl", VirtIOGPU, conf.flags,
+ DEFINE_PROP_BIT("virgl", VirtIOGPU, parent_obj.conf.flags,
VIRTIO_GPU_FLAG_VIRGL_ENABLED, true),
- DEFINE_PROP_BIT("stats", VirtIOGPU, conf.flags,
+ DEFINE_PROP_BIT("stats", VirtIOGPU, parent_obj.conf.flags,
VIRTIO_GPU_FLAG_STATS_ENABLED, false),
#endif
- DEFINE_PROP_UINT32("xres", VirtIOGPU, conf.xres, 1024),
- DEFINE_PROP_UINT32("yres", VirtIOGPU, conf.yres, 768),
DEFINE_PROP_END_OF_LIST(),
};
@@ -1331,27 +1153,20 @@ static void virtio_gpu_class_init(ObjectClass *klass,
void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
+ VirtIOGPUBaseClass *vgc = VIRTIO_GPU_BASE_CLASS(klass);
+ vgc->gl_unblock = virtio_gpu_gl_unblock;
vdc->realize = virtio_gpu_device_realize;
- vdc->unrealize = virtio_gpu_device_unrealize;
- 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;
- set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories);
- dc->props = virtio_gpu_properties;
dc->vmsd = &vmstate_virtio_gpu;
- dc->hotpluggable = false;
+ dc->props = virtio_gpu_properties;
}
static const TypeInfo virtio_gpu_info = {
.name = TYPE_VIRTIO_GPU,
- .parent = TYPE_VIRTIO_DEVICE,
+ .parent = TYPE_VIRTIO_GPU_BASE,
.instance_size = sizeof(VirtIOGPU),
- .instance_init = virtio_gpu_instance_init,
.class_init = virtio_gpu_class_init,
};
@@ -1361,26 +1176,3 @@ static void virtio_register_types(void)
}
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);
-
-QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_transfer_host_3d) != 72);
-QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_resource_create_3d) != 72);
-QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_ctx_create) != 96);
-QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_ctx_destroy) != 24);
-QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_ctx_resource) != 32);
-QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_cmd_submit) != 32);
-QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_get_capset_info) != 32);
-QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_resp_capset_info) != 40);
-QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_get_capset) != 32);
-QEMU_BUILD_BUG_ON(sizeof(struct virtio_gpu_resp_capset) != 24);
diff --git a/hw/display/virtio-vga.c b/hw/display/virtio-vga.c
index 8d3d9e14a7..00939b7e0c 100644
--- a/hw/display/virtio-vga.c
+++ b/hw/display/virtio-vga.c
@@ -22,8 +22,9 @@ typedef struct VirtIOVGA {
static void virtio_vga_invalidate_display(void *opaque)
{
VirtIOVGA *vvga = opaque;
+ VirtIOGPUBase *g = VIRTIO_GPU_BASE(&vvga->vdev);
- if (vvga->vdev.enable) {
+ if (g->enable) {
virtio_gpu_ops.invalidate(&vvga->vdev);
} else {
vvga->vga.hw_ops->invalidate(&vvga->vga);
@@ -33,8 +34,9 @@ static void virtio_vga_invalidate_display(void *opaque)
static void virtio_vga_update_display(void *opaque)
{
VirtIOVGA *vvga = opaque;
+ VirtIOGPUBase *g = VIRTIO_GPU_BASE(&vvga->vdev);
- if (vvga->vdev.enable) {
+ if (g->enable) {
virtio_gpu_ops.gfx_update(&vvga->vdev);
} else {
vvga->vga.hw_ops->gfx_update(&vvga->vga);
@@ -44,8 +46,9 @@ static void virtio_vga_update_display(void *opaque)
static void virtio_vga_text_update(void *opaque, console_ch_t *chardata)
{
VirtIOVGA *vvga = opaque;
+ VirtIOGPUBase *g = VIRTIO_GPU_BASE(&vvga->vdev);
- if (vvga->vdev.enable) {
+ if (g->enable) {
if (virtio_gpu_ops.text_update) {
virtio_gpu_ops.text_update(&vvga->vdev, chardata);
}
@@ -98,7 +101,7 @@ static const VMStateDescription vmstate_virtio_vga = {
static void virtio_vga_realize(VirtIOPCIProxy *vpci_dev, Error **errp)
{
VirtIOVGA *vvga = VIRTIO_VGA(vpci_dev);
- VirtIOGPU *g = &vvga->vdev;
+ VirtIOGPUBase *g = VIRTIO_GPU_BASE(&vvga->vdev);
VGACommonState *vga = &vvga->vga;
Error *err = NULL;
uint32_t offset;
@@ -168,7 +171,9 @@ static void virtio_vga_realize(VirtIOPCIProxy *vpci_dev,
Error **errp)
static void virtio_vga_reset(DeviceState *dev)
{
VirtIOVGA *vvga = VIRTIO_VGA(dev);
- vvga->vdev.enable = 0;
+ VirtIOGPUBase *g = VIRTIO_GPU_BASE(&vvga->vdev);
+
+ g->enable = 0;
vga_dirty_log_start(&vvga->vga);
}
diff --git a/hw/display/Makefile.objs b/hw/display/Makefile.objs
index fb8408c6d0..5e60015b77 100644
--- a/hw/display/Makefile.objs
+++ b/hw/display/Makefile.objs
@@ -39,7 +39,7 @@ obj-$(CONFIG_VGA) += vga.o
common-obj-$(CONFIG_QXL) += qxl.o qxl-logger.o qxl-render.o
-obj-$(CONFIG_VIRTIO_GPU) += virtio-gpu.o virtio-gpu-3d.o
+obj-$(CONFIG_VIRTIO_GPU) += virtio-gpu-base.o virtio-gpu.o virtio-gpu-3d.o
obj-$(call land,$(CONFIG_VIRTIO_GPU),$(CONFIG_VIRTIO_PCI)) += virtio-gpu-pci.o
obj-$(CONFIG_VIRTIO_VGA) += virtio-vga.o
virtio-gpu.o-cflags := $(VIRGL_CFLAGS)
--
2.18.0.129.ge3331758f1
- [Qemu-devel] [PATCH v4 19/29] util: promote qemu_egl_rendernode_open() to libqemuutil, (continued)
- [Qemu-devel] [PATCH v4 19/29] util: promote qemu_egl_rendernode_open() to libqemuutil, Marc-André Lureau, 2018/07/13
- [Qemu-devel] [PATCH v4 21/29] util: use fcntl() for qemu_write_pidfile() locking, Marc-André Lureau, 2018/07/13
- [Qemu-devel] [PATCH v4 20/29] util: add qemu_write_pidfile(), Marc-André Lureau, 2018/07/13
- [Qemu-devel] [PATCH v4 23/29] virtio-gpu: remove unused qdev, Marc-André Lureau, 2018/07/13
- [Qemu-devel] [PATCH v4 25/29] virtio-gpu: block both 2d and 3d rendering, Marc-André Lureau, 2018/07/13
- [Qemu-devel] [PATCH v4 24/29] virtio-gpu: remove unused config_size, Marc-André Lureau, 2018/07/13
- [Qemu-devel] [PATCH v4 22/29] contrib: add vhost-user-gpu, Marc-André Lureau, 2018/07/13
- [Qemu-devel] [PATCH v4 26/29] virtio-gpu: remove useless 'waiting' field, Marc-André Lureau, 2018/07/13
- [Qemu-devel] [PATCH v4 28/29] virtio-gpu: split virtio-gpu-pci & virtio-vga, Marc-André Lureau, 2018/07/13
- [Qemu-devel] [PATCH v4 29/29] hw/display: add vhost-user-vga & gpu-pci, Marc-André Lureau, 2018/07/13
- [Qemu-devel] [PATCH v4 27/29] virtio-gpu: split virtio-gpu, introduce virtio-gpu-base,
Marc-André Lureau <=