Files
RedBear-OS/local/recipes/gpu/redox-drm/source/src/drivers/intel/syncobj.rs
T
vasilito aa3257c6eb intel: P0 — DP retrain at modeset, sync_file fd export/import
display.rs: DP link retraining at set_mode time
  Before enabling DDI_BUF_CTL, retrain DP link for the active port
  Uses display's own dp_aux vector for DPCD communication
  Fixes link recovery after mode changes

syncobj.rs: sync_file fd infrastructure
  export_sync_file(): generate fd token, map syncobj → fd
  import_sync_file(): resolve fd token → syncobj handle
  close_sync_file(): remove fd from table

driver.rs: GpuDriver trait methods for sync_file
  syncobj_export_fd() / syncobj_import_fd() with default Unsupported

mod.rs: IntelDriver implementation delegates to SyncobjManager

scheme.rs: DRM_IOCTL_REDOX_SYNCOBJ_HANDLE_TO_FD (0x73)
  DRM_IOCTL_REDOX_SYNCOBJ_FD_TO_HANDLE (0x74)
  Wire types with proper #[repr(C)] Copy+Clone attributes
2026-06-01 23:42:19 +03:00

189 lines
5.8 KiB
Rust

use std::collections::BTreeMap;
use std::sync::Arc;
use log::debug;
use super::fence::FenceTimeline;
use crate::driver::{DriverError, Result, SyncobjHandle};
const DRM_SYNCOBJ_CREATE_SIGNALED: u32 = 1 << 0;
pub struct SyncobjObject {
pub handle: SyncobjHandle,
pub timeline: Arc<FenceTimeline>,
pub point: u64,
pub signaled: bool,
}
pub struct SyncobjManager {
objects: BTreeMap<SyncobjHandle, SyncobjObject>,
next_handle: SyncobjHandle,
global_timeline: Arc<FenceTimeline>,
fd_table: BTreeMap<i32, SyncobjHandle>,
next_fd: i32,
}
impl SyncobjManager {
pub fn new() -> Self {
Self {
objects: BTreeMap::new(),
next_handle: 1,
global_timeline: Arc::new(FenceTimeline::new()),
fd_table: BTreeMap::new(),
next_fd: 10,
}
}
pub fn timeline(&self) -> &Arc<FenceTimeline> {
&self.global_timeline
}
pub fn create(&mut self, flags: u32) -> Result<SyncobjHandle> {
let handle = self.next_handle;
self.next_handle = self.next_handle.wrapping_add(1);
let signaled = flags & DRM_SYNCOBJ_CREATE_SIGNALED != 0;
let point = if signaled {
self.global_timeline.allocate_seqno()
} else {
0
};
self.objects.insert(handle, SyncobjObject {
handle,
timeline: self.global_timeline.clone(),
point,
signaled,
});
debug!("redox-drm-intel: syncobj {} created (signaled={})", handle, signaled);
Ok(handle)
}
pub fn destroy(&mut self, handle: SyncobjHandle) -> Result<()> {
self.objects.remove(&handle).map(|_| ()).ok_or_else(|| {
DriverError::NotFound(format!("syncobj handle {} not found", handle))
})
}
pub fn signal(&mut self, handles: &[SyncobjHandle]) -> Result<()> {
let point = self.global_timeline.allocate_seqno();
for &handle in handles {
if let Some(obj) = self.objects.get_mut(&handle) {
obj.point = point;
obj.signaled = false;
}
}
self.global_timeline.signal(point);
debug!("redox-drm-intel: syncobj signal — {} handle(s) at point {}", handles.len(), point);
Ok(())
}
pub fn reset(&mut self, handles: &[SyncobjHandle]) -> Result<()> {
for &handle in handles {
if let Some(obj) = self.objects.get_mut(&handle) {
obj.point = 0;
obj.signaled = false;
}
}
Ok(())
}
pub fn wait(&self, handles: &[SyncobjHandle], timeout_ns: i64) -> Result<u32> {
let timeout_ms = if timeout_ns < 0 {
u64::MAX
} else {
(timeout_ns as u64) / 1_000_000
};
for (idx, &handle) in handles.iter().enumerate() {
let obj = self.objects.get(&handle).ok_or_else(|| {
DriverError::NotFound(format!("syncobj handle {} not found", handle))
})?;
if obj.signaled || obj.point == 0 {
return Ok(idx as u32);
}
if self.global_timeline.is_completed(obj.point) {
return Ok(idx as u32);
}
if timeout_ms > 0 {
match self.global_timeline.wait(obj.point, timeout_ms) {
Ok(()) => return Ok(idx as u32),
Err(_) => continue,
}
}
}
if timeout_ns == 0 {
return Ok(0);
}
Err(DriverError::Initialization(format!(
"syncobj_wait timeout: {} handles, {} ns",
handles.len(), timeout_ns
)))
}
pub fn query(&self, handle: SyncobjHandle) -> Result<bool> {
let obj = self.objects.get(&handle).ok_or_else(|| {
DriverError::NotFound(format!("syncobj handle {} not found", handle))
})?;
if obj.signaled || obj.point == 0 {
return Ok(true);
}
Ok(self.global_timeline.is_completed(obj.point))
}
pub fn fd_to_handle(&mut self, fd: i32) -> Result<SyncobjHandle> {
self.fd_table.get(&fd).copied().ok_or_else(|| {
DriverError::NotFound(format!("syncobj fd {} not found in local table", fd))
})
}
pub fn handle_to_fd(&mut self, handle: SyncobjHandle) -> Result<i32> {
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);
Ok(fd)
}
pub fn hardware_signal_completion(&self, completion_addr: u64, seqno: u64) {
self.global_timeline.signal(seqno);
debug!("redox-drm-intel: hardware fence completion at {:#010x} seqno {}", completion_addr, seqno);
}
pub fn is_handle_valid(&self, handle: SyncobjHandle) -> bool {
self.objects.contains_key(&handle)
}
pub fn export_sync_file(&mut self, handle: SyncobjHandle) -> Result<i32> {
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<SyncobjHandle> {
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);
}
}