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