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