xref: /aosp_15_r20/external/crosvm/gpu_display/src/lib.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
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