|  | /* | 
|  | * Virtio vhost-user GPU Device | 
|  | * | 
|  | * Copyright Red Hat, Inc. 2013-2018 | 
|  | * | 
|  | * Authors: | 
|  | *     Dave Airlie <airlied@redhat.com> | 
|  | *     Gerd Hoffmann <kraxel@redhat.com> | 
|  | *     Marc-André Lureau <marcandre.lureau@redhat.com> | 
|  | * | 
|  | * This work is licensed under the terms of the GNU GPL, version 2 or later. | 
|  | * See the COPYING file in the top-level directory. | 
|  | */ | 
|  |  | 
|  | #ifndef VUGPU_H | 
|  | #define VUGPU_H | 
|  |  | 
|  |  | 
|  | #include "libvhost-user-glib.h" | 
|  | #include "standard-headers/linux/virtio_gpu.h" | 
|  |  | 
|  | #include "qemu/queue.h" | 
|  | #include "qemu/iov.h" | 
|  | #include "qemu/bswap.h" | 
|  | #include "vugbm.h" | 
|  |  | 
|  | typedef enum VhostUserGpuRequest { | 
|  | VHOST_USER_GPU_NONE = 0, | 
|  | VHOST_USER_GPU_GET_PROTOCOL_FEATURES, | 
|  | VHOST_USER_GPU_SET_PROTOCOL_FEATURES, | 
|  | VHOST_USER_GPU_GET_DISPLAY_INFO, | 
|  | VHOST_USER_GPU_CURSOR_POS, | 
|  | VHOST_USER_GPU_CURSOR_POS_HIDE, | 
|  | VHOST_USER_GPU_CURSOR_UPDATE, | 
|  | VHOST_USER_GPU_SCANOUT, | 
|  | VHOST_USER_GPU_UPDATE, | 
|  | VHOST_USER_GPU_DMABUF_SCANOUT, | 
|  | VHOST_USER_GPU_DMABUF_UPDATE, | 
|  | VHOST_USER_GPU_GET_EDID, | 
|  | VHOST_USER_GPU_DMABUF_SCANOUT2, | 
|  | } VhostUserGpuRequest; | 
|  |  | 
|  | typedef struct VhostUserGpuDisplayInfoReply { | 
|  | struct virtio_gpu_resp_display_info info; | 
|  | } VhostUserGpuDisplayInfoReply; | 
|  |  | 
|  | typedef struct VhostUserGpuCursorPos { | 
|  | uint32_t scanout_id; | 
|  | uint32_t x; | 
|  | uint32_t y; | 
|  | } QEMU_PACKED VhostUserGpuCursorPos; | 
|  |  | 
|  | typedef struct VhostUserGpuCursorUpdate { | 
|  | VhostUserGpuCursorPos pos; | 
|  | uint32_t hot_x; | 
|  | uint32_t hot_y; | 
|  | uint32_t data[64 * 64]; | 
|  | } QEMU_PACKED VhostUserGpuCursorUpdate; | 
|  |  | 
|  | typedef struct VhostUserGpuScanout { | 
|  | uint32_t scanout_id; | 
|  | uint32_t width; | 
|  | uint32_t height; | 
|  | } QEMU_PACKED VhostUserGpuScanout; | 
|  |  | 
|  | typedef struct VhostUserGpuUpdate { | 
|  | uint32_t scanout_id; | 
|  | uint32_t x; | 
|  | uint32_t y; | 
|  | uint32_t width; | 
|  | uint32_t height; | 
|  | uint8_t data[]; | 
|  | } QEMU_PACKED VhostUserGpuUpdate; | 
|  |  | 
|  | typedef struct VhostUserGpuDMABUFScanout { | 
|  | uint32_t scanout_id; | 
|  | uint32_t x; | 
|  | uint32_t y; | 
|  | uint32_t width; | 
|  | uint32_t height; | 
|  | uint32_t fd_width; | 
|  | uint32_t fd_height; | 
|  | uint32_t fd_stride; | 
|  | uint32_t fd_flags; | 
|  | int fd_drm_fourcc; | 
|  | } QEMU_PACKED VhostUserGpuDMABUFScanout; | 
|  |  | 
|  | typedef struct VhostUserGpuDMABUFScanout2 { | 
|  | struct VhostUserGpuDMABUFScanout dmabuf_scanout; | 
|  | uint64_t modifier; | 
|  | } QEMU_PACKED VhostUserGpuDMABUFScanout2; | 
|  |  | 
|  | typedef struct VhostUserGpuEdidRequest { | 
|  | uint32_t scanout_id; | 
|  | } QEMU_PACKED VhostUserGpuEdidRequest; | 
|  |  | 
|  | typedef struct VhostUserGpuMsg { | 
|  | uint32_t request; /* VhostUserGpuRequest */ | 
|  | uint32_t flags; | 
|  | uint32_t size; /* the following payload size */ | 
|  | union { | 
|  | VhostUserGpuCursorPos cursor_pos; | 
|  | VhostUserGpuCursorUpdate cursor_update; | 
|  | VhostUserGpuScanout scanout; | 
|  | VhostUserGpuUpdate update; | 
|  | VhostUserGpuDMABUFScanout dmabuf_scanout; | 
|  | VhostUserGpuDMABUFScanout2 dmabuf_scanout2; | 
|  | VhostUserGpuEdidRequest edid_req; | 
|  | struct virtio_gpu_resp_edid resp_edid; | 
|  | struct virtio_gpu_resp_display_info display_info; | 
|  | uint64_t u64; | 
|  | } payload; | 
|  | } QEMU_PACKED VhostUserGpuMsg; | 
|  |  | 
|  | static VhostUserGpuMsg m __attribute__ ((unused)); | 
|  | #define VHOST_USER_GPU_HDR_SIZE \ | 
|  | (sizeof(m.request) + sizeof(m.flags) + sizeof(m.size)) | 
|  |  | 
|  | #define VHOST_USER_GPU_MSG_FLAG_REPLY 0x4 | 
|  |  | 
|  | #define VHOST_USER_GPU_PROTOCOL_F_EDID 0 | 
|  | #define VHOST_USER_GPU_PROTOCOL_F_DMABUF2 1 | 
|  |  | 
|  | struct virtio_gpu_scanout { | 
|  | uint32_t width, height; | 
|  | int x, y; | 
|  | int invalidate; | 
|  | uint32_t resource_id; | 
|  | }; | 
|  |  | 
|  | typedef struct VuGpu { | 
|  | VugDev dev; | 
|  | struct virtio_gpu_config virtio_config; | 
|  | struct vugbm_device gdev; | 
|  | int sock_fd; | 
|  | int drm_rnode_fd; | 
|  | GSource *renderer_source; | 
|  | guint wait_in; | 
|  |  | 
|  | bool virgl; | 
|  | bool virgl_inited; | 
|  | bool edid_inited; | 
|  | bool use_modifiers; | 
|  | uint32_t inflight; | 
|  |  | 
|  | struct virtio_gpu_scanout scanout[VIRTIO_GPU_MAX_SCANOUTS]; | 
|  | QTAILQ_HEAD(, virtio_gpu_simple_resource) reslist; | 
|  | QTAILQ_HEAD(, virtio_gpu_ctrl_command) fenceq; | 
|  | } VuGpu; | 
|  |  | 
|  | enum { | 
|  | VG_CMD_STATE_NEW, | 
|  | VG_CMD_STATE_PENDING, | 
|  | VG_CMD_STATE_FINISHED, | 
|  | }; | 
|  |  | 
|  | struct virtio_gpu_ctrl_command { | 
|  | VuVirtqElement elem; | 
|  | VuVirtq *vq; | 
|  | struct virtio_gpu_ctrl_hdr cmd_hdr; | 
|  | uint32_t error; | 
|  | int state; | 
|  | QTAILQ_ENTRY(virtio_gpu_ctrl_command) next; | 
|  | }; | 
|  |  | 
|  | #define VUGPU_FILL_CMD(out) do {                                \ | 
|  | size_t vugpufillcmd_s_ =                                \ | 
|  | iov_to_buf(cmd->elem.out_sg, cmd->elem.out_num, 0,  \ | 
|  | &out, sizeof(out));                      \ | 
|  | if (vugpufillcmd_s_ != sizeof(out)) {                   \ | 
|  | g_critical("%s: command size incorrect %zu vs %zu", \ | 
|  | __func__, vugpufillcmd_s_, sizeof(out)); \ | 
|  | return;                                             \ | 
|  | }                                                       \ | 
|  | } while (0) | 
|  |  | 
|  |  | 
|  | void    vg_ctrl_response(VuGpu *g, | 
|  | struct virtio_gpu_ctrl_command *cmd, | 
|  | struct virtio_gpu_ctrl_hdr *resp, | 
|  | size_t resp_len); | 
|  |  | 
|  | void    vg_ctrl_response_nodata(VuGpu *g, | 
|  | struct virtio_gpu_ctrl_command *cmd, | 
|  | enum virtio_gpu_ctrl_type type); | 
|  |  | 
|  | int     vg_create_mapping_iov(VuGpu *g, | 
|  | struct virtio_gpu_resource_attach_backing *ab, | 
|  | struct virtio_gpu_ctrl_command *cmd, | 
|  | struct iovec **iov); | 
|  | void    vg_cleanup_mapping_iov(VuGpu *g, struct iovec *iov, uint32_t count); | 
|  | void    vg_get_display_info(VuGpu *vg, struct virtio_gpu_ctrl_command *cmd); | 
|  | void    vg_get_edid(VuGpu *vg, struct virtio_gpu_ctrl_command *cmd); | 
|  |  | 
|  | void    vg_wait_ok(VuGpu *g); | 
|  |  | 
|  | void    vg_send_msg(VuGpu *g, const VhostUserGpuMsg *msg, int fd); | 
|  |  | 
|  | bool    vg_recv_msg(VuGpu *g, uint32_t expect_req, uint32_t expect_size, | 
|  | gpointer payload); | 
|  |  | 
|  |  | 
|  | #endif |