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