Compare commits

..

6 Commits

Author SHA1 Message Date
Gerd Hoffmann
0c244e50ee virtio-gpu: add live migration support
Store some additional state for cursor and resource backing storage,
so we can write out and reload things.  Implement vmsave+vmload for
2d mode.  Continue blocking live migration in 3d/virgl mode.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Message-id: 1464009727-7753-1-git-send-email-kraxel@redhat.com
2016-06-06 09:04:34 +02:00
Gerd Hoffmann
4e68a0ee17 vmsvga: don't process more than 1024 fifo commands at once
vmsvga_fifo_run is called in regular intervals (on each display update)
and will resume where it left off.  So we can simply exit the loop,
without having to worry about how processing will continue.

Fixes: CVE-2016-4453
Cc: qemu-stable@nongnu.org
Cc: P J P <ppandit@redhat.com>
Reported-by: 李强 <liqiang6-s@360.cn>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Message-id: 1464592161-18348-5-git-send-email-kraxel@redhat.com
2016-06-06 09:04:29 +02:00
Gerd Hoffmann
7e486f7577 vmsvga: shadow fifo registers
The fifo is normal ram.  So kvm vcpu threads and qemu iothread can
access the fifo in parallel without syncronization.  Which in turn
implies we can't use the fifo pointers in-place because the guest
can try changing them underneath us.  So add shadows for them, to
make sure the guest can't modify them after we've applied sanity
checks.

Fixes: CVE-2016-4454
Cc: qemu-stable@nongnu.org
Cc: P J P <ppandit@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Message-id: 1464592161-18348-4-git-send-email-kraxel@redhat.com
2016-06-06 09:04:24 +02:00
Gerd Hoffmann
c2e3c54d39 vmsvga: add more fifo checks
Make sure all fifo ptrs are within range.

Fixes: CVE-2016-4454
Cc: qemu-stable@nongnu.org
Cc: P J P <ppandit@redhat.com>
Reported-by: 李强 <liqiang6-s@360.cn>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Message-id: 1464592161-18348-3-git-send-email-kraxel@redhat.com
2016-06-06 09:04:19 +02:00
Gerd Hoffmann
5213602678 vmsvga: move fifo sanity checks to vmsvga_fifo_length
Sanity checks are applied when the fifo is enabled by the guest
(SVGA_REG_CONFIG_DONE write).  Which doesn't help much if the guest
changes the fifo registers afterwards.  Move the checks to
vmsvga_fifo_length so they are done each time qemu is about to read
from the fifo.

Fixes: CVE-2016-4454
Cc: qemu-stable@nongnu.org
Cc: P J P <ppandit@redhat.com>
Reported-by: 李强 <liqiang6-s@360.cn>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Message-id: 1464592161-18348-2-git-send-email-kraxel@redhat.com
2016-06-06 09:03:51 +02:00
Gerd Hoffmann
fa06e5cb7b virtio-gpu: fix scanout rectangles
Commit "ca58b45 ui/virtio-gpu: add and use qemu_create_displaysurface_pixman"
breaks scanouts which use a region of the underlying resource only.

So, we need another way to handle the underlying issue.  Lets create a
new pixman image, grab a reference on the pixman providing the
underlying storage, hook up a destroy callback which releases the
reference.  That way regions work again and releasing the backing
storage should still be impossible thanks to the extra reference we are
holding.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-id: 1464597655-26341-1-git-send-email-kraxel@redhat.com
2016-06-03 09:05:28 +02:00
13 changed files with 272 additions and 123 deletions

View File

