gpu_display/
gpu_display_stub.rs

1// Copyright 2020 The ChromiumOS Authors
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use 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    /// Gets the buffer at buffer_index, allocating it if necessary.
65    fn lazily_allocate_buffer(&mut self) -> Option<&mut Buffer> {
66        if self.buffer.is_none() {
67            // XRGB8888
68            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    /// This event is never triggered and is used solely to fulfill AsRawDescriptor.
115    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}