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. 265 #[allow(dead_code)] buffer_completion_type(&self) -> u32266 fn buffer_completion_type(&self) -> u32 { 267 0 268 } 269 270 /// Draws the current buffer on the screen. 271 #[allow(dead_code)] draw_current_buffer(&mut self)272 fn draw_current_buffer(&mut self) { 273 // no-op 274 } 275 276 /// Handles a compositor-specific client event. 277 #[allow(dead_code)] on_client_message(&mut self, _client_data: u64)278 fn on_client_message(&mut self, _client_data: u64) { 279 // no-op 280 } 281 282 /// Handles a compositor-specific shared memory completion event. 283 #[allow(dead_code)] on_shm_completion(&mut self, _shm_complete: u64)284 fn on_shm_completion(&mut self, _shm_complete: u64) { 285 // no-op 286 } 287 } 288 289 struct GpuDisplayEvents { 290 events: Vec<virtio_input_event>, 291 device_type: EventDeviceKind, 292 } 293 294 trait DisplayT: AsRawDescriptor { 295 /// Returns true if there are events that are on the queue. pending_events(&self) -> bool296 fn pending_events(&self) -> bool { 297 false 298 } 299 300 /// Sends any pending commands to the compositor. flush(&self)301 fn flush(&self) { 302 // no-op 303 } 304 305 /// Returns the surface descirptor associated with the current event next_event(&mut self) -> GpuDisplayResult<u64>306 fn next_event(&mut self) -> GpuDisplayResult<u64> { 307 Ok(0) 308 } 309 310 /// 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 fn handle_next_event( 312 &mut self, 313 _surface: &mut Box<dyn GpuDisplaySurface>, 314 ) -> Option<GpuDisplayEvents> { 315 None 316 } 317 318 /// Creates a surface with the given parameters. The display backend is given a non-zero 319 /// `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 fn create_surface( 321 &mut self, 322 parent_surface_id: Option<u32>, 323 surface_id: u32, 324 scanout_id: Option<u32>, 325 display_params: &DisplayParameters, 326 surf_type: SurfaceType, 327 ) -> GpuDisplayResult<Box<dyn GpuDisplaySurface>>; 328 329 /// Imports a resource into the display backend. The display backend is given a non-zero 330 /// `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 fn import_resource( 332 &mut self, 333 _import_id: u32, 334 _surface_id: u32, 335 _external_display_resource: DisplayExternalResourceImport, 336 ) -> anyhow::Result<()> { 337 Err(anyhow!("import_resource is unsupported")) 338 } 339 340 /// Frees a previously imported resource. release_import(&mut self, _import_id: u32, _surface_id: u32)341 fn release_import(&mut self, _import_id: u32, _surface_id: u32) {} 342 } 343 344 pub trait GpuDisplayExt { 345 /// Imports the given `event_device` into the display, returning an event device id on success. 346 /// This device may be used to dispatch input events to the guest. import_event_device(&mut self, event_device: EventDevice) -> GpuDisplayResult<u32>347 fn import_event_device(&mut self, event_device: EventDevice) -> GpuDisplayResult<u32>; 348 349 /// Called when an event device is readable. handle_event_device(&mut self, event_device_id: u32)350 fn handle_event_device(&mut self, event_device_id: u32); 351 } 352 353 pub enum DisplayExternalResourceImport<'a> { 354 Dmabuf { 355 descriptor: &'a dyn AsRawDescriptor, 356 offset: u32, 357 stride: u32, 358 modifiers: u64, 359 width: u32, 360 height: u32, 361 fourcc: u32, 362 }, 363 VulkanImage { 364 descriptor: &'a dyn AsRawDescriptor, 365 metadata: VulkanDisplayImageImportMetadata, 366 }, 367 VulkanTimelineSemaphore { 368 descriptor: &'a dyn AsRawDescriptor, 369 }, 370 } 371 372 pub struct VkExtent3D { 373 pub width: u32, 374 pub height: u32, 375 pub depth: u32, 376 } 377 378 pub struct VulkanDisplayImageImportMetadata { 379 // These fields go into a VkImageCreateInfo 380 pub flags: u32, 381 pub image_type: i32, 382 pub format: i32, 383 pub extent: VkExtent3D, 384 pub mip_levels: u32, 385 pub array_layers: u32, 386 pub samples: u32, 387 pub tiling: i32, 388 pub usage: u32, 389 pub sharing_mode: i32, 390 pub queue_family_indices: Vec<u32>, 391 pub initial_layout: i32, 392 393 // These fields go into a VkMemoryAllocateInfo 394 pub allocation_size: u64, 395 pub memory_type_index: u32, 396 397 // Additional information 398 pub dedicated_allocation: bool, 399 } 400 401 pub struct SemaphoreTimepoint { 402 pub import_id: u32, 403 pub value: u64, 404 } 405 406 pub enum FlipToExtraInfo { 407 #[cfg(feature = "vulkan_display")] 408 Vulkan { old_layout: i32, new_layout: i32 }, 409 } 410 411 /// A connection to the compositor and associated collection of state. 412 /// 413 /// The user of `GpuDisplay` can use `AsRawDescriptor` to poll on the compositor connection's file 414 /// descriptor. When the connection is readable, `dispatch_events` can be called to process it. 415 pub struct GpuDisplay { 416 next_id: u32, 417 event_devices: BTreeMap<u32, EventDevice>, 418 surfaces: BTreeMap<u32, Box<dyn GpuDisplaySurface>>, 419 wait_ctx: WaitContext<DisplayEventToken>, 420 // `inner` must be after `surfaces` to ensure those objects are dropped before 421 // the display context. The drop order for fields inside a struct is the order in which they 422 // are declared [Rust RFC 1857]. 423 // 424 // We also don't want to drop inner before wait_ctx because it contains references to the event 425 // devices owned by inner.display_event_dispatcher. 426 inner: Box<dyn SysDisplayT>, 427 } 428 429 impl GpuDisplay { 430 /// Opens a connection to X server open_x(display_name: Option<&str>) -> GpuDisplayResult<GpuDisplay>431 pub fn open_x(display_name: Option<&str>) -> GpuDisplayResult<GpuDisplay> { 432 let _ = display_name; 433 #[cfg(feature = "x")] 434 { 435 let display = gpu_display_x::DisplayX::open_display(display_name)?; 436 437 let wait_ctx = WaitContext::new()?; 438 wait_ctx.add(&display, DisplayEventToken::Display)?; 439 440 Ok(GpuDisplay { 441 inner: Box::new(display), 442 next_id: 1, 443 event_devices: Default::default(), 444 surfaces: Default::default(), 445 wait_ctx, 446 }) 447 } 448 #[cfg(not(feature = "x"))] 449 Err(GpuDisplayError::Unsupported) 450 } 451 open_android(service_name: &str) -> GpuDisplayResult<GpuDisplay>452 pub fn open_android(service_name: &str) -> GpuDisplayResult<GpuDisplay> { 453 let _ = service_name; 454 #[cfg(feature = "android_display")] 455 { 456 let display = gpu_display_android::DisplayAndroid::new(service_name)?; 457 458 let wait_ctx = WaitContext::new()?; 459 wait_ctx.add(&display, DisplayEventToken::Display)?; 460 461 Ok(GpuDisplay { 462 inner: Box::new(display), 463 next_id: 1, 464 event_devices: Default::default(), 465 surfaces: Default::default(), 466 wait_ctx, 467 }) 468 } 469 #[cfg(not(feature = "android_display"))] 470 Err(GpuDisplayError::Unsupported) 471 } 472 open_stub() -> GpuDisplayResult<GpuDisplay>473 pub fn open_stub() -> GpuDisplayResult<GpuDisplay> { 474 let display = gpu_display_stub::DisplayStub::new()?; 475 let wait_ctx = WaitContext::new()?; 476 wait_ctx.add(&display, DisplayEventToken::Display)?; 477 478 Ok(GpuDisplay { 479 inner: Box::new(display), 480 next_id: 1, 481 event_devices: Default::default(), 482 surfaces: Default::default(), 483 wait_ctx, 484 }) 485 } 486 487 // Leaves the `GpuDisplay` in a undefined state. 488 // 489 // TODO: Would be nice to change receiver from `&mut self` to `self`. Requires some refactoring 490 // elsewhere. take_event_devices(&mut self) -> Vec<EventDevice>491 pub fn take_event_devices(&mut self) -> Vec<EventDevice> { 492 std::mem::take(&mut self.event_devices) 493 .into_values() 494 .collect() 495 } 496 dispatch_display_events(&mut self) -> GpuDisplayResult<()>497 fn dispatch_display_events(&mut self) -> GpuDisplayResult<()> { 498 self.inner.flush(); 499 while self.inner.pending_events() { 500 let surface_descriptor = self.inner.next_event()?; 501 502 for surface in self.surfaces.values_mut() { 503 if surface_descriptor != surface.surface_descriptor() { 504 continue; 505 } 506 507 if let Some(gpu_display_events) = self.inner.handle_next_event(surface) { 508 for event_device in self.event_devices.values_mut() { 509 if event_device.kind() != gpu_display_events.device_type { 510 continue; 511 } 512 513 event_device.send_report(gpu_display_events.events.iter().cloned())?; 514 } 515 } 516 } 517 } 518 519 Ok(()) 520 } 521 522 /// Dispatches internal events that were received from the compositor since the last call to 523 /// `dispatch_events`. dispatch_events(&mut self) -> GpuDisplayResult<()>524 pub fn dispatch_events(&mut self) -> GpuDisplayResult<()> { 525 let wait_events = self.wait_ctx.wait_timeout(Duration::default())?; 526 527 if let Some(wait_event) = wait_events.iter().find(|e| e.is_hungup) { 528 base::error!( 529 "Display signaled with a hungup event for token {:?}", 530 wait_event.token 531 ); 532 self.wait_ctx = WaitContext::new().unwrap(); 533 return GpuDisplayResult::Err(GpuDisplayError::ConnectionBroken); 534 } 535 536 for wait_event in wait_events.iter().filter(|e| e.is_writable) { 537 if let DisplayEventToken::EventDevice { event_device_id } = wait_event.token { 538 if let Some(event_device) = self.event_devices.get_mut(&event_device_id) { 539 if !event_device.flush_buffered_events()? { 540 continue; 541 } 542 self.wait_ctx.modify( 543 event_device, 544 EventType::Read, 545 DisplayEventToken::EventDevice { event_device_id }, 546 )?; 547 } 548 } 549 } 550 551 for wait_event in wait_events.iter().filter(|e| e.is_readable) { 552 match wait_event.token { 553 DisplayEventToken::Display => self.dispatch_display_events()?, 554 DisplayEventToken::EventDevice { event_device_id } => { 555 self.handle_event_device(event_device_id) 556 } 557 } 558 } 559 560 Ok(()) 561 } 562 563 /// Creates a surface on the the compositor as either a top level window, or child of another 564 /// 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 pub fn create_surface( 566 &mut self, 567 parent_surface_id: Option<u32>, 568 scanout_id: Option<u32>, 569 display_params: &DisplayParameters, 570 surf_type: SurfaceType, 571 ) -> GpuDisplayResult<u32> { 572 if let Some(parent_id) = parent_surface_id { 573 if !self.surfaces.contains_key(&parent_id) { 574 return Err(GpuDisplayError::InvalidSurfaceId); 575 } 576 } 577 578 let new_surface_id = self.next_id; 579 let new_surface = self.inner.create_surface( 580 parent_surface_id, 581 new_surface_id, 582 scanout_id, 583 display_params, 584 surf_type, 585 )?; 586 587 self.next_id += 1; 588 self.surfaces.insert(new_surface_id, new_surface); 589 Ok(new_surface_id) 590 } 591 592 /// Releases a previously created surface identified by the given handle. release_surface(&mut self, surface_id: u32)593 pub fn release_surface(&mut self, surface_id: u32) { 594 self.surfaces.remove(&surface_id); 595 } 596 597 /// Gets a reference to an unused framebuffer for the identified surface. framebuffer(&mut self, surface_id: u32) -> Option<GpuDisplayFramebuffer>598 pub fn framebuffer(&mut self, surface_id: u32) -> Option<GpuDisplayFramebuffer> { 599 let surface = self.surfaces.get_mut(&surface_id)?; 600 surface.framebuffer() 601 } 602 603 /// 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 pub fn framebuffer_region( 605 &mut self, 606 surface_id: u32, 607 x: u32, 608 y: u32, 609 width: u32, 610 height: u32, 611 ) -> Option<GpuDisplayFramebuffer> { 612 let framebuffer = self.framebuffer(surface_id)?; 613 framebuffer.sub_region(x, y, width, height) 614 } 615 616 /// Returns true if the next buffer in the buffer queue for the given surface is currently in 617 /// use. 618 /// 619 /// If the next buffer is in use, the memory returned from `framebuffer_memory` should not be 620 /// written to. next_buffer_in_use(&self, surface_id: u32) -> bool621 pub fn next_buffer_in_use(&self, surface_id: u32) -> bool { 622 self.surfaces 623 .get(&surface_id) 624 .map(|s| s.next_buffer_in_use()) 625 .unwrap_or(false) 626 } 627 628 /// Changes the visible contents of the identified surface to the contents of the framebuffer 629 /// last returned by `framebuffer_memory` for this surface. flip(&mut self, surface_id: u32)630 pub fn flip(&mut self, surface_id: u32) { 631 if let Some(surface) = self.surfaces.get_mut(&surface_id) { 632 surface.flip() 633 } 634 } 635 636 /// Returns true if the identified top level surface has been told to close by the compositor, 637 /// and by extension the user. close_requested(&self, surface_id: u32) -> bool638 pub fn close_requested(&self, surface_id: u32) -> bool { 639 self.surfaces 640 .get(&surface_id) 641 .map(|s| s.close_requested()) 642 .unwrap_or(true) 643 } 644 645 /// Imports a resource to the display backend. This resource may be an image for the compositor 646 /// or a synchronization object. import_resource( &mut self, surface_id: u32, external_display_resource: DisplayExternalResourceImport, ) -> anyhow::Result<u32>647 pub fn import_resource( 648 &mut self, 649 surface_id: u32, 650 external_display_resource: DisplayExternalResourceImport, 651 ) -> anyhow::Result<u32> { 652 let import_id = self.next_id; 653 654 self.inner 655 .import_resource(import_id, surface_id, external_display_resource)?; 656 657 self.next_id += 1; 658 Ok(import_id) 659 } 660 661 /// Releases a previously imported resource identified by the given handle. release_import(&mut self, import_id: u32, surface_id: u32)662 pub fn release_import(&mut self, import_id: u32, surface_id: u32) { 663 self.inner.release_import(import_id, surface_id); 664 } 665 666 /// Commits any pending state for the identified surface. commit(&mut self, surface_id: u32) -> GpuDisplayResult<()>667 pub fn commit(&mut self, surface_id: u32) -> GpuDisplayResult<()> { 668 let surface = self 669 .surfaces 670 .get_mut(&surface_id) 671 .ok_or(GpuDisplayError::InvalidSurfaceId)?; 672 673 surface.commit() 674 } 675 676 /// Changes the visible contents of the identified surface to that of the identified imported 677 /// 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 pub fn flip_to( 679 &mut self, 680 surface_id: u32, 681 import_id: u32, 682 acquire_timepoint: Option<SemaphoreTimepoint>, 683 release_timepoint: Option<SemaphoreTimepoint>, 684 extra_info: Option<FlipToExtraInfo>, 685 ) -> anyhow::Result<Waitable> { 686 let surface = self 687 .surfaces 688 .get_mut(&surface_id) 689 .ok_or(GpuDisplayError::InvalidSurfaceId)?; 690 691 surface 692 .flip_to(import_id, acquire_timepoint, release_timepoint, extra_info) 693 .context("failed in flip on GpuDisplaySurface") 694 } 695 696 /// Sets the mouse mode used on this surface. set_mouse_mode( &mut self, surface_id: u32, mouse_mode: MouseMode, ) -> GpuDisplayResult<()>697 pub fn set_mouse_mode( 698 &mut self, 699 surface_id: u32, 700 mouse_mode: MouseMode, 701 ) -> GpuDisplayResult<()> { 702 let surface = self 703 .surfaces 704 .get_mut(&surface_id) 705 .ok_or(GpuDisplayError::InvalidSurfaceId)?; 706 707 surface.set_mouse_mode(mouse_mode); 708 Ok(()) 709 } 710 711 /// Sets the position of the identified subsurface relative to its parent. 712 /// 713 /// 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 pub fn set_position(&mut self, surface_id: u32, x: u32, y: u32) -> GpuDisplayResult<()> { 715 let surface = self 716 .surfaces 717 .get_mut(&surface_id) 718 .ok_or(GpuDisplayError::InvalidSurfaceId)?; 719 720 surface.set_position(x, y); 721 Ok(()) 722 } 723 } 724