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 #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 28 typedef 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 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 VhostUserGpuMsg { 88 uint32_t request; /* VhostUserGpuRequest */ 89 uint32_t flags; 90 uint32_t size; /* the following payload 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 102 static 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 108 struct virtio_gpu_scanout { 109 uint32_t width, height; 110 int x, y; 111 int invalidate; 112 uint32_t resource_id; 113 }; 114 115 typedef 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 133 struct 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 154 void 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 159 void vg_ctrl_response_nodata(VuGpu *g, 160 struct virtio_gpu_ctrl_command *cmd, 161 enum virtio_gpu_ctrl_type type); 162 163 int 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 168 void vg_get_display_info(VuGpu *vg, struct virtio_gpu_ctrl_command *cmd); 169 170 void vg_wait_ok(VuGpu *g); 171 172 void vg_send_msg(VuGpu *g, const VhostUserGpuMsg *msg, int fd); 173 174 bool vg_recv_msg(VuGpu *g, uint32_t expect_req, uint32_t expect_size, 175 gpointer payload); 176 177 178 #endif 179