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