UI patch queue

- vhost-user-gpu: support dmabuf modifiers
 - fix VNC crash when there are no active_console
 - cleanups and refactoring in ui/vc code
 -----BEGIN PGP SIGNATURE-----
 
 iQJQBAABCAA6FiEEh6m9kz+HxgbSdvYt2ujhCXWWnOUFAmUAQX4cHG1hcmNhbmRy
 ZS5sdXJlYXVAcmVkaGF0LmNvbQAKCRDa6OEJdZac5Y4jD/4/whR7a1KZqHytl6sc
 cCQ0Xn0gpcPM8rn3tWItp2vAOlGmx8ACfAyXYa5QzO7pBOU/xoMJt8a99geNRXFu
 nN33UJ0NRAWW6V0/cF5AVe9clckzs1Vq4VX2ITP+VAG+c+kt4E3fgFn9o8nwnBrd
 zuiqYz4pO9yBVO/av/FZQcBY8s9/M8jrdraDNNhsY2O2k2zLTxt1xxNG5qeVvPUw
 2RZyc/EOG7RzW8eUA55BW/NU8Olg5u7dxsB0jfYnWBQxknOy5c+wF9MTGJSKmdGk
 HmgfMns6intUdfHmmJuDpP1Tiy1sVK1lkrsMeeQ67M84lYZsrSI+kIG5+YbWN8vx
 mMB/qwDmNMVMnGiBN5/ktvAJwcilYBUqen0KFrEHBghTpGhqAVoBNCC1MT/9w/bO
 c3/E1viuCi8OamPixVu9LeqQsxuP2jK5qxjfyDYH87HdnljSY6wFbVzD/2zz5YNv
 43JtEbP9bv1yyRRd+JTpD54vCK0IZK7MBR8MbJqfknpbEw1FSPofRQxCSe9BlSJ/
 nYamatH9I9i92kGg5eD573X+UcLX9eOPBw8gVNKxuttwSIW1cwjGKi12B9MiFMg7
 Z6jP3gvpe9DrYef+4Wojo1PAioyweZVG5IFtWIqXRZjPwAoIzzVgBcEtcq4qeZwX
 BAliXWeUcRGsbLorT3COx2DjBw==
 =Xsr0
 -----END PGP SIGNATURE-----

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

UI patch queue

- vhost-user-gpu: support dmabuf modifiers
- fix VNC crash when there are no active_console
- cleanups and refactoring in ui/vc code

# -----BEGIN PGP SIGNATURE-----
#
# iQJQBAABCAA6FiEEh6m9kz+HxgbSdvYt2ujhCXWWnOUFAmUAQX4cHG1hcmNhbmRy
# ZS5sdXJlYXVAcmVkaGF0LmNvbQAKCRDa6OEJdZac5Y4jD/4/whR7a1KZqHytl6sc
# cCQ0Xn0gpcPM8rn3tWItp2vAOlGmx8ACfAyXYa5QzO7pBOU/xoMJt8a99geNRXFu
# nN33UJ0NRAWW6V0/cF5AVe9clckzs1Vq4VX2ITP+VAG+c+kt4E3fgFn9o8nwnBrd
# zuiqYz4pO9yBVO/av/FZQcBY8s9/M8jrdraDNNhsY2O2k2zLTxt1xxNG5qeVvPUw
# 2RZyc/EOG7RzW8eUA55BW/NU8Olg5u7dxsB0jfYnWBQxknOy5c+wF9MTGJSKmdGk
# HmgfMns6intUdfHmmJuDpP1Tiy1sVK1lkrsMeeQ67M84lYZsrSI+kIG5+YbWN8vx
# mMB/qwDmNMVMnGiBN5/ktvAJwcilYBUqen0KFrEHBghTpGhqAVoBNCC1MT/9w/bO
# c3/E1viuCi8OamPixVu9LeqQsxuP2jK5qxjfyDYH87HdnljSY6wFbVzD/2zz5YNv
# 43JtEbP9bv1yyRRd+JTpD54vCK0IZK7MBR8MbJqfknpbEw1FSPofRQxCSe9BlSJ/
# nYamatH9I9i92kGg5eD573X+UcLX9eOPBw8gVNKxuttwSIW1cwjGKi12B9MiFMg7
# Z6jP3gvpe9DrYef+4Wojo1PAioyweZVG5IFtWIqXRZjPwAoIzzVgBcEtcq4qeZwX
# BAliXWeUcRGsbLorT3COx2DjBw==
# =Xsr0
# -----END PGP SIGNATURE-----
# gpg: Signature made Tue 12 Sep 2023 06:46:22 EDT
# 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]
# Primary key fingerprint: 87A9 BD93 3F87 C606 D276  F62D DAE8 E109 7596 9CE5

