1use std::collections::BTreeMap;
9use std::io::Error as IoError;
10use std::time::Duration;
11
12use anyhow::anyhow;
13use anyhow::Context;
14use base::AsRawDescriptor;
15use base::Error as BaseError;
16use base::EventToken;
17use base::EventType;
18use base::VolatileSlice;
19use base::WaitContext;
20use remain::sorted;
21use serde::Deserialize;
22use serde::Serialize;
23use sync::Waitable;
24use thiserror::Error;
25use vm_control::gpu::DisplayParameters;
26use vm_control::gpu::MouseMode;
27#[cfg(feature = "vulkan_display")]
28use vulkano::VulkanLibrary;
29
30mod event_device;
31#[cfg(feature = "android_display")]
32mod gpu_display_android;
33#[cfg(feature = "android_display_stub")]
34mod gpu_display_android_stub;
35mod gpu_display_stub;
36#[cfg(windows)]
37mod gpu_display_win;
38#[cfg(any(target_os = "android", target_os = "linux"))]
39mod gpu_display_wl;
40#[cfg(feature = "x")]
41mod gpu_display_x;
42#[cfg(any(windows, feature = "x"))]
43mod keycode_converter;
44mod sys;
45#[cfg(feature = "vulkan_display")]
46pub mod vulkan;
47
48pub use event_device::EventDevice;
49pub use event_device::EventDeviceKind;
50#[cfg(windows)]
51pub use gpu_display_win::WindowProcedureThread;
52#[cfg(windows)]
53pub use gpu_display_win::WindowProcedureThreadBuilder;
54use linux_input_sys::virtio_input_event;
55use sys::SysDisplayT;
56pub use sys::SysGpuDisplayExt;
57
58#[cfg(feature = "vulkan_display")]
60const VK_UUID_BYTES: usize = 16;
61
62#[derive(Clone)]
63pub 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#[sorted]
74#[derive(Error, Debug)]
75pub enum GpuDisplayError {
76 #[error("internal allocation failed")]
78 Allocate,
79 #[error("received a base error: {0}")]
81 BaseError(BaseError),
82 #[error("failed to connect to compositor")]
84 Connect,
85 #[error("connection to compositor has been broken")]
87 ConnectionBroken,
88 #[error("failed to create event file descriptor")]
90 CreateEvent,
91 #[error("failed to crate surface on the compositor")]
93 CreateSurface,
94 #[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 #[error("failed to import a buffer to the compositor")]
101 FailedImport,
102 #[error("invalid Android display service name: {0}")]
104 InvalidAndroidDisplayServiceName(String),
105 #[error("invalid import ID")]
107 InvalidImportId,
108 #[error("invalid path")]
110 InvalidPath,
111 #[error("invalid surface ID")]
113 InvalidSurfaceId,
114 #[error("an input/output error occur: {0}")]
116 IoError(IoError),
117 #[error("required feature was missing: {0}")]
119 RequiredFeature(&'static str),
120 #[error("unsupported by the implementation")]
122 Unsupported,
123}
124
125pub type GpuDisplayResult<T> = std::result::Result<T, GpuDisplayError>;
126
127impl From<BaseError> for GpuDisplayError {
128 fn from(e: BaseError) -> GpuDisplayError {
129 GpuDisplayError::BaseError(e)
130 }
131}
132
133impl From<IoError> for GpuDisplayError {
134 fn from(e: IoError) -> GpuDisplayError {
135 GpuDisplayError::IoError(e)
136 }
137}
138
139#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
141pub enum SurfaceType {
142 Scanout,
144 Cursor,
146}
147
148#[derive(EventToken, Debug)]
150pub enum DisplayEventToken {
151 Display,
152 EventDevice { event_device_id: u32 },
153}
154
155#[derive(Clone)]
156pub struct GpuDisplayFramebuffer<'a> {
157 framebuffer: VolatileSlice<'a>,
158 slice: VolatileSlice<'a>,
159 stride: u32,
160 bytes_per_pixel: u32,
161}
162
163impl<'a> GpuDisplayFramebuffer<'a> {
164 fn new(
165 framebuffer: VolatileSlice<'a>,
166 stride: u32,
167 bytes_per_pixel: u32,
168 ) -> GpuDisplayFramebuffer<'a> {
169 GpuDisplayFramebuffer {
170 framebuffer,
171 slice: framebuffer,
172 stride,
173 bytes_per_pixel,
174 }
175 }
176
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
201 pub fn as_volatile_slice(&self) -> VolatileSlice<'a> {
202 self.slice
203 }
204
205 pub fn stride(&self) -> u32 {
206 self.stride
207 }
208}
209
210trait GpuDisplaySurface {
211 fn surface_descriptor(&self) -> u64 {
214 0
215 }
216
217 fn framebuffer(&mut self) -> Option<GpuDisplayFramebuffer> {
219 None
220 }
221
222 fn next_buffer_in_use(&self) -> bool {
224 false
225 }
226
227 fn close_requested(&self) -> bool {
229 false
230 }
231
232 fn flip(&mut self) {
234 }
236
237 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 Ok(Waitable::signaled())
247 }
248
249 fn commit(&mut self) -> GpuDisplayResult<()> {
251 Ok(())
252 }
253
254 fn set_mouse_mode(&mut self, _mouse_mode: MouseMode) {
256 }
258
259 fn set_position(&mut self, _x: u32, _y: u32) {
261 }
263
264 #[allow(dead_code)]
266 fn buffer_completion_type(&self) -> u32 {
267 0
268 }
269
270 #[allow(dead_code)]
272 fn draw_current_buffer(&mut self) {
273 }
275
276 #[allow(dead_code)]
278 fn on_client_message(&mut self, _client_data: u64) {
279 }
281
282 #[allow(dead_code)]
284 fn on_shm_completion(&mut self, _shm_complete: u64) {
285 }
287}
288
289struct GpuDisplayEvents {
290 events: Vec<virtio_input_event>,
291 device_type: EventDeviceKind,
292}
293
294trait DisplayT: AsRawDescriptor {
295 fn pending_events(&self) -> bool {
297 false
298 }
299
300 fn flush(&self) {
302 }
304
305 fn next_event(&mut self) -> GpuDisplayResult<u64> {
307 Ok(0)
308 }
309
310 fn handle_next_event(
312 &mut self,
313 _surface: &mut Box<dyn GpuDisplaySurface>,
314 ) -> Option<GpuDisplayEvents> {
315 None
316 }
317
318 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 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 fn release_import(&mut self, _import_id: u32, _surface_id: u32) {}
342}
343
344pub trait GpuDisplayExt {
345 fn import_event_device(&mut self, event_device: EventDevice) -> GpuDisplayResult<u32>;
348
349 fn handle_event_device(&mut self, event_device_id: u32);
351}
352
353pub 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
372pub struct VkExtent3D {
373 pub width: u32,
374 pub height: u32,
375 pub depth: u32,
376}
377
378pub struct VulkanDisplayImageImportMetadata {
379 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 pub allocation_size: u64,
395 pub memory_type_index: u32,
396
397 pub dedicated_allocation: bool,
399}
400
401pub struct SemaphoreTimepoint {
402 pub import_id: u32,
403 pub value: u64,
404}
405
406pub enum FlipToExtraInfo {
407 #[cfg(feature = "vulkan_display")]
408 Vulkan { old_layout: i32, new_layout: i32 },
409}
410
411pub 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: Box<dyn SysDisplayT>,
427}
428
429impl GpuDisplay {
430 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
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
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 pub fn take_event_devices(&mut self) -> Vec<EventDevice> {
492 std::mem::take(&mut self.event_devices)
493 .into_values()
494 .collect()
495 }
496
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 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 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 pub fn release_surface(&mut self, surface_id: u32) {
594 self.surfaces.remove(&surface_id);
595 }
596
597 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 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 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 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 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 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 pub fn release_import(&mut self, import_id: u32, surface_id: u32) {
663 self.inner.release_import(import_id, surface_id);
664 }
665
666 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 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 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 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}