From 1bc857b12c434b7255119de009a50237856a90b2 Mon Sep 17 00:00:00 2001 From: UjinT34 <41110182+UjinT34@users.noreply.github.com> Date: Wed, 4 Feb 2026 03:27:48 +0300 Subject: fifo: miscellaneous fifo fixes (#13136) * LOGM: clang-tidy fix * fix fifo state and scheduling * disable fifo_pending_workaround by default * fix tearing * fix "empty" commit skipping --- src/protocols/Fifo.cpp | 90 +++++++++++++++++++++++++++++--------------------- 1 file changed, 53 insertions(+), 37 deletions(-) (limited to 'src/protocols/Fifo.cpp') diff --git a/src/protocols/Fifo.cpp b/src/protocols/Fifo.cpp index 386327b5..8f842593 100644 --- a/src/protocols/Fifo.cpp +++ b/src/protocols/Fifo.cpp @@ -18,7 +18,8 @@ CFifoResource::CFifoResource(UP&& resource_, SP s return; } - m_pending.barrierSet = true; + m_surface->m_pending.barrierSet = true; + m_surface->m_pending.updated.bits.fifo = true; }); m_resource->setWaitBarrier([this](CWpFifoV1* r) { @@ -27,54 +28,37 @@ CFifoResource::CFifoResource(UP&& resource_, SP s return; } - if (!m_pending.barrierSet) + if (!m_surface->m_current.barrierSet) { + // that might mean an empty commit with a barrier_set alone + static const auto PPEND = CConfigValue("debug:fifo_pending_workaround"); + if (!m_surface->m_pending.fifoScheduled) + m_surface->m_pending.fifoScheduled = checkMonitors(*PPEND); + return; + } - m_pending.surfaceLocked = true; + m_surface->m_pending.surfaceLocked = true; }); m_listeners.surfaceStateCommit = m_surface->m_events.stateCommit.listen([this](auto state) { + if (!state || !state->surfaceLocked) + return; + static const auto PPEND = CConfigValue("debug:fifo_pending_workaround"); - if (!m_pending.surfaceLocked) - return; + //#TODO: + // this feels wrong, but if we have no pending frames, presented might never come because + // we are waiting on the barrier to unlock and no damage is around. + // unlock on timeout instead? + if (!state->fifoScheduled) + state->fifoScheduled = checkMonitors(*PPEND); - if (*PPEND) { - //#TODO: - // this feels wrong, but if we have no pending frames, presented might never come because - // we are waiting on the barrier to unlock and no damage is around. - // unlock on timeout instead? - if (m_surface->m_enteredOutputs.empty() && m_surface->m_hlSurface) { - for (auto& m : g_pCompositor->m_monitors) { - if (!m || !m->m_enabled) - continue; - - auto box = m_surface->m_hlSurface->getSurfaceBoxGlobal(); - if (box && !box->intersection({m->m_position, m->m_size}).empty()) { - if (m->m_tearingState.activelyTearing) - return; // dont fifo lock on tearing. - - g_pCompositor->scheduleFrameForMonitor(m, Aquamarine::IOutput::AQ_SCHEDULE_NEEDS_FRAME); - } - } - } else { - for (auto& m : m_surface->m_enteredOutputs) { - if (!m) - continue; - - if (m->m_tearingState.activelyTearing) - return; // dont fifo lock on tearing. - - g_pCompositor->scheduleFrameForMonitor(m.lock(), Aquamarine::IOutput::AQ_SCHEDULE_NEEDS_FRAME); - } - } - } + if (!state->fifoScheduled) + return; // only lock once its mapped. if (m_surface->m_mapped) m_surface->m_stateQueue.lock(state, LOCK_REASON_FIFO); - - m_pending = {}; }); } @@ -87,9 +71,41 @@ bool CFifoResource::good() { } void CFifoResource::presented() { + m_surface->m_current.barrierSet = false; m_surface->m_stateQueue.unlockFirst(LOCK_REASON_FIFO); } +bool CFifoResource::checkMonitors(bool needsSchedule) { + if (m_surface->m_enteredOutputs.empty() && m_surface->m_hlSurface) { + for (auto& m : g_pCompositor->m_monitors) { + if (!m || !m->m_enabled) + continue; + + auto box = m_surface->m_hlSurface->getSurfaceBoxGlobal(); + if (box && !box->intersection({m->m_position, m->m_size}).empty()) { + if (m->m_tearingState.activelyTearing) + return false; // dont fifo lock on tearing. + + if (needsSchedule) + g_pCompositor->scheduleFrameForMonitor(m, Aquamarine::IOutput::AQ_SCHEDULE_NEEDS_FRAME); + } + } + } else { + for (auto& m : m_surface->m_enteredOutputs) { + if (!m) + continue; + + if (m->m_tearingState.activelyTearing) + return false; // dont fifo lock on tearing. + + if (needsSchedule) + g_pCompositor->scheduleFrameForMonitor(m.lock(), Aquamarine::IOutput::AQ_SCHEDULE_NEEDS_FRAME); + } + } + + return true; +} + CFifoManagerResource::CFifoManagerResource(UP&& resource_) : m_resource(std::move(resource_)) { if UNLIKELY (!m_resource->resource()) return; -- cgit v1.2.3