customize refresh rate and resolution for the guest VM instead of being limited by the actual resolution of the host.
add edid info and modify conf like: "-device", "virtio-vga-gl,edid=on,max_outputs=2, refresh_rate0=120000,maxx0=7680,maxy0=1080,refresh_rate1=75000, maxx1=3840,maxy1=960" Change-Id: I5d5742d280186ffd5dee9eba7697f06a2b09b123 Signed-off-by: Lei Huang <lei.hu...@amd.com> --- hw/display/virtio-gpu-base.c | 41 ++++++++++++++++++++++++++++------ hw/display/virtio-gpu.c | 1 + include/hw/virtio/virtio-gpu.h | 26 +++++++++++++++++++++ 3 files changed, 61 insertions(+), 7 deletions(-) diff --git a/hw/display/virtio-gpu-base.c b/hw/display/virtio-gpu-base.c index 4fc7ef8896c..80d22005447 100644 --- a/hw/display/virtio-gpu-base.c +++ b/hw/display/virtio-gpu-base.c @@ -46,8 +46,18 @@ virtio_gpu_base_fill_display_info(VirtIOGPUBase *g, 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); + if (g->edid_info[i].maxx && g->edid_info[i].maxy && + virtio_gpu_edid_enabled(g->conf)) { + dpy_info->pmodes[i].r.width = + cpu_to_le32(g->edid_info[i].maxx); + dpy_info->pmodes[i].r.height = + cpu_to_le32(g->edid_info[i].maxy); + } else { + 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); + } } } } @@ -62,6 +72,8 @@ virtio_gpu_base_generate_edid(VirtIOGPUBase *g, int scanout, .prefx = g->req_state[scanout].width, .prefy = g->req_state[scanout].height, .refresh_rate = g->req_state[scanout].refresh_rate, + .maxx = g->req_state[scanout].width, + .maxy = g->req_state[scanout].height, }; edid->size = cpu_to_le32(sizeof(edid->edid)); @@ -96,9 +108,16 @@ static void virtio_gpu_ui_info(void *opaque, uint32_t idx, QemuUIInfo *info) g->req_state[idx].x = info->xoff; g->req_state[idx].y = info->yoff; - g->req_state[idx].refresh_rate = info->refresh_rate; - g->req_state[idx].width = info->width; - g->req_state[idx].height = info->height; + if (!g->edid_info[idx].refresh_rate) { + g->req_state[idx].refresh_rate = info->refresh_rate; + } + if (!g->edid_info[idx].maxx) { + g->req_state[idx].width = info->width; + } + if (!g->edid_info[idx].maxy) { + g->req_state[idx].height = info->height; + } + g->req_state[idx].width_mm = info->width_mm; g->req_state[idx].height_mm = info->height_mm; @@ -204,11 +223,19 @@ virtio_gpu_base_device_realize(DeviceState *qdev, g->enabled_output_bitmask = 1; - g->req_state[0].width = g->conf.xres; - g->req_state[0].height = g->conf.yres; g->hw_ops = &virtio_gpu_ops; for (i = 0; i < g->conf.max_outputs; i++) { + if (g->edid_info[i].maxx && g->edid_info[i].maxy && + virtio_gpu_edid_enabled(g->conf) && + g->edid_info[i].refresh_rate) { + g->req_state[i].refresh_rate = g->edid_info[i].refresh_rate; + g->req_state[i].width = g->edid_info[i].maxx; + g->req_state[i].height = g->edid_info[i].maxy; + } else { + g->req_state[i].width = g->conf.xres; + g->req_state[i].height = g->conf.yres; + } g->scanout[i].con = graphic_console_init(DEVICE(g), i, &virtio_gpu_ops, g); } diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c index 3281842bfe1..dd759a80522 100644 --- a/hw/display/virtio-gpu.c +++ b/hw/display/virtio-gpu.c @@ -1666,6 +1666,7 @@ static const VMStateDescription vmstate_virtio_gpu = { static Property virtio_gpu_properties[] = { VIRTIO_GPU_BASE_PROPERTIES(VirtIOGPU, parent_obj.conf), + VIRTIO_GPU_EDID_PROPERTIES_MULTI_DISPLAY(VirtIOGPU, parent_obj.edid_info), DEFINE_PROP_SIZE("max_hostmem", VirtIOGPU, conf_max_hostmem, 256 * MiB), DEFINE_PROP_BIT("blob", VirtIOGPU, parent_obj.conf.flags, diff --git a/include/hw/virtio/virtio-gpu.h b/include/hw/virtio/virtio-gpu.h index 7a59379f5a7..61c69735dba 100644 --- a/include/hw/virtio/virtio-gpu.h +++ b/include/hw/virtio/virtio-gpu.h @@ -18,6 +18,7 @@ #include "ui/qemu-pixman.h" #include "ui/console.h" #include "hw/virtio/virtio.h" +#include "hw/display/edid.h" #include "qemu/log.h" #include "sysemu/vhost-user-backend.h" @@ -150,6 +151,7 @@ struct VirtIOGPUBase { MemoryRegion hostmem; struct virtio_gpu_scanout scanout[VIRTIO_GPU_MAX_SCANOUTS]; + struct qemu_edid_info edid_info[VIRTIO_GPU_MAX_SCANOUTS]; int enabled_output_bitmask; struct virtio_gpu_requested_state req_state[VIRTIO_GPU_MAX_SCANOUTS]; @@ -168,6 +170,30 @@ struct VirtIOGPUBaseClass { DEFINE_PROP_UINT32("xres", _state, _conf.xres, 1280), \ DEFINE_PROP_UINT32("yres", _state, _conf.yres, 800) +#define VIRTIO_GPU_EDID_PROPERTIES_MULTI_DISPLAY(_state, _edid_info) \ + VIRTIO_GPU_EDID_PROPERTIES(_state, _edid_info, 0), \ + VIRTIO_GPU_EDID_PROPERTIES(_state, _edid_info, 1), \ + VIRTIO_GPU_EDID_PROPERTIES(_state, _edid_info, 2), \ + VIRTIO_GPU_EDID_PROPERTIES(_state, _edid_info, 3), \ + VIRTIO_GPU_EDID_PROPERTIES(_state, _edid_info, 4), \ + VIRTIO_GPU_EDID_PROPERTIES(_state, _edid_info, 5), \ + VIRTIO_GPU_EDID_PROPERTIES(_state, _edid_info, 6), \ + VIRTIO_GPU_EDID_PROPERTIES(_state, _edid_info, 7), \ + VIRTIO_GPU_EDID_PROPERTIES(_state, _edid_info, 8), \ + VIRTIO_GPU_EDID_PROPERTIES(_state, _edid_info, 9), \ + VIRTIO_GPU_EDID_PROPERTIES(_state, _edid_info, 10), \ + VIRTIO_GPU_EDID_PROPERTIES(_state, _edid_info, 11), \ + VIRTIO_GPU_EDID_PROPERTIES(_state, _edid_info, 12), \ + VIRTIO_GPU_EDID_PROPERTIES(_state, _edid_info, 13), \ + VIRTIO_GPU_EDID_PROPERTIES(_state, _edid_info, 14), \ + VIRTIO_GPU_EDID_PROPERTIES(_state, _edid_info, 15) \ + +#define VIRTIO_GPU_EDID_PROPERTIES(_state, _edid_info, id) \ + DEFINE_PROP_UINT32("maxx" #id, _state, _edid_info[id].maxx, 0), \ + DEFINE_PROP_UINT32("maxy" #id, _state, _edid_info[id].maxy, 0), \ + DEFINE_PROP_UINT32("refresh_rate" #id, _state, \ + _edid_info[id].refresh_rate, 0) + typedef struct VGPUDMABuf { QemuDmaBuf *buf; uint32_t scanout_id; -- 2.45.2