1*bb4ee6a4SAndroid Build Coastguard Worker // Copyright 2020 The ChromiumOS Authors 2*bb4ee6a4SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be 3*bb4ee6a4SAndroid Build Coastguard Worker // found in the LICENSE file. 4*bb4ee6a4SAndroid Build Coastguard Worker 5*bb4ee6a4SAndroid Build Coastguard Worker //! Definition of the trait `Device` that each backend video device must implement. 6*bb4ee6a4SAndroid Build Coastguard Worker 7*bb4ee6a4SAndroid Build Coastguard Worker use base::EventToken; 8*bb4ee6a4SAndroid Build Coastguard Worker use base::WaitContext; 9*bb4ee6a4SAndroid Build Coastguard Worker 10*bb4ee6a4SAndroid Build Coastguard Worker use crate::virtio::video::async_cmd_desc_map::AsyncCmdDescMap; 11*bb4ee6a4SAndroid Build Coastguard Worker use crate::virtio::video::command::QueueType; 12*bb4ee6a4SAndroid Build Coastguard Worker use crate::virtio::video::command::VideoCmd; 13*bb4ee6a4SAndroid Build Coastguard Worker use crate::virtio::video::error::*; 14*bb4ee6a4SAndroid Build Coastguard Worker use crate::virtio::video::event::VideoEvt; 15*bb4ee6a4SAndroid Build Coastguard Worker use crate::virtio::video::response; 16*bb4ee6a4SAndroid Build Coastguard Worker 17*bb4ee6a4SAndroid Build Coastguard Worker #[derive(EventToken, Debug)] 18*bb4ee6a4SAndroid Build Coastguard Worker pub enum Token { 19*bb4ee6a4SAndroid Build Coastguard Worker CmdQueue, 20*bb4ee6a4SAndroid Build Coastguard Worker EventQueue, 21*bb4ee6a4SAndroid Build Coastguard Worker Event { 22*bb4ee6a4SAndroid Build Coastguard Worker id: u32, 23*bb4ee6a4SAndroid Build Coastguard Worker }, 24*bb4ee6a4SAndroid Build Coastguard Worker /// Signals that processing of a given buffer has completed. Used for cases where the guest CPU 25*bb4ee6a4SAndroid Build Coastguard Worker /// may access the buffer, in which case it cannot be handed over to the guest until operations 26*bb4ee6a4SAndroid Build Coastguard Worker /// on it have completed. 27*bb4ee6a4SAndroid Build Coastguard Worker BufferBarrier { 28*bb4ee6a4SAndroid Build Coastguard Worker id: u32, 29*bb4ee6a4SAndroid Build Coastguard Worker }, 30*bb4ee6a4SAndroid Build Coastguard Worker Kill, 31*bb4ee6a4SAndroid Build Coastguard Worker InterruptResample, 32*bb4ee6a4SAndroid Build Coastguard Worker } 33*bb4ee6a4SAndroid Build Coastguard Worker 34*bb4ee6a4SAndroid Build Coastguard Worker /// A tag for commands being processed asynchronously in the back-end device. 35*bb4ee6a4SAndroid Build Coastguard Worker /// 36*bb4ee6a4SAndroid Build Coastguard Worker /// TODO(b/149720783): Remove this enum by using async primitives. 37*bb4ee6a4SAndroid Build Coastguard Worker #[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Debug)] 38*bb4ee6a4SAndroid Build Coastguard Worker pub enum AsyncCmdTag { 39*bb4ee6a4SAndroid Build Coastguard Worker Queue { 40*bb4ee6a4SAndroid Build Coastguard Worker stream_id: u32, 41*bb4ee6a4SAndroid Build Coastguard Worker queue_type: QueueType, 42*bb4ee6a4SAndroid Build Coastguard Worker resource_id: u32, 43*bb4ee6a4SAndroid Build Coastguard Worker }, 44*bb4ee6a4SAndroid Build Coastguard Worker Drain { 45*bb4ee6a4SAndroid Build Coastguard Worker stream_id: u32, 46*bb4ee6a4SAndroid Build Coastguard Worker }, 47*bb4ee6a4SAndroid Build Coastguard Worker Clear { 48*bb4ee6a4SAndroid Build Coastguard Worker stream_id: u32, 49*bb4ee6a4SAndroid Build Coastguard Worker queue_type: QueueType, 50*bb4ee6a4SAndroid Build Coastguard Worker }, 51*bb4ee6a4SAndroid Build Coastguard Worker // Used exclusively by the encoder. 52*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "video-encoder")] 53*bb4ee6a4SAndroid Build Coastguard Worker GetParams { 54*bb4ee6a4SAndroid Build Coastguard Worker stream_id: u32, 55*bb4ee6a4SAndroid Build Coastguard Worker queue_type: QueueType, 56*bb4ee6a4SAndroid Build Coastguard Worker }, 57*bb4ee6a4SAndroid Build Coastguard Worker } 58*bb4ee6a4SAndroid Build Coastguard Worker 59*bb4ee6a4SAndroid Build Coastguard Worker /// A return value when a command from the guest is processed. 60*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Debug)] 61*bb4ee6a4SAndroid Build Coastguard Worker pub enum VideoCmdResponseType { 62*bb4ee6a4SAndroid Build Coastguard Worker /// The response for a synchronous command. This can be returned to the guest immediately via 63*bb4ee6a4SAndroid Build Coastguard Worker /// command virtqueue. 64*bb4ee6a4SAndroid Build Coastguard Worker Sync(response::CmdResponse), 65*bb4ee6a4SAndroid Build Coastguard Worker /// The tag for an asynchronous command that the back-end device will complete. 66*bb4ee6a4SAndroid Build Coastguard Worker /// Once the command is completed, its result will be sent with the same tag. 67*bb4ee6a4SAndroid Build Coastguard Worker /// This can be seen as a poor man's future pattern. 68*bb4ee6a4SAndroid Build Coastguard Worker Async(AsyncCmdTag), 69*bb4ee6a4SAndroid Build Coastguard Worker } 70*bb4ee6a4SAndroid Build Coastguard Worker 71*bb4ee6a4SAndroid Build Coastguard Worker /// A response for an asynchronous command that was enqueued through `process_cmd` before. 72*bb4ee6a4SAndroid Build Coastguard Worker /// The `tag` must be same as the one returned when the command was enqueued. 73*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Debug)] 74*bb4ee6a4SAndroid Build Coastguard Worker pub struct AsyncCmdResponse { 75*bb4ee6a4SAndroid Build Coastguard Worker pub tag: AsyncCmdTag, 76*bb4ee6a4SAndroid Build Coastguard Worker pub response: VideoResult<response::CmdResponse>, 77*bb4ee6a4SAndroid Build Coastguard Worker } 78*bb4ee6a4SAndroid Build Coastguard Worker 79*bb4ee6a4SAndroid Build Coastguard Worker impl AsyncCmdResponse { from_response(tag: AsyncCmdTag, response: response::CmdResponse) -> Self80*bb4ee6a4SAndroid Build Coastguard Worker pub fn from_response(tag: AsyncCmdTag, response: response::CmdResponse) -> Self { 81*bb4ee6a4SAndroid Build Coastguard Worker Self { 82*bb4ee6a4SAndroid Build Coastguard Worker tag, 83*bb4ee6a4SAndroid Build Coastguard Worker response: Ok(response), 84*bb4ee6a4SAndroid Build Coastguard Worker } 85*bb4ee6a4SAndroid Build Coastguard Worker } 86*bb4ee6a4SAndroid Build Coastguard Worker from_error(tag: AsyncCmdTag, error: VideoError) -> Self87*bb4ee6a4SAndroid Build Coastguard Worker pub fn from_error(tag: AsyncCmdTag, error: VideoError) -> Self { 88*bb4ee6a4SAndroid Build Coastguard Worker Self { 89*bb4ee6a4SAndroid Build Coastguard Worker tag, 90*bb4ee6a4SAndroid Build Coastguard Worker response: Err(error), 91*bb4ee6a4SAndroid Build Coastguard Worker } 92*bb4ee6a4SAndroid Build Coastguard Worker } 93*bb4ee6a4SAndroid Build Coastguard Worker } 94*bb4ee6a4SAndroid Build Coastguard Worker 95*bb4ee6a4SAndroid Build Coastguard Worker /// A return value when processing a event the back-end device sent. 96*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Debug)] 97*bb4ee6a4SAndroid Build Coastguard Worker pub enum VideoEvtResponseType { 98*bb4ee6a4SAndroid Build Coastguard Worker /// The responses for an asynchronous command. 99*bb4ee6a4SAndroid Build Coastguard Worker AsyncCmd(AsyncCmdResponse), 100*bb4ee6a4SAndroid Build Coastguard Worker /// The event that happened in the back-end device. 101*bb4ee6a4SAndroid Build Coastguard Worker Event(VideoEvt), 102*bb4ee6a4SAndroid Build Coastguard Worker } 103*bb4ee6a4SAndroid Build Coastguard Worker 104*bb4ee6a4SAndroid Build Coastguard Worker pub trait Device { 105*bb4ee6a4SAndroid Build Coastguard Worker /// Processes a virtio-video command. 106*bb4ee6a4SAndroid Build Coastguard Worker /// If the command expects a synchronous response, it returns a response as 107*bb4ee6a4SAndroid Build Coastguard Worker /// `VideoCmdResponseType::Sync`. Otherwise, it returns a name of the descriptor chain that 108*bb4ee6a4SAndroid Build Coastguard Worker /// will be used when a response is prepared. Implementations of this method is passed a 109*bb4ee6a4SAndroid Build Coastguard Worker /// WaitContext object which can be used to add or remove descriptors to wait on. It is 110*bb4ee6a4SAndroid Build Coastguard Worker /// expected that only Token::Event items would be added. When a Token::Event event arrives, 111*bb4ee6a4SAndroid Build Coastguard Worker /// process_event() will be invoked. 112*bb4ee6a4SAndroid Build Coastguard Worker /// 113*bb4ee6a4SAndroid Build Coastguard Worker /// TODO(b/149720783): Make this an async function. process_cmd( &mut self, cmd: VideoCmd, wait_ctx: &WaitContext<Token>, ) -> ( VideoCmdResponseType, Option<(u32, Vec<VideoEvtResponseType>)>, )114*bb4ee6a4SAndroid Build Coastguard Worker fn process_cmd( 115*bb4ee6a4SAndroid Build Coastguard Worker &mut self, 116*bb4ee6a4SAndroid Build Coastguard Worker cmd: VideoCmd, 117*bb4ee6a4SAndroid Build Coastguard Worker wait_ctx: &WaitContext<Token>, 118*bb4ee6a4SAndroid Build Coastguard Worker ) -> ( 119*bb4ee6a4SAndroid Build Coastguard Worker VideoCmdResponseType, 120*bb4ee6a4SAndroid Build Coastguard Worker Option<(u32, Vec<VideoEvtResponseType>)>, 121*bb4ee6a4SAndroid Build Coastguard Worker ); 122*bb4ee6a4SAndroid Build Coastguard Worker 123*bb4ee6a4SAndroid Build Coastguard Worker /// Processes an available `Token::Event` event and returns a list of `VideoEvtResponseType` 124*bb4ee6a4SAndroid Build Coastguard Worker /// responses. It returns None if an invalid event comes. 125*bb4ee6a4SAndroid Build Coastguard Worker /// For responses to be sent via command queue, the return type is 126*bb4ee6a4SAndroid Build Coastguard Worker /// `VideoEvtResponseType::AsyncCmd`. For responses to be sent via event queue, the return 127*bb4ee6a4SAndroid Build Coastguard Worker /// type is `VideoEvtResponseType::Event`. 128*bb4ee6a4SAndroid Build Coastguard Worker /// 129*bb4ee6a4SAndroid Build Coastguard Worker /// TODO(b/149720783): Make this an async function. process_event( &mut self, desc_map: &mut AsyncCmdDescMap, stream_id: u32, wait_ctx: &WaitContext<Token>, ) -> Option<Vec<VideoEvtResponseType>>130*bb4ee6a4SAndroid Build Coastguard Worker fn process_event( 131*bb4ee6a4SAndroid Build Coastguard Worker &mut self, 132*bb4ee6a4SAndroid Build Coastguard Worker desc_map: &mut AsyncCmdDescMap, 133*bb4ee6a4SAndroid Build Coastguard Worker stream_id: u32, 134*bb4ee6a4SAndroid Build Coastguard Worker wait_ctx: &WaitContext<Token>, 135*bb4ee6a4SAndroid Build Coastguard Worker ) -> Option<Vec<VideoEvtResponseType>>; 136*bb4ee6a4SAndroid Build Coastguard Worker 137*bb4ee6a4SAndroid Build Coastguard Worker /// Processes a `Token::BufferBarrier` event and returns a list of `VideoEvtResponseType` 138*bb4ee6a4SAndroid Build Coastguard Worker /// responses. Only needs to be implemented for devices that adds `Token::BufferBarrier` tokens 139*bb4ee6a4SAndroid Build Coastguard Worker /// to the wait context. process_buffer_barrier( &mut self, _stream_id: u32, _wait_ctx: &WaitContext<Token>, ) -> Option<Vec<VideoEvtResponseType>>140*bb4ee6a4SAndroid Build Coastguard Worker fn process_buffer_barrier( 141*bb4ee6a4SAndroid Build Coastguard Worker &mut self, 142*bb4ee6a4SAndroid Build Coastguard Worker _stream_id: u32, 143*bb4ee6a4SAndroid Build Coastguard Worker _wait_ctx: &WaitContext<Token>, 144*bb4ee6a4SAndroid Build Coastguard Worker ) -> Option<Vec<VideoEvtResponseType>> { 145*bb4ee6a4SAndroid Build Coastguard Worker None 146*bb4ee6a4SAndroid Build Coastguard Worker } 147*bb4ee6a4SAndroid Build Coastguard Worker } 148