commit_timeline: wait for implicit sync dmabufs
This commit is contained in:
parent
c22af6efb7
commit
04343c96d6
7 changed files with 199 additions and 15 deletions
|
|
@ -23,8 +23,8 @@ use {
|
|||
drm_feedback::DrmFeedback,
|
||||
fixed::Fixed,
|
||||
gfx_api::{
|
||||
AcquireSync, AsyncShmGfxTexture, BufferResv, BufferResvUser, GfxError, ReleaseSync,
|
||||
SampleRect, SyncFile,
|
||||
AsyncShmGfxTexture, BufferResv, BufferResvUser, GfxError, ReleaseSync, SampleRect,
|
||||
SyncFile,
|
||||
},
|
||||
ifs::{
|
||||
wl_buffer::WlBuffer,
|
||||
|
|
@ -190,7 +190,6 @@ struct SurfaceBufferExplicitRelease {
|
|||
pub struct SurfaceBuffer {
|
||||
pub buffer: Rc<WlBuffer>,
|
||||
sync_files: SmallMap<BufferResvUser, SyncFile, 1>,
|
||||
pub sync: AcquireSync,
|
||||
pub release_sync: ReleaseSync,
|
||||
release: Option<SurfaceBufferExplicitRelease>,
|
||||
}
|
||||
|
|
@ -1093,9 +1092,9 @@ impl WlSurface {
|
|||
self.reset_shm_textures();
|
||||
}
|
||||
buffer.update_texture_or_log(self, false);
|
||||
let (sync, release_sync) = match pending.explicit_sync {
|
||||
false => (AcquireSync::Implicit, ReleaseSync::Implicit),
|
||||
true => (AcquireSync::Unnecessary, ReleaseSync::Explicit),
|
||||
let release_sync = match pending.explicit_sync {
|
||||
false => ReleaseSync::Implicit,
|
||||
true => ReleaseSync::Explicit,
|
||||
};
|
||||
let release = pending
|
||||
.release_point
|
||||
|
|
@ -1104,7 +1103,6 @@ impl WlSurface {
|
|||
let surface_buffer = SurfaceBuffer {
|
||||
buffer,
|
||||
sync_files: Default::default(),
|
||||
sync,
|
||||
release_sync,
|
||||
release,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -5,12 +5,14 @@ use {
|
|||
wl_buffer::WlBufferStorage,
|
||||
wl_surface::{PendingState, WlSurface, WlSurfaceError},
|
||||
},
|
||||
io_uring::{IoUring, IoUringError, PendingPoll, PollCallback},
|
||||
utils::{
|
||||
clonecell::CloneCell,
|
||||
copyhashmap::CopyHashMap,
|
||||
hash_map_ext::HashMapExt,
|
||||
linkedlist::{LinkedList, LinkedNode, NodeRef},
|
||||
numcell::NumCell,
|
||||
oserror::OsError,
|
||||
},
|
||||
video::drm::{
|
||||
sync_obj::{SyncObj, SyncObjPoint},
|
||||
|
|
@ -28,6 +30,7 @@ use {
|
|||
slice,
|
||||
},
|
||||
thiserror::Error,
|
||||
uapi::{c::c_short, OwnedFd},
|
||||
};
|
||||
|
||||
const MAX_TIMELINE_DEPTH: usize = 256;
|
||||
|
|
@ -37,6 +40,7 @@ linear_ids!(CommitTimelineIds, CommitTimelineId, u64);
|
|||
pub struct CommitTimelines {
|
||||
next_id: CommitTimelineIds,
|
||||
wfs: Rc<WaitForSyncObj>,
|
||||
ring: Rc<IoUring>,
|
||||
depth: NumCell<usize>,
|
||||
gc: CopyHashMap<CommitTimelineId, LinkedList<Entry>>,
|
||||
}
|
||||
|
|
@ -83,15 +87,20 @@ pub enum CommitTimelineError {
|
|||
Depth,
|
||||
#[error("Could not upload a shm texture")]
|
||||
ShmUpload(#[source] GfxError),
|
||||
#[error("Could not register an implicit-sync wait")]
|
||||
RegisterImplicitPoll(#[source] IoUringError),
|
||||
#[error("Could not wait for a dmabuf to become idle")]
|
||||
PollDmabuf(#[source] OsError),
|
||||
}
|
||||
|
||||
impl CommitTimelines {
|
||||
pub fn new(wfs: &Rc<WaitForSyncObj>) -> Self {
|
||||
pub fn new(wfs: &Rc<WaitForSyncObj>, ring: &Rc<IoUring>) -> Self {
|
||||
Self {
|
||||
next_id: Default::default(),
|
||||
depth: NumCell::new(0),
|
||||
wfs: wfs.clone(),
|
||||
gc: Default::default(),
|
||||
ring: ring.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -127,6 +136,7 @@ fn break_loops(list: &LinkedList<Entry>) {
|
|||
if let EntryKind::Commit(c) = &entry.kind {
|
||||
c.wait_handles.take();
|
||||
*c.shm_upload.borrow_mut() = ShmUploadState::None;
|
||||
c.pending_polls.take();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -153,8 +163,15 @@ impl CommitTimeline {
|
|||
) -> Result<(), CommitTimelineError> {
|
||||
let mut points = SmallVec::new();
|
||||
let mut pending_uploads = 0;
|
||||
collect_commit_data(pending, &mut points, &mut pending_uploads);
|
||||
let has_dependencies = points.is_not_empty() || pending_uploads > 0;
|
||||
let mut implicit_dmabufs = SmallVec::new();
|
||||
collect_commit_data(
|
||||
pending,
|
||||
&mut points,
|
||||
&mut pending_uploads,
|
||||
&mut implicit_dmabufs,
|
||||
);
|
||||
let has_dependencies =
|
||||
points.is_not_empty() || pending_uploads > 0 || implicit_dmabufs.is_not_empty();
|
||||
if !has_dependencies && self.own_timeline.entries.is_empty() {
|
||||
return surface
|
||||
.apply_state(pending)
|
||||
|
|
@ -174,6 +191,8 @@ impl CommitTimeline {
|
|||
wait_handles: Cell::new(Default::default()),
|
||||
pending_uploads: NumCell::new(pending_uploads),
|
||||
shm_upload: RefCell::new(ShmUploadState::None),
|
||||
num_pending_polls: NumCell::new(implicit_dmabufs.len()),
|
||||
pending_polls: Cell::new(Default::default()),
|
||||
}),
|
||||
);
|
||||
let mut needs_flush = false;
|
||||
|
|
@ -198,6 +217,18 @@ impl CommitTimeline {
|
|||
*commit.shm_upload.borrow_mut() = ShmUploadState::Todo(noderef.clone());
|
||||
needs_flush = true;
|
||||
}
|
||||
if implicit_dmabufs.is_not_empty() {
|
||||
let mut pending_polls = SmallVec::new();
|
||||
for fd in implicit_dmabufs {
|
||||
let handle = self
|
||||
.shared
|
||||
.ring
|
||||
.readable_external(&fd, noderef.clone())
|
||||
.map_err(CommitTimelineError::RegisterImplicitPoll)?;
|
||||
pending_polls.push(handle);
|
||||
}
|
||||
commit.pending_polls.set(pending_polls);
|
||||
}
|
||||
}
|
||||
if needs_flush && noderef.prev().is_none() {
|
||||
flush_from(noderef.clone()).map_err(CommitTimelineError::DelayedCommit)?;
|
||||
|
|
@ -246,6 +277,23 @@ impl AsyncShmGfxTextureCallback for NodeRef<Entry> {
|
|||
}
|
||||
}
|
||||
|
||||
impl PollCallback for NodeRef<Entry> {
|
||||
fn completed(self: Rc<Self>, res: Result<c_short, OsError>) {
|
||||
let EntryKind::Commit(commit) = &self.kind else {
|
||||
unreachable!();
|
||||
};
|
||||
if let Err(e) = res {
|
||||
commit
|
||||
.surface
|
||||
.client
|
||||
.error(CommitTimelineError::PollDmabuf(e));
|
||||
return;
|
||||
}
|
||||
commit.num_pending_polls.fetch_sub(1);
|
||||
flush_commit(&self, commit);
|
||||
}
|
||||
}
|
||||
|
||||
struct Entry {
|
||||
link: Cell<Option<LinkedNode<Entry>>>,
|
||||
shared: Rc<CommitTimelines>,
|
||||
|
|
@ -272,6 +320,8 @@ struct Commit {
|
|||
wait_handles: Cell<SmallVec<[WaitForSyncObjHandle; 1]>>,
|
||||
pending_uploads: NumCell<usize>,
|
||||
shm_upload: RefCell<ShmUploadState>,
|
||||
num_pending_polls: NumCell<usize>,
|
||||
pending_polls: Cell<SmallVec<[PendingPoll; 1]>>,
|
||||
}
|
||||
|
||||
fn flush_from(mut point: NodeRef<Entry>) -> Result<(), WlSurfaceError> {
|
||||
|
|
@ -304,6 +354,9 @@ impl NodeRef<Entry> {
|
|||
has_unmet_dependencies = true;
|
||||
}
|
||||
}
|
||||
if c.num_pending_polls.get() > 0 {
|
||||
has_unmet_dependencies = true;
|
||||
}
|
||||
if has_unmet_dependencies {
|
||||
return Ok(false);
|
||||
}
|
||||
|
|
@ -417,18 +470,26 @@ fn collect_commit_data(
|
|||
pending: &mut PendingState,
|
||||
acquire_points: &mut SmallVec<[Point; 1]>,
|
||||
shm_uploads: &mut usize,
|
||||
implicit_dmabufs: &mut SmallVec<[Rc<OwnedFd>; 1]>,
|
||||
) {
|
||||
if let Some(Some(buffer)) = &pending.buffer {
|
||||
if buffer.is_shm() {
|
||||
*shm_uploads += 1;
|
||||
}
|
||||
if !pending.explicit_sync {
|
||||
if let Some(dmabuf) = &buffer.dmabuf {
|
||||
for plane in &dmabuf.planes {
|
||||
implicit_dmabufs.push(plane.fd.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if let Some(point) = pending.acquire_point.take() {
|
||||
acquire_points.push(point);
|
||||
}
|
||||
for ss in pending.subsurfaces.values_mut() {
|
||||
if let Some(state) = &mut ss.pending.state {
|
||||
collect_commit_data(state, acquire_points, shm_uploads);
|
||||
collect_commit_data(state, acquire_points, shm_uploads, implicit_dmabufs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue