summaryrefslogtreecommitdiff
path: root/src/protocols
diff options
context:
space:
mode:
authorPppp1116 <pcaiadoguerreiro@gmail.com>2026-04-03 13:24:08 +0100
committerVaxry <43317083+vaxerski@users.noreply.github.com>2026-04-04 08:26:24 -0400
commit4c897c2d476d42c716dee254d151ff23c66ef53b (patch)
tree109be08644c1250ae36549a0c614ba24d0ef63d1 /src/protocols
parentf25473b21b45ab8ded4a0dbba69eb6b6660d568e (diff)
protocols: prune stale subsurface refs in hot traversals
Diffstat (limited to 'src/protocols')
-rw-r--r--src/protocols/PresentationTime.cpp4
-rw-r--r--src/protocols/PresentationTime.hpp1
-rw-r--r--src/protocols/core/Compositor.cpp56
-rw-r--r--src/protocols/core/Subcompositor.cpp11
-rw-r--r--src/protocols/core/Subcompositor.hpp1
5 files changed, 61 insertions, 12 deletions
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<CQueuedPresentationData>&& 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<CQueuedPresentationData>&& 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<SP<CWLSurfaceResource>> 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<SP<CWLSurfaceResource>> const& nod
Vector2D offset = {};
if (n->m_role->role() == SURFACE_ROLE_SUBSURFACE) {
auto subsurface = sc<CSubsurfaceRole*>(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<void(SP<CWLSurfaceResource>,
SP<CWLSurfaceResource> CWLSurfaceResource::findFirstPreorderHelper(SP<CWLSurfaceResource> root, std::function<bool(SP<CWLSurfaceResource>)> 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<CQueuedPresentationData>(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<CWlSubsurface> resource_, SP<CWL
}
CWLSubsurfaceResource::~CWLSubsurfaceResource() {
+ unlinkFromParent();
m_events.destroy.emit();
if (m_surface)
m_surface->resetRole();
}
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<CWLSurfaceResource> 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<CWlSubsurface> m_resource;
void destroy();
+ void unlinkFromParent();
struct {
CHyprSignalListener commitSurface;