From 4c897c2d476d42c716dee254d151ff23c66ef53b Mon Sep 17 00:00:00 2001 From: Pppp1116 Date: Fri, 3 Apr 2026 13:24:08 +0100 Subject: protocols: prune stale subsurface refs in hot traversals --- src/protocols/PresentationTime.cpp | 4 +++ src/protocols/PresentationTime.hpp | 1 + src/protocols/core/Compositor.cpp | 56 ++++++++++++++++++++++++++++-------- src/protocols/core/Subcompositor.cpp | 11 +++++++ src/protocols/core/Subcompositor.hpp | 1 + 5 files changed, 61 insertions(+), 12 deletions(-) (limited to 'src/protocols') diff --git a/src/protocols/PresentationTime.cpp b/src/protocols/PresentationTime.cpp index 456ad724..ab15d701 100644 --- a/src/protocols/PresentationTime.cpp +++ b/src/protocols/PresentationTime.cpp @@ -146,3 +146,7 @@ void CPresentationProtocol::onPresented(PHLMONITOR pMonitor, const timespec& whe void CPresentationProtocol::queueData(UP&& data) { m_queue.emplace_back(std::move(data)); } + +bool CPresentationProtocol::hasPendingFeedbacks() const { + return !m_feedbacks.empty(); +} diff --git a/src/protocols/PresentationTime.hpp b/src/protocols/PresentationTime.hpp index caf63ace..6bac9919 100644 --- a/src/protocols/PresentationTime.hpp +++ b/src/protocols/PresentationTime.hpp @@ -56,6 +56,7 @@ class CPresentationProtocol : public IWaylandProtocol { void onPresented(PHLMONITOR pMonitor, const timespec& when, uint32_t untilRefreshNs, uint64_t seq, uint32_t reportedFlags); void queueData(UP&& data); + bool hasPendingFeedbacks() const; private: void onManagerResourceDestroy(wl_resource* res); diff --git a/src/protocols/core/Compositor.cpp b/src/protocols/core/Compositor.cpp index e5008a3c..a51c60a2 100644 --- a/src/protocols/core/Compositor.cpp +++ b/src/protocols/core/Compositor.cpp @@ -358,13 +358,21 @@ void CWLSurfaceResource::bfHelper(std::vector> const& nod // first, gather all nodes below for (auto const& n : nodes) { std::erase_if(n->m_subsurfaces, [](const auto& e) { return e.expired(); }); + // subsurfaces is sorted lowest -> highest - for (auto const& c : n->m_subsurfaces) { - if (c->m_zIndex >= 0) + for (auto const& subsurfaceRef : n->m_subsurfaces) { + const auto subsurface = subsurfaceRef.lock(); + if (!subsurface) + continue; + + if (subsurface->m_zIndex >= 0) break; - if (c->m_surface.expired()) + + const auto surface = subsurface->m_surface.lock(); + if (!surface) continue; - nodes2.emplace_back(c->m_surface.lock()); + + nodes2.emplace_back(surface); } } @@ -377,19 +385,29 @@ void CWLSurfaceResource::bfHelper(std::vector> const& nod Vector2D offset = {}; if (n->m_role->role() == SURFACE_ROLE_SUBSURFACE) { auto subsurface = sc(n->m_role.get())->m_subsurface.lock(); - offset = subsurface->posRelativeToParent(); + if (subsurface) + offset = subsurface->posRelativeToParent(); } fn(n, offset, data); } for (auto const& n : nodes) { - for (auto const& c : n->m_subsurfaces) { - if (c->m_zIndex < 0) + std::erase_if(n->m_subsurfaces, [](const auto& e) { return e.expired(); }); + + for (auto const& subsurfaceRef : n->m_subsurfaces) { + const auto subsurface = subsurfaceRef.lock(); + if (!subsurface) continue; - if (c->m_surface.expired()) + + if (subsurface->m_zIndex < 0) + continue; + + const auto surface = subsurface->m_surface.lock(); + if (!surface) continue; - nodes2.emplace_back(c->m_surface.lock()); + + nodes2.emplace_back(surface); } } @@ -406,10 +424,19 @@ void CWLSurfaceResource::breadthfirst(std::function, SP CWLSurfaceResource::findFirstPreorderHelper(SP root, std::function)> fn) { if (fn(root)) return root; - for (auto const& sub : root->m_subsurfaces) { - if (sub.expired() || sub->m_surface.expired()) + + std::erase_if(root->m_subsurfaces, [](const auto& e) { return e.expired(); }); + + for (auto const& subsurfaceRef : root->m_subsurfaces) { + const auto subsurface = subsurfaceRef.lock(); + if (!subsurface) + continue; + + const auto surface = subsurface->m_surface.lock(); + if (!surface) continue; - const auto found = findFirstPreorderHelper(sub->m_surface.lock(), fn); + + const auto found = findFirstPreorderHelper(surface, fn); if (found) return found; } @@ -598,6 +625,7 @@ PImageDescription CWLSurfaceResource::getPreferredImageDescription() { } void CWLSurfaceResource::sortSubsurfaces() { + std::erase_if(m_subsurfaces, [](const auto& subsurface) { return !subsurface; }); std::ranges::sort(m_subsurfaces, [](const auto& a, const auto& b) { return a->m_zIndex < b->m_zIndex; }); // find the first non-negative index. We will preserve negativity: e.g. -2, -1, 1, 2 @@ -698,6 +726,10 @@ void CWLSurfaceResource::updateCursorShm(CRegion damage) { void CWLSurfaceResource::presentFeedback(const Time::steady_tp& when, PHLMONITOR pMonitor, bool discarded) { frame(when); + + if (!PROTO::presentation->hasPendingFeedbacks()) + return; + auto FEEDBACK = makeUnique(m_self.lock()); FEEDBACK->attachMonitor(pMonitor); if (discarded) diff --git a/src/protocols/core/Subcompositor.cpp b/src/protocols/core/Subcompositor.cpp index 14dc4666..d8a3e860 100644 --- a/src/protocols/core/Subcompositor.cpp +++ b/src/protocols/core/Subcompositor.cpp @@ -91,12 +91,15 @@ CWLSubsurfaceResource::CWLSubsurfaceResource(SP resource_, SPresetRole(); } void CWLSubsurfaceResource::destroy() { + unlinkFromParent(); + if (m_surface && m_surface->m_mapped) { m_surface->m_events.unmap.emit(); m_surface->unmap(); @@ -105,6 +108,14 @@ void CWLSubsurfaceResource::destroy() { PROTO::subcompositor->destroyResource(this); } +void CWLSubsurfaceResource::unlinkFromParent() { + const auto PARENT = m_parent.lock(); + if (!PARENT) + return; + + std::erase_if(PARENT->m_subsurfaces, [this](const auto& subsurface) { return !subsurface || subsurface.get() == this; }); +} + Vector2D CWLSubsurfaceResource::posRelativeToParent() { Vector2D pos = m_position; SP surf = m_parent.lock(); diff --git a/src/protocols/core/Subcompositor.hpp b/src/protocols/core/Subcompositor.hpp index 45b84eba..6c46c2e6 100644 --- a/src/protocols/core/Subcompositor.hpp +++ b/src/protocols/core/Subcompositor.hpp @@ -55,6 +55,7 @@ class CWLSubsurfaceResource { SP m_resource; void destroy(); + void unlinkFromParent(); struct { CHyprSignalListener commitSurface; -- cgit v1.2.3