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