1 // Copyright 2018 The Chromium OS Authors. All rights reserved.
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 use std::fs::File;
10 
11 use remain::sorted;
12 use serde::{Deserialize, Serialize};
13 use thiserror::Error;
14 
15 use base::{with_as_descriptor, Tube, TubeError};
16 
17 #[derive(Debug, Serialize, Deserialize)]
18 pub enum ResourceRequest {
19     GetBuffer { id: u32 },
20     GetFence { seqno: u64 },
21 }
22 
23 #[derive(Serialize, Deserialize, Clone, Copy, Default)]
24 pub struct PlaneInfo {
25     pub offset: u32,
26     pub stride: u32,
27 }
28 
29 #[derive(Serialize, Deserialize)]
30 pub struct BufferInfo {
31     #[serde(with = "with_as_descriptor")]
32     pub file: File,
33     pub planes: [PlaneInfo; RESOURE_PLANE_NUM],
34     pub modifier: u64,
35 }
36 
37 pub const RESOURE_PLANE_NUM: usize = 4;
38 #[derive(Serialize, Deserialize)]
39 pub enum ResourceInfo {
40     Buffer(BufferInfo),
41     Fence {
42         #[serde(with = "with_as_descriptor")]
43         file: File,
44     },
45 }
46 
47 #[derive(Serialize, Deserialize)]
48 pub enum ResourceResponse {
49     Resource(ResourceInfo),
50     Invalid,
51 }
52 
53 #[sorted]
54 #[derive(Error, Debug)]
55 pub enum ResourceBridgeError {
56     #[error("attempt to send non-existent gpu resource for {0}")]
57     InvalidResource(ResourceRequest),
58     #[error("error receiving resource bridge response for {0}: {1}")]
59     RecieveFailure(ResourceRequest, TubeError),
60     #[error("failed to send a resource bridge request for {0}: {1}")]
61     SendFailure(ResourceRequest, TubeError),
62 }
63 
64 impl fmt::Display for ResourceRequest {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result65     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
66         match self {
67             ResourceRequest::GetBuffer { id } => write!(f, "Buffer-{}", id),
68             ResourceRequest::GetFence { seqno } => write!(f, "Fence-{}", seqno),
69         }
70     }
71 }
72 
get_resource_info( tube: &Tube, request: ResourceRequest, ) -> std::result::Result<ResourceInfo, ResourceBridgeError>73 pub fn get_resource_info(
74     tube: &Tube,
75     request: ResourceRequest,
76 ) -> std::result::Result<ResourceInfo, ResourceBridgeError> {
77     if let Err(e) = tube.send(&request) {
78         return Err(ResourceBridgeError::SendFailure(request, e));
79     }
80 
81     match tube.recv() {
82         Ok(ResourceResponse::Resource(info)) => Ok(info),
83         Ok(ResourceResponse::Invalid) => Err(ResourceBridgeError::InvalidResource(request)),
84         Err(e) => Err(ResourceBridgeError::RecieveFailure(request, e)),
85     }
86 }
87