aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2017-03-27 16:15:29 +0100
committerPeter Maydell <peter.maydell@linaro.org>2017-03-27 16:15:29 +0100
commita001631cb8eef07654e0ca508dd24f448e0fd936 (patch)
treeb2aefaea9564be12e2469b6fb8be64f13cd73754
parentea2afcf5b6727a577cf561fd8fe0d8c397ecc927 (diff)
parente5766eb40453b1d22815fc5482802688ff184006 (diff)
Merge remote-tracking branch 'remotes/kraxel/tags/pull-fixes-20170327-1' into staging
fixes for 2.9: vga, egl, cirrus, virtio-input. # gpg: Signature made Mon 27 Mar 2017 14:19:45 BST # gpg: using RSA key 0x4CB6D8EED3E87138 # gpg: Good signature from "Gerd Hoffmann (work) <kraxel@redhat.com>" # gpg: aka "Gerd Hoffmann <gerd@kraxel.org>" # gpg: aka "Gerd Hoffmann (private) <kraxel@gmail.com>" # Primary key fingerprint: A032 8CFF B93A 17A7 9901 FE7D 4CB6 D8EE D3E8 7138 * remotes/kraxel/tags/pull-fixes-20170327-1: vnc: fix reverse mode ui/egl-helpers: fix egl 1.5 display init cirrus: fix PUTPIXEL macro virtio-input: fix eventq batching virtio-input: free event queue when finalizing Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
-rw-r--r--hw/display/cirrus_vga_rop2.h4
-rw-r--r--hw/input/virtio-input.c33
-rw-r--r--include/hw/virtio/virtio-input.h5
-rw-r--r--ui/egl-helpers.c58
-rw-r--r--ui/vnc.c17
5 files changed, 85 insertions, 32 deletions
diff --git a/hw/display/cirrus_vga_rop2.h b/hw/display/cirrus_vga_rop2.h
index b86bcd6e09..b208b7348a 100644
--- a/hw/display/cirrus_vga_rop2.h
+++ b/hw/display/cirrus_vga_rop2.h
@@ -29,8 +29,8 @@
#elif DEPTH == 24
#define PUTPIXEL(s, a, c) do { \
ROP_OP(s, a, c); \
- ROP_OP(s, a + 1, (col >> 8)); \
- ROP_OP(s, a + 2, (col >> 16)); \
+ ROP_OP(s, a + 1, (c >> 8)); \
+ ROP_OP(s, a + 2, (c >> 16)); \
} while (0)
#elif DEPTH == 32
#define PUTPIXEL(s, a, c) ROP_OP_32(s, a, c)
diff --git a/hw/input/virtio-input.c b/hw/input/virtio-input.c
index b678ee9f20..0e42f0d02c 100644
--- a/hw/input/virtio-input.c
+++ b/hw/input/virtio-input.c
@@ -22,7 +22,6 @@
void virtio_input_send(VirtIOInput *vinput, virtio_input_event *event)
{
VirtQueueElement *elem;
- unsigned have, need;
int i, len;
if (!vinput->active) {
@@ -32,10 +31,10 @@ void virtio_input_send(VirtIOInput *vinput, virtio_input_event *event)
/* queue up events ... */
if (vinput->qindex == vinput->qsize) {
vinput->qsize++;
- vinput->queue = realloc(vinput->queue, vinput->qsize *
- sizeof(virtio_input_event));
+ vinput->queue = g_realloc(vinput->queue, vinput->qsize *
+ sizeof(vinput->queue[0]));
}
- vinput->queue[vinput->qindex++] = *event;
+ vinput->queue[vinput->qindex++].event = *event;
/* ... until we see a report sync ... */
if (event->type != cpu_to_le16(EV_SYN) ||
@@ -44,24 +43,24 @@ void virtio_input_send(VirtIOInput *vinput, virtio_input_event *event)
}
/* ... then check available space ... */
- need = sizeof(virtio_input_event) * vinput->qindex;
- virtqueue_get_avail_bytes(vinput->evt, &have, NULL, need, 0);
- if (have < need) {
- vinput->qindex = 0;
- trace_virtio_input_queue_full();
- return;
- }
-
- /* ... and finally pass them to the guest */
for (i = 0; i < vinput->qindex; i++) {
elem = virtqueue_pop(vinput->evt, sizeof(VirtQueueElement));
if (!elem) {
- /* should not happen, we've checked for space beforehand */
- fprintf(stderr, "%s: Huh? No vq elem available ...\n", __func__);
+ while (--i >= 0) {
+ virtqueue_unpop(vinput->evt, vinput->queue[i].elem, 0);
+ }
+ vinput->qindex = 0;
+ trace_virtio_input_queue_full();
return;
}
+ vinput->queue[i].elem = elem;
+ }
+
+ /* ... and finally pass them to the guest */
+ for (i = 0; i < vinput->qindex; i++) {
+ elem = vinput->queue[i].elem;
len = iov_from_buf(elem->in_sg, elem->in_num,
- 0, vinput->queue+i, sizeof(virtio_input_event));
+ 0, &vinput->queue[i].event, sizeof(virtio_input_event));
virtqueue_push(vinput->evt, elem, len);
g_free(elem);
}
@@ -272,6 +271,8 @@ static void virtio_input_finalize(Object *obj)
QTAILQ_REMOVE(&vinput->cfg_list, cfg, node);
g_free(cfg);
}
+
+ g_free(vinput->queue);
}
static void virtio_input_device_unrealize(DeviceState *dev, Error **errp)
{
diff --git a/include/hw/virtio/virtio-input.h b/include/hw/virtio/virtio-input.h
index 55db31087a..91df57eca4 100644
--- a/include/hw/virtio/virtio-input.h
+++ b/include/hw/virtio/virtio-input.h
@@ -62,7 +62,10 @@ struct VirtIOInput {
VirtQueue *evt, *sts;
char *serial;
- virtio_input_event *queue;
+ struct {
+ virtio_input_event event;
+ VirtQueueElement *elem;
+ } *queue;
uint32_t qindex, qsize;
bool active;
diff --git a/ui/egl-helpers.c b/ui/egl-helpers.c
index 584dd1b04d..b7b6b2e3cc 100644
--- a/ui/egl-helpers.c
+++ b/ui/egl-helpers.c
@@ -192,6 +192,56 @@ EGLSurface qemu_egl_init_surface_x11(EGLContext ectx, Window win)
/* ---------------------------------------------------------------------- */
+/*
+ * Taken from glamor_egl.h from the Xorg xserver, which is MIT licensed
+ *
+ * Create an EGLDisplay from a native display type. This is a little quirky
+ * for a few reasons.
+ *
+ * 1: GetPlatformDisplayEXT and GetPlatformDisplay are the API you want to
+ * use, but have different function signatures in the third argument; this
+ * happens not to matter for us, at the moment, but it means epoxy won't alias
+ * them together.
+ *
+ * 2: epoxy 1.3 and earlier don't understand EGL client extensions, which
+ * means you can't call "eglGetPlatformDisplayEXT" directly, as the resolver
+ * will crash.
+ *
+ * 3: You can't tell whether you have EGL 1.5 at this point, because
+ * eglQueryString(EGL_VERSION) is a property of the display, which we don't
+ * have yet. So you have to query for extensions no matter what. Fortunately
+ * epoxy_has_egl_extension _does_ let you query for client extensions, so
+ * we don't have to write our own extension string parsing.
+ *
+ * 4. There is no EGL_KHR_platform_base to complement the EXT one, thus one
+ * needs to know EGL 1.5 is supported in order to use the eglGetPlatformDisplay
+ * function pointer.
+ * We can workaround this (circular dependency) by probing for the EGL 1.5
+ * platform extensions (EGL_KHR_platform_gbm and friends) yet it doesn't seem
+ * like mesa will be able to advertise these (even though it can do EGL 1.5).
+ */
+static EGLDisplay qemu_egl_get_display(void *native)
+{
+ EGLDisplay dpy = EGL_NO_DISPLAY;
+
+#ifdef EGL_MESA_platform_gbm
+ /* In practise any EGL 1.5 implementation would support the EXT extension */
+ if (epoxy_has_egl_extension(NULL, "EGL_EXT_platform_base")) {
+ PFNEGLGETPLATFORMDISPLAYEXTPROC getPlatformDisplayEXT =
+ (void *) eglGetProcAddress("eglGetPlatformDisplayEXT");
+ if (getPlatformDisplayEXT) {
+ dpy = getPlatformDisplayEXT(EGL_PLATFORM_GBM_MESA, native, NULL);
+ }
+ }
+#endif
+
+ if (dpy == EGL_NO_DISPLAY) {
+ /* fallback */
+ dpy = eglGetDisplay(native);
+ }
+ return dpy;
+}
+
int qemu_egl_init_dpy(EGLNativeDisplayType dpy, bool gles, bool debug)
{
static const EGLint conf_att_gl[] = {
@@ -222,12 +272,8 @@ int qemu_egl_init_dpy(EGLNativeDisplayType dpy, bool gles, bool debug)
setenv("LIBGL_DEBUG", "verbose", true);
}
- egl_dbg("eglGetDisplay (dpy %p) ...\n", dpy);
-#ifdef EGL_MESA_platform_gbm
- qemu_egl_display = eglGetPlatformDisplayEXT(EGL_PLATFORM_GBM_MESA, dpy, NULL);
-#else
- qemu_egl_display = eglGetDisplay(dpy);
-#endif
+ egl_dbg("qemu_egl_get_display (dpy %p) ...\n", dpy);
+ qemu_egl_display = qemu_egl_get_display(dpy);
if (qemu_egl_display == EGL_NO_DISPLAY) {
error_report("egl: eglGetDisplay failed");
return -1;
diff --git a/ui/vnc.c b/ui/vnc.c
index 6e93b883b5..821acdd8b0 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -3401,6 +3401,7 @@ vnc_display_create_creds(bool x509,
static int vnc_display_get_address(const char *addrstr,
bool websocket,
+ bool reverse,
int displaynum,
int to,
bool has_ipv4,
@@ -3480,21 +3481,22 @@ static int vnc_display_get_address(const char *addrstr,
inet->port = g_strdup(port);
}
} else {
+ int offset = reverse ? 0 : 5900;
if (parse_uint_full(port, &baseport, 10) < 0) {
error_setg(errp, "can't convert to a number: %s", port);
goto cleanup;
}
if (baseport > 65535 ||
- baseport + 5900 > 65535) {
+ baseport + offset > 65535) {
error_setg(errp, "port %s out of range", port);
goto cleanup;
}
inet->port = g_strdup_printf(
- "%d", (int)baseport + 5900);
+ "%d", (int)baseport + offset);
if (to) {
inet->has_to = true;
- inet->to = to + 5900;
+ inet->to = to + offset;
}
}
@@ -3516,6 +3518,7 @@ static int vnc_display_get_address(const char *addrstr,
}
static int vnc_display_get_addresses(QemuOpts *opts,
+ bool reverse,
SocketAddress ***retsaddr,
size_t *retnsaddr,
SocketAddress ***retwsaddr,
@@ -3555,7 +3558,7 @@ static int vnc_display_get_addresses(QemuOpts *opts,
qemu_opt_iter_init(&addriter, opts, "vnc");
while ((addr = qemu_opt_iter_next(&addriter)) != NULL) {
int rv;
- rv = vnc_display_get_address(addr, false, 0, to,
+ rv = vnc_display_get_address(addr, false, reverse, 0, to,
has_ipv4, has_ipv6,
ipv4, ipv6,
&saddr, errp);
@@ -3580,7 +3583,7 @@ static int vnc_display_get_addresses(QemuOpts *opts,
qemu_opt_iter_init(&addriter, opts, "websocket");
while ((addr = qemu_opt_iter_next(&addriter)) != NULL) {
- if (vnc_display_get_address(addr, true, displaynum, to,
+ if (vnc_display_get_address(addr, true, reverse, displaynum, to,
has_ipv4, has_ipv6,
ipv4, ipv6,
&wsaddr, errp) < 0) {
@@ -3777,7 +3780,8 @@ void vnc_display_open(const char *id, Error **errp)
return;
}
- if (vnc_display_get_addresses(opts, &saddr, &nsaddr,
+ reverse = qemu_opt_get_bool(opts, "reverse", false);
+ if (vnc_display_get_addresses(opts, reverse, &saddr, &nsaddr,
&wsaddr, &nwsaddr, errp) < 0) {
goto fail;
}
@@ -3803,7 +3807,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);