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}