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