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 rutabaga_gfx::AhbInfo;
22use serde::Deserialize;
23use serde::Serialize;
24use sync::Waitable;
25use thiserror::Error;
26use vm_control::gpu::DisplayParameters;
27use vm_control::gpu::MouseMode;
28#[cfg(feature = "vulkan_display")]
29use vulkano::VulkanLibrary;
30
31mod event_device;
32#[cfg(feature = "android_display")]
33mod gpu_display_android;
34#[cfg(feature = "android_display_stub")]
35mod gpu_display_android_stub;
36mod gpu_display_stub;
37#[cfg(windows)]
38mod gpu_display_win;
39#[cfg(any(target_os = "android", target_os = "linux"))]
40mod gpu_display_wl;
41#[cfg(feature = "x")]
42mod gpu_display_x;
43#[cfg(any(windows, feature = "x"))]
44mod keycode_converter;
45mod sys;
46#[cfg(feature = "vulkan_display")]
47pub mod vulkan;
48
49pub use event_device::EventDevice;
50pub use event_device::EventDeviceKind;
51#[cfg(windows)]
52pub use gpu_display_win::WindowProcedureThread;
53#[cfg(windows)]
54pub use gpu_display_win::WindowProcedureThreadBuilder;
55use linux_input_sys::virtio_input_event;
56use sys::SysDisplayT;
57pub use sys::SysGpuDisplayExt;
58
59#[cfg(feature = "vulkan_display")]
61const VK_UUID_BYTES: usize = 16;
62
63#[derive(Clone)]
64pub struct VulkanCreateParams {
65 #[cfg(feature = "vulkan_display")]
66 pub vulkan_library: std::sync::Arc<VulkanLibrary>,
67 #[cfg(feature = "vulkan_display")]
68 pub device_uuid: [u8; VK_UUID_BYTES],
69 #[cfg(feature = "vulkan_display")]
70 pub driver_uuid: [u8; VK_UUID_BYTES],
71}
72
73#[sorted]
75#[derive(Error, Debug)]
76pub enum GpuDisplayError {
77 #[error("internal allocation failed")]
79 Allocate,
80 #[error("received a base error: {0}")]
82 BaseError(BaseError),
83 #[error("failed to connect to compositor")]
85 Connect,
86 #[error("connection to compositor has been broken")]
88 ConnectionBroken,
89 #[error("failed to create event file descriptor")]
91 CreateEvent,
92 #[error("failed to crate surface on the compositor")]
94 CreateSurface,
95 #[error("failed to import an event device: {0}")]
97 FailedEventDeviceImport(String),
98 #[error("failed to register an event device to listen for guest events: {0}")]
99 FailedEventDeviceListen(base::TubeError),
100 #[error("failed to import a buffer to the compositor")]
102 FailedImport,
103 #[error("invalid Android display service name: {0}")]
105 InvalidAndroidDisplayServiceName(String),
106 #[error("invalid import ID")]
108 InvalidImportId,
109 #[error("invalid path")]
111 InvalidPath,
112 #[error("invalid surface ID")]
114 InvalidSurfaceId,
115 #[error("an input/output error occur: {0}")]
117 IoError(IoError),
118 #[error("required feature was missing: {0}")]
120 RequiredFeature(&'static str),
121 #[error("unsupported by the implementation")]
123 Unsupported,
124}
125
126pub type GpuDisplayResult<T> = std::result::Result<T, GpuDisplayError>;
127
128impl From<BaseError> for GpuDisplayError {
129 fn from(e: BaseError) -> GpuDisplayError {
130 GpuDisplayError::BaseError(e)
131 }
132}
133
134impl From<IoError> for GpuDisplayError {
135 fn from(e: IoError) -> GpuDisplayError {
136 GpuDisplayError::IoError(e)
137 }
138}
139
140#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
142pub enum SurfaceType {
143 Scanout,
145 Cursor,
147}
148
149#[derive(EventToken, Debug)]
151pub enum DisplayEventToken {
152 Display,
153 EventDevice { event_device_id: u32 },
154}
155
156#[derive(Clone)]
157pub struct GpuDisplayFramebuffer<'a> {
158 framebuffer: VolatileSlice<'a>,
159 slice: VolatileSlice<'a>,
160 stride: u32,
161 bytes_per_pixel: u32,
162}
163
164impl<'a> GpuDisplayFramebuffer<'a> {
165 fn new(
166 framebuffer: VolatileSlice<'a>,
167 stride: u32,
168 bytes_per_pixel: u32,
169 ) -> GpuDisplayFramebuffer<'a> {
170 GpuDisplayFramebuffer {
171 framebuffer,
172 slice: framebuffer,
173 stride,
174 bytes_per_pixel,
175 }
176 }
177
178 fn sub_region(
179 &self,
180 x: u32,
181 y: u32,
182 width: u32,
183 height: u32,
184 ) -> Option<GpuDisplayFramebuffer<'a>> {
185 let x_byte_offset = x.checked_mul(self.bytes_per_pixel)?;
186 let y_byte_offset = y.checked_mul(self.stride)?;
187 let byte_offset = x_byte_offset.checked_add(y_byte_offset)?;
188
189 let width_bytes = width.checked_mul(self.bytes_per_pixel)?;
190 let count = height
191 .checked_mul(self.stride)?
192 .checked_sub(self.stride)?
193 .checked_add(width_bytes)?;
194 let slice = self
195 .framebuffer
196 .sub_slice(byte_offset as usize, count as usize)
197 .unwrap();
198
199 Some(GpuDisplayFramebuffer { slice, ..*self })
200 }
201
202 pub fn as_volatile_slice(&self) -> VolatileSlice<'a> {
203 self.slice
204 }
205
206 pub fn stride(&self) -> u32 {
207 self.stride
208 }
209}
210
211trait GpuDisplaySurface {
212 fn surface_descriptor(&self) -> u64 {
215 0
216 }
217
218 fn framebuffer(&mut self) -> Option<GpuDisplayFramebuffer> {
220 None
221 }
222
223 fn next_buffer_in_use(&self) -> bool {
225 false
226 }
227
228 fn close_requested(&self) -> bool {
230 false
231 }
232
233 fn flip(&mut self) {
235 }
237
238 fn flip_to(
240 &mut self,
241 _import_id: u32,
242 _acquire_timepoint: Option<SemaphoreTimepoint>,
243 _release_timepoint: Option<SemaphoreTimepoint>,
244 _extra_info: Option<FlipToExtraInfo>,
245 ) -> anyhow::Result<Waitable> {
246 Ok(Waitable::signaled())
248 }
249
250 fn commit(&mut self) -> GpuDisplayResult<()> {
252 Ok(())
253 }
254
255 fn set_mouse_mode(&mut self, _mouse_mode: MouseMode) {
257 }
259
260 fn set_position(&mut self, _x: u32, _y: u32) {
262 }
264
265 #[allow(dead_code)]
267 fn buffer_completion_type(&self) -> u32 {
268 0
269 }
270
271 #[allow(dead_code)]
273 fn draw_current_buffer(&mut self) {
274 }
276
277 #[allow(dead_code)]
279 fn on_client_message(&mut self, _client_data: u64) {
280 }
282
283 #[allow(dead_code)]
285 fn on_shm_completion(&mut self, _shm_complete: u64) {
286 }
288}
289
290struct GpuDisplayEvents {
291 events: Vec<virtio_input_event>,
292 device_type: EventDeviceKind,
293}
294
295trait DisplayT: AsRawDescriptor {
296 fn pending_events(&self) -> bool {
298 false
299 }
300
301 fn flush(&self) {
303 }
305
306 fn next_event(&mut self) -> GpuDisplayResult<u64> {
308 Ok(0)
309 }
310
311 fn handle_next_event(
313 &mut self,
314 _surface: &mut Box<dyn GpuDisplaySurface>,
315 ) -> Option<GpuDisplayEvents> {
316 None
317 }
318
319 fn create_surface(
322 &mut self,
323 parent_surface_id: Option<u32>,
324 surface_id: u32,
325 scanout_id: Option<u32>,
326 display_params: &DisplayParameters,
327 surf_type: SurfaceType,
328 ) -> GpuDisplayResult<Box<dyn GpuDisplaySurface>>;
329
330 fn import_resource(
333 &mut self,
334 _import_id: u32,
335 _surface_id: u32,
336 _external_display_resource: DisplayExternalResourceImport,
337 ) -> anyhow::Result<()> {
338 Err(anyhow!("import_resource is unsupported"))
339 }
340
341 fn release_import(&mut self, _import_id: u32, _surface_id: u32) {}
343
344 fn release_surface(&mut self, _surface_id: u32) {}
346}
347
348pub trait GpuDisplayExt {
349 fn import_event_device(&mut self, event_device: EventDevice) -> GpuDisplayResult<u32>;
352
353 fn handle_event_device(&mut self, event_device_id: u32);
355}
356
357pub enum DisplayExternalResourceImport<'a> {
358 Dmabuf {
359 descriptor: &'a dyn AsRawDescriptor,
360 offset: u32,
361 stride: u32,
362 modifiers: u64,
363 width: u32,
364 height: u32,
365 fourcc: u32,
366 },
367 VulkanImage {
368 descriptor: &'a dyn AsRawDescriptor,
369 metadata: VulkanDisplayImageImportMetadata,
370 },
371 VulkanTimelineSemaphore {
372 descriptor: &'a dyn AsRawDescriptor,
373 },
374 AHardwareBuffer {
375 info: AhbInfo,
376 },
377}
378
379pub struct VkExtent3D {
380 pub width: u32,
381 pub height: u32,
382 pub depth: u32,
383}
384
385pub struct VulkanDisplayImageImportMetadata {
386 pub flags: u32,
388 pub image_type: i32,
389 pub format: i32,
390 pub extent: VkExtent3D,
391 pub mip_levels: u32,
392 pub array_layers: u32,
393 pub samples: u32,
394 pub tiling: i32,
395 pub usage: u32,
396 pub sharing_mode: i32,
397 pub queue_family_indices: Vec<u32>,
398 pub initial_layout: i32,
399
400 pub allocation_size: u64,
402 pub memory_type_index: u32,
403
404 pub dedicated_allocation: bool,
406}
407
408pub struct SemaphoreTimepoint {
409 pub import_id: u32,
410 pub value: u64,
411}
412
413pub enum FlipToExtraInfo {
414 #[cfg(feature = "vulkan_display")]
415 Vulkan { old_layout: i32, new_layout: i32 },
416}
417
418pub struct GpuDisplay {
423 next_id: u32,
424 event_devices: BTreeMap<u32, EventDevice>,
425 surfaces: BTreeMap<u32, Box<dyn GpuDisplaySurface>>,
426 wait_ctx: WaitContext<DisplayEventToken>,
427 inner: Box<dyn SysDisplayT>,
434}
435
436impl GpuDisplay {
437 pub fn open_x(display_name: Option<&str>) -> GpuDisplayResult<GpuDisplay> {
439 let _ = display_name;
440 #[cfg(feature = "x")]
441 {
442 let display = gpu_display_x::DisplayX::open_display(display_name)?;
443
444 let wait_ctx = WaitContext::new()?;
445 wait_ctx.add(&display, DisplayEventToken::Display)?;
446
447 Ok(GpuDisplay {
448 inner: Box::new(display),
449 next_id: 1,
450 event_devices: Default::default(),
451 surfaces: Default::default(),
452 wait_ctx,
453 })
454 }
455 #[cfg(not(feature = "x"))]
456 Err(GpuDisplayError::Unsupported)
457 }
458
459 pub fn open_android(service_name: &str) -> GpuDisplayResult<GpuDisplay> {
460 let _ = service_name;
461 #[cfg(feature = "android_display")]
462 {
463 let display = gpu_display_android::DisplayAndroid::new(service_name)?;
464
465 let wait_ctx = WaitContext::new()?;
466 wait_ctx.add(&display, DisplayEventToken::Display)?;
467
468 Ok(GpuDisplay {
469 inner: Box::new(display),
470 next_id: 1,
471 event_devices: Default::default(),
472 surfaces: Default::default(),
473 wait_ctx,
474 })
475 }
476 #[cfg(not(feature = "android_display"))]
477 Err(GpuDisplayError::Unsupported)
478 }
479
480 pub fn open_stub() -> GpuDisplayResult<GpuDisplay> {
481 let display = gpu_display_stub::DisplayStub::new()?;
482 let wait_ctx = WaitContext::new()?;
483 wait_ctx.add(&display, DisplayEventToken::Display)?;
484
485 Ok(GpuDisplay {
486 inner: Box::new(display),
487 next_id: 1,
488 event_devices: Default::default(),
489 surfaces: Default::default(),
490 wait_ctx,
491 })
492 }
493
494 pub fn take_event_devices(&mut self) -> Vec<EventDevice> {
499 std::mem::take(&mut self.event_devices)
500 .into_values()
501 .collect()
502 }
503
504 fn dispatch_display_events(&mut self) -> GpuDisplayResult<()> {
505 self.inner.flush();
506 while self.inner.pending_events() {
507 let surface_descriptor = self.inner.next_event()?;
508
509 for surface in self.surfaces.values_mut() {
510 if surface_descriptor != surface.surface_descriptor() {
511 continue;
512 }
513
514 if let Some(gpu_display_events) = self.inner.handle_next_event(surface) {
515 for event_device in self.event_devices.values_mut() {
516 if event_device.kind() != gpu_display_events.device_type {
517 continue;
518 }
519
520 event_device.send_report(gpu_display_events.events.iter().cloned())?;
521 }
522 }
523 }
524 }
525
526 Ok(())
527 }
528
529 pub fn dispatch_events(&mut self) -> GpuDisplayResult<()> {
532 let wait_events = self.wait_ctx.wait_timeout(Duration::default())?;
533
534 if let Some(wait_event) = wait_events.iter().find(|e| e.is_hungup) {
535 base::error!(
536 "Display signaled with a hungup event for token {:?}",
537 wait_event.token
538 );
539 self.wait_ctx = WaitContext::new().unwrap();
540 return GpuDisplayResult::Err(GpuDisplayError::ConnectionBroken);
541 }
542
543 for wait_event in wait_events.iter().filter(|e| e.is_writable) {
544 if let DisplayEventToken::EventDevice { event_device_id } = wait_event.token {
545 if let Some(event_device) = self.event_devices.get_mut(&event_device_id) {
546 if !event_device.flush_buffered_events()? {
547 continue;
548 }
549 self.wait_ctx.modify(
550 event_device,
551 EventType::Read,
552 DisplayEventToken::EventDevice { event_device_id },
553 )?;
554 }
555 }
556 }
557
558 for wait_event in wait_events.iter().filter(|e| e.is_readable) {
559 match wait_event.token {
560 DisplayEventToken::Display => self.dispatch_display_events()?,
561 DisplayEventToken::EventDevice { event_device_id } => {
562 self.handle_event_device(event_device_id)
563 }
564 }
565 }
566
567 Ok(())
568 }
569
570 pub fn create_surface(
573 &mut self,
574 parent_surface_id: Option<u32>,
575 scanout_id: Option<u32>,
576 display_params: &DisplayParameters,
577 surf_type: SurfaceType,
578 ) -> GpuDisplayResult<u32> {
579 if let Some(parent_id) = parent_surface_id {
580 if !self.surfaces.contains_key(&parent_id) {
581 return Err(GpuDisplayError::InvalidSurfaceId);
582 }
583 }
584
585 let new_surface_id = self.next_id;
586 let new_surface = self.inner.create_surface(
587 parent_surface_id,
588 new_surface_id,
589 scanout_id,
590 display_params,
591 surf_type,
592 )?;
593
594 self.next_id += 1;
595 self.surfaces.insert(new_surface_id, new_surface);
596 Ok(new_surface_id)
597 }
598
599 pub fn release_surface(&mut self, surface_id: u32) {
601 self.surfaces.remove(&surface_id);
602 self.inner.release_surface(surface_id);
603 }
604
605 pub fn framebuffer(&mut self, surface_id: u32) -> Option<GpuDisplayFramebuffer> {
607 let surface = self.surfaces.get_mut(&surface_id)?;
608 surface.framebuffer()
609 }
610
611 pub fn framebuffer_region(
613 &mut self,
614 surface_id: u32,
615 x: u32,
616 y: u32,
617 width: u32,
618 height: u32,
619 ) -> Option<GpuDisplayFramebuffer> {
620 let framebuffer = self.framebuffer(surface_id)?;
621 framebuffer.sub_region(x, y, width, height)
622 }
623
624 pub fn next_buffer_in_use(&self, surface_id: u32) -> bool {
630 self.surfaces
631 .get(&surface_id)
632 .map(|s| s.next_buffer_in_use())
633 .unwrap_or(false)
634 }
635
636 pub fn flip(&mut self, surface_id: u32) {
639 if let Some(surface) = self.surfaces.get_mut(&surface_id) {
640 surface.flip()
641 }
642 }
643
644 pub fn close_requested(&self, surface_id: u32) -> bool {
647 self.surfaces
648 .get(&surface_id)
649 .map(|s| s.close_requested())
650 .unwrap_or(true)
651 }
652
653 pub fn import_resource(
656 &mut self,
657 surface_id: u32,
658 external_display_resource: DisplayExternalResourceImport,
659 ) -> anyhow::Result<u32> {
660 let import_id = self.next_id;
661
662 self.inner
663 .import_resource(import_id, surface_id, external_display_resource)?;
664
665 self.next_id += 1;
666 Ok(import_id)
667 }
668
669 pub fn release_import(&mut self, import_id: u32, surface_id: u32) {
671 self.inner.release_import(import_id, surface_id);
672 }
673
674 pub fn commit(&mut self, surface_id: u32) -> GpuDisplayResult<()> {
676 let surface = self
677 .surfaces
678 .get_mut(&surface_id)
679 .ok_or(GpuDisplayError::InvalidSurfaceId)?;
680
681 surface.commit()
682 }
683
684 pub fn flip_to(
687 &mut self,
688 surface_id: u32,
689 import_id: u32,
690 acquire_timepoint: Option<SemaphoreTimepoint>,
691 release_timepoint: Option<SemaphoreTimepoint>,
692 extra_info: Option<FlipToExtraInfo>,
693 ) -> anyhow::Result<Waitable> {
694 let surface = self
695 .surfaces
696 .get_mut(&surface_id)
697 .ok_or(GpuDisplayError::InvalidSurfaceId)?;
698
699 surface
700 .flip_to(import_id, acquire_timepoint, release_timepoint, extra_info)
701 .context("failed in flip on GpuDisplaySurface")
702 }
703
704 pub fn set_mouse_mode(
706 &mut self,
707 surface_id: u32,
708 mouse_mode: MouseMode,
709 ) -> GpuDisplayResult<()> {
710 let surface = self
711 .surfaces
712 .get_mut(&surface_id)
713 .ok_or(GpuDisplayError::InvalidSurfaceId)?;
714
715 surface.set_mouse_mode(mouse_mode);
716 Ok(())
717 }
718
719 pub fn set_position(&mut self, surface_id: u32, x: u32, y: u32) -> GpuDisplayResult<()> {
723 let surface = self
724 .surfaces
725 .get_mut(&surface_id)
726 .ok_or(GpuDisplayError::InvalidSurfaceId)?;
727
728 surface.set_position(x, y);
729 Ok(())
730 }
731}