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>
This commit is contained in:
commit
265aad58e9
@ -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: {
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
@ -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
49
include/ui/dmabuf.h
Normal 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
|
@ -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.
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
|
@ -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
229
ui/dmabuf.c
Normal 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;
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
53
ui/gtk-egl.c
53
ui/gtk-egl.c
@ -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;
|
||||
|
@ -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
|
||||
|
32
ui/gtk.c
32
ui/gtk.c
@ -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 ||
|
||||
|
@ -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',
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
5
ui/vnc.c
5
ui/vnc.c
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user