|  | ======================= | 
|  | Vhost-user-gpu Protocol | 
|  | ======================= | 
|  |  | 
|  | .. | 
|  | Licence: This work is licensed under the terms of the GNU GPL, | 
|  | version 2 or later. See the COPYING file in the top-level | 
|  | directory. | 
|  |  | 
|  | .. contents:: Table of Contents | 
|  |  | 
|  | Introduction | 
|  | ============ | 
|  |  | 
|  | The vhost-user-gpu protocol is aiming at sharing the rendering result | 
|  | of a virtio-gpu, done from a vhost-user back-end process to a vhost-user | 
|  | front-end process (such as QEMU). It bears a resemblance to a display | 
|  | server protocol, if you consider QEMU as the display server and the | 
|  | back-end as the client, but in a very limited way. Typically, it will | 
|  | work by setting a scanout/display configuration, before sending flush | 
|  | events for the display updates. It will also update the cursor shape | 
|  | and position. | 
|  |  | 
|  | The protocol is sent over a UNIX domain stream socket, since it uses | 
|  | socket ancillary data to share opened file descriptors (DMABUF fds or | 
|  | shared memory). The socket is usually obtained via | 
|  | ``VHOST_USER_GPU_SET_SOCKET``. | 
|  |  | 
|  | Requests are sent by the *back-end*, and the optional replies by the | 
|  | *front-end*. | 
|  |  | 
|  | Wire format | 
|  | =========== | 
|  |  | 
|  | Unless specified differently, numbers are in the machine native byte | 
|  | order. | 
|  |  | 
|  | A vhost-user-gpu message (request and reply) consists of 3 header | 
|  | fields and a payload. | 
|  |  | 
|  | +---------+-------+------+---------+ | 
|  | | request | flags | size | payload | | 
|  | +---------+-------+------+---------+ | 
|  |  | 
|  | Header | 
|  | ------ | 
|  |  | 
|  | :request: ``u32``, type of the request | 
|  |  | 
|  | :flags: ``u32``, 32-bit bit field: | 
|  |  | 
|  | - Bit 2 is the reply flag - needs to be set on each reply | 
|  |  | 
|  | :size: ``u32``, size of the payload | 
|  |  | 
|  | Payload types | 
|  | ------------- | 
|  |  | 
|  | Depending on the request type, **payload** can be: | 
|  |  | 
|  | VhostUserGpuCursorPos | 
|  | ^^^^^^^^^^^^^^^^^^^^^ | 
|  |  | 
|  | +------------+---+---+ | 
|  | | scanout-id | x | y | | 
|  | +------------+---+---+ | 
|  |  | 
|  | :scanout-id: ``u32``, the scanout where the cursor is located | 
|  |  | 
|  | :x/y: ``u32``, the cursor position | 
|  |  | 
|  | VhostUserGpuCursorUpdate | 
|  | ^^^^^^^^^^^^^^^^^^^^^^^^ | 
|  |  | 
|  | +-----+-------+-------+--------+ | 
|  | | pos | hot_x | hot_y | cursor | | 
|  | +-----+-------+-------+--------+ | 
|  |  | 
|  | :pos: a ``VhostUserGpuCursorPos``, the cursor location | 
|  |  | 
|  | :hot_x/hot_y: ``u32``, the cursor hot location | 
|  |  | 
|  | :cursor: ``[u32; 64 * 64]``, 64x64 RGBA cursor data (PIXMAN_a8r8g8b8 format) | 
|  |  | 
|  | VhostUserGpuScanout | 
|  | ^^^^^^^^^^^^^^^^^^^ | 
|  |  | 
|  | +------------+---+---+ | 
|  | | scanout-id | w | h | | 
|  | +------------+---+---+ | 
|  |  | 
|  | :scanout-id: ``u32``, the scanout configuration to set | 
|  |  | 
|  | :w/h: ``u32``, the scanout width/height size | 
|  |  | 
|  | VhostUserGpuUpdate | 
|  | ^^^^^^^^^^^^^^^^^^ | 
|  |  | 
|  | +------------+---+---+---+---+------+ | 
|  | | scanout-id | x | y | w | h | data | | 
|  | +------------+---+---+---+---+------+ | 
|  |  | 
|  | :scanout-id: ``u32``, the scanout content to update | 
|  |  | 
|  | :x/y/w/h: ``u32``, region of the update | 
|  |  | 
|  | :data: RGB data (PIXMAN_x8r8g8b8 format) | 
|  |  | 
|  | VhostUserGpuDMABUFScanout | 
|  | ^^^^^^^^^^^^^^^^^^^^^^^^^ | 
|  |  | 
|  | +------------+---+---+---+---+-----+-----+--------+-------+--------+ | 
|  | | scanout-id | x | y | w | h | fdw | fwh | stride | flags | fourcc | | 
|  | +------------+---+---+---+---+-----+-----+--------+-------+--------+ | 
|  |  | 
|  | :scanout-id: ``u32``, the scanout configuration to set | 
|  |  | 
|  | :x/y: ``u32``, the location of the scanout within the DMABUF | 
|  |  | 
|  | :w/h: ``u32``, the scanout width/height size | 
|  |  | 
|  | :fdw/fdh/stride/flags: ``u32``, the DMABUF width/height/stride/flags | 
|  |  | 
|  | :fourcc: ``i32``, the DMABUF fourcc | 
|  |  | 
|  |  | 
|  | VhostUserGpuEdidRequest | 
|  | ^^^^^^^^^^^^^^^^^^^^^^^ | 
|  |  | 
|  | +------------+ | 
|  | | scanout-id | | 
|  | +------------+ | 
|  |  | 
|  | :scanout-id: ``u32``, the scanout to get edid from | 
|  |  | 
|  |  | 
|  | VhostUserGpuDMABUFScanout2 | 
|  | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | 
|  |  | 
|  | +----------------+----------+ | 
|  | | dmabuf_scanout | modifier | | 
|  | +----------------+----------+ | 
|  |  | 
|  | :dmabuf_scanout: ``VhostUserGpuDMABUFScanout``, filled as described in the | 
|  | VhostUserGpuDMABUFScanout structure. | 
|  |  | 
|  | :modifier: ``u64``, the DMABUF modifiers | 
|  |  | 
|  |  | 
|  | C structure | 
|  | ----------- | 
|  |  | 
|  | In QEMU the vhost-user-gpu message is implemented with the following struct: | 
|  |  | 
|  | .. code:: c | 
|  |  | 
|  | 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; | 
|  | 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; | 
|  |  | 
|  | Protocol features | 
|  | ----------------- | 
|  |  | 
|  | .. code:: c | 
|  |  | 
|  | #define VHOST_USER_GPU_PROTOCOL_F_EDID    0 | 
|  | #define VHOST_USER_GPU_PROTOCOL_F_DMABUF2 1 | 
|  |  | 
|  | New messages and communication changes are negotiated thanks to the | 
|  | ``VHOST_USER_GPU_GET_PROTOCOL_FEATURES`` and | 
|  | ``VHOST_USER_GPU_SET_PROTOCOL_FEATURES`` requests. | 
|  |  | 
|  | Communication | 
|  | ============= | 
|  |  | 
|  | Message types | 
|  | ------------- | 
|  |  | 
|  | ``VHOST_USER_GPU_GET_PROTOCOL_FEATURES`` | 
|  | :id: 1 | 
|  | :request payload: N/A | 
|  | :reply payload: ``u64`` | 
|  |  | 
|  | Get the supported protocol features bitmask. | 
|  |  | 
|  | ``VHOST_USER_GPU_SET_PROTOCOL_FEATURES`` | 
|  | :id: 2 | 
|  | :request payload: ``u64`` | 
|  | :reply payload: N/A | 
|  |  | 
|  | Enable protocol features using a bitmask. | 
|  |  | 
|  | ``VHOST_USER_GPU_GET_DISPLAY_INFO`` | 
|  | :id: 3 | 
|  | :request payload: N/A | 
|  | :reply payload: ``struct virtio_gpu_resp_display_info`` (from virtio specification) | 
|  |  | 
|  | Get the preferred display configuration. | 
|  |  | 
|  | ``VHOST_USER_GPU_CURSOR_POS`` | 
|  | :id: 4 | 
|  | :request payload: ``VhostUserGpuCursorPos`` | 
|  | :reply payload: N/A | 
|  |  | 
|  | Set/show the cursor position. | 
|  |  | 
|  | ``VHOST_USER_GPU_CURSOR_POS_HIDE`` | 
|  | :id: 5 | 
|  | :request payload: ``VhostUserGpuCursorPos`` | 
|  | :reply payload: N/A | 
|  |  | 
|  | Set/hide the cursor. | 
|  |  | 
|  | ``VHOST_USER_GPU_CURSOR_UPDATE`` | 
|  | :id: 6 | 
|  | :request payload: ``VhostUserGpuCursorUpdate`` | 
|  | :reply payload: N/A | 
|  |  | 
|  | Update the cursor shape and location. | 
|  |  | 
|  | ``VHOST_USER_GPU_SCANOUT`` | 
|  | :id: 7 | 
|  | :request payload: ``VhostUserGpuScanout`` | 
|  | :reply payload: N/A | 
|  |  | 
|  | Set the scanout resolution. To disable a scanout, the dimensions | 
|  | width/height are set to 0. | 
|  |  | 
|  | ``VHOST_USER_GPU_UPDATE`` | 
|  | :id: 8 | 
|  | :request payload: ``VhostUserGpuUpdate`` | 
|  | :reply payload: N/A | 
|  |  | 
|  | Update the scanout content. The data payload contains the graphical bits. | 
|  | The display should be flushed and presented. | 
|  |  | 
|  | ``VHOST_USER_GPU_DMABUF_SCANOUT`` | 
|  | :id: 9 | 
|  | :request payload: ``VhostUserGpuDMABUFScanout`` | 
|  | :reply payload: N/A | 
|  |  | 
|  | Set the scanout resolution/configuration, and share a DMABUF file | 
|  | descriptor for the scanout content, which is passed as ancillary | 
|  | data. To disable a scanout, the dimensions width/height are set | 
|  | to 0, there is no file descriptor passed. | 
|  |  | 
|  | ``VHOST_USER_GPU_DMABUF_UPDATE`` | 
|  | :id: 10 | 
|  | :request payload: ``VhostUserGpuUpdate`` | 
|  | :reply payload: empty payload | 
|  |  | 
|  | The display should be flushed and presented according to updated | 
|  | region from ``VhostUserGpuUpdate``. | 
|  |  | 
|  | Note: there is no data payload, since the scanout is shared thanks | 
|  | to DMABUF, that must have been set previously with | 
|  | ``VHOST_USER_GPU_DMABUF_SCANOUT``. | 
|  |  | 
|  | ``VHOST_USER_GPU_GET_EDID`` | 
|  | :id: 11 | 
|  | :request payload: ``struct VhostUserGpuEdidRequest`` | 
|  | :reply payload: ``struct virtio_gpu_resp_edid`` (from virtio specification) | 
|  |  | 
|  | Retrieve the EDID data for a given scanout. | 
|  | This message requires the ``VHOST_USER_GPU_PROTOCOL_F_EDID`` protocol | 
|  | feature to be supported. | 
|  |  | 
|  | ``VHOST_USER_GPU_DMABUF_SCANOUT2`` | 
|  | :id: 12 | 
|  | :request payload: ``VhostUserGpuDMABUFScanout2`` | 
|  | :reply payload: N/A | 
|  |  | 
|  | Same as VHOST_USER_GPU_DMABUF_SCANOUT, but also sends the dmabuf modifiers | 
|  | appended to the message, which were not provided in the other message. | 
|  | This message requires the ``VHOST_USER_GPU_PROTOCOL_F_DMABUF2`` protocol | 
|  | feature to be supported. |