devices/virtio/
resource_bridge.rs

1// Copyright 2018 The ChromiumOS Authors
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5//! This module defines the protocol between `virtio-wayland` and `virtio-gpu` for sharing resources
6//! that are backed by file descriptors.
7
8use std::fmt;
9
10use base::with_as_descriptor;
11use base::SafeDescriptor;
12use base::Tube;
13use base::TubeError;
14use remain::sorted;
15use serde::Deserialize;
16use serde::Serialize;
17use thiserror::Error;
18
19#[derive(Debug, Serialize, Deserialize)]
20pub enum ResourceRequest {
21    GetBuffer { id: u32 },
22    GetFence { seqno: u64 },
23}
24
25#[derive(Serialize, Deserialize, Clone, Copy, Default)]
26pub struct PlaneInfo {
27    pub offset: u32,
28    pub stride: u32,
29}
30
31#[derive(Serialize, Deserialize)]
32pub struct BufferInfo {
33    #[serde(with = "with_as_descriptor")]
34    pub handle: SafeDescriptor,
35    pub planes: [PlaneInfo; RESOURE_PLANE_NUM],
36    pub modifier: u64,
37    /// Whether the buffer can be accessed by the guest CPU.
38    pub guest_cpu_mappable: bool,
39}
40
41pub const RESOURE_PLANE_NUM: usize = 4;
42#[derive(Serialize, Deserialize)]
43pub enum ResourceInfo {
44    Buffer(BufferInfo),
45    Fence {
46        #[serde(with = "with_as_descriptor")]
47        handle: SafeDescriptor,
48    },
49}
50
51#[derive(Serialize, Deserialize)]
52pub enum ResourceResponse {
53    Resource(ResourceInfo),
54    Invalid,
55}
56
57#[sorted]
58#[derive(Error, Debug)]
59pub enum ResourceBridgeError {
60    #[error("attempt to send non-existent gpu resource for {0}")]
61    InvalidResource(ResourceRequest),
62    #[error("error receiving resource bridge response for {0}: {1}")]
63    RecieveFailure(ResourceRequest, TubeError),
64    #[error("failed to send a resource bridge request for {0}: {1}")]
65    SendFailure(ResourceRequest, TubeError),
66}
67
68impl fmt::Display for ResourceRequest {
69    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
70        match self {
71            ResourceRequest::GetBuffer { id } => write!(f, "Buffer-{id}"),
72            ResourceRequest::GetFence { seqno } => write!(f, "Fence-{seqno}"),
73        }
74    }
75}
76
77pub fn get_resource_info(
78    tube: &Tube,
79    request: ResourceRequest,
80) -> std::result::Result<ResourceInfo, ResourceBridgeError> {
81    if let Err(e) = tube.send(&request) {
82        return Err(ResourceBridgeError::SendFailure(request, e));
83    }
84
85    match tube.recv() {
86        Ok(ResourceResponse::Resource(info)) => Ok(info),
87        Ok(ResourceResponse::Invalid) => Err(ResourceBridgeError::InvalidResource(request)),
88        Err(e) => Err(ResourceBridgeError::RecieveFailure(request, e)),
89    }
90}