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 }
38
39 pub const RESOURE_PLANE_NUM: usize = 4;
40 #[derive(Serialize, Deserialize)]
41 pub enum ResourceInfo {
42 Buffer(BufferInfo),
43 Fence {
44 #[serde(with = "with_as_descriptor")]
45 handle: SafeDescriptor,
46 },
47 }
48
49 #[derive(Serialize, Deserialize)]
50 pub enum ResourceResponse {
51 Resource(ResourceInfo),
52 Invalid,
53 }
54
55 #[sorted]
56 #[derive(Error, Debug)]
57 pub enum ResourceBridgeError {
58 #[error("attempt to send non-existent gpu resource for {0}")]
59 InvalidResource(ResourceRequest),
60 #[error("error receiving resource bridge response for {0}: {1}")]
61 RecieveFailure(ResourceRequest, TubeError),
62 #[error("failed to send a resource bridge request for {0}: {1}")]
63 SendFailure(ResourceRequest, TubeError),
64 }
65
66 impl fmt::Display for ResourceRequest {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result67 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
68 match self {
69 ResourceRequest::GetBuffer { id } => write!(f, "Buffer-{}", id),
70 ResourceRequest::GetFence { seqno } => write!(f, "Fence-{}", seqno),
71 }
72 }
73 }
74
get_resource_info( tube: &Tube, request: ResourceRequest, ) -> std::result::Result<ResourceInfo, ResourceBridgeError>75 pub fn get_resource_info(
76 tube: &Tube,
77 request: ResourceRequest,
78 ) -> std::result::Result<ResourceInfo, ResourceBridgeError> {
79 if let Err(e) = tube.send(&request) {
80 return Err(ResourceBridgeError::SendFailure(request, e));
81 }
82
83 match tube.recv() {
84 Ok(ResourceResponse::Resource(info)) => Ok(info),
85 Ok(ResourceResponse::Invalid) => Err(ResourceBridgeError::InvalidResource(request)),
86 Err(e) => Err(ResourceBridgeError::RecieveFailure(request, e)),
87 }
88 }
89