* tag 'ui-pull-request' of https://gitlab.com/marcandre.lureau/qemu:
  ui: add precondition for dpy_get_ui_info()
  ui: fix crash when there are no active_console
  virtio-gpu/win32: set the destroy function on load
  ui/console: move DisplaySurface to its own header
  ui/vc: split off the VC part from console.c
  ui/vc: preliminary QemuTextConsole changes before split
  ui/console: remove redundant format field
  ui/vc: rename kbd_put to qemu_text_console functions
  ui/vc: remove kbd_put_keysym() and update function calls
  vmmouse: use explicit code
  vmmouse: replace DPRINTF with tracing
  vhost-user-gpu: support dmabuf modifiers
  contrib/vhost-user-gpu: add support for sending dmabuf modifiers
  docs: vhost-user-gpu: add protocol changes for dmabuf modifiers

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
Stefan Hajnoczi 2023-09-13 07:52:27 -04:00
commit 7754c97179
22 changed files with 1426 additions and 1245 deletions

View File

@ -1071,6 +1071,7 @@ static gboolean
protocol_features_cb(gint fd, GIOCondition condition, gpointer user_data)
{
const uint64_t protocol_edid = (1 << VHOST_USER_GPU_PROTOCOL_F_EDID);
const uint64_t protocol_dmabuf2 = (1 << VHOST_USER_GPU_PROTOCOL_F_DMABUF2);
VuGpu *g = user_data;
uint64_t protocol_features;
VhostUserGpuMsg msg = {
@ -1082,7 +1083,7 @@ protocol_features_cb(gint fd, GIOCondition condition, gpointer user_data)
return G_SOURCE_CONTINUE;
}
protocol_features &= protocol_edid;
protocol_features &= (protocol_edid | protocol_dmabuf2);
msg = (VhostUserGpuMsg) {
.request = VHOST_USER_GPU_SET_PROTOCOL_FEATURES,
@ -1100,6 +1101,8 @@ protocol_features_cb(gint fd, GIOCondition condition, gpointer user_data)
exit(EXIT_FAILURE);
}
g->use_modifiers = !!(protocol_features & protocol_dmabuf2);
return G_SOURCE_REMOVE;
}

View File

