1
2
3
4
5
6
7
8
9
10
11
12
13
14
15#ifndef VUGPU_H
16#define VUGPU_H
17
18#include "qemu/osdep.h"
19
20#include "contrib/libvhost-user/libvhost-user-glib.h"
21#include "standard-headers/linux/virtio_gpu.h"
22
23#include "qemu/queue.h"
24#include "qemu/iov.h"
25#include "qemu/bswap.h"
26#include "vugbm.h"
27
28typedef enum VhostUserGpuRequest {
29 VHOST_USER_GPU_NONE = 0,
30 VHOST_USER_GPU_GET_PROTOCOL_FEATURES,
31 VHOST_USER_GPU_SET_PROTOCOL_FEATURES,
32 VHOST_USER_GPU_GET_DISPLAY_INFO,
33 VHOST_USER_GPU_CURSOR_POS,
34 VHOST_USER_GPU_CURSOR_POS_HIDE,
35 VHOST_USER_GPU_CURSOR_UPDATE,
36 VHOST_USER_GPU_SCANOUT,
37 VHOST_USER_GPU_UPDATE,
38 VHOST_USER_GPU_DMABUF_SCANOUT,
39 VHOST_USER_GPU_DMABUF_UPDATE,
40} VhostUserGpuRequest;
41
42typedef struct VhostUserGpuDisplayInfoReply {
43 struct virtio_gpu_resp_display_info info;
44} VhostUserGpuDisplayInfoReply;
45
46typedef struct VhostUserGpuCursorPos {
47 uint32_t scanout_id;
48 uint32_t x;
49 uint32_t y;
50} QEMU_PACKED VhostUserGpuCursorPos;
51
52typedef struct VhostUserGpuCursorUpdate {
53 VhostUserGpuCursorPos pos;
54 uint32_t hot_x;
55 uint32_t hot_y;
56 uint32_t data[64 * 64];
57} QEMU_PACKED VhostUserGpuCursorUpdate;
58
59typedef struct VhostUserGpuScanout {
60 uint32_t scanout_id;
61 uint32_t width;
62 uint32_t height;
63} QEMU_PACKED VhostUserGpuScanout;
64
65typedef struct VhostUserGpuUpdate {
66 uint32_t scanout_id;
67 uint32_t x;
68 uint32_t y;
69 uint32_t width;
70 uint32_t height;
71 uint8_t data[];
72} QEMU_PACKED VhostUserGpuUpdate;
73
74typedef struct VhostUserGpuDMABUFScanout {
75 uint32_t scanout_id;
76 uint32_t x;
77 uint32_t y;
78 uint32_t width;
79 uint32_t height;
80 uint32_t fd_width;
81 uint32_t fd_height;
82 uint32_t fd_stride;
83 uint32_t fd_flags;
84 int fd_drm_fourcc;
85} QEMU_PACKED VhostUserGpuDMABUFScanout;
86
87typedef struct VhostUserGpuMsg {
88 uint32_t request;
89 uint32_t flags;
90 uint32_t size;
91 union {
92 VhostUserGpuCursorPos cursor_pos;
93 VhostUserGpuCursorUpdate cursor_update;
94 VhostUserGpuScanout scanout;
95 VhostUserGpuUpdate update;
96 VhostUserGpuDMABUFScanout dmabuf_scanout;
97 struct virtio_gpu_resp_display_info display_info;
98 uint64_t u64;
99 } payload;
100} QEMU_PACKED VhostUserGpuMsg;
101
102static VhostUserGpuMsg m __attribute__ ((unused));
103#define VHOST_USER_GPU_HDR_SIZE \
104 (sizeof(m.request) + sizeof(m.flags) + sizeof(m.size))
105
106#define VHOST_USER_GPU_MSG_FLAG_REPLY 0x4
107
108struct virtio_gpu_scanout {
109 uint32_t width, height;
110 int x, y;
111 int invalidate;
112 uint32_t resource_id;
113};
114
115typedef struct VuGpu {
116 VugDev dev;
117 struct virtio_gpu_config virtio_config;
118 struct vugbm_device gdev;
119 int sock_fd;
120 int drm_rnode_fd;
121 GSource *renderer_source;
122 guint wait_ok;
123
124 bool virgl;
125 bool virgl_inited;
126 uint32_t inflight;
127
128 struct virtio_gpu_scanout scanout[VIRTIO_GPU_MAX_SCANOUTS];
129 QTAILQ_HEAD(, virtio_gpu_simple_resource) reslist;
130 QTAILQ_HEAD(, virtio_gpu_ctrl_command) fenceq;
131} VuGpu;
132
133struct virtio_gpu_ctrl_command {
134 VuVirtqElement elem;
135 VuVirtq *vq;
136 struct virtio_gpu_ctrl_hdr cmd_hdr;
137 uint32_t error;
138 bool finished;
139 QTAILQ_ENTRY(virtio_gpu_ctrl_command) next;
140};
141
142#define VUGPU_FILL_CMD(out) do { \
143 size_t s; \
144 s = iov_to_buf(cmd->elem.out_sg, cmd->elem.out_num, 0, \
145 &out, sizeof(out)); \
146 if (s != sizeof(out)) { \
147 g_critical("%s: command size incorrect %zu vs %zu", \
148 __func__, s, sizeof(out)); \
149 return; \
150 } \
151 } while (0)
152
153
154void vg_ctrl_response(VuGpu *g,
155 struct virtio_gpu_ctrl_command *cmd,
156 struct virtio_gpu_ctrl_hdr *resp,
157 size_t resp_len);
158
159void vg_ctrl_response_nodata(VuGpu *g,
160 struct virtio_gpu_ctrl_command *cmd,
161 enum virtio_gpu_ctrl_type type);
162
163int vg_create_mapping_iov(VuGpu *g,
164 struct virtio_gpu_resource_attach_backing *ab,
165 struct virtio_gpu_ctrl_command *cmd,
166 struct iovec **iov);
167
168void vg_get_display_info(VuGpu *vg, struct virtio_gpu_ctrl_command *cmd);
169
170void vg_wait_ok(VuGpu *g);
171
172void vg_send_msg(VuGpu *g, const VhostUserGpuMsg *msg, int fd);
173
174bool vg_recv_msg(VuGpu *g, uint32_t expect_req, uint32_t expect_size,
175 gpointer payload);
176
177
178#endif
179