diff --git a/local/recipes/gpu/redox-drm/source/src/driver.rs b/local/recipes/gpu/redox-drm/source/src/driver.rs index b527fae9bb..fe606ad8da 100644 --- a/local/recipes/gpu/redox-drm/source/src/driver.rs +++ b/local/recipes/gpu/redox-drm/source/src/driver.rs @@ -186,6 +186,14 @@ pub trait GpuDriver: Send + Sync { Err(DriverError::Unsupported("syncobj not supported by this backend")) } + fn syncobj_export_fd(&self, _handle: SyncobjHandle) -> Result { + Err(DriverError::Unsupported("syncobj fd export not supported")) + } + + fn syncobj_import_fd(&self, _fd: i32) -> Result { + Err(DriverError::Unsupported("syncobj fd import not supported")) + } + fn redox_private_cs_submit( &self, _submit: &RedoxPrivateCsSubmit, diff --git a/local/recipes/gpu/redox-drm/source/src/drivers/intel/display.rs b/local/recipes/gpu/redox-drm/source/src/drivers/intel/display.rs index d3476b385b..7d66876417 100644 --- a/local/recipes/gpu/redox-drm/source/src/drivers/intel/display.rs +++ b/local/recipes/gpu/redox-drm/source/src/drivers/intel/display.rs @@ -226,6 +226,14 @@ impl IntelDisplay { pub fn set_mode(&self, pipe: &DisplayPipe, mode: &ModeInfo) -> Result<()> { let index = usize::from(pipe.index); + + if let Some(port) = pipe.port { + if (port as usize) < self.dp_aux.len() { + debug!("redox-drm-intel: retraining DP link port {} for {}x{}@{}", + port, mode.hdisplay, mode.vdisplay, mode.vrefresh); + let _ = super::dp_link::train_dp_link(&self.mmio, &self.dp_aux[port as usize], port); + } + } self.write32( self.regs.htotal(index as u8), pack_pair(mode.htotal, mode.hdisplay), diff --git a/local/recipes/gpu/redox-drm/source/src/drivers/intel/mod.rs b/local/recipes/gpu/redox-drm/source/src/drivers/intel/mod.rs index 60611e26ea..cf0e6a4268 100644 --- a/local/recipes/gpu/redox-drm/source/src/drivers/intel/mod.rs +++ b/local/recipes/gpu/redox-drm/source/src/drivers/intel/mod.rs @@ -1193,6 +1193,18 @@ impl GpuDriver for IntelDriver { Err(e) => Err(e), } } + + fn syncobj_export_fd(&self, handle: SyncobjHandle) -> Result { + let mut mgr = self.syncobj_mgr.lock() + .map_err(|_| DriverError::Initialization("Intel syncobj state poisoned".into()))?; + mgr.export_sync_file(handle) + } + + fn syncobj_import_fd(&self, fd: i32) -> Result { + let mgr = self.syncobj_mgr.lock() + .map_err(|_| DriverError::Initialization("Intel syncobj state poisoned".into()))?; + mgr.import_sync_file(fd) + } } fn detect_display_topology(display: &IntelDisplay) -> Result<(Vec, Vec)> { diff --git a/local/recipes/gpu/redox-drm/source/src/drivers/intel/syncobj.rs b/local/recipes/gpu/redox-drm/source/src/drivers/intel/syncobj.rs index e60d79c83e..73d9a0bb3c 100644 --- a/local/recipes/gpu/redox-drm/source/src/drivers/intel/syncobj.rs +++ b/local/recipes/gpu/redox-drm/source/src/drivers/intel/syncobj.rs @@ -163,4 +163,26 @@ impl SyncobjManager { pub fn is_handle_valid(&self, handle: SyncobjHandle) -> bool { self.objects.contains_key(&handle) } + + pub fn export_sync_file(&mut self, handle: SyncobjHandle) -> Result { + if !self.objects.contains_key(&handle) { + return Err(DriverError::NotFound(format!("syncobj handle {} not found", handle))); + } + let fd = self.next_fd; + self.next_fd = self.next_fd.wrapping_add(1); + self.fd_table.insert(fd, handle); + debug!("redox-drm-intel: sync_file fd {} exported for syncobj {}", fd, handle); + Ok(fd) + } + + pub fn import_sync_file(&self, fd: i32) -> Result { + self.fd_table.get(&fd).copied().ok_or_else(|| { + DriverError::NotFound(format!("sync_file fd {} not found", fd)) + }) + } + + pub fn close_sync_file(&mut self, fd: i32) { + self.fd_table.remove(&fd); + debug!("redox-drm-intel: sync_file fd {} closed", fd); + } } diff --git a/local/recipes/gpu/redox-drm/source/src/scheme.rs b/local/recipes/gpu/redox-drm/source/src/scheme.rs index 6601d0fb05..019e7d910d 100644 --- a/local/recipes/gpu/redox-drm/source/src/scheme.rs +++ b/local/recipes/gpu/redox-drm/source/src/scheme.rs @@ -73,6 +73,8 @@ const DRM_IOCTL_MODE_ATOMIC: usize = DRM_IOCTL_BASE + 0x3C; const DRM_IOCTL_REDOX_SYNCOBJ_CREATE: usize = DRM_IOCTL_BASE + 0x70; const DRM_IOCTL_REDOX_SYNCOBJ_DESTROY: usize = DRM_IOCTL_BASE + 0x71; const DRM_IOCTL_REDOX_SYNCOBJ_WAIT: usize = DRM_IOCTL_BASE + 0x72; +const DRM_IOCTL_REDOX_SYNCOBJ_HANDLE_TO_FD: usize = DRM_IOCTL_BASE + 0x73; +const DRM_IOCTL_REDOX_SYNCOBJ_FD_TO_HANDLE: usize = DRM_IOCTL_BASE + 0x74; const DRM_MODE_ATOMIC_TEST_ONLY: u32 = 0x0100; const DRM_MODE_ATOMIC_NONBLOCK: u32 = 0x0200; const DRM_MODE_PAGE_FLIP_EVENT: u32 = 0x01; @@ -598,8 +600,27 @@ struct RedoxSyncobjWaitWire { #[derive(Clone, Copy, Debug, Default)] struct RedoxSyncobjWaitResultWire { completed: u32, + _pad: [u8; 4], } +#[derive(Copy, Clone)] +#[repr(C)] +struct RedoxSyncobjHandleToFdWire { + handle: u32, + flags: u32, + fd: i32, + _pad: [u8; 4], +} + +#[derive(Copy, Clone)] +#[repr(C)] +struct RedoxSyncobjFdToHandleWire { + fd: i32, + handle: u32, + _pad: [u8; 4], +} + + // ---- Internal handle types ---- #[derive(Clone, Debug)] @@ -1471,6 +1492,8 @@ impl DrmScheme { DRM_IOCTL_REDOX_SYNCOBJ_CREATE => "SYNCOBJ_CREATE", DRM_IOCTL_REDOX_SYNCOBJ_DESTROY => "SYNCOBJ_DESTROY", DRM_IOCTL_REDOX_SYNCOBJ_WAIT => "SYNCOBJ_WAIT", + DRM_IOCTL_REDOX_SYNCOBJ_HANDLE_TO_FD => "SYNCOBJ_HANDLE_TO_FD", + DRM_IOCTL_REDOX_SYNCOBJ_FD_TO_HANDLE => "SYNCOBJ_FD_TO_HANDLE", _ => "UNKNOWN", }; log::info!( @@ -1656,10 +1679,29 @@ impl DrmScheme { .map_err(driver_to_syscall)?; let resp = RedoxSyncobjWaitResultWire { completed: if completed { 1 } else { 0 }, + _pad: [0u8; 4], }; bytes_of(&resp) } + DRM_IOCTL_REDOX_SYNCOBJ_HANDLE_TO_FD => { + let req = decode_wire::(payload)?; + let fd = self.driver.syncobj_export_fd(req.handle) + .map_err(driver_to_syscall)?; + let mut resp = req; + resp.fd = fd; + bytes_of(&resp) + } + + DRM_IOCTL_REDOX_SYNCOBJ_FD_TO_HANDLE => { + let req = decode_wire::(payload)?; + let handle = self.driver.syncobj_import_fd(req.fd) + .map_err(driver_to_syscall)?; + let mut resp = req; + resp.handle = handle; + bytes_of(&resp) + } + DRM_IOCTL_MODE_CREATE_DUMB => { let mut req = decode_wire::(payload)?; info!(