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