1*bb4ee6a4SAndroid Build Coastguard Worker // Copyright 2018 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 mod edid;
6*bb4ee6a4SAndroid Build Coastguard Worker mod parameters;
7*bb4ee6a4SAndroid Build Coastguard Worker mod protocol;
8*bb4ee6a4SAndroid Build Coastguard Worker mod virtio_gpu;
9*bb4ee6a4SAndroid Build Coastguard Worker
10*bb4ee6a4SAndroid Build Coastguard Worker use std::cell::RefCell;
11*bb4ee6a4SAndroid Build Coastguard Worker use std::collections::BTreeMap;
12*bb4ee6a4SAndroid Build Coastguard Worker use std::io::Read;
13*bb4ee6a4SAndroid Build Coastguard Worker use std::path::PathBuf;
14*bb4ee6a4SAndroid Build Coastguard Worker use std::rc::Rc;
15*bb4ee6a4SAndroid Build Coastguard Worker use std::sync::atomic::AtomicBool;
16*bb4ee6a4SAndroid Build Coastguard Worker use std::sync::atomic::Ordering;
17*bb4ee6a4SAndroid Build Coastguard Worker use std::sync::mpsc;
18*bb4ee6a4SAndroid Build Coastguard Worker use std::sync::Arc;
19*bb4ee6a4SAndroid Build Coastguard Worker
20*bb4ee6a4SAndroid Build Coastguard Worker use anyhow::anyhow;
21*bb4ee6a4SAndroid Build Coastguard Worker use anyhow::Context;
22*bb4ee6a4SAndroid Build Coastguard Worker use base::custom_serde::deserialize_map_from_kv_vec;
23*bb4ee6a4SAndroid Build Coastguard Worker use base::custom_serde::serialize_map_as_kv_vec;
24*bb4ee6a4SAndroid Build Coastguard Worker use base::debug;
25*bb4ee6a4SAndroid Build Coastguard Worker use base::error;
26*bb4ee6a4SAndroid Build Coastguard Worker use base::info;
27*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(any(target_os = "android", target_os = "linux"))]
28*bb4ee6a4SAndroid Build Coastguard Worker use base::linux::move_task_to_cgroup;
29*bb4ee6a4SAndroid Build Coastguard Worker use base::warn;
30*bb4ee6a4SAndroid Build Coastguard Worker use base::AsRawDescriptor;
31*bb4ee6a4SAndroid Build Coastguard Worker use base::Event;
32*bb4ee6a4SAndroid Build Coastguard Worker use base::EventToken;
33*bb4ee6a4SAndroid Build Coastguard Worker use base::RawDescriptor;
34*bb4ee6a4SAndroid Build Coastguard Worker use base::ReadNotifier;
35*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(windows)]
36*bb4ee6a4SAndroid Build Coastguard Worker use base::RecvTube;
37*bb4ee6a4SAndroid Build Coastguard Worker use base::Result;
38*bb4ee6a4SAndroid Build Coastguard Worker use base::SafeDescriptor;
39*bb4ee6a4SAndroid Build Coastguard Worker use base::SendTube;
40*bb4ee6a4SAndroid Build Coastguard Worker use base::Tube;
41*bb4ee6a4SAndroid Build Coastguard Worker use base::VmEventType;
42*bb4ee6a4SAndroid Build Coastguard Worker use base::WaitContext;
43*bb4ee6a4SAndroid Build Coastguard Worker use base::WorkerThread;
44*bb4ee6a4SAndroid Build Coastguard Worker use data_model::*;
45*bb4ee6a4SAndroid Build Coastguard Worker pub use gpu_display::EventDevice;
46*bb4ee6a4SAndroid Build Coastguard Worker use gpu_display::*;
47*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::MemCacheType;
48*bb4ee6a4SAndroid Build Coastguard Worker pub use parameters::AudioDeviceMode;
49*bb4ee6a4SAndroid Build Coastguard Worker pub use parameters::GpuParameters;
50*bb4ee6a4SAndroid Build Coastguard Worker use rutabaga_gfx::*;
51*bb4ee6a4SAndroid Build Coastguard Worker use serde::Deserialize;
52*bb4ee6a4SAndroid Build Coastguard Worker use serde::Serialize;
53*bb4ee6a4SAndroid Build Coastguard Worker use sync::Mutex;
54*bb4ee6a4SAndroid Build Coastguard Worker pub use vm_control::gpu::DisplayMode as GpuDisplayMode;
55*bb4ee6a4SAndroid Build Coastguard Worker pub use vm_control::gpu::DisplayParameters as GpuDisplayParameters;
56*bb4ee6a4SAndroid Build Coastguard Worker use vm_control::gpu::GpuControlCommand;
57*bb4ee6a4SAndroid Build Coastguard Worker use vm_control::gpu::GpuControlResult;
58*bb4ee6a4SAndroid Build Coastguard Worker pub use vm_control::gpu::MouseMode as GpuMouseMode;
59*bb4ee6a4SAndroid Build Coastguard Worker pub use vm_control::gpu::DEFAULT_DISPLAY_HEIGHT;
60*bb4ee6a4SAndroid Build Coastguard Worker pub use vm_control::gpu::DEFAULT_DISPLAY_WIDTH;
61*bb4ee6a4SAndroid Build Coastguard Worker pub use vm_control::gpu::DEFAULT_REFRESH_RATE;
62*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(windows)]
63*bb4ee6a4SAndroid Build Coastguard Worker use vm_control::ModifyWaitContext;
64*bb4ee6a4SAndroid Build Coastguard Worker use vm_memory::GuestAddress;
65*bb4ee6a4SAndroid Build Coastguard Worker use vm_memory::GuestMemory;
66*bb4ee6a4SAndroid Build Coastguard Worker use zerocopy::AsBytes;
67*bb4ee6a4SAndroid Build Coastguard Worker
68*bb4ee6a4SAndroid Build Coastguard Worker pub use self::protocol::virtio_gpu_config;
69*bb4ee6a4SAndroid Build Coastguard Worker pub use self::protocol::VIRTIO_GPU_F_CONTEXT_INIT;
70*bb4ee6a4SAndroid Build Coastguard Worker pub use self::protocol::VIRTIO_GPU_F_CREATE_GUEST_HANDLE;
71*bb4ee6a4SAndroid Build Coastguard Worker pub use self::protocol::VIRTIO_GPU_F_EDID;
72*bb4ee6a4SAndroid Build Coastguard Worker pub use self::protocol::VIRTIO_GPU_F_FENCE_PASSING;
73*bb4ee6a4SAndroid Build Coastguard Worker pub use self::protocol::VIRTIO_GPU_F_RESOURCE_BLOB;
74*bb4ee6a4SAndroid Build Coastguard Worker pub use self::protocol::VIRTIO_GPU_F_RESOURCE_UUID;
75*bb4ee6a4SAndroid Build Coastguard Worker pub use self::protocol::VIRTIO_GPU_F_VIRGL;
76*bb4ee6a4SAndroid Build Coastguard Worker pub use self::protocol::VIRTIO_GPU_MAX_SCANOUTS;
77*bb4ee6a4SAndroid Build Coastguard Worker pub use self::protocol::VIRTIO_GPU_SHM_ID_HOST_VISIBLE;
78*bb4ee6a4SAndroid Build Coastguard Worker use self::protocol::*;
79*bb4ee6a4SAndroid Build Coastguard Worker use self::virtio_gpu::to_rutabaga_descriptor;
80*bb4ee6a4SAndroid Build Coastguard Worker pub use self::virtio_gpu::ProcessDisplayResult;
81*bb4ee6a4SAndroid Build Coastguard Worker use self::virtio_gpu::VirtioGpu;
82*bb4ee6a4SAndroid Build Coastguard Worker use self::virtio_gpu::VirtioGpuSnapshot;
83*bb4ee6a4SAndroid Build Coastguard Worker use super::copy_config;
84*bb4ee6a4SAndroid Build Coastguard Worker use super::resource_bridge::ResourceRequest;
85*bb4ee6a4SAndroid Build Coastguard Worker use super::DescriptorChain;
86*bb4ee6a4SAndroid Build Coastguard Worker use super::DeviceType;
87*bb4ee6a4SAndroid Build Coastguard Worker use super::Interrupt;
88*bb4ee6a4SAndroid Build Coastguard Worker use super::Queue;
89*bb4ee6a4SAndroid Build Coastguard Worker use super::Reader;
90*bb4ee6a4SAndroid Build Coastguard Worker use super::SharedMemoryMapper;
91*bb4ee6a4SAndroid Build Coastguard Worker use super::SharedMemoryPrepareType;
92*bb4ee6a4SAndroid Build Coastguard Worker use super::SharedMemoryRegion;
93*bb4ee6a4SAndroid Build Coastguard Worker use super::VirtioDevice;
94*bb4ee6a4SAndroid Build Coastguard Worker use super::Writer;
95*bb4ee6a4SAndroid Build Coastguard Worker use crate::PciAddress;
96*bb4ee6a4SAndroid Build Coastguard Worker
97*bb4ee6a4SAndroid Build Coastguard Worker // First queue is for virtio gpu commands. Second queue is for cursor commands, which we expect
98*bb4ee6a4SAndroid Build Coastguard Worker // there to be fewer of.
99*bb4ee6a4SAndroid Build Coastguard Worker const QUEUE_SIZES: &[u16] = &[512, 16];
100*bb4ee6a4SAndroid Build Coastguard Worker
101*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
102*bb4ee6a4SAndroid Build Coastguard Worker pub enum GpuMode {
103*bb4ee6a4SAndroid Build Coastguard Worker #[serde(rename = "2d", alias = "2D")]
104*bb4ee6a4SAndroid Build Coastguard Worker Mode2D,
105*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "virgl_renderer")]
106*bb4ee6a4SAndroid Build Coastguard Worker #[serde(rename = "virglrenderer", alias = "3d", alias = "3D")]
107*bb4ee6a4SAndroid Build Coastguard Worker ModeVirglRenderer,
108*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "gfxstream")]
109*bb4ee6a4SAndroid Build Coastguard Worker #[serde(rename = "gfxstream")]
110*bb4ee6a4SAndroid Build Coastguard Worker ModeGfxstream,
111*bb4ee6a4SAndroid Build Coastguard Worker }
112*bb4ee6a4SAndroid Build Coastguard Worker
113*bb4ee6a4SAndroid Build Coastguard Worker impl Default for GpuMode {
default() -> Self114*bb4ee6a4SAndroid Build Coastguard Worker fn default() -> Self {
115*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(all(windows, feature = "gfxstream"))]
116*bb4ee6a4SAndroid Build Coastguard Worker return GpuMode::ModeGfxstream;
117*bb4ee6a4SAndroid Build Coastguard Worker
118*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(all(unix, feature = "virgl_renderer"))]
119*bb4ee6a4SAndroid Build Coastguard Worker return GpuMode::ModeVirglRenderer;
120*bb4ee6a4SAndroid Build Coastguard Worker
121*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(not(any(
122*bb4ee6a4SAndroid Build Coastguard Worker all(windows, feature = "gfxstream"),
123*bb4ee6a4SAndroid Build Coastguard Worker all(unix, feature = "virgl_renderer"),
124*bb4ee6a4SAndroid Build Coastguard Worker )))]
125*bb4ee6a4SAndroid Build Coastguard Worker return GpuMode::Mode2D;
126*bb4ee6a4SAndroid Build Coastguard Worker }
127*bb4ee6a4SAndroid Build Coastguard Worker }
128*bb4ee6a4SAndroid Build Coastguard Worker
129*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Clone, Debug, Serialize, Deserialize)]
130*bb4ee6a4SAndroid Build Coastguard Worker #[serde(rename_all = "kebab-case")]
131*bb4ee6a4SAndroid Build Coastguard Worker pub enum GpuWsi {
132*bb4ee6a4SAndroid Build Coastguard Worker #[serde(alias = "vk")]
133*bb4ee6a4SAndroid Build Coastguard Worker Vulkan,
134*bb4ee6a4SAndroid Build Coastguard Worker }
135*bb4ee6a4SAndroid Build Coastguard Worker
136*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Copy, Clone, Debug)]
137*bb4ee6a4SAndroid Build Coastguard Worker pub struct VirtioScanoutBlobData {
138*bb4ee6a4SAndroid Build Coastguard Worker pub width: u32,
139*bb4ee6a4SAndroid Build Coastguard Worker pub height: u32,
140*bb4ee6a4SAndroid Build Coastguard Worker pub drm_format: DrmFormat,
141*bb4ee6a4SAndroid Build Coastguard Worker pub strides: [u32; 4],
142*bb4ee6a4SAndroid Build Coastguard Worker pub offsets: [u32; 4],
143*bb4ee6a4SAndroid Build Coastguard Worker }
144*bb4ee6a4SAndroid Build Coastguard Worker
145*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
146*bb4ee6a4SAndroid Build Coastguard Worker enum VirtioGpuRing {
147*bb4ee6a4SAndroid Build Coastguard Worker Global,
148*bb4ee6a4SAndroid Build Coastguard Worker ContextSpecific { ctx_id: u32, ring_idx: u8 },
149*bb4ee6a4SAndroid Build Coastguard Worker }
150*bb4ee6a4SAndroid Build Coastguard Worker
151*bb4ee6a4SAndroid Build Coastguard Worker struct FenceDescriptor {
152*bb4ee6a4SAndroid Build Coastguard Worker ring: VirtioGpuRing,
153*bb4ee6a4SAndroid Build Coastguard Worker fence_id: u64,
154*bb4ee6a4SAndroid Build Coastguard Worker desc_chain: DescriptorChain,
155*bb4ee6a4SAndroid Build Coastguard Worker len: u32,
156*bb4ee6a4SAndroid Build Coastguard Worker }
157*bb4ee6a4SAndroid Build Coastguard Worker
158*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Default)]
159*bb4ee6a4SAndroid Build Coastguard Worker pub struct FenceState {
160*bb4ee6a4SAndroid Build Coastguard Worker descs: Vec<FenceDescriptor>,
161*bb4ee6a4SAndroid Build Coastguard Worker completed_fences: BTreeMap<VirtioGpuRing, u64>,
162*bb4ee6a4SAndroid Build Coastguard Worker }
163*bb4ee6a4SAndroid Build Coastguard Worker
164*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Serialize, Deserialize)]
165*bb4ee6a4SAndroid Build Coastguard Worker struct FenceStateSnapshot {
166*bb4ee6a4SAndroid Build Coastguard Worker // Customize serialization to avoid errors when trying to use objects as keys in JSON
167*bb4ee6a4SAndroid Build Coastguard Worker // dictionaries.
168*bb4ee6a4SAndroid Build Coastguard Worker #[serde(
169*bb4ee6a4SAndroid Build Coastguard Worker serialize_with = "serialize_map_as_kv_vec",
170*bb4ee6a4SAndroid Build Coastguard Worker deserialize_with = "deserialize_map_from_kv_vec"
171*bb4ee6a4SAndroid Build Coastguard Worker )]
172*bb4ee6a4SAndroid Build Coastguard Worker completed_fences: BTreeMap<VirtioGpuRing, u64>,
173*bb4ee6a4SAndroid Build Coastguard Worker }
174*bb4ee6a4SAndroid Build Coastguard Worker
175*bb4ee6a4SAndroid Build Coastguard Worker impl FenceState {
snapshot(&self) -> FenceStateSnapshot176*bb4ee6a4SAndroid Build Coastguard Worker fn snapshot(&self) -> FenceStateSnapshot {
177*bb4ee6a4SAndroid Build Coastguard Worker assert!(self.descs.is_empty(), "can't snapshot with pending fences");
178*bb4ee6a4SAndroid Build Coastguard Worker FenceStateSnapshot {
179*bb4ee6a4SAndroid Build Coastguard Worker completed_fences: self.completed_fences.clone(),
180*bb4ee6a4SAndroid Build Coastguard Worker }
181*bb4ee6a4SAndroid Build Coastguard Worker }
182*bb4ee6a4SAndroid Build Coastguard Worker
restore(&mut self, snapshot: FenceStateSnapshot)183*bb4ee6a4SAndroid Build Coastguard Worker fn restore(&mut self, snapshot: FenceStateSnapshot) {
184*bb4ee6a4SAndroid Build Coastguard Worker assert!(self.descs.is_empty(), "can't restore activated device");
185*bb4ee6a4SAndroid Build Coastguard Worker self.completed_fences = snapshot.completed_fences;
186*bb4ee6a4SAndroid Build Coastguard Worker }
187*bb4ee6a4SAndroid Build Coastguard Worker }
188*bb4ee6a4SAndroid Build Coastguard Worker
189*bb4ee6a4SAndroid Build Coastguard Worker pub trait QueueReader {
pop(&self) -> Option<DescriptorChain>190*bb4ee6a4SAndroid Build Coastguard Worker fn pop(&self) -> Option<DescriptorChain>;
add_used(&self, desc_chain: DescriptorChain, len: u32)191*bb4ee6a4SAndroid Build Coastguard Worker fn add_used(&self, desc_chain: DescriptorChain, len: u32);
signal_used(&self)192*bb4ee6a4SAndroid Build Coastguard Worker fn signal_used(&self);
193*bb4ee6a4SAndroid Build Coastguard Worker }
194*bb4ee6a4SAndroid Build Coastguard Worker
195*bb4ee6a4SAndroid Build Coastguard Worker struct LocalQueueReader {
196*bb4ee6a4SAndroid Build Coastguard Worker queue: RefCell<Queue>,
197*bb4ee6a4SAndroid Build Coastguard Worker }
198*bb4ee6a4SAndroid Build Coastguard Worker
199*bb4ee6a4SAndroid Build Coastguard Worker impl LocalQueueReader {
new(queue: Queue) -> Self200*bb4ee6a4SAndroid Build Coastguard Worker fn new(queue: Queue) -> Self {
201*bb4ee6a4SAndroid Build Coastguard Worker Self {
202*bb4ee6a4SAndroid Build Coastguard Worker queue: RefCell::new(queue),
203*bb4ee6a4SAndroid Build Coastguard Worker }
204*bb4ee6a4SAndroid Build Coastguard Worker }
205*bb4ee6a4SAndroid Build Coastguard Worker }
206*bb4ee6a4SAndroid Build Coastguard Worker
207*bb4ee6a4SAndroid Build Coastguard Worker impl QueueReader for LocalQueueReader {
pop(&self) -> Option<DescriptorChain>208*bb4ee6a4SAndroid Build Coastguard Worker fn pop(&self) -> Option<DescriptorChain> {
209*bb4ee6a4SAndroid Build Coastguard Worker self.queue.borrow_mut().pop()
210*bb4ee6a4SAndroid Build Coastguard Worker }
211*bb4ee6a4SAndroid Build Coastguard Worker
add_used(&self, desc_chain: DescriptorChain, len: u32)212*bb4ee6a4SAndroid Build Coastguard Worker fn add_used(&self, desc_chain: DescriptorChain, len: u32) {
213*bb4ee6a4SAndroid Build Coastguard Worker self.queue.borrow_mut().add_used(desc_chain, len)
214*bb4ee6a4SAndroid Build Coastguard Worker }
215*bb4ee6a4SAndroid Build Coastguard Worker
signal_used(&self)216*bb4ee6a4SAndroid Build Coastguard Worker fn signal_used(&self) {
217*bb4ee6a4SAndroid Build Coastguard Worker self.queue.borrow_mut().trigger_interrupt();
218*bb4ee6a4SAndroid Build Coastguard Worker }
219*bb4ee6a4SAndroid Build Coastguard Worker }
220*bb4ee6a4SAndroid Build Coastguard Worker
221*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Clone)]
222*bb4ee6a4SAndroid Build Coastguard Worker struct SharedQueueReader {
223*bb4ee6a4SAndroid Build Coastguard Worker queue: Arc<Mutex<Queue>>,
224*bb4ee6a4SAndroid Build Coastguard Worker }
225*bb4ee6a4SAndroid Build Coastguard Worker
226*bb4ee6a4SAndroid Build Coastguard Worker impl SharedQueueReader {
new(queue: Queue) -> Self227*bb4ee6a4SAndroid Build Coastguard Worker fn new(queue: Queue) -> Self {
228*bb4ee6a4SAndroid Build Coastguard Worker Self {
229*bb4ee6a4SAndroid Build Coastguard Worker queue: Arc::new(Mutex::new(queue)),
230*bb4ee6a4SAndroid Build Coastguard Worker }
231*bb4ee6a4SAndroid Build Coastguard Worker }
232*bb4ee6a4SAndroid Build Coastguard Worker }
233*bb4ee6a4SAndroid Build Coastguard Worker
234*bb4ee6a4SAndroid Build Coastguard Worker impl QueueReader for SharedQueueReader {
pop(&self) -> Option<DescriptorChain>235*bb4ee6a4SAndroid Build Coastguard Worker fn pop(&self) -> Option<DescriptorChain> {
236*bb4ee6a4SAndroid Build Coastguard Worker self.queue.lock().pop()
237*bb4ee6a4SAndroid Build Coastguard Worker }
238*bb4ee6a4SAndroid Build Coastguard Worker
add_used(&self, desc_chain: DescriptorChain, len: u32)239*bb4ee6a4SAndroid Build Coastguard Worker fn add_used(&self, desc_chain: DescriptorChain, len: u32) {
240*bb4ee6a4SAndroid Build Coastguard Worker self.queue.lock().add_used(desc_chain, len)
241*bb4ee6a4SAndroid Build Coastguard Worker }
242*bb4ee6a4SAndroid Build Coastguard Worker
signal_used(&self)243*bb4ee6a4SAndroid Build Coastguard Worker fn signal_used(&self) {
244*bb4ee6a4SAndroid Build Coastguard Worker self.queue.lock().trigger_interrupt();
245*bb4ee6a4SAndroid Build Coastguard Worker }
246*bb4ee6a4SAndroid Build Coastguard Worker }
247*bb4ee6a4SAndroid Build Coastguard Worker
248*bb4ee6a4SAndroid Build Coastguard Worker /// Initializes the virtio_gpu state tracker.
build( display_backends: &[DisplayBackend], display_params: Vec<GpuDisplayParameters>, display_event: Arc<AtomicBool>, rutabaga: Rutabaga, mapper: Arc<Mutex<Option<Box<dyn SharedMemoryMapper>>>>, external_blob: bool, fixed_blob_mapping: bool, #[cfg(windows)] wndproc_thread: &mut Option<WindowProcedureThread>, udmabuf: bool, #[cfg(windows)] gpu_display_wait_descriptor_ctrl_wr: SendTube, ) -> Option<VirtioGpu>249*bb4ee6a4SAndroid Build Coastguard Worker fn build(
250*bb4ee6a4SAndroid Build Coastguard Worker display_backends: &[DisplayBackend],
251*bb4ee6a4SAndroid Build Coastguard Worker display_params: Vec<GpuDisplayParameters>,
252*bb4ee6a4SAndroid Build Coastguard Worker display_event: Arc<AtomicBool>,
253*bb4ee6a4SAndroid Build Coastguard Worker rutabaga: Rutabaga,
254*bb4ee6a4SAndroid Build Coastguard Worker mapper: Arc<Mutex<Option<Box<dyn SharedMemoryMapper>>>>,
255*bb4ee6a4SAndroid Build Coastguard Worker external_blob: bool,
256*bb4ee6a4SAndroid Build Coastguard Worker fixed_blob_mapping: bool,
257*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(windows)] wndproc_thread: &mut Option<WindowProcedureThread>,
258*bb4ee6a4SAndroid Build Coastguard Worker udmabuf: bool,
259*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(windows)] gpu_display_wait_descriptor_ctrl_wr: SendTube,
260*bb4ee6a4SAndroid Build Coastguard Worker ) -> Option<VirtioGpu> {
261*bb4ee6a4SAndroid Build Coastguard Worker let mut display_opt = None;
262*bb4ee6a4SAndroid Build Coastguard Worker for display_backend in display_backends {
263*bb4ee6a4SAndroid Build Coastguard Worker match display_backend.build(
264*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(windows)]
265*bb4ee6a4SAndroid Build Coastguard Worker wndproc_thread,
266*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(windows)]
267*bb4ee6a4SAndroid Build Coastguard Worker gpu_display_wait_descriptor_ctrl_wr
268*bb4ee6a4SAndroid Build Coastguard Worker .try_clone()
269*bb4ee6a4SAndroid Build Coastguard Worker .expect("failed to clone wait context ctrl channel"),
270*bb4ee6a4SAndroid Build Coastguard Worker ) {
271*bb4ee6a4SAndroid Build Coastguard Worker Ok(c) => {
272*bb4ee6a4SAndroid Build Coastguard Worker display_opt = Some(c);
273*bb4ee6a4SAndroid Build Coastguard Worker break;
274*bb4ee6a4SAndroid Build Coastguard Worker }
275*bb4ee6a4SAndroid Build Coastguard Worker Err(e) => error!("failed to open display: {}", e),
276*bb4ee6a4SAndroid Build Coastguard Worker };
277*bb4ee6a4SAndroid Build Coastguard Worker }
278*bb4ee6a4SAndroid Build Coastguard Worker
279*bb4ee6a4SAndroid Build Coastguard Worker let display = match display_opt {
280*bb4ee6a4SAndroid Build Coastguard Worker Some(d) => d,
281*bb4ee6a4SAndroid Build Coastguard Worker None => {
282*bb4ee6a4SAndroid Build Coastguard Worker error!("failed to open any displays");
283*bb4ee6a4SAndroid Build Coastguard Worker return None;
284*bb4ee6a4SAndroid Build Coastguard Worker }
285*bb4ee6a4SAndroid Build Coastguard Worker };
286*bb4ee6a4SAndroid Build Coastguard Worker
287*bb4ee6a4SAndroid Build Coastguard Worker VirtioGpu::new(
288*bb4ee6a4SAndroid Build Coastguard Worker display,
289*bb4ee6a4SAndroid Build Coastguard Worker display_params,
290*bb4ee6a4SAndroid Build Coastguard Worker display_event,
291*bb4ee6a4SAndroid Build Coastguard Worker rutabaga,
292*bb4ee6a4SAndroid Build Coastguard Worker mapper,
293*bb4ee6a4SAndroid Build Coastguard Worker external_blob,
294*bb4ee6a4SAndroid Build Coastguard Worker fixed_blob_mapping,
295*bb4ee6a4SAndroid Build Coastguard Worker udmabuf,
296*bb4ee6a4SAndroid Build Coastguard Worker )
297*bb4ee6a4SAndroid Build Coastguard Worker }
298*bb4ee6a4SAndroid Build Coastguard Worker
299*bb4ee6a4SAndroid Build Coastguard Worker /// Resources used by the fence handler.
300*bb4ee6a4SAndroid Build Coastguard Worker pub struct FenceHandlerActivationResources<Q>
301*bb4ee6a4SAndroid Build Coastguard Worker where
302*bb4ee6a4SAndroid Build Coastguard Worker Q: QueueReader + Send + Clone + 'static,
303*bb4ee6a4SAndroid Build Coastguard Worker {
304*bb4ee6a4SAndroid Build Coastguard Worker pub mem: GuestMemory,
305*bb4ee6a4SAndroid Build Coastguard Worker pub ctrl_queue: Q,
306*bb4ee6a4SAndroid Build Coastguard Worker }
307*bb4ee6a4SAndroid Build Coastguard Worker
308*bb4ee6a4SAndroid Build Coastguard Worker /// Create a handler that writes into the completed fence queue
create_fence_handler<Q>( fence_handler_resources: Arc<Mutex<Option<FenceHandlerActivationResources<Q>>>>, fence_state: Arc<Mutex<FenceState>>, ) -> RutabagaFenceHandler where Q: QueueReader + Send + Clone + 'static,309*bb4ee6a4SAndroid Build Coastguard Worker pub fn create_fence_handler<Q>(
310*bb4ee6a4SAndroid Build Coastguard Worker fence_handler_resources: Arc<Mutex<Option<FenceHandlerActivationResources<Q>>>>,
311*bb4ee6a4SAndroid Build Coastguard Worker fence_state: Arc<Mutex<FenceState>>,
312*bb4ee6a4SAndroid Build Coastguard Worker ) -> RutabagaFenceHandler
313*bb4ee6a4SAndroid Build Coastguard Worker where
314*bb4ee6a4SAndroid Build Coastguard Worker Q: QueueReader + Send + Clone + 'static,
315*bb4ee6a4SAndroid Build Coastguard Worker {
316*bb4ee6a4SAndroid Build Coastguard Worker RutabagaFenceHandler::new(move |completed_fence: RutabagaFence| {
317*bb4ee6a4SAndroid Build Coastguard Worker let mut signal = false;
318*bb4ee6a4SAndroid Build Coastguard Worker
319*bb4ee6a4SAndroid Build Coastguard Worker if let Some(ref fence_handler_resources) = *fence_handler_resources.lock() {
320*bb4ee6a4SAndroid Build Coastguard Worker // Limits the lifetime of `fence_state`:
321*bb4ee6a4SAndroid Build Coastguard Worker {
322*bb4ee6a4SAndroid Build Coastguard Worker let ring = match completed_fence.flags & VIRTIO_GPU_FLAG_INFO_RING_IDX {
323*bb4ee6a4SAndroid Build Coastguard Worker 0 => VirtioGpuRing::Global,
324*bb4ee6a4SAndroid Build Coastguard Worker _ => VirtioGpuRing::ContextSpecific {
325*bb4ee6a4SAndroid Build Coastguard Worker ctx_id: completed_fence.ctx_id,
326*bb4ee6a4SAndroid Build Coastguard Worker ring_idx: completed_fence.ring_idx,
327*bb4ee6a4SAndroid Build Coastguard Worker },
328*bb4ee6a4SAndroid Build Coastguard Worker };
329*bb4ee6a4SAndroid Build Coastguard Worker
330*bb4ee6a4SAndroid Build Coastguard Worker let mut fence_state = fence_state.lock();
331*bb4ee6a4SAndroid Build Coastguard Worker // TODO(dverkamp): use `drain_filter()` when it is stabilized
332*bb4ee6a4SAndroid Build Coastguard Worker let mut i = 0;
333*bb4ee6a4SAndroid Build Coastguard Worker while i < fence_state.descs.len() {
334*bb4ee6a4SAndroid Build Coastguard Worker if fence_state.descs[i].ring == ring
335*bb4ee6a4SAndroid Build Coastguard Worker && fence_state.descs[i].fence_id <= completed_fence.fence_id
336*bb4ee6a4SAndroid Build Coastguard Worker {
337*bb4ee6a4SAndroid Build Coastguard Worker let completed_desc = fence_state.descs.remove(i);
338*bb4ee6a4SAndroid Build Coastguard Worker fence_handler_resources
339*bb4ee6a4SAndroid Build Coastguard Worker .ctrl_queue
340*bb4ee6a4SAndroid Build Coastguard Worker .add_used(completed_desc.desc_chain, completed_desc.len);
341*bb4ee6a4SAndroid Build Coastguard Worker signal = true;
342*bb4ee6a4SAndroid Build Coastguard Worker } else {
343*bb4ee6a4SAndroid Build Coastguard Worker i += 1;
344*bb4ee6a4SAndroid Build Coastguard Worker }
345*bb4ee6a4SAndroid Build Coastguard Worker }
346*bb4ee6a4SAndroid Build Coastguard Worker
347*bb4ee6a4SAndroid Build Coastguard Worker // Update the last completed fence for this context
348*bb4ee6a4SAndroid Build Coastguard Worker fence_state
349*bb4ee6a4SAndroid Build Coastguard Worker .completed_fences
350*bb4ee6a4SAndroid Build Coastguard Worker .insert(ring, completed_fence.fence_id);
351*bb4ee6a4SAndroid Build Coastguard Worker }
352*bb4ee6a4SAndroid Build Coastguard Worker
353*bb4ee6a4SAndroid Build Coastguard Worker if signal {
354*bb4ee6a4SAndroid Build Coastguard Worker fence_handler_resources.ctrl_queue.signal_used();
355*bb4ee6a4SAndroid Build Coastguard Worker }
356*bb4ee6a4SAndroid Build Coastguard Worker }
357*bb4ee6a4SAndroid Build Coastguard Worker })
358*bb4ee6a4SAndroid Build Coastguard Worker }
359*bb4ee6a4SAndroid Build Coastguard Worker
360*bb4ee6a4SAndroid Build Coastguard Worker pub struct ReturnDescriptor {
361*bb4ee6a4SAndroid Build Coastguard Worker pub desc_chain: DescriptorChain,
362*bb4ee6a4SAndroid Build Coastguard Worker pub len: u32,
363*bb4ee6a4SAndroid Build Coastguard Worker }
364*bb4ee6a4SAndroid Build Coastguard Worker
365*bb4ee6a4SAndroid Build Coastguard Worker pub struct Frontend {
366*bb4ee6a4SAndroid Build Coastguard Worker fence_state: Arc<Mutex<FenceState>>,
367*bb4ee6a4SAndroid Build Coastguard Worker virtio_gpu: VirtioGpu,
368*bb4ee6a4SAndroid Build Coastguard Worker }
369*bb4ee6a4SAndroid Build Coastguard Worker
370*bb4ee6a4SAndroid Build Coastguard Worker impl Frontend {
new(virtio_gpu: VirtioGpu, fence_state: Arc<Mutex<FenceState>>) -> Frontend371*bb4ee6a4SAndroid Build Coastguard Worker fn new(virtio_gpu: VirtioGpu, fence_state: Arc<Mutex<FenceState>>) -> Frontend {
372*bb4ee6a4SAndroid Build Coastguard Worker Frontend {
373*bb4ee6a4SAndroid Build Coastguard Worker fence_state,
374*bb4ee6a4SAndroid Build Coastguard Worker virtio_gpu,
375*bb4ee6a4SAndroid Build Coastguard Worker }
376*bb4ee6a4SAndroid Build Coastguard Worker }
377*bb4ee6a4SAndroid Build Coastguard Worker
378*bb4ee6a4SAndroid Build Coastguard Worker /// Returns the internal connection to the compositor and its associated state.
display(&mut self) -> &Rc<RefCell<GpuDisplay>>379*bb4ee6a4SAndroid Build Coastguard Worker pub fn display(&mut self) -> &Rc<RefCell<GpuDisplay>> {
380*bb4ee6a4SAndroid Build Coastguard Worker self.virtio_gpu.display()
381*bb4ee6a4SAndroid Build Coastguard Worker }
382*bb4ee6a4SAndroid Build Coastguard Worker
383*bb4ee6a4SAndroid Build Coastguard Worker /// Processes the internal `display` events and returns `true` if any display was closed.
process_display(&mut self) -> ProcessDisplayResult384*bb4ee6a4SAndroid Build Coastguard Worker pub fn process_display(&mut self) -> ProcessDisplayResult {
385*bb4ee6a4SAndroid Build Coastguard Worker self.virtio_gpu.process_display()
386*bb4ee6a4SAndroid Build Coastguard Worker }
387*bb4ee6a4SAndroid Build Coastguard Worker
388*bb4ee6a4SAndroid Build Coastguard Worker /// Processes incoming requests on `resource_bridge`.
process_resource_bridge(&mut self, resource_bridge: &Tube) -> anyhow::Result<()>389*bb4ee6a4SAndroid Build Coastguard Worker pub fn process_resource_bridge(&mut self, resource_bridge: &Tube) -> anyhow::Result<()> {
390*bb4ee6a4SAndroid Build Coastguard Worker let response = match resource_bridge.recv() {
391*bb4ee6a4SAndroid Build Coastguard Worker Ok(ResourceRequest::GetBuffer { id }) => self.virtio_gpu.export_resource(id),
392*bb4ee6a4SAndroid Build Coastguard Worker Ok(ResourceRequest::GetFence { seqno }) => self.virtio_gpu.export_fence(seqno),
393*bb4ee6a4SAndroid Build Coastguard Worker Err(e) => return Err(e).context("Error receiving resource bridge request"),
394*bb4ee6a4SAndroid Build Coastguard Worker };
395*bb4ee6a4SAndroid Build Coastguard Worker
396*bb4ee6a4SAndroid Build Coastguard Worker resource_bridge
397*bb4ee6a4SAndroid Build Coastguard Worker .send(&response)
398*bb4ee6a4SAndroid Build Coastguard Worker .context("Error sending resource bridge response")?;
399*bb4ee6a4SAndroid Build Coastguard Worker
400*bb4ee6a4SAndroid Build Coastguard Worker Ok(())
401*bb4ee6a4SAndroid Build Coastguard Worker }
402*bb4ee6a4SAndroid Build Coastguard Worker
403*bb4ee6a4SAndroid Build Coastguard Worker /// Processes the GPU control command and returns the result with a bool indicating if the
404*bb4ee6a4SAndroid Build Coastguard Worker /// GPU device's config needs to be updated.
process_gpu_control_command(&mut self, cmd: GpuControlCommand) -> GpuControlResult405*bb4ee6a4SAndroid Build Coastguard Worker pub fn process_gpu_control_command(&mut self, cmd: GpuControlCommand) -> GpuControlResult {
406*bb4ee6a4SAndroid Build Coastguard Worker self.virtio_gpu.process_gpu_control_command(cmd)
407*bb4ee6a4SAndroid Build Coastguard Worker }
408*bb4ee6a4SAndroid Build Coastguard Worker
process_gpu_command( &mut self, mem: &GuestMemory, cmd: GpuCommand, reader: &mut Reader, ) -> VirtioGpuResult409*bb4ee6a4SAndroid Build Coastguard Worker fn process_gpu_command(
410*bb4ee6a4SAndroid Build Coastguard Worker &mut self,
411*bb4ee6a4SAndroid Build Coastguard Worker mem: &GuestMemory,
412*bb4ee6a4SAndroid Build Coastguard Worker cmd: GpuCommand,
413*bb4ee6a4SAndroid Build Coastguard Worker reader: &mut Reader,
414*bb4ee6a4SAndroid Build Coastguard Worker ) -> VirtioGpuResult {
415*bb4ee6a4SAndroid Build Coastguard Worker self.virtio_gpu.force_ctx_0();
416*bb4ee6a4SAndroid Build Coastguard Worker
417*bb4ee6a4SAndroid Build Coastguard Worker match cmd {
418*bb4ee6a4SAndroid Build Coastguard Worker GpuCommand::GetDisplayInfo(_) => Ok(GpuResponse::OkDisplayInfo(
419*bb4ee6a4SAndroid Build Coastguard Worker self.virtio_gpu.display_info().to_vec(),
420*bb4ee6a4SAndroid Build Coastguard Worker )),
421*bb4ee6a4SAndroid Build Coastguard Worker GpuCommand::ResourceCreate2d(info) => {
422*bb4ee6a4SAndroid Build Coastguard Worker let resource_id = info.resource_id.to_native();
423*bb4ee6a4SAndroid Build Coastguard Worker
424*bb4ee6a4SAndroid Build Coastguard Worker let resource_create_3d = ResourceCreate3D {
425*bb4ee6a4SAndroid Build Coastguard Worker target: RUTABAGA_PIPE_TEXTURE_2D,
426*bb4ee6a4SAndroid Build Coastguard Worker format: info.format.to_native(),
427*bb4ee6a4SAndroid Build Coastguard Worker bind: RUTABAGA_PIPE_BIND_RENDER_TARGET,
428*bb4ee6a4SAndroid Build Coastguard Worker width: info.width.to_native(),
429*bb4ee6a4SAndroid Build Coastguard Worker height: info.height.to_native(),
430*bb4ee6a4SAndroid Build Coastguard Worker depth: 1,
431*bb4ee6a4SAndroid Build Coastguard Worker array_size: 1,
432*bb4ee6a4SAndroid Build Coastguard Worker last_level: 0,
433*bb4ee6a4SAndroid Build Coastguard Worker nr_samples: 0,
434*bb4ee6a4SAndroid Build Coastguard Worker flags: 0,
435*bb4ee6a4SAndroid Build Coastguard Worker };
436*bb4ee6a4SAndroid Build Coastguard Worker
437*bb4ee6a4SAndroid Build Coastguard Worker self.virtio_gpu
438*bb4ee6a4SAndroid Build Coastguard Worker .resource_create_3d(resource_id, resource_create_3d)
439*bb4ee6a4SAndroid Build Coastguard Worker }
440*bb4ee6a4SAndroid Build Coastguard Worker GpuCommand::ResourceUnref(info) => {
441*bb4ee6a4SAndroid Build Coastguard Worker self.virtio_gpu.unref_resource(info.resource_id.to_native())
442*bb4ee6a4SAndroid Build Coastguard Worker }
443*bb4ee6a4SAndroid Build Coastguard Worker GpuCommand::SetScanout(info) => self.virtio_gpu.set_scanout(
444*bb4ee6a4SAndroid Build Coastguard Worker info.scanout_id.to_native(),
445*bb4ee6a4SAndroid Build Coastguard Worker info.resource_id.to_native(),
446*bb4ee6a4SAndroid Build Coastguard Worker None,
447*bb4ee6a4SAndroid Build Coastguard Worker ),
448*bb4ee6a4SAndroid Build Coastguard Worker GpuCommand::ResourceFlush(info) => {
449*bb4ee6a4SAndroid Build Coastguard Worker self.virtio_gpu.flush_resource(info.resource_id.to_native())
450*bb4ee6a4SAndroid Build Coastguard Worker }
451*bb4ee6a4SAndroid Build Coastguard Worker GpuCommand::TransferToHost2d(info) => {
452*bb4ee6a4SAndroid Build Coastguard Worker let resource_id = info.resource_id.to_native();
453*bb4ee6a4SAndroid Build Coastguard Worker let transfer = Transfer3D::new_2d(
454*bb4ee6a4SAndroid Build Coastguard Worker info.r.x.to_native(),
455*bb4ee6a4SAndroid Build Coastguard Worker info.r.y.to_native(),
456*bb4ee6a4SAndroid Build Coastguard Worker info.r.width.to_native(),
457*bb4ee6a4SAndroid Build Coastguard Worker info.r.height.to_native(),
458*bb4ee6a4SAndroid Build Coastguard Worker info.offset.to_native(),
459*bb4ee6a4SAndroid Build Coastguard Worker );
460*bb4ee6a4SAndroid Build Coastguard Worker self.virtio_gpu.transfer_write(0, resource_id, transfer)
461*bb4ee6a4SAndroid Build Coastguard Worker }
462*bb4ee6a4SAndroid Build Coastguard Worker GpuCommand::ResourceAttachBacking(info) => {
463*bb4ee6a4SAndroid Build Coastguard Worker let available_bytes = reader.available_bytes();
464*bb4ee6a4SAndroid Build Coastguard Worker if available_bytes != 0 {
465*bb4ee6a4SAndroid Build Coastguard Worker let entry_count = info.nr_entries.to_native() as usize;
466*bb4ee6a4SAndroid Build Coastguard Worker let mut vecs = Vec::with_capacity(entry_count);
467*bb4ee6a4SAndroid Build Coastguard Worker for _ in 0..entry_count {
468*bb4ee6a4SAndroid Build Coastguard Worker match reader.read_obj::<virtio_gpu_mem_entry>() {
469*bb4ee6a4SAndroid Build Coastguard Worker Ok(entry) => {
470*bb4ee6a4SAndroid Build Coastguard Worker let addr = GuestAddress(entry.addr.to_native());
471*bb4ee6a4SAndroid Build Coastguard Worker let len = entry.length.to_native() as usize;
472*bb4ee6a4SAndroid Build Coastguard Worker vecs.push((addr, len))
473*bb4ee6a4SAndroid Build Coastguard Worker }
474*bb4ee6a4SAndroid Build Coastguard Worker Err(_) => return Err(GpuResponse::ErrUnspec),
475*bb4ee6a4SAndroid Build Coastguard Worker }
476*bb4ee6a4SAndroid Build Coastguard Worker }
477*bb4ee6a4SAndroid Build Coastguard Worker self.virtio_gpu
478*bb4ee6a4SAndroid Build Coastguard Worker .attach_backing(info.resource_id.to_native(), mem, vecs)
479*bb4ee6a4SAndroid Build Coastguard Worker } else {
480*bb4ee6a4SAndroid Build Coastguard Worker error!("missing data for command {:?}", cmd);
481*bb4ee6a4SAndroid Build Coastguard Worker Err(GpuResponse::ErrUnspec)
482*bb4ee6a4SAndroid Build Coastguard Worker }
483*bb4ee6a4SAndroid Build Coastguard Worker }
484*bb4ee6a4SAndroid Build Coastguard Worker GpuCommand::ResourceDetachBacking(info) => {
485*bb4ee6a4SAndroid Build Coastguard Worker self.virtio_gpu.detach_backing(info.resource_id.to_native())
486*bb4ee6a4SAndroid Build Coastguard Worker }
487*bb4ee6a4SAndroid Build Coastguard Worker GpuCommand::UpdateCursor(info) => self.virtio_gpu.update_cursor(
488*bb4ee6a4SAndroid Build Coastguard Worker info.resource_id.to_native(),
489*bb4ee6a4SAndroid Build Coastguard Worker info.pos.scanout_id.to_native(),
490*bb4ee6a4SAndroid Build Coastguard Worker info.pos.x.into(),
491*bb4ee6a4SAndroid Build Coastguard Worker info.pos.y.into(),
492*bb4ee6a4SAndroid Build Coastguard Worker ),
493*bb4ee6a4SAndroid Build Coastguard Worker GpuCommand::MoveCursor(info) => self.virtio_gpu.move_cursor(
494*bb4ee6a4SAndroid Build Coastguard Worker info.pos.scanout_id.to_native(),
495*bb4ee6a4SAndroid Build Coastguard Worker info.pos.x.into(),
496*bb4ee6a4SAndroid Build Coastguard Worker info.pos.y.into(),
497*bb4ee6a4SAndroid Build Coastguard Worker ),
498*bb4ee6a4SAndroid Build Coastguard Worker GpuCommand::ResourceAssignUuid(info) => {
499*bb4ee6a4SAndroid Build Coastguard Worker let resource_id = info.resource_id.to_native();
500*bb4ee6a4SAndroid Build Coastguard Worker self.virtio_gpu.resource_assign_uuid(resource_id)
501*bb4ee6a4SAndroid Build Coastguard Worker }
502*bb4ee6a4SAndroid Build Coastguard Worker GpuCommand::GetCapsetInfo(info) => self
503*bb4ee6a4SAndroid Build Coastguard Worker .virtio_gpu
504*bb4ee6a4SAndroid Build Coastguard Worker .get_capset_info(info.capset_index.to_native()),
505*bb4ee6a4SAndroid Build Coastguard Worker GpuCommand::GetCapset(info) => self
506*bb4ee6a4SAndroid Build Coastguard Worker .virtio_gpu
507*bb4ee6a4SAndroid Build Coastguard Worker .get_capset(info.capset_id.to_native(), info.capset_version.to_native()),
508*bb4ee6a4SAndroid Build Coastguard Worker GpuCommand::CtxCreate(info) => {
509*bb4ee6a4SAndroid Build Coastguard Worker let context_name: Option<String> = String::from_utf8(info.debug_name.to_vec()).ok();
510*bb4ee6a4SAndroid Build Coastguard Worker self.virtio_gpu.create_context(
511*bb4ee6a4SAndroid Build Coastguard Worker info.hdr.ctx_id.to_native(),
512*bb4ee6a4SAndroid Build Coastguard Worker info.context_init.to_native(),
513*bb4ee6a4SAndroid Build Coastguard Worker context_name.as_deref(),
514*bb4ee6a4SAndroid Build Coastguard Worker )
515*bb4ee6a4SAndroid Build Coastguard Worker }
516*bb4ee6a4SAndroid Build Coastguard Worker GpuCommand::CtxDestroy(info) => {
517*bb4ee6a4SAndroid Build Coastguard Worker self.virtio_gpu.destroy_context(info.hdr.ctx_id.to_native())
518*bb4ee6a4SAndroid Build Coastguard Worker }
519*bb4ee6a4SAndroid Build Coastguard Worker GpuCommand::CtxAttachResource(info) => self
520*bb4ee6a4SAndroid Build Coastguard Worker .virtio_gpu
521*bb4ee6a4SAndroid Build Coastguard Worker .context_attach_resource(info.hdr.ctx_id.to_native(), info.resource_id.to_native()),
522*bb4ee6a4SAndroid Build Coastguard Worker GpuCommand::CtxDetachResource(info) => self
523*bb4ee6a4SAndroid Build Coastguard Worker .virtio_gpu
524*bb4ee6a4SAndroid Build Coastguard Worker .context_detach_resource(info.hdr.ctx_id.to_native(), info.resource_id.to_native()),
525*bb4ee6a4SAndroid Build Coastguard Worker GpuCommand::ResourceCreate3d(info) => {
526*bb4ee6a4SAndroid Build Coastguard Worker let resource_id = info.resource_id.to_native();
527*bb4ee6a4SAndroid Build Coastguard Worker let resource_create_3d = ResourceCreate3D {
528*bb4ee6a4SAndroid Build Coastguard Worker target: info.target.to_native(),
529*bb4ee6a4SAndroid Build Coastguard Worker format: info.format.to_native(),
530*bb4ee6a4SAndroid Build Coastguard Worker bind: info.bind.to_native(),
531*bb4ee6a4SAndroid Build Coastguard Worker width: info.width.to_native(),
532*bb4ee6a4SAndroid Build Coastguard Worker height: info.height.to_native(),
533*bb4ee6a4SAndroid Build Coastguard Worker depth: info.depth.to_native(),
534*bb4ee6a4SAndroid Build Coastguard Worker array_size: info.array_size.to_native(),
535*bb4ee6a4SAndroid Build Coastguard Worker last_level: info.last_level.to_native(),
536*bb4ee6a4SAndroid Build Coastguard Worker nr_samples: info.nr_samples.to_native(),
537*bb4ee6a4SAndroid Build Coastguard Worker flags: info.flags.to_native(),
538*bb4ee6a4SAndroid Build Coastguard Worker };
539*bb4ee6a4SAndroid Build Coastguard Worker
540*bb4ee6a4SAndroid Build Coastguard Worker self.virtio_gpu
541*bb4ee6a4SAndroid Build Coastguard Worker .resource_create_3d(resource_id, resource_create_3d)
542*bb4ee6a4SAndroid Build Coastguard Worker }
543*bb4ee6a4SAndroid Build Coastguard Worker GpuCommand::TransferToHost3d(info) => {
544*bb4ee6a4SAndroid Build Coastguard Worker let ctx_id = info.hdr.ctx_id.to_native();
545*bb4ee6a4SAndroid Build Coastguard Worker let resource_id = info.resource_id.to_native();
546*bb4ee6a4SAndroid Build Coastguard Worker
547*bb4ee6a4SAndroid Build Coastguard Worker let transfer = Transfer3D {
548*bb4ee6a4SAndroid Build Coastguard Worker x: info.box_.x.to_native(),
549*bb4ee6a4SAndroid Build Coastguard Worker y: info.box_.y.to_native(),
550*bb4ee6a4SAndroid Build Coastguard Worker z: info.box_.z.to_native(),
551*bb4ee6a4SAndroid Build Coastguard Worker w: info.box_.w.to_native(),
552*bb4ee6a4SAndroid Build Coastguard Worker h: info.box_.h.to_native(),
553*bb4ee6a4SAndroid Build Coastguard Worker d: info.box_.d.to_native(),
554*bb4ee6a4SAndroid Build Coastguard Worker level: info.level.to_native(),
555*bb4ee6a4SAndroid Build Coastguard Worker stride: info.stride.to_native(),
556*bb4ee6a4SAndroid Build Coastguard Worker layer_stride: info.layer_stride.to_native(),
557*bb4ee6a4SAndroid Build Coastguard Worker offset: info.offset.to_native(),
558*bb4ee6a4SAndroid Build Coastguard Worker };
559*bb4ee6a4SAndroid Build Coastguard Worker
560*bb4ee6a4SAndroid Build Coastguard Worker self.virtio_gpu
561*bb4ee6a4SAndroid Build Coastguard Worker .transfer_write(ctx_id, resource_id, transfer)
562*bb4ee6a4SAndroid Build Coastguard Worker }
563*bb4ee6a4SAndroid Build Coastguard Worker GpuCommand::TransferFromHost3d(info) => {
564*bb4ee6a4SAndroid Build Coastguard Worker let ctx_id = info.hdr.ctx_id.to_native();
565*bb4ee6a4SAndroid Build Coastguard Worker let resource_id = info.resource_id.to_native();
566*bb4ee6a4SAndroid Build Coastguard Worker
567*bb4ee6a4SAndroid Build Coastguard Worker let transfer = Transfer3D {
568*bb4ee6a4SAndroid Build Coastguard Worker x: info.box_.x.to_native(),
569*bb4ee6a4SAndroid Build Coastguard Worker y: info.box_.y.to_native(),
570*bb4ee6a4SAndroid Build Coastguard Worker z: info.box_.z.to_native(),
571*bb4ee6a4SAndroid Build Coastguard Worker w: info.box_.w.to_native(),
572*bb4ee6a4SAndroid Build Coastguard Worker h: info.box_.h.to_native(),
573*bb4ee6a4SAndroid Build Coastguard Worker d: info.box_.d.to_native(),
574*bb4ee6a4SAndroid Build Coastguard Worker level: info.level.to_native(),
575*bb4ee6a4SAndroid Build Coastguard Worker stride: info.stride.to_native(),
576*bb4ee6a4SAndroid Build Coastguard Worker layer_stride: info.layer_stride.to_native(),
577*bb4ee6a4SAndroid Build Coastguard Worker offset: info.offset.to_native(),
578*bb4ee6a4SAndroid Build Coastguard Worker };
579*bb4ee6a4SAndroid Build Coastguard Worker
580*bb4ee6a4SAndroid Build Coastguard Worker self.virtio_gpu
581*bb4ee6a4SAndroid Build Coastguard Worker .transfer_read(ctx_id, resource_id, transfer, None)
582*bb4ee6a4SAndroid Build Coastguard Worker }
583*bb4ee6a4SAndroid Build Coastguard Worker GpuCommand::CmdSubmit3d(info) => {
584*bb4ee6a4SAndroid Build Coastguard Worker if reader.available_bytes() != 0 {
585*bb4ee6a4SAndroid Build Coastguard Worker let num_in_fences = info.num_in_fences.to_native() as usize;
586*bb4ee6a4SAndroid Build Coastguard Worker let cmd_size = info.size.to_native() as usize;
587*bb4ee6a4SAndroid Build Coastguard Worker let mut cmd_buf = vec![0; cmd_size];
588*bb4ee6a4SAndroid Build Coastguard Worker let mut fence_ids: Vec<u64> = Vec::with_capacity(num_in_fences);
589*bb4ee6a4SAndroid Build Coastguard Worker let ctx_id = info.hdr.ctx_id.to_native();
590*bb4ee6a4SAndroid Build Coastguard Worker
591*bb4ee6a4SAndroid Build Coastguard Worker for _ in 0..num_in_fences {
592*bb4ee6a4SAndroid Build Coastguard Worker match reader.read_obj::<Le64>() {
593*bb4ee6a4SAndroid Build Coastguard Worker Ok(fence_id) => {
594*bb4ee6a4SAndroid Build Coastguard Worker fence_ids.push(fence_id.to_native());
595*bb4ee6a4SAndroid Build Coastguard Worker }
596*bb4ee6a4SAndroid Build Coastguard Worker Err(_) => return Err(GpuResponse::ErrUnspec),
597*bb4ee6a4SAndroid Build Coastguard Worker }
598*bb4ee6a4SAndroid Build Coastguard Worker }
599*bb4ee6a4SAndroid Build Coastguard Worker
600*bb4ee6a4SAndroid Build Coastguard Worker if reader.read_exact(&mut cmd_buf[..]).is_ok() {
601*bb4ee6a4SAndroid Build Coastguard Worker self.virtio_gpu
602*bb4ee6a4SAndroid Build Coastguard Worker .submit_command(ctx_id, &mut cmd_buf[..], &fence_ids[..])
603*bb4ee6a4SAndroid Build Coastguard Worker } else {
604*bb4ee6a4SAndroid Build Coastguard Worker Err(GpuResponse::ErrInvalidParameter)
605*bb4ee6a4SAndroid Build Coastguard Worker }
606*bb4ee6a4SAndroid Build Coastguard Worker } else {
607*bb4ee6a4SAndroid Build Coastguard Worker // Silently accept empty command buffers to allow for
608*bb4ee6a4SAndroid Build Coastguard Worker // benchmarking.
609*bb4ee6a4SAndroid Build Coastguard Worker Ok(GpuResponse::OkNoData)
610*bb4ee6a4SAndroid Build Coastguard Worker }
611*bb4ee6a4SAndroid Build Coastguard Worker }
612*bb4ee6a4SAndroid Build Coastguard Worker GpuCommand::ResourceCreateBlob(info) => {
613*bb4ee6a4SAndroid Build Coastguard Worker let resource_id = info.resource_id.to_native();
614*bb4ee6a4SAndroid Build Coastguard Worker let ctx_id = info.hdr.ctx_id.to_native();
615*bb4ee6a4SAndroid Build Coastguard Worker
616*bb4ee6a4SAndroid Build Coastguard Worker let resource_create_blob = ResourceCreateBlob {
617*bb4ee6a4SAndroid Build Coastguard Worker blob_mem: info.blob_mem.to_native(),
618*bb4ee6a4SAndroid Build Coastguard Worker blob_flags: info.blob_flags.to_native(),
619*bb4ee6a4SAndroid Build Coastguard Worker blob_id: info.blob_id.to_native(),
620*bb4ee6a4SAndroid Build Coastguard Worker size: info.size.to_native(),
621*bb4ee6a4SAndroid Build Coastguard Worker };
622*bb4ee6a4SAndroid Build Coastguard Worker
623*bb4ee6a4SAndroid Build Coastguard Worker let entry_count = info.nr_entries.to_native();
624*bb4ee6a4SAndroid Build Coastguard Worker if reader.available_bytes() == 0 && entry_count > 0 {
625*bb4ee6a4SAndroid Build Coastguard Worker return Err(GpuResponse::ErrUnspec);
626*bb4ee6a4SAndroid Build Coastguard Worker }
627*bb4ee6a4SAndroid Build Coastguard Worker
628*bb4ee6a4SAndroid Build Coastguard Worker let mut vecs = Vec::with_capacity(entry_count as usize);
629*bb4ee6a4SAndroid Build Coastguard Worker for _ in 0..entry_count {
630*bb4ee6a4SAndroid Build Coastguard Worker match reader.read_obj::<virtio_gpu_mem_entry>() {
631*bb4ee6a4SAndroid Build Coastguard Worker Ok(entry) => {
632*bb4ee6a4SAndroid Build Coastguard Worker let addr = GuestAddress(entry.addr.to_native());
633*bb4ee6a4SAndroid Build Coastguard Worker let len = entry.length.to_native() as usize;
634*bb4ee6a4SAndroid Build Coastguard Worker vecs.push((addr, len))
635*bb4ee6a4SAndroid Build Coastguard Worker }
636*bb4ee6a4SAndroid Build Coastguard Worker Err(_) => return Err(GpuResponse::ErrUnspec),
637*bb4ee6a4SAndroid Build Coastguard Worker }
638*bb4ee6a4SAndroid Build Coastguard Worker }
639*bb4ee6a4SAndroid Build Coastguard Worker
640*bb4ee6a4SAndroid Build Coastguard Worker self.virtio_gpu.resource_create_blob(
641*bb4ee6a4SAndroid Build Coastguard Worker ctx_id,
642*bb4ee6a4SAndroid Build Coastguard Worker resource_id,
643*bb4ee6a4SAndroid Build Coastguard Worker resource_create_blob,
644*bb4ee6a4SAndroid Build Coastguard Worker vecs,
645*bb4ee6a4SAndroid Build Coastguard Worker mem,
646*bb4ee6a4SAndroid Build Coastguard Worker )
647*bb4ee6a4SAndroid Build Coastguard Worker }
648*bb4ee6a4SAndroid Build Coastguard Worker GpuCommand::SetScanoutBlob(info) => {
649*bb4ee6a4SAndroid Build Coastguard Worker let scanout_id = info.scanout_id.to_native();
650*bb4ee6a4SAndroid Build Coastguard Worker let resource_id = info.resource_id.to_native();
651*bb4ee6a4SAndroid Build Coastguard Worker let virtio_gpu_format = info.format.to_native();
652*bb4ee6a4SAndroid Build Coastguard Worker let width = info.width.to_native();
653*bb4ee6a4SAndroid Build Coastguard Worker let height = info.height.to_native();
654*bb4ee6a4SAndroid Build Coastguard Worker let mut strides: [u32; 4] = [0; 4];
655*bb4ee6a4SAndroid Build Coastguard Worker let mut offsets: [u32; 4] = [0; 4];
656*bb4ee6a4SAndroid Build Coastguard Worker
657*bb4ee6a4SAndroid Build Coastguard Worker // As of v4.19, virtio-gpu kms only really uses these formats. If that changes,
658*bb4ee6a4SAndroid Build Coastguard Worker // the following may have to change too.
659*bb4ee6a4SAndroid Build Coastguard Worker let drm_format = match virtio_gpu_format {
660*bb4ee6a4SAndroid Build Coastguard Worker VIRTIO_GPU_FORMAT_B8G8R8X8_UNORM => DrmFormat::new(b'X', b'R', b'2', b'4'),
661*bb4ee6a4SAndroid Build Coastguard Worker VIRTIO_GPU_FORMAT_B8G8R8A8_UNORM => DrmFormat::new(b'A', b'R', b'2', b'4'),
662*bb4ee6a4SAndroid Build Coastguard Worker _ => {
663*bb4ee6a4SAndroid Build Coastguard Worker error!("unrecognized virtio-gpu format {}", virtio_gpu_format);
664*bb4ee6a4SAndroid Build Coastguard Worker return Err(GpuResponse::ErrUnspec);
665*bb4ee6a4SAndroid Build Coastguard Worker }
666*bb4ee6a4SAndroid Build Coastguard Worker };
667*bb4ee6a4SAndroid Build Coastguard Worker
668*bb4ee6a4SAndroid Build Coastguard Worker for plane_index in 0..PLANE_INFO_MAX_COUNT {
669*bb4ee6a4SAndroid Build Coastguard Worker offsets[plane_index] = info.offsets[plane_index].to_native();
670*bb4ee6a4SAndroid Build Coastguard Worker strides[plane_index] = info.strides[plane_index].to_native();
671*bb4ee6a4SAndroid Build Coastguard Worker }
672*bb4ee6a4SAndroid Build Coastguard Worker
673*bb4ee6a4SAndroid Build Coastguard Worker let scanout = VirtioScanoutBlobData {
674*bb4ee6a4SAndroid Build Coastguard Worker width,
675*bb4ee6a4SAndroid Build Coastguard Worker height,
676*bb4ee6a4SAndroid Build Coastguard Worker drm_format,
677*bb4ee6a4SAndroid Build Coastguard Worker strides,
678*bb4ee6a4SAndroid Build Coastguard Worker offsets,
679*bb4ee6a4SAndroid Build Coastguard Worker };
680*bb4ee6a4SAndroid Build Coastguard Worker
681*bb4ee6a4SAndroid Build Coastguard Worker self.virtio_gpu
682*bb4ee6a4SAndroid Build Coastguard Worker .set_scanout(scanout_id, resource_id, Some(scanout))
683*bb4ee6a4SAndroid Build Coastguard Worker }
684*bb4ee6a4SAndroid Build Coastguard Worker GpuCommand::ResourceMapBlob(info) => {
685*bb4ee6a4SAndroid Build Coastguard Worker let resource_id = info.resource_id.to_native();
686*bb4ee6a4SAndroid Build Coastguard Worker let offset = info.offset.to_native();
687*bb4ee6a4SAndroid Build Coastguard Worker self.virtio_gpu.resource_map_blob(resource_id, offset)
688*bb4ee6a4SAndroid Build Coastguard Worker }
689*bb4ee6a4SAndroid Build Coastguard Worker GpuCommand::ResourceUnmapBlob(info) => {
690*bb4ee6a4SAndroid Build Coastguard Worker let resource_id = info.resource_id.to_native();
691*bb4ee6a4SAndroid Build Coastguard Worker self.virtio_gpu.resource_unmap_blob(resource_id)
692*bb4ee6a4SAndroid Build Coastguard Worker }
693*bb4ee6a4SAndroid Build Coastguard Worker GpuCommand::GetEdid(info) => self.virtio_gpu.get_edid(info.scanout.to_native()),
694*bb4ee6a4SAndroid Build Coastguard Worker }
695*bb4ee6a4SAndroid Build Coastguard Worker }
696*bb4ee6a4SAndroid Build Coastguard Worker
697*bb4ee6a4SAndroid Build Coastguard Worker /// Processes virtio messages on `queue`.
process_queue(&mut self, mem: &GuestMemory, queue: &dyn QueueReader) -> bool698*bb4ee6a4SAndroid Build Coastguard Worker pub fn process_queue(&mut self, mem: &GuestMemory, queue: &dyn QueueReader) -> bool {
699*bb4ee6a4SAndroid Build Coastguard Worker let mut signal_used = false;
700*bb4ee6a4SAndroid Build Coastguard Worker while let Some(desc) = queue.pop() {
701*bb4ee6a4SAndroid Build Coastguard Worker if let Some(ret_desc) = self.process_descriptor(mem, desc) {
702*bb4ee6a4SAndroid Build Coastguard Worker queue.add_used(ret_desc.desc_chain, ret_desc.len);
703*bb4ee6a4SAndroid Build Coastguard Worker signal_used = true;
704*bb4ee6a4SAndroid Build Coastguard Worker }
705*bb4ee6a4SAndroid Build Coastguard Worker }
706*bb4ee6a4SAndroid Build Coastguard Worker
707*bb4ee6a4SAndroid Build Coastguard Worker signal_used
708*bb4ee6a4SAndroid Build Coastguard Worker }
709*bb4ee6a4SAndroid Build Coastguard Worker
process_descriptor( &mut self, mem: &GuestMemory, mut desc_chain: DescriptorChain, ) -> Option<ReturnDescriptor>710*bb4ee6a4SAndroid Build Coastguard Worker fn process_descriptor(
711*bb4ee6a4SAndroid Build Coastguard Worker &mut self,
712*bb4ee6a4SAndroid Build Coastguard Worker mem: &GuestMemory,
713*bb4ee6a4SAndroid Build Coastguard Worker mut desc_chain: DescriptorChain,
714*bb4ee6a4SAndroid Build Coastguard Worker ) -> Option<ReturnDescriptor> {
715*bb4ee6a4SAndroid Build Coastguard Worker let reader = &mut desc_chain.reader;
716*bb4ee6a4SAndroid Build Coastguard Worker let writer = &mut desc_chain.writer;
717*bb4ee6a4SAndroid Build Coastguard Worker let mut resp = Err(GpuResponse::ErrUnspec);
718*bb4ee6a4SAndroid Build Coastguard Worker let mut gpu_cmd = None;
719*bb4ee6a4SAndroid Build Coastguard Worker let mut len = 0;
720*bb4ee6a4SAndroid Build Coastguard Worker match GpuCommand::decode(reader) {
721*bb4ee6a4SAndroid Build Coastguard Worker Ok(cmd) => {
722*bb4ee6a4SAndroid Build Coastguard Worker resp = self.process_gpu_command(mem, cmd, reader);
723*bb4ee6a4SAndroid Build Coastguard Worker gpu_cmd = Some(cmd);
724*bb4ee6a4SAndroid Build Coastguard Worker }
725*bb4ee6a4SAndroid Build Coastguard Worker Err(e) => debug!("descriptor decode error: {}", e),
726*bb4ee6a4SAndroid Build Coastguard Worker }
727*bb4ee6a4SAndroid Build Coastguard Worker
728*bb4ee6a4SAndroid Build Coastguard Worker let mut gpu_response = match resp {
729*bb4ee6a4SAndroid Build Coastguard Worker Ok(gpu_response) => gpu_response,
730*bb4ee6a4SAndroid Build Coastguard Worker Err(gpu_response) => {
731*bb4ee6a4SAndroid Build Coastguard Worker if let Some(gpu_cmd) = gpu_cmd {
732*bb4ee6a4SAndroid Build Coastguard Worker error!(
733*bb4ee6a4SAndroid Build Coastguard Worker "error processing gpu command {:?}: {:?}",
734*bb4ee6a4SAndroid Build Coastguard Worker gpu_cmd, gpu_response
735*bb4ee6a4SAndroid Build Coastguard Worker );
736*bb4ee6a4SAndroid Build Coastguard Worker }
737*bb4ee6a4SAndroid Build Coastguard Worker gpu_response
738*bb4ee6a4SAndroid Build Coastguard Worker }
739*bb4ee6a4SAndroid Build Coastguard Worker };
740*bb4ee6a4SAndroid Build Coastguard Worker
741*bb4ee6a4SAndroid Build Coastguard Worker if writer.available_bytes() != 0 {
742*bb4ee6a4SAndroid Build Coastguard Worker let mut fence_id = 0;
743*bb4ee6a4SAndroid Build Coastguard Worker let mut ctx_id = 0;
744*bb4ee6a4SAndroid Build Coastguard Worker let mut flags = 0;
745*bb4ee6a4SAndroid Build Coastguard Worker let mut ring_idx = 0;
746*bb4ee6a4SAndroid Build Coastguard Worker if let Some(cmd) = gpu_cmd {
747*bb4ee6a4SAndroid Build Coastguard Worker let ctrl_hdr = cmd.ctrl_hdr();
748*bb4ee6a4SAndroid Build Coastguard Worker if ctrl_hdr.flags.to_native() & VIRTIO_GPU_FLAG_FENCE != 0 {
749*bb4ee6a4SAndroid Build Coastguard Worker flags = ctrl_hdr.flags.to_native();
750*bb4ee6a4SAndroid Build Coastguard Worker fence_id = ctrl_hdr.fence_id.to_native();
751*bb4ee6a4SAndroid Build Coastguard Worker ctx_id = ctrl_hdr.ctx_id.to_native();
752*bb4ee6a4SAndroid Build Coastguard Worker ring_idx = ctrl_hdr.ring_idx;
753*bb4ee6a4SAndroid Build Coastguard Worker
754*bb4ee6a4SAndroid Build Coastguard Worker let fence = RutabagaFence {
755*bb4ee6a4SAndroid Build Coastguard Worker flags,
756*bb4ee6a4SAndroid Build Coastguard Worker fence_id,
757*bb4ee6a4SAndroid Build Coastguard Worker ctx_id,
758*bb4ee6a4SAndroid Build Coastguard Worker ring_idx,
759*bb4ee6a4SAndroid Build Coastguard Worker };
760*bb4ee6a4SAndroid Build Coastguard Worker gpu_response = match self.virtio_gpu.create_fence(fence) {
761*bb4ee6a4SAndroid Build Coastguard Worker Ok(_) => gpu_response,
762*bb4ee6a4SAndroid Build Coastguard Worker Err(fence_resp) => {
763*bb4ee6a4SAndroid Build Coastguard Worker warn!("create_fence {} -> {:?}", fence_id, fence_resp);
764*bb4ee6a4SAndroid Build Coastguard Worker fence_resp
765*bb4ee6a4SAndroid Build Coastguard Worker }
766*bb4ee6a4SAndroid Build Coastguard Worker };
767*bb4ee6a4SAndroid Build Coastguard Worker }
768*bb4ee6a4SAndroid Build Coastguard Worker }
769*bb4ee6a4SAndroid Build Coastguard Worker
770*bb4ee6a4SAndroid Build Coastguard Worker // Prepare the response now, even if it is going to wait until
771*bb4ee6a4SAndroid Build Coastguard Worker // fence is complete.
772*bb4ee6a4SAndroid Build Coastguard Worker match gpu_response.encode(flags, fence_id, ctx_id, ring_idx, writer) {
773*bb4ee6a4SAndroid Build Coastguard Worker Ok(l) => len = l,
774*bb4ee6a4SAndroid Build Coastguard Worker Err(e) => debug!("ctrl queue response encode error: {}", e),
775*bb4ee6a4SAndroid Build Coastguard Worker }
776*bb4ee6a4SAndroid Build Coastguard Worker
777*bb4ee6a4SAndroid Build Coastguard Worker if flags & VIRTIO_GPU_FLAG_FENCE != 0 {
778*bb4ee6a4SAndroid Build Coastguard Worker let ring = match flags & VIRTIO_GPU_FLAG_INFO_RING_IDX {
779*bb4ee6a4SAndroid Build Coastguard Worker 0 => VirtioGpuRing::Global,
780*bb4ee6a4SAndroid Build Coastguard Worker _ => VirtioGpuRing::ContextSpecific { ctx_id, ring_idx },
781*bb4ee6a4SAndroid Build Coastguard Worker };
782*bb4ee6a4SAndroid Build Coastguard Worker
783*bb4ee6a4SAndroid Build Coastguard Worker // In case the fence is signaled immediately after creation, don't add a return
784*bb4ee6a4SAndroid Build Coastguard Worker // FenceDescriptor.
785*bb4ee6a4SAndroid Build Coastguard Worker let mut fence_state = self.fence_state.lock();
786*bb4ee6a4SAndroid Build Coastguard Worker if fence_id > *fence_state.completed_fences.get(&ring).unwrap_or(&0) {
787*bb4ee6a4SAndroid Build Coastguard Worker fence_state.descs.push(FenceDescriptor {
788*bb4ee6a4SAndroid Build Coastguard Worker ring,
789*bb4ee6a4SAndroid Build Coastguard Worker fence_id,
790*bb4ee6a4SAndroid Build Coastguard Worker desc_chain,
791*bb4ee6a4SAndroid Build Coastguard Worker len,
792*bb4ee6a4SAndroid Build Coastguard Worker });
793*bb4ee6a4SAndroid Build Coastguard Worker
794*bb4ee6a4SAndroid Build Coastguard Worker return None;
795*bb4ee6a4SAndroid Build Coastguard Worker }
796*bb4ee6a4SAndroid Build Coastguard Worker }
797*bb4ee6a4SAndroid Build Coastguard Worker
798*bb4ee6a4SAndroid Build Coastguard Worker // No fence (or already completed fence), respond now.
799*bb4ee6a4SAndroid Build Coastguard Worker }
800*bb4ee6a4SAndroid Build Coastguard Worker Some(ReturnDescriptor { desc_chain, len })
801*bb4ee6a4SAndroid Build Coastguard Worker }
802*bb4ee6a4SAndroid Build Coastguard Worker
event_poll(&self)803*bb4ee6a4SAndroid Build Coastguard Worker pub fn event_poll(&self) {
804*bb4ee6a4SAndroid Build Coastguard Worker self.virtio_gpu.event_poll();
805*bb4ee6a4SAndroid Build Coastguard Worker }
806*bb4ee6a4SAndroid Build Coastguard Worker }
807*bb4ee6a4SAndroid Build Coastguard Worker
808*bb4ee6a4SAndroid Build Coastguard Worker #[derive(EventToken, PartialEq, Eq, Clone, Copy, Debug)]
809*bb4ee6a4SAndroid Build Coastguard Worker enum WorkerToken {
810*bb4ee6a4SAndroid Build Coastguard Worker CtrlQueue,
811*bb4ee6a4SAndroid Build Coastguard Worker CursorQueue,
812*bb4ee6a4SAndroid Build Coastguard Worker Display,
813*bb4ee6a4SAndroid Build Coastguard Worker GpuControl,
814*bb4ee6a4SAndroid Build Coastguard Worker InterruptResample,
815*bb4ee6a4SAndroid Build Coastguard Worker Sleep,
816*bb4ee6a4SAndroid Build Coastguard Worker Kill,
817*bb4ee6a4SAndroid Build Coastguard Worker ResourceBridge {
818*bb4ee6a4SAndroid Build Coastguard Worker index: usize,
819*bb4ee6a4SAndroid Build Coastguard Worker },
820*bb4ee6a4SAndroid Build Coastguard Worker VirtioGpuPoll,
821*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(windows)]
822*bb4ee6a4SAndroid Build Coastguard Worker DisplayDescriptorRequest,
823*bb4ee6a4SAndroid Build Coastguard Worker }
824*bb4ee6a4SAndroid Build Coastguard Worker
825*bb4ee6a4SAndroid Build Coastguard Worker struct EventManager<'a> {
826*bb4ee6a4SAndroid Build Coastguard Worker pub wait_ctx: WaitContext<WorkerToken>,
827*bb4ee6a4SAndroid Build Coastguard Worker events: Vec<(&'a dyn AsRawDescriptor, WorkerToken)>,
828*bb4ee6a4SAndroid Build Coastguard Worker }
829*bb4ee6a4SAndroid Build Coastguard Worker
830*bb4ee6a4SAndroid Build Coastguard Worker impl<'a> EventManager<'a> {
new() -> Result<EventManager<'a>>831*bb4ee6a4SAndroid Build Coastguard Worker pub fn new() -> Result<EventManager<'a>> {
832*bb4ee6a4SAndroid Build Coastguard Worker Ok(EventManager {
833*bb4ee6a4SAndroid Build Coastguard Worker wait_ctx: WaitContext::new()?,
834*bb4ee6a4SAndroid Build Coastguard Worker events: vec![],
835*bb4ee6a4SAndroid Build Coastguard Worker })
836*bb4ee6a4SAndroid Build Coastguard Worker }
837*bb4ee6a4SAndroid Build Coastguard Worker
build_with( triggers: &[(&'a dyn AsRawDescriptor, WorkerToken)], ) -> Result<EventManager<'a>>838*bb4ee6a4SAndroid Build Coastguard Worker pub fn build_with(
839*bb4ee6a4SAndroid Build Coastguard Worker triggers: &[(&'a dyn AsRawDescriptor, WorkerToken)],
840*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<EventManager<'a>> {
841*bb4ee6a4SAndroid Build Coastguard Worker let mut manager = EventManager::new()?;
842*bb4ee6a4SAndroid Build Coastguard Worker manager.wait_ctx.add_many(triggers)?;
843*bb4ee6a4SAndroid Build Coastguard Worker
844*bb4ee6a4SAndroid Build Coastguard Worker for (descriptor, token) in triggers {
845*bb4ee6a4SAndroid Build Coastguard Worker manager.events.push((*descriptor, *token));
846*bb4ee6a4SAndroid Build Coastguard Worker }
847*bb4ee6a4SAndroid Build Coastguard Worker Ok(manager)
848*bb4ee6a4SAndroid Build Coastguard Worker }
849*bb4ee6a4SAndroid Build Coastguard Worker
add(&mut self, descriptor: &'a dyn AsRawDescriptor, token: WorkerToken) -> Result<()>850*bb4ee6a4SAndroid Build Coastguard Worker pub fn add(&mut self, descriptor: &'a dyn AsRawDescriptor, token: WorkerToken) -> Result<()> {
851*bb4ee6a4SAndroid Build Coastguard Worker self.wait_ctx.add(descriptor, token)?;
852*bb4ee6a4SAndroid Build Coastguard Worker self.events.push((descriptor, token));
853*bb4ee6a4SAndroid Build Coastguard Worker Ok(())
854*bb4ee6a4SAndroid Build Coastguard Worker }
855*bb4ee6a4SAndroid Build Coastguard Worker
delete(&mut self, token: WorkerToken)856*bb4ee6a4SAndroid Build Coastguard Worker pub fn delete(&mut self, token: WorkerToken) {
857*bb4ee6a4SAndroid Build Coastguard Worker self.events.retain(|event| {
858*bb4ee6a4SAndroid Build Coastguard Worker if event.1 == token {
859*bb4ee6a4SAndroid Build Coastguard Worker self.wait_ctx.delete(event.0).ok();
860*bb4ee6a4SAndroid Build Coastguard Worker return false;
861*bb4ee6a4SAndroid Build Coastguard Worker }
862*bb4ee6a4SAndroid Build Coastguard Worker true
863*bb4ee6a4SAndroid Build Coastguard Worker });
864*bb4ee6a4SAndroid Build Coastguard Worker }
865*bb4ee6a4SAndroid Build Coastguard Worker }
866*bb4ee6a4SAndroid Build Coastguard Worker
867*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Serialize, Deserialize)]
868*bb4ee6a4SAndroid Build Coastguard Worker struct WorkerSnapshot {
869*bb4ee6a4SAndroid Build Coastguard Worker fence_state_snapshot: FenceStateSnapshot,
870*bb4ee6a4SAndroid Build Coastguard Worker virtio_gpu_snapshot: VirtioGpuSnapshot,
871*bb4ee6a4SAndroid Build Coastguard Worker }
872*bb4ee6a4SAndroid Build Coastguard Worker
873*bb4ee6a4SAndroid Build Coastguard Worker struct WorkerActivateRequest {
874*bb4ee6a4SAndroid Build Coastguard Worker resources: GpuActivationResources,
875*bb4ee6a4SAndroid Build Coastguard Worker }
876*bb4ee6a4SAndroid Build Coastguard Worker
877*bb4ee6a4SAndroid Build Coastguard Worker enum WorkerRequest {
878*bb4ee6a4SAndroid Build Coastguard Worker Activate(WorkerActivateRequest),
879*bb4ee6a4SAndroid Build Coastguard Worker Suspend,
880*bb4ee6a4SAndroid Build Coastguard Worker Snapshot,
881*bb4ee6a4SAndroid Build Coastguard Worker Restore(WorkerSnapshot),
882*bb4ee6a4SAndroid Build Coastguard Worker }
883*bb4ee6a4SAndroid Build Coastguard Worker
884*bb4ee6a4SAndroid Build Coastguard Worker enum WorkerResponse {
885*bb4ee6a4SAndroid Build Coastguard Worker Ok,
886*bb4ee6a4SAndroid Build Coastguard Worker Suspend(GpuDeactivationResources),
887*bb4ee6a4SAndroid Build Coastguard Worker Snapshot(WorkerSnapshot),
888*bb4ee6a4SAndroid Build Coastguard Worker }
889*bb4ee6a4SAndroid Build Coastguard Worker
890*bb4ee6a4SAndroid Build Coastguard Worker struct GpuActivationResources {
891*bb4ee6a4SAndroid Build Coastguard Worker mem: GuestMemory,
892*bb4ee6a4SAndroid Build Coastguard Worker interrupt: Interrupt,
893*bb4ee6a4SAndroid Build Coastguard Worker ctrl_queue: SharedQueueReader,
894*bb4ee6a4SAndroid Build Coastguard Worker cursor_queue: LocalQueueReader,
895*bb4ee6a4SAndroid Build Coastguard Worker }
896*bb4ee6a4SAndroid Build Coastguard Worker
897*bb4ee6a4SAndroid Build Coastguard Worker struct GpuDeactivationResources {
898*bb4ee6a4SAndroid Build Coastguard Worker queues: Option<Vec<Queue>>,
899*bb4ee6a4SAndroid Build Coastguard Worker }
900*bb4ee6a4SAndroid Build Coastguard Worker
901*bb4ee6a4SAndroid Build Coastguard Worker struct Worker {
902*bb4ee6a4SAndroid Build Coastguard Worker request_receiver: mpsc::Receiver<WorkerRequest>,
903*bb4ee6a4SAndroid Build Coastguard Worker response_sender: mpsc::Sender<anyhow::Result<WorkerResponse>>,
904*bb4ee6a4SAndroid Build Coastguard Worker exit_evt_wrtube: SendTube,
905*bb4ee6a4SAndroid Build Coastguard Worker gpu_control_tube: Tube,
906*bb4ee6a4SAndroid Build Coastguard Worker resource_bridges: ResourceBridges,
907*bb4ee6a4SAndroid Build Coastguard Worker suspend_evt: Event,
908*bb4ee6a4SAndroid Build Coastguard Worker kill_evt: Event,
909*bb4ee6a4SAndroid Build Coastguard Worker state: Frontend,
910*bb4ee6a4SAndroid Build Coastguard Worker fence_state: Arc<Mutex<FenceState>>,
911*bb4ee6a4SAndroid Build Coastguard Worker fence_handler_resources: Arc<Mutex<Option<FenceHandlerActivationResources<SharedQueueReader>>>>,
912*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(windows)]
913*bb4ee6a4SAndroid Build Coastguard Worker gpu_display_wait_descriptor_ctrl_rd: RecvTube,
914*bb4ee6a4SAndroid Build Coastguard Worker activation_resources: Option<GpuActivationResources>,
915*bb4ee6a4SAndroid Build Coastguard Worker }
916*bb4ee6a4SAndroid Build Coastguard Worker
917*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Copy, Clone)]
918*bb4ee6a4SAndroid Build Coastguard Worker enum WorkerStopReason {
919*bb4ee6a4SAndroid Build Coastguard Worker Sleep,
920*bb4ee6a4SAndroid Build Coastguard Worker Kill,
921*bb4ee6a4SAndroid Build Coastguard Worker }
922*bb4ee6a4SAndroid Build Coastguard Worker
923*bb4ee6a4SAndroid Build Coastguard Worker enum WorkerState {
924*bb4ee6a4SAndroid Build Coastguard Worker Inactive,
925*bb4ee6a4SAndroid Build Coastguard Worker Active,
926*bb4ee6a4SAndroid Build Coastguard Worker Error,
927*bb4ee6a4SAndroid Build Coastguard Worker }
928*bb4ee6a4SAndroid Build Coastguard Worker
929*bb4ee6a4SAndroid Build Coastguard Worker impl Worker {
new( rutabaga_builder: RutabagaBuilder, rutabaga_server_descriptor: Option<RutabagaDescriptor>, display_backends: Vec<DisplayBackend>, display_params: Vec<GpuDisplayParameters>, display_event: Arc<AtomicBool>, mapper: Arc<Mutex<Option<Box<dyn SharedMemoryMapper>>>>, event_devices: Vec<EventDevice>, external_blob: bool, fixed_blob_mapping: bool, udmabuf: bool, request_receiver: mpsc::Receiver<WorkerRequest>, response_sender: mpsc::Sender<anyhow::Result<WorkerResponse>>, exit_evt_wrtube: SendTube, gpu_control_tube: Tube, resource_bridges: ResourceBridges, suspend_evt: Event, kill_evt: Event, #[cfg(windows)] mut wndproc_thread: Option<WindowProcedureThread>, #[cfg(windows)] gpu_display_wait_descriptor_ctrl_rd: RecvTube, #[cfg(windows)] gpu_display_wait_descriptor_ctrl_wr: SendTube, ) -> anyhow::Result<Worker>930*bb4ee6a4SAndroid Build Coastguard Worker fn new(
931*bb4ee6a4SAndroid Build Coastguard Worker rutabaga_builder: RutabagaBuilder,
932*bb4ee6a4SAndroid Build Coastguard Worker rutabaga_server_descriptor: Option<RutabagaDescriptor>,
933*bb4ee6a4SAndroid Build Coastguard Worker display_backends: Vec<DisplayBackend>,
934*bb4ee6a4SAndroid Build Coastguard Worker display_params: Vec<GpuDisplayParameters>,
935*bb4ee6a4SAndroid Build Coastguard Worker display_event: Arc<AtomicBool>,
936*bb4ee6a4SAndroid Build Coastguard Worker mapper: Arc<Mutex<Option<Box<dyn SharedMemoryMapper>>>>,
937*bb4ee6a4SAndroid Build Coastguard Worker event_devices: Vec<EventDevice>,
938*bb4ee6a4SAndroid Build Coastguard Worker external_blob: bool,
939*bb4ee6a4SAndroid Build Coastguard Worker fixed_blob_mapping: bool,
940*bb4ee6a4SAndroid Build Coastguard Worker udmabuf: bool,
941*bb4ee6a4SAndroid Build Coastguard Worker request_receiver: mpsc::Receiver<WorkerRequest>,
942*bb4ee6a4SAndroid Build Coastguard Worker response_sender: mpsc::Sender<anyhow::Result<WorkerResponse>>,
943*bb4ee6a4SAndroid Build Coastguard Worker exit_evt_wrtube: SendTube,
944*bb4ee6a4SAndroid Build Coastguard Worker gpu_control_tube: Tube,
945*bb4ee6a4SAndroid Build Coastguard Worker resource_bridges: ResourceBridges,
946*bb4ee6a4SAndroid Build Coastguard Worker suspend_evt: Event,
947*bb4ee6a4SAndroid Build Coastguard Worker kill_evt: Event,
948*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(windows)] mut wndproc_thread: Option<WindowProcedureThread>,
949*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(windows)] gpu_display_wait_descriptor_ctrl_rd: RecvTube,
950*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(windows)] gpu_display_wait_descriptor_ctrl_wr: SendTube,
951*bb4ee6a4SAndroid Build Coastguard Worker ) -> anyhow::Result<Worker> {
952*bb4ee6a4SAndroid Build Coastguard Worker let fence_state = Arc::new(Mutex::new(Default::default()));
953*bb4ee6a4SAndroid Build Coastguard Worker let fence_handler_resources = Arc::new(Mutex::new(None));
954*bb4ee6a4SAndroid Build Coastguard Worker let fence_handler =
955*bb4ee6a4SAndroid Build Coastguard Worker create_fence_handler(fence_handler_resources.clone(), fence_state.clone());
956*bb4ee6a4SAndroid Build Coastguard Worker let rutabaga = rutabaga_builder.build(fence_handler, rutabaga_server_descriptor)?;
957*bb4ee6a4SAndroid Build Coastguard Worker let mut virtio_gpu = build(
958*bb4ee6a4SAndroid Build Coastguard Worker &display_backends,
959*bb4ee6a4SAndroid Build Coastguard Worker display_params,
960*bb4ee6a4SAndroid Build Coastguard Worker display_event,
961*bb4ee6a4SAndroid Build Coastguard Worker rutabaga,
962*bb4ee6a4SAndroid Build Coastguard Worker mapper,
963*bb4ee6a4SAndroid Build Coastguard Worker external_blob,
964*bb4ee6a4SAndroid Build Coastguard Worker fixed_blob_mapping,
965*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(windows)]
966*bb4ee6a4SAndroid Build Coastguard Worker &mut wndproc_thread,
967*bb4ee6a4SAndroid Build Coastguard Worker udmabuf,
968*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(windows)]
969*bb4ee6a4SAndroid Build Coastguard Worker gpu_display_wait_descriptor_ctrl_wr,
970*bb4ee6a4SAndroid Build Coastguard Worker )
971*bb4ee6a4SAndroid Build Coastguard Worker .ok_or_else(|| anyhow!("failed to build virtio gpu"))?;
972*bb4ee6a4SAndroid Build Coastguard Worker
973*bb4ee6a4SAndroid Build Coastguard Worker for event_device in event_devices {
974*bb4ee6a4SAndroid Build Coastguard Worker virtio_gpu
975*bb4ee6a4SAndroid Build Coastguard Worker .import_event_device(event_device)
976*bb4ee6a4SAndroid Build Coastguard Worker // We lost the `EventDevice`, so fail hard.
977*bb4ee6a4SAndroid Build Coastguard Worker .context("failed to import event device")?;
978*bb4ee6a4SAndroid Build Coastguard Worker }
979*bb4ee6a4SAndroid Build Coastguard Worker
980*bb4ee6a4SAndroid Build Coastguard Worker Ok(Worker {
981*bb4ee6a4SAndroid Build Coastguard Worker request_receiver,
982*bb4ee6a4SAndroid Build Coastguard Worker response_sender,
983*bb4ee6a4SAndroid Build Coastguard Worker exit_evt_wrtube,
984*bb4ee6a4SAndroid Build Coastguard Worker gpu_control_tube,
985*bb4ee6a4SAndroid Build Coastguard Worker resource_bridges,
986*bb4ee6a4SAndroid Build Coastguard Worker suspend_evt,
987*bb4ee6a4SAndroid Build Coastguard Worker kill_evt,
988*bb4ee6a4SAndroid Build Coastguard Worker state: Frontend::new(virtio_gpu, fence_state.clone()),
989*bb4ee6a4SAndroid Build Coastguard Worker fence_state,
990*bb4ee6a4SAndroid Build Coastguard Worker fence_handler_resources,
991*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(windows)]
992*bb4ee6a4SAndroid Build Coastguard Worker gpu_display_wait_descriptor_ctrl_rd,
993*bb4ee6a4SAndroid Build Coastguard Worker activation_resources: None,
994*bb4ee6a4SAndroid Build Coastguard Worker })
995*bb4ee6a4SAndroid Build Coastguard Worker }
996*bb4ee6a4SAndroid Build Coastguard Worker
run(&mut self)997*bb4ee6a4SAndroid Build Coastguard Worker fn run(&mut self) {
998*bb4ee6a4SAndroid Build Coastguard Worker // This loop effectively only runs while the worker is inactive. Once activated via
999*bb4ee6a4SAndroid Build Coastguard Worker // a `WorkerRequest::Activate`, the worker will remain in `run_until_sleep_or_exit()`
1000*bb4ee6a4SAndroid Build Coastguard Worker // until suspended via `kill_evt` or `suspend_evt` being signaled.
1001*bb4ee6a4SAndroid Build Coastguard Worker loop {
1002*bb4ee6a4SAndroid Build Coastguard Worker let request = match self.request_receiver.recv() {
1003*bb4ee6a4SAndroid Build Coastguard Worker Ok(r) => r,
1004*bb4ee6a4SAndroid Build Coastguard Worker Err(_) => {
1005*bb4ee6a4SAndroid Build Coastguard Worker info!("virtio gpu worker connection ended, exiting.");
1006*bb4ee6a4SAndroid Build Coastguard Worker return;
1007*bb4ee6a4SAndroid Build Coastguard Worker }
1008*bb4ee6a4SAndroid Build Coastguard Worker };
1009*bb4ee6a4SAndroid Build Coastguard Worker
1010*bb4ee6a4SAndroid Build Coastguard Worker match request {
1011*bb4ee6a4SAndroid Build Coastguard Worker WorkerRequest::Activate(request) => {
1012*bb4ee6a4SAndroid Build Coastguard Worker let response = self.on_activate(request).map(|_| WorkerResponse::Ok);
1013*bb4ee6a4SAndroid Build Coastguard Worker self.response_sender
1014*bb4ee6a4SAndroid Build Coastguard Worker .send(response)
1015*bb4ee6a4SAndroid Build Coastguard Worker .expect("failed to send gpu worker response for activate");
1016*bb4ee6a4SAndroid Build Coastguard Worker
1017*bb4ee6a4SAndroid Build Coastguard Worker let stop_reason = self
1018*bb4ee6a4SAndroid Build Coastguard Worker .run_until_sleep_or_exit()
1019*bb4ee6a4SAndroid Build Coastguard Worker .expect("failed to run gpu worker processing");
1020*bb4ee6a4SAndroid Build Coastguard Worker
1021*bb4ee6a4SAndroid Build Coastguard Worker if let WorkerStopReason::Kill = stop_reason {
1022*bb4ee6a4SAndroid Build Coastguard Worker break;
1023*bb4ee6a4SAndroid Build Coastguard Worker }
1024*bb4ee6a4SAndroid Build Coastguard Worker }
1025*bb4ee6a4SAndroid Build Coastguard Worker WorkerRequest::Suspend => {
1026*bb4ee6a4SAndroid Build Coastguard Worker let response = self.on_suspend().map(WorkerResponse::Suspend);
1027*bb4ee6a4SAndroid Build Coastguard Worker self.response_sender
1028*bb4ee6a4SAndroid Build Coastguard Worker .send(response)
1029*bb4ee6a4SAndroid Build Coastguard Worker .expect("failed to send gpu worker response for suspend");
1030*bb4ee6a4SAndroid Build Coastguard Worker }
1031*bb4ee6a4SAndroid Build Coastguard Worker WorkerRequest::Snapshot => {
1032*bb4ee6a4SAndroid Build Coastguard Worker let response = self.on_snapshot().map(WorkerResponse::Snapshot);
1033*bb4ee6a4SAndroid Build Coastguard Worker self.response_sender
1034*bb4ee6a4SAndroid Build Coastguard Worker .send(response)
1035*bb4ee6a4SAndroid Build Coastguard Worker .expect("failed to send gpu worker response for snapshot");
1036*bb4ee6a4SAndroid Build Coastguard Worker }
1037*bb4ee6a4SAndroid Build Coastguard Worker WorkerRequest::Restore(snapshot) => {
1038*bb4ee6a4SAndroid Build Coastguard Worker let response = self.on_restore(snapshot).map(|_| WorkerResponse::Ok);
1039*bb4ee6a4SAndroid Build Coastguard Worker self.response_sender
1040*bb4ee6a4SAndroid Build Coastguard Worker .send(response)
1041*bb4ee6a4SAndroid Build Coastguard Worker .expect("failed to send gpu worker response for restore");
1042*bb4ee6a4SAndroid Build Coastguard Worker }
1043*bb4ee6a4SAndroid Build Coastguard Worker }
1044*bb4ee6a4SAndroid Build Coastguard Worker }
1045*bb4ee6a4SAndroid Build Coastguard Worker }
1046*bb4ee6a4SAndroid Build Coastguard Worker
on_activate(&mut self, request: WorkerActivateRequest) -> anyhow::Result<()>1047*bb4ee6a4SAndroid Build Coastguard Worker fn on_activate(&mut self, request: WorkerActivateRequest) -> anyhow::Result<()> {
1048*bb4ee6a4SAndroid Build Coastguard Worker self.fence_handler_resources
1049*bb4ee6a4SAndroid Build Coastguard Worker .lock()
1050*bb4ee6a4SAndroid Build Coastguard Worker .replace(FenceHandlerActivationResources {
1051*bb4ee6a4SAndroid Build Coastguard Worker mem: request.resources.mem.clone(),
1052*bb4ee6a4SAndroid Build Coastguard Worker ctrl_queue: request.resources.ctrl_queue.clone(),
1053*bb4ee6a4SAndroid Build Coastguard Worker });
1054*bb4ee6a4SAndroid Build Coastguard Worker
1055*bb4ee6a4SAndroid Build Coastguard Worker self.state
1056*bb4ee6a4SAndroid Build Coastguard Worker .virtio_gpu
1057*bb4ee6a4SAndroid Build Coastguard Worker .resume(&request.resources.mem)
1058*bb4ee6a4SAndroid Build Coastguard Worker .context("gpu worker failed to activate virtio frontend")?;
1059*bb4ee6a4SAndroid Build Coastguard Worker
1060*bb4ee6a4SAndroid Build Coastguard Worker self.activation_resources = Some(request.resources);
1061*bb4ee6a4SAndroid Build Coastguard Worker
1062*bb4ee6a4SAndroid Build Coastguard Worker Ok(())
1063*bb4ee6a4SAndroid Build Coastguard Worker }
1064*bb4ee6a4SAndroid Build Coastguard Worker
on_suspend(&mut self) -> anyhow::Result<GpuDeactivationResources>1065*bb4ee6a4SAndroid Build Coastguard Worker fn on_suspend(&mut self) -> anyhow::Result<GpuDeactivationResources> {
1066*bb4ee6a4SAndroid Build Coastguard Worker self.state
1067*bb4ee6a4SAndroid Build Coastguard Worker .virtio_gpu
1068*bb4ee6a4SAndroid Build Coastguard Worker .suspend()
1069*bb4ee6a4SAndroid Build Coastguard Worker .context("failed to suspend VirtioGpu")?;
1070*bb4ee6a4SAndroid Build Coastguard Worker
1071*bb4ee6a4SAndroid Build Coastguard Worker self.fence_handler_resources.lock().take();
1072*bb4ee6a4SAndroid Build Coastguard Worker
1073*bb4ee6a4SAndroid Build Coastguard Worker let queues = if let Some(activation_resources) = self.activation_resources.take() {
1074*bb4ee6a4SAndroid Build Coastguard Worker Some(vec![
1075*bb4ee6a4SAndroid Build Coastguard Worker match Arc::try_unwrap(activation_resources.ctrl_queue.queue) {
1076*bb4ee6a4SAndroid Build Coastguard Worker Ok(x) => x.into_inner(),
1077*bb4ee6a4SAndroid Build Coastguard Worker Err(_) => panic!("too many refs on ctrl_queue"),
1078*bb4ee6a4SAndroid Build Coastguard Worker },
1079*bb4ee6a4SAndroid Build Coastguard Worker activation_resources.cursor_queue.queue.into_inner(),
1080*bb4ee6a4SAndroid Build Coastguard Worker ])
1081*bb4ee6a4SAndroid Build Coastguard Worker } else {
1082*bb4ee6a4SAndroid Build Coastguard Worker None
1083*bb4ee6a4SAndroid Build Coastguard Worker };
1084*bb4ee6a4SAndroid Build Coastguard Worker
1085*bb4ee6a4SAndroid Build Coastguard Worker Ok(GpuDeactivationResources { queues })
1086*bb4ee6a4SAndroid Build Coastguard Worker }
1087*bb4ee6a4SAndroid Build Coastguard Worker
on_snapshot(&mut self) -> anyhow::Result<WorkerSnapshot>1088*bb4ee6a4SAndroid Build Coastguard Worker fn on_snapshot(&mut self) -> anyhow::Result<WorkerSnapshot> {
1089*bb4ee6a4SAndroid Build Coastguard Worker Ok(WorkerSnapshot {
1090*bb4ee6a4SAndroid Build Coastguard Worker fence_state_snapshot: self.fence_state.lock().snapshot(),
1091*bb4ee6a4SAndroid Build Coastguard Worker virtio_gpu_snapshot: self
1092*bb4ee6a4SAndroid Build Coastguard Worker .state
1093*bb4ee6a4SAndroid Build Coastguard Worker .virtio_gpu
1094*bb4ee6a4SAndroid Build Coastguard Worker .snapshot()
1095*bb4ee6a4SAndroid Build Coastguard Worker .context("failed to snapshot VirtioGpu")?,
1096*bb4ee6a4SAndroid Build Coastguard Worker })
1097*bb4ee6a4SAndroid Build Coastguard Worker }
1098*bb4ee6a4SAndroid Build Coastguard Worker
on_restore(&mut self, snapshot: WorkerSnapshot) -> anyhow::Result<()>1099*bb4ee6a4SAndroid Build Coastguard Worker fn on_restore(&mut self, snapshot: WorkerSnapshot) -> anyhow::Result<()> {
1100*bb4ee6a4SAndroid Build Coastguard Worker self.fence_state
1101*bb4ee6a4SAndroid Build Coastguard Worker .lock()
1102*bb4ee6a4SAndroid Build Coastguard Worker .restore(snapshot.fence_state_snapshot);
1103*bb4ee6a4SAndroid Build Coastguard Worker
1104*bb4ee6a4SAndroid Build Coastguard Worker self.state
1105*bb4ee6a4SAndroid Build Coastguard Worker .virtio_gpu
1106*bb4ee6a4SAndroid Build Coastguard Worker .restore(snapshot.virtio_gpu_snapshot)
1107*bb4ee6a4SAndroid Build Coastguard Worker .context("failed to restore VirtioGpu")?;
1108*bb4ee6a4SAndroid Build Coastguard Worker
1109*bb4ee6a4SAndroid Build Coastguard Worker Ok(())
1110*bb4ee6a4SAndroid Build Coastguard Worker }
1111*bb4ee6a4SAndroid Build Coastguard Worker
run_until_sleep_or_exit(&mut self) -> anyhow::Result<WorkerStopReason>1112*bb4ee6a4SAndroid Build Coastguard Worker fn run_until_sleep_or_exit(&mut self) -> anyhow::Result<WorkerStopReason> {
1113*bb4ee6a4SAndroid Build Coastguard Worker let activation_resources = self
1114*bb4ee6a4SAndroid Build Coastguard Worker .activation_resources
1115*bb4ee6a4SAndroid Build Coastguard Worker .as_ref()
1116*bb4ee6a4SAndroid Build Coastguard Worker .context("virtio gpu worker missing activation resources")?;
1117*bb4ee6a4SAndroid Build Coastguard Worker
1118*bb4ee6a4SAndroid Build Coastguard Worker let display_desc =
1119*bb4ee6a4SAndroid Build Coastguard Worker SafeDescriptor::try_from(&*self.state.display().borrow() as &dyn AsRawDescriptor)
1120*bb4ee6a4SAndroid Build Coastguard Worker .context("failed getting event descriptor for display")?;
1121*bb4ee6a4SAndroid Build Coastguard Worker
1122*bb4ee6a4SAndroid Build Coastguard Worker let ctrl_evt = activation_resources
1123*bb4ee6a4SAndroid Build Coastguard Worker .ctrl_queue
1124*bb4ee6a4SAndroid Build Coastguard Worker .queue
1125*bb4ee6a4SAndroid Build Coastguard Worker .lock()
1126*bb4ee6a4SAndroid Build Coastguard Worker .event()
1127*bb4ee6a4SAndroid Build Coastguard Worker .try_clone()
1128*bb4ee6a4SAndroid Build Coastguard Worker .context("failed to clone queue event")?;
1129*bb4ee6a4SAndroid Build Coastguard Worker let cursor_evt = activation_resources
1130*bb4ee6a4SAndroid Build Coastguard Worker .cursor_queue
1131*bb4ee6a4SAndroid Build Coastguard Worker .queue
1132*bb4ee6a4SAndroid Build Coastguard Worker .borrow()
1133*bb4ee6a4SAndroid Build Coastguard Worker .event()
1134*bb4ee6a4SAndroid Build Coastguard Worker .try_clone()
1135*bb4ee6a4SAndroid Build Coastguard Worker .context("failed to clone queue event")?;
1136*bb4ee6a4SAndroid Build Coastguard Worker
1137*bb4ee6a4SAndroid Build Coastguard Worker let mut event_manager = EventManager::build_with(&[
1138*bb4ee6a4SAndroid Build Coastguard Worker (&ctrl_evt, WorkerToken::CtrlQueue),
1139*bb4ee6a4SAndroid Build Coastguard Worker (&cursor_evt, WorkerToken::CursorQueue),
1140*bb4ee6a4SAndroid Build Coastguard Worker (&display_desc, WorkerToken::Display),
1141*bb4ee6a4SAndroid Build Coastguard Worker (
1142*bb4ee6a4SAndroid Build Coastguard Worker self.gpu_control_tube.get_read_notifier(),
1143*bb4ee6a4SAndroid Build Coastguard Worker WorkerToken::GpuControl,
1144*bb4ee6a4SAndroid Build Coastguard Worker ),
1145*bb4ee6a4SAndroid Build Coastguard Worker (&self.suspend_evt, WorkerToken::Sleep),
1146*bb4ee6a4SAndroid Build Coastguard Worker (&self.kill_evt, WorkerToken::Kill),
1147*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(windows)]
1148*bb4ee6a4SAndroid Build Coastguard Worker (
1149*bb4ee6a4SAndroid Build Coastguard Worker self.gpu_display_wait_descriptor_ctrl_rd.get_read_notifier(),
1150*bb4ee6a4SAndroid Build Coastguard Worker WorkerToken::DisplayDescriptorRequest,
1151*bb4ee6a4SAndroid Build Coastguard Worker ),
1152*bb4ee6a4SAndroid Build Coastguard Worker ])
1153*bb4ee6a4SAndroid Build Coastguard Worker .context("failed creating gpu worker WaitContext")?;
1154*bb4ee6a4SAndroid Build Coastguard Worker
1155*bb4ee6a4SAndroid Build Coastguard Worker if let Some(resample_evt) = activation_resources.interrupt.get_resample_evt() {
1156*bb4ee6a4SAndroid Build Coastguard Worker event_manager
1157*bb4ee6a4SAndroid Build Coastguard Worker .add(resample_evt, WorkerToken::InterruptResample)
1158*bb4ee6a4SAndroid Build Coastguard Worker .context("failed adding interrupt resample event to WaitContext")?;
1159*bb4ee6a4SAndroid Build Coastguard Worker }
1160*bb4ee6a4SAndroid Build Coastguard Worker
1161*bb4ee6a4SAndroid Build Coastguard Worker let poll_desc: SafeDescriptor;
1162*bb4ee6a4SAndroid Build Coastguard Worker if let Some(desc) = self.state.virtio_gpu.poll_descriptor() {
1163*bb4ee6a4SAndroid Build Coastguard Worker poll_desc = desc;
1164*bb4ee6a4SAndroid Build Coastguard Worker event_manager
1165*bb4ee6a4SAndroid Build Coastguard Worker .add(&poll_desc, WorkerToken::VirtioGpuPoll)
1166*bb4ee6a4SAndroid Build Coastguard Worker .context("failed adding poll event to WaitContext")?;
1167*bb4ee6a4SAndroid Build Coastguard Worker }
1168*bb4ee6a4SAndroid Build Coastguard Worker
1169*bb4ee6a4SAndroid Build Coastguard Worker self.resource_bridges
1170*bb4ee6a4SAndroid Build Coastguard Worker .add_to_wait_context(&mut event_manager.wait_ctx);
1171*bb4ee6a4SAndroid Build Coastguard Worker
1172*bb4ee6a4SAndroid Build Coastguard Worker // TODO(davidriley): The entire main loop processing is somewhat racey and incorrect with
1173*bb4ee6a4SAndroid Build Coastguard Worker // respect to cursor vs control queue processing. As both currently and originally
1174*bb4ee6a4SAndroid Build Coastguard Worker // written, while the control queue is only processed/read from after the the cursor queue
1175*bb4ee6a4SAndroid Build Coastguard Worker // is finished, the entire queue will be processed at that time. The end effect of this
1176*bb4ee6a4SAndroid Build Coastguard Worker // racyiness is that control queue descriptors that are issued after cursors descriptors
1177*bb4ee6a4SAndroid Build Coastguard Worker // might be handled first instead of the other way around. In practice, the cursor queue
1178*bb4ee6a4SAndroid Build Coastguard Worker // isn't used so this isn't a huge issue.
1179*bb4ee6a4SAndroid Build Coastguard Worker
1180*bb4ee6a4SAndroid Build Coastguard Worker loop {
1181*bb4ee6a4SAndroid Build Coastguard Worker let events = event_manager
1182*bb4ee6a4SAndroid Build Coastguard Worker .wait_ctx
1183*bb4ee6a4SAndroid Build Coastguard Worker .wait()
1184*bb4ee6a4SAndroid Build Coastguard Worker .context("failed polling for gpu worker events")?;
1185*bb4ee6a4SAndroid Build Coastguard Worker
1186*bb4ee6a4SAndroid Build Coastguard Worker let mut signal_used_cursor = false;
1187*bb4ee6a4SAndroid Build Coastguard Worker let mut signal_used_ctrl = false;
1188*bb4ee6a4SAndroid Build Coastguard Worker let mut ctrl_available = false;
1189*bb4ee6a4SAndroid Build Coastguard Worker let mut display_available = false;
1190*bb4ee6a4SAndroid Build Coastguard Worker let mut needs_config_interrupt = false;
1191*bb4ee6a4SAndroid Build Coastguard Worker
1192*bb4ee6a4SAndroid Build Coastguard Worker // Remove event triggers that have been hung-up to prevent unnecessary worker wake-ups
1193*bb4ee6a4SAndroid Build Coastguard Worker // (see b/244486346#comment62 for context).
1194*bb4ee6a4SAndroid Build Coastguard Worker for event in events.iter().filter(|e| e.is_hungup) {
1195*bb4ee6a4SAndroid Build Coastguard Worker error!(
1196*bb4ee6a4SAndroid Build Coastguard Worker "unhandled virtio-gpu worker event hang-up detected: {:?}",
1197*bb4ee6a4SAndroid Build Coastguard Worker event.token
1198*bb4ee6a4SAndroid Build Coastguard Worker );
1199*bb4ee6a4SAndroid Build Coastguard Worker event_manager.delete(event.token);
1200*bb4ee6a4SAndroid Build Coastguard Worker }
1201*bb4ee6a4SAndroid Build Coastguard Worker
1202*bb4ee6a4SAndroid Build Coastguard Worker for event in events.iter().filter(|e| e.is_readable) {
1203*bb4ee6a4SAndroid Build Coastguard Worker match event.token {
1204*bb4ee6a4SAndroid Build Coastguard Worker WorkerToken::CtrlQueue => {
1205*bb4ee6a4SAndroid Build Coastguard Worker let _ = ctrl_evt.wait();
1206*bb4ee6a4SAndroid Build Coastguard Worker // Set flag that control queue is available to be read, but defer reading
1207*bb4ee6a4SAndroid Build Coastguard Worker // until rest of the events are processed.
1208*bb4ee6a4SAndroid Build Coastguard Worker ctrl_available = true;
1209*bb4ee6a4SAndroid Build Coastguard Worker }
1210*bb4ee6a4SAndroid Build Coastguard Worker WorkerToken::CursorQueue => {
1211*bb4ee6a4SAndroid Build Coastguard Worker let _ = cursor_evt.wait();
1212*bb4ee6a4SAndroid Build Coastguard Worker if self.state.process_queue(
1213*bb4ee6a4SAndroid Build Coastguard Worker &activation_resources.mem,
1214*bb4ee6a4SAndroid Build Coastguard Worker &activation_resources.cursor_queue,
1215*bb4ee6a4SAndroid Build Coastguard Worker ) {
1216*bb4ee6a4SAndroid Build Coastguard Worker signal_used_cursor = true;
1217*bb4ee6a4SAndroid Build Coastguard Worker }
1218*bb4ee6a4SAndroid Build Coastguard Worker }
1219*bb4ee6a4SAndroid Build Coastguard Worker WorkerToken::Display => {
1220*bb4ee6a4SAndroid Build Coastguard Worker // We only need to process_display once-per-wake, regardless of how many
1221*bb4ee6a4SAndroid Build Coastguard Worker // WorkerToken::Display events are received.
1222*bb4ee6a4SAndroid Build Coastguard Worker display_available = true;
1223*bb4ee6a4SAndroid Build Coastguard Worker }
1224*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(windows)]
1225*bb4ee6a4SAndroid Build Coastguard Worker WorkerToken::DisplayDescriptorRequest => {
1226*bb4ee6a4SAndroid Build Coastguard Worker if let Ok(req) = self
1227*bb4ee6a4SAndroid Build Coastguard Worker .gpu_display_wait_descriptor_ctrl_rd
1228*bb4ee6a4SAndroid Build Coastguard Worker .recv::<ModifyWaitContext>()
1229*bb4ee6a4SAndroid Build Coastguard Worker {
1230*bb4ee6a4SAndroid Build Coastguard Worker match req {
1231*bb4ee6a4SAndroid Build Coastguard Worker ModifyWaitContext::Add(desc) => {
1232*bb4ee6a4SAndroid Build Coastguard Worker if let Err(e) =
1233*bb4ee6a4SAndroid Build Coastguard Worker event_manager.wait_ctx.add(&desc, WorkerToken::Display)
1234*bb4ee6a4SAndroid Build Coastguard Worker {
1235*bb4ee6a4SAndroid Build Coastguard Worker error!(
1236*bb4ee6a4SAndroid Build Coastguard Worker "failed to add extra descriptor from display \
1237*bb4ee6a4SAndroid Build Coastguard Worker to GPU worker wait context: {:?}",
1238*bb4ee6a4SAndroid Build Coastguard Worker e
1239*bb4ee6a4SAndroid Build Coastguard Worker )
1240*bb4ee6a4SAndroid Build Coastguard Worker }
1241*bb4ee6a4SAndroid Build Coastguard Worker }
1242*bb4ee6a4SAndroid Build Coastguard Worker }
1243*bb4ee6a4SAndroid Build Coastguard Worker } else {
1244*bb4ee6a4SAndroid Build Coastguard Worker error!("failed to receive ModifyWaitContext request.")
1245*bb4ee6a4SAndroid Build Coastguard Worker }
1246*bb4ee6a4SAndroid Build Coastguard Worker }
1247*bb4ee6a4SAndroid Build Coastguard Worker WorkerToken::GpuControl => {
1248*bb4ee6a4SAndroid Build Coastguard Worker let req = self
1249*bb4ee6a4SAndroid Build Coastguard Worker .gpu_control_tube
1250*bb4ee6a4SAndroid Build Coastguard Worker .recv()
1251*bb4ee6a4SAndroid Build Coastguard Worker .context("failed to recv from gpu control socket")?;
1252*bb4ee6a4SAndroid Build Coastguard Worker let resp = self.state.process_gpu_control_command(req);
1253*bb4ee6a4SAndroid Build Coastguard Worker
1254*bb4ee6a4SAndroid Build Coastguard Worker if let GpuControlResult::DisplaysUpdated = resp {
1255*bb4ee6a4SAndroid Build Coastguard Worker needs_config_interrupt = true;
1256*bb4ee6a4SAndroid Build Coastguard Worker }
1257*bb4ee6a4SAndroid Build Coastguard Worker
1258*bb4ee6a4SAndroid Build Coastguard Worker self.gpu_control_tube
1259*bb4ee6a4SAndroid Build Coastguard Worker .send(&resp)
1260*bb4ee6a4SAndroid Build Coastguard Worker .context("failed to send gpu control socket response")?;
1261*bb4ee6a4SAndroid Build Coastguard Worker }
1262*bb4ee6a4SAndroid Build Coastguard Worker WorkerToken::ResourceBridge { index } => {
1263*bb4ee6a4SAndroid Build Coastguard Worker self.resource_bridges.set_should_process(index);
1264*bb4ee6a4SAndroid Build Coastguard Worker }
1265*bb4ee6a4SAndroid Build Coastguard Worker WorkerToken::InterruptResample => {
1266*bb4ee6a4SAndroid Build Coastguard Worker activation_resources.interrupt.interrupt_resample();
1267*bb4ee6a4SAndroid Build Coastguard Worker }
1268*bb4ee6a4SAndroid Build Coastguard Worker WorkerToken::VirtioGpuPoll => {
1269*bb4ee6a4SAndroid Build Coastguard Worker self.state.event_poll();
1270*bb4ee6a4SAndroid Build Coastguard Worker }
1271*bb4ee6a4SAndroid Build Coastguard Worker WorkerToken::Sleep => {
1272*bb4ee6a4SAndroid Build Coastguard Worker return Ok(WorkerStopReason::Sleep);
1273*bb4ee6a4SAndroid Build Coastguard Worker }
1274*bb4ee6a4SAndroid Build Coastguard Worker WorkerToken::Kill => {
1275*bb4ee6a4SAndroid Build Coastguard Worker return Ok(WorkerStopReason::Kill);
1276*bb4ee6a4SAndroid Build Coastguard Worker }
1277*bb4ee6a4SAndroid Build Coastguard Worker }
1278*bb4ee6a4SAndroid Build Coastguard Worker }
1279*bb4ee6a4SAndroid Build Coastguard Worker
1280*bb4ee6a4SAndroid Build Coastguard Worker if display_available {
1281*bb4ee6a4SAndroid Build Coastguard Worker match self.state.process_display() {
1282*bb4ee6a4SAndroid Build Coastguard Worker ProcessDisplayResult::CloseRequested => {
1283*bb4ee6a4SAndroid Build Coastguard Worker let _ = self.exit_evt_wrtube.send::<VmEventType>(&VmEventType::Exit);
1284*bb4ee6a4SAndroid Build Coastguard Worker }
1285*bb4ee6a4SAndroid Build Coastguard Worker ProcessDisplayResult::Error(_e) => {
1286*bb4ee6a4SAndroid Build Coastguard Worker base::error!("Display processing failed, disabling display event handler.");
1287*bb4ee6a4SAndroid Build Coastguard Worker event_manager.delete(WorkerToken::Display);
1288*bb4ee6a4SAndroid Build Coastguard Worker }
1289*bb4ee6a4SAndroid Build Coastguard Worker ProcessDisplayResult::Success => (),
1290*bb4ee6a4SAndroid Build Coastguard Worker };
1291*bb4ee6a4SAndroid Build Coastguard Worker }
1292*bb4ee6a4SAndroid Build Coastguard Worker
1293*bb4ee6a4SAndroid Build Coastguard Worker if ctrl_available
1294*bb4ee6a4SAndroid Build Coastguard Worker && self
1295*bb4ee6a4SAndroid Build Coastguard Worker .state
1296*bb4ee6a4SAndroid Build Coastguard Worker .process_queue(&activation_resources.mem, &activation_resources.ctrl_queue)
1297*bb4ee6a4SAndroid Build Coastguard Worker {
1298*bb4ee6a4SAndroid Build Coastguard Worker signal_used_ctrl = true;
1299*bb4ee6a4SAndroid Build Coastguard Worker }
1300*bb4ee6a4SAndroid Build Coastguard Worker
1301*bb4ee6a4SAndroid Build Coastguard Worker // Process the entire control queue before the resource bridge in case a resource is
1302*bb4ee6a4SAndroid Build Coastguard Worker // created or destroyed by the control queue. Processing the resource bridge first may
1303*bb4ee6a4SAndroid Build Coastguard Worker // lead to a race condition.
1304*bb4ee6a4SAndroid Build Coastguard Worker // TODO(davidriley): This is still inherently racey if both the control queue request
1305*bb4ee6a4SAndroid Build Coastguard Worker // and the resource bridge request come in at the same time after the control queue is
1306*bb4ee6a4SAndroid Build Coastguard Worker // processed above and before the corresponding bridge is processed below.
1307*bb4ee6a4SAndroid Build Coastguard Worker self.resource_bridges
1308*bb4ee6a4SAndroid Build Coastguard Worker .process_resource_bridges(&mut self.state, &mut event_manager.wait_ctx);
1309*bb4ee6a4SAndroid Build Coastguard Worker
1310*bb4ee6a4SAndroid Build Coastguard Worker if signal_used_ctrl {
1311*bb4ee6a4SAndroid Build Coastguard Worker activation_resources.ctrl_queue.signal_used();
1312*bb4ee6a4SAndroid Build Coastguard Worker }
1313*bb4ee6a4SAndroid Build Coastguard Worker
1314*bb4ee6a4SAndroid Build Coastguard Worker if signal_used_cursor {
1315*bb4ee6a4SAndroid Build Coastguard Worker activation_resources.cursor_queue.signal_used();
1316*bb4ee6a4SAndroid Build Coastguard Worker }
1317*bb4ee6a4SAndroid Build Coastguard Worker
1318*bb4ee6a4SAndroid Build Coastguard Worker if needs_config_interrupt {
1319*bb4ee6a4SAndroid Build Coastguard Worker activation_resources.interrupt.signal_config_changed();
1320*bb4ee6a4SAndroid Build Coastguard Worker }
1321*bb4ee6a4SAndroid Build Coastguard Worker }
1322*bb4ee6a4SAndroid Build Coastguard Worker }
1323*bb4ee6a4SAndroid Build Coastguard Worker }
1324*bb4ee6a4SAndroid Build Coastguard Worker
1325*bb4ee6a4SAndroid Build Coastguard Worker /// Indicates a backend that should be tried for the gpu to use for display.
1326*bb4ee6a4SAndroid Build Coastguard Worker ///
1327*bb4ee6a4SAndroid Build Coastguard Worker /// Several instances of this enum are used in an ordered list to give the gpu device many backends
1328*bb4ee6a4SAndroid Build Coastguard Worker /// to use as fallbacks in case some do not work.
1329*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Clone)]
1330*bb4ee6a4SAndroid Build Coastguard Worker pub enum DisplayBackend {
1331*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(any(target_os = "android", target_os = "linux"))]
1332*bb4ee6a4SAndroid Build Coastguard Worker /// Use the wayland backend with the given socket path if given.
1333*bb4ee6a4SAndroid Build Coastguard Worker Wayland(Option<PathBuf>),
1334*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(any(target_os = "android", target_os = "linux"))]
1335*bb4ee6a4SAndroid Build Coastguard Worker /// Open a connection to the X server at the given display if given.
1336*bb4ee6a4SAndroid Build Coastguard Worker X(Option<String>),
1337*bb4ee6a4SAndroid Build Coastguard Worker /// Emulate a display without actually displaying it.
1338*bb4ee6a4SAndroid Build Coastguard Worker Stub,
1339*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(windows)]
1340*bb4ee6a4SAndroid Build Coastguard Worker /// Open a window using WinAPI.
1341*bb4ee6a4SAndroid Build Coastguard Worker WinApi,
1342*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "android_display")]
1343*bb4ee6a4SAndroid Build Coastguard Worker /// The display buffer is backed by an Android surface. The surface is set via an AIDL service
1344*bb4ee6a4SAndroid Build Coastguard Worker /// that the backend hosts. Currently, the AIDL service is registered to the service manager
1345*bb4ee6a4SAndroid Build Coastguard Worker /// using the name given here. The entity holding the surface is expected to locate the service
1346*bb4ee6a4SAndroid Build Coastguard Worker /// via this name, and pass the surface to it.
1347*bb4ee6a4SAndroid Build Coastguard Worker Android(String),
1348*bb4ee6a4SAndroid Build Coastguard Worker }
1349*bb4ee6a4SAndroid Build Coastguard Worker
1350*bb4ee6a4SAndroid Build Coastguard Worker impl DisplayBackend {
build( &self, #[cfg(windows)] wndproc_thread: &mut Option<WindowProcedureThread>, #[cfg(windows)] gpu_display_wait_descriptor_ctrl: SendTube, ) -> std::result::Result<GpuDisplay, GpuDisplayError>1351*bb4ee6a4SAndroid Build Coastguard Worker fn build(
1352*bb4ee6a4SAndroid Build Coastguard Worker &self,
1353*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(windows)] wndproc_thread: &mut Option<WindowProcedureThread>,
1354*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(windows)] gpu_display_wait_descriptor_ctrl: SendTube,
1355*bb4ee6a4SAndroid Build Coastguard Worker ) -> std::result::Result<GpuDisplay, GpuDisplayError> {
1356*bb4ee6a4SAndroid Build Coastguard Worker match self {
1357*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(any(target_os = "android", target_os = "linux"))]
1358*bb4ee6a4SAndroid Build Coastguard Worker DisplayBackend::Wayland(path) => GpuDisplay::open_wayland(path.as_ref()),
1359*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(any(target_os = "android", target_os = "linux"))]
1360*bb4ee6a4SAndroid Build Coastguard Worker DisplayBackend::X(display) => GpuDisplay::open_x(display.as_deref()),
1361*bb4ee6a4SAndroid Build Coastguard Worker DisplayBackend::Stub => GpuDisplay::open_stub(),
1362*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(windows)]
1363*bb4ee6a4SAndroid Build Coastguard Worker DisplayBackend::WinApi => match wndproc_thread.take() {
1364*bb4ee6a4SAndroid Build Coastguard Worker Some(wndproc_thread) => GpuDisplay::open_winapi(
1365*bb4ee6a4SAndroid Build Coastguard Worker wndproc_thread,
1366*bb4ee6a4SAndroid Build Coastguard Worker /* win_metrics= */ None,
1367*bb4ee6a4SAndroid Build Coastguard Worker gpu_display_wait_descriptor_ctrl,
1368*bb4ee6a4SAndroid Build Coastguard Worker None,
1369*bb4ee6a4SAndroid Build Coastguard Worker ),
1370*bb4ee6a4SAndroid Build Coastguard Worker None => {
1371*bb4ee6a4SAndroid Build Coastguard Worker error!("wndproc_thread is none");
1372*bb4ee6a4SAndroid Build Coastguard Worker Err(GpuDisplayError::Allocate)
1373*bb4ee6a4SAndroid Build Coastguard Worker }
1374*bb4ee6a4SAndroid Build Coastguard Worker },
1375*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "android_display")]
1376*bb4ee6a4SAndroid Build Coastguard Worker DisplayBackend::Android(service_name) => GpuDisplay::open_android(service_name),
1377*bb4ee6a4SAndroid Build Coastguard Worker }
1378*bb4ee6a4SAndroid Build Coastguard Worker }
1379*bb4ee6a4SAndroid Build Coastguard Worker }
1380*bb4ee6a4SAndroid Build Coastguard Worker
1381*bb4ee6a4SAndroid Build Coastguard Worker pub struct Gpu {
1382*bb4ee6a4SAndroid Build Coastguard Worker exit_evt_wrtube: SendTube,
1383*bb4ee6a4SAndroid Build Coastguard Worker pub gpu_control_tube: Option<Tube>,
1384*bb4ee6a4SAndroid Build Coastguard Worker mapper: Arc<Mutex<Option<Box<dyn SharedMemoryMapper>>>>,
1385*bb4ee6a4SAndroid Build Coastguard Worker resource_bridges: Option<ResourceBridges>,
1386*bb4ee6a4SAndroid Build Coastguard Worker event_devices: Option<Vec<EventDevice>>,
1387*bb4ee6a4SAndroid Build Coastguard Worker worker_suspend_evt: Option<Event>,
1388*bb4ee6a4SAndroid Build Coastguard Worker worker_request_sender: Option<mpsc::Sender<WorkerRequest>>,
1389*bb4ee6a4SAndroid Build Coastguard Worker worker_response_receiver: Option<mpsc::Receiver<anyhow::Result<WorkerResponse>>>,
1390*bb4ee6a4SAndroid Build Coastguard Worker worker_state: WorkerState,
1391*bb4ee6a4SAndroid Build Coastguard Worker worker_thread: Option<WorkerThread<()>>,
1392*bb4ee6a4SAndroid Build Coastguard Worker display_backends: Vec<DisplayBackend>,
1393*bb4ee6a4SAndroid Build Coastguard Worker display_params: Vec<GpuDisplayParameters>,
1394*bb4ee6a4SAndroid Build Coastguard Worker display_event: Arc<AtomicBool>,
1395*bb4ee6a4SAndroid Build Coastguard Worker rutabaga_builder: RutabagaBuilder,
1396*bb4ee6a4SAndroid Build Coastguard Worker pci_address: Option<PciAddress>,
1397*bb4ee6a4SAndroid Build Coastguard Worker pci_bar_size: u64,
1398*bb4ee6a4SAndroid Build Coastguard Worker external_blob: bool,
1399*bb4ee6a4SAndroid Build Coastguard Worker fixed_blob_mapping: bool,
1400*bb4ee6a4SAndroid Build Coastguard Worker rutabaga_component: RutabagaComponentType,
1401*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(windows)]
1402*bb4ee6a4SAndroid Build Coastguard Worker wndproc_thread: Option<WindowProcedureThread>,
1403*bb4ee6a4SAndroid Build Coastguard Worker base_features: u64,
1404*bb4ee6a4SAndroid Build Coastguard Worker udmabuf: bool,
1405*bb4ee6a4SAndroid Build Coastguard Worker rutabaga_server_descriptor: Option<SafeDescriptor>,
1406*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(windows)]
1407*bb4ee6a4SAndroid Build Coastguard Worker /// Because the Windows GpuDisplay can't expose an epollfd, it has to inform the GPU worker
1408*bb4ee6a4SAndroid Build Coastguard Worker /// which descriptors to add to its wait context. That's what this Tube is used for (it is
1409*bb4ee6a4SAndroid Build Coastguard Worker /// provided to each display backend.
1410*bb4ee6a4SAndroid Build Coastguard Worker gpu_display_wait_descriptor_ctrl_wr: SendTube,
1411*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(windows)]
1412*bb4ee6a4SAndroid Build Coastguard Worker /// The GPU worker uses this Tube to receive the descriptors that should be added to its wait
1413*bb4ee6a4SAndroid Build Coastguard Worker /// context.
1414*bb4ee6a4SAndroid Build Coastguard Worker gpu_display_wait_descriptor_ctrl_rd: Option<RecvTube>,
1415*bb4ee6a4SAndroid Build Coastguard Worker capset_mask: u64,
1416*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(any(target_os = "android", target_os = "linux"))]
1417*bb4ee6a4SAndroid Build Coastguard Worker gpu_cgroup_path: Option<PathBuf>,
1418*bb4ee6a4SAndroid Build Coastguard Worker }
1419*bb4ee6a4SAndroid Build Coastguard Worker
1420*bb4ee6a4SAndroid Build Coastguard Worker impl Gpu {
new( exit_evt_wrtube: SendTube, gpu_control_tube: Tube, resource_bridges: Vec<Tube>, display_backends: Vec<DisplayBackend>, gpu_parameters: &GpuParameters, rutabaga_server_descriptor: Option<SafeDescriptor>, event_devices: Vec<EventDevice>, base_features: u64, channels: &BTreeMap<String, PathBuf>, #[cfg(windows)] wndproc_thread: WindowProcedureThread, #[cfg(any(target_os = "android", target_os = "linux"))] gpu_cgroup_path: Option<&PathBuf>, ) -> Gpu1421*bb4ee6a4SAndroid Build Coastguard Worker pub fn new(
1422*bb4ee6a4SAndroid Build Coastguard Worker exit_evt_wrtube: SendTube,
1423*bb4ee6a4SAndroid Build Coastguard Worker gpu_control_tube: Tube,
1424*bb4ee6a4SAndroid Build Coastguard Worker resource_bridges: Vec<Tube>,
1425*bb4ee6a4SAndroid Build Coastguard Worker display_backends: Vec<DisplayBackend>,
1426*bb4ee6a4SAndroid Build Coastguard Worker gpu_parameters: &GpuParameters,
1427*bb4ee6a4SAndroid Build Coastguard Worker rutabaga_server_descriptor: Option<SafeDescriptor>,
1428*bb4ee6a4SAndroid Build Coastguard Worker event_devices: Vec<EventDevice>,
1429*bb4ee6a4SAndroid Build Coastguard Worker base_features: u64,
1430*bb4ee6a4SAndroid Build Coastguard Worker channels: &BTreeMap<String, PathBuf>,
1431*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(windows)] wndproc_thread: WindowProcedureThread,
1432*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(any(target_os = "android", target_os = "linux"))] gpu_cgroup_path: Option<&PathBuf>,
1433*bb4ee6a4SAndroid Build Coastguard Worker ) -> Gpu {
1434*bb4ee6a4SAndroid Build Coastguard Worker let mut display_params = gpu_parameters.display_params.clone();
1435*bb4ee6a4SAndroid Build Coastguard Worker if display_params.is_empty() {
1436*bb4ee6a4SAndroid Build Coastguard Worker display_params.push(Default::default());
1437*bb4ee6a4SAndroid Build Coastguard Worker }
1438*bb4ee6a4SAndroid Build Coastguard Worker let (display_width, display_height) = display_params[0].get_virtual_display_size();
1439*bb4ee6a4SAndroid Build Coastguard Worker
1440*bb4ee6a4SAndroid Build Coastguard Worker let mut rutabaga_channels: Vec<RutabagaChannel> = Vec::new();
1441*bb4ee6a4SAndroid Build Coastguard Worker for (channel_name, path) in channels {
1442*bb4ee6a4SAndroid Build Coastguard Worker match &channel_name[..] {
1443*bb4ee6a4SAndroid Build Coastguard Worker "" => rutabaga_channels.push(RutabagaChannel {
1444*bb4ee6a4SAndroid Build Coastguard Worker base_channel: path.clone(),
1445*bb4ee6a4SAndroid Build Coastguard Worker channel_type: RUTABAGA_CHANNEL_TYPE_WAYLAND,
1446*bb4ee6a4SAndroid Build Coastguard Worker }),
1447*bb4ee6a4SAndroid Build Coastguard Worker "mojo" => rutabaga_channels.push(RutabagaChannel {
1448*bb4ee6a4SAndroid Build Coastguard Worker base_channel: path.clone(),
1449*bb4ee6a4SAndroid Build Coastguard Worker channel_type: RUTABAGA_CHANNEL_TYPE_CAMERA,
1450*bb4ee6a4SAndroid Build Coastguard Worker }),
1451*bb4ee6a4SAndroid Build Coastguard Worker _ => error!("unknown rutabaga channel"),
1452*bb4ee6a4SAndroid Build Coastguard Worker }
1453*bb4ee6a4SAndroid Build Coastguard Worker }
1454*bb4ee6a4SAndroid Build Coastguard Worker
1455*bb4ee6a4SAndroid Build Coastguard Worker let rutabaga_channels_opt = Some(rutabaga_channels);
1456*bb4ee6a4SAndroid Build Coastguard Worker let component = match gpu_parameters.mode {
1457*bb4ee6a4SAndroid Build Coastguard Worker GpuMode::Mode2D => RutabagaComponentType::Rutabaga2D,
1458*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "virgl_renderer")]
1459*bb4ee6a4SAndroid Build Coastguard Worker GpuMode::ModeVirglRenderer => RutabagaComponentType::VirglRenderer,
1460*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "gfxstream")]
1461*bb4ee6a4SAndroid Build Coastguard Worker GpuMode::ModeGfxstream => RutabagaComponentType::Gfxstream,
1462*bb4ee6a4SAndroid Build Coastguard Worker };
1463*bb4ee6a4SAndroid Build Coastguard Worker
1464*bb4ee6a4SAndroid Build Coastguard Worker // Only allow virglrenderer to fork its own render server when explicitly requested.
1465*bb4ee6a4SAndroid Build Coastguard Worker // Caller can enforce its own restrictions (e.g. not allowed when sandboxed) and set the
1466*bb4ee6a4SAndroid Build Coastguard Worker // allow flag appropriately.
1467*bb4ee6a4SAndroid Build Coastguard Worker let use_render_server = rutabaga_server_descriptor.is_some()
1468*bb4ee6a4SAndroid Build Coastguard Worker || gpu_parameters.allow_implicit_render_server_exec;
1469*bb4ee6a4SAndroid Build Coastguard Worker
1470*bb4ee6a4SAndroid Build Coastguard Worker let rutabaga_wsi = match gpu_parameters.wsi {
1471*bb4ee6a4SAndroid Build Coastguard Worker Some(GpuWsi::Vulkan) => RutabagaWsi::VulkanSwapchain,
1472*bb4ee6a4SAndroid Build Coastguard Worker _ => RutabagaWsi::Surfaceless,
1473*bb4ee6a4SAndroid Build Coastguard Worker };
1474*bb4ee6a4SAndroid Build Coastguard Worker
1475*bb4ee6a4SAndroid Build Coastguard Worker let rutabaga_builder = RutabagaBuilder::new(component, gpu_parameters.capset_mask)
1476*bb4ee6a4SAndroid Build Coastguard Worker .set_display_width(display_width)
1477*bb4ee6a4SAndroid Build Coastguard Worker .set_display_height(display_height)
1478*bb4ee6a4SAndroid Build Coastguard Worker .set_rutabaga_channels(rutabaga_channels_opt)
1479*bb4ee6a4SAndroid Build Coastguard Worker .set_use_egl(gpu_parameters.renderer_use_egl)
1480*bb4ee6a4SAndroid Build Coastguard Worker .set_use_gles(gpu_parameters.renderer_use_gles)
1481*bb4ee6a4SAndroid Build Coastguard Worker .set_use_glx(gpu_parameters.renderer_use_glx)
1482*bb4ee6a4SAndroid Build Coastguard Worker .set_use_surfaceless(gpu_parameters.renderer_use_surfaceless)
1483*bb4ee6a4SAndroid Build Coastguard Worker .set_use_vulkan(gpu_parameters.use_vulkan.unwrap_or_default())
1484*bb4ee6a4SAndroid Build Coastguard Worker .set_wsi(rutabaga_wsi)
1485*bb4ee6a4SAndroid Build Coastguard Worker .set_use_external_blob(gpu_parameters.external_blob)
1486*bb4ee6a4SAndroid Build Coastguard Worker .set_use_system_blob(gpu_parameters.system_blob)
1487*bb4ee6a4SAndroid Build Coastguard Worker .set_use_render_server(use_render_server)
1488*bb4ee6a4SAndroid Build Coastguard Worker .set_renderer_features(gpu_parameters.renderer_features.clone());
1489*bb4ee6a4SAndroid Build Coastguard Worker
1490*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(windows)]
1491*bb4ee6a4SAndroid Build Coastguard Worker let (gpu_display_wait_descriptor_ctrl_wr, gpu_display_wait_descriptor_ctrl_rd) =
1492*bb4ee6a4SAndroid Build Coastguard Worker Tube::directional_pair().expect("failed to create wait descriptor control pair.");
1493*bb4ee6a4SAndroid Build Coastguard Worker
1494*bb4ee6a4SAndroid Build Coastguard Worker Gpu {
1495*bb4ee6a4SAndroid Build Coastguard Worker exit_evt_wrtube,
1496*bb4ee6a4SAndroid Build Coastguard Worker gpu_control_tube: Some(gpu_control_tube),
1497*bb4ee6a4SAndroid Build Coastguard Worker mapper: Arc::new(Mutex::new(None)),
1498*bb4ee6a4SAndroid Build Coastguard Worker resource_bridges: Some(ResourceBridges::new(resource_bridges)),
1499*bb4ee6a4SAndroid Build Coastguard Worker event_devices: Some(event_devices),
1500*bb4ee6a4SAndroid Build Coastguard Worker worker_request_sender: None,
1501*bb4ee6a4SAndroid Build Coastguard Worker worker_response_receiver: None,
1502*bb4ee6a4SAndroid Build Coastguard Worker worker_suspend_evt: None,
1503*bb4ee6a4SAndroid Build Coastguard Worker worker_state: WorkerState::Inactive,
1504*bb4ee6a4SAndroid Build Coastguard Worker worker_thread: None,
1505*bb4ee6a4SAndroid Build Coastguard Worker display_backends,
1506*bb4ee6a4SAndroid Build Coastguard Worker display_params,
1507*bb4ee6a4SAndroid Build Coastguard Worker display_event: Arc::new(AtomicBool::new(false)),
1508*bb4ee6a4SAndroid Build Coastguard Worker rutabaga_builder,
1509*bb4ee6a4SAndroid Build Coastguard Worker pci_address: gpu_parameters.pci_address,
1510*bb4ee6a4SAndroid Build Coastguard Worker pci_bar_size: gpu_parameters.pci_bar_size,
1511*bb4ee6a4SAndroid Build Coastguard Worker external_blob: gpu_parameters.external_blob,
1512*bb4ee6a4SAndroid Build Coastguard Worker fixed_blob_mapping: gpu_parameters.fixed_blob_mapping,
1513*bb4ee6a4SAndroid Build Coastguard Worker rutabaga_component: component,
1514*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(windows)]
1515*bb4ee6a4SAndroid Build Coastguard Worker wndproc_thread: Some(wndproc_thread),
1516*bb4ee6a4SAndroid Build Coastguard Worker base_features,
1517*bb4ee6a4SAndroid Build Coastguard Worker udmabuf: gpu_parameters.udmabuf,
1518*bb4ee6a4SAndroid Build Coastguard Worker rutabaga_server_descriptor,
1519*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(windows)]
1520*bb4ee6a4SAndroid Build Coastguard Worker gpu_display_wait_descriptor_ctrl_wr,
1521*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(windows)]
1522*bb4ee6a4SAndroid Build Coastguard Worker gpu_display_wait_descriptor_ctrl_rd: Some(gpu_display_wait_descriptor_ctrl_rd),
1523*bb4ee6a4SAndroid Build Coastguard Worker capset_mask: gpu_parameters.capset_mask,
1524*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(any(target_os = "android", target_os = "linux"))]
1525*bb4ee6a4SAndroid Build Coastguard Worker gpu_cgroup_path: gpu_cgroup_path.cloned(),
1526*bb4ee6a4SAndroid Build Coastguard Worker }
1527*bb4ee6a4SAndroid Build Coastguard Worker }
1528*bb4ee6a4SAndroid Build Coastguard Worker
1529*bb4ee6a4SAndroid Build Coastguard Worker /// Initializes the internal device state so that it can begin processing virtqueues.
1530*bb4ee6a4SAndroid Build Coastguard Worker ///
1531*bb4ee6a4SAndroid Build Coastguard Worker /// Only used by vhost-user GPU.
initialize_frontend( &mut self, fence_state: Arc<Mutex<FenceState>>, fence_handler: RutabagaFenceHandler, mapper: Arc<Mutex<Option<Box<dyn SharedMemoryMapper>>>>, ) -> Option<Frontend>1532*bb4ee6a4SAndroid Build Coastguard Worker pub fn initialize_frontend(
1533*bb4ee6a4SAndroid Build Coastguard Worker &mut self,
1534*bb4ee6a4SAndroid Build Coastguard Worker fence_state: Arc<Mutex<FenceState>>,
1535*bb4ee6a4SAndroid Build Coastguard Worker fence_handler: RutabagaFenceHandler,
1536*bb4ee6a4SAndroid Build Coastguard Worker mapper: Arc<Mutex<Option<Box<dyn SharedMemoryMapper>>>>,
1537*bb4ee6a4SAndroid Build Coastguard Worker ) -> Option<Frontend> {
1538*bb4ee6a4SAndroid Build Coastguard Worker let rutabaga_server_descriptor = self.rutabaga_server_descriptor.as_ref().map(|d| {
1539*bb4ee6a4SAndroid Build Coastguard Worker to_rutabaga_descriptor(d.try_clone().expect("failed to clone server descriptor"))
1540*bb4ee6a4SAndroid Build Coastguard Worker });
1541*bb4ee6a4SAndroid Build Coastguard Worker let rutabaga = self
1542*bb4ee6a4SAndroid Build Coastguard Worker .rutabaga_builder
1543*bb4ee6a4SAndroid Build Coastguard Worker .clone()
1544*bb4ee6a4SAndroid Build Coastguard Worker .build(fence_handler, rutabaga_server_descriptor)
1545*bb4ee6a4SAndroid Build Coastguard Worker .map_err(|e| error!("failed to build rutabaga {}", e))
1546*bb4ee6a4SAndroid Build Coastguard Worker .ok()?;
1547*bb4ee6a4SAndroid Build Coastguard Worker
1548*bb4ee6a4SAndroid Build Coastguard Worker let mut virtio_gpu = build(
1549*bb4ee6a4SAndroid Build Coastguard Worker &self.display_backends,
1550*bb4ee6a4SAndroid Build Coastguard Worker self.display_params.clone(),
1551*bb4ee6a4SAndroid Build Coastguard Worker self.display_event.clone(),
1552*bb4ee6a4SAndroid Build Coastguard Worker rutabaga,
1553*bb4ee6a4SAndroid Build Coastguard Worker mapper,
1554*bb4ee6a4SAndroid Build Coastguard Worker self.external_blob,
1555*bb4ee6a4SAndroid Build Coastguard Worker self.fixed_blob_mapping,
1556*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(windows)]
1557*bb4ee6a4SAndroid Build Coastguard Worker &mut self.wndproc_thread,
1558*bb4ee6a4SAndroid Build Coastguard Worker self.udmabuf,
1559*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(windows)]
1560*bb4ee6a4SAndroid Build Coastguard Worker self.gpu_display_wait_descriptor_ctrl_wr
1561*bb4ee6a4SAndroid Build Coastguard Worker .try_clone()
1562*bb4ee6a4SAndroid Build Coastguard Worker .expect("failed to clone wait context control channel"),
1563*bb4ee6a4SAndroid Build Coastguard Worker )?;
1564*bb4ee6a4SAndroid Build Coastguard Worker
1565*bb4ee6a4SAndroid Build Coastguard Worker for event_device in self.event_devices.take().expect("missing event_devices") {
1566*bb4ee6a4SAndroid Build Coastguard Worker virtio_gpu
1567*bb4ee6a4SAndroid Build Coastguard Worker .import_event_device(event_device)
1568*bb4ee6a4SAndroid Build Coastguard Worker // We lost the `EventDevice`, so fail hard.
1569*bb4ee6a4SAndroid Build Coastguard Worker .expect("failed to import event device");
1570*bb4ee6a4SAndroid Build Coastguard Worker }
1571*bb4ee6a4SAndroid Build Coastguard Worker
1572*bb4ee6a4SAndroid Build Coastguard Worker Some(Frontend::new(virtio_gpu, fence_state))
1573*bb4ee6a4SAndroid Build Coastguard Worker }
1574*bb4ee6a4SAndroid Build Coastguard Worker
1575*bb4ee6a4SAndroid Build Coastguard Worker // This is not invoked when running with vhost-user GPU.
start_worker_thread(&mut self)1576*bb4ee6a4SAndroid Build Coastguard Worker fn start_worker_thread(&mut self) {
1577*bb4ee6a4SAndroid Build Coastguard Worker let suspend_evt = Event::new().unwrap();
1578*bb4ee6a4SAndroid Build Coastguard Worker let suspend_evt_copy = suspend_evt
1579*bb4ee6a4SAndroid Build Coastguard Worker .try_clone()
1580*bb4ee6a4SAndroid Build Coastguard Worker .context("error cloning suspend event")
1581*bb4ee6a4SAndroid Build Coastguard Worker .unwrap();
1582*bb4ee6a4SAndroid Build Coastguard Worker
1583*bb4ee6a4SAndroid Build Coastguard Worker let exit_evt_wrtube = self
1584*bb4ee6a4SAndroid Build Coastguard Worker .exit_evt_wrtube
1585*bb4ee6a4SAndroid Build Coastguard Worker .try_clone()
1586*bb4ee6a4SAndroid Build Coastguard Worker .context("error cloning exit tube")
1587*bb4ee6a4SAndroid Build Coastguard Worker .unwrap();
1588*bb4ee6a4SAndroid Build Coastguard Worker
1589*bb4ee6a4SAndroid Build Coastguard Worker let gpu_control_tube = self
1590*bb4ee6a4SAndroid Build Coastguard Worker .gpu_control_tube
1591*bb4ee6a4SAndroid Build Coastguard Worker .take()
1592*bb4ee6a4SAndroid Build Coastguard Worker .context("gpu_control_tube is none")
1593*bb4ee6a4SAndroid Build Coastguard Worker .unwrap();
1594*bb4ee6a4SAndroid Build Coastguard Worker
1595*bb4ee6a4SAndroid Build Coastguard Worker let resource_bridges = self
1596*bb4ee6a4SAndroid Build Coastguard Worker .resource_bridges
1597*bb4ee6a4SAndroid Build Coastguard Worker .take()
1598*bb4ee6a4SAndroid Build Coastguard Worker .context("resource_bridges is none")
1599*bb4ee6a4SAndroid Build Coastguard Worker .unwrap();
1600*bb4ee6a4SAndroid Build Coastguard Worker
1601*bb4ee6a4SAndroid Build Coastguard Worker let display_backends = self.display_backends.clone();
1602*bb4ee6a4SAndroid Build Coastguard Worker let display_params = self.display_params.clone();
1603*bb4ee6a4SAndroid Build Coastguard Worker let display_event = self.display_event.clone();
1604*bb4ee6a4SAndroid Build Coastguard Worker let event_devices = self.event_devices.take().expect("missing event_devices");
1605*bb4ee6a4SAndroid Build Coastguard Worker let external_blob = self.external_blob;
1606*bb4ee6a4SAndroid Build Coastguard Worker let fixed_blob_mapping = self.fixed_blob_mapping;
1607*bb4ee6a4SAndroid Build Coastguard Worker let udmabuf = self.udmabuf;
1608*bb4ee6a4SAndroid Build Coastguard Worker
1609*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(windows)]
1610*bb4ee6a4SAndroid Build Coastguard Worker let mut wndproc_thread = self.wndproc_thread.take();
1611*bb4ee6a4SAndroid Build Coastguard Worker
1612*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(windows)]
1613*bb4ee6a4SAndroid Build Coastguard Worker let gpu_display_wait_descriptor_ctrl_wr = self
1614*bb4ee6a4SAndroid Build Coastguard Worker .gpu_display_wait_descriptor_ctrl_wr
1615*bb4ee6a4SAndroid Build Coastguard Worker .try_clone()
1616*bb4ee6a4SAndroid Build Coastguard Worker .expect("failed to clone wait context ctrl channel");
1617*bb4ee6a4SAndroid Build Coastguard Worker
1618*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(windows)]
1619*bb4ee6a4SAndroid Build Coastguard Worker let gpu_display_wait_descriptor_ctrl_rd = self
1620*bb4ee6a4SAndroid Build Coastguard Worker .gpu_display_wait_descriptor_ctrl_rd
1621*bb4ee6a4SAndroid Build Coastguard Worker .take()
1622*bb4ee6a4SAndroid Build Coastguard Worker .expect("failed to take gpu_display_wait_descriptor_ctrl_rd");
1623*bb4ee6a4SAndroid Build Coastguard Worker
1624*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(any(target_os = "android", target_os = "linux"))]
1625*bb4ee6a4SAndroid Build Coastguard Worker let gpu_cgroup_path = self.gpu_cgroup_path.clone();
1626*bb4ee6a4SAndroid Build Coastguard Worker
1627*bb4ee6a4SAndroid Build Coastguard Worker let mapper = Arc::clone(&self.mapper);
1628*bb4ee6a4SAndroid Build Coastguard Worker
1629*bb4ee6a4SAndroid Build Coastguard Worker let rutabaga_builder = self.rutabaga_builder.clone();
1630*bb4ee6a4SAndroid Build Coastguard Worker let rutabaga_server_descriptor = self.rutabaga_server_descriptor.as_ref().map(|d| {
1631*bb4ee6a4SAndroid Build Coastguard Worker to_rutabaga_descriptor(d.try_clone().expect("failed to clone server descriptor"))
1632*bb4ee6a4SAndroid Build Coastguard Worker });
1633*bb4ee6a4SAndroid Build Coastguard Worker
1634*bb4ee6a4SAndroid Build Coastguard Worker let (init_finished_tx, init_finished_rx) = mpsc::channel();
1635*bb4ee6a4SAndroid Build Coastguard Worker
1636*bb4ee6a4SAndroid Build Coastguard Worker let (worker_request_sender, worker_request_receiver) = mpsc::channel();
1637*bb4ee6a4SAndroid Build Coastguard Worker let (worker_response_sender, worker_response_receiver) = mpsc::channel();
1638*bb4ee6a4SAndroid Build Coastguard Worker
1639*bb4ee6a4SAndroid Build Coastguard Worker let worker_thread = WorkerThread::start("v_gpu", move |kill_evt| {
1640*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(any(target_os = "android", target_os = "linux"))]
1641*bb4ee6a4SAndroid Build Coastguard Worker if let Some(cgroup_path) = gpu_cgroup_path {
1642*bb4ee6a4SAndroid Build Coastguard Worker move_task_to_cgroup(cgroup_path, base::gettid())
1643*bb4ee6a4SAndroid Build Coastguard Worker .expect("Failed to move v_gpu into requested cgroup");
1644*bb4ee6a4SAndroid Build Coastguard Worker }
1645*bb4ee6a4SAndroid Build Coastguard Worker
1646*bb4ee6a4SAndroid Build Coastguard Worker let mut worker = Worker::new(
1647*bb4ee6a4SAndroid Build Coastguard Worker rutabaga_builder,
1648*bb4ee6a4SAndroid Build Coastguard Worker rutabaga_server_descriptor,
1649*bb4ee6a4SAndroid Build Coastguard Worker display_backends,
1650*bb4ee6a4SAndroid Build Coastguard Worker display_params,
1651*bb4ee6a4SAndroid Build Coastguard Worker display_event,
1652*bb4ee6a4SAndroid Build Coastguard Worker mapper,
1653*bb4ee6a4SAndroid Build Coastguard Worker event_devices,
1654*bb4ee6a4SAndroid Build Coastguard Worker external_blob,
1655*bb4ee6a4SAndroid Build Coastguard Worker fixed_blob_mapping,
1656*bb4ee6a4SAndroid Build Coastguard Worker udmabuf,
1657*bb4ee6a4SAndroid Build Coastguard Worker worker_request_receiver,
1658*bb4ee6a4SAndroid Build Coastguard Worker worker_response_sender,
1659*bb4ee6a4SAndroid Build Coastguard Worker exit_evt_wrtube,
1660*bb4ee6a4SAndroid Build Coastguard Worker gpu_control_tube,
1661*bb4ee6a4SAndroid Build Coastguard Worker resource_bridges,
1662*bb4ee6a4SAndroid Build Coastguard Worker suspend_evt_copy,
1663*bb4ee6a4SAndroid Build Coastguard Worker kill_evt,
1664*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(windows)]
1665*bb4ee6a4SAndroid Build Coastguard Worker wndproc_thread,
1666*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(windows)]
1667*bb4ee6a4SAndroid Build Coastguard Worker gpu_display_wait_descriptor_ctrl_rd,
1668*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(windows)]
1669*bb4ee6a4SAndroid Build Coastguard Worker gpu_display_wait_descriptor_ctrl_wr,
1670*bb4ee6a4SAndroid Build Coastguard Worker )
1671*bb4ee6a4SAndroid Build Coastguard Worker .expect("Failed to create virtio gpu worker thread");
1672*bb4ee6a4SAndroid Build Coastguard Worker
1673*bb4ee6a4SAndroid Build Coastguard Worker // Tell the parent thread that the init phase is complete.
1674*bb4ee6a4SAndroid Build Coastguard Worker let _ = init_finished_tx.send(());
1675*bb4ee6a4SAndroid Build Coastguard Worker
1676*bb4ee6a4SAndroid Build Coastguard Worker worker.run()
1677*bb4ee6a4SAndroid Build Coastguard Worker });
1678*bb4ee6a4SAndroid Build Coastguard Worker
1679*bb4ee6a4SAndroid Build Coastguard Worker self.worker_request_sender = Some(worker_request_sender);
1680*bb4ee6a4SAndroid Build Coastguard Worker self.worker_response_receiver = Some(worker_response_receiver);
1681*bb4ee6a4SAndroid Build Coastguard Worker self.worker_suspend_evt = Some(suspend_evt);
1682*bb4ee6a4SAndroid Build Coastguard Worker self.worker_state = WorkerState::Inactive;
1683*bb4ee6a4SAndroid Build Coastguard Worker self.worker_thread = Some(worker_thread);
1684*bb4ee6a4SAndroid Build Coastguard Worker
1685*bb4ee6a4SAndroid Build Coastguard Worker match init_finished_rx.recv() {
1686*bb4ee6a4SAndroid Build Coastguard Worker Ok(()) => {}
1687*bb4ee6a4SAndroid Build Coastguard Worker Err(mpsc::RecvError) => panic!("virtio-gpu worker thread init failed"),
1688*bb4ee6a4SAndroid Build Coastguard Worker }
1689*bb4ee6a4SAndroid Build Coastguard Worker }
1690*bb4ee6a4SAndroid Build Coastguard Worker
stop_worker_thread(&mut self)1691*bb4ee6a4SAndroid Build Coastguard Worker fn stop_worker_thread(&mut self) {
1692*bb4ee6a4SAndroid Build Coastguard Worker self.worker_request_sender.take();
1693*bb4ee6a4SAndroid Build Coastguard Worker self.worker_response_receiver.take();
1694*bb4ee6a4SAndroid Build Coastguard Worker self.worker_suspend_evt.take();
1695*bb4ee6a4SAndroid Build Coastguard Worker if let Some(worker_thread) = self.worker_thread.take() {
1696*bb4ee6a4SAndroid Build Coastguard Worker worker_thread.stop();
1697*bb4ee6a4SAndroid Build Coastguard Worker }
1698*bb4ee6a4SAndroid Build Coastguard Worker }
1699*bb4ee6a4SAndroid Build Coastguard Worker
get_config(&self) -> virtio_gpu_config1700*bb4ee6a4SAndroid Build Coastguard Worker fn get_config(&self) -> virtio_gpu_config {
1701*bb4ee6a4SAndroid Build Coastguard Worker let mut events_read = 0;
1702*bb4ee6a4SAndroid Build Coastguard Worker
1703*bb4ee6a4SAndroid Build Coastguard Worker if self.display_event.load(Ordering::Relaxed) {
1704*bb4ee6a4SAndroid Build Coastguard Worker events_read |= VIRTIO_GPU_EVENT_DISPLAY;
1705*bb4ee6a4SAndroid Build Coastguard Worker }
1706*bb4ee6a4SAndroid Build Coastguard Worker
1707*bb4ee6a4SAndroid Build Coastguard Worker let num_capsets = match self.capset_mask {
1708*bb4ee6a4SAndroid Build Coastguard Worker 0 => {
1709*bb4ee6a4SAndroid Build Coastguard Worker match self.rutabaga_component {
1710*bb4ee6a4SAndroid Build Coastguard Worker RutabagaComponentType::Rutabaga2D => 0,
1711*bb4ee6a4SAndroid Build Coastguard Worker _ => {
1712*bb4ee6a4SAndroid Build Coastguard Worker #[allow(unused_mut)]
1713*bb4ee6a4SAndroid Build Coastguard Worker let mut num_capsets = 0;
1714*bb4ee6a4SAndroid Build Coastguard Worker
1715*bb4ee6a4SAndroid Build Coastguard Worker // Three capsets for virgl_renderer
1716*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "virgl_renderer")]
1717*bb4ee6a4SAndroid Build Coastguard Worker {
1718*bb4ee6a4SAndroid Build Coastguard Worker num_capsets += 3;
1719*bb4ee6a4SAndroid Build Coastguard Worker }
1720*bb4ee6a4SAndroid Build Coastguard Worker
1721*bb4ee6a4SAndroid Build Coastguard Worker // One capset for gfxstream
1722*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "gfxstream")]
1723*bb4ee6a4SAndroid Build Coastguard Worker {
1724*bb4ee6a4SAndroid Build Coastguard Worker num_capsets += 1;
1725*bb4ee6a4SAndroid Build Coastguard Worker }
1726*bb4ee6a4SAndroid Build Coastguard Worker
1727*bb4ee6a4SAndroid Build Coastguard Worker num_capsets
1728*bb4ee6a4SAndroid Build Coastguard Worker }
1729*bb4ee6a4SAndroid Build Coastguard Worker }
1730*bb4ee6a4SAndroid Build Coastguard Worker }
1731*bb4ee6a4SAndroid Build Coastguard Worker _ => self.capset_mask.count_ones(),
1732*bb4ee6a4SAndroid Build Coastguard Worker };
1733*bb4ee6a4SAndroid Build Coastguard Worker
1734*bb4ee6a4SAndroid Build Coastguard Worker virtio_gpu_config {
1735*bb4ee6a4SAndroid Build Coastguard Worker events_read: Le32::from(events_read),
1736*bb4ee6a4SAndroid Build Coastguard Worker events_clear: Le32::from(0),
1737*bb4ee6a4SAndroid Build Coastguard Worker num_scanouts: Le32::from(VIRTIO_GPU_MAX_SCANOUTS as u32),
1738*bb4ee6a4SAndroid Build Coastguard Worker num_capsets: Le32::from(num_capsets),
1739*bb4ee6a4SAndroid Build Coastguard Worker }
1740*bb4ee6a4SAndroid Build Coastguard Worker }
1741*bb4ee6a4SAndroid Build Coastguard Worker
1742*bb4ee6a4SAndroid Build Coastguard Worker /// Send a request to exit the process to VMM.
send_exit_evt(&self) -> anyhow::Result<()>1743*bb4ee6a4SAndroid Build Coastguard Worker pub fn send_exit_evt(&self) -> anyhow::Result<()> {
1744*bb4ee6a4SAndroid Build Coastguard Worker self.exit_evt_wrtube
1745*bb4ee6a4SAndroid Build Coastguard Worker .send::<VmEventType>(&VmEventType::Exit)
1746*bb4ee6a4SAndroid Build Coastguard Worker .context("failed to send exit event")
1747*bb4ee6a4SAndroid Build Coastguard Worker }
1748*bb4ee6a4SAndroid Build Coastguard Worker }
1749*bb4ee6a4SAndroid Build Coastguard Worker
1750*bb4ee6a4SAndroid Build Coastguard Worker impl VirtioDevice for Gpu {
keep_rds(&self) -> Vec<RawDescriptor>1751*bb4ee6a4SAndroid Build Coastguard Worker fn keep_rds(&self) -> Vec<RawDescriptor> {
1752*bb4ee6a4SAndroid Build Coastguard Worker let mut keep_rds = Vec::new();
1753*bb4ee6a4SAndroid Build Coastguard Worker
1754*bb4ee6a4SAndroid Build Coastguard Worker // To find the RawDescriptor associated with stdout and stderr on Windows is difficult.
1755*bb4ee6a4SAndroid Build Coastguard Worker // Resource bridges are used only for Wayland displays. There is also no meaningful way
1756*bb4ee6a4SAndroid Build Coastguard Worker // casting the underlying DMA buffer wrapped in File to a copyable RawDescriptor.
1757*bb4ee6a4SAndroid Build Coastguard Worker // TODO(davidriley): Remove once virgl has another path to include
1758*bb4ee6a4SAndroid Build Coastguard Worker // debugging logs.
1759*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(any(target_os = "android", target_os = "linux"))]
1760*bb4ee6a4SAndroid Build Coastguard Worker if cfg!(debug_assertions) {
1761*bb4ee6a4SAndroid Build Coastguard Worker keep_rds.push(libc::STDOUT_FILENO);
1762*bb4ee6a4SAndroid Build Coastguard Worker keep_rds.push(libc::STDERR_FILENO);
1763*bb4ee6a4SAndroid Build Coastguard Worker }
1764*bb4ee6a4SAndroid Build Coastguard Worker
1765*bb4ee6a4SAndroid Build Coastguard Worker if let Some(ref mapper) = *self.mapper.lock() {
1766*bb4ee6a4SAndroid Build Coastguard Worker if let Some(descriptor) = mapper.as_raw_descriptor() {
1767*bb4ee6a4SAndroid Build Coastguard Worker keep_rds.push(descriptor);
1768*bb4ee6a4SAndroid Build Coastguard Worker }
1769*bb4ee6a4SAndroid Build Coastguard Worker }
1770*bb4ee6a4SAndroid Build Coastguard Worker
1771*bb4ee6a4SAndroid Build Coastguard Worker if let Some(ref rutabaga_server_descriptor) = self.rutabaga_server_descriptor {
1772*bb4ee6a4SAndroid Build Coastguard Worker keep_rds.push(rutabaga_server_descriptor.as_raw_descriptor());
1773*bb4ee6a4SAndroid Build Coastguard Worker }
1774*bb4ee6a4SAndroid Build Coastguard Worker
1775*bb4ee6a4SAndroid Build Coastguard Worker keep_rds.push(self.exit_evt_wrtube.as_raw_descriptor());
1776*bb4ee6a4SAndroid Build Coastguard Worker
1777*bb4ee6a4SAndroid Build Coastguard Worker if let Some(gpu_control_tube) = &self.gpu_control_tube {
1778*bb4ee6a4SAndroid Build Coastguard Worker keep_rds.push(gpu_control_tube.as_raw_descriptor());
1779*bb4ee6a4SAndroid Build Coastguard Worker }
1780*bb4ee6a4SAndroid Build Coastguard Worker
1781*bb4ee6a4SAndroid Build Coastguard Worker if let Some(resource_bridges) = &self.resource_bridges {
1782*bb4ee6a4SAndroid Build Coastguard Worker resource_bridges.append_raw_descriptors(&mut keep_rds);
1783*bb4ee6a4SAndroid Build Coastguard Worker }
1784*bb4ee6a4SAndroid Build Coastguard Worker
1785*bb4ee6a4SAndroid Build Coastguard Worker for event_device in self.event_devices.iter().flatten() {
1786*bb4ee6a4SAndroid Build Coastguard Worker keep_rds.push(event_device.as_raw_descriptor());
1787*bb4ee6a4SAndroid Build Coastguard Worker }
1788*bb4ee6a4SAndroid Build Coastguard Worker
1789*bb4ee6a4SAndroid Build Coastguard Worker keep_rds
1790*bb4ee6a4SAndroid Build Coastguard Worker }
1791*bb4ee6a4SAndroid Build Coastguard Worker
device_type(&self) -> DeviceType1792*bb4ee6a4SAndroid Build Coastguard Worker fn device_type(&self) -> DeviceType {
1793*bb4ee6a4SAndroid Build Coastguard Worker DeviceType::Gpu
1794*bb4ee6a4SAndroid Build Coastguard Worker }
1795*bb4ee6a4SAndroid Build Coastguard Worker
queue_max_sizes(&self) -> &[u16]1796*bb4ee6a4SAndroid Build Coastguard Worker fn queue_max_sizes(&self) -> &[u16] {
1797*bb4ee6a4SAndroid Build Coastguard Worker QUEUE_SIZES
1798*bb4ee6a4SAndroid Build Coastguard Worker }
1799*bb4ee6a4SAndroid Build Coastguard Worker
features(&self) -> u641800*bb4ee6a4SAndroid Build Coastguard Worker fn features(&self) -> u64 {
1801*bb4ee6a4SAndroid Build Coastguard Worker let mut virtio_gpu_features = 1 << VIRTIO_GPU_F_EDID;
1802*bb4ee6a4SAndroid Build Coastguard Worker
1803*bb4ee6a4SAndroid Build Coastguard Worker // If a non-2D component is specified, enable 3D features. It is possible to run display
1804*bb4ee6a4SAndroid Build Coastguard Worker // contexts without 3D backend (i.e, gfxstream / virglrender), so check for that too.
1805*bb4ee6a4SAndroid Build Coastguard Worker if self.rutabaga_component != RutabagaComponentType::Rutabaga2D || self.capset_mask != 0 {
1806*bb4ee6a4SAndroid Build Coastguard Worker virtio_gpu_features |= 1 << VIRTIO_GPU_F_VIRGL
1807*bb4ee6a4SAndroid Build Coastguard Worker | 1 << VIRTIO_GPU_F_RESOURCE_UUID
1808*bb4ee6a4SAndroid Build Coastguard Worker | 1 << VIRTIO_GPU_F_RESOURCE_BLOB
1809*bb4ee6a4SAndroid Build Coastguard Worker | 1 << VIRTIO_GPU_F_CONTEXT_INIT
1810*bb4ee6a4SAndroid Build Coastguard Worker | 1 << VIRTIO_GPU_F_EDID;
1811*bb4ee6a4SAndroid Build Coastguard Worker
1812*bb4ee6a4SAndroid Build Coastguard Worker if self.udmabuf {
1813*bb4ee6a4SAndroid Build Coastguard Worker virtio_gpu_features |= 1 << VIRTIO_GPU_F_CREATE_GUEST_HANDLE;
1814*bb4ee6a4SAndroid Build Coastguard Worker }
1815*bb4ee6a4SAndroid Build Coastguard Worker
1816*bb4ee6a4SAndroid Build Coastguard Worker // New experimental/unstable feature, not upstreamed.
1817*bb4ee6a4SAndroid Build Coastguard Worker // Safe to enable because guest must explicitly opt-in.
1818*bb4ee6a4SAndroid Build Coastguard Worker virtio_gpu_features |= 1 << VIRTIO_GPU_F_FENCE_PASSING;
1819*bb4ee6a4SAndroid Build Coastguard Worker }
1820*bb4ee6a4SAndroid Build Coastguard Worker
1821*bb4ee6a4SAndroid Build Coastguard Worker self.base_features | virtio_gpu_features
1822*bb4ee6a4SAndroid Build Coastguard Worker }
1823*bb4ee6a4SAndroid Build Coastguard Worker
ack_features(&mut self, value: u64)1824*bb4ee6a4SAndroid Build Coastguard Worker fn ack_features(&mut self, value: u64) {
1825*bb4ee6a4SAndroid Build Coastguard Worker let _ = value;
1826*bb4ee6a4SAndroid Build Coastguard Worker }
1827*bb4ee6a4SAndroid Build Coastguard Worker
read_config(&self, offset: u64, data: &mut [u8])1828*bb4ee6a4SAndroid Build Coastguard Worker fn read_config(&self, offset: u64, data: &mut [u8]) {
1829*bb4ee6a4SAndroid Build Coastguard Worker copy_config(data, 0, self.get_config().as_bytes(), offset);
1830*bb4ee6a4SAndroid Build Coastguard Worker }
1831*bb4ee6a4SAndroid Build Coastguard Worker
write_config(&mut self, offset: u64, data: &[u8])1832*bb4ee6a4SAndroid Build Coastguard Worker fn write_config(&mut self, offset: u64, data: &[u8]) {
1833*bb4ee6a4SAndroid Build Coastguard Worker let mut cfg = self.get_config();
1834*bb4ee6a4SAndroid Build Coastguard Worker copy_config(cfg.as_bytes_mut(), offset, data, 0);
1835*bb4ee6a4SAndroid Build Coastguard Worker if (cfg.events_clear.to_native() & VIRTIO_GPU_EVENT_DISPLAY) != 0 {
1836*bb4ee6a4SAndroid Build Coastguard Worker self.display_event.store(false, Ordering::Relaxed);
1837*bb4ee6a4SAndroid Build Coastguard Worker }
1838*bb4ee6a4SAndroid Build Coastguard Worker }
1839*bb4ee6a4SAndroid Build Coastguard Worker
on_device_sandboxed(&mut self)1840*bb4ee6a4SAndroid Build Coastguard Worker fn on_device_sandboxed(&mut self) {
1841*bb4ee6a4SAndroid Build Coastguard Worker // Unlike most Virtio devices which start their worker thread in activate(),
1842*bb4ee6a4SAndroid Build Coastguard Worker // the Gpu's worker thread is started earlier here so that rutabaga and the
1843*bb4ee6a4SAndroid Build Coastguard Worker // underlying render server have a chance to initialize before the guest OS
1844*bb4ee6a4SAndroid Build Coastguard Worker // starts. This is needed because the Virtio GPU kernel module has a timeout
1845*bb4ee6a4SAndroid Build Coastguard Worker // for some calls during initialization and some host GPU drivers have been
1846*bb4ee6a4SAndroid Build Coastguard Worker // observed to be extremely slow to initialize on fresh GCE instances. The
1847*bb4ee6a4SAndroid Build Coastguard Worker // entire worker thread is started here (as opposed to just initializing
1848*bb4ee6a4SAndroid Build Coastguard Worker // rutabaga and the underlying render server) as OpenGL based renderers may
1849*bb4ee6a4SAndroid Build Coastguard Worker // expect to be initialized on the same thread that later processes commands.
1850*bb4ee6a4SAndroid Build Coastguard Worker self.start_worker_thread();
1851*bb4ee6a4SAndroid Build Coastguard Worker }
1852*bb4ee6a4SAndroid Build Coastguard Worker
activate( &mut self, mem: GuestMemory, interrupt: Interrupt, mut queues: BTreeMap<usize, Queue>, ) -> anyhow::Result<()>1853*bb4ee6a4SAndroid Build Coastguard Worker fn activate(
1854*bb4ee6a4SAndroid Build Coastguard Worker &mut self,
1855*bb4ee6a4SAndroid Build Coastguard Worker mem: GuestMemory,
1856*bb4ee6a4SAndroid Build Coastguard Worker interrupt: Interrupt,
1857*bb4ee6a4SAndroid Build Coastguard Worker mut queues: BTreeMap<usize, Queue>,
1858*bb4ee6a4SAndroid Build Coastguard Worker ) -> anyhow::Result<()> {
1859*bb4ee6a4SAndroid Build Coastguard Worker if queues.len() != QUEUE_SIZES.len() {
1860*bb4ee6a4SAndroid Build Coastguard Worker return Err(anyhow!(
1861*bb4ee6a4SAndroid Build Coastguard Worker "expected {} queues, got {}",
1862*bb4ee6a4SAndroid Build Coastguard Worker QUEUE_SIZES.len(),
1863*bb4ee6a4SAndroid Build Coastguard Worker queues.len()
1864*bb4ee6a4SAndroid Build Coastguard Worker ));
1865*bb4ee6a4SAndroid Build Coastguard Worker }
1866*bb4ee6a4SAndroid Build Coastguard Worker
1867*bb4ee6a4SAndroid Build Coastguard Worker let ctrl_queue = SharedQueueReader::new(queues.remove(&0).unwrap());
1868*bb4ee6a4SAndroid Build Coastguard Worker let cursor_queue = LocalQueueReader::new(queues.remove(&1).unwrap());
1869*bb4ee6a4SAndroid Build Coastguard Worker
1870*bb4ee6a4SAndroid Build Coastguard Worker self.worker_request_sender
1871*bb4ee6a4SAndroid Build Coastguard Worker .as_ref()
1872*bb4ee6a4SAndroid Build Coastguard Worker .context("worker thread missing on activate?")?
1873*bb4ee6a4SAndroid Build Coastguard Worker .send(WorkerRequest::Activate(WorkerActivateRequest {
1874*bb4ee6a4SAndroid Build Coastguard Worker resources: GpuActivationResources {
1875*bb4ee6a4SAndroid Build Coastguard Worker mem,
1876*bb4ee6a4SAndroid Build Coastguard Worker interrupt,
1877*bb4ee6a4SAndroid Build Coastguard Worker ctrl_queue,
1878*bb4ee6a4SAndroid Build Coastguard Worker cursor_queue,
1879*bb4ee6a4SAndroid Build Coastguard Worker },
1880*bb4ee6a4SAndroid Build Coastguard Worker }))
1881*bb4ee6a4SAndroid Build Coastguard Worker .map_err(|e| anyhow!("failed to send virtio gpu worker activate request: {:?}", e))?;
1882*bb4ee6a4SAndroid Build Coastguard Worker
1883*bb4ee6a4SAndroid Build Coastguard Worker self.worker_response_receiver
1884*bb4ee6a4SAndroid Build Coastguard Worker .as_ref()
1885*bb4ee6a4SAndroid Build Coastguard Worker .context("worker thread missing on activate?")?
1886*bb4ee6a4SAndroid Build Coastguard Worker .recv()
1887*bb4ee6a4SAndroid Build Coastguard Worker .inspect(|_| self.worker_state = WorkerState::Active)
1888*bb4ee6a4SAndroid Build Coastguard Worker .inspect_err(|_| self.worker_state = WorkerState::Error)
1889*bb4ee6a4SAndroid Build Coastguard Worker .context("failed to receive response for virtio gpu worker resume request")??;
1890*bb4ee6a4SAndroid Build Coastguard Worker
1891*bb4ee6a4SAndroid Build Coastguard Worker Ok(())
1892*bb4ee6a4SAndroid Build Coastguard Worker }
1893*bb4ee6a4SAndroid Build Coastguard Worker
pci_address(&self) -> Option<PciAddress>1894*bb4ee6a4SAndroid Build Coastguard Worker fn pci_address(&self) -> Option<PciAddress> {
1895*bb4ee6a4SAndroid Build Coastguard Worker self.pci_address
1896*bb4ee6a4SAndroid Build Coastguard Worker }
1897*bb4ee6a4SAndroid Build Coastguard Worker
get_shared_memory_region(&self) -> Option<SharedMemoryRegion>1898*bb4ee6a4SAndroid Build Coastguard Worker fn get_shared_memory_region(&self) -> Option<SharedMemoryRegion> {
1899*bb4ee6a4SAndroid Build Coastguard Worker Some(SharedMemoryRegion {
1900*bb4ee6a4SAndroid Build Coastguard Worker id: VIRTIO_GPU_SHM_ID_HOST_VISIBLE,
1901*bb4ee6a4SAndroid Build Coastguard Worker length: self.pci_bar_size,
1902*bb4ee6a4SAndroid Build Coastguard Worker })
1903*bb4ee6a4SAndroid Build Coastguard Worker }
1904*bb4ee6a4SAndroid Build Coastguard Worker
set_shared_memory_mapper(&mut self, mapper: Box<dyn SharedMemoryMapper>)1905*bb4ee6a4SAndroid Build Coastguard Worker fn set_shared_memory_mapper(&mut self, mapper: Box<dyn SharedMemoryMapper>) {
1906*bb4ee6a4SAndroid Build Coastguard Worker self.mapper.lock().replace(mapper);
1907*bb4ee6a4SAndroid Build Coastguard Worker }
1908*bb4ee6a4SAndroid Build Coastguard Worker
expose_shmem_descriptors_with_viommu(&self) -> bool1909*bb4ee6a4SAndroid Build Coastguard Worker fn expose_shmem_descriptors_with_viommu(&self) -> bool {
1910*bb4ee6a4SAndroid Build Coastguard Worker // TODO(b/323368701): integrate with fixed_blob_mapping so this can always return true.
1911*bb4ee6a4SAndroid Build Coastguard Worker !self.fixed_blob_mapping
1912*bb4ee6a4SAndroid Build Coastguard Worker }
1913*bb4ee6a4SAndroid Build Coastguard Worker
get_shared_memory_prepare_type(&mut self) -> SharedMemoryPrepareType1914*bb4ee6a4SAndroid Build Coastguard Worker fn get_shared_memory_prepare_type(&mut self) -> SharedMemoryPrepareType {
1915*bb4ee6a4SAndroid Build Coastguard Worker if self.fixed_blob_mapping {
1916*bb4ee6a4SAndroid Build Coastguard Worker let cache_type = if cfg!(feature = "noncoherent-dma") {
1917*bb4ee6a4SAndroid Build Coastguard Worker MemCacheType::CacheNonCoherent
1918*bb4ee6a4SAndroid Build Coastguard Worker } else {
1919*bb4ee6a4SAndroid Build Coastguard Worker MemCacheType::CacheCoherent
1920*bb4ee6a4SAndroid Build Coastguard Worker };
1921*bb4ee6a4SAndroid Build Coastguard Worker SharedMemoryPrepareType::SingleMappingOnFirst(cache_type)
1922*bb4ee6a4SAndroid Build Coastguard Worker } else {
1923*bb4ee6a4SAndroid Build Coastguard Worker SharedMemoryPrepareType::DynamicPerMapping
1924*bb4ee6a4SAndroid Build Coastguard Worker }
1925*bb4ee6a4SAndroid Build Coastguard Worker }
1926*bb4ee6a4SAndroid Build Coastguard Worker
1927*bb4ee6a4SAndroid Build Coastguard Worker // Notes on sleep/wake/snapshot/restore functionality.
1928*bb4ee6a4SAndroid Build Coastguard Worker //
1929*bb4ee6a4SAndroid Build Coastguard Worker // * Only 2d mode is supported so far.
1930*bb4ee6a4SAndroid Build Coastguard Worker // * We only snapshot the state relevant to the virtio-gpu 2d mode protocol (i.e. scanouts,
1931*bb4ee6a4SAndroid Build Coastguard Worker // resources, fences).
1932*bb4ee6a4SAndroid Build Coastguard Worker // * The GpuDisplay is recreated from scratch, we don't want to snapshot the state of a
1933*bb4ee6a4SAndroid Build Coastguard Worker // Wayland socket (for example).
1934*bb4ee6a4SAndroid Build Coastguard Worker // * No state about pending virtio requests needs to be snapshotted because the 2d backend
1935*bb4ee6a4SAndroid Build Coastguard Worker // completes them synchronously.
virtio_sleep(&mut self) -> anyhow::Result<Option<BTreeMap<usize, Queue>>>1936*bb4ee6a4SAndroid Build Coastguard Worker fn virtio_sleep(&mut self) -> anyhow::Result<Option<BTreeMap<usize, Queue>>> {
1937*bb4ee6a4SAndroid Build Coastguard Worker match self.worker_state {
1938*bb4ee6a4SAndroid Build Coastguard Worker WorkerState::Error => {
1939*bb4ee6a4SAndroid Build Coastguard Worker return Err(anyhow!(
1940*bb4ee6a4SAndroid Build Coastguard Worker "failed to sleep virtio gpu worker which is in error state"
1941*bb4ee6a4SAndroid Build Coastguard Worker ));
1942*bb4ee6a4SAndroid Build Coastguard Worker }
1943*bb4ee6a4SAndroid Build Coastguard Worker WorkerState::Inactive => {
1944*bb4ee6a4SAndroid Build Coastguard Worker return Ok(None);
1945*bb4ee6a4SAndroid Build Coastguard Worker }
1946*bb4ee6a4SAndroid Build Coastguard Worker _ => (),
1947*bb4ee6a4SAndroid Build Coastguard Worker };
1948*bb4ee6a4SAndroid Build Coastguard Worker
1949*bb4ee6a4SAndroid Build Coastguard Worker if let (
1950*bb4ee6a4SAndroid Build Coastguard Worker Some(worker_request_sender),
1951*bb4ee6a4SAndroid Build Coastguard Worker Some(worker_response_receiver),
1952*bb4ee6a4SAndroid Build Coastguard Worker Some(worker_suspend_evt),
1953*bb4ee6a4SAndroid Build Coastguard Worker ) = (
1954*bb4ee6a4SAndroid Build Coastguard Worker &self.worker_request_sender,
1955*bb4ee6a4SAndroid Build Coastguard Worker &self.worker_response_receiver,
1956*bb4ee6a4SAndroid Build Coastguard Worker &self.worker_suspend_evt,
1957*bb4ee6a4SAndroid Build Coastguard Worker ) {
1958*bb4ee6a4SAndroid Build Coastguard Worker worker_request_sender
1959*bb4ee6a4SAndroid Build Coastguard Worker .send(WorkerRequest::Suspend)
1960*bb4ee6a4SAndroid Build Coastguard Worker .map_err(|e| {
1961*bb4ee6a4SAndroid Build Coastguard Worker anyhow!(
1962*bb4ee6a4SAndroid Build Coastguard Worker "failed to send suspend request to virtio gpu worker: {:?}",
1963*bb4ee6a4SAndroid Build Coastguard Worker e
1964*bb4ee6a4SAndroid Build Coastguard Worker )
1965*bb4ee6a4SAndroid Build Coastguard Worker })?;
1966*bb4ee6a4SAndroid Build Coastguard Worker
1967*bb4ee6a4SAndroid Build Coastguard Worker worker_suspend_evt
1968*bb4ee6a4SAndroid Build Coastguard Worker .signal()
1969*bb4ee6a4SAndroid Build Coastguard Worker .context("failed to signal virtio gpu worker suspend event")?;
1970*bb4ee6a4SAndroid Build Coastguard Worker
1971*bb4ee6a4SAndroid Build Coastguard Worker let response = worker_response_receiver
1972*bb4ee6a4SAndroid Build Coastguard Worker .recv()
1973*bb4ee6a4SAndroid Build Coastguard Worker .inspect(|_| self.worker_state = WorkerState::Inactive)
1974*bb4ee6a4SAndroid Build Coastguard Worker .inspect_err(|_| self.worker_state = WorkerState::Error)
1975*bb4ee6a4SAndroid Build Coastguard Worker .context("failed to receive response for virtio gpu worker suspend request")??;
1976*bb4ee6a4SAndroid Build Coastguard Worker
1977*bb4ee6a4SAndroid Build Coastguard Worker worker_suspend_evt
1978*bb4ee6a4SAndroid Build Coastguard Worker .reset()
1979*bb4ee6a4SAndroid Build Coastguard Worker .context("failed to reset virtio gpu worker suspend event")?;
1980*bb4ee6a4SAndroid Build Coastguard Worker
1981*bb4ee6a4SAndroid Build Coastguard Worker match response {
1982*bb4ee6a4SAndroid Build Coastguard Worker WorkerResponse::Suspend(deactivation_resources) => Ok(deactivation_resources
1983*bb4ee6a4SAndroid Build Coastguard Worker .queues
1984*bb4ee6a4SAndroid Build Coastguard Worker .map(|q| q.into_iter().enumerate().collect())),
1985*bb4ee6a4SAndroid Build Coastguard Worker _ => {
1986*bb4ee6a4SAndroid Build Coastguard Worker panic!("unexpected response from virtio gpu worker sleep request");
1987*bb4ee6a4SAndroid Build Coastguard Worker }
1988*bb4ee6a4SAndroid Build Coastguard Worker }
1989*bb4ee6a4SAndroid Build Coastguard Worker } else {
1990*bb4ee6a4SAndroid Build Coastguard Worker Err(anyhow!("virtio gpu worker not available for sleep"))
1991*bb4ee6a4SAndroid Build Coastguard Worker }
1992*bb4ee6a4SAndroid Build Coastguard Worker }
1993*bb4ee6a4SAndroid Build Coastguard Worker
virtio_wake( &mut self, queues_state: Option<(GuestMemory, Interrupt, BTreeMap<usize, Queue>)>, ) -> anyhow::Result<()>1994*bb4ee6a4SAndroid Build Coastguard Worker fn virtio_wake(
1995*bb4ee6a4SAndroid Build Coastguard Worker &mut self,
1996*bb4ee6a4SAndroid Build Coastguard Worker queues_state: Option<(GuestMemory, Interrupt, BTreeMap<usize, Queue>)>,
1997*bb4ee6a4SAndroid Build Coastguard Worker ) -> anyhow::Result<()> {
1998*bb4ee6a4SAndroid Build Coastguard Worker match self.worker_state {
1999*bb4ee6a4SAndroid Build Coastguard Worker WorkerState::Error => {
2000*bb4ee6a4SAndroid Build Coastguard Worker return Err(anyhow!(
2001*bb4ee6a4SAndroid Build Coastguard Worker "failed to wake virtio gpu worker which is in error state"
2002*bb4ee6a4SAndroid Build Coastguard Worker ));
2003*bb4ee6a4SAndroid Build Coastguard Worker }
2004*bb4ee6a4SAndroid Build Coastguard Worker WorkerState::Active => {
2005*bb4ee6a4SAndroid Build Coastguard Worker return Ok(());
2006*bb4ee6a4SAndroid Build Coastguard Worker }
2007*bb4ee6a4SAndroid Build Coastguard Worker _ => (),
2008*bb4ee6a4SAndroid Build Coastguard Worker };
2009*bb4ee6a4SAndroid Build Coastguard Worker
2010*bb4ee6a4SAndroid Build Coastguard Worker match queues_state {
2011*bb4ee6a4SAndroid Build Coastguard Worker None => Ok(()),
2012*bb4ee6a4SAndroid Build Coastguard Worker Some((mem, interrupt, queues)) => {
2013*bb4ee6a4SAndroid Build Coastguard Worker // TODO(khei): activate is just what we want at the moment, but we should probably
2014*bb4ee6a4SAndroid Build Coastguard Worker // move it into a "start workers" function to make it obvious that it isn't
2015*bb4ee6a4SAndroid Build Coastguard Worker // strictly used for activate events.
2016*bb4ee6a4SAndroid Build Coastguard Worker self.activate(mem, interrupt, queues)?;
2017*bb4ee6a4SAndroid Build Coastguard Worker Ok(())
2018*bb4ee6a4SAndroid Build Coastguard Worker }
2019*bb4ee6a4SAndroid Build Coastguard Worker }
2020*bb4ee6a4SAndroid Build Coastguard Worker }
2021*bb4ee6a4SAndroid Build Coastguard Worker
virtio_snapshot(&mut self) -> anyhow::Result<serde_json::Value>2022*bb4ee6a4SAndroid Build Coastguard Worker fn virtio_snapshot(&mut self) -> anyhow::Result<serde_json::Value> {
2023*bb4ee6a4SAndroid Build Coastguard Worker match self.worker_state {
2024*bb4ee6a4SAndroid Build Coastguard Worker WorkerState::Error => {
2025*bb4ee6a4SAndroid Build Coastguard Worker return Err(anyhow!(
2026*bb4ee6a4SAndroid Build Coastguard Worker "failed to snapshot virtio gpu worker which is in error state"
2027*bb4ee6a4SAndroid Build Coastguard Worker ));
2028*bb4ee6a4SAndroid Build Coastguard Worker }
2029*bb4ee6a4SAndroid Build Coastguard Worker WorkerState::Active => {
2030*bb4ee6a4SAndroid Build Coastguard Worker return Err(anyhow!(
2031*bb4ee6a4SAndroid Build Coastguard Worker "failed to snapshot virtio gpu worker which is in active state"
2032*bb4ee6a4SAndroid Build Coastguard Worker ));
2033*bb4ee6a4SAndroid Build Coastguard Worker }
2034*bb4ee6a4SAndroid Build Coastguard Worker _ => (),
2035*bb4ee6a4SAndroid Build Coastguard Worker };
2036*bb4ee6a4SAndroid Build Coastguard Worker
2037*bb4ee6a4SAndroid Build Coastguard Worker if let (Some(worker_request_sender), Some(worker_response_receiver)) =
2038*bb4ee6a4SAndroid Build Coastguard Worker (&self.worker_request_sender, &self.worker_response_receiver)
2039*bb4ee6a4SAndroid Build Coastguard Worker {
2040*bb4ee6a4SAndroid Build Coastguard Worker worker_request_sender
2041*bb4ee6a4SAndroid Build Coastguard Worker .send(WorkerRequest::Snapshot)
2042*bb4ee6a4SAndroid Build Coastguard Worker .map_err(|e| {
2043*bb4ee6a4SAndroid Build Coastguard Worker anyhow!(
2044*bb4ee6a4SAndroid Build Coastguard Worker "failed to send snapshot request to virtio gpu worker: {:?}",
2045*bb4ee6a4SAndroid Build Coastguard Worker e
2046*bb4ee6a4SAndroid Build Coastguard Worker )
2047*bb4ee6a4SAndroid Build Coastguard Worker })?;
2048*bb4ee6a4SAndroid Build Coastguard Worker
2049*bb4ee6a4SAndroid Build Coastguard Worker match worker_response_receiver
2050*bb4ee6a4SAndroid Build Coastguard Worker .recv()
2051*bb4ee6a4SAndroid Build Coastguard Worker .inspect_err(|_| self.worker_state = WorkerState::Error)
2052*bb4ee6a4SAndroid Build Coastguard Worker .context("failed to receive response for virtio gpu worker suspend request")??
2053*bb4ee6a4SAndroid Build Coastguard Worker {
2054*bb4ee6a4SAndroid Build Coastguard Worker WorkerResponse::Snapshot(snapshot) => Ok(serde_json::to_value(snapshot)?),
2055*bb4ee6a4SAndroid Build Coastguard Worker _ => {
2056*bb4ee6a4SAndroid Build Coastguard Worker panic!("unexpected response from virtio gpu worker sleep request");
2057*bb4ee6a4SAndroid Build Coastguard Worker }
2058*bb4ee6a4SAndroid Build Coastguard Worker }
2059*bb4ee6a4SAndroid Build Coastguard Worker } else {
2060*bb4ee6a4SAndroid Build Coastguard Worker Err(anyhow!("virtio gpu worker not available for snapshot"))
2061*bb4ee6a4SAndroid Build Coastguard Worker }
2062*bb4ee6a4SAndroid Build Coastguard Worker }
2063*bb4ee6a4SAndroid Build Coastguard Worker
virtio_restore(&mut self, data: serde_json::Value) -> anyhow::Result<()>2064*bb4ee6a4SAndroid Build Coastguard Worker fn virtio_restore(&mut self, data: serde_json::Value) -> anyhow::Result<()> {
2065*bb4ee6a4SAndroid Build Coastguard Worker match self.worker_state {
2066*bb4ee6a4SAndroid Build Coastguard Worker WorkerState::Error => {
2067*bb4ee6a4SAndroid Build Coastguard Worker return Err(anyhow!(
2068*bb4ee6a4SAndroid Build Coastguard Worker "failed to restore virtio gpu worker which is in error state"
2069*bb4ee6a4SAndroid Build Coastguard Worker ));
2070*bb4ee6a4SAndroid Build Coastguard Worker }
2071*bb4ee6a4SAndroid Build Coastguard Worker WorkerState::Active => {
2072*bb4ee6a4SAndroid Build Coastguard Worker return Err(anyhow!(
2073*bb4ee6a4SAndroid Build Coastguard Worker "failed to restore virtio gpu worker which is in active state"
2074*bb4ee6a4SAndroid Build Coastguard Worker ));
2075*bb4ee6a4SAndroid Build Coastguard Worker }
2076*bb4ee6a4SAndroid Build Coastguard Worker _ => (),
2077*bb4ee6a4SAndroid Build Coastguard Worker };
2078*bb4ee6a4SAndroid Build Coastguard Worker
2079*bb4ee6a4SAndroid Build Coastguard Worker let snapshot: WorkerSnapshot = serde_json::from_value(data)?;
2080*bb4ee6a4SAndroid Build Coastguard Worker
2081*bb4ee6a4SAndroid Build Coastguard Worker if let (Some(worker_request_sender), Some(worker_response_receiver)) =
2082*bb4ee6a4SAndroid Build Coastguard Worker (&self.worker_request_sender, &self.worker_response_receiver)
2083*bb4ee6a4SAndroid Build Coastguard Worker {
2084*bb4ee6a4SAndroid Build Coastguard Worker worker_request_sender
2085*bb4ee6a4SAndroid Build Coastguard Worker .send(WorkerRequest::Restore(snapshot))
2086*bb4ee6a4SAndroid Build Coastguard Worker .map_err(|e| {
2087*bb4ee6a4SAndroid Build Coastguard Worker anyhow!(
2088*bb4ee6a4SAndroid Build Coastguard Worker "failed to send suspend request to virtio gpu worker: {:?}",
2089*bb4ee6a4SAndroid Build Coastguard Worker e
2090*bb4ee6a4SAndroid Build Coastguard Worker )
2091*bb4ee6a4SAndroid Build Coastguard Worker })?;
2092*bb4ee6a4SAndroid Build Coastguard Worker
2093*bb4ee6a4SAndroid Build Coastguard Worker let response = worker_response_receiver
2094*bb4ee6a4SAndroid Build Coastguard Worker .recv()
2095*bb4ee6a4SAndroid Build Coastguard Worker .inspect_err(|_| self.worker_state = WorkerState::Error)
2096*bb4ee6a4SAndroid Build Coastguard Worker .context("failed to receive response for virtio gpu worker suspend request")??;
2097*bb4ee6a4SAndroid Build Coastguard Worker
2098*bb4ee6a4SAndroid Build Coastguard Worker match response {
2099*bb4ee6a4SAndroid Build Coastguard Worker WorkerResponse::Ok => Ok(()),
2100*bb4ee6a4SAndroid Build Coastguard Worker _ => {
2101*bb4ee6a4SAndroid Build Coastguard Worker panic!("unexpected response from virtio gpu worker sleep request");
2102*bb4ee6a4SAndroid Build Coastguard Worker }
2103*bb4ee6a4SAndroid Build Coastguard Worker }
2104*bb4ee6a4SAndroid Build Coastguard Worker } else {
2105*bb4ee6a4SAndroid Build Coastguard Worker Err(anyhow!("virtio gpu worker not available for restore"))
2106*bb4ee6a4SAndroid Build Coastguard Worker }
2107*bb4ee6a4SAndroid Build Coastguard Worker }
2108*bb4ee6a4SAndroid Build Coastguard Worker
reset(&mut self) -> anyhow::Result<()>2109*bb4ee6a4SAndroid Build Coastguard Worker fn reset(&mut self) -> anyhow::Result<()> {
2110*bb4ee6a4SAndroid Build Coastguard Worker self.stop_worker_thread();
2111*bb4ee6a4SAndroid Build Coastguard Worker Ok(())
2112*bb4ee6a4SAndroid Build Coastguard Worker }
2113*bb4ee6a4SAndroid Build Coastguard Worker }
2114*bb4ee6a4SAndroid Build Coastguard Worker
2115*bb4ee6a4SAndroid Build Coastguard Worker impl Drop for Gpu {
drop(&mut self)2116*bb4ee6a4SAndroid Build Coastguard Worker fn drop(&mut self) {
2117*bb4ee6a4SAndroid Build Coastguard Worker let _ = self.reset();
2118*bb4ee6a4SAndroid Build Coastguard Worker }
2119*bb4ee6a4SAndroid Build Coastguard Worker }
2120*bb4ee6a4SAndroid Build Coastguard Worker
2121*bb4ee6a4SAndroid Build Coastguard Worker /// This struct takes the ownership of resource bridges and tracks which ones should be processed.
2122*bb4ee6a4SAndroid Build Coastguard Worker struct ResourceBridges {
2123*bb4ee6a4SAndroid Build Coastguard Worker resource_bridges: Vec<Tube>,
2124*bb4ee6a4SAndroid Build Coastguard Worker should_process: Vec<bool>,
2125*bb4ee6a4SAndroid Build Coastguard Worker }
2126*bb4ee6a4SAndroid Build Coastguard Worker
2127*bb4ee6a4SAndroid Build Coastguard Worker impl ResourceBridges {
new(resource_bridges: Vec<Tube>) -> Self2128*bb4ee6a4SAndroid Build Coastguard Worker pub fn new(resource_bridges: Vec<Tube>) -> Self {
2129*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(windows)]
2130*bb4ee6a4SAndroid Build Coastguard Worker assert!(
2131*bb4ee6a4SAndroid Build Coastguard Worker resource_bridges.is_empty(),
2132*bb4ee6a4SAndroid Build Coastguard Worker "resource bridges are not supported on Windows"
2133*bb4ee6a4SAndroid Build Coastguard Worker );
2134*bb4ee6a4SAndroid Build Coastguard Worker
2135*bb4ee6a4SAndroid Build Coastguard Worker let mut resource_bridges = Self {
2136*bb4ee6a4SAndroid Build Coastguard Worker resource_bridges,
2137*bb4ee6a4SAndroid Build Coastguard Worker should_process: Default::default(),
2138*bb4ee6a4SAndroid Build Coastguard Worker };
2139*bb4ee6a4SAndroid Build Coastguard Worker resource_bridges.reset_should_process();
2140*bb4ee6a4SAndroid Build Coastguard Worker resource_bridges
2141*bb4ee6a4SAndroid Build Coastguard Worker }
2142*bb4ee6a4SAndroid Build Coastguard Worker
2143*bb4ee6a4SAndroid Build Coastguard Worker // Appends raw descriptors of all resource bridges to the given vector.
append_raw_descriptors(&self, rds: &mut Vec<RawDescriptor>)2144*bb4ee6a4SAndroid Build Coastguard Worker pub fn append_raw_descriptors(&self, rds: &mut Vec<RawDescriptor>) {
2145*bb4ee6a4SAndroid Build Coastguard Worker for bridge in &self.resource_bridges {
2146*bb4ee6a4SAndroid Build Coastguard Worker rds.push(bridge.as_raw_descriptor());
2147*bb4ee6a4SAndroid Build Coastguard Worker }
2148*bb4ee6a4SAndroid Build Coastguard Worker }
2149*bb4ee6a4SAndroid Build Coastguard Worker
2150*bb4ee6a4SAndroid Build Coastguard Worker /// Adds all resource bridges to WaitContext.
add_to_wait_context(&self, wait_ctx: &mut WaitContext<WorkerToken>)2151*bb4ee6a4SAndroid Build Coastguard Worker pub fn add_to_wait_context(&self, wait_ctx: &mut WaitContext<WorkerToken>) {
2152*bb4ee6a4SAndroid Build Coastguard Worker for (index, bridge) in self.resource_bridges.iter().enumerate() {
2153*bb4ee6a4SAndroid Build Coastguard Worker if let Err(e) = wait_ctx.add(bridge, WorkerToken::ResourceBridge { index }) {
2154*bb4ee6a4SAndroid Build Coastguard Worker error!("failed to add resource bridge to WaitContext: {}", e);
2155*bb4ee6a4SAndroid Build Coastguard Worker }
2156*bb4ee6a4SAndroid Build Coastguard Worker }
2157*bb4ee6a4SAndroid Build Coastguard Worker }
2158*bb4ee6a4SAndroid Build Coastguard Worker
2159*bb4ee6a4SAndroid Build Coastguard Worker /// Marks that the resource bridge at the given index should be processed when
2160*bb4ee6a4SAndroid Build Coastguard Worker /// `process_resource_bridges()` is called.
set_should_process(&mut self, index: usize)2161*bb4ee6a4SAndroid Build Coastguard Worker pub fn set_should_process(&mut self, index: usize) {
2162*bb4ee6a4SAndroid Build Coastguard Worker self.should_process[index] = true;
2163*bb4ee6a4SAndroid Build Coastguard Worker }
2164*bb4ee6a4SAndroid Build Coastguard Worker
2165*bb4ee6a4SAndroid Build Coastguard Worker /// Processes all resource bridges that have been marked as should be processed. The markings
2166*bb4ee6a4SAndroid Build Coastguard Worker /// will be cleared before returning. Faulty resource bridges will be removed from WaitContext.
process_resource_bridges( &mut self, state: &mut Frontend, wait_ctx: &mut WaitContext<WorkerToken>, )2167*bb4ee6a4SAndroid Build Coastguard Worker pub fn process_resource_bridges(
2168*bb4ee6a4SAndroid Build Coastguard Worker &mut self,
2169*bb4ee6a4SAndroid Build Coastguard Worker state: &mut Frontend,
2170*bb4ee6a4SAndroid Build Coastguard Worker wait_ctx: &mut WaitContext<WorkerToken>,
2171*bb4ee6a4SAndroid Build Coastguard Worker ) {
2172*bb4ee6a4SAndroid Build Coastguard Worker for (bridge, &should_process) in self.resource_bridges.iter().zip(&self.should_process) {
2173*bb4ee6a4SAndroid Build Coastguard Worker if should_process {
2174*bb4ee6a4SAndroid Build Coastguard Worker if let Err(e) = state.process_resource_bridge(bridge) {
2175*bb4ee6a4SAndroid Build Coastguard Worker error!("Failed to process resource bridge: {:#}", e);
2176*bb4ee6a4SAndroid Build Coastguard Worker error!("Removing that resource bridge from the wait context.");
2177*bb4ee6a4SAndroid Build Coastguard Worker wait_ctx.delete(bridge).unwrap_or_else(|e| {
2178*bb4ee6a4SAndroid Build Coastguard Worker error!("Failed to remove faulty resource bridge: {:#}", e)
2179*bb4ee6a4SAndroid Build Coastguard Worker });
2180*bb4ee6a4SAndroid Build Coastguard Worker }
2181*bb4ee6a4SAndroid Build Coastguard Worker }
2182*bb4ee6a4SAndroid Build Coastguard Worker }
2183*bb4ee6a4SAndroid Build Coastguard Worker self.reset_should_process();
2184*bb4ee6a4SAndroid Build Coastguard Worker }
2185*bb4ee6a4SAndroid Build Coastguard Worker
reset_should_process(&mut self)2186*bb4ee6a4SAndroid Build Coastguard Worker fn reset_should_process(&mut self) {
2187*bb4ee6a4SAndroid Build Coastguard Worker self.should_process.clear();
2188*bb4ee6a4SAndroid Build Coastguard Worker self.should_process
2189*bb4ee6a4SAndroid Build Coastguard Worker .resize(self.resource_bridges.len(), false);
2190*bb4ee6a4SAndroid Build Coastguard Worker }
2191*bb4ee6a4SAndroid Build Coastguard Worker }
2192