Compare commits

..

7 Commits

Author SHA1 Message Date
Gerd Hoffmann
c5ce833344 vnc: add configurable keyboard delay
Limits the rate kbd events from the vnc server are forwarded to the
guest, so input devices which are typically low-bandwidth can keep
up even on bulky input.

v2: update documentation too.
v3: spell fixes.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Tested-by: Yang Hongyang <hongyang.yang@easystack.cn>
Message-id: 1464762150-25817-1-git-send-email-kraxel@redhat.com
2016-06-03 08:23:26 +02:00
Gerd Hoffmann
8efa5f29f8 sdl2: skip init without outputs
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Tested-by: Cole Robinson <crobinso@redhat.com>
Message-id: 1464790116-32405-1-git-send-email-kraxel@redhat.com
2016-06-03 08:23:26 +02:00
Alexander Graf
0c426e4534 vnc: Add support for color map
Our current VNC code does not handle color maps (aka non-true-color) at all
and aborts if a client requests them. There are 2 major issues with this:

 1) A VNC viewer on an 8-bit X11 system may request color maps
 2) RealVNC _always_ starts requesting color maps, then moves on to full color

In order to support these 2 use cases, let's just create a fake color map
that covers exactly our normal true color 8 bit color space. That way we don't
lose anything over a client that wants true color.

Reported-by: Sascha Wehnert <swehnert@suse.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
Signed-off-by: Pavel Butsykin <pbutsykin@virtuozzo.com>
Signed-off-by: Denis V. Lunev <den@openvz.org>
Message-id: 1464099559-20789-1-git-send-email-den@openvz.org

Actually this is a very old patch originally submitted in 2013 by
Alexander. The situation is still the same with RealVNC, it does not
connect by default to QEMU VNC. The problem is that this client is
really popular. This is better to be kludged.

Signed-off-by: Pavel Butsykin <pbutsykin@virtuozzo.com>
Signed-off-by: Denis V. Lunev <den@openvz.org>
CC: Gerd Hoffmann <kraxel@redhat.com>
CC: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2016-06-03 08:23:26 +02:00
Pavel Dovgalyuk
435deffefb SDL2: add bgrx pixel format
This patch adds support of b8g8r8x8 pixel format for SDL2.

Signed-off-by: Pavel Dovgalyuk <pavel.dovgaluk@ispras.ru>
Message-id: 20160517072848.4540.34695.stgit@PASHA-ISP
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2016-06-03 08:23:26 +02:00
Gerd Hoffmann
41cc5239f3 gtk: fix unchecked vc dereference
Spotted by Coverity.

Cc: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Message-id: 1463737748-1062-1-git-send-email-kraxel@redhat.com
2016-06-03 08:23:26 +02:00
Cole Robinson
daafc661cc ui: spice: Exit if gl=on EGL init fails
The user explicitly requested spice GL, so if we know it isn't
going to work we should exit

Signed-off-by: Cole Robinson <crobinso@redhat.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-id: e3789e35b16f9e3cc6f2652f91c52d88ba6d6936.1463588606.git.crobinso@redhat.com
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2016-06-03 08:23:26 +02:00
Cole Robinson
38a55bddcc ui: egl: Replace fprintf with error_report
Signed-off-by: Cole Robinson <crobinso@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-id: c880920f6e40a506394d89dbbe1f67c63d359c17.1463588606.git.crobinso@redhat.com
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2016-06-03 08:23:26 +02:00
13 changed files with 117 additions and 65 deletions

View File

