blob: fee392cf9d4dc1ce9c62db5d9c3adf3e4f3085ca [file] [log] [blame]
// Copyright 2023 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SRC_GRAPHICS_LIB_VIRTIO_VIRTIO_ABI_H_
#define SRC_GRAPHICS_LIB_VIRTIO_VIRTIO_ABI_H_
// The constants and structures in this file are from the OASIS Virtual I/O
// Device (VIRTIO) specification, which can be downloaded from
// https://docs.oasis-open.org/virtio/virtio/
//
// virtio12 is Version 1.2, Committee Specification 01, dated 01 July 2022.
// We map the specification types "le32" and "le64" (little-endian 32/64-bit
// integers) to uint32_t and uint64_t, because Fuchsia only supports
// little-endian systems.
//
// We use static_asserts in the associated test file to ensure that our C++
// structure definitions are compatible with the C ABI specified by the spec.
// Concretely, we check that our structures have the same size (which implies
// the same packing) and a compatible alignment (same or larger) as the C
// structures defined by the specification.
//
// The specification uses "request" and "command" interchangeably. This header
// standardizes on "command". "request" must only be used when quoting the
// specification.
#include <cstdint>
namespace virtio_abi {
enum class CapsetId : uint32_t {
kCapsetVirGl = 1,
kCapsetVirGl2 = 2,
kCapsetGfxstream = 3,
kCapsetVenus = 4,
kCapsetCrossDomain = 5,
};
// GPU device configuration.
//
// struct virtio_gpu_config in virtio12 5.7.4 "Device configuration layout"
struct GpuDeviceConfig {
using Events = uint32_t;
// VIRTIO_GPU_EVENT_DISPLAY
static constexpr Events kDisplayConfigChanged = 1 << 0;
// The driver must not write to this field.
Events pending_events;
// Setting bits to one here clears the corresponding bits in `pending_events`.
//
// This works similarly to W/C (Write-Clear) registers in hardware.
Events clear_events;
// Maximum number of supported scanouts. Values must be in the range [1, 16].
uint32_t scanout_limit;
// Maximum number of supported capability sets. May be zero.
uint32_t capability_set_limit;
};
// Type discriminant for driver commands and device responses.
//
// enum virtio_gpu_ctrl_type in virtio12 5.7.6.7 "Device Operation: Request
// header"
enum class ControlType : uint32_t {
// Command encoded by `GetDisplayInfoCommand`.
//
// VIRTIO_GPU_CMD_GET_DISPLAY_INFO
kGetDisplayInfoCommand = 0x0100,
// Command encoded by `Create2DResourceCommand`.
//
// VIRTIO_GPU_CMD_RESOURCE_CREATE_2D
kCreate2DResourceCommand = 0x0101,
// VIRTIO_GPU_CMD_RESOURCE_UNREF
kDestroyResourceCommand = 0x0102,
// Command encoded by `SetScanoutCommand`.
//
// VIRTIO_GPU_CMD_SET_SCANOUT
kSetScanoutCommand = 0x0103,
// Command encoded by `FlushResourceCommand`.
//
// VIRTIO_GPU_CMD_RESOURCE_FLUSH
kFlushResourceCommand = 0x0104,
// Command encoded by `Transfer2DResourceToHostCommand`.
//
// VIRTIO_GPU_CMD_TRANSFER_TO_HOST_2D
kTransfer2DResourceToHostCommand = 0x0105,
// Command encoded by `AttachResourceBackingCommand`.
//
// VIRTIO_GPU_CMD_RESOURCE_ATTACH_BACKING
kAttachResourceBackingCommand = 0x0106,
// VIRTIO_GPU_CMD_RESOURCE_DETACH_BACKING
kDetachResourceBackingCommand = 0x0107,
// VIRTIO_GPU_CMD_GET_CAPSET_INFO
kGetCapabilitySetInfoCommand = 0x0108,
// VIRTIO_GPU_CMD_GET_CAPSET
kGetCapabilitySetCommand = 0x0109,
// VIRTIO_GPU_CMD_GET_EDID
kGetExtendedDisplayIdCommand = 0x010a,
// VIRTIO_GPU_CMD_RESOURCE_ASSIGN_UUID
kAssignResourceUuidCommand = 0x010b,
// VIRTIO_GPU_CMD_CREATE_BLOB
kCreateBlobCommand = 0x010c,
// VIRTIO_GPU_CMD_SET_SCANOUT_BLOB
kSetScanoutBlobCommand = 0x010d,
// Response encoded by `EmptyResponse`.
//
// VIRTIO_GPU_RESP_OK_NODATA
kEmptyResponse = 0x1100,
// Response encoded by `DisplayInfoResponse`.
//
// VIRTIO_GPU_RESP_OK_DISPLAY_INFO
kDisplayInfoResponse = 0x1101,
// VIRTIO_GPU_RESP_OK_CAPSET_INFO
kCapabilitySetInfoResponse = 0x1102,
// VIRTIO_GPU_RESP_OK_CAPSET
kCapabilitySetResponse = 0x1103,
// VIRTIO_GPU_RESP_OK_EDID
kExtendedDisplayIdResponse = 0x1104,
// VIRTIO_GPU_RESP_OK_RESOURCE_UUID
kResourceUuidResponse = 0x1105,
// VIRTIO_GPU_RESP_OK_MAP_INFO
kMapInfoResponse = 0x1106,
// VIRTIO_GPU_RESP_ERR_UNSPEC
kUnspecifiedError = 0x1200,
// VIRTIO_GPU_RESP_ERR_OUT_OF_MEMORY
kOutOfMemoryError = 0x1201,
// VIRTIO_GPU_RESP_ERR_INVALID_SCANOUT_ID
kInvalidScanoutIdError = 0x1202,
// VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID
kInvalidResourceIdError = 0x1203,
// VIRTIO_GPU_RESP_ERR_INVALID_CONTEXT_ID
kInvalidContextIdError = 0x1204,
// VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER
kInvalidParameterError = 0x1205,
// Command encoded by `UpdateCursorCommand`.
//
// VIRTIO_GPU_CMD_UPDATE_CURSOR
kUpdateCursorCommand = 0x0300,
// Command encoding reuses the `UpdateCursorCommand` structure.
//
// VIRTIO_GPU_CMD_MOVE_CURSOR
kMoveCursorCommand = 0x0301,
};
// Descriptor for logging and debugging.
const char* ControlTypeToString(ControlType type);
// struct virtio_gpu_ctrl_hdr in virtio12 5.7.6.7 "Device Operation: Request
// header"
struct ControlHeader {
using Flags = uint32_t;
// See `fence_id` and `ring_index` for details.
//
// VIRTIO_GPU_FLAG_FENCE
static constexpr Flags kFence = 1 << 0;
// See `fence_id` and `ring_index` for details.
//
// VIRTIO_GPU_FLAG_INFO_RING_IDX
static constexpr Flags kRingIndex = 1 << 1;
ControlType type;
Flags flags = 0;
// Used for synchronization between the driver and the device.
//
// Only valid if the `kFence` bit is set in the `flags` field.
//
// The device must complete a command with the `kFence` flag set before
// sending a response. The response must also have the `kFence` flag set, and
// the same `fence_id`.
uint64_t fence_id = 0;
// Rendering context ID. Only used in 3D mode.
uint32_t context_id = 0;
// Points to a context-specific timeline for fences.
//
// Only valid if the `kRingIndex` and `kFence` bits are set in the `flags`
// field. Values must be in the range [0, 63].
uint8_t ring_index = 0;
};
// Encodes all driver-to-device commands that have no data besides the header.
struct EmptyCommand {
ControlHeader header;
};
// Encodes all device-to-driver responses that have no data besides the header.
struct EmptyResponse {
ControlHeader header;
};
// Populates a `DisplayInfoResponse` with the current output configuration.
using GetDisplayInfoCommand = EmptyCommand;
// struct virtio_gpu_rect in virtio12 5.7.6.8 "Device Operation: controlq",
// under the VIRTIO_GPU_CMD_GET_DISPLAY_INFO command description
struct ScanoutGeometry {
// Placement relative to other displays.
//
// 0 is the left, axis points to the right.
uint32_t placement_x;
// Position relative to other displays.
//
// 0 is the top, axis points down.
uint32_t placement_y;
// The display's horizontal resolution, in pixels.
uint32_t width;
// The display's vertical resolution, in pixels.
uint32_t height;
};
// struct virtio_gpu_display_one in virtio12 5.7.6.8 "Device Operation:
// controlq", under the VIRTIO_GPU_CMD_GET_DISPLAY_INFO command description
struct ScanoutInfo {
ScanoutGeometry geometry;
// True as long as the display is "connected" (enabled by the user).
//
// This behaves similarly to the voltage level of the HPD (Hot-Plug Detect)
// pin in connectors such as DisplayPort and HDMI. This is different from the
// HPD interrupt generated by display hardware, which is triggered by changes
// to the HPD pin voltage level.
uint32_t enabled;
// No flags are currently documented.
uint32_t flags;
};
struct CursorPos {
uint32_t scanout_id;
uint32_t x;
uint32_t y;
uint32_t padding;
};
// VIRTIO_GPU_MAX_SCANOUTS in virtio12 5.7.6.8 "Device Operation: controlq",
// under the VIRTIO_GPU_CMD_GET_DISPLAY_INFO command description
constexpr int kMaxScanouts = 16;
// Response to a VIRTIO_GPU_CMD_GET_DISPLAY_INFO command.
//
// struct virtio_gpu_resp_display_info in virtio12 5.7.6.8 "Device Operation:
// controlq", under the VIRTIO_GPU_CMD_GET_DISPLAY_INFO command description
struct DisplayInfoResponse {
// `type` must be `kDisplayInfoResponse`.
ControlHeader header;
ScanoutInfo scanouts[kMaxScanouts];
};
// enum virtio_gpu_formats in virtio12 5.7.6.8 "Device Operation:
// controlq", under the VIRTIO_GPU_CMD_RESOURCE_CREATE_2D command description
enum class ResourceFormat : uint32_t {
// Equivalent to [`fuchsia.images2/PixelFormat.BGRA32`]
//
// VIRTIO_GPU_FORMAT_B8G8R8A8_UNORM
kBgra32 = 1,
// VIRTIO_GPU_FORMAT_B8G8R8X8_UNORM
kBgrx32 = 2,
// VIRTIO_GPU_FORMAT_A8R8G8B8_UNORM
kArgb32 = 3,
// VIRTIO_GPU_FORMAT_X8R8G8B8_UNORM
kXrgb32 = 4,
// Equivalent to [`fuchsia.images2/PixelFormat.R8G8B8A8`].
//
// VIRTIO_GPU_FORMAT_R8G8B8A8_UNORM
kR8g8b8a8 = 67,
// VIRTIO_GPU_FORMAT_X8B8G8R8_UNORM
kXbgr32 = 68,
// VIRTIO_GPU_FORMAT_A8B8G8R8_UNORM
kAbgr32 = 121,
// VIRTIO_GPU_FORMAT_A8B8G8R8_UNORM
kRgbx32 = 134,
};
// Resource ID that has a special meaning in at least one operation.
//
// virtio12 5.7.6.8 "Device Operation: controlq", the
// VIRTIO_GPU_CMD_SET_SCANOUT command description states that using a resource
// ID with this value disables the scanout.
constexpr uint32_t kInvalidResourceId = 0;
// struct virtio_gpu_resource_create_2d in virtio12 5.7.6.8 "Device Operation:
// controlq", under the VIRTIO_GPU_CMD_RESOURCE_CREATE_2D command description
struct Create2DResourceCommand {
// `type` must be `kCreate2DResourceCommand`.
ControlHeader header;
uint32_t resource_id;
ResourceFormat format;
uint32_t width;
uint32_t height;
};
// struct virtio_gpu_update_cursor in virtio12 5.7.6.10 "Device Operation:
// cursorq", under the VIRTIO_GPU_CMD_UPDATE_CURSOR and
// VIRTIO_GPU_CMD_MOVE_CURSOR command descriptions.
struct UpdateCursorCommand {
// `type` must be `kUpdateCursorCommand` or `kMoveCursorCommand`.
ControlHeader header;
CursorPos pos;
// Ignored when `type` is `kMoveCursorCommand`
uint32_t resource_id;
uint32_t hot_x;
uint32_t hot_y;
uint32_t padding;
};
// Sets scanout parameters for a single output.
//
// The response does not have any data.
//
// struct virtio_gpu_set_scanout in virtio12 5.7.6.8 "Device Operation:
// controlq", under the VIRTIO_GPU_CMD_SET_SCANOUT command description
struct SetScanoutCommand {
// `type` must be `kSetScanoutCommand`.
ControlHeader header;
ScanoutGeometry geometry;
uint32_t scanout_id;
// kInvalidResourceId means that the scanout is disabled.
uint32_t resource_id;
};
// Flushes a scanout resource to the screen.
//
// The response does not have any data.
//
// struct virtio_gpu_resource_flush in virtio12 5.7.6.8 "Device Operation:
// controlq", under the VIRTIO_GPU_CMD_RESOURCE_FLUSH command description
struct FlushResourceCommand {
// `type` must be `kFlushResourceCommand`.
ControlHeader header;
ScanoutGeometry geometry;
// Any scanouts that use this resource will be flushed.
uint32_t resource_id;
};
// Flushes a scanout resource to the screen.
//
// The response does not have any data.
//
// struct virtio_gpu_transfer_to_host_2d in virtio12 5.7.6.8 "Device Operation:
// controlq", under the VIRTIO_GPU_CMD_TRANSFER_TO_HOST_2D command description
struct Transfer2DResourceToHostCommand {
// `type` must be `kTransfer2DResourceToHostCommand`.
ControlHeader header;
// Box to be transferred to the host.
ScanoutGeometry geometry;
uint64_t destination_offset;
uint32_t resource_id;
};
// A continuous list of memory pages assigned to a 2D resource.
//
// The response does not have any data.
//
// struct virtio_gpu_mem_entry in virtio12 5.7.6.8 "Device Operation:
// controlq", under the VIRTIO_GPU_CMD_RESOURCE_ATTACH_BACKING command
// description
struct MemoryEntry {
uint64_t address;
uint32_t length;
};
// Assigns backing pages to a resource.
//
// The response does not have any data.
//
// Typesafe combination of struct virtio_gpu_resource_attach_backing and
// struct virtio_gpu_mem_entry in virtio12 5.7.6.8 "Device Operation: controlq",
// under the VIRTIO_GPU_CMD_RESOURCE_ATTACH_BACKING command
template <uint32_t N>
struct AttachResourceBackingCommand {
// `type` must be `kAttachResourceBackingCommand`.
ControlHeader header;
uint32_t resource_id;
uint32_t entry_count = N;
MemoryEntry entries[N];
};
struct GetCapsetInfoCommand {
ControlHeader header;
uint32_t capset_index;
uint32_t padding;
};
struct GetCapsetInfoResponse {
ControlHeader header;
uint32_t capset_id;
uint32_t capset_max_version;
uint32_t capset_max_size;
uint32_t padding;
};
struct GetCapsetCommand {
ControlHeader header;
uint32_t capset_id;
uint32_t capset_version;
};
struct GetCapsetResponse {
ControlHeader header;
// Variable length response.
uint8_t capset_data[];
};
} // namespace virtio_abi
#endif // SRC_GRAPHICS_LIB_VIRTIO_VIRTIO_ABI_H_