blob: 2a2343f20fbb0185a0893b0ef646e3d8b64a869e [file] [log] [blame]
// Copyright 2018 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//! This module defines the protocol between `virtio-wayland` and `virtio-gpu` for sharing resources
//! that are backed by file descriptors.
use std::fmt;
use std::fs::File;
use msg_on_socket_derive::MsgOnSocket;
use msg_socket::{MsgError, MsgReceiver, MsgSender, MsgSocket};
#[derive(MsgOnSocket)]
pub enum ResourceRequest {
GetResource { id: u32 },
}
#[derive(MsgOnSocket, Clone)]
pub struct PlaneInfo {
pub offset: u32,
pub stride: u32,
}
const RESOURE_PLANE_NUM: usize = 4;
#[derive(MsgOnSocket)]
pub struct ResourceInfo {
pub file: File,
pub planes: [PlaneInfo; RESOURE_PLANE_NUM],
}
#[derive(MsgOnSocket)]
pub enum ResourceResponse {
Resource(ResourceInfo),
Invalid,
}
pub type ResourceRequestSocket = MsgSocket<ResourceRequest, ResourceResponse>;
pub type ResourceResponseSocket = MsgSocket<ResourceResponse, ResourceRequest>;
pub fn pair() -> std::io::Result<(ResourceRequestSocket, ResourceResponseSocket)> {
msg_socket::pair()
}
#[derive(Debug)]
pub enum ResourceBridgeError {
InvalidResource(u32),
SendFailure(u32, MsgError),
RecieveFailure(u32, MsgError),
}
impl fmt::Display for ResourceBridgeError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
ResourceBridgeError::InvalidResource(id) => {
write!(f, "attempt to send non-existent gpu resource for id {}", id)
}
ResourceBridgeError::SendFailure(id, e) => write!(
f,
"failed to send a resource bridge request for id {}: {}",
id, e
),
ResourceBridgeError::RecieveFailure(id, e) => write!(
f,
"error receiving resource bridge response for id {}: {}",
id, e
),
}
}
}
impl std::error::Error for ResourceBridgeError {}
pub fn get_resource_info(
sock: &ResourceRequestSocket,
id: u32,
) -> std::result::Result<ResourceInfo, ResourceBridgeError> {
if let Err(e) = sock.send(&ResourceRequest::GetResource { id }) {
return Err(ResourceBridgeError::SendFailure(id, e));
}
match sock.recv() {
Ok(ResourceResponse::Resource(info)) => Ok(info),
Ok(ResourceResponse::Invalid) => Err(ResourceBridgeError::InvalidResource(id)),
Err(e) => Err(ResourceBridgeError::RecieveFailure(id, e)),
}
}