@@ -781,22 +781,23 @@ static int qpa_ctl_in (HWVoiceIn *hw, int cmd, ...)
pa_threaded_mainloop_lock (g->mainloop); pa_threaded_mainloop_lock (g->mainloop);
op = pa_context_set_source_output_volume (g->context, /* FIXME: use the upcoming "set_source_output_{volume,mute}" */
pa_stream_get_index (pa->stream), op = pa_context_set_source_volume_by_index (g->context,
pa_stream_get_device_index (pa->stream),
&v, NULL, NULL); &v, NULL, NULL);
if (!op) { if (!op) {
qpa_logerr (pa_context_errno (g->context), qpa_logerr (pa_context_errno (g->context),
"set_source_output_volume() failed\n"); "set_source_volume() failed\n");
} else { } else {
pa_operation_unref(op); pa_operation_unref(op);
} }
op = pa_context_set_source_output_mute (g->context, op = pa_context_set_source_mute_by_index (g->context,
pa_stream_get_index (pa->stream), pa_stream_get_index (pa->stream),
sw->vol.mute, NULL, NULL); sw->vol.mute, NULL, NULL);
if (!op) { if (!op) {
qpa_logerr (pa_context_errno (g->context), qpa_logerr (pa_context_errno (g->context),
"set_source_output_mute() failed\n"); "set_source_mute() failed\n");
} else { } else {
pa_operation_unref (op); pa_operation_unref (op);
} }

4
configure vendored
View File

@@ -2813,8 +2813,8 @@ for drv in $audio_drv_list; do
;; ;;
pa) pa)
audio_drv_probe $drv pulse/pulseaudio.h "-lpulse" \ audio_drv_probe $drv pulse/mainloop.h "-lpulse" \
"pa_context_set_source_output_volume(NULL, 0, NULL, NULL, NULL); return 0;" "pa_mainloop *m = 0; pa_mainloop_free (m); return 0;"
libs_softmmu="-lpulse $libs_softmmu" libs_softmmu="-lpulse $libs_softmmu"
audio_pt_int="yes" audio_pt_int="yes"
;; ;;

View File

