gpu_display/
gpu_display_stub.rs1use std::collections::HashMap;
6use std::collections::HashSet;
7use std::sync::Arc;
8
9use base::AsRawDescriptor;
10use base::Event;
11use base::RawDescriptor;
12use base::VolatileSlice;
13use sync::Mutex;
14use sync::Waitable;
15use vm_control::gpu::DisplayParameters;
16
17use crate::DisplayExternalResourceImport;
18use crate::DisplayT;
19use crate::FlipToExtraInfo;
20use crate::GpuDisplayError;
21use crate::GpuDisplayFramebuffer;
22use crate::GpuDisplayResult;
23use crate::GpuDisplaySurface;
24use crate::SemaphoreTimepoint;
25use crate::SurfaceType;
26use crate::SysDisplayT;
27
28type StubImportSet = HashSet<u32>;
29
30#[allow(dead_code)]
31struct Buffer {
32 width: u32,
33 _height: u32,
34 bytes_per_pixel: u32,
35 bytes: Vec<u8>,
36}
37
38impl Drop for Buffer {
39 fn drop(&mut self) {}
40}
41
42impl Buffer {
43 fn as_volatile_slice(&mut self) -> VolatileSlice {
44 VolatileSlice::new(self.bytes.as_mut_slice())
45 }
46
47 fn stride(&self) -> usize {
48 (self.bytes_per_pixel as usize) * (self.width as usize)
49 }
50
51 fn bytes_per_pixel(&self) -> usize {
52 self.bytes_per_pixel as usize
53 }
54}
55
56struct StubSurface {
57 width: u32,
58 height: u32,
59 buffer: Option<Buffer>,
60 imports: Arc<Mutex<StubImportSet>>,
61}
62
63impl StubSurface {
64 fn lazily_allocate_buffer(&mut self) -> Option<&mut Buffer> {
66 if self.buffer.is_none() {
67 let bytes_per_pixel = 4;
69 let bytes_total = (self.width as u64) * (self.height as u64) * (bytes_per_pixel as u64);
70
71 self.buffer = Some(Buffer {
72 width: self.width,
73 _height: self.height,
74 bytes_per_pixel,
75 bytes: vec![0; bytes_total as usize],
76 });
77 }
78
79 self.buffer.as_mut()
80 }
81}
82
83impl GpuDisplaySurface for StubSurface {
84 fn framebuffer(&mut self) -> Option<GpuDisplayFramebuffer> {
85 let framebuffer = self.lazily_allocate_buffer()?;
86 let framebuffer_stride = framebuffer.stride() as u32;
87 let framebuffer_bytes_per_pixel = framebuffer.bytes_per_pixel() as u32;
88 Some(GpuDisplayFramebuffer::new(
89 framebuffer.as_volatile_slice(),
90 framebuffer_stride,
91 framebuffer_bytes_per_pixel,
92 ))
93 }
94
95 fn flip_to(
96 &mut self,
97 import_id: u32,
98 _acquire_timepoint: Option<SemaphoreTimepoint>,
99 _release_timepoint: Option<SemaphoreTimepoint>,
100 _extra_info: Option<FlipToExtraInfo>,
101 ) -> anyhow::Result<Waitable> {
102 if !self.imports.lock().contains(&import_id) {
103 return Err(GpuDisplayError::InvalidImportId.into());
104 }
105 Ok(Waitable::signaled())
106 }
107}
108
109impl Drop for StubSurface {
110 fn drop(&mut self) {}
111}
112
113pub struct DisplayStub {
114 event: Event,
116 surface_imports: HashMap<u32, Arc<Mutex<StubImportSet>>>,
117}
118
119impl DisplayStub {
120 pub fn new() -> GpuDisplayResult<DisplayStub> {
121 let event = Event::new().map_err(|_| GpuDisplayError::CreateEvent)?;
122
123 Ok(DisplayStub {
124 event,
125 surface_imports: HashMap::new(),
126 })
127 }
128}
129
130impl DisplayT for DisplayStub {
131 fn create_surface(
132 &mut self,
133 parent_surface_id: Option<u32>,
134 surface_id: u32,
135 _scanout_id: Option<u32>,
136 display_params: &DisplayParameters,
137 _surf_type: SurfaceType,
138 ) -> GpuDisplayResult<Box<dyn GpuDisplaySurface>> {
139 if parent_surface_id.is_some() {
140 return Err(GpuDisplayError::Unsupported);
141 }
142
143 let (width, height) = display_params.get_virtual_display_size();
144 let imports = Arc::clone(self.surface_imports.entry(surface_id).or_default());
145 Ok(Box::new(StubSurface {
146 width,
147 height,
148 buffer: None,
149 imports,
150 }))
151 }
152
153 fn release_surface(&mut self, surface_id: u32) {
154 self.surface_imports.remove(&surface_id);
155 }
156
157 fn import_resource(
158 &mut self,
159 import_id: u32,
160 surface_id: u32,
161 _external_display_resource: DisplayExternalResourceImport,
162 ) -> anyhow::Result<()> {
163 self.surface_imports
164 .entry(surface_id)
165 .or_default()
166 .lock()
167 .insert(import_id);
168 Ok(())
169 }
170
171 fn release_import(&mut self, surface_id: u32, import_id: u32) {
172 if let Some(imports) = self.surface_imports.get(&surface_id) {
173 imports.lock().remove(&import_id);
174 }
175 }
176}
177
178impl SysDisplayT for DisplayStub {}
179
180impl AsRawDescriptor for DisplayStub {
181 fn as_raw_descriptor(&self) -> RawDescriptor {
182 self.event.as_raw_descriptor()
183 }
184}