1 // Copyright 2018 The ChromiumOS Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 //! Crate for displaying simple surfaces and GPU buffers over a low-level display backend such as 6 //! Wayland or X. 7 8 use std::collections::BTreeMap; 9 use std::io::Error as IoError; 10 use std::time::Duration; 11 12 use base::AsRawDescriptor; 13 use base::Error as BaseError; 14 use base::EventToken; 15 use base::EventType; 16 use base::WaitContext; 17 use data_model::VolatileSlice; 18 use remain::sorted; 19 use thiserror::Error; 20 21 mod event_device; 22 mod gpu_display_stub; 23 #[cfg(windows)] 24 mod gpu_display_win; 25 #[cfg(unix)] 26 mod gpu_display_wl; 27 #[cfg(feature = "x")] 28 mod gpu_display_x; 29 #[cfg(feature = "x")] 30 mod keycode_converter; 31 mod sys; 32 33 pub use event_device::EventDevice; 34 pub use event_device::EventDeviceKind; 35 #[cfg(windows)] 36 pub use gpu_display_win::DisplayProperties as WinDisplayProperties; 37 use linux_input_sys::virtio_input_event; 38 use sys::SysDisplayT; 39 pub use sys::SysGpuDisplayExt; 40 #[cfg(windows)] 41 pub type WindowProcedureThread = gpu_display_win::WindowProcedureThread<gpu_display_win::Surface>; 42 43 /// An error generated by `GpuDisplay`. 44 #[sorted] 45 #[derive(Error, Debug)] 46 pub enum GpuDisplayError { 47 /// An internal allocation failed. 48 #[error("internal allocation failed")] 49 Allocate, 50 /// A base error occurred. 51 #[error("received a base error: {0}")] 52 BaseError(BaseError), 53 /// Connecting to the compositor failed. 54 #[error("failed to connect to compositor")] 55 Connect, 56 /// Connection to compositor has been broken. 57 #[error("connection to compositor has been broken")] 58 ConnectionBroken, 59 /// Creating event file descriptor failed. 60 #[error("failed to create event file descriptor")] 61 CreateEvent, 62 /// Failed to create a surface on the compositor. 63 #[error("failed to crate surface on the compositor")] 64 CreateSurface, 65 /// Failed to import an event device. 66 #[error("failed to import an event device: {0}")] 67 FailedEventDeviceImport(String), 68 /// Failed to import a buffer to the compositor. 69 #[error("failed to import a buffer to the compositor")] 70 FailedImport, 71 /// The import ID is invalid. 72 #[error("invalid import ID")] 73 InvalidImportId, 74 /// The path is invalid. 75 #[error("invalid path")] 76 InvalidPath, 77 /// The surface ID is invalid. 78 #[error("invalid surface ID")] 79 InvalidSurfaceId, 80 /// An input/output error occured. 81 #[error("an input/output error occur: {0}")] 82 IoError(IoError), 83 /// A required feature was missing. 84 #[error("required feature was missing: {0}")] 85 RequiredFeature(&'static str), 86 /// The method is unsupported by the implementation. 87 #[error("unsupported by the implementation")] 88 Unsupported, 89 } 90 91 pub type GpuDisplayResult<T> = std::result::Result<T, GpuDisplayError>; 92 93 impl From<BaseError> for GpuDisplayError { from(e: BaseError) -> GpuDisplayError94 fn from(e: BaseError) -> GpuDisplayError { 95 GpuDisplayError::BaseError(e) 96 } 97 } 98 99 impl From<IoError> for GpuDisplayError { from(e: IoError) -> GpuDisplayError100 fn from(e: IoError) -> GpuDisplayError { 101 GpuDisplayError::IoError(e) 102 } 103 } 104 105 /// A surface type 106 #[derive(Clone, Copy, Debug, PartialEq, Eq)] 107 pub enum SurfaceType { 108 /// Scanout surface 109 Scanout, 110 /// Mouse cursor surface 111 Cursor, 112 } 113 114 /// Event token for display instances 115 #[derive(EventToken, Debug)] 116 pub enum DisplayEventToken { 117 Display, 118 EventDevice { event_device_id: u32 }, 119 } 120 121 #[derive(Clone)] 122 pub struct GpuDisplayFramebuffer<'a> { 123 framebuffer: VolatileSlice<'a>, 124 slice: VolatileSlice<'a>, 125 stride: u32, 126 bytes_per_pixel: u32, 127 } 128 129 impl<'a> GpuDisplayFramebuffer<'a> { new( framebuffer: VolatileSlice<'a>, stride: u32, bytes_per_pixel: u32, ) -> GpuDisplayFramebuffer130 fn new( 131 framebuffer: VolatileSlice<'a>, 132 stride: u32, 133 bytes_per_pixel: u32, 134 ) -> GpuDisplayFramebuffer { 135 GpuDisplayFramebuffer { 136 framebuffer, 137 slice: framebuffer, 138 stride, 139 bytes_per_pixel, 140 } 141 } 142 sub_region( &self, x: u32, y: u32, width: u32, height: u32, ) -> Option<GpuDisplayFramebuffer<'a>>143 fn sub_region( 144 &self, 145 x: u32, 146 y: u32, 147 width: u32, 148 height: u32, 149 ) -> Option<GpuDisplayFramebuffer<'a>> { 150 let x_byte_offset = x.checked_mul(self.bytes_per_pixel)?; 151 let y_byte_offset = y.checked_mul(self.stride)?; 152 let byte_offset = x_byte_offset.checked_add(y_byte_offset)?; 153 154 let width_bytes = width.checked_mul(self.bytes_per_pixel)?; 155 let count = height 156 .checked_mul(self.stride)? 157 .checked_sub(self.stride)? 158 .checked_add(width_bytes)?; 159 let slice = self 160 .framebuffer 161 .sub_slice(byte_offset as usize, count as usize) 162 .unwrap(); 163 164 Some(GpuDisplayFramebuffer { slice, ..*self }) 165 } 166 as_volatile_slice(&self) -> VolatileSlice<'a>167 pub fn as_volatile_slice(&self) -> VolatileSlice<'a> { 168 self.slice 169 } 170 stride(&self) -> u32171 pub fn stride(&self) -> u32 { 172 self.stride 173 } 174 } 175 176 /// Empty trait, just used as a bounds for now 177 trait GpuDisplayImport {} 178 179 trait GpuDisplaySurface { 180 /// Returns an unique ID associated with the surface. This is typically generated by the 181 /// compositor or cast of a raw pointer. surface_descriptor(&self) -> u64182 fn surface_descriptor(&self) -> u64 { 183 0 184 } 185 186 /// Returns the next framebuffer, allocating if necessary. framebuffer(&mut self) -> Option<GpuDisplayFramebuffer>187 fn framebuffer(&mut self) -> Option<GpuDisplayFramebuffer> { 188 None 189 } 190 191 /// Returns true if the next buffer in the swapchain is already in use. next_buffer_in_use(&self) -> bool192 fn next_buffer_in_use(&self) -> bool { 193 false 194 } 195 196 /// Returns true if the surface should be closed. close_requested(&self) -> bool197 fn close_requested(&self) -> bool { 198 false 199 } 200 201 /// Puts the next buffer on the screen, making it the current buffer. flip(&mut self)202 fn flip(&mut self) { 203 // no-op 204 } 205 206 /// Puts the specified import_id on the screen. flip_to(&mut self, _import_id: u32)207 fn flip_to(&mut self, _import_id: u32) { 208 // no-op 209 } 210 211 /// Commits the surface to the compositor. commit(&mut self) -> GpuDisplayResult<()>212 fn commit(&mut self) -> GpuDisplayResult<()> { 213 Ok(()) 214 } 215 216 /// Sets the position of the identified subsurface relative to its parent. set_position(&mut self, _x: u32, _y: u32)217 fn set_position(&mut self, _x: u32, _y: u32) { 218 // no-op 219 } 220 221 /// Returns the type of the completed buffer. buffer_completion_type(&self) -> u32222 fn buffer_completion_type(&self) -> u32 { 223 0 224 } 225 226 /// Draws the current buffer on the screen. draw_current_buffer(&mut self)227 fn draw_current_buffer(&mut self) { 228 // no-op 229 } 230 231 /// Handles a compositor-specific client event. on_client_message(&mut self, _client_data: u64)232 fn on_client_message(&mut self, _client_data: u64) { 233 // no-op 234 } 235 236 /// Handles a compositor-specific shared memory completion event. on_shm_completion(&mut self, _shm_complete: u64)237 fn on_shm_completion(&mut self, _shm_complete: u64) { 238 // no-op 239 } 240 241 /// Sets the scanout ID for the surface. set_scanout_id(&mut self, _scanout_id: u32)242 fn set_scanout_id(&mut self, _scanout_id: u32) { 243 // no-op 244 } 245 } 246 247 struct GpuDisplayEvents { 248 events: Vec<virtio_input_event>, 249 device_type: EventDeviceKind, 250 } 251 252 trait DisplayT: AsRawDescriptor { 253 /// Returns true if there are events that are on the queue. pending_events(&self) -> bool254 fn pending_events(&self) -> bool { 255 false 256 } 257 258 /// Sends any pending commands to the compositor. flush(&self)259 fn flush(&self) { 260 // no-op 261 } 262 263 /// Returns the surface descirptor associated with the current event next_event(&mut self) -> GpuDisplayResult<u64>264 fn next_event(&mut self) -> GpuDisplayResult<u64> { 265 Ok(0) 266 } 267 268 /// Handles the event from the compositor, and returns an list of events handle_next_event( &mut self, _surface: &mut Box<dyn GpuDisplaySurface>, ) -> Option<GpuDisplayEvents>269 fn handle_next_event( 270 &mut self, 271 _surface: &mut Box<dyn GpuDisplaySurface>, 272 ) -> Option<GpuDisplayEvents> { 273 None 274 } 275 276 /// Creates a surface with the given parameters. The display backend is given a non-zero 277 /// `surface_id` as a handle for subsequent operations. create_surface( &mut self, parent_surface_id: Option<u32>, surface_id: u32, width: u32, height: u32, surf_type: SurfaceType, ) -> GpuDisplayResult<Box<dyn GpuDisplaySurface>>278 fn create_surface( 279 &mut self, 280 parent_surface_id: Option<u32>, 281 surface_id: u32, 282 width: u32, 283 height: u32, 284 surf_type: SurfaceType, 285 ) -> GpuDisplayResult<Box<dyn GpuDisplaySurface>>; 286 287 /// Imports memory into the display backend. The display backend is given a non-zero 288 /// `import_id` as a handle for subsequent operations. import_memory( &mut self, _import_id: u32, _descriptor: &dyn AsRawDescriptor, _offset: u32, _stride: u32, _modifiers: u64, _width: u32, _height: u32, _fourcc: u32, ) -> GpuDisplayResult<Box<dyn GpuDisplayImport>>289 fn import_memory( 290 &mut self, 291 _import_id: u32, 292 _descriptor: &dyn AsRawDescriptor, 293 _offset: u32, 294 _stride: u32, 295 _modifiers: u64, 296 _width: u32, 297 _height: u32, 298 _fourcc: u32, 299 ) -> GpuDisplayResult<Box<dyn GpuDisplayImport>> { 300 Err(GpuDisplayError::Unsupported) 301 } 302 } 303 304 pub trait GpuDisplayExt { 305 /// Imports the given `event_device` into the display, returning an event device id on success. 306 /// This device may be used to poll for input events. import_event_device(&mut self, event_device: EventDevice) -> GpuDisplayResult<u32>307 fn import_event_device(&mut self, event_device: EventDevice) -> GpuDisplayResult<u32>; 308 } 309 310 /// A connection to the compositor and associated collection of state. 311 /// 312 /// The user of `GpuDisplay` can use `AsRawDescriptor` to poll on the compositor connection's file 313 /// descriptor. When the connection is readable, `dispatch_events` can be called to process it. 314 pub struct GpuDisplay { 315 next_id: u32, 316 event_devices: BTreeMap<u32, EventDevice>, 317 surfaces: BTreeMap<u32, Box<dyn GpuDisplaySurface>>, 318 imports: BTreeMap<u32, Box<dyn GpuDisplayImport>>, 319 // `inner` must be after `imports` and `surfaces` to ensure those objects are dropped before 320 // the display context. The drop order for fields inside a struct is the order in which they 321 // are declared [Rust RFC 1857]. 322 inner: Box<dyn SysDisplayT>, 323 wait_ctx: WaitContext<DisplayEventToken>, 324 is_x: bool, 325 } 326 327 impl GpuDisplay { 328 /// Opens a connection to X server open_x<S: AsRef<str>>(display_name: Option<S>) -> GpuDisplayResult<GpuDisplay>329 pub fn open_x<S: AsRef<str>>(display_name: Option<S>) -> GpuDisplayResult<GpuDisplay> { 330 let _ = display_name; 331 #[cfg(feature = "x")] 332 { 333 let display = match display_name { 334 Some(s) => gpu_display_x::DisplayX::open_display(Some(s.as_ref()))?, 335 None => gpu_display_x::DisplayX::open_display(None)?, 336 }; 337 338 let wait_ctx = WaitContext::new()?; 339 wait_ctx.add(&display, DisplayEventToken::Display)?; 340 341 Ok(GpuDisplay { 342 inner: Box::new(display), 343 next_id: 1, 344 event_devices: Default::default(), 345 surfaces: Default::default(), 346 imports: Default::default(), 347 wait_ctx, 348 is_x: true, 349 }) 350 } 351 #[cfg(not(feature = "x"))] 352 Err(GpuDisplayError::Unsupported) 353 } 354 open_stub() -> GpuDisplayResult<GpuDisplay>355 pub fn open_stub() -> GpuDisplayResult<GpuDisplay> { 356 let display = gpu_display_stub::DisplayStub::new()?; 357 let wait_ctx = WaitContext::new()?; 358 wait_ctx.add(&display, DisplayEventToken::Display)?; 359 360 Ok(GpuDisplay { 361 inner: Box::new(display), 362 next_id: 1, 363 event_devices: Default::default(), 364 surfaces: Default::default(), 365 imports: Default::default(), 366 wait_ctx, 367 is_x: false, 368 }) 369 } 370 371 /// Return whether this display is an X display is_x(&self) -> bool372 pub fn is_x(&self) -> bool { 373 self.is_x 374 } 375 handle_event_device(&mut self, event_device_id: u32)376 fn handle_event_device(&mut self, event_device_id: u32) { 377 if let Some(event_device) = self.event_devices.get(&event_device_id) { 378 // TODO(zachr): decode the event and forward to the device. 379 let _ = event_device.recv_event_encoded(); 380 } 381 } 382 dispatch_display_events(&mut self) -> GpuDisplayResult<()>383 fn dispatch_display_events(&mut self) -> GpuDisplayResult<()> { 384 self.inner.flush(); 385 while self.inner.pending_events() { 386 let surface_descriptor = self.inner.next_event()?; 387 388 for surface in self.surfaces.values_mut() { 389 if surface_descriptor != surface.surface_descriptor() { 390 continue; 391 } 392 393 if let Some(gpu_display_events) = self.inner.handle_next_event(surface) { 394 for event_device in self.event_devices.values_mut() { 395 if event_device.kind() != gpu_display_events.device_type { 396 continue; 397 } 398 399 event_device.send_report(gpu_display_events.events.iter().cloned())?; 400 } 401 } 402 } 403 } 404 405 Ok(()) 406 } 407 408 /// Dispatches internal events that were received from the compositor since the last call to 409 /// `dispatch_events`. dispatch_events(&mut self) -> GpuDisplayResult<()>410 pub fn dispatch_events(&mut self) -> GpuDisplayResult<()> { 411 let wait_events = self.wait_ctx.wait_timeout(Duration::default())?; 412 413 if let Some(wait_event) = wait_events.iter().find(|e| e.is_hungup) { 414 base::error!( 415 "Display signaled with a hungup event for token {:?}", 416 wait_event.token 417 ); 418 self.wait_ctx = WaitContext::new().unwrap(); 419 return GpuDisplayResult::Err(GpuDisplayError::ConnectionBroken); 420 } 421 422 for wait_event in wait_events.iter().filter(|e| e.is_writable) { 423 if let DisplayEventToken::EventDevice { event_device_id } = wait_event.token { 424 if let Some(event_device) = self.event_devices.get_mut(&event_device_id) { 425 if !event_device.flush_buffered_events()? { 426 continue; 427 } 428 self.wait_ctx.modify( 429 event_device, 430 EventType::Read, 431 DisplayEventToken::EventDevice { event_device_id }, 432 )?; 433 } 434 } 435 } 436 437 for wait_event in wait_events.iter().filter(|e| e.is_readable) { 438 match wait_event.token { 439 DisplayEventToken::Display => self.dispatch_display_events()?, 440 DisplayEventToken::EventDevice { event_device_id } => { 441 self.handle_event_device(event_device_id) 442 } 443 } 444 } 445 446 Ok(()) 447 } 448 449 /// Creates a surface on the the compositor as either a top level window, or child of another 450 /// surface, returning a handle to the new surface. create_surface( &mut self, parent_surface_id: Option<u32>, width: u32, height: u32, surf_type: SurfaceType, ) -> GpuDisplayResult<u32>451 pub fn create_surface( 452 &mut self, 453 parent_surface_id: Option<u32>, 454 width: u32, 455 height: u32, 456 surf_type: SurfaceType, 457 ) -> GpuDisplayResult<u32> { 458 if let Some(parent_id) = parent_surface_id { 459 if !self.surfaces.contains_key(&parent_id) { 460 return Err(GpuDisplayError::InvalidSurfaceId); 461 } 462 } 463 464 let new_surface_id = self.next_id; 465 let new_surface = self.inner.create_surface( 466 parent_surface_id, 467 new_surface_id, 468 width, 469 height, 470 surf_type, 471 )?; 472 473 self.next_id += 1; 474 self.surfaces.insert(new_surface_id, new_surface); 475 Ok(new_surface_id) 476 } 477 478 /// Releases a previously created surface identified by the given handle. release_surface(&mut self, surface_id: u32)479 pub fn release_surface(&mut self, surface_id: u32) { 480 self.surfaces.remove(&surface_id); 481 } 482 483 /// Gets a reference to an unused framebuffer for the identified surface. framebuffer(&mut self, surface_id: u32) -> Option<GpuDisplayFramebuffer>484 pub fn framebuffer(&mut self, surface_id: u32) -> Option<GpuDisplayFramebuffer> { 485 let surface = self.surfaces.get_mut(&surface_id)?; 486 surface.framebuffer() 487 } 488 489 /// 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>490 pub fn framebuffer_region( 491 &mut self, 492 surface_id: u32, 493 x: u32, 494 y: u32, 495 width: u32, 496 height: u32, 497 ) -> Option<GpuDisplayFramebuffer> { 498 let framebuffer = self.framebuffer(surface_id)?; 499 framebuffer.sub_region(x, y, width, height) 500 } 501 502 /// Returns true if the next buffer in the buffer queue for the given surface is currently in 503 /// use. 504 /// 505 /// If the next buffer is in use, the memory returned from `framebuffer_memory` should not be 506 /// written to. next_buffer_in_use(&self, surface_id: u32) -> bool507 pub fn next_buffer_in_use(&self, surface_id: u32) -> bool { 508 self.surfaces 509 .get(&surface_id) 510 .map(|s| s.next_buffer_in_use()) 511 .unwrap_or(false) 512 } 513 514 /// Changes the visible contents of the identified surface to the contents of the framebuffer 515 /// last returned by `framebuffer_memory` for this surface. flip(&mut self, surface_id: u32)516 pub fn flip(&mut self, surface_id: u32) { 517 if let Some(surface) = self.surfaces.get_mut(&surface_id) { 518 surface.flip() 519 } 520 } 521 522 /// Returns true if the identified top level surface has been told to close by the compositor, 523 /// and by extension the user. close_requested(&self, surface_id: u32) -> bool524 pub fn close_requested(&self, surface_id: u32) -> bool { 525 self.surfaces 526 .get(&surface_id) 527 .map(|s| s.close_requested()) 528 .unwrap_or(true) 529 } 530 531 /// Imports memory to the compositor for use as a surface buffer and returns a handle 532 /// to it. import_memory( &mut self, descriptor: &dyn AsRawDescriptor, offset: u32, stride: u32, modifiers: u64, width: u32, height: u32, fourcc: u32, ) -> GpuDisplayResult<u32>533 pub fn import_memory( 534 &mut self, 535 descriptor: &dyn AsRawDescriptor, 536 offset: u32, 537 stride: u32, 538 modifiers: u64, 539 width: u32, 540 height: u32, 541 fourcc: u32, 542 ) -> GpuDisplayResult<u32> { 543 let import_id = self.next_id; 544 545 let gpu_display_memory = self.inner.import_memory( 546 import_id, descriptor, offset, stride, modifiers, width, height, fourcc, 547 )?; 548 549 self.next_id += 1; 550 self.imports.insert(import_id, gpu_display_memory); 551 Ok(import_id) 552 } 553 554 /// Releases a previously imported memory identified by the given handle. release_import(&mut self, import_id: u32)555 pub fn release_import(&mut self, import_id: u32) { 556 self.imports.remove(&import_id); 557 } 558 559 /// Commits any pending state for the identified surface. commit(&mut self, surface_id: u32) -> GpuDisplayResult<()>560 pub fn commit(&mut self, surface_id: u32) -> GpuDisplayResult<()> { 561 let surface = self 562 .surfaces 563 .get_mut(&surface_id) 564 .ok_or(GpuDisplayError::InvalidSurfaceId)?; 565 566 surface.commit() 567 } 568 569 /// Changes the visible contents of the identified surface to that of the identified imported 570 /// buffer. flip_to(&mut self, surface_id: u32, import_id: u32) -> GpuDisplayResult<()>571 pub fn flip_to(&mut self, surface_id: u32, import_id: u32) -> GpuDisplayResult<()> { 572 let surface = self 573 .surfaces 574 .get_mut(&surface_id) 575 .ok_or(GpuDisplayError::InvalidSurfaceId)?; 576 577 if !self.imports.contains_key(&import_id) { 578 return Err(GpuDisplayError::InvalidImportId); 579 } 580 581 surface.flip_to(import_id); 582 Ok(()) 583 } 584 585 /// Sets the position of the identified subsurface relative to its parent. 586 /// 587 /// 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<()>588 pub fn set_position(&mut self, surface_id: u32, x: u32, y: u32) -> GpuDisplayResult<()> { 589 let surface = self 590 .surfaces 591 .get_mut(&surface_id) 592 .ok_or(GpuDisplayError::InvalidSurfaceId)?; 593 594 surface.set_position(x, y); 595 Ok(()) 596 } 597 598 /// Associates the scanout id with the given surface. set_scanout_id(&mut self, surface_id: u32, scanout_id: u32) -> GpuDisplayResult<()>599 pub fn set_scanout_id(&mut self, surface_id: u32, scanout_id: u32) -> GpuDisplayResult<()> { 600 let surface = self 601 .surfaces 602 .get_mut(&surface_id) 603 .ok_or(GpuDisplayError::InvalidSurfaceId)?; 604 605 surface.set_scanout_id(scanout_id); 606 Ok(()) 607 } 608 } 609