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