@ -318,6 +318,37 @@ virgl_resource_detach_backing(VuGpu *g,
vg_cleanup_mapping_iov(g, res_iovs, num_iovs);
}
static int
virgl_get_resource_info_modifiers(uint32_t resource_id,
struct virgl_renderer_resource_info *info,
uint64_t *modifiers)
{
int ret;
#ifdef VIRGL_RENDERER_RESOURCE_INFO_EXT_VERSION
struct virgl_renderer_resource_info_ext info_ext;
ret = virgl_renderer_resource_get_info_ext(resource_id, &info_ext);
if (ret < 0) {
return ret;
}
*info = info_ext.base;
*modifiers = info_ext.modifiers;
#else
ret = virgl_renderer_resource_get_info(resource_id, info);
if (ret < 0) {
return ret;
}
/*
* Before virgl_renderer_resource_get_info_ext,
* getting the modifiers was not possible.
*/
*modifiers = 0;
#endif
return 0;
}
static void
virgl_cmd_set_scanout(VuGpu *g,
struct virtio_gpu_ctrl_command *cmd)
@ -338,7 +369,9 @@ virgl_cmd_set_scanout(VuGpu *g,
memset(&info, 0, sizeof(info));
if (ss.resource_id && ss.r.width && ss.r.height) {
ret = virgl_renderer_resource_get_info(ss.resource_id, &info);
uint64_t modifiers = 0;
ret = virgl_get_resource_info_modifiers(ss.resource_id, &info,
&modifiers);
if (ret == -1) {
g_critical("%s: illegal resource specified %d\n",
__func__, ss.resource_id);
@ -354,8 +387,6 @@ virgl_cmd_set_scanout(VuGpu *g,
}
assert(fd >= 0);
VhostUserGpuMsg msg = {
.request = VHOST_USER_GPU_DMABUF_SCANOUT,
.size = sizeof(VhostUserGpuDMABUFScanout),
.payload.dmabuf_scanout.scanout_id = ss.scanout_id,
.payload.dmabuf_scanout.x = ss.r.x,
.payload.dmabuf_scanout.y = ss.r.y,
@ -367,6 +398,20 @@ virgl_cmd_set_scanout(VuGpu *g,
.payload.dmabuf_scanout.fd_flags = info.flags,
.payload.dmabuf_scanout.fd_drm_fourcc = info.drm_fourcc
};
if (g->use_modifiers) {
/*
* The mesage uses all the fields set in dmabuf_scanout plus
* modifiers which is appended after VhostUserGpuDMABUFScanout.
*/
msg.request = VHOST_USER_GPU_DMABUF_SCANOUT2;
msg.size = sizeof(VhostUserGpuDMABUFScanout2);
msg.payload.dmabuf_scanout2.modifier = modifiers;
} else {
msg.request = VHOST_USER_GPU_DMABUF_SCANOUT;
msg.size = sizeof(VhostUserGpuDMABUFScanout);
}
vg_send_msg(g, &msg, fd);
close(fd);
} else {

View File

@ -37,6 +37,7 @@ typedef enum VhostUserGpuRequest {
VHOST_USER_GPU_DMABUF_SCANOUT,
VHOST_USER_GPU_DMABUF_UPDATE,
VHOST_USER_GPU_GET_EDID,
VHOST_USER_GPU_DMABUF_SCANOUT2,
} VhostUserGpuRequest;
typedef struct VhostUserGpuDisplayInfoReply {
@ -84,6 +85,11 @@ typedef struct VhostUserGpuDMABUFScanout {
int fd_drm_fourcc;
} QEMU_PACKED VhostUserGpuDMABUFScanout;
typedef struct VhostUserGpuDMABUFScanout2 {
struct VhostUserGpuDMABUFScanout dmabuf_scanout;
uint64_t modifier;
} QEMU_PACKED VhostUserGpuDMABUFScanout2;
typedef struct VhostUserGpuEdidRequest {
uint32_t scanout_id;
} QEMU_PACKED VhostUserGpuEdidRequest;
@ -98,6 +104,7 @@ typedef struct VhostUserGpuMsg {
VhostUserGpuScanout scanout;
VhostUserGpuUpdate update;
VhostUserGpuDMABUFScanout dmabuf_scanout;
VhostUserGpuDMABUFScanout2 dmabuf_scanout2;
VhostUserGpuEdidRequest edid_req;
struct virtio_gpu_resp_edid resp_edid;
struct virtio_gpu_resp_display_info display_info;
@ -112,6 +119,7 @@ static VhostUserGpuMsg m __attribute__ ((unused));
#define VHOST_USER_GPU_MSG_FLAG_REPLY 0x4
#define VHOST_USER_GPU_PROTOCOL_F_EDID 0
#define VHOST_USER_GPU_PROTOCOL_F_DMABUF2 1
struct virtio_gpu_scanout {
uint32_t width, height;
@ -132,6 +140,7 @@ typedef struct VuGpu {
bool virgl;
bool virgl_inited;
bool edid_inited;
bool use_modifiers;
uint32_t inflight;
struct virtio_gpu_scanout scanout[VIRTIO_GPU_MAX_SCANOUTS];

View File

@ -134,6 +134,19 @@ VhostUserGpuEdidRequest
:scanout-id: ``u32``, the scanout to get edid from
VhostUserGpuDMABUFScanout2
^^^^^^^^^^^^^^^^^^^^^^^^^^
+----------------+----------+
| dmabuf_scanout | modifier |
+----------------+----------+
:dmabuf_scanout: ``VhostUserGpuDMABUFScanout``, filled as described in the
VhostUserGpuDMABUFScanout structure.
:modifier: ``u64``, the DMABUF modifiers
C structure
-----------
@ -163,7 +176,8 @@ Protocol features
.. code:: c
#define VHOST_USER_GPU_PROTOCOL_F_EDID 0
#define VHOST_USER_GPU_PROTOCOL_F_EDID 0
#define VHOST_USER_GPU_PROTOCOL_F_DMABUF2 1
New messages and communication changes are negotiated thanks to the
``VHOST_USER_GPU_GET_PROTOCOL_FEATURES`` and
@ -263,3 +277,13 @@ Message types
Retrieve the EDID data for a given scanout.
This message requires the ``VHOST_USER_GPU_PROTOCOL_F_EDID`` protocol
feature to be supported.
``VHOST_USER_GPU_DMABUF_SCANOUT2``
:id: 12
:request payload: ``VhostUserGpuDMABUFScanout2``
:reply payload: N/A
Same as VHOST_USER_GPU_DMABUF_SCANOUT, but also sends the dmabuf modifiers
appended to the message, which were not provided in the other message.
This message requires the ``VHOST_USER_GPU_PROTOCOL_F_DMABUF2`` protocol
feature to be supported.

View File

@ -32,6 +32,7 @@ typedef enum VhostUserGpuRequest {
VHOST_USER_GPU_DMABUF_SCANOUT,
VHOST_USER_GPU_DMABUF_UPDATE,
VHOST_USER_GPU_GET_EDID,
VHOST_USER_GPU_DMABUF_SCANOUT2,
} VhostUserGpuRequest;
typedef struct VhostUserGpuDisplayInfoReply {
@ -79,6 +80,11 @@ typedef struct VhostUserGpuDMABUFScanout {
int fd_drm_fourcc;
} QEMU_PACKED VhostUserGpuDMABUFScanout;
typedef struct VhostUserGpuDMABUFScanout2 {
struct VhostUserGpuDMABUFScanout dmabuf_scanout;
uint64_t modifier;
} QEMU_PACKED VhostUserGpuDMABUFScanout2;
typedef struct VhostUserGpuEdidRequest {
uint32_t scanout_id;
} QEMU_PACKED VhostUserGpuEdidRequest;
@ -93,6 +99,7 @@ typedef struct VhostUserGpuMsg {
VhostUserGpuScanout scanout;
VhostUserGpuUpdate update;
VhostUserGpuDMABUFScanout dmabuf_scanout;
VhostUserGpuDMABUFScanout2 dmabuf_scanout2;
VhostUserGpuEdidRequest edid_req;
struct virtio_gpu_resp_edid resp_edid;
struct virtio_gpu_resp_display_info display_info;
@ -107,6 +114,7 @@ static VhostUserGpuMsg m __attribute__ ((unused));
#define VHOST_USER_GPU_MSG_FLAG_REPLY 0x4
#define VHOST_USER_GPU_PROTOCOL_F_EDID 0
#define VHOST_USER_GPU_PROTOCOL_F_DMABUF2 1
static void vhost_user_gpu_update_blocked(VhostUserGPU *g, bool blocked);
@ -171,7 +179,8 @@ vhost_user_gpu_handle_display(VhostUserGPU *g, VhostUserGpuMsg *msg)
.flags = VHOST_USER_GPU_MSG_FLAG_REPLY,
.size = sizeof(uint64_t),
.payload = {
.u64 = (1 << VHOST_USER_GPU_PROTOCOL_F_EDID)
.u64 = (1 << VHOST_USER_GPU_PROTOCOL_F_EDID) |
(1 << VHOST_USER_GPU_PROTOCOL_F_DMABUF2)
}
};
@ -236,6 +245,7 @@ vhost_user_gpu_handle_display(VhostUserGPU *g, VhostUserGpuMsg *msg)
break;
}
case VHOST_USER_GPU_DMABUF_SCANOUT2:
case VHOST_USER_GPU_DMABUF_SCANOUT: {
VhostUserGpuDMABUFScanout *m = &msg->payload.dmabuf_scanout;
int fd = qemu_chr_fe_get_msgfd(&g->vhost_chr);
@ -269,6 +279,11 @@ vhost_user_gpu_handle_display(VhostUserGPU *g, VhostUserGpuMsg *msg)
.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;
}
dpy_gl_scanout_dmabuf(con, dmabuf);
break;
}

View File

@ -1283,7 +1283,9 @@ static int virtio_gpu_load(QEMUFile *f, void *opaque, size_t size,
g_free(res);
return -EINVAL;
}
#ifdef WIN32
pixman_image_set_destroy_function(res->image, win32_pixman_image_destroy, res->handle);
#endif
res->addrs = g_new(uint64_t, res->iov_cnt);
res->iov = g_new(struct iovec, res->iov_cnt);

View File

@ -121,3 +121,13 @@ x86_pic_interrupt(int irqn, int level) "PIC interrupt #%d level:%d"
# port92.c
port92_read(uint8_t val) "port92: read 0x%02x"
port92_write(uint8_t val) "port92: write 0x%02x"
# vmmouse.c
vmmouse_get_status(void) ""
vmmouse_mouse_event(int x, int y, int dz, int buttons_state) "event: x=%d y=%d dz=%d state=%d"
vmmouse_init(void) ""
vmmouse_read_id(void) ""
vmmouse_request_relative(void) ""
vmmouse_request_absolute(void) ""
vmmouse_disable(void) ""
vmmouse_data(uint32_t size) "data: size=%" PRIu32

View File

@ -32,6 +32,8 @@
#include "cpu.h"
#include "qom/object.h"
#include "trace.h"
/* debug only vmmouse */
//#define DEBUG_VMMOUSE
@ -50,11 +52,10 @@
#define VMMOUSE_RIGHT_BUTTON 0x10
#define VMMOUSE_MIDDLE_BUTTON 0x08
#ifdef DEBUG_VMMOUSE
#define DPRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__)
#else
#define DPRINTF(fmt, ...) do { } while (0)
#endif
#define VMMOUSE_MIN_X 0
#define VMMOUSE_MIN_Y 0
#define VMMOUSE_MAX_X 0xFFFF
#define VMMOUSE_MAX_Y 0xFFFF
#define TYPE_VMMOUSE "vmmouse"
OBJECT_DECLARE_SIMPLE_TYPE(VMMouseState, VMMOUSE)
@ -93,7 +94,8 @@ static void vmmouse_set_data(const uint32_t *data)
static uint32_t vmmouse_get_status(VMMouseState *s)
{
DPRINTF("vmmouse_get_status()\n");
trace_vmmouse_get_status();
return (s->status << 16) | s->nb_queue;
}
@ -105,8 +107,7 @@ static void vmmouse_mouse_event(void *opaque, int x, int y, int dz, int buttons_
if (s->nb_queue > (VMMOUSE_QUEUE_SIZE - 4))
return;
DPRINTF("vmmouse_mouse_event(%d, %d, %d, %d)\n",
x, y, dz, buttons_state);
trace_vmmouse_mouse_event(x, y, dz, buttons_state);
if ((buttons_state & MOUSE_EVENT_LBUTTON))
buttons |= VMMOUSE_LEFT_BUTTON;
@ -116,8 +117,12 @@ static void vmmouse_mouse_event(void *opaque, int x, int y, int dz, int buttons_
buttons |= VMMOUSE_MIDDLE_BUTTON;
if (s->absolute) {
x <<= 1;
y <<= 1;
x = qemu_input_scale_axis(x,
INPUT_EVENT_ABS_MIN, INPUT_EVENT_ABS_MAX,
VMMOUSE_MIN_X, VMMOUSE_MAX_X);
y = qemu_input_scale_axis(y,
INPUT_EVENT_ABS_MIN, INPUT_EVENT_ABS_MAX,
VMMOUSE_MIN_Y, VMMOUSE_MAX_Y);
} else{
/* add for guest vmmouse driver to judge this is a relative packet. */
buttons |= VMMOUSE_RELATIVE_PACKET;
@ -160,7 +165,7 @@ static void vmmouse_update_handler(VMMouseState *s, int absolute)
static void vmmouse_read_id(VMMouseState *s)
{
DPRINTF("vmmouse_read_id()\n");
trace_vmmouse_read_id();
if (s->nb_queue == VMMOUSE_QUEUE_SIZE)
return;
@ -172,19 +177,22 @@ static void vmmouse_read_id(VMMouseState *s)
static void vmmouse_request_relative(VMMouseState *s)
{
DPRINTF("vmmouse_request_relative()\n");
trace_vmmouse_request_relative();
vmmouse_update_handler(s, 0);
}
static void vmmouse_request_absolute(VMMouseState *s)
{
DPRINTF("vmmouse_request_absolute()\n");
trace_vmmouse_request_absolute();
vmmouse_update_handler(s, 1);
}
static void vmmouse_disable(VMMouseState *s)
{
DPRINTF("vmmouse_disable()\n");
trace_vmmouse_disable();
s->status = 0xffff;
vmmouse_remove_handler(s);
}
@ -193,7 +201,7 @@ static void vmmouse_data(VMMouseState *s, uint32_t *data, uint32_t size)
{
int i;
DPRINTF("vmmouse_data(%d)\n", size);
trace_vmmouse_data(size);
if (size == 0 || size > 6 || size > s->nb_queue) {
printf("vmmouse: driver requested too much data %d\n", size);
@ -293,7 +301,7 @@ static void vmmouse_realizefn(DeviceState *dev, Error **errp)
{
VMMouseState *s = VMMOUSE(dev);
DPRINTF("vmmouse_init\n");
trace_vmmouse_init();
if (!s->i8042) {
error_setg(errp, "'i8042' link is not set");

View File

@ -6,11 +6,7 @@
#include "qemu/notify.h"
#include "qapi/qapi-types-ui.h"
#include "ui/input.h"
#ifdef CONFIG_OPENGL
# include <epoxy/gl.h>
# include "ui/shader.h"
#endif
#include "ui/surface.h"
#define TYPE_QEMU_CONSOLE "qemu-console"
OBJECT_DECLARE_TYPE(QemuConsole, QemuConsoleClass, QEMU_CONSOLE)
@ -112,10 +108,9 @@ bool qemu_mouse_set(int index, Error **errp);
#define QEMU_KEY_CTRL_PAGEUP 0xe406
#define QEMU_KEY_CTRL_PAGEDOWN 0xe407
void kbd_put_keysym_console(QemuTextConsole *s, int keysym);
bool kbd_put_qcode_console(QemuTextConsole *s, int qcode, bool ctrl);
void kbd_put_string_console(QemuTextConsole *s, const char *str, int len);
void kbd_put_keysym(int keysym);
void qemu_text_console_put_keysym(QemuTextConsole *s, int keysym);
bool qemu_text_console_put_qcode(QemuTextConsole *s, int qcode, bool ctrl);
void qemu_text_console_put_string(QemuTextConsole *s, const char *str, int len);
/* Touch devices */
typedef struct touch_slot {
@ -137,9 +132,6 @@ struct QemuConsoleClass {
ObjectClass parent_class;
};
#define QEMU_ALLOCATED_FLAG 0x01
#define QEMU_PLACEHOLDER_FLAG 0x02
typedef struct ScanoutTexture {
uint32_t backing_id;
bool backing_y_0_top;
@ -152,21 +144,6 @@ typedef struct ScanoutTexture {
void *d3d_tex2d;
} ScanoutTexture;
typedef struct DisplaySurface {
pixman_format_code_t format;
pixman_image_t *image;
uint8_t flags;
#ifdef CONFIG_OPENGL
GLenum glformat;
GLenum gltype;
GLuint texture;
#endif
#ifdef WIN32
HANDLE handle;
uint32_t handle_offset;
#endif
} DisplaySurface;
typedef struct QemuUIInfo {
/* physical dimension */
uint16_t width_mm;
@ -346,37 +323,13 @@ struct DisplayGLCtx {
};
DisplayState *init_displaystate(void);
DisplaySurface *qemu_create_displaysurface_from(int width, int height,
pixman_format_code_t format,
int linesize, uint8_t *data);
DisplaySurface *qemu_create_displaysurface_pixman(pixman_image_t *image);
DisplaySurface *qemu_create_placeholder_surface(int w, int h,
const char *msg);
#ifdef WIN32
void qemu_displaysurface_win32_set_handle(DisplaySurface *surface,
HANDLE h, uint32_t offset);
#endif
PixelFormat qemu_default_pixelformat(int bpp);
DisplaySurface *qemu_create_displaysurface(int width, int height);
void qemu_free_displaysurface(DisplaySurface *surface);
static inline int is_buffer_shared(DisplaySurface *surface)
{
return !(surface->flags & QEMU_ALLOCATED_FLAG);
}
static inline int is_placeholder(DisplaySurface *surface)
{
return surface->flags & QEMU_PLACEHOLDER_FLAG;
}
void register_displaychangelistener(DisplayChangeListener *dcl);
void update_displaychangelistener(DisplayChangeListener *dcl,
uint64_t interval);
void unregister_displaychangelistener(DisplayChangeListener *dcl);
bool dpy_ui_info_supported(QemuConsole *con);
bool dpy_ui_info_supported(const QemuConsole *con);
const QemuUIInfo *dpy_get_ui_info(const QemuConsole *con);
int dpy_set_ui_info(QemuConsole *con, QemuUIInfo *info, bool delay);
@ -417,43 +370,6 @@ int dpy_gl_ctx_make_current(QemuConsole *con, QEMUGLContext ctx);
bool console_has_gl(QemuConsole *con);
static inline int surface_stride(DisplaySurface *s)
{
return pixman_image_get_stride(s->image);
}
static inline void *surface_data(DisplaySurface *s)
{
return pixman_image_get_data(s->image);
}
static inline int surface_width(DisplaySurface *s)
{
return pixman_image_get_width(s->image);
}
static inline int surface_height(DisplaySurface *s)
{
return pixman_image_get_height(s->image);
}
static inline int surface_bits_per_pixel(DisplaySurface *s)
{
int bits = PIXMAN_FORMAT_BPP(s->format);
return bits;
}
static inline int surface_bytes_per_pixel(DisplaySurface *s)
{
int bits = PIXMAN_FORMAT_BPP(s->format);
return DIV_ROUND_UP(bits, 8);
}
static inline pixman_format_code_t surface_format(DisplaySurface *s)
{
return s->format;
}
typedef uint32_t console_ch_t;
static inline void console_write_ch(console_ch_t *dest, uint32_t ch)

95
include/ui/surface.h Normal file
View File

@ -0,0 +1,95 @@
/*
* SPDX-License-Identifier: GPL-2.0-or-later
* QEMU UI Console
*/
#ifndef SURFACE_H
#define SURFACE_H
#include "ui/qemu-pixman.h"
#ifdef CONFIG_OPENGL
# include <epoxy/gl.h>
# include "ui/shader.h"
#endif
#define QEMU_ALLOCATED_FLAG 0x01
#define QEMU_PLACEHOLDER_FLAG 0x02
typedef struct DisplaySurface {
pixman_image_t *image;
uint8_t flags;
#ifdef CONFIG_OPENGL
GLenum glformat;
GLenum gltype;
GLuint texture;
#endif
#ifdef WIN32
HANDLE handle;
uint32_t handle_offset;
#endif
} DisplaySurface;
PixelFormat qemu_default_pixelformat(int bpp);
DisplaySurface *qemu_create_displaysurface_from(int width, int height,
pixman_format_code_t format,
int linesize, uint8_t *data);
DisplaySurface *qemu_create_displaysurface_pixman(pixman_image_t *image);
DisplaySurface *qemu_create_placeholder_surface(int w, int h,
const char *msg);
#ifdef WIN32
void qemu_displaysurface_win32_set_handle(DisplaySurface *surface,
HANDLE h, uint32_t offset);
#endif
DisplaySurface *qemu_create_displaysurface(int width, int height);
void qemu_free_displaysurface(DisplaySurface *surface);
static inline int is_buffer_shared(DisplaySurface *surface)
{
return !(surface->flags & QEMU_ALLOCATED_FLAG);
}
static inline int is_placeholder(DisplaySurface *surface)
{
return surface->flags & QEMU_PLACEHOLDER_FLAG;
}
static inline int surface_stride(DisplaySurface *s)
{
return pixman_image_get_stride(s->image);
}
static inline void *surface_data(DisplaySurface *s)
{
return pixman_image_get_data(s->image);
}
static inline int surface_width(DisplaySurface *s)
{
return pixman_image_get_width(s->image);
}
static inline int surface_height(DisplaySurface *s)
{
return pixman_image_get_height(s->image);
}
static inline pixman_format_code_t surface_format(DisplaySurface *s)
{
return pixman_image_get_format(s->image);
}
static inline int surface_bits_per_pixel(DisplaySurface *s)
{
int bits = PIXMAN_FORMAT_BPP(surface_format(s));
return bits;
}
static inline int surface_bytes_per_pixel(DisplaySurface *s)
{
int bits = PIXMAN_FORMAT_BPP(surface_format(s));
return DIV_ROUND_UP(bits, 8);
}
#endif

View File

@ -784,7 +784,7 @@ static CGEventRef handleTapEvent(CGEventTapProxy proxy, CGEventType type, CGEven
}
if (keysym) {
kbd_put_keysym(keysym);
qemu_text_console_put_keysym(NULL, keysym);
}
}

View File

@ -53,7 +53,7 @@ void surface_gl_create_texture(QemuGLShader *gls,
return;
}
switch (surface->format) {
switch (surface_format(surface)) {
case PIXMAN_BE_b8g8r8x8:
case PIXMAN_BE_b8g8r8a8:
surface->glformat = GL_BGRA_EXT;

43
ui/console-priv.h Normal file
View File

@ -0,0 +1,43 @@
/*
* SPDX-License-Identifier: GPL-2.0-or-later
* QEMU UI Console
*/
#ifndef CONSOLE_PRIV_H
#define CONSOLE_PRIV_H
#include "ui/console.h"
#include "qemu/coroutine.h"
#include "qemu/timer.h"
#include "vgafont.h"
#define FONT_HEIGHT 16
#define FONT_WIDTH 8
struct QemuConsole {
Object parent;
int index;
DisplayState *ds;
DisplaySurface *surface;
DisplayScanout scanout;
int dcls;
DisplayGLCtx *gl;
int gl_block;
QEMUTimer *gl_unblock_timer;
int window_id;
QemuUIInfo ui_info;
QEMUTimer *ui_timer;
const GraphicHwOps *hw_ops;
void *hw;
CoQueue dump_queue;
QTAILQ_ENTRY(QemuConsole) next;
};
void qemu_text_console_select(QemuTextConsole *c);
const char * qemu_text_console_get_label(QemuTextConsole *c);
void qemu_text_console_update_cursor(void);
void qemu_text_console_handle_keysym(QemuTextConsole *s, int keysym);
#endif

1079
ui/console-vc.c Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -400,7 +400,7 @@ static void curses_refresh(DisplayChangeListener *dcl)
if (keysym == -1)
keysym = chr;
kbd_put_keysym(keysym);
qemu_text_console_put_keysym(NULL, keysym);
}
}
}

View File

@ -514,7 +514,7 @@ static void gd_switch(DisplayChangeListener *dcl,
}
vc->gfx.ds = surface;
if (surface->format == PIXMAN_x8r8g8b8) {
if (surface_format(surface) == PIXMAN_x8r8g8b8) {
/*
* PIXMAN_x8r8g8b8 == CAIRO_FORMAT_RGB24
*
@ -1190,12 +1190,12 @@ static gboolean gd_text_key_down(GtkWidget *widget,
QemuTextConsole *con = QEMU_TEXT_CONSOLE(vc->gfx.dcl.con);
if (key->keyval == GDK_KEY_Delete) {
kbd_put_qcode_console(con, Q_KEY_CODE_DELETE, false);
qemu_text_console_put_qcode(con, Q_KEY_CODE_DELETE, false);
} else if (key->length) {
kbd_put_string_console(con, key->string, key->length);
qemu_text_console_put_string(con, key->string, key->length);
} else {
int qcode = gd_map_keycode(gd_get_keycode(key));
kbd_put_qcode_console(con, qcode, false);
qemu_text_console_put_qcode(con, qcode, false);
}
return TRUE;
}

View File

@ -6,6 +6,7 @@ system_ss.add(png)
system_ss.add(files(
'clipboard.c',
'console.c',
'console-vc.c',
'cursor.c',
'input-keymap.c',
'input-legacy.c',

View File

@ -49,10 +49,10 @@ void sdl2_process_key(struct sdl2_console *scon,
if (ev->type == SDL_KEYDOWN) {
switch (qcode) {
case Q_KEY_CODE_RET:
kbd_put_keysym_console(s, '\n');
qemu_text_console_put_keysym(s, '\n');
break;
default:
kbd_put_qcode_console(s, qcode, ctrl);
qemu_text_console_put_qcode(s, qcode, ctrl);
break;
}
}

View File

@ -484,7 +484,7 @@ static void handle_textinput(SDL_Event *ev)
}
if (QEMU_IS_TEXT_CONSOLE(con)) {
kbd_put_string_console(QEMU_TEXT_CONSOLE(con), ev->text.text, strlen(ev->text.text));
qemu_text_console_put_string(QEMU_TEXT_CONSOLE(con), ev->text.text, strlen(ev->text.text));
}
}

View File

@ -437,7 +437,7 @@ void qemu_spice_display_switch(SimpleSpiceDisplay *ssd,
}
if (ssd->ds) {
ssd->surface = pixman_image_ref(ssd->ds->image);
ssd->mirror = qemu_pixman_mirror_create(ssd->ds->format,
ssd->mirror = qemu_pixman_mirror_create(surface_format(ssd->ds),
ssd->ds->image);
qemu_spice_create_host_primary(ssd);
}

View File

@ -833,7 +833,7 @@ static void vnc_dpy_switch(DisplayChangeListener *dcl,
/* guest surface */
qemu_pixman_image_unref(vd->guest.fb);
vd->guest.fb = pixman_image_ref(surface->image);
vd->guest.format = surface->format;
vd->guest.format = surface_format(surface);
if (pageflip) {
@ -1945,88 +1945,88 @@ static void do_key_event(VncState *vs, int down, int keycode, int sym)
case 0xb8: /* Right ALT */
break;
case 0xc8:
kbd_put_keysym(QEMU_KEY_UP);
qemu_text_console_put_keysym(NULL, QEMU_KEY_UP);
break;
case 0xd0:
kbd_put_keysym(QEMU_KEY_DOWN);
qemu_text_console_put_keysym(NULL, QEMU_KEY_DOWN);
break;
case 0xcb:
kbd_put_keysym(QEMU_KEY_LEFT);
qemu_text_console_put_keysym(NULL, QEMU_KEY_LEFT);
break;
case 0xcd:
kbd_put_keysym(QEMU_KEY_RIGHT);
qemu_text_console_put_keysym(NULL, QEMU_KEY_RIGHT);
break;
case 0xd3:
kbd_put_keysym(QEMU_KEY_DELETE);
qemu_text_console_put_keysym(NULL, QEMU_KEY_DELETE);
break;
case 0xc7:
kbd_put_keysym(QEMU_KEY_HOME);
qemu_text_console_put_keysym(NULL, QEMU_KEY_HOME);
break;
case 0xcf:
kbd_put_keysym(QEMU_KEY_END);
qemu_text_console_put_keysym(NULL, QEMU_KEY_END);
break;
case 0xc9:
kbd_put_keysym(QEMU_KEY_PAGEUP);
qemu_text_console_put_keysym(NULL, QEMU_KEY_PAGEUP);
break;
case 0xd1:
kbd_put_keysym(QEMU_KEY_PAGEDOWN);
qemu_text_console_put_keysym(NULL, QEMU_KEY_PAGEDOWN);
break;
case 0x47:
kbd_put_keysym(numlock ? '7' : QEMU_KEY_HOME);
qemu_text_console_put_keysym(NULL, numlock ? '7' : QEMU_KEY_HOME);
break;
case 0x48:
kbd_put_keysym(numlock ? '8' : QEMU_KEY_UP);
qemu_text_console_put_keysym(NULL, numlock ? '8' : QEMU_KEY_UP);
break;
case 0x49:
kbd_put_keysym(numlock ? '9' : QEMU_KEY_PAGEUP);
qemu_text_console_put_keysym(NULL, numlock ? '9' : QEMU_KEY_PAGEUP);
break;
case 0x4b:
kbd_put_keysym(numlock ? '4' : QEMU_KEY_LEFT);
qemu_text_console_put_keysym(NULL, numlock ? '4' : QEMU_KEY_LEFT);
break;
case 0x4c:
kbd_put_keysym('5');
qemu_text_console_put_keysym(NULL, '5');
break;
case 0x4d:
kbd_put_keysym(numlock ? '6' : QEMU_KEY_RIGHT);
qemu_text_console_put_keysym(NULL, numlock ? '6' : QEMU_KEY_RIGHT);
break;
case 0x4f:
kbd_put_keysym(numlock ? '1' : QEMU_KEY_END);
qemu_text_console_put_keysym(NULL, numlock ? '1' : QEMU_KEY_END);
break;
case 0x50:
kbd_put_keysym(numlock ? '2' : QEMU_KEY_DOWN);
qemu_text_console_put_keysym(NULL, numlock ? '2' : QEMU_KEY_DOWN);
break;
case 0x51:
kbd_put_keysym(numlock ? '3' : QEMU_KEY_PAGEDOWN);
qemu_text_console_put_keysym(NULL, numlock ? '3' : QEMU_KEY_PAGEDOWN);
break;
case 0x52:
kbd_put_keysym('0');
qemu_text_console_put_keysym(NULL, '0');
break;
case 0x53:
kbd_put_keysym(numlock ? '.' : QEMU_KEY_DELETE);
qemu_text_console_put_keysym(NULL, numlock ? '.' : QEMU_KEY_DELETE);
break;
case 0xb5:
kbd_put_keysym('/');
qemu_text_console_put_keysym(NULL, '/');
break;
case 0x37:
kbd_put_keysym('*');
qemu_text_console_put_keysym(NULL, '*');
break;
case 0x4a:
kbd_put_keysym('-');
qemu_text_console_put_keysym(NULL, '-');
break;
case 0x4e:
kbd_put_keysym('+');
qemu_text_console_put_keysym(NULL, '+');
break;
case 0x9c:
kbd_put_keysym('\n');
qemu_text_console_put_keysym(NULL, '\n');
break;
default:
if (control) {
kbd_put_keysym(sym & 0x1f);
qemu_text_console_put_keysym(NULL, sym & 0x1f);
} else {
kbd_put_keysym(sym);
qemu_text_console_put_keysym(NULL, sym);
}
break;
}