mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
virtio-gpu: split virtio-gpu, introduce virtio-gpu-base
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 <marcandre.lureau@redhat.com> Message-id: 20190524130946.31736-8-marcandre.lureau@redhat.com Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
This commit is contained in:
committed by
Gerd Hoffmann
parent
cb0efb7125
commit
50d8e25ea6
@@ -43,7 +43,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)
|
||||
|
||||
+26
-23
@@ -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;
|
||||
}
|
||||
@@ -507,7 +509,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);
|
||||
}
|
||||
}
|
||||
@@ -524,7 +526,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;
|
||||
}
|
||||
|
||||
@@ -533,7 +535,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,
|
||||
@@ -542,7 +544,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 = {
|
||||
@@ -594,11 +597,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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -614,7 +617,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);
|
||||
|
||||
@@ -0,0 +1,268 @@
|
||||
/*
|
||||
* 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 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,
|
||||
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 (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);
|
||||
} 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 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);
|
||||
}
|
||||
if (virtio_gpu_edid_enabled(g->conf)) {
|
||||
features |= (1 << VIRTIO_GPU_F_EDID);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
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);
|
||||
@@ -41,7 +41,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;
|
||||
|
||||
+102
-276
File diff suppressed because it is too large
Load Diff
@@ -32,8 +32,9 @@ typedef struct VirtIOVGAClass {
|
||||
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);
|
||||
@@ -43,8 +44,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);
|
||||
@@ -54,8 +56,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);
|
||||
}
|
||||
@@ -108,7 +111,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;
|
||||
|
||||
@@ -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,
|
||||
VIRTIO_GPU_FLAG_EDID_ENABLED,
|
||||
@@ -71,8 +79,7 @@ enum virtio_gpu_conf_flags {
|
||||
#define virtio_gpu_edid_enabled(_cfg) \
|
||||
(_cfg.flags & (1 << VIRTIO_GPU_FLAG_EDID_ENABLED))
|
||||
|
||||
struct virtio_gpu_conf {
|
||||
uint64_t max_hostmem;
|
||||
struct virtio_gpu_base_conf {
|
||||
uint32_t max_outputs;
|
||||
uint32_t flags;
|
||||
uint32_t xres;
|
||||
@@ -88,31 +95,55 @@ 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_BIT("edid", _state, _conf.flags, \
|
||||
VIRTIO_GPU_FLAG_EDID_ENABLED, false), \
|
||||
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;
|
||||
bool renderer_reset;
|
||||
QEMUTimer *fence_poll;
|
||||
QEMUTimer *print_stats;
|
||||
@@ -124,8 +155,6 @@ typedef struct VirtIOGPU {
|
||||
uint32_t req_3d;
|
||||
uint32_t bytes_3d;
|
||||
} stats;
|
||||
|
||||
Error *migration_blocker;
|
||||
} VirtIOGPU;
|
||||
|
||||
extern const GraphicHwOps virtio_gpu_ops;
|
||||
@@ -148,6 +177,15 @@ extern const GraphicHwOps virtio_gpu_ops;
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/* virtio-gpu-base.c */
|
||||
bool virtio_gpu_base_device_realize(DeviceState *qdev,
|
||||
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,
|
||||
@@ -175,4 +213,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
|
||||
|
||||
Reference in New Issue
Block a user