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