summary refs log blame commit diff
path: root/devices/src/virtio/resource_bridge.rs
blob: 2a2343f20fbb0185a0893b0ef646e3d8b64a869e (plain) (tree)
1
2
3
4
5
6
7
8
9






                                                                                                    
             
                  

                                      
                                                              





                            












                                               

                           
                           





                                                                               
                                                                                   

                      





























                                                                                    
                         

                                 
                                                             




                                                                     
                                                         



                                                                                       
// 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)),
    }
}