Skip to content

Conversation

cmeissl
Copy link
Collaborator

@cmeissl cmeissl commented Apr 19, 2025

This PR extends the existing Blocker API with a BlockerKind. Allowing to put blockers into two groups, Immediate and Delayed. Blockers with BlockerKind::Delayed will only be evaluated once all Immediate have been cleared.
After all Immediate blockers have been cleared all Blockers will be notified, allowing delayed blockers to make a decision based on that.
All blockers still need to be cleared for the transaction to be unblocked.

Additionally the PR adds a reference implementation of a delayed blocker, SurfaceBarrier.

One example for this is implementing animation transactions spanning multiple otherwise unrelated surfaces.
While this can be implemented without the SurfaceBarrier, it might help to enhance synchronization when some other blockers further delay the buffer.

A compositor could place a Immediate blocker, like for example a simple Barrier, on each surface participating in the animation transaction and also register it in a SurfaceBarrier with the same scope as the animation transaction.
Once the Immediate blocker representing the transaction is cleared, the blocker in the SurfaceBarrier will try to resolve and ping the compositor once it completed.

cc @YaLTeR

@cmeissl cmeissl force-pushed the feature/delayed_blocker branch 2 times, most recently from d125eef to 2c2ec49 Compare April 19, 2025 14:41
Copy link
Contributor

@YaLTeR YaLTeR left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only a cursory glance for now; will have to see how it looks in niri to give proper feedback.

ready_transactions.push(self.transactions.remove(i));
let transaction = &mut self.transactions[i];

transaction.notify_blockers();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Won't this get called over and over after the immediate blockers are done but before the delayed blockers are done?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Depends on the impl of the delayed blocker and the precense of other delayed blockers. It could unblock from within notify and if it is the last one it would not be called again. But yes, it could get notified multiple times until the transaction completed. Maybe something worth documenting on the notify function. Just FYI, I also evaluated a design based on a callback which could place additional blockers but that had its own shortcomings.

{
let signaled = self.ready.swap(true, std::sync::atomic::Ordering::Acquire);
if !signaled {
self.ping.ping();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IIRC in niri I didn't use the Ping source for the actual ready notification because it would arrive only on the next event loop iteration. I'm not sure if this is a problem here.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interesting. I am also not sure this is a problem in this case. We could use a channel instead maybe?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants