UI: small fixes and improvements

-----BEGIN PGP SIGNATURE-----
 
 iQJQBAABCAA6FiEEh6m9kz+HxgbSdvYt2ujhCXWWnOUFAmZDZEAcHG1hcmNhbmRy
 ZS5sdXJlYXVAcmVkaGF0LmNvbQAKCRDa6OEJdZac5UxvD/9HWbB8JdbV8lNCLePT
 a6RUWSqLyP/cV0FCw9URYgAjAYROO966dZopCH7+Sz6goC8tk3IFUoqL0LbtZQjK
 zMNueGRbwJj0iGMxFG4wuWBpBF6Dzc4sh90TF3XWSE8PMpWsDY+sP3VRu4sP1qu7
 OmCGTuSwNUugxazPLxvbTpLMnco9b+asAGlAU6WqpcURmia7XN7dBLGzfQ9vMxuc
 L5od+pPGfcxuj3ETMG+5OQlIZH1lmX3465LajkUDVxffNfznqMVDYyo4sKNW5KOY
 u420AoACeVsANWce1Aw2ekj1ETsvqxj23RClNIgdpDbMsGk9eM6eS+6vRctcM6z4
 wMH6GAKKI3AWj7Q6qY4096bcdNmYD/GOs9dgswqYjf+JLzEVcI1dHQ36K124nKH0
 t+9t3UUx1NBMwAp+EEN94W1ClwOZ0zvapS8zNaf76KIi9Eb4vrIyOlzdTM7SU4kC
 CQ4Tu9MBB5WIqzhsVtIH36zDBasgAU8DCtpelDY1AJiODGiQbfZi4yo8eEiQMS1s
 onixsXa7zyCCpmxwkYmvF54RbZFlPXxmdvu0jYxKddbEuTGX/Y3qvDAWv1kz6iJS
 iGmYtokfkv86XBCTGTAb3QEmFfOWcLnPc59Gg0TF3zyzY3q05nU/qjuIlgYedR/o
 TnnNYbyqXumojRCd69Dyy3THEg==
 =SW9v
 -----END PGP SIGNATURE-----

Merge tag 'ui-pull-request' of https://gitlab.com/marcandre.lureau/qemu into staging

UI: small fixes and improvements

# -----BEGIN PGP SIGNATURE-----
#
# iQJQBAABCAA6FiEEh6m9kz+HxgbSdvYt2ujhCXWWnOUFAmZDZEAcHG1hcmNhbmRy
# ZS5sdXJlYXVAcmVkaGF0LmNvbQAKCRDa6OEJdZac5UxvD/9HWbB8JdbV8lNCLePT
# a6RUWSqLyP/cV0FCw9URYgAjAYROO966dZopCH7+Sz6goC8tk3IFUoqL0LbtZQjK
# zMNueGRbwJj0iGMxFG4wuWBpBF6Dzc4sh90TF3XWSE8PMpWsDY+sP3VRu4sP1qu7
# OmCGTuSwNUugxazPLxvbTpLMnco9b+asAGlAU6WqpcURmia7XN7dBLGzfQ9vMxuc
# L5od+pPGfcxuj3ETMG+5OQlIZH1lmX3465LajkUDVxffNfznqMVDYyo4sKNW5KOY
# u420AoACeVsANWce1Aw2ekj1ETsvqxj23RClNIgdpDbMsGk9eM6eS+6vRctcM6z4
# wMH6GAKKI3AWj7Q6qY4096bcdNmYD/GOs9dgswqYjf+JLzEVcI1dHQ36K124nKH0
# t+9t3UUx1NBMwAp+EEN94W1ClwOZ0zvapS8zNaf76KIi9Eb4vrIyOlzdTM7SU4kC
# CQ4Tu9MBB5WIqzhsVtIH36zDBasgAU8DCtpelDY1AJiODGiQbfZi4yo8eEiQMS1s
# onixsXa7zyCCpmxwkYmvF54RbZFlPXxmdvu0jYxKddbEuTGX/Y3qvDAWv1kz6iJS
# iGmYtokfkv86XBCTGTAb3QEmFfOWcLnPc59Gg0TF3zyzY3q05nU/qjuIlgYedR/o
# TnnNYbyqXumojRCd69Dyy3THEg==
# =SW9v
# -----END PGP SIGNATURE-----
# gpg: Signature made Tue 14 May 2024 03:16:48 PM CEST
# gpg:                using RSA key 87A9BD933F87C606D276F62DDAE8E10975969CE5
# gpg:                issuer "marcandre.lureau@redhat.com"
# gpg: Good signature from "Marc-André Lureau <marcandre.lureau@redhat.com>" [full]
# gpg:                 aka "Marc-André Lureau <marcandre.lureau@gmail.com>" [full]

* tag 'ui-pull-request' of https://gitlab.com/marcandre.lureau/qemu:
  ui/sdl2: Allow host to power down screen
  ui/gtk: Fix mouse/motion event scaling issue with GTK display backend
  ui/gtk: Add gd_motion_event trace event
  ui/console: move QemuDmaBuf struct def to dmabuf.c
  ui/console: Use qemu_dmabuf_new() and free() helpers instead
  ui/console: Use qemu_dmabuf_set_..() helpers instead
  ui/console: Use qemu_dmabuf_get_..() helpers instead
  ui/console: new dmabuf.h and dmabuf.c for QemuDmaBuf struct and helpers
  ui/gtk: Check if fence_fd is equal to or greater than 0
  ui/gtk: Draw guest frame at refresh cycle
  Allow UNIX socket option for VNC websocket

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
master
Richard Henderson 2024-05-15 08:52:27 +02:00
commit 265aad58e9
22 changed files with 554 additions and 210 deletions

View File

@ -249,6 +249,7 @@ vhost_user_gpu_handle_display(VhostUserGPU *g, VhostUserGpuMsg *msg)
case VHOST_USER_GPU_DMABUF_SCANOUT: {
VhostUserGpuDMABUFScanout *m = &msg->payload.dmabuf_scanout;
int fd = qemu_chr_fe_get_msgfd(&g->vhost_chr);
uint64_t modifier = 0;
QemuDmaBuf *dmabuf;
if (m->scanout_id >= g->parent_obj.conf.max_outputs) {
@ -261,30 +262,33 @@ vhost_user_gpu_handle_display(VhostUserGPU *g, VhostUserGpuMsg *msg)
g->parent_obj.enable = 1;
con = g->parent_obj.scanout[m->scanout_id].con;
dmabuf = &g->dmabuf[m->scanout_id];
if (dmabuf->fd >= 0) {
close(dmabuf->fd);
dmabuf->fd = -1;
}
dpy_gl_release_dmabuf(con, dmabuf);
if (fd == -1) {
dpy_gl_scanout_disable(con);
break;
}
*dmabuf = (QemuDmaBuf) {
.fd = fd,
.width = m->fd_width,
.height = m->fd_height,
.stride = m->fd_stride,
.fourcc = m->fd_drm_fourcc,
.y0_top = m->fd_flags & VIRTIO_GPU_RESOURCE_FLAG_Y_0_TOP,
};
if (msg->request == VHOST_USER_GPU_DMABUF_SCANOUT2) {
VhostUserGpuDMABUFScanout2 *m2 = &msg->payload.dmabuf_scanout2;
dmabuf->modifier = m2->modifier;
dmabuf = g->dmabuf[m->scanout_id];
if (dmabuf) {
qemu_dmabuf_close(dmabuf);
dpy_gl_release_dmabuf(con, dmabuf);
g_clear_pointer(&dmabuf, qemu_dmabuf_free);
}
if (fd == -1) {
dpy_gl_scanout_disable(con);
g->dmabuf[m->scanout_id] = NULL;
break;
}
if (msg->request == VHOST_USER_GPU_DMABUF_SCANOUT2) {
VhostUserGpuDMABUFScanout2 *m2 = &msg->payload.dmabuf_scanout2;
modifier = m2->modifier;
}
dmabuf = qemu_dmabuf_new(m->fd_width, m->fd_height,
m->fd_stride, 0, 0, 0, 0,
m->fd_drm_fourcc, modifier,
fd, false, m->fd_flags &
VIRTIO_GPU_RESOURCE_FLAG_Y_0_TOP);
dpy_gl_scanout_dmabuf(con, dmabuf);
g->dmabuf[m->scanout_id] = dmabuf;
break;
}
case VHOST_USER_GPU_DMABUF_UPDATE: {

View File

@ -162,7 +162,8 @@ static void virtio_gpu_free_dmabuf(VirtIOGPU *g, VGPUDMABuf *dmabuf)
struct virtio_gpu_scanout *scanout;
scanout = &g->parent_obj.scanout[dmabuf->scanout_id];
dpy_gl_release_dmabuf(scanout->con, &dmabuf->buf);
dpy_gl_release_dmabuf(scanout->con, dmabuf->buf);
g_clear_pointer(&dmabuf->buf, qemu_dmabuf_free);
QTAILQ_REMOVE(&g->dmabuf.bufs, dmabuf, next);
g_free(dmabuf);
}
@ -181,17 +182,10 @@ static VGPUDMABuf
}
dmabuf = g_new0(VGPUDMABuf, 1);
dmabuf->buf.width = r->width;
dmabuf->buf.height = r->height;
dmabuf->buf.stride = fb->stride;
dmabuf->buf.x = r->x;
dmabuf->buf.y = r->y;
dmabuf->buf.backing_width = fb->width;
dmabuf->buf.backing_height = fb->height;
dmabuf->buf.fourcc = qemu_pixman_to_drm_format(fb->format);
dmabuf->buf.fd = res->dmabuf_fd;
dmabuf->buf.allow_fences = true;
dmabuf->buf.draw_submitted = false;
dmabuf->buf = qemu_dmabuf_new(r->width, r->height, fb->stride,
r->x, r->y, fb->width, fb->height,
qemu_pixman_to_drm_format(fb->format),
0, res->dmabuf_fd, true, false);
dmabuf->scanout_id = scanout_id;
QTAILQ_INSERT_HEAD(&g->dmabuf.bufs, dmabuf, next);
@ -206,6 +200,7 @@ int virtio_gpu_update_dmabuf(VirtIOGPU *g,
{
struct virtio_gpu_scanout *scanout = &g->parent_obj.scanout[scanout_id];
VGPUDMABuf *new_primary, *old_primary = NULL;
uint32_t width, height;
new_primary = virtio_gpu_create_dmabuf(g, scanout_id, res, fb, r);
if (!new_primary) {
@ -216,11 +211,11 @@ int virtio_gpu_update_dmabuf(VirtIOGPU *g,
old_primary = g->dmabuf.primary[scanout_id];
}
width = qemu_dmabuf_get_width(new_primary->buf);
height = qemu_dmabuf_get_height(new_primary->buf);
g->dmabuf.primary[scanout_id] = new_primary;
qemu_console_resize(scanout->con,
new_primary->buf.width,
new_primary->buf.height);
dpy_gl_scanout_dmabuf(scanout->con, &new_primary->buf);
qemu_console_resize(scanout->con, width, height);
dpy_gl_scanout_dmabuf(scanout->con, new_primary->buf);
if (old_primary) {
virtio_gpu_free_dmabuf(g, old_primary);

View File

@ -241,14 +241,11 @@ static VFIODMABuf *vfio_display_get_dmabuf(VFIOPCIDevice *vdev,
dmabuf = g_new0(VFIODMABuf, 1);
dmabuf->dmabuf_id = plane.dmabuf_id;
dmabuf->buf.width = plane.width;
dmabuf->buf.height = plane.height;
dmabuf->buf.backing_width = plane.width;
dmabuf->buf.backing_height = plane.height;
dmabuf->buf.stride = plane.stride;
dmabuf->buf.fourcc = plane.drm_format;
dmabuf->buf.modifier = plane.drm_format_mod;
dmabuf->buf.fd = fd;
dmabuf->buf = qemu_dmabuf_new(plane.width, plane.height,
plane.stride, 0, 0, plane.width,
plane.height, plane.drm_format,
plane.drm_format_mod, fd, false, false);
if (plane_type == DRM_PLANE_TYPE_CURSOR) {
vfio_display_update_cursor(dmabuf, &plane);
}
@ -260,8 +257,10 @@ static VFIODMABuf *vfio_display_get_dmabuf(VFIOPCIDevice *vdev,
static void vfio_display_free_one_dmabuf(VFIODisplay *dpy, VFIODMABuf *dmabuf)
{
QTAILQ_REMOVE(&dpy->dmabuf.bufs, dmabuf, next);
dpy_gl_release_dmabuf(dpy->con, &dmabuf->buf);
close(dmabuf->buf.fd);
qemu_dmabuf_close(dmabuf->buf);
dpy_gl_release_dmabuf(dpy->con, dmabuf->buf);
g_clear_pointer(&dmabuf->buf, qemu_dmabuf_free);
g_free(dmabuf);
}
@ -286,6 +285,7 @@ static void vfio_display_dmabuf_update(void *opaque)
VFIOPCIDevice *vdev = opaque;
VFIODisplay *dpy = vdev->dpy;
VFIODMABuf *primary, *cursor;
uint32_t width, height;
bool free_bufs = false, new_cursor = false;
primary = vfio_display_get_dmabuf(vdev, DRM_PLANE_TYPE_PRIMARY);
@ -296,11 +296,13 @@ static void vfio_display_dmabuf_update(void *opaque)
return;
}
width = qemu_dmabuf_get_width(primary->buf);
height = qemu_dmabuf_get_height(primary->buf);
if (dpy->dmabuf.primary != primary) {
dpy->dmabuf.primary = primary;
qemu_console_resize(dpy->con,
primary->buf.width, primary->buf.height);
dpy_gl_scanout_dmabuf(dpy->con, &primary->buf);
qemu_console_resize(dpy->con, width, height);
dpy_gl_scanout_dmabuf(dpy->con, primary->buf);
free_bufs = true;
}
@ -314,7 +316,7 @@ static void vfio_display_dmabuf_update(void *opaque)
if (cursor && (new_cursor || cursor->hot_updates)) {
bool have_hot = (cursor->hot_x != 0xffffffff &&
cursor->hot_y != 0xffffffff);
dpy_gl_cursor_dmabuf(dpy->con, &cursor->buf, have_hot,
dpy_gl_cursor_dmabuf(dpy->con, cursor->buf, have_hot,
cursor->hot_x, cursor->hot_y);
cursor->hot_updates = 0;
} else if (!cursor && new_cursor) {
@ -328,7 +330,7 @@ static void vfio_display_dmabuf_update(void *opaque)
cursor->pos_updates = 0;
}
dpy_gl_update(dpy->con, 0, 0, primary->buf.width, primary->buf.height);
dpy_gl_update(dpy->con, 0, 0, width, height);
if (free_bufs) {
vfio_display_free_dmabufs(vdev);

View File

@ -148,7 +148,7 @@ typedef struct VFIOGroup {
} VFIOGroup;
typedef struct VFIODMABuf {
QemuDmaBuf buf;
QemuDmaBuf *buf;
uint32_t pos_x, pos_y, pos_updates;
uint32_t hot_x, hot_y, hot_updates;
int dmabuf_id;

View File

@ -169,7 +169,7 @@ struct VirtIOGPUBaseClass {
DEFINE_PROP_UINT32("yres", _state, _conf.yres, 800)
typedef struct VGPUDMABuf {
QemuDmaBuf buf;
QemuDmaBuf *buf;
uint32_t scanout_id;
QTAILQ_ENTRY(VGPUDMABuf) next;
} VGPUDMABuf;
@ -238,7 +238,7 @@ struct VhostUserGPU {
VhostUserBackend *vhost;
int vhost_gpu_fd; /* closed by the chardev */
CharBackend vhost_chr;
QemuDmaBuf dmabuf[VIRTIO_GPU_MAX_SCANOUTS];
QemuDmaBuf *dmabuf[VIRTIO_GPU_MAX_SCANOUTS];
bool backend_blocked;
};

View File

@ -7,6 +7,7 @@
#include "qapi/qapi-types-ui.h"
#include "ui/input.h"
#include "ui/surface.h"
#include "ui/dmabuf.h"
#define TYPE_QEMU_CONSOLE "qemu-console"
OBJECT_DECLARE_TYPE(QemuConsole, QemuConsoleClass, QEMU_CONSOLE)
@ -185,25 +186,6 @@ struct QEMUGLParams {
int minor_ver;
};
typedef struct QemuDmaBuf {
int fd;
uint32_t width;
uint32_t height;
uint32_t stride;
uint32_t fourcc;
uint64_t modifier;
uint32_t texture;
uint32_t x;
uint32_t y;
uint32_t backing_width;
uint32_t backing_height;
bool y0_top;
void *sync;
int fence_fd;
bool allow_fences;
bool draw_submitted;
} QemuDmaBuf;
enum display_scanout {
SCANOUT_NONE,
SCANOUT_SURFACE,

49
include/ui/dmabuf.h Normal file
View File

@ -0,0 +1,49 @@
/*
* SPDX-License-Identifier: GPL-2.0-or-later
*
* QemuDmaBuf struct and helpers used for accessing its data
*
* This work is licensed under the terms of the GNU GPL, version 2 or later.
* See the COPYING file in the top-level directory.
*/
#ifndef DMABUF_H
#define DMABUF_H
typedef struct QemuDmaBuf QemuDmaBuf;
QemuDmaBuf *qemu_dmabuf_new(uint32_t width, uint32_t height,
uint32_t stride, uint32_t x,
uint32_t y, uint32_t backing_width,
uint32_t backing_height, uint32_t fourcc,
uint64_t modifier, int dmabuf_fd,
bool allow_fences, bool y0_top);
void qemu_dmabuf_free(QemuDmaBuf *dmabuf);
G_DEFINE_AUTOPTR_CLEANUP_FUNC(QemuDmaBuf, qemu_dmabuf_free);
int qemu_dmabuf_get_fd(QemuDmaBuf *dmabuf);
int qemu_dmabuf_dup_fd(QemuDmaBuf *dmabuf);
void qemu_dmabuf_close(QemuDmaBuf *dmabuf);
uint32_t qemu_dmabuf_get_width(QemuDmaBuf *dmabuf);
uint32_t qemu_dmabuf_get_height(QemuDmaBuf *dmabuf);
uint32_t qemu_dmabuf_get_stride(QemuDmaBuf *dmabuf);
uint32_t qemu_dmabuf_get_fourcc(QemuDmaBuf *dmabuf);
uint64_t qemu_dmabuf_get_modifier(QemuDmaBuf *dmabuf);
uint32_t qemu_dmabuf_get_texture(QemuDmaBuf *dmabuf);
uint32_t qemu_dmabuf_get_x(QemuDmaBuf *dmabuf);
uint32_t qemu_dmabuf_get_y(QemuDmaBuf *dmabuf);
uint32_t qemu_dmabuf_get_backing_width(QemuDmaBuf *dmabuf);
uint32_t qemu_dmabuf_get_backing_height(QemuDmaBuf *dmabuf);
bool qemu_dmabuf_get_y0_top(QemuDmaBuf *dmabuf);
void *qemu_dmabuf_get_sync(QemuDmaBuf *dmabuf);
int32_t qemu_dmabuf_get_fence_fd(QemuDmaBuf *dmabuf);
bool qemu_dmabuf_get_allow_fences(QemuDmaBuf *dmabuf);
bool qemu_dmabuf_get_draw_submitted(QemuDmaBuf *dmabuf);
void qemu_dmabuf_set_texture(QemuDmaBuf *dmabuf, uint32_t texture);
void qemu_dmabuf_set_fence_fd(QemuDmaBuf *dmabuf, int32_t fence_fd);
void qemu_dmabuf_set_sync(QemuDmaBuf *dmabuf, void *sync);
void qemu_dmabuf_set_draw_submitted(QemuDmaBuf *dmabuf, bool draw_submitted);
void qemu_dmabuf_set_fd(QemuDmaBuf *dmabuf, int32_t fd);
#endif

View File

@ -2516,6 +2516,10 @@ SRST
host. It is possible to control the websocket listen address
independently, using the syntax ``websocket``\ =host:port.
Websocket could be allowed over UNIX domain socket, using the syntax
``websocket``\ =unix:path, where path is the location of a unix socket
to listen for connections on.
If no TLS credentials are provided, the websocket connection
runs in unencrypted mode. If TLS credentials are provided, the
websocket connection requires encrypted client connections.

View File

@ -1459,7 +1459,7 @@ int qemu_console_get_width(QemuConsole *con, int fallback)
}
switch (con->scanout.kind) {
case SCANOUT_DMABUF:
return con->scanout.dmabuf->width;
return qemu_dmabuf_get_width(con->scanout.dmabuf);
case SCANOUT_TEXTURE:
return con->scanout.texture.width;
case SCANOUT_SURFACE:
@ -1476,7 +1476,7 @@ int qemu_console_get_height(QemuConsole *con, int fallback)
}
switch (con->scanout.kind) {
case SCANOUT_DMABUF:
return con->scanout.dmabuf->height;
return qemu_dmabuf_get_height(con->scanout.dmabuf);
case SCANOUT_TEXTURE:
return con->scanout.texture.height;
case SCANOUT_SURFACE:

View File

@ -110,11 +110,14 @@ static void
dbus_gl_scanout_dmabuf(DisplayChangeListener *dcl,
QemuDmaBuf *dmabuf)
{
uint32_t width, height;
DBusDisplayConsole *ddc = container_of(dcl, DBusDisplayConsole, dcl);
dbus_display_console_set_size(ddc,
dmabuf->width,
dmabuf->height);
width = qemu_dmabuf_get_width(dmabuf);
height = qemu_dmabuf_get_height(dmabuf);
dbus_display_console_set_size(ddc, width, height);
}
static void

View File

@ -278,29 +278,33 @@ static void dbus_scanout_dmabuf(DisplayChangeListener *dcl,
DBusDisplayListener *ddl = container_of(dcl, DBusDisplayListener, dcl);
g_autoptr(GError) err = NULL;
g_autoptr(GUnixFDList) fd_list = NULL;
int fd;
uint32_t width, height, stride, fourcc;
uint64_t modifier;
bool y0_top;
fd = qemu_dmabuf_get_fd(dmabuf);
fd_list = g_unix_fd_list_new();
if (g_unix_fd_list_append(fd_list, dmabuf->fd, &err) != 0) {
if (g_unix_fd_list_append(fd_list, fd, &err) != 0) {
error_report("Failed to setup dmabuf fdlist: %s", err->message);
return;
}
ddl_discard_pending_messages(ddl);
width = qemu_dmabuf_get_width(dmabuf);
height = qemu_dmabuf_get_height(dmabuf);
stride = qemu_dmabuf_get_stride(dmabuf);
fourcc = qemu_dmabuf_get_fourcc(dmabuf);
modifier = qemu_dmabuf_get_modifier(dmabuf);
y0_top = qemu_dmabuf_get_y0_top(dmabuf);
/* FIXME: add missing x/y/w/h support */
qemu_dbus_display1_listener_call_scanout_dmabuf(
ddl->proxy,
g_variant_new_handle(0),
dmabuf->width,
dmabuf->height,
dmabuf->stride,
dmabuf->fourcc,
dmabuf->modifier,
dmabuf->y0_top,
G_DBUS_CALL_FLAGS_NONE,
-1,
fd_list,
NULL, NULL, NULL);
ddl->proxy, g_variant_new_handle(0),
width, height, stride, fourcc, modifier,
y0_top, G_DBUS_CALL_FLAGS_NONE,
-1, fd_list, NULL, NULL, NULL);
}
#endif /* GBM */
#endif /* OPENGL */
@ -438,28 +442,24 @@ static void dbus_scanout_texture(DisplayChangeListener *dcl,
trace_dbus_scanout_texture(tex_id, backing_y_0_top,
backing_width, backing_height, x, y, w, h);
#ifdef CONFIG_GBM
QemuDmaBuf dmabuf = {
.width = w,
.height = h,
.y0_top = backing_y_0_top,
.x = x,
.y = y,
.backing_width = backing_width,
.backing_height = backing_height,
};
g_autoptr(QemuDmaBuf) dmabuf = NULL;
int fd;
uint32_t stride, fourcc;
uint64_t modifier;
assert(tex_id);
dmabuf.fd = egl_get_fd_for_texture(
tex_id, (EGLint *)&dmabuf.stride,
(EGLint *)&dmabuf.fourcc,
&dmabuf.modifier);
if (dmabuf.fd < 0) {
fd = egl_get_fd_for_texture(tex_id, (EGLint *)&stride, (EGLint *)&fourcc,
&modifier);
if (fd < 0) {
error_report("%s: failed to get fd for texture", __func__);
return;
}
dmabuf = qemu_dmabuf_new(w, h, stride, x, y, backing_width,
backing_height, fourcc, modifier, fd,
false, backing_y_0_top);
dbus_scanout_dmabuf(dcl, &dmabuf);
close(dmabuf.fd);
dbus_scanout_dmabuf(dcl, dmabuf);
qemu_dmabuf_close(dmabuf);
#endif
#ifdef WIN32
@ -488,6 +488,7 @@ static void dbus_cursor_dmabuf(DisplayChangeListener *dcl,
DisplaySurface *ds;
GVariant *v_data = NULL;
egl_fb cursor_fb = EGL_FB_INIT;
uint32_t width, height, texture;
if (!dmabuf) {
qemu_dbus_display1_listener_call_mouse_set(
@ -497,12 +498,16 @@ static void dbus_cursor_dmabuf(DisplayChangeListener *dcl,
}
egl_dmabuf_import_texture(dmabuf);
if (!dmabuf->texture) {
texture = qemu_dmabuf_get_texture(dmabuf);
if (!texture) {
return;
}
egl_fb_setup_for_tex(&cursor_fb, dmabuf->width, dmabuf->height,
dmabuf->texture, false);
ds = qemu_create_displaysurface(dmabuf->width, dmabuf->height);
width = qemu_dmabuf_get_width(dmabuf);
height = qemu_dmabuf_get_height(dmabuf);
egl_fb_setup_for_tex(&cursor_fb, width, height, texture, false);
ds = qemu_create_displaysurface(width, height);
egl_fb_read(ds, &cursor_fb);
v_data = g_variant_new_from_data(

229
ui/dmabuf.c Normal file
View File

@ -0,0 +1,229 @@
/*
* SPDX-License-Identifier: GPL-2.0-or-later
*
* QemuDmaBuf struct and helpers used for accessing its data
*
* 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 "ui/dmabuf.h"
struct QemuDmaBuf {
int fd;
uint32_t width;
uint32_t height;
uint32_t stride;
uint32_t fourcc;
uint64_t modifier;
uint32_t texture;
uint32_t x;
uint32_t y;
uint32_t backing_width;
uint32_t backing_height;
bool y0_top;
void *sync;
int fence_fd;
bool allow_fences;
bool draw_submitted;
};
QemuDmaBuf *qemu_dmabuf_new(uint32_t width, uint32_t height,
uint32_t stride, uint32_t x,
uint32_t y, uint32_t backing_width,
uint32_t backing_height, uint32_t fourcc,
uint64_t modifier, int32_t dmabuf_fd,
bool allow_fences, bool y0_top) {
QemuDmaBuf *dmabuf;
dmabuf = g_new0(QemuDmaBuf, 1);
dmabuf->width = width;
dmabuf->height = height;
dmabuf->stride = stride;
dmabuf->x = x;
dmabuf->y = y;
dmabuf->backing_width = backing_width;
dmabuf->backing_height = backing_height;
dmabuf->fourcc = fourcc;
dmabuf->modifier = modifier;
dmabuf->fd = dmabuf_fd;
dmabuf->allow_fences = allow_fences;
dmabuf->y0_top = y0_top;
dmabuf->fence_fd = -1;
return dmabuf;
}
void qemu_dmabuf_free(QemuDmaBuf *dmabuf)
{
if (dmabuf == NULL) {
return;
}
g_free(dmabuf);
}
int qemu_dmabuf_get_fd(QemuDmaBuf *dmabuf)
{
assert(dmabuf != NULL);
return dmabuf->fd;
}
int qemu_dmabuf_dup_fd(QemuDmaBuf *dmabuf)
{
assert(dmabuf != NULL);
if (dmabuf->fd >= 0) {
return dup(dmabuf->fd);
} else {
return -1;
}
}
void qemu_dmabuf_close(QemuDmaBuf *dmabuf)
{
assert(dmabuf != NULL);
if (dmabuf->fd >= 0) {
close(dmabuf->fd);
dmabuf->fd = -1;
}
}
uint32_t qemu_dmabuf_get_width(QemuDmaBuf *dmabuf)
{
assert(dmabuf != NULL);
return dmabuf->width;
}
uint32_t qemu_dmabuf_get_height(QemuDmaBuf *dmabuf)
{
assert(dmabuf != NULL);
return dmabuf->height;
}
uint32_t qemu_dmabuf_get_stride(QemuDmaBuf *dmabuf)
{
assert(dmabuf != NULL);
return dmabuf->stride;
}
uint32_t qemu_dmabuf_get_fourcc(QemuDmaBuf *dmabuf)
{
assert(dmabuf != NULL);
return dmabuf->fourcc;
}
uint64_t qemu_dmabuf_get_modifier(QemuDmaBuf *dmabuf)
{
assert(dmabuf != NULL);
return dmabuf->modifier;
}
uint32_t qemu_dmabuf_get_texture(QemuDmaBuf *dmabuf)
{
assert(dmabuf != NULL);
return dmabuf->texture;
}
uint32_t qemu_dmabuf_get_x(QemuDmaBuf *dmabuf)
{
assert(dmabuf != NULL);
return dmabuf->x;
}
uint32_t qemu_dmabuf_get_y(QemuDmaBuf *dmabuf)
{
assert(dmabuf != NULL);
return dmabuf->y;
}
uint32_t qemu_dmabuf_get_backing_width(QemuDmaBuf *dmabuf)
{
assert(dmabuf != NULL);
return dmabuf->backing_width;
}
uint32_t qemu_dmabuf_get_backing_height(QemuDmaBuf *dmabuf)
{
assert(dmabuf != NULL);
return dmabuf->backing_height;
}
bool qemu_dmabuf_get_y0_top(QemuDmaBuf *dmabuf)
{
assert(dmabuf != NULL);
return dmabuf->y0_top;
}
void *qemu_dmabuf_get_sync(QemuDmaBuf *dmabuf)
{
assert(dmabuf != NULL);
return dmabuf->sync;
}
int32_t qemu_dmabuf_get_fence_fd(QemuDmaBuf *dmabuf)
{
assert(dmabuf != NULL);
return dmabuf->fence_fd;
}
bool qemu_dmabuf_get_allow_fences(QemuDmaBuf *dmabuf)
{
assert(dmabuf != NULL);
return dmabuf->allow_fences;
}
bool qemu_dmabuf_get_draw_submitted(QemuDmaBuf *dmabuf)
{
assert(dmabuf != NULL);
return dmabuf->draw_submitted;
}
void qemu_dmabuf_set_texture(QemuDmaBuf *dmabuf, uint32_t texture)
{
assert(dmabuf != NULL);
dmabuf->texture = texture;
}
void qemu_dmabuf_set_fence_fd(QemuDmaBuf *dmabuf, int32_t fence_fd)
{
assert(dmabuf != NULL);
dmabuf->fence_fd = fence_fd;
}
void qemu_dmabuf_set_sync(QemuDmaBuf *dmabuf, void *sync)
{
assert(dmabuf != NULL);
dmabuf->sync = sync;
}
void qemu_dmabuf_set_draw_submitted(QemuDmaBuf *dmabuf, bool draw_submitted)
{
assert(dmabuf != NULL);
dmabuf->draw_submitted = draw_submitted;
}
void qemu_dmabuf_set_fd(QemuDmaBuf *dmabuf, int32_t fd)
{
assert(dmabuf != NULL);
dmabuf->fd = fd;
}

View File

@ -85,29 +85,38 @@ static void egl_scanout_texture(DisplayChangeListener *dcl,
static void egl_scanout_dmabuf(DisplayChangeListener *dcl,
QemuDmaBuf *dmabuf)
{
uint32_t width, height, texture;
egl_dmabuf_import_texture(dmabuf);
if (!dmabuf->texture) {
texture = qemu_dmabuf_get_texture(dmabuf);
if (!texture) {
return;
}
egl_scanout_texture(dcl, dmabuf->texture,
false, dmabuf->width, dmabuf->height,
0, 0, dmabuf->width, dmabuf->height, NULL);
width = qemu_dmabuf_get_width(dmabuf);
height = qemu_dmabuf_get_height(dmabuf);
egl_scanout_texture(dcl, texture, false, width, height, 0, 0,
width, height, NULL);
}
static void egl_cursor_dmabuf(DisplayChangeListener *dcl,
QemuDmaBuf *dmabuf, bool have_hot,
uint32_t hot_x, uint32_t hot_y)
{
uint32_t width, height, texture;
egl_dpy *edpy = container_of(dcl, egl_dpy, dcl);
if (dmabuf) {
egl_dmabuf_import_texture(dmabuf);
if (!dmabuf->texture) {
texture = qemu_dmabuf_get_texture(dmabuf);
if (!texture) {
return;
}
egl_fb_setup_for_tex(&edpy->cursor_fb, dmabuf->width, dmabuf->height,
dmabuf->texture, false);
width = qemu_dmabuf_get_width(dmabuf);
height = qemu_dmabuf_get_height(dmabuf);
egl_fb_setup_for_tex(&edpy->cursor_fb, width, height, texture, false);
} else {
egl_fb_destroy(&edpy->cursor_fb);
}

View File

@ -146,10 +146,10 @@ void egl_fb_blit(egl_fb *dst, egl_fb *src, bool flip)
glViewport(0, 0, dst->width, dst->height);
if (src->dmabuf) {
x1 = src->dmabuf->x;
y1 = src->dmabuf->y;
w = src->dmabuf->width;
h = src->dmabuf->height;
x1 = qemu_dmabuf_get_x(src->dmabuf);
y1 = qemu_dmabuf_get_y(src->dmabuf);
w = qemu_dmabuf_get_width(src->dmabuf);
h = qemu_dmabuf_get_height(src->dmabuf);
}
w = (x1 + w) > src->width ? src->width - x1 : w;
@ -308,30 +308,33 @@ void egl_dmabuf_import_texture(QemuDmaBuf *dmabuf)
EGLImageKHR image = EGL_NO_IMAGE_KHR;
EGLint attrs[64];
int i = 0;
uint64_t modifier;
uint32_t texture = qemu_dmabuf_get_texture(dmabuf);
if (dmabuf->texture != 0) {
if (texture != 0) {
return;
}
attrs[i++] = EGL_WIDTH;
attrs[i++] = dmabuf->backing_width;
attrs[i++] = qemu_dmabuf_get_backing_width(dmabuf);
attrs[i++] = EGL_HEIGHT;
attrs[i++] = dmabuf->backing_height;
attrs[i++] = qemu_dmabuf_get_backing_height(dmabuf);
attrs[i++] = EGL_LINUX_DRM_FOURCC_EXT;
attrs[i++] = dmabuf->fourcc;
attrs[i++] = qemu_dmabuf_get_fourcc(dmabuf);
attrs[i++] = EGL_DMA_BUF_PLANE0_FD_EXT;
attrs[i++] = dmabuf->fd;
attrs[i++] = qemu_dmabuf_get_fd(dmabuf);
attrs[i++] = EGL_DMA_BUF_PLANE0_PITCH_EXT;
attrs[i++] = dmabuf->stride;
attrs[i++] = qemu_dmabuf_get_stride(dmabuf);
attrs[i++] = EGL_DMA_BUF_PLANE0_OFFSET_EXT;
attrs[i++] = 0;
#ifdef EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT
if (dmabuf->modifier) {
modifier = qemu_dmabuf_get_modifier(dmabuf);
if (modifier) {
attrs[i++] = EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT;
attrs[i++] = (dmabuf->modifier >> 0) & 0xffffffff;
attrs[i++] = (modifier >> 0) & 0xffffffff;
attrs[i++] = EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT;
attrs[i++] = (dmabuf->modifier >> 32) & 0xffffffff;
attrs[i++] = (modifier >> 32) & 0xffffffff;
}
#endif
attrs[i++] = EGL_NONE;
@ -345,8 +348,9 @@ void egl_dmabuf_import_texture(QemuDmaBuf *dmabuf)
return;
}
glGenTextures(1, &dmabuf->texture);
glBindTexture(GL_TEXTURE_2D, dmabuf->texture);
glGenTextures(1, &texture);
qemu_dmabuf_set_texture(dmabuf, texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
@ -356,12 +360,15 @@ void egl_dmabuf_import_texture(QemuDmaBuf *dmabuf)
void egl_dmabuf_release_texture(QemuDmaBuf *dmabuf)
{
if (dmabuf->texture == 0) {
uint32_t texture;
texture = qemu_dmabuf_get_texture(dmabuf);
if (texture == 0) {
return;
}
glDeleteTextures(1, &dmabuf->texture);
dmabuf->texture = 0;
glDeleteTextures(1, &texture);
qemu_dmabuf_set_texture(dmabuf, 0);
}
void egl_dmabuf_create_sync(QemuDmaBuf *dmabuf)
@ -375,18 +382,22 @@ void egl_dmabuf_create_sync(QemuDmaBuf *dmabuf)
sync = eglCreateSyncKHR(qemu_egl_display,
EGL_SYNC_NATIVE_FENCE_ANDROID, NULL);
if (sync != EGL_NO_SYNC_KHR) {
dmabuf->sync = sync;
qemu_dmabuf_set_sync(dmabuf, sync);
}
}
}
void egl_dmabuf_create_fence(QemuDmaBuf *dmabuf)
{
if (dmabuf->sync) {
dmabuf->fence_fd = eglDupNativeFenceFDANDROID(qemu_egl_display,
dmabuf->sync);
eglDestroySyncKHR(qemu_egl_display, dmabuf->sync);
dmabuf->sync = NULL;
void *sync = qemu_dmabuf_get_sync(dmabuf);
int fence_fd;
if (sync) {
fence_fd = eglDupNativeFenceFDANDROID(qemu_egl_display,
sync);
qemu_dmabuf_set_fence_fd(dmabuf, fence_fd);
eglDestroySyncKHR(qemu_egl_display, sync);
qemu_dmabuf_set_sync(dmabuf, NULL);
}
}

View File

@ -70,6 +70,7 @@ void gd_egl_draw(VirtualConsole *vc)
QemuDmaBuf *dmabuf = vc->gfx.guest_fb.dmabuf;
#endif
int ww, wh, ws;
int fence_fd;
if (!vc->gfx.gls) {
return;
@ -83,10 +84,10 @@ void gd_egl_draw(VirtualConsole *vc)
if (vc->gfx.scanout_mode) {
#ifdef CONFIG_GBM
if (dmabuf) {
if (!dmabuf->draw_submitted) {
if (!qemu_dmabuf_get_draw_submitted(dmabuf)) {
return;
} else {
dmabuf->draw_submitted = false;
qemu_dmabuf_set_draw_submitted(dmabuf, false);
}
}
#endif
@ -99,8 +100,9 @@ void gd_egl_draw(VirtualConsole *vc)
#ifdef CONFIG_GBM
if (dmabuf) {
egl_dmabuf_create_fence(dmabuf);
if (dmabuf->fence_fd > 0) {
qemu_set_fd_handler(dmabuf->fence_fd, gd_hw_gl_flushed, NULL, vc);
fence_fd = qemu_dmabuf_get_fence_fd(dmabuf);
if (fence_fd >= 0) {
qemu_set_fd_handler(fence_fd, gd_hw_gl_flushed, NULL, vc);
return;
}
graphic_hw_gl_block(vc->gfx.dcl.con, false);
@ -149,7 +151,9 @@ void gd_egl_refresh(DisplayChangeListener *dcl)
gd_update_monitor_refresh_rate(
vc, vc->window ? vc->window : vc->gfx.drawing_area);
if (vc->gfx.guest_fb.dmabuf && vc->gfx.guest_fb.dmabuf->draw_submitted) {
if (vc->gfx.guest_fb.dmabuf &&
qemu_dmabuf_get_draw_submitted(vc->gfx.guest_fb.dmabuf)) {
gd_egl_draw(vc);
return;
}
@ -264,22 +268,30 @@ void gd_egl_scanout_dmabuf(DisplayChangeListener *dcl,
{
#ifdef CONFIG_GBM
VirtualConsole *vc = container_of(dcl, VirtualConsole, gfx.dcl);
uint32_t x, y, width, height, backing_width, backing_height, texture;
bool y0_top;
eglMakeCurrent(qemu_egl_display, vc->gfx.esurface,
vc->gfx.esurface, vc->gfx.ectx);
egl_dmabuf_import_texture(dmabuf);
if (!dmabuf->texture) {
texture = qemu_dmabuf_get_texture(dmabuf);
if (!texture) {
return;
}
gd_egl_scanout_texture(dcl, dmabuf->texture,
dmabuf->y0_top,
dmabuf->backing_width, dmabuf->backing_height,
dmabuf->x, dmabuf->y, dmabuf->width,
dmabuf->height, NULL);
x = qemu_dmabuf_get_x(dmabuf);
y = qemu_dmabuf_get_y(dmabuf);
width = qemu_dmabuf_get_width(dmabuf);
height = qemu_dmabuf_get_height(dmabuf);
backing_width = qemu_dmabuf_get_backing_width(dmabuf);
backing_height = qemu_dmabuf_get_backing_height(dmabuf);
y0_top = qemu_dmabuf_get_y0_top(dmabuf);
if (dmabuf->allow_fences) {
gd_egl_scanout_texture(dcl, texture, y0_top, backing_width, backing_height,
x, y, width, height, NULL);
if (qemu_dmabuf_get_allow_fences(dmabuf)) {
vc->gfx.guest_fb.dmabuf = dmabuf;
}
#endif
@ -291,15 +303,19 @@ void gd_egl_cursor_dmabuf(DisplayChangeListener *dcl,
{
#ifdef CONFIG_GBM
VirtualConsole *vc = container_of(dcl, VirtualConsole, gfx.dcl);
uint32_t backing_width, backing_height, texture;
if (dmabuf) {
egl_dmabuf_import_texture(dmabuf);
if (!dmabuf->texture) {
texture = qemu_dmabuf_get_texture(dmabuf);
if (!texture) {
return;
}
egl_fb_setup_for_tex(&vc->gfx.cursor_fb,
dmabuf->backing_width, dmabuf->backing_height,
dmabuf->texture, false);
backing_width = qemu_dmabuf_get_backing_width(dmabuf);
backing_height = qemu_dmabuf_get_backing_height(dmabuf);
egl_fb_setup_for_tex(&vc->gfx.cursor_fb, backing_width, backing_height,
texture, false);
} else {
egl_fb_destroy(&vc->gfx.cursor_fb);
}
@ -363,9 +379,10 @@ void gd_egl_flush(DisplayChangeListener *dcl,
VirtualConsole *vc = container_of(dcl, VirtualConsole, gfx.dcl);
GtkWidget *area = vc->gfx.drawing_area;
if (vc->gfx.guest_fb.dmabuf && !vc->gfx.guest_fb.dmabuf->draw_submitted) {
if (vc->gfx.guest_fb.dmabuf &&
!qemu_dmabuf_get_draw_submitted(vc->gfx.guest_fb.dmabuf)) {
graphic_hw_gl_block(vc->gfx.dcl.con, true);
vc->gfx.guest_fb.dmabuf->draw_submitted = true;
qemu_dmabuf_set_draw_submitted(vc->gfx.guest_fb.dmabuf, true);
gtk_egl_set_scanout_mode(vc, true);
gtk_widget_queue_draw_area(area, x, y, w, h);
return;

View File

@ -60,10 +60,10 @@ void gd_gl_area_draw(VirtualConsole *vc)
#ifdef CONFIG_GBM
if (dmabuf) {
if (!dmabuf->draw_submitted) {
if (!qemu_dmabuf_get_draw_submitted(dmabuf)) {
return;
} else {
dmabuf->draw_submitted = false;
qemu_dmabuf_set_draw_submitted(dmabuf, false);
}
}
#endif
@ -85,9 +85,11 @@ void gd_gl_area_draw(VirtualConsole *vc)
glFlush();
#ifdef CONFIG_GBM
if (dmabuf) {
int fence_fd;
egl_dmabuf_create_fence(dmabuf);
if (dmabuf->fence_fd > 0) {
qemu_set_fd_handler(dmabuf->fence_fd, gd_hw_gl_flushed, NULL, vc);
fence_fd = qemu_dmabuf_get_fence_fd(dmabuf);
if (fence_fd >= 0) {
qemu_set_fd_handler(fence_fd, gd_hw_gl_flushed, NULL, vc);
return;
}
graphic_hw_gl_block(vc->gfx.dcl.con, false);
@ -125,7 +127,9 @@ void gd_gl_area_refresh(DisplayChangeListener *dcl)
gd_update_monitor_refresh_rate(vc, vc->window ? vc->window : vc->gfx.drawing_area);
if (vc->gfx.guest_fb.dmabuf && vc->gfx.guest_fb.dmabuf->draw_submitted) {
if (vc->gfx.guest_fb.dmabuf &&
qemu_dmabuf_get_draw_submitted(vc->gfx.guest_fb.dmabuf)) {
gd_gl_area_draw(vc);
return;
}
@ -285,9 +289,10 @@ void gd_gl_area_scanout_flush(DisplayChangeListener *dcl,
{
VirtualConsole *vc = container_of(dcl, VirtualConsole, gfx.dcl);
if (vc->gfx.guest_fb.dmabuf && !vc->gfx.guest_fb.dmabuf->draw_submitted) {
if (vc->gfx.guest_fb.dmabuf &&
!qemu_dmabuf_get_draw_submitted(vc->gfx.guest_fb.dmabuf)) {
graphic_hw_gl_block(vc->gfx.dcl.con, true);
vc->gfx.guest_fb.dmabuf->draw_submitted = true;
qemu_dmabuf_set_draw_submitted(vc->gfx.guest_fb.dmabuf, true);
gtk_gl_area_set_scanout_mode(vc, true);
}
gtk_gl_area_queue_render(GTK_GL_AREA(vc->gfx.drawing_area));
@ -298,20 +303,29 @@ void gd_gl_area_scanout_dmabuf(DisplayChangeListener *dcl,
{
#ifdef CONFIG_GBM
VirtualConsole *vc = container_of(dcl, VirtualConsole, gfx.dcl);
uint32_t x, y, width, height, backing_width, backing_height, texture;
bool y0_top;
gtk_gl_area_make_current(GTK_GL_AREA(vc->gfx.drawing_area));
egl_dmabuf_import_texture(dmabuf);
if (!dmabuf->texture) {
texture = qemu_dmabuf_get_texture(dmabuf);
if (!texture) {
return;
}
gd_gl_area_scanout_texture(dcl, dmabuf->texture,
dmabuf->y0_top,
dmabuf->backing_width, dmabuf->backing_height,
dmabuf->x, dmabuf->y, dmabuf->width,
dmabuf->height, NULL);
x = qemu_dmabuf_get_x(dmabuf);
y = qemu_dmabuf_get_y(dmabuf);
width = qemu_dmabuf_get_width(dmabuf);
height = qemu_dmabuf_get_height(dmabuf);
backing_width = qemu_dmabuf_get_backing_width(dmabuf);
backing_height = qemu_dmabuf_get_backing_height(dmabuf);
y0_top = qemu_dmabuf_get_y0_top(dmabuf);
if (dmabuf->allow_fences) {
gd_gl_area_scanout_texture(dcl, texture, y0_top,
backing_width, backing_height,
x, y, width, height, NULL);
if (qemu_dmabuf_get_allow_fences(dmabuf)) {
vc->gfx.guest_fb.dmabuf = dmabuf;
}
#endif

View File

@ -596,11 +596,15 @@ void gd_hw_gl_flushed(void *vcon)
{
VirtualConsole *vc = vcon;
QemuDmaBuf *dmabuf = vc->gfx.guest_fb.dmabuf;
int fence_fd;
qemu_set_fd_handler(dmabuf->fence_fd, NULL, NULL, NULL);
close(dmabuf->fence_fd);
dmabuf->fence_fd = -1;
graphic_hw_gl_block(vc->gfx.dcl.con, false);
fence_fd = qemu_dmabuf_get_fence_fd(dmabuf);
if (fence_fd >= 0) {
qemu_set_fd_handler(fence_fd, NULL, NULL, NULL);
close(fence_fd);
qemu_dmabuf_set_fence_fd(dmabuf, -1);
graphic_hw_gl_block(vc->gfx.dcl.con, false);
}
}
/** DisplayState Callbacks (opengl version) **/
@ -887,7 +891,7 @@ static gboolean gd_motion_event(GtkWidget *widget, GdkEventMotion *motion,
int x, y;
int mx, my;
int fbh, fbw;
int ww, wh, ws;
int ww, wh;
if (!vc->gfx.ds) {
return TRUE;
@ -895,11 +899,15 @@ static gboolean gd_motion_event(GtkWidget *widget, GdkEventMotion *motion,
fbw = surface_width(vc->gfx.ds) * vc->gfx.scale_x;
fbh = surface_height(vc->gfx.ds) * vc->gfx.scale_y;
ww = gtk_widget_get_allocated_width(widget);
wh = gtk_widget_get_allocated_height(widget);
ws = gtk_widget_get_scale_factor(widget);
/*
* `widget` may not have the same size with the frame buffer.
* In such cases, some paddings are needed around the `vc`.
* To achieve that, `vc` will be displayed at (mx, my)
* so that it is displayed at the center of the widget.
*/
mx = my = 0;
if (ww > fbw) {
mx = (ww - fbw) / 2;
@ -908,8 +916,14 @@ static gboolean gd_motion_event(GtkWidget *widget, GdkEventMotion *motion,
my = (wh - fbh) / 2;
}
x = (motion->x - mx) / vc->gfx.scale_x * ws;
y = (motion->y - my) / vc->gfx.scale_y * ws;
/*
* `motion` is reported in `widget` coordinates
* so translating it to the coordinates in `vc`.
*/
x = (motion->x - mx) / vc->gfx.scale_x;
y = (motion->y - my) / vc->gfx.scale_y;
trace_gd_motion_event(ww, wh, gtk_widget_get_scale_factor(widget), x, y);
if (qemu_input_is_absolute(vc->gfx.dcl.con)) {
if (x < 0 || y < 0 ||

View File

@ -7,6 +7,7 @@ system_ss.add(files(
'clipboard.c',
'console.c',
'cursor.c',
'dmabuf.c',
'input-keymap.c',
'input-legacy.c',
'input-barrier.c',

View File

@ -874,6 +874,7 @@ static void sdl2_display_init(DisplayState *ds, DisplayOptions *o)
SDL_SetHint(SDL_HINT_ALLOW_ALT_TAB_WHILE_GRABBED, "0");
#endif
SDL_SetHint(SDL_HINT_WINDOWS_NO_CLOSE_ON_ALT_F4, "1");
SDL_EnableScreenSaver();
memset(&info, 0, sizeof(info));
SDL_VERSION(&info.version);

View File

@ -976,6 +976,7 @@ static void qemu_spice_gl_cursor_dmabuf(DisplayChangeListener *dcl,
uint32_t hot_x, uint32_t hot_y)
{
SimpleSpiceDisplay *ssd = container_of(dcl, SimpleSpiceDisplay, dcl);
uint32_t width, height, texture;
ssd->have_hot = have_hot;
ssd->hot_x = hot_x;
@ -984,11 +985,13 @@ static void qemu_spice_gl_cursor_dmabuf(DisplayChangeListener *dcl,
trace_qemu_spice_gl_cursor(ssd->qxl.id, dmabuf != NULL, have_hot);
if (dmabuf) {
egl_dmabuf_import_texture(dmabuf);
if (!dmabuf->texture) {
texture = qemu_dmabuf_get_texture(dmabuf);
if (!texture) {
return;
}
egl_fb_setup_for_tex(&ssd->cursor_fb, dmabuf->width, dmabuf->height,
dmabuf->texture, false);
width = qemu_dmabuf_get_width(dmabuf);
height = qemu_dmabuf_get_height(dmabuf);
egl_fb_setup_for_tex(&ssd->cursor_fb, width, height, texture, false);
} else {
egl_fb_destroy(&ssd->cursor_fb);
}
@ -1026,6 +1029,7 @@ static void qemu_spice_gl_update(DisplayChangeListener *dcl,
bool y_0_top = false; /* FIXME */
uint64_t cookie;
int fd;
uint32_t width, height, texture;
if (!ssd->have_scanout) {
return;
@ -1042,41 +1046,45 @@ static void qemu_spice_gl_update(DisplayChangeListener *dcl,
if (ssd->guest_dmabuf_refresh) {
QemuDmaBuf *dmabuf = ssd->guest_dmabuf;
width = qemu_dmabuf_get_width(dmabuf);
height = qemu_dmabuf_get_height(dmabuf);
if (render_cursor) {
egl_dmabuf_import_texture(dmabuf);
if (!dmabuf->texture) {
texture = qemu_dmabuf_get_texture(dmabuf);
if (!texture) {
return;
}
/* source framebuffer */
egl_fb_setup_for_tex(&ssd->guest_fb,
dmabuf->width, dmabuf->height,
dmabuf->texture, false);
egl_fb_setup_for_tex(&ssd->guest_fb, width, height,
texture, false);
/* dest framebuffer */
if (ssd->blit_fb.width != dmabuf->width ||
ssd->blit_fb.height != dmabuf->height) {
trace_qemu_spice_gl_render_dmabuf(ssd->qxl.id, dmabuf->width,
dmabuf->height);
if (ssd->blit_fb.width != width ||
ssd->blit_fb.height != height) {
trace_qemu_spice_gl_render_dmabuf(ssd->qxl.id, width,
height);
egl_fb_destroy(&ssd->blit_fb);
egl_fb_setup_new_tex(&ssd->blit_fb,
dmabuf->width, dmabuf->height);
width, height);
fd = egl_get_fd_for_texture(ssd->blit_fb.texture,
&stride, &fourcc, NULL);
spice_qxl_gl_scanout(&ssd->qxl, fd,
dmabuf->width, dmabuf->height,
spice_qxl_gl_scanout(&ssd->qxl, fd, width, height,
stride, fourcc, false);
}
} else {
trace_qemu_spice_gl_forward_dmabuf(ssd->qxl.id,
dmabuf->width, dmabuf->height);
stride = qemu_dmabuf_get_stride(dmabuf);
fourcc = qemu_dmabuf_get_fourcc(dmabuf);
y_0_top = qemu_dmabuf_get_y0_top(dmabuf);
fd = qemu_dmabuf_dup_fd(dmabuf);
trace_qemu_spice_gl_forward_dmabuf(ssd->qxl.id, width, height);
/* note: spice server will close the fd, so hand over a dup */
spice_qxl_gl_scanout(&ssd->qxl, dup(dmabuf->fd),
dmabuf->width, dmabuf->height,
dmabuf->stride, dmabuf->fourcc,
dmabuf->y0_top);
spice_qxl_gl_scanout(&ssd->qxl, fd, width, height,
stride, fourcc, y_0_top);
}
qemu_spice_gl_monitor_config(ssd, 0, 0, dmabuf->width, dmabuf->height);
qemu_spice_gl_monitor_config(ssd, 0, 0, width, height);
ssd->guest_dmabuf_refresh = false;
}

View File

@ -28,6 +28,7 @@ gd_ungrab(const char *tab, const char *device) "tab=%s, dev=%s"
gd_keymap_windowing(const char *name) "backend=%s"
gd_gl_area_create_context(void *ctx, int major, int minor) "ctx=%p, major=%d, minor=%d"
gd_gl_area_destroy_context(void *ctx, void *current_ctx) "ctx=%p, current_ctx=%p"
gd_motion_event(int ww, int wh, int ws, int x, int y) "ww=%d, wh=%d, ws=%d, x=%d, y=%d"
# vnc-auth-sasl.c
# vnc-auth-vencrypt.c

View File

@ -3734,11 +3734,6 @@ static int vnc_display_get_address(const char *addrstr,
addr->type = SOCKET_ADDRESS_TYPE_UNIX;
addr->u.q_unix.path = g_strdup(addrstr + 5);
if (websocket) {
error_setg(errp, "UNIX sockets not supported with websock");
goto cleanup;
}
if (to) {
error_setg(errp, "Port range not support with UNIX socket");
goto cleanup;