]>
Commit | Line | Data |
---|---|---|
62232bf4 GH |
1 | /* |
2 | * Virtio GPU Device | |
3 | * | |
4 | * Copyright Red Hat, Inc. 2013-2014 | |
5 | * | |
6 | * Authors: | |
7 | * Dave Airlie <airlied@redhat.com> | |
8 | * Gerd Hoffmann <kraxel@redhat.com> | |
9 | * | |
10 | * This work is licensed under the terms of the GNU GPL, version 2. | |
11 | * See the COPYING file in the top-level directory. | |
12 | */ | |
13 | ||
121d0712 MA |
14 | #ifndef HW_VIRTIO_GPU_H |
15 | #define HW_VIRTIO_GPU_H | |
62232bf4 GH |
16 | |
17 | #include "qemu/queue.h" | |
18 | #include "ui/qemu-pixman.h" | |
19 | #include "ui/console.h" | |
20 | #include "hw/virtio/virtio.h" | |
8afc224f | 21 | #include "qemu/log.h" |
267f6646 | 22 | #include "sysemu/vhost-user-backend.h" |
62232bf4 GH |
23 | |
24 | #include "standard-headers/linux/virtio_gpu.h" | |
3857cd5c | 25 | #include "standard-headers/linux/virtio_ids.h" |
db1015e9 | 26 | #include "qom/object.h" |
a8bff79e | 27 | |
50d8e25e | 28 | #define TYPE_VIRTIO_GPU_BASE "virtio-gpu-base" |
c821774a | 29 | OBJECT_DECLARE_TYPE(VirtIOGPUBase, VirtIOGPUBaseClass, |
30b5707c | 30 | VIRTIO_GPU_BASE) |
50d8e25e | 31 | |
62232bf4 | 32 | #define TYPE_VIRTIO_GPU "virtio-gpu-device" |
cabbe8e5 | 33 | OBJECT_DECLARE_TYPE(VirtIOGPU, VirtIOGPUClass, VIRTIO_GPU) |
62232bf4 | 34 | |
063cd34a GH |
35 | #define TYPE_VIRTIO_GPU_GL "virtio-gpu-gl-device" |
36 | OBJECT_DECLARE_SIMPLE_TYPE(VirtIOGPUGL, VIRTIO_GPU_GL) | |
37 | ||
267f6646 | 38 | #define TYPE_VHOST_USER_GPU "vhost-user-gpu" |
8063396b | 39 | OBJECT_DECLARE_SIMPLE_TYPE(VhostUserGPU, VHOST_USER_GPU) |
267f6646 | 40 | |
62232bf4 GH |
41 | struct virtio_gpu_simple_resource { |
42 | uint32_t resource_id; | |
43 | uint32_t width; | |
44 | uint32_t height; | |
45 | uint32_t format; | |
0c244e50 | 46 | uint64_t *addrs; |
62232bf4 GH |
47 | struct iovec *iov; |
48 | unsigned int iov_cnt; | |
49 | uint32_t scanout_bitmask; | |
50 | pixman_image_t *image; | |
9b7621bc | 51 | uint64_t hostmem; |
9b60cdf9 VK |
52 | |
53 | uint64_t blob_size; | |
54 | void *blob; | |
55 | int dmabuf_fd; | |
56 | uint8_t *remapped; | |
57 | ||
62232bf4 GH |
58 | QTAILQ_ENTRY(virtio_gpu_simple_resource) next; |
59 | }; | |
60 | ||
e64d4b6a VK |
61 | struct virtio_gpu_framebuffer { |
62 | pixman_format_code_t format; | |
63 | uint32_t bytes_pp; | |
64 | uint32_t width, height; | |
65 | uint32_t stride; | |
66 | uint32_t offset; | |
67 | }; | |
68 | ||
62232bf4 GH |
69 | struct virtio_gpu_scanout { |
70 | QemuConsole *con; | |
71 | DisplaySurface *ds; | |
72 | uint32_t width, height; | |
73 | int x, y; | |
74 | int invalidate; | |
75 | uint32_t resource_id; | |
0c244e50 | 76 | struct virtio_gpu_update_cursor cursor; |
62232bf4 GH |
77 | QEMUCursor *current_cursor; |
78 | }; | |
79 | ||
80 | struct virtio_gpu_requested_state { | |
4bf47f36 | 81 | uint16_t width_mm, height_mm; |
62232bf4 | 82 | uint32_t width, height; |
b95b5631 | 83 | uint32_t refresh_rate; |
62232bf4 GH |
84 | int x, y; |
85 | }; | |
86 | ||
50d8e25e | 87 | enum virtio_gpu_base_conf_flags { |
9d9e1521 GH |
88 | VIRTIO_GPU_FLAG_VIRGL_ENABLED = 1, |
89 | VIRTIO_GPU_FLAG_STATS_ENABLED, | |
1ed2cb32 | 90 | VIRTIO_GPU_FLAG_EDID_ENABLED, |
ff64d44f | 91 | VIRTIO_GPU_FLAG_DMABUF_ENABLED, |
cce386e1 | 92 | VIRTIO_GPU_FLAG_BLOB_ENABLED, |
9d9e1521 GH |
93 | }; |
94 | ||
95 | #define virtio_gpu_virgl_enabled(_cfg) \ | |
96 | (_cfg.flags & (1 << VIRTIO_GPU_FLAG_VIRGL_ENABLED)) | |
97 | #define virtio_gpu_stats_enabled(_cfg) \ | |
98 | (_cfg.flags & (1 << VIRTIO_GPU_FLAG_STATS_ENABLED)) | |
1ed2cb32 GH |
99 | #define virtio_gpu_edid_enabled(_cfg) \ |
100 | (_cfg.flags & (1 << VIRTIO_GPU_FLAG_EDID_ENABLED)) | |
ff64d44f MAL |
101 | #define virtio_gpu_dmabuf_enabled(_cfg) \ |
102 | (_cfg.flags & (1 << VIRTIO_GPU_FLAG_DMABUF_ENABLED)) | |
cce386e1 VK |
103 | #define virtio_gpu_blob_enabled(_cfg) \ |
104 | (_cfg.flags & (1 << VIRTIO_GPU_FLAG_BLOB_ENABLED)) | |
9d9e1521 | 105 | |
50d8e25e | 106 | struct virtio_gpu_base_conf { |
62232bf4 | 107 | uint32_t max_outputs; |
9d9e1521 | 108 | uint32_t flags; |
729abb6a GH |
109 | uint32_t xres; |
110 | uint32_t yres; | |
62232bf4 GH |
111 | }; |
112 | ||
113 | struct virtio_gpu_ctrl_command { | |
114 | VirtQueueElement elem; | |
115 | VirtQueue *vq; | |
116 | struct virtio_gpu_ctrl_hdr cmd_hdr; | |
117 | uint32_t error; | |
118 | bool finished; | |
119 | QTAILQ_ENTRY(virtio_gpu_ctrl_command) next; | |
120 | }; | |
121 | ||
db1015e9 | 122 | struct VirtIOGPUBase { |
62232bf4 GH |
123 | VirtIODevice parent_obj; |
124 | ||
50d8e25e MAL |
125 | Error *migration_blocker; |
126 | ||
127 | struct virtio_gpu_base_conf conf; | |
128 | struct virtio_gpu_config virtio_config; | |
3b593b3f | 129 | const GraphicHwOps *hw_ops; |
50d8e25e | 130 | |
50d8e25e MAL |
131 | int renderer_blocked; |
132 | int enable; | |
133 | ||
134 | struct virtio_gpu_scanout scanout[VIRTIO_GPU_MAX_SCANOUTS]; | |
135 | ||
136 | int enabled_output_bitmask; | |
137 | struct virtio_gpu_requested_state req_state[VIRTIO_GPU_MAX_SCANOUTS]; | |
db1015e9 | 138 | }; |
50d8e25e | 139 | |
db1015e9 | 140 | struct VirtIOGPUBaseClass { |
50d8e25e MAL |
141 | VirtioDeviceClass parent; |
142 | ||
3cddb8b9 | 143 | void (*gl_flushed)(VirtIOGPUBase *g); |
db1015e9 | 144 | }; |
50d8e25e MAL |
145 | |
146 | #define VIRTIO_GPU_BASE_PROPERTIES(_state, _conf) \ | |
147 | DEFINE_PROP_UINT32("max_outputs", _state, _conf.max_outputs, 1), \ | |
148 | DEFINE_PROP_BIT("edid", _state, _conf.flags, \ | |
0a719662 | 149 | VIRTIO_GPU_FLAG_EDID_ENABLED, true), \ |
de72c4b7 DB |
150 | DEFINE_PROP_UINT32("xres", _state, _conf.xres, 1280), \ |
151 | DEFINE_PROP_UINT32("yres", _state, _conf.yres, 800) | |
50d8e25e | 152 | |
5752519e VK |
153 | typedef struct VGPUDMABuf { |
154 | QemuDmaBuf buf; | |
155 | uint32_t scanout_id; | |
156 | QTAILQ_ENTRY(VGPUDMABuf) next; | |
157 | } VGPUDMABuf; | |
158 | ||
db1015e9 | 159 | struct VirtIOGPU { |
50d8e25e MAL |
160 | VirtIOGPUBase parent_obj; |
161 | ||
162 | uint64_t conf_max_hostmem; | |
163 | ||
62232bf4 GH |
164 | VirtQueue *ctrl_vq; |
165 | VirtQueue *cursor_vq; | |
166 | ||
50d8e25e MAL |
167 | QEMUBH *ctrl_bh; |
168 | QEMUBH *cursor_bh; | |
62232bf4 | 169 | |
62232bf4 | 170 | QTAILQ_HEAD(, virtio_gpu_simple_resource) reslist; |
3eb769fd | 171 | QTAILQ_HEAD(, virtio_gpu_ctrl_command) cmdq; |
62232bf4 GH |
172 | QTAILQ_HEAD(, virtio_gpu_ctrl_command) fenceq; |
173 | ||
9b7621bc | 174 | uint64_t hostmem; |
62232bf4 | 175 | |
f8f3c271 | 176 | bool processing_cmdq; |
62232bf4 GH |
177 | QEMUTimer *fence_poll; |
178 | QEMUTimer *print_stats; | |
179 | ||
9d9e1521 | 180 | uint32_t inflight; |
62232bf4 | 181 | struct { |
62232bf4 GH |
182 | uint32_t max_inflight; |
183 | uint32_t requests; | |
184 | uint32_t req_3d; | |
185 | uint32_t bytes_3d; | |
186 | } stats; | |
5752519e VK |
187 | |
188 | struct { | |
189 | QTAILQ_HEAD(, VGPUDMABuf) bufs; | |
e86a93f5 | 190 | VGPUDMABuf *primary[VIRTIO_GPU_MAX_SCANOUTS]; |
5752519e | 191 | } dmabuf; |
db1015e9 | 192 | }; |
62232bf4 | 193 | |
cabbe8e5 GH |
194 | struct VirtIOGPUClass { |
195 | VirtIOGPUBaseClass parent; | |
196 | ||
197 | void (*handle_ctrl)(VirtIODevice *vdev, VirtQueue *vq); | |
2f47691a | 198 | void (*process_cmd)(VirtIOGPU *g, struct virtio_gpu_ctrl_command *cmd); |
2c267d66 GH |
199 | void (*update_cursor_data)(VirtIOGPU *g, |
200 | struct virtio_gpu_scanout *s, | |
201 | uint32_t resource_id); | |
cabbe8e5 GH |
202 | }; |
203 | ||
063cd34a GH |
204 | struct VirtIOGPUGL { |
205 | struct VirtIOGPU parent_obj; | |
eff6fa17 GH |
206 | |
207 | bool renderer_inited; | |
208 | bool renderer_reset; | |
063cd34a GH |
209 | }; |
210 | ||
db1015e9 | 211 | struct VhostUserGPU { |
267f6646 | 212 | VirtIOGPUBase parent_obj; |
62232bf4 | 213 | |
267f6646 MAL |
214 | VhostUserBackend *vhost; |
215 | int vhost_gpu_fd; /* closed by the chardev */ | |
216 | CharBackend vhost_chr; | |
217 | QemuDmaBuf dmabuf[VIRTIO_GPU_MAX_SCANOUTS]; | |
218 | bool backend_blocked; | |
db1015e9 | 219 | }; |
267f6646 | 220 | |
62232bf4 GH |
221 | #define VIRTIO_GPU_FILL_CMD(out) do { \ |
222 | size_t s; \ | |
223 | s = iov_to_buf(cmd->elem.out_sg, cmd->elem.out_num, 0, \ | |
224 | &out, sizeof(out)); \ | |
225 | if (s != sizeof(out)) { \ | |
226 | qemu_log_mask(LOG_GUEST_ERROR, \ | |
227 | "%s: command size incorrect %zu vs %zu\n", \ | |
228 | __func__, s, sizeof(out)); \ | |
229 | return; \ | |
230 | } \ | |
231 | } while (0) | |
232 | ||
50d8e25e MAL |
233 | /* virtio-gpu-base.c */ |
234 | bool virtio_gpu_base_device_realize(DeviceState *qdev, | |
235 | VirtIOHandleOutput ctrl_cb, | |
236 | VirtIOHandleOutput cursor_cb, | |
237 | Error **errp); | |
238 | void virtio_gpu_base_reset(VirtIOGPUBase *g); | |
239 | void virtio_gpu_base_fill_display_info(VirtIOGPUBase *g, | |
240 | struct virtio_gpu_resp_display_info *dpy_info); | |
241 | ||
62232bf4 GH |
242 | /* virtio-gpu.c */ |
243 | void virtio_gpu_ctrl_response(VirtIOGPU *g, | |
244 | struct virtio_gpu_ctrl_command *cmd, | |
245 | struct virtio_gpu_ctrl_hdr *resp, | |
246 | size_t resp_len); | |
247 | void virtio_gpu_ctrl_response_nodata(VirtIOGPU *g, | |
248 | struct virtio_gpu_ctrl_command *cmd, | |
249 | enum virtio_gpu_ctrl_type type); | |
250 | void virtio_gpu_get_display_info(VirtIOGPU *g, | |
251 | struct virtio_gpu_ctrl_command *cmd); | |
1ed2cb32 GH |
252 | void virtio_gpu_get_edid(VirtIOGPU *g, |
253 | struct virtio_gpu_ctrl_command *cmd); | |
3bb68f79 | 254 | int virtio_gpu_create_mapping_iov(VirtIOGPU *g, |
70d37662 | 255 | uint32_t nr_entries, uint32_t offset, |
62232bf4 | 256 | struct virtio_gpu_ctrl_command *cmd, |
9049f8bc GH |
257 | uint64_t **addr, struct iovec **iov, |
258 | uint32_t *niov); | |
3bb68f79 GH |
259 | void virtio_gpu_cleanup_mapping_iov(VirtIOGPU *g, |
260 | struct iovec *iov, uint32_t count); | |
0c55a1cf | 261 | void virtio_gpu_process_cmdq(VirtIOGPU *g); |
37f86af0 | 262 | void virtio_gpu_device_realize(DeviceState *qdev, Error **errp); |
76fa8b35 | 263 | void virtio_gpu_reset(VirtIODevice *vdev); |
2f47691a | 264 | void virtio_gpu_simple_process_cmd(VirtIOGPU *g, struct virtio_gpu_ctrl_command *cmd); |
2c267d66 GH |
265 | void virtio_gpu_update_cursor_data(VirtIOGPU *g, |
266 | struct virtio_gpu_scanout *s, | |
267 | uint32_t resource_id); | |
62232bf4 | 268 | |
9b60cdf9 VK |
269 | /* virtio-gpu-udmabuf.c */ |
270 | bool virtio_gpu_have_udmabuf(void); | |
271 | void virtio_gpu_init_udmabuf(struct virtio_gpu_simple_resource *res); | |
272 | void virtio_gpu_fini_udmabuf(struct virtio_gpu_simple_resource *res); | |
5752519e VK |
273 | int virtio_gpu_update_dmabuf(VirtIOGPU *g, |
274 | uint32_t scanout_id, | |
275 | struct virtio_gpu_simple_resource *res, | |
e86a93f5 DK |
276 | struct virtio_gpu_framebuffer *fb, |
277 | struct virtio_gpu_rect *r); | |
9b60cdf9 | 278 | |
9d9e1521 GH |
279 | /* virtio-gpu-3d.c */ |
280 | void virtio_gpu_virgl_process_cmd(VirtIOGPU *g, | |
281 | struct virtio_gpu_ctrl_command *cmd); | |
282 | void virtio_gpu_virgl_fence_poll(VirtIOGPU *g); | |
8a13b9bc | 283 | void virtio_gpu_virgl_reset_scanout(VirtIOGPU *g); |
9d9e1521 GH |
284 | void virtio_gpu_virgl_reset(VirtIOGPU *g); |
285 | int virtio_gpu_virgl_init(VirtIOGPU *g); | |
5643cc94 | 286 | int virtio_gpu_virgl_get_num_capsets(VirtIOGPU *g); |
50d8e25e | 287 | |
62232bf4 | 288 | #endif |