xref: /qemu/contrib/vhost-user-gpu/vugpu.h (revision dcaaf2bf)
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 } VhostUserGpuRequest;
41 
42 typedef struct VhostUserGpuDisplayInfoReply {
43     struct virtio_gpu_resp_display_info info;
44 } VhostUserGpuDisplayInfoReply;
45 
46 typedef struct VhostUserGpuCursorPos {
47     uint32_t scanout_id;
48     uint32_t x;
49     uint32_t y;
50 } QEMU_PACKED VhostUserGpuCursorPos;
51 
52 typedef 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 
59 typedef struct VhostUserGpuScanout {
60     uint32_t scanout_id;
61     uint32_t width;
62     uint32_t height;
63 } QEMU_PACKED VhostUserGpuScanout;
64 
65 typedef 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 
74 typedef 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 
87 typedef struct VhostUserGpuEdidRequest {
88     uint32_t scanout_id;
89 } QEMU_PACKED VhostUserGpuEdidRequest;
90 
91 typedef struct VhostUserGpuMsg {
92     uint32_t request; /* VhostUserGpuRequest */
93     uint32_t flags;
94     uint32_t size; /* the following payload size */
95     union {
96         VhostUserGpuCursorPos cursor_pos;
97         VhostUserGpuCursorUpdate cursor_update;
98         VhostUserGpuScanout scanout;
99         VhostUserGpuUpdate update;
100         VhostUserGpuDMABUFScanout dmabuf_scanout;
101         VhostUserGpuEdidRequest edid_req;
102         struct virtio_gpu_resp_edid resp_edid;
103         struct virtio_gpu_resp_display_info display_info;
104         uint64_t u64;
105     } payload;
106 } QEMU_PACKED VhostUserGpuMsg;
107 
108 static VhostUserGpuMsg m __attribute__ ((unused));
109 #define VHOST_USER_GPU_HDR_SIZE \
110     (sizeof(m.request) + sizeof(m.flags) + sizeof(m.size))
111 
112 #define VHOST_USER_GPU_MSG_FLAG_REPLY 0x4
113 
114 #define VHOST_USER_GPU_PROTOCOL_F_EDID 0
115 
116 struct virtio_gpu_scanout {
117     uint32_t width, height;
118     int x, y;
119     int invalidate;
120     uint32_t resource_id;
121 };
122 
123 typedef struct VuGpu {
124     VugDev dev;
125     struct virtio_gpu_config virtio_config;
126     struct vugbm_device gdev;
127     int sock_fd;
128     int drm_rnode_fd;
129     GSource *renderer_source;
130     guint wait_in;
131 
132     bool virgl;
133     bool virgl_inited;
134     bool edid_inited;
135     uint32_t inflight;
136 
137     struct virtio_gpu_scanout scanout[VIRTIO_GPU_MAX_SCANOUTS];
138     QTAILQ_HEAD(, virtio_gpu_simple_resource) reslist;
139     QTAILQ_HEAD(, virtio_gpu_ctrl_command) fenceq;
140 } VuGpu;
141 
142 enum {
143     VG_CMD_STATE_NEW,
144     VG_CMD_STATE_PENDING,
145     VG_CMD_STATE_FINISHED,
146 };
147 
148 struct virtio_gpu_ctrl_command {
149     VuVirtqElement elem;
150     VuVirtq *vq;
151     struct virtio_gpu_ctrl_hdr cmd_hdr;
152     uint32_t error;
153     int state;
154     QTAILQ_ENTRY(virtio_gpu_ctrl_command) next;
155 };
156 
157 #define VUGPU_FILL_CMD(out) do {                                \
158         size_t s;                                               \
159         s = iov_to_buf(cmd->elem.out_sg, cmd->elem.out_num, 0,  \
160                        &out, sizeof(out));                      \
161         if (s != sizeof(out)) {                                 \
162             g_critical("%s: command size incorrect %zu vs %zu", \
163                        __func__, s, sizeof(out));               \
164             return;                                             \
165         }                                                       \
166     } while (0)
167 
168 
169 void    vg_ctrl_response(VuGpu *g,
170                          struct virtio_gpu_ctrl_command *cmd,
171                          struct virtio_gpu_ctrl_hdr *resp,
172                          size_t resp_len);
173 
174 void    vg_ctrl_response_nodata(VuGpu *g,
175                                 struct virtio_gpu_ctrl_command *cmd,
176                                 enum virtio_gpu_ctrl_type type);
177 
178 int     vg_create_mapping_iov(VuGpu *g,
179                               struct virtio_gpu_resource_attach_backing *ab,
180                               struct virtio_gpu_ctrl_command *cmd,
181                               struct iovec **iov);
182 void    vg_cleanup_mapping_iov(VuGpu *g, struct iovec *iov, uint32_t count);
183 void    vg_get_display_info(VuGpu *vg, struct virtio_gpu_ctrl_command *cmd);
184 void    vg_get_edid(VuGpu *vg, struct virtio_gpu_ctrl_command *cmd);
185 
186 void    vg_wait_ok(VuGpu *g);
187 
188 void    vg_send_msg(VuGpu *g, const VhostUserGpuMsg *msg, int fd);
189 
190 bool    vg_recv_msg(VuGpu *g, uint32_t expect_req, uint32_t expect_size,
191                     gpointer payload);
192 
193 
194 #endif
195