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