xref: /qemu/contrib/vhost-user-gpu/vugpu.h (revision cc46a7ef)
1d52c454aSMarc-André Lureau /*
2d52c454aSMarc-André Lureau  * Virtio vhost-user GPU Device
3d52c454aSMarc-André Lureau  *
4d52c454aSMarc-André Lureau  * Copyright Red Hat, Inc. 2013-2018
5d52c454aSMarc-André Lureau  *
6d52c454aSMarc-André Lureau  * Authors:
7d52c454aSMarc-André Lureau  *     Dave Airlie <airlied@redhat.com>
8d52c454aSMarc-André Lureau  *     Gerd Hoffmann <kraxel@redhat.com>
9d52c454aSMarc-André Lureau  *     Marc-André Lureau <marcandre.lureau@redhat.com>
10d52c454aSMarc-André Lureau  *
11d52c454aSMarc-André Lureau  * This work is licensed under the terms of the GNU GPL, version 2 or later.
12d52c454aSMarc-André Lureau  * See the COPYING file in the top-level directory.
13d52c454aSMarc-André Lureau  */
14fe2611b0SMarkus Armbruster 
15fe2611b0SMarkus Armbruster #ifndef VUGPU_H
16fe2611b0SMarkus Armbruster #define VUGPU_H
17d52c454aSMarc-André Lureau 
18d52c454aSMarc-André Lureau 
190df750e9SMarc-André Lureau #include "libvhost-user-glib.h"
20d52c454aSMarc-André Lureau #include "standard-headers/linux/virtio_gpu.h"
21d52c454aSMarc-André Lureau 
22d52c454aSMarc-André Lureau #include "qemu/queue.h"
23d52c454aSMarc-André Lureau #include "qemu/iov.h"
24d52c454aSMarc-André Lureau #include "qemu/bswap.h"
25d52c454aSMarc-André Lureau #include "vugbm.h"
26d52c454aSMarc-André Lureau 
27d52c454aSMarc-André Lureau typedef enum VhostUserGpuRequest {
28d52c454aSMarc-André Lureau     VHOST_USER_GPU_NONE = 0,
29d52c454aSMarc-André Lureau     VHOST_USER_GPU_GET_PROTOCOL_FEATURES,
30d52c454aSMarc-André Lureau     VHOST_USER_GPU_SET_PROTOCOL_FEATURES,
31d52c454aSMarc-André Lureau     VHOST_USER_GPU_GET_DISPLAY_INFO,
32d52c454aSMarc-André Lureau     VHOST_USER_GPU_CURSOR_POS,
33d52c454aSMarc-André Lureau     VHOST_USER_GPU_CURSOR_POS_HIDE,
34d52c454aSMarc-André Lureau     VHOST_USER_GPU_CURSOR_UPDATE,
35d52c454aSMarc-André Lureau     VHOST_USER_GPU_SCANOUT,
36d52c454aSMarc-André Lureau     VHOST_USER_GPU_UPDATE,
37d52c454aSMarc-André Lureau     VHOST_USER_GPU_DMABUF_SCANOUT,
38d52c454aSMarc-André Lureau     VHOST_USER_GPU_DMABUF_UPDATE,
39c0644426SErico Nunes     VHOST_USER_GPU_GET_EDID,
40e3c82fe0SErico Nunes     VHOST_USER_GPU_DMABUF_SCANOUT2,
41d52c454aSMarc-André Lureau } VhostUserGpuRequest;
42d52c454aSMarc-André Lureau 
43d52c454aSMarc-André Lureau typedef struct VhostUserGpuDisplayInfoReply {
44d52c454aSMarc-André Lureau     struct virtio_gpu_resp_display_info info;
45d52c454aSMarc-André Lureau } VhostUserGpuDisplayInfoReply;
46d52c454aSMarc-André Lureau 
47d52c454aSMarc-André Lureau typedef struct VhostUserGpuCursorPos {
48d52c454aSMarc-André Lureau     uint32_t scanout_id;
49d52c454aSMarc-André Lureau     uint32_t x;
50d52c454aSMarc-André Lureau     uint32_t y;
51d52c454aSMarc-André Lureau } QEMU_PACKED VhostUserGpuCursorPos;
52d52c454aSMarc-André Lureau 
53d52c454aSMarc-André Lureau typedef struct VhostUserGpuCursorUpdate {
54d52c454aSMarc-André Lureau     VhostUserGpuCursorPos pos;
55d52c454aSMarc-André Lureau     uint32_t hot_x;
56d52c454aSMarc-André Lureau     uint32_t hot_y;
57d52c454aSMarc-André Lureau     uint32_t data[64 * 64];
58d52c454aSMarc-André Lureau } QEMU_PACKED VhostUserGpuCursorUpdate;
59d52c454aSMarc-André Lureau 
60d52c454aSMarc-André Lureau typedef struct VhostUserGpuScanout {
61d52c454aSMarc-André Lureau     uint32_t scanout_id;
62d52c454aSMarc-André Lureau     uint32_t width;
63d52c454aSMarc-André Lureau     uint32_t height;
64d52c454aSMarc-André Lureau } QEMU_PACKED VhostUserGpuScanout;
65d52c454aSMarc-André Lureau 
66d52c454aSMarc-André Lureau typedef struct VhostUserGpuUpdate {
67d52c454aSMarc-André Lureau     uint32_t scanout_id;
68d52c454aSMarc-André Lureau     uint32_t x;
69d52c454aSMarc-André Lureau     uint32_t y;
70d52c454aSMarc-André Lureau     uint32_t width;
71d52c454aSMarc-André Lureau     uint32_t height;
72d52c454aSMarc-André Lureau     uint8_t data[];
73d52c454aSMarc-André Lureau } QEMU_PACKED VhostUserGpuUpdate;
74d52c454aSMarc-André Lureau 
75d52c454aSMarc-André Lureau typedef struct VhostUserGpuDMABUFScanout {
76d52c454aSMarc-André Lureau     uint32_t scanout_id;
77d52c454aSMarc-André Lureau     uint32_t x;
78d52c454aSMarc-André Lureau     uint32_t y;
79d52c454aSMarc-André Lureau     uint32_t width;
80d52c454aSMarc-André Lureau     uint32_t height;
81d52c454aSMarc-André Lureau     uint32_t fd_width;
82d52c454aSMarc-André Lureau     uint32_t fd_height;
83d52c454aSMarc-André Lureau     uint32_t fd_stride;
84d52c454aSMarc-André Lureau     uint32_t fd_flags;
85d52c454aSMarc-André Lureau     int fd_drm_fourcc;
86d52c454aSMarc-André Lureau } QEMU_PACKED VhostUserGpuDMABUFScanout;
87d52c454aSMarc-André Lureau 
88e3c82fe0SErico Nunes typedef struct VhostUserGpuDMABUFScanout2 {
89e3c82fe0SErico Nunes     struct VhostUserGpuDMABUFScanout dmabuf_scanout;
90e3c82fe0SErico Nunes     uint64_t modifier;
91e3c82fe0SErico Nunes } QEMU_PACKED VhostUserGpuDMABUFScanout2;
92e3c82fe0SErico Nunes 
93c0644426SErico Nunes typedef struct VhostUserGpuEdidRequest {
94c0644426SErico Nunes     uint32_t scanout_id;
95c0644426SErico Nunes } QEMU_PACKED VhostUserGpuEdidRequest;
96c0644426SErico Nunes 
97d52c454aSMarc-André Lureau typedef struct VhostUserGpuMsg {
98d52c454aSMarc-André Lureau     uint32_t request; /* VhostUserGpuRequest */
99d52c454aSMarc-André Lureau     uint32_t flags;
100d52c454aSMarc-André Lureau     uint32_t size; /* the following payload size */
101d52c454aSMarc-André Lureau     union {
102d52c454aSMarc-André Lureau         VhostUserGpuCursorPos cursor_pos;
103d52c454aSMarc-André Lureau         VhostUserGpuCursorUpdate cursor_update;
104d52c454aSMarc-André Lureau         VhostUserGpuScanout scanout;
105d52c454aSMarc-André Lureau         VhostUserGpuUpdate update;
106d52c454aSMarc-André Lureau         VhostUserGpuDMABUFScanout dmabuf_scanout;
107e3c82fe0SErico Nunes         VhostUserGpuDMABUFScanout2 dmabuf_scanout2;
108c0644426SErico Nunes         VhostUserGpuEdidRequest edid_req;
109c0644426SErico Nunes         struct virtio_gpu_resp_edid resp_edid;
110d52c454aSMarc-André Lureau         struct virtio_gpu_resp_display_info display_info;
111d52c454aSMarc-André Lureau         uint64_t u64;
112d52c454aSMarc-André Lureau     } payload;
113d52c454aSMarc-André Lureau } QEMU_PACKED VhostUserGpuMsg;
114d52c454aSMarc-André Lureau 
115d52c454aSMarc-André Lureau static VhostUserGpuMsg m __attribute__ ((unused));
116d52c454aSMarc-André Lureau #define VHOST_USER_GPU_HDR_SIZE \
117d52c454aSMarc-André Lureau     (sizeof(m.request) + sizeof(m.flags) + sizeof(m.size))
118d52c454aSMarc-André Lureau 
119d52c454aSMarc-André Lureau #define VHOST_USER_GPU_MSG_FLAG_REPLY 0x4
120d52c454aSMarc-André Lureau 
121c0644426SErico Nunes #define VHOST_USER_GPU_PROTOCOL_F_EDID 0
122e3c82fe0SErico Nunes #define VHOST_USER_GPU_PROTOCOL_F_DMABUF2 1
123c0644426SErico Nunes 
124d52c454aSMarc-André Lureau struct virtio_gpu_scanout {
125d52c454aSMarc-André Lureau     uint32_t width, height;
126d52c454aSMarc-André Lureau     int x, y;
127d52c454aSMarc-André Lureau     int invalidate;
128d52c454aSMarc-André Lureau     uint32_t resource_id;
129d52c454aSMarc-André Lureau };
130d52c454aSMarc-André Lureau 
131d52c454aSMarc-André Lureau typedef struct VuGpu {
132d52c454aSMarc-André Lureau     VugDev dev;
133d52c454aSMarc-André Lureau     struct virtio_gpu_config virtio_config;
134d52c454aSMarc-André Lureau     struct vugbm_device gdev;
135d52c454aSMarc-André Lureau     int sock_fd;
136d52c454aSMarc-André Lureau     int drm_rnode_fd;
137d52c454aSMarc-André Lureau     GSource *renderer_source;
1381f83ea8dSMarc-André Lureau     guint wait_in;
139d52c454aSMarc-André Lureau 
140d52c454aSMarc-André Lureau     bool virgl;
141d52c454aSMarc-André Lureau     bool virgl_inited;
142c0644426SErico Nunes     bool edid_inited;
143e3c82fe0SErico Nunes     bool use_modifiers;
144d52c454aSMarc-André Lureau     uint32_t inflight;
145d52c454aSMarc-André Lureau 
146d52c454aSMarc-André Lureau     struct virtio_gpu_scanout scanout[VIRTIO_GPU_MAX_SCANOUTS];
147d52c454aSMarc-André Lureau     QTAILQ_HEAD(, virtio_gpu_simple_resource) reslist;
148d52c454aSMarc-André Lureau     QTAILQ_HEAD(, virtio_gpu_ctrl_command) fenceq;
149d52c454aSMarc-André Lureau } VuGpu;
150d52c454aSMarc-André Lureau 
15172e631c6SMarc-André Lureau enum {
15272e631c6SMarc-André Lureau     VG_CMD_STATE_NEW,
15372e631c6SMarc-André Lureau     VG_CMD_STATE_PENDING,
15472e631c6SMarc-André Lureau     VG_CMD_STATE_FINISHED,
15572e631c6SMarc-André Lureau };
15672e631c6SMarc-André Lureau 
157d52c454aSMarc-André Lureau struct virtio_gpu_ctrl_command {
158d52c454aSMarc-André Lureau     VuVirtqElement elem;
159d52c454aSMarc-André Lureau     VuVirtq *vq;
160d52c454aSMarc-André Lureau     struct virtio_gpu_ctrl_hdr cmd_hdr;
161d52c454aSMarc-André Lureau     uint32_t error;
16272e631c6SMarc-André Lureau     int state;
163d52c454aSMarc-André Lureau     QTAILQ_ENTRY(virtio_gpu_ctrl_command) next;
164d52c454aSMarc-André Lureau };
165d52c454aSMarc-André Lureau 
166d52c454aSMarc-André Lureau #define VUGPU_FILL_CMD(out) do {                                \
167cc46a7efSThomas Huth         size_t vugpufillcmd_s_ =                                \
168cc46a7efSThomas Huth             iov_to_buf(cmd->elem.out_sg, cmd->elem.out_num, 0,  \
169d52c454aSMarc-André Lureau                        &out, sizeof(out));                      \
170cc46a7efSThomas Huth         if (vugpufillcmd_s_ != sizeof(out)) {                   \
171d52c454aSMarc-André Lureau             g_critical("%s: command size incorrect %zu vs %zu", \
172cc46a7efSThomas Huth                        __func__, vugpufillcmd_s_, sizeof(out)); \
173d52c454aSMarc-André Lureau             return;                                             \
174d52c454aSMarc-André Lureau         }                                                       \
175d52c454aSMarc-André Lureau     } while (0)
176d52c454aSMarc-André Lureau 
177d52c454aSMarc-André Lureau 
178d52c454aSMarc-André Lureau void    vg_ctrl_response(VuGpu *g,
179d52c454aSMarc-André Lureau                          struct virtio_gpu_ctrl_command *cmd,
180d52c454aSMarc-André Lureau                          struct virtio_gpu_ctrl_hdr *resp,
181d52c454aSMarc-André Lureau                          size_t resp_len);
182d52c454aSMarc-André Lureau 
183d52c454aSMarc-André Lureau void    vg_ctrl_response_nodata(VuGpu *g,
184d52c454aSMarc-André Lureau                                 struct virtio_gpu_ctrl_command *cmd,
185d52c454aSMarc-André Lureau                                 enum virtio_gpu_ctrl_type type);
186d52c454aSMarc-André Lureau 
187d52c454aSMarc-André Lureau int     vg_create_mapping_iov(VuGpu *g,
188d52c454aSMarc-André Lureau                               struct virtio_gpu_resource_attach_backing *ab,
189d52c454aSMarc-André Lureau                               struct virtio_gpu_ctrl_command *cmd,
190d52c454aSMarc-André Lureau                               struct iovec **iov);
1913ea32d13SLi Qiang void    vg_cleanup_mapping_iov(VuGpu *g, struct iovec *iov, uint32_t count);
192d52c454aSMarc-André Lureau void    vg_get_display_info(VuGpu *vg, struct virtio_gpu_ctrl_command *cmd);
193c0644426SErico Nunes void    vg_get_edid(VuGpu *vg, struct virtio_gpu_ctrl_command *cmd);
194d52c454aSMarc-André Lureau 
195d52c454aSMarc-André Lureau void    vg_wait_ok(VuGpu *g);
196d52c454aSMarc-André Lureau 
197d52c454aSMarc-André Lureau void    vg_send_msg(VuGpu *g, const VhostUserGpuMsg *msg, int fd);
198d52c454aSMarc-André Lureau 
199d52c454aSMarc-André Lureau bool    vg_recv_msg(VuGpu *g, uint32_t expect_req, uint32_t expect_size,
200d52c454aSMarc-André Lureau                     gpointer payload);
201d52c454aSMarc-André Lureau 
202d52c454aSMarc-André Lureau 
203d52c454aSMarc-André Lureau #endif
204