xref: /aosp_15_r20/external/crosvm/gpu_display/src/lib.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 //! Crate for displaying simple surfaces and GPU buffers over a low-level display backend such as
6*bb4ee6a4SAndroid Build Coastguard Worker //! Wayland or X.
7*bb4ee6a4SAndroid Build Coastguard Worker 
8*bb4ee6a4SAndroid Build Coastguard Worker use std::collections::BTreeMap;
9*bb4ee6a4SAndroid Build Coastguard Worker use std::io::Error as IoError;
10*bb4ee6a4SAndroid Build Coastguard Worker use std::time::Duration;
11*bb4ee6a4SAndroid Build Coastguard Worker 
12*bb4ee6a4SAndroid Build Coastguard Worker use anyhow::anyhow;
13*bb4ee6a4SAndroid Build Coastguard Worker use anyhow::Context;
14*bb4ee6a4SAndroid Build Coastguard Worker use base::AsRawDescriptor;
15*bb4ee6a4SAndroid Build Coastguard Worker use base::Error as BaseError;
16*bb4ee6a4SAndroid Build Coastguard Worker use base::EventToken;
17*bb4ee6a4SAndroid Build Coastguard Worker use base::EventType;
18*bb4ee6a4SAndroid Build Coastguard Worker use base::VolatileSlice;
19*bb4ee6a4SAndroid Build Coastguard Worker use base::WaitContext;
20*bb4ee6a4SAndroid Build Coastguard Worker use remain::sorted;
21*bb4ee6a4SAndroid Build Coastguard Worker use serde::Deserialize;
22*bb4ee6a4SAndroid Build Coastguard Worker use serde::Serialize;
23*bb4ee6a4SAndroid Build Coastguard Worker use sync::Waitable;
24*bb4ee6a4SAndroid Build Coastguard Worker use thiserror::Error;
25*bb4ee6a4SAndroid Build Coastguard Worker use vm_control::gpu::DisplayParameters;
26*bb4ee6a4SAndroid Build Coastguard Worker use vm_control::gpu::MouseMode;
27*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "vulkan_display")]
28*bb4ee6a4SAndroid Build Coastguard Worker use vulkano::VulkanLibrary;
29*bb4ee6a4SAndroid Build Coastguard Worker 
30*bb4ee6a4SAndroid Build Coastguard Worker mod event_device;
31*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "android_display")]
32*bb4ee6a4SAndroid Build Coastguard Worker mod gpu_display_android;
33*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "android_display_stub")]
34*bb4ee6a4SAndroid Build Coastguard Worker mod gpu_display_android_stub;
35*bb4ee6a4SAndroid Build Coastguard Worker mod gpu_display_stub;
36*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(windows)]
37*bb4ee6a4SAndroid Build Coastguard Worker mod gpu_display_win;
38*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(any(target_os = "android", target_os = "linux"))]
39*bb4ee6a4SAndroid Build Coastguard Worker mod gpu_display_wl;
40*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "x")]
41*bb4ee6a4SAndroid Build Coastguard Worker mod gpu_display_x;
42*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(any(windows, feature = "x"))]
43*bb4ee6a4SAndroid Build Coastguard Worker mod keycode_converter;
44*bb4ee6a4SAndroid Build Coastguard Worker mod sys;
45*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "vulkan_display")]
46*bb4ee6a4SAndroid Build Coastguard Worker pub mod vulkan;
47*bb4ee6a4SAndroid Build Coastguard Worker 
48*bb4ee6a4SAndroid Build Coastguard Worker pub use event_device::EventDevice;
49*bb4ee6a4SAndroid Build Coastguard Worker pub use event_device::EventDeviceKind;
50*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(windows)]
51*bb4ee6a4SAndroid Build Coastguard Worker pub use gpu_display_win::WindowProcedureThread;
52*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(windows)]
53*bb4ee6a4SAndroid Build Coastguard Worker pub use gpu_display_win::WindowProcedureThreadBuilder;
54*bb4ee6a4SAndroid Build Coastguard Worker use linux_input_sys::virtio_input_event;
55*bb4ee6a4SAndroid Build Coastguard Worker use sys::SysDisplayT;
56*bb4ee6a4SAndroid Build Coastguard Worker pub use sys::SysGpuDisplayExt;
57*bb4ee6a4SAndroid Build Coastguard Worker 
58*bb4ee6a4SAndroid Build Coastguard Worker // The number of bytes in a vulkan UUID.
59*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "vulkan_display")]
60*bb4ee6a4SAndroid Build Coastguard Worker const VK_UUID_BYTES: usize = 16;
61*bb4ee6a4SAndroid Build Coastguard Worker 
62*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Clone)]
63*bb4ee6a4SAndroid Build Coastguard Worker pub struct VulkanCreateParams {
64*bb4ee6a4SAndroid Build Coastguard Worker     #[cfg(feature = "vulkan_display")]
65*bb4ee6a4SAndroid Build Coastguard Worker     pub vulkan_library: std::sync::Arc<VulkanLibrary>,
66*bb4ee6a4SAndroid Build Coastguard Worker     #[cfg(feature = "vulkan_display")]
67*bb4ee6a4SAndroid Build Coastguard Worker     pub device_uuid: [u8; VK_UUID_BYTES],
68*bb4ee6a4SAndroid Build Coastguard Worker     #[cfg(feature = "vulkan_display")]
69*bb4ee6a4SAndroid Build Coastguard Worker     pub driver_uuid: [u8; VK_UUID_BYTES],
70*bb4ee6a4SAndroid Build Coastguard Worker }
71*bb4ee6a4SAndroid Build Coastguard Worker 
72*bb4ee6a4SAndroid Build Coastguard Worker /// An error generated by `GpuDisplay`.
73*bb4ee6a4SAndroid Build Coastguard Worker #[sorted]
74*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Error, Debug)]
75*bb4ee6a4SAndroid Build Coastguard Worker pub enum GpuDisplayError {
76*bb4ee6a4SAndroid Build Coastguard Worker     /// An internal allocation failed.
77*bb4ee6a4SAndroid Build Coastguard Worker     #[error("internal allocation failed")]
78*bb4ee6a4SAndroid Build Coastguard Worker     Allocate,
79*bb4ee6a4SAndroid Build Coastguard Worker     /// A base error occurred.
80*bb4ee6a4SAndroid Build Coastguard Worker     #[error("received a base error: {0}")]
81*bb4ee6a4SAndroid Build Coastguard Worker     BaseError(BaseError),
82*bb4ee6a4SAndroid Build Coastguard Worker     /// Connecting to the compositor failed.
83*bb4ee6a4SAndroid Build Coastguard Worker     #[error("failed to connect to compositor")]
84*bb4ee6a4SAndroid Build Coastguard Worker     Connect,
85*bb4ee6a4SAndroid Build Coastguard Worker     /// Connection to compositor has been broken.
86*bb4ee6a4SAndroid Build Coastguard Worker     #[error("connection to compositor has been broken")]
87*bb4ee6a4SAndroid Build Coastguard Worker     ConnectionBroken,
88*bb4ee6a4SAndroid Build Coastguard Worker     /// Creating event file descriptor failed.
89*bb4ee6a4SAndroid Build Coastguard Worker     #[error("failed to create event file descriptor")]
90*bb4ee6a4SAndroid Build Coastguard Worker     CreateEvent,
91*bb4ee6a4SAndroid Build Coastguard Worker     /// Failed to create a surface on the compositor.
92*bb4ee6a4SAndroid Build Coastguard Worker     #[error("failed to crate surface on the compositor")]
93*bb4ee6a4SAndroid Build Coastguard Worker     CreateSurface,
94*bb4ee6a4SAndroid Build Coastguard Worker     /// Failed to import an event device.
95*bb4ee6a4SAndroid Build Coastguard Worker     #[error("failed to import an event device: {0}")]
96*bb4ee6a4SAndroid Build Coastguard Worker     FailedEventDeviceImport(String),
97*bb4ee6a4SAndroid Build Coastguard Worker     #[error("failed to register an event device to listen for guest events: {0}")]
98*bb4ee6a4SAndroid Build Coastguard Worker     FailedEventDeviceListen(base::TubeError),
99*bb4ee6a4SAndroid Build Coastguard Worker     /// Failed to import a buffer to the compositor.
100*bb4ee6a4SAndroid Build Coastguard Worker     #[error("failed to import a buffer to the compositor")]
101*bb4ee6a4SAndroid Build Coastguard Worker     FailedImport,
102*bb4ee6a4SAndroid Build Coastguard Worker     /// Android display service name is invalid.
103*bb4ee6a4SAndroid Build Coastguard Worker     #[error("invalid Android display service name: {0}")]
104*bb4ee6a4SAndroid Build Coastguard Worker     InvalidAndroidDisplayServiceName(String),
105*bb4ee6a4SAndroid Build Coastguard Worker     /// The import ID is invalid.
106*bb4ee6a4SAndroid Build Coastguard Worker     #[error("invalid import ID")]
107*bb4ee6a4SAndroid Build Coastguard Worker     InvalidImportId,
108*bb4ee6a4SAndroid Build Coastguard Worker     /// The path is invalid.
109*bb4ee6a4SAndroid Build Coastguard Worker     #[error("invalid path")]
110*bb4ee6a4SAndroid Build Coastguard Worker     InvalidPath,
111*bb4ee6a4SAndroid Build Coastguard Worker     /// The surface ID is invalid.
112*bb4ee6a4SAndroid Build Coastguard Worker     #[error("invalid surface ID")]
113*bb4ee6a4SAndroid Build Coastguard Worker     InvalidSurfaceId,
114*bb4ee6a4SAndroid Build Coastguard Worker     /// An input/output error occured.
115*bb4ee6a4SAndroid Build Coastguard Worker     #[error("an input/output error occur: {0}")]
116*bb4ee6a4SAndroid Build Coastguard Worker     IoError(IoError),
117*bb4ee6a4SAndroid Build Coastguard Worker     /// A required feature was missing.
118*bb4ee6a4SAndroid Build Coastguard Worker     #[error("required feature was missing: {0}")]
119*bb4ee6a4SAndroid Build Coastguard Worker     RequiredFeature(&'static str),
120*bb4ee6a4SAndroid Build Coastguard Worker     /// The method is unsupported by the implementation.
121*bb4ee6a4SAndroid Build Coastguard Worker     #[error("unsupported by the implementation")]
122*bb4ee6a4SAndroid Build Coastguard Worker     Unsupported,
123*bb4ee6a4SAndroid Build Coastguard Worker }
124*bb4ee6a4SAndroid Build Coastguard Worker 
125*bb4ee6a4SAndroid Build Coastguard Worker pub type GpuDisplayResult<T> = std::result::Result<T, GpuDisplayError>;
126*bb4ee6a4SAndroid Build Coastguard Worker 
127*bb4ee6a4SAndroid Build Coastguard Worker impl From<BaseError> for GpuDisplayError {
from(e: BaseError) -> GpuDisplayError128*bb4ee6a4SAndroid Build Coastguard Worker     fn from(e: BaseError) -> GpuDisplayError {
129*bb4ee6a4SAndroid Build Coastguard Worker         GpuDisplayError::BaseError(e)
130*bb4ee6a4SAndroid Build Coastguard Worker     }
131*bb4ee6a4SAndroid Build Coastguard Worker }
132*bb4ee6a4SAndroid Build Coastguard Worker 
133*bb4ee6a4SAndroid Build Coastguard Worker impl From<IoError> for GpuDisplayError {
from(e: IoError) -> GpuDisplayError134*bb4ee6a4SAndroid Build Coastguard Worker     fn from(e: IoError) -> GpuDisplayError {
135*bb4ee6a4SAndroid Build Coastguard Worker         GpuDisplayError::IoError(e)
136*bb4ee6a4SAndroid Build Coastguard Worker     }
137*bb4ee6a4SAndroid Build Coastguard Worker }
138*bb4ee6a4SAndroid Build Coastguard Worker 
139*bb4ee6a4SAndroid Build Coastguard Worker /// A surface type
140*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
141*bb4ee6a4SAndroid Build Coastguard Worker pub enum SurfaceType {
142*bb4ee6a4SAndroid Build Coastguard Worker     /// Scanout surface
143*bb4ee6a4SAndroid Build Coastguard Worker     Scanout,
144*bb4ee6a4SAndroid Build Coastguard Worker     /// Mouse cursor surface
145*bb4ee6a4SAndroid Build Coastguard Worker     Cursor,
146*bb4ee6a4SAndroid Build Coastguard Worker }
147*bb4ee6a4SAndroid Build Coastguard Worker 
148*bb4ee6a4SAndroid Build Coastguard Worker /// Event token for display instances
149*bb4ee6a4SAndroid Build Coastguard Worker #[derive(EventToken, Debug)]
150*bb4ee6a4SAndroid Build Coastguard Worker pub enum DisplayEventToken {
151*bb4ee6a4SAndroid Build Coastguard Worker     Display,
152*bb4ee6a4SAndroid Build Coastguard Worker     EventDevice { event_device_id: u32 },
153*bb4ee6a4SAndroid Build Coastguard Worker }
154*bb4ee6a4SAndroid Build Coastguard Worker 
155*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Clone)]
156*bb4ee6a4SAndroid Build Coastguard Worker pub struct GpuDisplayFramebuffer<'a> {
157*bb4ee6a4SAndroid Build Coastguard Worker     framebuffer: VolatileSlice<'a>,
158*bb4ee6a4SAndroid Build Coastguard Worker     slice: VolatileSlice<'a>,
159*bb4ee6a4SAndroid Build Coastguard Worker     stride: u32,
160*bb4ee6a4SAndroid Build Coastguard Worker     bytes_per_pixel: u32,
161*bb4ee6a4SAndroid Build Coastguard Worker }
162*bb4ee6a4SAndroid Build Coastguard Worker 
163*bb4ee6a4SAndroid Build Coastguard Worker impl<'a> GpuDisplayFramebuffer<'a> {
new( framebuffer: VolatileSlice<'a>, stride: u32, bytes_per_pixel: u32, ) -> GpuDisplayFramebuffer164*bb4ee6a4SAndroid Build Coastguard Worker     fn new(
165*bb4ee6a4SAndroid Build Coastguard Worker         framebuffer: VolatileSlice<'a>,
166*bb4ee6a4SAndroid Build Coastguard Worker         stride: u32,
167*bb4ee6a4SAndroid Build Coastguard Worker         bytes_per_pixel: u32,
168*bb4ee6a4SAndroid Build Coastguard Worker     ) -> GpuDisplayFramebuffer {
169*bb4ee6a4SAndroid Build Coastguard Worker         GpuDisplayFramebuffer {
170*bb4ee6a4SAndroid Build Coastguard Worker             framebuffer,
171*bb4ee6a4SAndroid Build Coastguard Worker             slice: framebuffer,
172*bb4ee6a4SAndroid Build Coastguard Worker             stride,
173*bb4ee6a4SAndroid Build Coastguard Worker             bytes_per_pixel,
174*bb4ee6a4SAndroid Build Coastguard Worker         }
175*bb4ee6a4SAndroid Build Coastguard Worker     }
176*bb4ee6a4SAndroid Build Coastguard Worker 
sub_region( &self, x: u32, y: u32, width: u32, height: u32, ) -> Option<GpuDisplayFramebuffer<'a>>177*bb4ee6a4SAndroid Build Coastguard Worker     fn sub_region(
178*bb4ee6a4SAndroid Build Coastguard Worker         &self,
179*bb4ee6a4SAndroid Build Coastguard Worker         x: u32,
180*bb4ee6a4SAndroid Build Coastguard Worker         y: u32,
181*bb4ee6a4SAndroid Build Coastguard Worker         width: u32,
182*bb4ee6a4SAndroid Build Coastguard Worker         height: u32,
183*bb4ee6a4SAndroid Build Coastguard Worker     ) -> Option<GpuDisplayFramebuffer<'a>> {
184*bb4ee6a4SAndroid Build Coastguard Worker         let x_byte_offset = x.checked_mul(self.bytes_per_pixel)?;
185*bb4ee6a4SAndroid Build Coastguard Worker         let y_byte_offset = y.checked_mul(self.stride)?;
186*bb4ee6a4SAndroid Build Coastguard Worker         let byte_offset = x_byte_offset.checked_add(y_byte_offset)?;
187*bb4ee6a4SAndroid Build Coastguard Worker 
188*bb4ee6a4SAndroid Build Coastguard Worker         let width_bytes = width.checked_mul(self.bytes_per_pixel)?;
189*bb4ee6a4SAndroid Build Coastguard Worker         let count = height
190*bb4ee6a4SAndroid Build Coastguard Worker             .checked_mul(self.stride)?
191*bb4ee6a4SAndroid Build Coastguard Worker             .checked_sub(self.stride)?
192*bb4ee6a4SAndroid Build Coastguard Worker             .checked_add(width_bytes)?;
193*bb4ee6a4SAndroid Build Coastguard Worker         let slice = self
194*bb4ee6a4SAndroid Build Coastguard Worker             .framebuffer
195*bb4ee6a4SAndroid Build Coastguard Worker             .sub_slice(byte_offset as usize, count as usize)
196*bb4ee6a4SAndroid Build Coastguard Worker             .unwrap();
197*bb4ee6a4SAndroid Build Coastguard Worker 
198*bb4ee6a4SAndroid Build Coastguard Worker         Some(GpuDisplayFramebuffer { slice, ..*self })
199*bb4ee6a4SAndroid Build Coastguard Worker     }
200*bb4ee6a4SAndroid Build Coastguard Worker 
as_volatile_slice(&self) -> VolatileSlice<'a>201*bb4ee6a4SAndroid Build Coastguard Worker     pub fn as_volatile_slice(&self) -> VolatileSlice<'a> {
202*bb4ee6a4SAndroid Build Coastguard Worker         self.slice
203*bb4ee6a4SAndroid Build Coastguard Worker     }
204*bb4ee6a4SAndroid Build Coastguard Worker 
stride(&self) -> u32205*bb4ee6a4SAndroid Build Coastguard Worker     pub fn stride(&self) -> u32 {
206*bb4ee6a4SAndroid Build Coastguard Worker         self.stride
207*bb4ee6a4SAndroid Build Coastguard Worker     }
208*bb4ee6a4SAndroid Build Coastguard Worker }
209*bb4ee6a4SAndroid Build Coastguard Worker 
210*bb4ee6a4SAndroid Build Coastguard Worker trait GpuDisplaySurface {
211*bb4ee6a4SAndroid Build Coastguard Worker     /// Returns an unique ID associated with the surface.  This is typically generated by the
212*bb4ee6a4SAndroid Build Coastguard Worker     /// compositor or cast of a raw pointer.
surface_descriptor(&self) -> u64213*bb4ee6a4SAndroid Build Coastguard Worker     fn surface_descriptor(&self) -> u64 {
214*bb4ee6a4SAndroid Build Coastguard Worker         0
215*bb4ee6a4SAndroid Build Coastguard Worker     }
216*bb4ee6a4SAndroid Build Coastguard Worker 
217*bb4ee6a4SAndroid Build Coastguard Worker     /// Returns the next framebuffer, allocating if necessary.
framebuffer(&mut self) -> Option<GpuDisplayFramebuffer>218*bb4ee6a4SAndroid Build Coastguard Worker     fn framebuffer(&mut self) -> Option<GpuDisplayFramebuffer> {
219*bb4ee6a4SAndroid Build Coastguard Worker         None
220*bb4ee6a4SAndroid Build Coastguard Worker     }
221*bb4ee6a4SAndroid Build Coastguard Worker 
222*bb4ee6a4SAndroid Build Coastguard Worker     /// Returns true if the next buffer in the swapchain is already in use.
next_buffer_in_use(&self) -> bool223*bb4ee6a4SAndroid Build Coastguard Worker     fn next_buffer_in_use(&self) -> bool {
224*bb4ee6a4SAndroid Build Coastguard Worker         false
225*bb4ee6a4SAndroid Build Coastguard Worker     }
226*bb4ee6a4SAndroid Build Coastguard Worker 
227*bb4ee6a4SAndroid Build Coastguard Worker     /// Returns true if the surface should be closed.
close_requested(&self) -> bool228*bb4ee6a4SAndroid Build Coastguard Worker     fn close_requested(&self) -> bool {
229*bb4ee6a4SAndroid Build Coastguard Worker         false
230*bb4ee6a4SAndroid Build Coastguard Worker     }
231*bb4ee6a4SAndroid Build Coastguard Worker 
232*bb4ee6a4SAndroid Build Coastguard Worker     /// Puts the next buffer on the screen, making it the current buffer.
flip(&mut self)233*bb4ee6a4SAndroid Build Coastguard Worker     fn flip(&mut self) {
234*bb4ee6a4SAndroid Build Coastguard Worker         // no-op
235*bb4ee6a4SAndroid Build Coastguard Worker     }
236*bb4ee6a4SAndroid Build Coastguard Worker 
237*bb4ee6a4SAndroid Build Coastguard Worker     /// Puts the specified import_id on the screen.
flip_to( &mut self, _import_id: u32, _acquire_timepoint: Option<SemaphoreTimepoint>, _release_timepoint: Option<SemaphoreTimepoint>, _extra_info: Option<FlipToExtraInfo>, ) -> anyhow::Result<Waitable>238*bb4ee6a4SAndroid Build Coastguard Worker     fn flip_to(
239*bb4ee6a4SAndroid Build Coastguard Worker         &mut self,
240*bb4ee6a4SAndroid Build Coastguard Worker         _import_id: u32,
241*bb4ee6a4SAndroid Build Coastguard Worker         _acquire_timepoint: Option<SemaphoreTimepoint>,
242*bb4ee6a4SAndroid Build Coastguard Worker         _release_timepoint: Option<SemaphoreTimepoint>,
243*bb4ee6a4SAndroid Build Coastguard Worker         _extra_info: Option<FlipToExtraInfo>,
244*bb4ee6a4SAndroid Build Coastguard Worker     ) -> anyhow::Result<Waitable> {
245*bb4ee6a4SAndroid Build Coastguard Worker         // no-op
246*bb4ee6a4SAndroid Build Coastguard Worker         Ok(Waitable::signaled())
247*bb4ee6a4SAndroid Build Coastguard Worker     }
248*bb4ee6a4SAndroid Build Coastguard Worker 
249*bb4ee6a4SAndroid Build Coastguard Worker     /// Commits the surface to the compositor.
commit(&mut self) -> GpuDisplayResult<()>250*bb4ee6a4SAndroid Build Coastguard Worker     fn commit(&mut self) -> GpuDisplayResult<()> {
251*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
252*bb4ee6a4SAndroid Build Coastguard Worker     }
253*bb4ee6a4SAndroid Build Coastguard Worker 
254*bb4ee6a4SAndroid Build Coastguard Worker     /// Sets the mouse mode used on this surface.
set_mouse_mode(&mut self, _mouse_mode: MouseMode)255*bb4ee6a4SAndroid Build Coastguard Worker     fn set_mouse_mode(&mut self, _mouse_mode: MouseMode) {
256*bb4ee6a4SAndroid Build Coastguard Worker         // no-op
257*bb4ee6a4SAndroid Build Coastguard Worker     }
258*bb4ee6a4SAndroid Build Coastguard Worker 
259*bb4ee6a4SAndroid Build Coastguard Worker     /// Sets the position of the identified subsurface relative to its parent.
set_position(&mut self, _x: u32, _y: u32)260*bb4ee6a4SAndroid Build Coastguard Worker     fn set_position(&mut self, _x: u32, _y: u32) {
261*bb4ee6a4SAndroid Build Coastguard Worker         // no-op
262*bb4ee6a4SAndroid Build Coastguard Worker     }
263*bb4ee6a4SAndroid Build Coastguard Worker 
264*bb4ee6a4SAndroid Build Coastguard Worker     /// Returns the type of the completed buffer.
265*bb4ee6a4SAndroid Build Coastguard Worker     #[allow(dead_code)]
buffer_completion_type(&self) -> u32266*bb4ee6a4SAndroid Build Coastguard Worker     fn buffer_completion_type(&self) -> u32 {
267*bb4ee6a4SAndroid Build Coastguard Worker         0
268*bb4ee6a4SAndroid Build Coastguard Worker     }
269*bb4ee6a4SAndroid Build Coastguard Worker 
270*bb4ee6a4SAndroid Build Coastguard Worker     /// Draws the current buffer on the screen.
271*bb4ee6a4SAndroid Build Coastguard Worker     #[allow(dead_code)]
draw_current_buffer(&mut self)272*bb4ee6a4SAndroid Build Coastguard Worker     fn draw_current_buffer(&mut self) {
273*bb4ee6a4SAndroid Build Coastguard Worker         // no-op
274*bb4ee6a4SAndroid Build Coastguard Worker     }
275*bb4ee6a4SAndroid Build Coastguard Worker 
276*bb4ee6a4SAndroid Build Coastguard Worker     /// Handles a compositor-specific client event.
277*bb4ee6a4SAndroid Build Coastguard Worker     #[allow(dead_code)]
on_client_message(&mut self, _client_data: u64)278*bb4ee6a4SAndroid Build Coastguard Worker     fn on_client_message(&mut self, _client_data: u64) {
279*bb4ee6a4SAndroid Build Coastguard Worker         // no-op
280*bb4ee6a4SAndroid Build Coastguard Worker     }
281*bb4ee6a4SAndroid Build Coastguard Worker 
282*bb4ee6a4SAndroid Build Coastguard Worker     /// Handles a compositor-specific shared memory completion event.
283*bb4ee6a4SAndroid Build Coastguard Worker     #[allow(dead_code)]
on_shm_completion(&mut self, _shm_complete: u64)284*bb4ee6a4SAndroid Build Coastguard Worker     fn on_shm_completion(&mut self, _shm_complete: u64) {
285*bb4ee6a4SAndroid Build Coastguard Worker         // no-op
286*bb4ee6a4SAndroid Build Coastguard Worker     }
287*bb4ee6a4SAndroid Build Coastguard Worker }
288*bb4ee6a4SAndroid Build Coastguard Worker 
289*bb4ee6a4SAndroid Build Coastguard Worker struct GpuDisplayEvents {
290*bb4ee6a4SAndroid Build Coastguard Worker     events: Vec<virtio_input_event>,
291*bb4ee6a4SAndroid Build Coastguard Worker     device_type: EventDeviceKind,
292*bb4ee6a4SAndroid Build Coastguard Worker }
293*bb4ee6a4SAndroid Build Coastguard Worker 
294*bb4ee6a4SAndroid Build Coastguard Worker trait DisplayT: AsRawDescriptor {
295*bb4ee6a4SAndroid Build Coastguard Worker     /// Returns true if there are events that are on the queue.
pending_events(&self) -> bool296*bb4ee6a4SAndroid Build Coastguard Worker     fn pending_events(&self) -> bool {
297*bb4ee6a4SAndroid Build Coastguard Worker         false
298*bb4ee6a4SAndroid Build Coastguard Worker     }
299*bb4ee6a4SAndroid Build Coastguard Worker 
300*bb4ee6a4SAndroid Build Coastguard Worker     /// Sends any pending commands to the compositor.
flush(&self)301*bb4ee6a4SAndroid Build Coastguard Worker     fn flush(&self) {
302*bb4ee6a4SAndroid Build Coastguard Worker         // no-op
303*bb4ee6a4SAndroid Build Coastguard Worker     }
304*bb4ee6a4SAndroid Build Coastguard Worker 
305*bb4ee6a4SAndroid Build Coastguard Worker     /// Returns the surface descirptor associated with the current event
next_event(&mut self) -> GpuDisplayResult<u64>306*bb4ee6a4SAndroid Build Coastguard Worker     fn next_event(&mut self) -> GpuDisplayResult<u64> {
307*bb4ee6a4SAndroid Build Coastguard Worker         Ok(0)
308*bb4ee6a4SAndroid Build Coastguard Worker     }
309*bb4ee6a4SAndroid Build Coastguard Worker 
310*bb4ee6a4SAndroid Build Coastguard Worker     /// Handles the event from the compositor, and returns an list of events
handle_next_event( &mut self, _surface: &mut Box<dyn GpuDisplaySurface>, ) -> Option<GpuDisplayEvents>311*bb4ee6a4SAndroid Build Coastguard Worker     fn handle_next_event(
312*bb4ee6a4SAndroid Build Coastguard Worker         &mut self,
313*bb4ee6a4SAndroid Build Coastguard Worker         _surface: &mut Box<dyn GpuDisplaySurface>,
314*bb4ee6a4SAndroid Build Coastguard Worker     ) -> Option<GpuDisplayEvents> {
315*bb4ee6a4SAndroid Build Coastguard Worker         None
316*bb4ee6a4SAndroid Build Coastguard Worker     }
317*bb4ee6a4SAndroid Build Coastguard Worker 
318*bb4ee6a4SAndroid Build Coastguard Worker     /// Creates a surface with the given parameters.  The display backend is given a non-zero
319*bb4ee6a4SAndroid Build Coastguard Worker     /// `surface_id` as a handle for subsequent operations.
create_surface( &mut self, parent_surface_id: Option<u32>, surface_id: u32, scanout_id: Option<u32>, display_params: &DisplayParameters, surf_type: SurfaceType, ) -> GpuDisplayResult<Box<dyn GpuDisplaySurface>>320*bb4ee6a4SAndroid Build Coastguard Worker     fn create_surface(
321*bb4ee6a4SAndroid Build Coastguard Worker         &mut self,
322*bb4ee6a4SAndroid Build Coastguard Worker         parent_surface_id: Option<u32>,
323*bb4ee6a4SAndroid Build Coastguard Worker         surface_id: u32,
324*bb4ee6a4SAndroid Build Coastguard Worker         scanout_id: Option<u32>,
325*bb4ee6a4SAndroid Build Coastguard Worker         display_params: &DisplayParameters,
326*bb4ee6a4SAndroid Build Coastguard Worker         surf_type: SurfaceType,
327*bb4ee6a4SAndroid Build Coastguard Worker     ) -> GpuDisplayResult<Box<dyn GpuDisplaySurface>>;
328*bb4ee6a4SAndroid Build Coastguard Worker 
329*bb4ee6a4SAndroid Build Coastguard Worker     /// Imports a resource into the display backend.  The display backend is given a non-zero
330*bb4ee6a4SAndroid Build Coastguard Worker     /// `import_id` as a handle for subsequent operations.
import_resource( &mut self, _import_id: u32, _surface_id: u32, _external_display_resource: DisplayExternalResourceImport, ) -> anyhow::Result<()>331*bb4ee6a4SAndroid Build Coastguard Worker     fn import_resource(
332*bb4ee6a4SAndroid Build Coastguard Worker         &mut self,
333*bb4ee6a4SAndroid Build Coastguard Worker         _import_id: u32,
334*bb4ee6a4SAndroid Build Coastguard Worker         _surface_id: u32,
335*bb4ee6a4SAndroid Build Coastguard Worker         _external_display_resource: DisplayExternalResourceImport,
336*bb4ee6a4SAndroid Build Coastguard Worker     ) -> anyhow::Result<()> {
337*bb4ee6a4SAndroid Build Coastguard Worker         Err(anyhow!("import_resource is unsupported"))
338*bb4ee6a4SAndroid Build Coastguard Worker     }
339*bb4ee6a4SAndroid Build Coastguard Worker 
340*bb4ee6a4SAndroid Build Coastguard Worker     /// Frees a previously imported resource.
release_import(&mut self, _import_id: u32, _surface_id: u32)341*bb4ee6a4SAndroid Build Coastguard Worker     fn release_import(&mut self, _import_id: u32, _surface_id: u32) {}
342*bb4ee6a4SAndroid Build Coastguard Worker }
343*bb4ee6a4SAndroid Build Coastguard Worker 
344*bb4ee6a4SAndroid Build Coastguard Worker pub trait GpuDisplayExt {
345*bb4ee6a4SAndroid Build Coastguard Worker     /// Imports the given `event_device` into the display, returning an event device id on success.
346*bb4ee6a4SAndroid Build Coastguard Worker     /// This device may be used to dispatch input events to the guest.
import_event_device(&mut self, event_device: EventDevice) -> GpuDisplayResult<u32>347*bb4ee6a4SAndroid Build Coastguard Worker     fn import_event_device(&mut self, event_device: EventDevice) -> GpuDisplayResult<u32>;
348*bb4ee6a4SAndroid Build Coastguard Worker 
349*bb4ee6a4SAndroid Build Coastguard Worker     /// Called when an event device is readable.
handle_event_device(&mut self, event_device_id: u32)350*bb4ee6a4SAndroid Build Coastguard Worker     fn handle_event_device(&mut self, event_device_id: u32);
351*bb4ee6a4SAndroid Build Coastguard Worker }
352*bb4ee6a4SAndroid Build Coastguard Worker 
353*bb4ee6a4SAndroid Build Coastguard Worker pub enum DisplayExternalResourceImport<'a> {
354*bb4ee6a4SAndroid Build Coastguard Worker     Dmabuf {
355*bb4ee6a4SAndroid Build Coastguard Worker         descriptor: &'a dyn AsRawDescriptor,
356*bb4ee6a4SAndroid Build Coastguard Worker         offset: u32,
357*bb4ee6a4SAndroid Build Coastguard Worker         stride: u32,
358*bb4ee6a4SAndroid Build Coastguard Worker         modifiers: u64,
359*bb4ee6a4SAndroid Build Coastguard Worker         width: u32,
360*bb4ee6a4SAndroid Build Coastguard Worker         height: u32,
361*bb4ee6a4SAndroid Build Coastguard Worker         fourcc: u32,
362*bb4ee6a4SAndroid Build Coastguard Worker     },
363*bb4ee6a4SAndroid Build Coastguard Worker     VulkanImage {
364*bb4ee6a4SAndroid Build Coastguard Worker         descriptor: &'a dyn AsRawDescriptor,
365*bb4ee6a4SAndroid Build Coastguard Worker         metadata: VulkanDisplayImageImportMetadata,
366*bb4ee6a4SAndroid Build Coastguard Worker     },
367*bb4ee6a4SAndroid Build Coastguard Worker     VulkanTimelineSemaphore {
368*bb4ee6a4SAndroid Build Coastguard Worker         descriptor: &'a dyn AsRawDescriptor,
369*bb4ee6a4SAndroid Build Coastguard Worker     },
370*bb4ee6a4SAndroid Build Coastguard Worker }
371*bb4ee6a4SAndroid Build Coastguard Worker 
372*bb4ee6a4SAndroid Build Coastguard Worker pub struct VkExtent3D {
373*bb4ee6a4SAndroid Build Coastguard Worker     pub width: u32,
374*bb4ee6a4SAndroid Build Coastguard Worker     pub height: u32,
375*bb4ee6a4SAndroid Build Coastguard Worker     pub depth: u32,
376*bb4ee6a4SAndroid Build Coastguard Worker }
377*bb4ee6a4SAndroid Build Coastguard Worker 
378*bb4ee6a4SAndroid Build Coastguard Worker pub struct VulkanDisplayImageImportMetadata {
379*bb4ee6a4SAndroid Build Coastguard Worker     // These fields go into a VkImageCreateInfo
380*bb4ee6a4SAndroid Build Coastguard Worker     pub flags: u32,
381*bb4ee6a4SAndroid Build Coastguard Worker     pub image_type: i32,
382*bb4ee6a4SAndroid Build Coastguard Worker     pub format: i32,
383*bb4ee6a4SAndroid Build Coastguard Worker     pub extent: VkExtent3D,
384*bb4ee6a4SAndroid Build Coastguard Worker     pub mip_levels: u32,
385*bb4ee6a4SAndroid Build Coastguard Worker     pub array_layers: u32,
386*bb4ee6a4SAndroid Build Coastguard Worker     pub samples: u32,
387*bb4ee6a4SAndroid Build Coastguard Worker     pub tiling: i32,
388*bb4ee6a4SAndroid Build Coastguard Worker     pub usage: u32,
389*bb4ee6a4SAndroid Build Coastguard Worker     pub sharing_mode: i32,
390*bb4ee6a4SAndroid Build Coastguard Worker     pub queue_family_indices: Vec<u32>,
391*bb4ee6a4SAndroid Build Coastguard Worker     pub initial_layout: i32,
392*bb4ee6a4SAndroid Build Coastguard Worker 
393*bb4ee6a4SAndroid Build Coastguard Worker     // These fields go into a VkMemoryAllocateInfo
394*bb4ee6a4SAndroid Build Coastguard Worker     pub allocation_size: u64,
395*bb4ee6a4SAndroid Build Coastguard Worker     pub memory_type_index: u32,
396*bb4ee6a4SAndroid Build Coastguard Worker 
397*bb4ee6a4SAndroid Build Coastguard Worker     // Additional information
398*bb4ee6a4SAndroid Build Coastguard Worker     pub dedicated_allocation: bool,
399*bb4ee6a4SAndroid Build Coastguard Worker }
400*bb4ee6a4SAndroid Build Coastguard Worker 
401*bb4ee6a4SAndroid Build Coastguard Worker pub struct SemaphoreTimepoint {
402*bb4ee6a4SAndroid Build Coastguard Worker     pub import_id: u32,
403*bb4ee6a4SAndroid Build Coastguard Worker     pub value: u64,
404*bb4ee6a4SAndroid Build Coastguard Worker }
405*bb4ee6a4SAndroid Build Coastguard Worker 
406*bb4ee6a4SAndroid Build Coastguard Worker pub enum FlipToExtraInfo {
407*bb4ee6a4SAndroid Build Coastguard Worker     #[cfg(feature = "vulkan_display")]
408*bb4ee6a4SAndroid Build Coastguard Worker     Vulkan { old_layout: i32, new_layout: i32 },
409*bb4ee6a4SAndroid Build Coastguard Worker }
410*bb4ee6a4SAndroid Build Coastguard Worker 
411*bb4ee6a4SAndroid Build Coastguard Worker /// A connection to the compositor and associated collection of state.
412*bb4ee6a4SAndroid Build Coastguard Worker ///
413*bb4ee6a4SAndroid Build Coastguard Worker /// The user of `GpuDisplay` can use `AsRawDescriptor` to poll on the compositor connection's file
414*bb4ee6a4SAndroid Build Coastguard Worker /// descriptor. When the connection is readable, `dispatch_events` can be called to process it.
415*bb4ee6a4SAndroid Build Coastguard Worker pub struct GpuDisplay {
416*bb4ee6a4SAndroid Build Coastguard Worker     next_id: u32,
417*bb4ee6a4SAndroid Build Coastguard Worker     event_devices: BTreeMap<u32, EventDevice>,
418*bb4ee6a4SAndroid Build Coastguard Worker     surfaces: BTreeMap<u32, Box<dyn GpuDisplaySurface>>,
419*bb4ee6a4SAndroid Build Coastguard Worker     wait_ctx: WaitContext<DisplayEventToken>,
420*bb4ee6a4SAndroid Build Coastguard Worker     // `inner` must be after `surfaces` to ensure those objects are dropped before
421*bb4ee6a4SAndroid Build Coastguard Worker     // the display context. The drop order for fields inside a struct is the order in which they
422*bb4ee6a4SAndroid Build Coastguard Worker     // are declared [Rust RFC 1857].
423*bb4ee6a4SAndroid Build Coastguard Worker     //
424*bb4ee6a4SAndroid Build Coastguard Worker     // We also don't want to drop inner before wait_ctx because it contains references to the event
425*bb4ee6a4SAndroid Build Coastguard Worker     // devices owned by inner.display_event_dispatcher.
426*bb4ee6a4SAndroid Build Coastguard Worker     inner: Box<dyn SysDisplayT>,
427*bb4ee6a4SAndroid Build Coastguard Worker }
428*bb4ee6a4SAndroid Build Coastguard Worker 
429*bb4ee6a4SAndroid Build Coastguard Worker impl GpuDisplay {
430*bb4ee6a4SAndroid Build Coastguard Worker     /// Opens a connection to X server
open_x(display_name: Option<&str>) -> GpuDisplayResult<GpuDisplay>431*bb4ee6a4SAndroid Build Coastguard Worker     pub fn open_x(display_name: Option<&str>) -> GpuDisplayResult<GpuDisplay> {
432*bb4ee6a4SAndroid Build Coastguard Worker         let _ = display_name;
433*bb4ee6a4SAndroid Build Coastguard Worker         #[cfg(feature = "x")]
434*bb4ee6a4SAndroid Build Coastguard Worker         {
435*bb4ee6a4SAndroid Build Coastguard Worker             let display = gpu_display_x::DisplayX::open_display(display_name)?;
436*bb4ee6a4SAndroid Build Coastguard Worker 
437*bb4ee6a4SAndroid Build Coastguard Worker             let wait_ctx = WaitContext::new()?;
438*bb4ee6a4SAndroid Build Coastguard Worker             wait_ctx.add(&display, DisplayEventToken::Display)?;
439*bb4ee6a4SAndroid Build Coastguard Worker 
440*bb4ee6a4SAndroid Build Coastguard Worker             Ok(GpuDisplay {
441*bb4ee6a4SAndroid Build Coastguard Worker                 inner: Box::new(display),
442*bb4ee6a4SAndroid Build Coastguard Worker                 next_id: 1,
443*bb4ee6a4SAndroid Build Coastguard Worker                 event_devices: Default::default(),
444*bb4ee6a4SAndroid Build Coastguard Worker                 surfaces: Default::default(),
445*bb4ee6a4SAndroid Build Coastguard Worker                 wait_ctx,
446*bb4ee6a4SAndroid Build Coastguard Worker             })
447*bb4ee6a4SAndroid Build Coastguard Worker         }
448*bb4ee6a4SAndroid Build Coastguard Worker         #[cfg(not(feature = "x"))]
449*bb4ee6a4SAndroid Build Coastguard Worker         Err(GpuDisplayError::Unsupported)
450*bb4ee6a4SAndroid Build Coastguard Worker     }
451*bb4ee6a4SAndroid Build Coastguard Worker 
open_android(service_name: &str) -> GpuDisplayResult<GpuDisplay>452*bb4ee6a4SAndroid Build Coastguard Worker     pub fn open_android(service_name: &str) -> GpuDisplayResult<GpuDisplay> {
453*bb4ee6a4SAndroid Build Coastguard Worker         let _ = service_name;
454*bb4ee6a4SAndroid Build Coastguard Worker         #[cfg(feature = "android_display")]
455*bb4ee6a4SAndroid Build Coastguard Worker         {
456*bb4ee6a4SAndroid Build Coastguard Worker             let display = gpu_display_android::DisplayAndroid::new(service_name)?;
457*bb4ee6a4SAndroid Build Coastguard Worker 
458*bb4ee6a4SAndroid Build Coastguard Worker             let wait_ctx = WaitContext::new()?;
459*bb4ee6a4SAndroid Build Coastguard Worker             wait_ctx.add(&display, DisplayEventToken::Display)?;
460*bb4ee6a4SAndroid Build Coastguard Worker 
461*bb4ee6a4SAndroid Build Coastguard Worker             Ok(GpuDisplay {
462*bb4ee6a4SAndroid Build Coastguard Worker                 inner: Box::new(display),
463*bb4ee6a4SAndroid Build Coastguard Worker                 next_id: 1,
464*bb4ee6a4SAndroid Build Coastguard Worker                 event_devices: Default::default(),
465*bb4ee6a4SAndroid Build Coastguard Worker                 surfaces: Default::default(),
466*bb4ee6a4SAndroid Build Coastguard Worker                 wait_ctx,
467*bb4ee6a4SAndroid Build Coastguard Worker             })
468*bb4ee6a4SAndroid Build Coastguard Worker         }
469*bb4ee6a4SAndroid Build Coastguard Worker         #[cfg(not(feature = "android_display"))]
470*bb4ee6a4SAndroid Build Coastguard Worker         Err(GpuDisplayError::Unsupported)
471*bb4ee6a4SAndroid Build Coastguard Worker     }
472*bb4ee6a4SAndroid Build Coastguard Worker 
open_stub() -> GpuDisplayResult<GpuDisplay>473*bb4ee6a4SAndroid Build Coastguard Worker     pub fn open_stub() -> GpuDisplayResult<GpuDisplay> {
474*bb4ee6a4SAndroid Build Coastguard Worker         let display = gpu_display_stub::DisplayStub::new()?;
475*bb4ee6a4SAndroid Build Coastguard Worker         let wait_ctx = WaitContext::new()?;
476*bb4ee6a4SAndroid Build Coastguard Worker         wait_ctx.add(&display, DisplayEventToken::Display)?;
477*bb4ee6a4SAndroid Build Coastguard Worker 
478*bb4ee6a4SAndroid Build Coastguard Worker         Ok(GpuDisplay {
479*bb4ee6a4SAndroid Build Coastguard Worker             inner: Box::new(display),
480*bb4ee6a4SAndroid Build Coastguard Worker             next_id: 1,
481*bb4ee6a4SAndroid Build Coastguard Worker             event_devices: Default::default(),
482*bb4ee6a4SAndroid Build Coastguard Worker             surfaces: Default::default(),
483*bb4ee6a4SAndroid Build Coastguard Worker             wait_ctx,
484*bb4ee6a4SAndroid Build Coastguard Worker         })
485*bb4ee6a4SAndroid Build Coastguard Worker     }
486*bb4ee6a4SAndroid Build Coastguard Worker 
487*bb4ee6a4SAndroid Build Coastguard Worker     // Leaves the `GpuDisplay` in a undefined state.
488*bb4ee6a4SAndroid Build Coastguard Worker     //
489*bb4ee6a4SAndroid Build Coastguard Worker     // TODO: Would be nice to change receiver from `&mut self` to `self`. Requires some refactoring
490*bb4ee6a4SAndroid Build Coastguard Worker     // elsewhere.
take_event_devices(&mut self) -> Vec<EventDevice>491*bb4ee6a4SAndroid Build Coastguard Worker     pub fn take_event_devices(&mut self) -> Vec<EventDevice> {
492*bb4ee6a4SAndroid Build Coastguard Worker         std::mem::take(&mut self.event_devices)
493*bb4ee6a4SAndroid Build Coastguard Worker             .into_values()
494*bb4ee6a4SAndroid Build Coastguard Worker             .collect()
495*bb4ee6a4SAndroid Build Coastguard Worker     }
496*bb4ee6a4SAndroid Build Coastguard Worker 
dispatch_display_events(&mut self) -> GpuDisplayResult<()>497*bb4ee6a4SAndroid Build Coastguard Worker     fn dispatch_display_events(&mut self) -> GpuDisplayResult<()> {
498*bb4ee6a4SAndroid Build Coastguard Worker         self.inner.flush();
499*bb4ee6a4SAndroid Build Coastguard Worker         while self.inner.pending_events() {
500*bb4ee6a4SAndroid Build Coastguard Worker             let surface_descriptor = self.inner.next_event()?;
501*bb4ee6a4SAndroid Build Coastguard Worker 
502*bb4ee6a4SAndroid Build Coastguard Worker             for surface in self.surfaces.values_mut() {
503*bb4ee6a4SAndroid Build Coastguard Worker                 if surface_descriptor != surface.surface_descriptor() {
504*bb4ee6a4SAndroid Build Coastguard Worker                     continue;
505*bb4ee6a4SAndroid Build Coastguard Worker                 }
506*bb4ee6a4SAndroid Build Coastguard Worker 
507*bb4ee6a4SAndroid Build Coastguard Worker                 if let Some(gpu_display_events) = self.inner.handle_next_event(surface) {
508*bb4ee6a4SAndroid Build Coastguard Worker                     for event_device in self.event_devices.values_mut() {
509*bb4ee6a4SAndroid Build Coastguard Worker                         if event_device.kind() != gpu_display_events.device_type {
510*bb4ee6a4SAndroid Build Coastguard Worker                             continue;
511*bb4ee6a4SAndroid Build Coastguard Worker                         }
512*bb4ee6a4SAndroid Build Coastguard Worker 
513*bb4ee6a4SAndroid Build Coastguard Worker                         event_device.send_report(gpu_display_events.events.iter().cloned())?;
514*bb4ee6a4SAndroid Build Coastguard Worker                     }
515*bb4ee6a4SAndroid Build Coastguard Worker                 }
516*bb4ee6a4SAndroid Build Coastguard Worker             }
517*bb4ee6a4SAndroid Build Coastguard Worker         }
518*bb4ee6a4SAndroid Build Coastguard Worker 
519*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
520*bb4ee6a4SAndroid Build Coastguard Worker     }
521*bb4ee6a4SAndroid Build Coastguard Worker 
522*bb4ee6a4SAndroid Build Coastguard Worker     /// Dispatches internal events that were received from the compositor since the last call to
523*bb4ee6a4SAndroid Build Coastguard Worker     /// `dispatch_events`.
dispatch_events(&mut self) -> GpuDisplayResult<()>524*bb4ee6a4SAndroid Build Coastguard Worker     pub fn dispatch_events(&mut self) -> GpuDisplayResult<()> {
525*bb4ee6a4SAndroid Build Coastguard Worker         let wait_events = self.wait_ctx.wait_timeout(Duration::default())?;
526*bb4ee6a4SAndroid Build Coastguard Worker 
527*bb4ee6a4SAndroid Build Coastguard Worker         if let Some(wait_event) = wait_events.iter().find(|e| e.is_hungup) {
528*bb4ee6a4SAndroid Build Coastguard Worker             base::error!(
529*bb4ee6a4SAndroid Build Coastguard Worker                 "Display signaled with a hungup event for token {:?}",
530*bb4ee6a4SAndroid Build Coastguard Worker                 wait_event.token
531*bb4ee6a4SAndroid Build Coastguard Worker             );
532*bb4ee6a4SAndroid Build Coastguard Worker             self.wait_ctx = WaitContext::new().unwrap();
533*bb4ee6a4SAndroid Build Coastguard Worker             return GpuDisplayResult::Err(GpuDisplayError::ConnectionBroken);
534*bb4ee6a4SAndroid Build Coastguard Worker         }
535*bb4ee6a4SAndroid Build Coastguard Worker 
536*bb4ee6a4SAndroid Build Coastguard Worker         for wait_event in wait_events.iter().filter(|e| e.is_writable) {
537*bb4ee6a4SAndroid Build Coastguard Worker             if let DisplayEventToken::EventDevice { event_device_id } = wait_event.token {
538*bb4ee6a4SAndroid Build Coastguard Worker                 if let Some(event_device) = self.event_devices.get_mut(&event_device_id) {
539*bb4ee6a4SAndroid Build Coastguard Worker                     if !event_device.flush_buffered_events()? {
540*bb4ee6a4SAndroid Build Coastguard Worker                         continue;
541*bb4ee6a4SAndroid Build Coastguard Worker                     }
542*bb4ee6a4SAndroid Build Coastguard Worker                     self.wait_ctx.modify(
543*bb4ee6a4SAndroid Build Coastguard Worker                         event_device,
544*bb4ee6a4SAndroid Build Coastguard Worker                         EventType::Read,
545*bb4ee6a4SAndroid Build Coastguard Worker                         DisplayEventToken::EventDevice { event_device_id },
546*bb4ee6a4SAndroid Build Coastguard Worker                     )?;
547*bb4ee6a4SAndroid Build Coastguard Worker                 }
548*bb4ee6a4SAndroid Build Coastguard Worker             }
549*bb4ee6a4SAndroid Build Coastguard Worker         }
550*bb4ee6a4SAndroid Build Coastguard Worker 
551*bb4ee6a4SAndroid Build Coastguard Worker         for wait_event in wait_events.iter().filter(|e| e.is_readable) {
552*bb4ee6a4SAndroid Build Coastguard Worker             match wait_event.token {
553*bb4ee6a4SAndroid Build Coastguard Worker                 DisplayEventToken::Display => self.dispatch_display_events()?,
554*bb4ee6a4SAndroid Build Coastguard Worker                 DisplayEventToken::EventDevice { event_device_id } => {
555*bb4ee6a4SAndroid Build Coastguard Worker                     self.handle_event_device(event_device_id)
556*bb4ee6a4SAndroid Build Coastguard Worker                 }
557*bb4ee6a4SAndroid Build Coastguard Worker             }
558*bb4ee6a4SAndroid Build Coastguard Worker         }
559*bb4ee6a4SAndroid Build Coastguard Worker 
560*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
561*bb4ee6a4SAndroid Build Coastguard Worker     }
562*bb4ee6a4SAndroid Build Coastguard Worker 
563*bb4ee6a4SAndroid Build Coastguard Worker     /// Creates a surface on the the compositor as either a top level window, or child of another
564*bb4ee6a4SAndroid Build Coastguard Worker     /// surface, returning a handle to the new surface.
create_surface( &mut self, parent_surface_id: Option<u32>, scanout_id: Option<u32>, display_params: &DisplayParameters, surf_type: SurfaceType, ) -> GpuDisplayResult<u32>565*bb4ee6a4SAndroid Build Coastguard Worker     pub fn create_surface(
566*bb4ee6a4SAndroid Build Coastguard Worker         &mut self,
567*bb4ee6a4SAndroid Build Coastguard Worker         parent_surface_id: Option<u32>,
568*bb4ee6a4SAndroid Build Coastguard Worker         scanout_id: Option<u32>,
569*bb4ee6a4SAndroid Build Coastguard Worker         display_params: &DisplayParameters,
570*bb4ee6a4SAndroid Build Coastguard Worker         surf_type: SurfaceType,
571*bb4ee6a4SAndroid Build Coastguard Worker     ) -> GpuDisplayResult<u32> {
572*bb4ee6a4SAndroid Build Coastguard Worker         if let Some(parent_id) = parent_surface_id {
573*bb4ee6a4SAndroid Build Coastguard Worker             if !self.surfaces.contains_key(&parent_id) {
574*bb4ee6a4SAndroid Build Coastguard Worker                 return Err(GpuDisplayError::InvalidSurfaceId);
575*bb4ee6a4SAndroid Build Coastguard Worker             }
576*bb4ee6a4SAndroid Build Coastguard Worker         }
577*bb4ee6a4SAndroid Build Coastguard Worker 
578*bb4ee6a4SAndroid Build Coastguard Worker         let new_surface_id = self.next_id;
579*bb4ee6a4SAndroid Build Coastguard Worker         let new_surface = self.inner.create_surface(
580*bb4ee6a4SAndroid Build Coastguard Worker             parent_surface_id,
581*bb4ee6a4SAndroid Build Coastguard Worker             new_surface_id,
582*bb4ee6a4SAndroid Build Coastguard Worker             scanout_id,
583*bb4ee6a4SAndroid Build Coastguard Worker             display_params,
584*bb4ee6a4SAndroid Build Coastguard Worker             surf_type,
585*bb4ee6a4SAndroid Build Coastguard Worker         )?;
586*bb4ee6a4SAndroid Build Coastguard Worker 
587*bb4ee6a4SAndroid Build Coastguard Worker         self.next_id += 1;
588*bb4ee6a4SAndroid Build Coastguard Worker         self.surfaces.insert(new_surface_id, new_surface);
589*bb4ee6a4SAndroid Build Coastguard Worker         Ok(new_surface_id)
590*bb4ee6a4SAndroid Build Coastguard Worker     }
591*bb4ee6a4SAndroid Build Coastguard Worker 
592*bb4ee6a4SAndroid Build Coastguard Worker     /// Releases a previously created surface identified by the given handle.
release_surface(&mut self, surface_id: u32)593*bb4ee6a4SAndroid Build Coastguard Worker     pub fn release_surface(&mut self, surface_id: u32) {
594*bb4ee6a4SAndroid Build Coastguard Worker         self.surfaces.remove(&surface_id);
595*bb4ee6a4SAndroid Build Coastguard Worker     }
596*bb4ee6a4SAndroid Build Coastguard Worker 
597*bb4ee6a4SAndroid Build Coastguard Worker     /// Gets a reference to an unused framebuffer for the identified surface.
framebuffer(&mut self, surface_id: u32) -> Option<GpuDisplayFramebuffer>598*bb4ee6a4SAndroid Build Coastguard Worker     pub fn framebuffer(&mut self, surface_id: u32) -> Option<GpuDisplayFramebuffer> {
599*bb4ee6a4SAndroid Build Coastguard Worker         let surface = self.surfaces.get_mut(&surface_id)?;
600*bb4ee6a4SAndroid Build Coastguard Worker         surface.framebuffer()
601*bb4ee6a4SAndroid Build Coastguard Worker     }
602*bb4ee6a4SAndroid Build Coastguard Worker 
603*bb4ee6a4SAndroid Build Coastguard Worker     /// Gets a reference to an unused framebuffer for the identified surface.
framebuffer_region( &mut self, surface_id: u32, x: u32, y: u32, width: u32, height: u32, ) -> Option<GpuDisplayFramebuffer>604*bb4ee6a4SAndroid Build Coastguard Worker     pub fn framebuffer_region(
605*bb4ee6a4SAndroid Build Coastguard Worker         &mut self,
606*bb4ee6a4SAndroid Build Coastguard Worker         surface_id: u32,
607*bb4ee6a4SAndroid Build Coastguard Worker         x: u32,
608*bb4ee6a4SAndroid Build Coastguard Worker         y: u32,
609*bb4ee6a4SAndroid Build Coastguard Worker         width: u32,
610*bb4ee6a4SAndroid Build Coastguard Worker         height: u32,
611*bb4ee6a4SAndroid Build Coastguard Worker     ) -> Option<GpuDisplayFramebuffer> {
612*bb4ee6a4SAndroid Build Coastguard Worker         let framebuffer = self.framebuffer(surface_id)?;
613*bb4ee6a4SAndroid Build Coastguard Worker         framebuffer.sub_region(x, y, width, height)
614*bb4ee6a4SAndroid Build Coastguard Worker     }
615*bb4ee6a4SAndroid Build Coastguard Worker 
616*bb4ee6a4SAndroid Build Coastguard Worker     /// Returns true if the next buffer in the buffer queue for the given surface is currently in
617*bb4ee6a4SAndroid Build Coastguard Worker     /// use.
618*bb4ee6a4SAndroid Build Coastguard Worker     ///
619*bb4ee6a4SAndroid Build Coastguard Worker     /// If the next buffer is in use, the memory returned from `framebuffer_memory` should not be
620*bb4ee6a4SAndroid Build Coastguard Worker     /// written to.
next_buffer_in_use(&self, surface_id: u32) -> bool621*bb4ee6a4SAndroid Build Coastguard Worker     pub fn next_buffer_in_use(&self, surface_id: u32) -> bool {
622*bb4ee6a4SAndroid Build Coastguard Worker         self.surfaces
623*bb4ee6a4SAndroid Build Coastguard Worker             .get(&surface_id)
624*bb4ee6a4SAndroid Build Coastguard Worker             .map(|s| s.next_buffer_in_use())
625*bb4ee6a4SAndroid Build Coastguard Worker             .unwrap_or(false)
626*bb4ee6a4SAndroid Build Coastguard Worker     }
627*bb4ee6a4SAndroid Build Coastguard Worker 
628*bb4ee6a4SAndroid Build Coastguard Worker     /// Changes the visible contents of the identified surface to the contents of the framebuffer
629*bb4ee6a4SAndroid Build Coastguard Worker     /// last returned by `framebuffer_memory` for this surface.
flip(&mut self, surface_id: u32)630*bb4ee6a4SAndroid Build Coastguard Worker     pub fn flip(&mut self, surface_id: u32) {
631*bb4ee6a4SAndroid Build Coastguard Worker         if let Some(surface) = self.surfaces.get_mut(&surface_id) {
632*bb4ee6a4SAndroid Build Coastguard Worker             surface.flip()
633*bb4ee6a4SAndroid Build Coastguard Worker         }
634*bb4ee6a4SAndroid Build Coastguard Worker     }
635*bb4ee6a4SAndroid Build Coastguard Worker 
636*bb4ee6a4SAndroid Build Coastguard Worker     /// Returns true if the identified top level surface has been told to close by the compositor,
637*bb4ee6a4SAndroid Build Coastguard Worker     /// and by extension the user.
close_requested(&self, surface_id: u32) -> bool638*bb4ee6a4SAndroid Build Coastguard Worker     pub fn close_requested(&self, surface_id: u32) -> bool {
639*bb4ee6a4SAndroid Build Coastguard Worker         self.surfaces
640*bb4ee6a4SAndroid Build Coastguard Worker             .get(&surface_id)
641*bb4ee6a4SAndroid Build Coastguard Worker             .map(|s| s.close_requested())
642*bb4ee6a4SAndroid Build Coastguard Worker             .unwrap_or(true)
643*bb4ee6a4SAndroid Build Coastguard Worker     }
644*bb4ee6a4SAndroid Build Coastguard Worker 
645*bb4ee6a4SAndroid Build Coastguard Worker     /// Imports a resource to the display backend. This resource may be an image for the compositor
646*bb4ee6a4SAndroid Build Coastguard Worker     /// or a synchronization object.
import_resource( &mut self, surface_id: u32, external_display_resource: DisplayExternalResourceImport, ) -> anyhow::Result<u32>647*bb4ee6a4SAndroid Build Coastguard Worker     pub fn import_resource(
648*bb4ee6a4SAndroid Build Coastguard Worker         &mut self,
649*bb4ee6a4SAndroid Build Coastguard Worker         surface_id: u32,
650*bb4ee6a4SAndroid Build Coastguard Worker         external_display_resource: DisplayExternalResourceImport,
651*bb4ee6a4SAndroid Build Coastguard Worker     ) -> anyhow::Result<u32> {
652*bb4ee6a4SAndroid Build Coastguard Worker         let import_id = self.next_id;
653*bb4ee6a4SAndroid Build Coastguard Worker 
654*bb4ee6a4SAndroid Build Coastguard Worker         self.inner
655*bb4ee6a4SAndroid Build Coastguard Worker             .import_resource(import_id, surface_id, external_display_resource)?;
656*bb4ee6a4SAndroid Build Coastguard Worker 
657*bb4ee6a4SAndroid Build Coastguard Worker         self.next_id += 1;
658*bb4ee6a4SAndroid Build Coastguard Worker         Ok(import_id)
659*bb4ee6a4SAndroid Build Coastguard Worker     }
660*bb4ee6a4SAndroid Build Coastguard Worker 
661*bb4ee6a4SAndroid Build Coastguard Worker     /// Releases a previously imported resource identified by the given handle.
release_import(&mut self, import_id: u32, surface_id: u32)662*bb4ee6a4SAndroid Build Coastguard Worker     pub fn release_import(&mut self, import_id: u32, surface_id: u32) {
663*bb4ee6a4SAndroid Build Coastguard Worker         self.inner.release_import(import_id, surface_id);
664*bb4ee6a4SAndroid Build Coastguard Worker     }
665*bb4ee6a4SAndroid Build Coastguard Worker 
666*bb4ee6a4SAndroid Build Coastguard Worker     /// Commits any pending state for the identified surface.
commit(&mut self, surface_id: u32) -> GpuDisplayResult<()>667*bb4ee6a4SAndroid Build Coastguard Worker     pub fn commit(&mut self, surface_id: u32) -> GpuDisplayResult<()> {
668*bb4ee6a4SAndroid Build Coastguard Worker         let surface = self
669*bb4ee6a4SAndroid Build Coastguard Worker             .surfaces
670*bb4ee6a4SAndroid Build Coastguard Worker             .get_mut(&surface_id)
671*bb4ee6a4SAndroid Build Coastguard Worker             .ok_or(GpuDisplayError::InvalidSurfaceId)?;
672*bb4ee6a4SAndroid Build Coastguard Worker 
673*bb4ee6a4SAndroid Build Coastguard Worker         surface.commit()
674*bb4ee6a4SAndroid Build Coastguard Worker     }
675*bb4ee6a4SAndroid Build Coastguard Worker 
676*bb4ee6a4SAndroid Build Coastguard Worker     /// Changes the visible contents of the identified surface to that of the identified imported
677*bb4ee6a4SAndroid Build Coastguard Worker     /// buffer.
flip_to( &mut self, surface_id: u32, import_id: u32, acquire_timepoint: Option<SemaphoreTimepoint>, release_timepoint: Option<SemaphoreTimepoint>, extra_info: Option<FlipToExtraInfo>, ) -> anyhow::Result<Waitable>678*bb4ee6a4SAndroid Build Coastguard Worker     pub fn flip_to(
679*bb4ee6a4SAndroid Build Coastguard Worker         &mut self,
680*bb4ee6a4SAndroid Build Coastguard Worker         surface_id: u32,
681*bb4ee6a4SAndroid Build Coastguard Worker         import_id: u32,
682*bb4ee6a4SAndroid Build Coastguard Worker         acquire_timepoint: Option<SemaphoreTimepoint>,
683*bb4ee6a4SAndroid Build Coastguard Worker         release_timepoint: Option<SemaphoreTimepoint>,
684*bb4ee6a4SAndroid Build Coastguard Worker         extra_info: Option<FlipToExtraInfo>,
685*bb4ee6a4SAndroid Build Coastguard Worker     ) -> anyhow::Result<Waitable> {
686*bb4ee6a4SAndroid Build Coastguard Worker         let surface = self
687*bb4ee6a4SAndroid Build Coastguard Worker             .surfaces
688*bb4ee6a4SAndroid Build Coastguard Worker             .get_mut(&surface_id)
689*bb4ee6a4SAndroid Build Coastguard Worker             .ok_or(GpuDisplayError::InvalidSurfaceId)?;
690*bb4ee6a4SAndroid Build Coastguard Worker 
691*bb4ee6a4SAndroid Build Coastguard Worker         surface
692*bb4ee6a4SAndroid Build Coastguard Worker             .flip_to(import_id, acquire_timepoint, release_timepoint, extra_info)
693*bb4ee6a4SAndroid Build Coastguard Worker             .context("failed in flip on GpuDisplaySurface")
694*bb4ee6a4SAndroid Build Coastguard Worker     }
695*bb4ee6a4SAndroid Build Coastguard Worker 
696*bb4ee6a4SAndroid Build Coastguard Worker     /// Sets the mouse mode used on this surface.
set_mouse_mode( &mut self, surface_id: u32, mouse_mode: MouseMode, ) -> GpuDisplayResult<()>697*bb4ee6a4SAndroid Build Coastguard Worker     pub fn set_mouse_mode(
698*bb4ee6a4SAndroid Build Coastguard Worker         &mut self,
699*bb4ee6a4SAndroid Build Coastguard Worker         surface_id: u32,
700*bb4ee6a4SAndroid Build Coastguard Worker         mouse_mode: MouseMode,
701*bb4ee6a4SAndroid Build Coastguard Worker     ) -> GpuDisplayResult<()> {
702*bb4ee6a4SAndroid Build Coastguard Worker         let surface = self
703*bb4ee6a4SAndroid Build Coastguard Worker             .surfaces
704*bb4ee6a4SAndroid Build Coastguard Worker             .get_mut(&surface_id)
705*bb4ee6a4SAndroid Build Coastguard Worker             .ok_or(GpuDisplayError::InvalidSurfaceId)?;
706*bb4ee6a4SAndroid Build Coastguard Worker 
707*bb4ee6a4SAndroid Build Coastguard Worker         surface.set_mouse_mode(mouse_mode);
708*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
709*bb4ee6a4SAndroid Build Coastguard Worker     }
710*bb4ee6a4SAndroid Build Coastguard Worker 
711*bb4ee6a4SAndroid Build Coastguard Worker     /// Sets the position of the identified subsurface relative to its parent.
712*bb4ee6a4SAndroid Build Coastguard Worker     ///
713*bb4ee6a4SAndroid Build Coastguard Worker     /// The change in position will not be visible until `commit` is called for the parent surface.
set_position(&mut self, surface_id: u32, x: u32, y: u32) -> GpuDisplayResult<()>714*bb4ee6a4SAndroid Build Coastguard Worker     pub fn set_position(&mut self, surface_id: u32, x: u32, y: u32) -> GpuDisplayResult<()> {
715*bb4ee6a4SAndroid Build Coastguard Worker         let surface = self
716*bb4ee6a4SAndroid Build Coastguard Worker             .surfaces
717*bb4ee6a4SAndroid Build Coastguard Worker             .get_mut(&surface_id)
718*bb4ee6a4SAndroid Build Coastguard Worker             .ok_or(GpuDisplayError::InvalidSurfaceId)?;
719*bb4ee6a4SAndroid Build Coastguard Worker 
720*bb4ee6a4SAndroid Build Coastguard Worker         surface.set_position(x, y);
721*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
722*bb4ee6a4SAndroid Build Coastguard Worker     }
723*bb4ee6a4SAndroid Build Coastguard Worker }
724