xref: /aosp_15_r20/external/crosvm/devices/src/virtio/resource_bridge.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
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 
8 use std::fmt;
9 
10 use base::with_as_descriptor;
11 use base::SafeDescriptor;
12 use base::Tube;
13 use base::TubeError;
14 use remain::sorted;
15 use serde::Deserialize;
16 use serde::Serialize;
17 use thiserror::Error;
18 
19 #[derive(Debug, Serialize, Deserialize)]
20 pub enum ResourceRequest {
21     GetBuffer { id: u32 },
22     GetFence { seqno: u64 },
23 }
24 
25 #[derive(Serialize, Deserialize, Clone, Copy, Default)]
26 pub struct PlaneInfo {
27     pub offset: u32,
28     pub stride: u32,
29 }
30 
31 #[derive(Serialize, Deserialize)]
32 pub 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 
41 pub const RESOURE_PLANE_NUM: usize = 4;
42 #[derive(Serialize, Deserialize)]
43 pub enum ResourceInfo {
44     Buffer(BufferInfo),
45     Fence {
46         #[serde(with = "with_as_descriptor")]
47         handle: SafeDescriptor,
48     },
49 }
50 
51 #[derive(Serialize, Deserialize)]
52 pub enum ResourceResponse {
53     Resource(ResourceInfo),
54     Invalid,
55 }
56 
57 #[sorted]
58 #[derive(Error, Debug)]
59 pub 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 
68 impl fmt::Display for ResourceRequest {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result69     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 
get_resource_info( tube: &Tube, request: ResourceRequest, ) -> std::result::Result<ResourceInfo, ResourceBridgeError>77 pub 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 }
91