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