@@ -145,15 +145,16 @@ static const VMStateDescription vmstate_cs4231 = {
} }
}; };
static void cs4231_init(Object *obj) static int cs4231_init1(SysBusDevice *dev)
{ {
CSState *s = CS4231(obj); CSState *s = CS4231(dev);
SysBusDevice *dev = SYS_BUS_DEVICE(obj);
memory_region_init_io(&s->iomem, obj, &cs_mem_ops, s, "cs4321", memory_region_init_io(&s->iomem, OBJECT(s), &cs_mem_ops, s, "cs4321",
CS_SIZE); CS_SIZE);
sysbus_init_mmio(dev, &s->iomem); sysbus_init_mmio(dev, &s->iomem);
sysbus_init_irq(dev, &s->irq); sysbus_init_irq(dev, &s->irq);
return 0;
} }
static Property cs4231_properties[] = { static Property cs4231_properties[] = {
@@ -163,7 +164,9 @@ static Property cs4231_properties[] = {
static void cs4231_class_init(ObjectClass *klass, void *data) static void cs4231_class_init(ObjectClass *klass, void *data)
{ {
DeviceClass *dc = DEVICE_CLASS(klass); DeviceClass *dc = DEVICE_CLASS(klass);
SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
k->init = cs4231_init1;
dc->reset = cs_reset; dc->reset = cs_reset;
dc->vmsd = &vmstate_cs4231; dc->vmsd = &vmstate_cs4231;
dc->props = cs4231_properties; dc->props = cs4231_properties;
@@ -173,7 +176,6 @@ static const TypeInfo cs4231_info = {
.name = TYPE_CS4231, .name = TYPE_CS4231,
.parent = TYPE_SYS_BUS_DEVICE, .parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(CSState), .instance_size = sizeof(CSState),
.instance_init = cs4231_init,
.class_init = cs4231_class_init, .class_init = cs4231_class_init,
}; };

View File

@@ -26,7 +26,6 @@
#include "intel-hda.h" #include "intel-hda.h"
#include "intel-hda-defs.h" #include "intel-hda-defs.h"
#include "sysemu/dma.h" #include "sysemu/dma.h"
#include "qapi/error.h"
/* --------------------------------------------------------------------- */ /* --------------------------------------------------------------------- */
/* hda bus */ /* hda bus */
@@ -51,28 +50,25 @@ void hda_codec_bus_init(DeviceState *dev, HDACodecBus *bus, size_t bus_size,
bus->xfer = xfer; bus->xfer = xfer;
} }
static void hda_codec_dev_realize(DeviceState *qdev, Error **errp) static int hda_codec_dev_init(DeviceState *qdev)
{ {
HDACodecBus *bus = HDA_BUS(qdev->parent_bus); HDACodecBus *bus = DO_UPCAST(HDACodecBus, qbus, qdev->parent_bus);
HDACodecDevice *dev = HDA_CODEC_DEVICE(qdev); HDACodecDevice *dev = DO_UPCAST(HDACodecDevice, qdev, qdev);
HDACodecDeviceClass *cdc = HDA_CODEC_DEVICE_GET_CLASS(dev); HDACodecDeviceClass *cdc = HDA_CODEC_DEVICE_GET_CLASS(dev);
if (dev->cad == -1) { if (dev->cad == -1) {
dev->cad = bus->next_cad; dev->cad = bus->next_cad;
} }
if (dev->cad >= 15) { if (dev->cad >= 15) {
error_setg(errp, "HDA audio codec address is full"); return -1;
return;
} }
bus->next_cad = dev->cad + 1; bus->next_cad = dev->cad + 1;
if (cdc->init(dev) != 0) { return cdc->init(dev);
error_setg(errp, "HDA audio init failed");
}
} }
static int hda_codec_dev_exit(DeviceState *qdev) static int hda_codec_dev_exit(DeviceState *qdev)
{ {
HDACodecDevice *dev = HDA_CODEC_DEVICE(qdev); HDACodecDevice *dev = DO_UPCAST(HDACodecDevice, qdev, qdev);
HDACodecDeviceClass *cdc = HDA_CODEC_DEVICE_GET_CLASS(dev); HDACodecDeviceClass *cdc = HDA_CODEC_DEVICE_GET_CLASS(dev);
if (cdc->exit) { if (cdc->exit) {
@@ -88,7 +84,7 @@ HDACodecDevice *hda_codec_find(HDACodecBus *bus, uint32_t cad)
QTAILQ_FOREACH(kid, &bus->qbus.children, sibling) { QTAILQ_FOREACH(kid, &bus->qbus.children, sibling) {
DeviceState *qdev = kid->child; DeviceState *qdev = kid->child;
cdev = HDA_CODEC_DEVICE(qdev); cdev = DO_UPCAST(HDACodecDevice, qdev, qdev);
if (cdev->cad == cad) { if (cdev->cad == cad) {
return cdev; return cdev;
} }
@@ -98,14 +94,14 @@ HDACodecDevice *hda_codec_find(HDACodecBus *bus, uint32_t cad)
void hda_codec_response(HDACodecDevice *dev, bool solicited, uint32_t response) void hda_codec_response(HDACodecDevice *dev, bool solicited, uint32_t response)
{ {
HDACodecBus *bus = HDA_BUS(dev->qdev.parent_bus); HDACodecBus *bus = DO_UPCAST(HDACodecBus, qbus, dev->qdev.parent_bus);
bus->response(dev, solicited, response); bus->response(dev, solicited, response);
} }
bool hda_codec_xfer(HDACodecDevice *dev, uint32_t stnr, bool output, bool hda_codec_xfer(HDACodecDevice *dev, uint32_t stnr, bool output,
uint8_t *buf, uint32_t len) uint8_t *buf, uint32_t len)
{ {
HDACodecBus *bus = HDA_BUS(dev->qdev.parent_bus); HDACodecBus *bus = DO_UPCAST(HDACodecBus, qbus, dev->qdev.parent_bus);
return bus->xfer(dev, stnr, output, buf, len); return bus->xfer(dev, stnr, output, buf, len);
} }
@@ -341,7 +337,7 @@ static void intel_hda_corb_run(IntelHDAState *d)
static void intel_hda_response(HDACodecDevice *dev, bool solicited, uint32_t response) static void intel_hda_response(HDACodecDevice *dev, bool solicited, uint32_t response)
{ {
HDACodecBus *bus = HDA_BUS(dev->qdev.parent_bus); HDACodecBus *bus = DO_UPCAST(HDACodecBus, qbus, dev->qdev.parent_bus);
IntelHDAState *d = container_of(bus, IntelHDAState, codecs); IntelHDAState *d = container_of(bus, IntelHDAState, codecs);
hwaddr addr; hwaddr addr;
uint32_t wp, ex; uint32_t wp, ex;
@@ -390,7 +386,7 @@ static void intel_hda_response(HDACodecDevice *dev, bool solicited, uint32_t res
static bool intel_hda_xfer(HDACodecDevice *dev, uint32_t stnr, bool output, static bool intel_hda_xfer(HDACodecDevice *dev, uint32_t stnr, bool output,
uint8_t *buf, uint32_t len) uint8_t *buf, uint32_t len)
{ {
HDACodecBus *bus = HDA_BUS(dev->qdev.parent_bus); HDACodecBus *bus = DO_UPCAST(HDACodecBus, qbus, dev->qdev.parent_bus);
IntelHDAState *d = container_of(bus, IntelHDAState, codecs); IntelHDAState *d = container_of(bus, IntelHDAState, codecs);
hwaddr addr; hwaddr addr;
uint32_t s, copy, left; uint32_t s, copy, left;
@@ -497,7 +493,7 @@ static void intel_hda_notify_codecs(IntelHDAState *d, uint32_t stream, bool runn
DeviceState *qdev = kid->child; DeviceState *qdev = kid->child;
HDACodecDeviceClass *cdc; HDACodecDeviceClass *cdc;
cdev = HDA_CODEC_DEVICE(qdev); cdev = DO_UPCAST(HDACodecDevice, qdev, qdev);
cdc = HDA_CODEC_DEVICE_GET_CLASS(cdev); cdc = HDA_CODEC_DEVICE_GET_CLASS(cdev);
if (cdc->stream) { if (cdc->stream) {
cdc->stream(cdev, stream, running, output); cdc->stream(cdev, stream, running, output);
@@ -1124,7 +1120,7 @@ static void intel_hda_reset(DeviceState *dev)
/* reset codecs */ /* reset codecs */
QTAILQ_FOREACH(kid, &d->codecs.qbus.children, sibling) { QTAILQ_FOREACH(kid, &d->codecs.qbus.children, sibling) {
DeviceState *qdev = kid->child; DeviceState *qdev = kid->child;
cdev = HDA_CODEC_DEVICE(qdev); cdev = DO_UPCAST(HDACodecDevice, qdev, qdev);
device_reset(DEVICE(cdev)); device_reset(DEVICE(cdev));
d->state_sts |= (1 << cdev->cad); d->state_sts |= (1 << cdev->cad);
} }
@@ -1302,7 +1298,7 @@ static const TypeInfo intel_hda_info_ich9 = {
static void hda_codec_device_class_init(ObjectClass *klass, void *data) static void hda_codec_device_class_init(ObjectClass *klass, void *data)
{ {
DeviceClass *k = DEVICE_CLASS(klass); DeviceClass *k = DEVICE_CLASS(klass);
k->realize = hda_codec_dev_realize; k->init = hda_codec_dev_init;
k->exit = hda_codec_dev_exit; k->exit = hda_codec_dev_exit;
set_bit(DEVICE_CATEGORY_SOUND, k->categories); set_bit(DEVICE_CATEGORY_SOUND, k->categories);
k->bus_type = TYPE_HDA_BUS; k->bus_type = TYPE_HDA_BUS;

View File

@@ -284,26 +284,16 @@ static int ac97_post_load(void *opaque, int version_id)
return 0; return 0;
} }
static void milkymist_ac97_init(Object *obj) static int milkymist_ac97_init(SysBusDevice *dev)
{ {
MilkymistAC97State *s = MILKYMIST_AC97(obj); MilkymistAC97State *s = MILKYMIST_AC97(dev);
SysBusDevice *dev = SYS_BUS_DEVICE(obj);
struct audsettings as;
sysbus_init_irq(dev, &s->crrequest_irq); sysbus_init_irq(dev, &s->crrequest_irq);
sysbus_init_irq(dev, &s->crreply_irq); sysbus_init_irq(dev, &s->crreply_irq);
sysbus_init_irq(dev, &s->dmar_irq); sysbus_init_irq(dev, &s->dmar_irq);
sysbus_init_irq(dev, &s->dmaw_irq); sysbus_init_irq(dev, &s->dmaw_irq);
memory_region_init_io(&s->regs_region, obj, &ac97_mmio_ops, s,
"milkymist-ac97", R_MAX * 4);
sysbus_init_mmio(dev, &s->regs_region);
}
static void milkymist_ac97_realize(DeviceState *dev, Error **errp)
{
MilkymistAC97State *s = MILKYMIST_AC97(dev);
struct audsettings as;
AUD_register_card("Milkymist AC'97", &s->card); AUD_register_card("Milkymist AC'97", &s->card);
as.freq = 48000; as.freq = 48000;
@@ -315,6 +305,12 @@ static void milkymist_ac97_realize(DeviceState *dev, Error **errp)
"mm_ac97.in", s, ac97_in_cb, &as); "mm_ac97.in", s, ac97_in_cb, &as);
s->voice_out = AUD_open_out(&s->card, s->voice_out, s->voice_out = AUD_open_out(&s->card, s->voice_out,
"mm_ac97.out", s, ac97_out_cb, &as); "mm_ac97.out", s, ac97_out_cb, &as);
memory_region_init_io(&s->regs_region, OBJECT(s), &ac97_mmio_ops, s,
"milkymist-ac97", R_MAX * 4);
sysbus_init_mmio(dev, &s->regs_region);
return 0;
} }
static const VMStateDescription vmstate_milkymist_ac97 = { static const VMStateDescription vmstate_milkymist_ac97 = {
@@ -331,8 +327,9 @@ static const VMStateDescription vmstate_milkymist_ac97 = {
static void milkymist_ac97_class_init(ObjectClass *klass, void *data) static void milkymist_ac97_class_init(ObjectClass *klass, void *data)
{ {
DeviceClass *dc = DEVICE_CLASS(klass); DeviceClass *dc = DEVICE_CLASS(klass);
SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
dc->realize = milkymist_ac97_realize; k->init = milkymist_ac97_init;
dc->reset = milkymist_ac97_reset; dc->reset = milkymist_ac97_reset;
dc->vmsd = &vmstate_milkymist_ac97; dc->vmsd = &vmstate_milkymist_ac97;
} }
@@ -341,7 +338,6 @@ static const TypeInfo milkymist_ac97_info = {
.name = TYPE_MILKYMIST_AC97, .name = TYPE_MILKYMIST_AC97,
.parent = TYPE_SYS_BUS_DEVICE, .parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(MilkymistAC97State), .instance_size = sizeof(MilkymistAC97State),
.instance_init = milkymist_ac97_init,
.class_init = milkymist_ac97_class_init, .class_init = milkymist_ac97_class_init,
}; };

View File

@@ -1410,6 +1410,14 @@ everybody else. 'ignore' completely ignores the shared flag and
allows everybody connect unconditionally. Doesn't conform to the rfb allows everybody connect unconditionally. Doesn't conform to the rfb
spec but is traditional QEMU behavior. 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 @end table
ETEXI ETEXI

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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