@@ -284,7 +284,7 @@ static void virgl_resource_attach_backing(VirtIOGPU *g,
VIRTIO_GPU_FILL_CMD(att_rb);
trace_virtio_gpu_cmd_res_back_attach(att_rb.resource_id);
ret = virtio_gpu_create_mapping_iov(&att_rb, cmd, &res_iovs);
ret = virtio_gpu_create_mapping_iov(&att_rb, cmd, NULL, &res_iovs);
if (ret != 0) {
cmd->error = VIRTIO_GPU_RESP_ERR_UNSPEC;
return;

View File

@@ -22,6 +22,8 @@
#include "qemu/log.h"
#include "qapi/error.h"
#define VIRTIO_GPU_VM_VERSION 1
static struct virtio_gpu_simple_resource*
virtio_gpu_find_resource(VirtIOGPU *g, uint32_t resource_id);
@@ -94,7 +96,7 @@ static void update_cursor_data_virgl(VirtIOGPU *g,
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;
bool move = cursor->hdr.type == VIRTIO_GPU_CMD_MOVE_CURSOR;
if (cursor->pos.scanout_id >= g->conf.max_outputs) {
return;
@@ -107,7 +109,7 @@ static void update_cursor(VirtIOGPU *g, struct virtio_gpu_update_cursor *cursor)
move ? "move" : "update",
cursor->resource_id);
if (move) {
if (!move) {
if (!s->current_cursor) {
s->current_cursor = cursor_alloc(64, 64);
}
@@ -120,6 +122,11 @@ static void update_cursor(VirtIOGPU *g, struct virtio_gpu_update_cursor *cursor)
g, s, cursor->resource_id);
}
dpy_cursor_define(s->con, s->current_cursor);
s->cursor = *cursor;
} else {
s->cursor.pos.x = cursor->pos.x;
s->cursor.pos.y = cursor->pos.y;
}
dpy_mouse_set(s->con, cursor->pos.x, cursor->pos.y,
cursor->resource_id ? 1 : 0);
@@ -495,6 +502,11 @@ static void virtio_gpu_resource_flush(VirtIOGPU *g,
pixman_region_fini(&flush_region);
}
static void virtio_unref_resource(pixman_image_t *image, void *data)
{
pixman_image_unref(data);
}
static void virtio_gpu_set_scanout(VirtIOGPU *g,
struct virtio_gpu_ctrl_command *cmd)
{
@@ -571,8 +583,15 @@ static void virtio_gpu_set_scanout(VirtIOGPU *g,
!= ((uint8_t *)pixman_image_get_data(res->image) + offset) ||
scanout->width != ss.r.width ||
scanout->height != ss.r.height) {
pixman_image_t *rect;
void *ptr = (uint8_t *)pixman_image_get_data(res->image) + offset;
rect = pixman_image_create_bits(format, ss.r.width, ss.r.height, ptr,
pixman_image_get_stride(res->image));
pixman_image_ref(res->image);
pixman_image_set_destroy_function(rect, virtio_unref_resource,
res->image);
/* realloc the surface ptr */
scanout->ds = qemu_create_displaysurface_pixman(res->image);
scanout->ds = qemu_create_displaysurface_pixman(rect);
if (!scanout->ds) {
cmd->error = VIRTIO_GPU_RESP_ERR_UNSPEC;
return;
@@ -590,7 +609,7 @@ static void virtio_gpu_set_scanout(VirtIOGPU *g,
int virtio_gpu_create_mapping_iov(struct virtio_gpu_resource_attach_backing *ab,
struct virtio_gpu_ctrl_command *cmd,
struct iovec **iov)
uint64_t **addr, struct iovec **iov)
{
struct virtio_gpu_mem_entry *ents;
size_t esize, s;
@@ -616,10 +635,16 @@ int virtio_gpu_create_mapping_iov(struct virtio_gpu_resource_attach_backing *ab,
}
*iov = g_malloc0(sizeof(struct iovec) * ab->nr_entries);
if (addr) {
*addr = g_malloc0(sizeof(uint64_t) * 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 (addr) {
(*addr)[i] = ents[i].addr;
}
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",
@@ -627,6 +652,10 @@ int virtio_gpu_create_mapping_iov(struct virtio_gpu_resource_attach_backing *ab,
virtio_gpu_cleanup_mapping_iov(*iov, i);
g_free(ents);
*iov = NULL;
if (addr) {
g_free(*addr);
*addr = NULL;
}
return -1;
}
}
@@ -650,6 +679,8 @@ static void virtio_gpu_cleanup_mapping(struct virtio_gpu_simple_resource *res)
virtio_gpu_cleanup_mapping_iov(res->iov, res->iov_cnt);
res->iov = NULL;
res->iov_cnt = 0;
g_free(res->addrs);
res->addrs = NULL;
}
static void
@@ -671,7 +702,7 @@ virtio_gpu_resource_attach_backing(VirtIOGPU *g,
return;
}
ret = virtio_gpu_create_mapping_iov(&ab, cmd, &res->iov);
ret = virtio_gpu_create_mapping_iov(&ab, cmd, &res->addrs, &res->iov);
if (ret != 0) {
cmd->error = VIRTIO_GPU_RESP_ERR_UNSPEC;
return;
@@ -917,11 +948,163 @@ const GraphicHwOps virtio_gpu_ops = {
.gl_block = virtio_gpu_gl_block,
};
static const VMStateDescription vmstate_virtio_gpu_scanout = {
.name = "virtio-gpu-one-scanout",
.version_id = 1,
.fields = (VMStateField[]) {
VMSTATE_UINT32(resource_id, struct virtio_gpu_scanout),
VMSTATE_UINT32(width, struct virtio_gpu_scanout),
VMSTATE_UINT32(height, struct virtio_gpu_scanout),
VMSTATE_INT32(x, struct virtio_gpu_scanout),
VMSTATE_INT32(y, struct virtio_gpu_scanout),
VMSTATE_UINT32(cursor.resource_id, struct virtio_gpu_scanout),
VMSTATE_UINT32(cursor.hot_x, struct virtio_gpu_scanout),
VMSTATE_UINT32(cursor.hot_y, struct virtio_gpu_scanout),
VMSTATE_UINT32(cursor.pos.x, struct virtio_gpu_scanout),
VMSTATE_UINT32(cursor.pos.y, struct virtio_gpu_scanout),
VMSTATE_END_OF_LIST()
},
};
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),
VMSTATE_STRUCT_VARRAY_UINT32(scanout, struct VirtIOGPU,
conf.max_outputs, 1,
vmstate_virtio_gpu_scanout,
struct virtio_gpu_scanout),
VMSTATE_END_OF_LIST()
},
};
static const VMStateDescription vmstate_virtio_gpu_unmigratable = {
.name = "virtio-gpu",
.name = "virtio-gpu-with-virgl",
.unmigratable = 1,
};
static void virtio_gpu_save(QEMUFile *f, void *opaque)
{
VirtIOGPU *g = opaque;
VirtIODevice *vdev = VIRTIO_DEVICE(g);
struct virtio_gpu_simple_resource *res;
int i;
virtio_save(vdev, f);
/* in 2d mode we should never find unprocessed commands here */
assert(QTAILQ_EMPTY(&g->cmdq));
QTAILQ_FOREACH(res, &g->reslist, next) {
qemu_put_be32(f, res->resource_id);
qemu_put_be32(f, res->width);
qemu_put_be32(f, res->height);
qemu_put_be32(f, res->format);
qemu_put_be32(f, res->iov_cnt);
for (i = 0; i < res->iov_cnt; i++) {
qemu_put_be64(f, res->addrs[i]);
qemu_put_be32(f, res->iov[i].iov_len);
}
qemu_put_buffer(f, (void *)pixman_image_get_data(res->image),
pixman_image_get_stride(res->image) * res->height);
}
qemu_put_be32(f, 0); /* end of list */
vmstate_save_state(f, &vmstate_virtio_gpu_scanouts, g, NULL);
}
static int virtio_gpu_load(QEMUFile *f, void *opaque, int version_id)
{
VirtIOGPU *g = opaque;
VirtIODevice *vdev = VIRTIO_DEVICE(g);
struct virtio_gpu_simple_resource *res;
struct virtio_gpu_scanout *scanout;
uint32_t resource_id, pformat;
int i, ret;
if (version_id != VIRTIO_GPU_VM_VERSION) {
return -EINVAL;
}
ret = virtio_load(vdev, f, version_id);
if (ret) {
return ret;
}
resource_id = qemu_get_be32(f);
while (resource_id != 0) {
res = g_new0(struct virtio_gpu_simple_resource, 1);
res->resource_id = resource_id;
res->width = qemu_get_be32(f);
res->height = qemu_get_be32(f);
res->format = qemu_get_be32(f);
res->iov_cnt = qemu_get_be32(f);
/* allocate */
pformat = get_pixman_format(res->format);
if (!pformat) {
return -EINVAL;
}
res->image = pixman_image_create_bits(pformat,
res->width, res->height,
NULL, 0);
if (!res->image) {
return -EINVAL;
}
res->addrs = g_new(uint64_t, res->iov_cnt);
res->iov = g_new(struct iovec, res->iov_cnt);
/* read data */
for (i = 0; i < res->iov_cnt; i++) {
res->addrs[i] = qemu_get_be64(f);
res->iov[i].iov_len = qemu_get_be32(f);
}
qemu_get_buffer(f, (void *)pixman_image_get_data(res->image),
pixman_image_get_stride(res->image) * res->height);
/* restore mapping */
for (i = 0; i < res->iov_cnt; i++) {
hwaddr len = res->iov[i].iov_len;
res->iov[i].iov_base =
cpu_physical_memory_map(res->addrs[i], &len, 1);
if (!res->iov[i].iov_base || len != res->iov[i].iov_len) {
return -EINVAL;
}
}
QTAILQ_INSERT_HEAD(&g->reslist, res, next);
resource_id = qemu_get_be32(f);
}
/* 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];
if (!scanout->resource_id) {
continue;
}
res = virtio_gpu_find_resource(g, scanout->resource_id);
if (!res) {
return -EINVAL;
}
scanout->ds = qemu_create_displaysurface_pixman(res->image);
if (!scanout->ds) {
return -EINVAL;
}
dpy_gfx_replace_surface(scanout->con, scanout->ds);
dpy_gfx_update(scanout->con, 0, 0, scanout->width, scanout->height);
update_cursor(g, &scanout->cursor);
res->scanout_bitmask |= (1 << i);
}
return 0;
}
static void virtio_gpu_device_realize(DeviceState *qdev, Error **errp)
{
VirtIODevice *vdev = VIRTIO_DEVICE(qdev);
@@ -979,7 +1162,12 @@ static void virtio_gpu_device_realize(DeviceState *qdev, Error **errp)
}
}
vmstate_register(qdev, -1, &vmstate_virtio_gpu_unmigratable, g);
if (virtio_gpu_virgl_enabled(g->conf)) {
vmstate_register(qdev, -1, &vmstate_virtio_gpu_unmigratable, g);
} else {
register_savevm(qdev, "virtio-gpu", -1, VIRTIO_GPU_VM_VERSION,
virtio_gpu_save, virtio_gpu_load, g);
}
}
static void virtio_gpu_instance_init(Object *obj)

View File

@@ -84,6 +84,17 @@ static const GraphicHwOps virtio_vga_ops = {
.gl_block = virtio_vga_gl_block,
};
static const VMStateDescription vmstate_virtio_vga = {
.name = "virtio-vga",
.version_id = 2,
.minimum_version_id = 2,
.fields = (VMStateField[]) {
/* no pci stuff here, saving the virtio device will handle that */
VMSTATE_STRUCT(vga, VirtIOVGA, 0, vmstate_vga_common, VGACommonState),
VMSTATE_END_OF_LIST()
}
};
/* VGA device wrapper around PCI device around virtio GPU */
static void virtio_vga_realize(VirtIOPCIProxy *vpci_dev, Error **errp)
{
@@ -168,6 +179,7 @@ static void virtio_vga_class_init(ObjectClass *klass, void *data)
set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories);
dc->props = virtio_vga_properties;
dc->reset = virtio_vga_reset;
dc->vmsd = &vmstate_virtio_vga;
dc->hotpluggable = false;
k->realize = virtio_vga_realize;

View File

@@ -66,17 +66,11 @@ struct vmsvga_state_s {
uint8_t *fifo_ptr;
unsigned int fifo_size;
union {
uint32_t *fifo;
struct QEMU_PACKED {
uint32_t min;
uint32_t max;
uint32_t next_cmd;
uint32_t stop;
/* Add registers here when adding capabilities. */
uint32_t fifo[0];
} *cmd;
};
uint32_t *fifo;
uint32_t fifo_min;
uint32_t fifo_max;
uint32_t fifo_next;
uint32_t fifo_stop;
#define REDRAW_FIFO_LEN 512
struct vmsvga_rect_s {
@@ -198,7 +192,7 @@ enum {
*/
SVGA_FIFO_MIN = 0,
SVGA_FIFO_MAX, /* The distance from MIN to MAX must be at least 10K */
SVGA_FIFO_NEXT_CMD,
SVGA_FIFO_NEXT,
SVGA_FIFO_STOP,
/*
@@ -546,8 +540,6 @@ static inline void vmsvga_cursor_define(struct vmsvga_state_s *s,
}
#endif
#define CMD(f) le32_to_cpu(s->cmd->f)
static inline int vmsvga_fifo_length(struct vmsvga_state_s *s)
{
int num;
@@ -555,21 +547,45 @@ static inline int vmsvga_fifo_length(struct vmsvga_state_s *s)
if (!s->config || !s->enable) {
return 0;
}
num = CMD(next_cmd) - CMD(stop);
s->fifo_min = le32_to_cpu(s->fifo[SVGA_FIFO_MIN]);
s->fifo_max = le32_to_cpu(s->fifo[SVGA_FIFO_MAX]);
s->fifo_next = le32_to_cpu(s->fifo[SVGA_FIFO_NEXT]);
s->fifo_stop = le32_to_cpu(s->fifo[SVGA_FIFO_STOP]);
/* Check range and alignment. */
if ((s->fifo_min | s->fifo_max | s->fifo_next | s->fifo_stop) & 3) {
return 0;
}
if (s->fifo_min < sizeof(uint32_t) * 4) {
return 0;
}
if (s->fifo_max > SVGA_FIFO_SIZE ||
s->fifo_min >= SVGA_FIFO_SIZE ||
s->fifo_stop >= SVGA_FIFO_SIZE ||
s->fifo_next >= SVGA_FIFO_SIZE) {
return 0;
}
if (s->fifo_max < s->fifo_min + 10 * 1024) {
return 0;
}
num = s->fifo_next - s->fifo_stop;
if (num < 0) {
num += CMD(max) - CMD(min);
num += s->fifo_max - s->fifo_min;
}
return num >> 2;
}
static inline uint32_t vmsvga_fifo_read_raw(struct vmsvga_state_s *s)
{
uint32_t cmd = s->fifo[CMD(stop) >> 2];
uint32_t cmd = s->fifo[s->fifo_stop >> 2];
s->cmd->stop = cpu_to_le32(CMD(stop) + 4);
if (CMD(stop) >= CMD(max)) {
s->cmd->stop = s->cmd->min;
s->fifo_stop += 4;
if (s->fifo_stop >= s->fifo_max) {
s->fifo_stop = s->fifo_min;
}
s->fifo[SVGA_FIFO_STOP] = cpu_to_le32(s->fifo_stop);
return cmd;
}
@@ -581,15 +597,15 @@ static inline uint32_t vmsvga_fifo_read(struct vmsvga_state_s *s)
static void vmsvga_fifo_run(struct vmsvga_state_s *s)
{
uint32_t cmd, colour;
int args, len;
int args, len, maxloop = 1024;
int x, y, dx, dy, width, height;
struct vmsvga_cursor_definition_s cursor;
uint32_t cmd_start;
len = vmsvga_fifo_length(s);
while (len > 0) {
while (len > 0 && --maxloop > 0) {
/* May need to go back to the start of the command if incomplete */
cmd_start = s->cmd->stop;
cmd_start = s->fifo_stop;
switch (cmd = vmsvga_fifo_read(s)) {
case SVGA_CMD_UPDATE:
@@ -748,7 +764,8 @@ static void vmsvga_fifo_run(struct vmsvga_state_s *s)
break;
rewind:
s->cmd->stop = cmd_start;
s->fifo_stop = cmd_start;
s->fifo[SVGA_FIFO_STOP] = cpu_to_le32(s->fifo_stop);
break;
}
}
@@ -1005,19 +1022,6 @@ static void vmsvga_value_write(void *opaque, uint32_t address, uint32_t value)
case SVGA_REG_CONFIG_DONE:
if (value) {
s->fifo = (uint32_t *) s->fifo_ptr;
/* Check range and alignment. */
if ((CMD(min) | CMD(max) | CMD(next_cmd) | CMD(stop)) & 3) {
break;
}
if (CMD(min) < (uint8_t *) s->cmd->fifo - (uint8_t *) s->fifo) {
break;
}
if (CMD(max) > SVGA_FIFO_SIZE) {
break;
}
if (CMD(max) < CMD(min) + 10 * 1024) {
break;
}
vga_dirty_log_stop(&s->vga);
}
s->config = !!value;

View File

@@ -32,6 +32,7 @@ struct virtio_gpu_simple_resource {
uint32_t width;
uint32_t height;
uint32_t format;
uint64_t *addrs;
struct iovec *iov;
unsigned int iov_cnt;
uint32_t scanout_bitmask;
@@ -46,6 +47,7 @@ struct virtio_gpu_scanout {
int x, y;
int invalidate;
uint32_t resource_id;
struct virtio_gpu_update_cursor cursor;
QEMUCursor *current_cursor;
};
@@ -150,7 +152,7 @@ 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);
uint64_t **addr, struct iovec **iov);
void virtio_gpu_cleanup_mapping_iov(struct iovec *iov, uint32_t count);
void virtio_gpu_process_cmdq(VirtIOGPU *g);

View File

@@ -1410,14 +1410,6 @@ everybody else. 'ignore' completely ignores the shared flag and
allows everybody connect unconditionally. Doesn't conform to the rfb
spec but is traditional QEMU behavior.
@item key-delay-ms
Set keyboard delay, for key down and key up events, in milliseconds.
Default is 1. Keyboards are low-bandwidth devices, so this slowdown
can help the device and guest to keep up and not lose events in case
events are arriving in bulk. Possible causes for the latter are flaky
network connections, or scripts for automated testing.
@end table
ETEXI

View File

@@ -2,7 +2,6 @@
#include <glob.h>
#include <dirent.h>
#include "qemu/error-report.h"
#include "ui/egl-helpers.h"
EGLDisplay *qemu_egl_display;
@@ -75,13 +74,13 @@ int egl_rendernode_init(void)
qemu_egl_rn_fd = qemu_egl_rendernode_open();
if (qemu_egl_rn_fd == -1) {
error_report("egl: no drm render node available");
fprintf(stderr, "egl: no drm render node available\n");
goto err;
}
qemu_egl_rn_gbm_dev = gbm_create_device(qemu_egl_rn_fd);
if (!qemu_egl_rn_gbm_dev) {
error_report("egl: gbm_create_device failed");
fprintf(stderr, "egl: gbm_create_device failed\n");
goto err;
}
@@ -89,18 +88,18 @@ int egl_rendernode_init(void)
if (!epoxy_has_egl_extension(qemu_egl_display,
"EGL_KHR_surfaceless_context")) {
error_report("egl: EGL_KHR_surfaceless_context not supported");
fprintf(stderr, "egl: EGL_KHR_surfaceless_context not supported\n");
goto err;
}
if (!epoxy_has_egl_extension(qemu_egl_display,
"EGL_MESA_image_dma_buf_export")) {
error_report("egl: EGL_MESA_image_dma_buf_export not supported");
fprintf(stderr, "egl: EGL_MESA_image_dma_buf_export not supported\n");
goto err;
}
qemu_egl_rn_ctx = qemu_egl_init_ctx();
if (!qemu_egl_rn_ctx) {
error_report("egl: egl_init_ctx failed");
fprintf(stderr, "egl: egl_init_ctx failed\n");
goto err;
}
@@ -157,13 +156,13 @@ EGLSurface qemu_egl_init_surface_x11(EGLContext ectx, Window win)
qemu_egl_config,
(EGLNativeWindowType)win, NULL);
if (esurface == EGL_NO_SURFACE) {
error_report("egl: eglCreateWindowSurface failed");
fprintf(stderr, "egl: eglCreateWindowSurface failed\n");
return NULL;
}
b = eglMakeCurrent(qemu_egl_display, esurface, esurface, ectx);
if (b == EGL_FALSE) {
error_report("egl: eglMakeCurrent failed");
fprintf(stderr, "egl: eglMakeCurrent failed\n");
return NULL;
}
@@ -205,21 +204,21 @@ int qemu_egl_init_dpy(EGLNativeDisplayType dpy, bool gles, bool debug)
egl_dbg("eglGetDisplay (dpy %p) ...\n", dpy);
qemu_egl_display = eglGetDisplay(dpy);
if (qemu_egl_display == EGL_NO_DISPLAY) {
error_report("egl: eglGetDisplay failed");
fprintf(stderr, "egl: eglGetDisplay failed\n");
return -1;
}
egl_dbg("eglInitialize ...\n");
b = eglInitialize(qemu_egl_display, &major, &minor);
if (b == EGL_FALSE) {
error_report("egl: eglInitialize failed");
fprintf(stderr, "egl: eglInitialize failed\n");
return -1;
}
egl_dbg("eglBindAPI ...\n");
b = eglBindAPI(gles ? EGL_OPENGL_ES_API : EGL_OPENGL_API);
if (b == EGL_FALSE) {
error_report("egl: eglBindAPI failed");
fprintf(stderr, "egl: eglBindAPI failed\n");
return -1;
}
@@ -228,7 +227,7 @@ int qemu_egl_init_dpy(EGLNativeDisplayType dpy, bool gles, bool debug)
gles ? conf_att_gles : conf_att_gl,
&qemu_egl_config, 1, &n);
if (b == EGL_FALSE || n != 1) {
error_report("egl: eglChooseConfig failed");
fprintf(stderr, "egl: eglChooseConfig failed\n");
return -1;
}
@@ -253,13 +252,13 @@ EGLContext qemu_egl_init_ctx(void)
ectx = eglCreateContext(qemu_egl_display, qemu_egl_config, EGL_NO_CONTEXT,
egl_gles ? ctx_att_gles : ctx_att_gl);
if (ectx == EGL_NO_CONTEXT) {
error_report("egl: eglCreateContext failed");
fprintf(stderr, "egl: eglCreateContext failed\n");
return NULL;
}
b = eglMakeCurrent(qemu_egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, ectx);
if (b == EGL_FALSE) {
error_report("egl: eglMakeCurrent failed");
fprintf(stderr, "egl: eglMakeCurrent failed\n");
return NULL;
}

View File

@@ -1477,14 +1477,13 @@ static void gd_grab_pointer(VirtualConsole *vc, const char *reason)
static void gd_ungrab_pointer(GtkDisplayState *s)
{
VirtualConsole *vc = s->ptr_owner;
GdkDisplay *display;
GdkDisplay *display = gtk_widget_get_display(vc->gfx.drawing_area);
if (vc == NULL) {
return;
}
s->ptr_owner = NULL;
display = gtk_widget_get_display(vc->gfx.drawing_area);
#if GTK_CHECK_VERSION(3, 20, 0)
gd_grab_update(vc, vc->s->kbd_owner == vc, false);
gdk_device_warp(gd_get_pointer(display),

View File

@@ -116,9 +116,6 @@ void sdl2_2d_switch(DisplayChangeListener *dcl,
case PIXMAN_r8g8b8x8:
format = SDL_PIXELFORMAT_RGBA8888;
break;
case PIXMAN_b8g8r8x8:
format = SDL_PIXELFORMAT_BGRX8888;
break;
default:
g_assert_not_reached();
}

View File

@@ -794,9 +794,6 @@ void sdl_display_init(DisplayState *ds, int full_screen, int no_frame)
}
}
sdl2_num_outputs = i;
if (sdl2_num_outputs == 0) {
return;
}
sdl2_console = g_new0(struct sdl2_console, sdl2_num_outputs);
for (i = 0; i < sdl2_num_outputs; i++) {
QemuConsole *con = qemu_console_lookup_by_index(i);

View File

@@ -833,11 +833,9 @@ void qemu_spice_init(void)
"incompatible with -spice port/tls-port");
exit(1);
}
if (egl_rendernode_init() != 0) {
error_report("Failed to initialize EGL render node for SPICE GL");
exit(1);
if (egl_rendernode_init() == 0) {
display_opengl = 1;
}
display_opengl = 1;
}
#endif
}

View File

@@ -1629,7 +1629,6 @@ static void reset_keys(VncState *vs)
for(i = 0; i < 256; i++) {
if (vs->modifiers_state[i]) {
qemu_input_event_send_key_number(vs->vd->dcl.con, i, false);
qemu_input_event_send_key_delay(vs->vd->key_delay_ms);
vs->modifiers_state[i] = 0;
}
}
@@ -1639,9 +1638,9 @@ static void press_key(VncState *vs, int keysym)
{
int keycode = keysym2scancode(vs->vd->kbd_layout, keysym) & SCANCODE_KEYMASK;
qemu_input_event_send_key_number(vs->vd->dcl.con, keycode, true);
qemu_input_event_send_key_delay(vs->vd->key_delay_ms);
qemu_input_event_send_key_delay(0);
qemu_input_event_send_key_number(vs->vd->dcl.con, keycode, false);
qemu_input_event_send_key_delay(vs->vd->key_delay_ms);
qemu_input_event_send_key_delay(0);
}
static int current_led_state(VncState *vs)
@@ -1793,7 +1792,6 @@ static void do_key_event(VncState *vs, int down, int keycode, int sym)
if (qemu_console_is_graphic(NULL)) {
qemu_input_event_send_key_number(vs->vd->dcl.con, keycode, down);
qemu_input_event_send_key_delay(vs->vd->key_delay_ms);
} else {
bool numlock = vs->modifiers_state[0x45];
bool control = (vs->modifiers_state[0x1d] ||
@@ -1915,7 +1913,6 @@ static void vnc_release_modifiers(VncState *vs)
continue;
}
qemu_input_event_send_key_number(vs->vd->dcl.con, keycode, false);
qemu_input_event_send_key_delay(vs->vd->key_delay_ms);
}
}
@@ -2097,24 +2094,6 @@ static void set_pixel_conversion(VncState *vs)
}
}
static void send_color_map(VncState *vs)
{
int i;
vnc_write_u8(vs, VNC_MSG_SERVER_SET_COLOUR_MAP_ENTRIES);
vnc_write_u8(vs, 0); /* padding */
vnc_write_u16(vs, 0); /* first color */
vnc_write_u16(vs, 256); /* # of colors */
for (i = 0; i < 256; i++) {
PixelFormat *pf = &vs->client_pf;
vnc_write_u16(vs, (((i >> pf->rshift) & pf->rmax) << (16 - pf->rbits)));
vnc_write_u16(vs, (((i >> pf->gshift) & pf->gmax) << (16 - pf->gbits)));
vnc_write_u16(vs, (((i >> pf->bshift) & pf->bmax) << (16 - pf->bbits)));
}
}
static void set_pixel_format(VncState *vs,
int bits_per_pixel, int depth,
int big_endian_flag, int true_color_flag,
@@ -2122,15 +2101,8 @@ static void set_pixel_format(VncState *vs,
int red_shift, int green_shift, int blue_shift)
{
if (!true_color_flag) {
/* Expose a reasonable default 256 color map */
bits_per_pixel = 8;
depth = 8;
red_max = 7;
green_max = 7;
blue_max = 3;
red_shift = 0;
green_shift = 3;
blue_shift = 6;
vnc_client_error(vs);
return;
}
switch (bits_per_pixel) {
@@ -2160,10 +2132,6 @@ static void set_pixel_format(VncState *vs,
vs->client_pf.depth = bits_per_pixel == 32 ? 24 : bits_per_pixel;
vs->client_be = big_endian_flag;
if (!true_color_flag) {
send_color_map(vs);
}
set_pixel_conversion(vs);
graphic_hw_invalidate(vs->vd->dcl.con);
@@ -3280,9 +3248,6 @@ static QemuOptsList qemu_vnc_opts = {
},{
.name = "lock-key-sync",
.type = QEMU_OPT_BOOL,
},{
.name = "key-delay-ms",
.type = QEMU_OPT_NUMBER,
},{
.name = "sasl",
.type = QEMU_OPT_BOOL,
@@ -3521,7 +3486,6 @@ void vnc_display_open(const char *id, Error **errp)
#endif
int acl = 0;
int lock_key_sync = 1;
int key_delay_ms;
if (!vs) {
error_setg(errp, "VNC display not active");
@@ -3640,7 +3604,6 @@ void vnc_display_open(const char *id, Error **errp)
reverse = qemu_opt_get_bool(opts, "reverse", false);
lock_key_sync = qemu_opt_get_bool(opts, "lock-key-sync", true);
key_delay_ms = qemu_opt_get_number(opts, "key-delay-ms", 1);
sasl = qemu_opt_get_bool(opts, "sasl", false);
#ifndef CONFIG_VNC_SASL
if (sasl) {
@@ -3772,7 +3735,6 @@ void vnc_display_open(const char *id, Error **errp)
}
#endif
vs->lock_key_sync = lock_key_sync;
vs->key_delay_ms = key_delay_ms;
device_id = qemu_opt_get(opts, "display");
if (device_id) {

View File

@@ -155,7 +155,6 @@ struct VncDisplay
DisplayChangeListener dcl;
kbd_layout_t *kbd_layout;
int lock_key_sync;
int key_delay_ms;
QemuMutex mutex;
QEMUCursor *cursor;