use drmkit_planes::LayerId;
use drmkit_sync::SyncFence;
use crate::source::AcquiredBuffer;
#[derive(Debug)]
#[non_exhaustive]
pub struct Acquisition {
pub layer: LayerId,
pub buffer: AcquiredBuffer,
pub release_fence: Option<SyncFence>,
}
impl Acquisition {
#[must_use]
pub const fn new(layer: LayerId, buffer: AcquiredBuffer) -> Self {
Self {
layer,
buffer,
release_fence: None,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[non_exhaustive]
pub enum ReleaseReason {
Retired,
CommitFailed,
TestOnly,
Drained,
}
#[derive(Debug)]
#[non_exhaustive]
pub struct Released {
pub acquisitions: Vec<Acquisition>,
pub reason: ReleaseReason,
}
impl Released {
#[must_use]
pub fn is_empty(&self) -> bool {
self.acquisitions.is_empty()
}
#[must_use]
pub fn len(&self) -> usize {
self.acquisitions.len()
}
}
#[derive(Debug, Default)]
pub struct ReleaseQueue {
previous: Vec<Acquisition>,
two_ago: Vec<Acquisition>,
}
impl ReleaseQueue {
#[must_use]
pub const fn new() -> Self {
Self {
previous: Vec::new(),
two_ago: Vec::new(),
}
}
#[must_use]
pub fn in_flight(&self) -> usize {
self.previous.len() + self.two_ago.len()
}
#[must_use]
pub fn is_empty(&self) -> bool {
self.previous.is_empty() && self.two_ago.is_empty()
}
pub fn commit_succeeded<F>(
&mut self,
current: Vec<Acquisition>,
release_fence: Option<&SyncFence>,
mut wants_fence: F,
) -> Released
where
F: FnMut(LayerId) -> bool,
{
if let Some(fence) = release_fence {
for acquisition in &mut self.previous {
if wants_fence(acquisition.layer)
&& let Some(fd) = fence.as_fd()
&& let Ok(duplicate) = SyncFence::import(fd)
{
acquisition.release_fence = Some(duplicate);
}
}
}
let retired = std::mem::take(&mut self.two_ago);
self.two_ago = std::mem::take(&mut self.previous);
self.previous = current;
Released {
acquisitions: retired,
reason: ReleaseReason::Retired,
}
}
pub fn release_displaced(&mut self) -> Released {
Released {
acquisitions: std::mem::take(&mut self.two_ago),
reason: ReleaseReason::Retired,
}
}
pub fn commit_failed(&mut self, current: Vec<Acquisition>) -> Released {
Released {
acquisitions: current,
reason: ReleaseReason::CommitFailed,
}
}
pub fn test_committed(&mut self, current: Vec<Acquisition>) -> Released {
Released {
acquisitions: current,
reason: ReleaseReason::TestOnly,
}
}
pub fn drain(&mut self) -> Released {
let mut acquisitions = std::mem::take(&mut self.two_ago);
acquisitions.append(&mut self.previous);
Released {
acquisitions,
reason: ReleaseReason::Drained,
}
}
}
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
pub struct ScenePendingFlip {
armed: bool,
}
impl ScenePendingFlip {
#[must_use]
pub const fn new() -> Self {
Self { armed: false }
}
pub const fn arm(&mut self) {
self.armed = true;
}
pub const fn landed(&mut self) {
self.armed = false;
}
#[must_use]
pub const fn is_armed(&self) -> bool {
self.armed
}
}