=======================
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.
