| /* | 
 |  * 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 |