xref: /aosp_15_r20/external/crosvm/devices/src/virtio/video/device.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
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