2 * Virtio vhost-user GPU Device
4 * Copyright Red Hat, Inc. 2013-2018
7 * Dave Airlie <airlied@redhat.com>
8 * Gerd Hoffmann <kraxel@redhat.com>
9 * Marc-André Lureau <marcandre.lureau@redhat.com>
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.
19 #include "libvhost-user-glib.h"
20 #include "standard-headers/linux/virtio_gpu.h"
22 #include "qemu/queue.h"
24 #include "qemu/bswap.h"
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
;
43 typedef struct VhostUserGpuDisplayInfoReply
{
44 struct virtio_gpu_resp_display_info info
;
45 } VhostUserGpuDisplayInfoReply
;
47 typedef struct VhostUserGpuCursorPos
{
51 } QEMU_PACKED VhostUserGpuCursorPos
;
53 typedef struct VhostUserGpuCursorUpdate
{
54 VhostUserGpuCursorPos pos
;
57 uint32_t data
[64 * 64];
58 } QEMU_PACKED VhostUserGpuCursorUpdate
;
60 typedef struct VhostUserGpuScanout
{
64 } QEMU_PACKED VhostUserGpuScanout
;
66 typedef struct VhostUserGpuUpdate
{
73 } QEMU_PACKED VhostUserGpuUpdate
;
75 typedef struct VhostUserGpuDMABUFScanout
{
86 } QEMU_PACKED VhostUserGpuDMABUFScanout
;
88 typedef struct VhostUserGpuDMABUFScanout2
{
89 struct VhostUserGpuDMABUFScanout dmabuf_scanout
;
91 } QEMU_PACKED VhostUserGpuDMABUFScanout2
;
93 typedef struct VhostUserGpuEdidRequest
{
95 } QEMU_PACKED VhostUserGpuEdidRequest
;
97 typedef struct VhostUserGpuMsg
{
98 uint32_t request
; /* VhostUserGpuRequest */
100 uint32_t size
; /* the following payload size */
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
;
113 } QEMU_PACKED VhostUserGpuMsg
;
115 static VhostUserGpuMsg m
__attribute__ ((unused
));
116 #define VHOST_USER_GPU_HDR_SIZE \
117 (sizeof(m.request) + sizeof(m.flags) + sizeof(m.size))
119 #define VHOST_USER_GPU_MSG_FLAG_REPLY 0x4
121 #define VHOST_USER_GPU_PROTOCOL_F_EDID 0
122 #define VHOST_USER_GPU_PROTOCOL_F_DMABUF2 1
124 struct virtio_gpu_scanout
{
125 uint32_t width
, height
;
128 uint32_t resource_id
;
131 typedef struct VuGpu
{
133 struct virtio_gpu_config virtio_config
;
134 struct vugbm_device gdev
;
137 GSource
*renderer_source
;
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
;
153 VG_CMD_STATE_PENDING
,
154 VG_CMD_STATE_FINISHED
,
157 struct virtio_gpu_ctrl_command
{
160 struct virtio_gpu_ctrl_hdr cmd_hdr
;
163 QTAILQ_ENTRY(virtio_gpu_ctrl_command
) next
;
166 #define VUGPU_FILL_CMD(out) do { \
168 s = iov_to_buf(cmd->elem.out_sg, cmd->elem.out_num, 0, \
169 &out, sizeof(out)); \
170 if (s != sizeof(out)) { \
171 g_critical("%s: command size incorrect %zu vs %zu", \
172 __func__, s, sizeof(out)); \
178 void vg_ctrl_response(VuGpu
*g
,
179 struct virtio_gpu_ctrl_command
*cmd
,
180 struct virtio_gpu_ctrl_hdr
*resp
,
183 void vg_ctrl_response_nodata(VuGpu
*g
,
184 struct virtio_gpu_ctrl_command
*cmd
,
185 enum virtio_gpu_ctrl_type type
);
187 int vg_create_mapping_iov(VuGpu
*g
,
188 struct virtio_gpu_resource_attach_backing
*ab
,
189 struct virtio_gpu_ctrl_command
*cmd
,
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
);
195 void vg_wait_ok(VuGpu
*g
);
197 void vg_send_msg(VuGpu
*g
, const VhostUserGpuMsg
*msg
, int fd
);
199 bool vg_recv_msg(VuGpu
*g
, uint32_t expect_req
, uint32_t expect_size
,