diff --git a/debian/patches/sync.patch b/debian/patches/sync.patch index f92ad4d..bb682de 100644 --- a/debian/patches/sync.patch +++ b/debian/patches/sync.patch @@ -1,4 +1,4 @@ -From 7d74ba21c822ca1761a6d3f14555ea3a7e8aba9d Mon Sep 17 00:00:00 2001 +From 46dbd22d987e5781ba7e6651f7e6be543009881f Mon Sep 17 00:00:00 2001 From: Tom Englund Date: Tue, 18 Feb 2025 15:29:53 +0100 Subject: [PATCH] syncobj: use eventfd instead of stalling fd checks @@ -14,17 +14,17 @@ releasepoints. remove that and let the buffers releaser handle it. --- src/helpers/Monitor.cpp | 16 +----- src/helpers/sync/SyncReleaser.cpp | 4 -- - src/helpers/sync/SyncReleaser.hpp | 3 - + src/helpers/sync/SyncReleaser.hpp | 3 -- src/helpers/sync/SyncTimeline.cpp | 17 ++++++ src/helpers/sync/SyncTimeline.hpp | 1 + - src/protocols/DRMSyncobj.cpp | 78 +++++++++++++------------- - src/protocols/DRMSyncobj.hpp | 16 ++++-- - src/protocols/core/Compositor.cpp | 17 +++--- + src/protocols/DRMSyncobj.cpp | 75 +++++++++++++------------- + src/protocols/DRMSyncobj.hpp | 22 ++++++-- + src/protocols/core/Compositor.cpp | 16 +++--- src/protocols/core/Compositor.hpp | 4 +- src/protocols/types/Buffer.hpp | 4 +- src/render/Renderer.cpp | 5 +- src/render/pass/SurfacePassElement.cpp | 4 +- - 12 files changed, 87 insertions(+), 82 deletions(-) + 12 files changed, 93 insertions(+), 78 deletions(-) diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index 24db3ea4b2d..6aa75ce9f95 100644 @@ -137,62 +137,46 @@ index ba65e004d0b..bfd70416106 100644 bool importFromSyncFileFD(uint64_t dst, Hyprutils::OS::CFileDescriptor& fd); bool transfer(SP from, uint64_t fromPoint, uint64_t toPoint); diff --git a/src/protocols/DRMSyncobj.cpp b/src/protocols/DRMSyncobj.cpp -index 38aab305af3..425794814c9 100644 +index 38aab305af3..63f0946b58c 100644 --- a/src/protocols/DRMSyncobj.cpp +++ b/src/protocols/DRMSyncobj.cpp -@@ -8,6 +8,11 @@ - #include - using namespace Hyprutils::OS; - -+CDRMSyncobjSurfaceResource::TimeLineState::~TimeLineState() { -+ if (resource) -+ resource->timeline->removeAllWaiters(); -+} -+ - CDRMSyncobjSurfaceResource::CDRMSyncobjSurfaceResource(SP resource_, SP surface_) : surface(surface_), resource(resource_) { - if UNLIKELY (!good()) - return; -@@ -23,9 +28,9 @@ CDRMSyncobjSurfaceResource::CDRMSyncobjSurfaceResource(SPsetSetReleasePoint([this](CWpLinuxDrmSyncobjSurfaceV1* r, wl_resource* timeline_, uint32_t hi, uint32_t lo) { -@@ -34,13 +39,14 @@ CDRMSyncobjSurfaceResource::CDRMSyncobjSurfaceResource(SP(release.resource->timeline, release.point)); ++ pendingRelease.resource = timeline; ++ pendingRelease.point = ((uint64_t)hi << 32) | (uint64_t)lo; ++ releasePoints.emplace_back(makeUnique(pendingRelease.resource->timeline, pendingRelease.point)); }); listeners.surfacePrecommit = surface->events.precommit.registerListener([this](std::any d) { - if ((pending.acquireTimeline || pending.releaseTimeline) && !surface->pending.texture) { -+ if ((acquire.resource || release.resource) && !surface->pending.texture) { ++ if ((pendingAcquire.resource || pendingRelease.resource) && !surface->pending.texture) { resource->error(WP_LINUX_DRM_SYNCOBJ_SURFACE_V1_ERROR_NO_BUFFER, "Missing buffer"); surface->pending.rejected = true; return; -@@ -49,57 +55,49 @@ CDRMSyncobjSurfaceResource::CDRMSyncobjSurfaceResource(SPpending.newBuffer) return; // this commit does not change the state here - if (!!pending.acquireTimeline != !!pending.releaseTimeline) { - resource->error(pending.acquireTimeline ? WP_LINUX_DRM_SYNCOBJ_SURFACE_V1_ERROR_NO_RELEASE_POINT : WP_LINUX_DRM_SYNCOBJ_SURFACE_V1_ERROR_NO_ACQUIRE_POINT, -- "Missing timeline"); -+ if (!!acquire.resource != !!release.resource) { -+ resource->error(acquire.resource ? WP_LINUX_DRM_SYNCOBJ_SURFACE_V1_ERROR_NO_RELEASE_POINT : WP_LINUX_DRM_SYNCOBJ_SURFACE_V1_ERROR_NO_ACQUIRE_POINT, "Missing timeline"); ++ if (!!pendingAcquire.resource != !!pendingRelease.resource) { ++ resource->error(pendingAcquire.resource ? WP_LINUX_DRM_SYNCOBJ_SURFACE_V1_ERROR_NO_RELEASE_POINT : WP_LINUX_DRM_SYNCOBJ_SURFACE_V1_ERROR_NO_ACQUIRE_POINT, + "Missing timeline"); surface->pending.rejected = true; return; } @@ -202,8 +186,8 @@ index 38aab305af3..425794814c9 100644 - - if (pending.acquireTimeline && pending.releaseTimeline && pending.acquireTimeline == pending.releaseTimeline) { - if (pending.acquirePoint >= pending.releasePoint) { -+ if (acquire.resource && release.resource && acquire.resource == release.resource) { -+ if (acquire.point >= release.point) { ++ if (pendingAcquire.resource && pendingRelease.resource && pendingAcquire.resource == pendingRelease.resource) { ++ if (pendingAcquire.point >= pendingRelease.point) { resource->error(WP_LINUX_DRM_SYNCOBJ_SURFACE_V1_ERROR_CONFLICTING_POINTS, "Acquire and release points are on the same timeline, and acquire >= release"); surface->pending.rejected = true; return; @@ -215,32 +199,13 @@ index 38aab305af3..425794814c9 100644 - if (!materialized.has_value()) { - LOGM(ERR, "Failed to check the acquire timeline"); - resource->noMemory(); -+ if (!acquire.resource) ++ if (!pendingAcquire.resource) return; -- } - -- if (materialized.value()) -- return; -- -- surface->lockPendingState(); -- pending.acquireTimeline->timeline->addWaiter([this]() { surface->unlockPendingState(); }, pending.acquirePoint, DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE); -- }); -- -- listeners.surfaceCommit = surface->events.roleCommit.registerListener([this](std::any d) { -- // apply timelines if new ones have been attached, otherwise don't touch -- // the current ones -- if (pending.releaseTimeline) { -- current.releaseTimeline = pending.releaseTimeline; -- current.releasePoint = pending.releasePoint; -+ if (acquireWaiting) { -+ acquire.resource->timeline->removeAllWaiters(); -+ surface->unlockPendingState(); // unref for the new potential ref. - } - -- if (pending.acquireTimeline) { -- current.acquireTimeline = pending.acquireTimeline; -- current.acquirePoint = pending.acquirePoint; -+ if (acquire.resource->timeline->addWaiter( ++ ++ if (acquireWaiting) ++ return; // wait for acquire waiter to signal. ++ ++ if (pendingAcquire.resource->timeline->addWaiter( + [this]() { + if (surface.expired()) + return; @@ -249,26 +214,51 @@ index 38aab305af3..425794814c9 100644 + surface->commitPendingState(); + acquireWaiting = false; + }, -+ acquire.point, 0u)) { ++ pendingAcquire.point, 0u)) { + surface->lockPendingState(); + acquireWaiting = true; } -- -- pending.releaseTimeline.reset(); -- pending.acquireTimeline.reset(); - }); - } ++ }); +- if (materialized.value()) +- return; ++ listeners.surfaceRoleCommit = surface->events.roleCommit.registerListener([this](std::any d) { ++ if (pendingAcquire.resource) ++ acquire = std::exchange(pendingAcquire, {}); + +- surface->lockPendingState(); +- pending.acquireTimeline->timeline->addWaiter([this]() { surface->unlockPendingState(); }, pending.acquirePoint, DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE); ++ if (pendingRelease.resource) ++ release = std::exchange(pendingRelease, {}); + }); ++} + +- listeners.surfaceCommit = surface->events.roleCommit.registerListener([this](std::any d) { +- // apply timelines if new ones have been attached, otherwise don't touch +- // the current ones +- if (pending.releaseTimeline) { +- current.releaseTimeline = pending.releaseTimeline; +- current.releasePoint = pending.releasePoint; +- } +CDRMSyncobjSurfaceResource::~CDRMSyncobjSurfaceResource() { + if (acquire.resource) + acquire.resource->timeline->removeAllWaiters(); -+} -+ - bool CDRMSyncobjSurfaceResource::good() { - return resource->resource(); + +- if (pending.acquireTimeline) { +- current.acquireTimeline = pending.acquireTimeline; +- current.acquirePoint = pending.acquirePoint; +- } +- +- pending.releaseTimeline.reset(); +- pending.acquireTimeline.reset(); +- }); ++ if (pendingAcquire.resource) ++ pendingAcquire.resource->timeline->removeAllWaiters(); } + + bool CDRMSyncobjSurfaceResource::good() { diff --git a/src/protocols/DRMSyncobj.hpp b/src/protocols/DRMSyncobj.hpp -index 9895dff17e3..6512ed419d8 100644 +index 9895dff17e3..06a3def2565 100644 --- a/src/protocols/DRMSyncobj.hpp +++ b/src/protocols/DRMSyncobj.hpp @@ -2,6 +2,7 @@ @@ -279,7 +269,7 @@ index 9895dff17e3..6512ed419d8 100644 #include "linux-drm-syncobj-v1.hpp" #include "../helpers/signal/Signal.hpp" #include -@@ -13,21 +14,26 @@ class CSyncTimeline; +@@ -13,21 +14,32 @@ class CSyncTimeline; class CDRMSyncobjSurfaceResource { public: CDRMSyncobjSurfaceResource(SP resource_, SP surface_); @@ -292,12 +282,17 @@ index 9895dff17e3..6512ed419d8 100644 - WP acquireTimeline, releaseTimeline; - uint64_t acquirePoint = 0, releasePoint = 0; - } current, pending; -+ struct TimeLineState { ++ struct STimeLineState { + WP resource; + uint64_t point = 0; + -+ ~TimeLineState(); -+ } acquire, release; ++ STimeLineState() = default; ++ STimeLineState(STimeLineState&&) noexcept = default; ++ STimeLineState& operator=(STimeLineState&&) noexcept = default; ++ STimeLineState(const STimeLineState&) = delete; ++ STimeLineState& operator=(const STimeLineState&) = delete; ++ ~STimeLineState() = default; ++ } acquire, release, pendingAcquire, pendingRelease; + + std::vector> releasePoints; @@ -308,11 +303,12 @@ index 9895dff17e3..6512ed419d8 100644 struct { CHyprSignalListener surfacePrecommit; - CHyprSignalListener surfaceCommit; ++ CHyprSignalListener surfaceRoleCommit; } listeners; }; diff --git a/src/protocols/core/Compositor.cpp b/src/protocols/core/Compositor.cpp -index 92c3c425d7c..0674743ea9e 100644 +index 92c3c425d7c..87adaeae1be 100644 --- a/src/protocols/core/Compositor.cpp +++ b/src/protocols/core/Compositor.cpp @@ -113,8 +113,7 @@ CWLSurfaceResource::CWLSurfaceResource(SP resource_) : resource(reso @@ -347,15 +343,14 @@ index 92c3c425d7c..0674743ea9e 100644 static auto PDROP = CConfigValue("render:allow_early_buffer_release"); auto const previousBuffer = current.buffer; current = pending; -@@ -433,8 +433,9 @@ void CWLSurfaceResource::commitPendingState() { +@@ -433,8 +433,8 @@ void CWLSurfaceResource::commitPendingState() { events.roleCommit.emit(); - if (syncobj && syncobj->current.releaseTimeline && syncobj->current.releaseTimeline->timeline && current.buffer && current.buffer->buffer) - current.buffer->releaser = makeShared(syncobj->current.releaseTimeline->timeline, syncobj->current.releasePoint); -+ if (syncobj && syncobj->release.resource && syncobj->release.resource->timeline && current.buffer && current.buffer->buffer) { ++ if (syncobj && syncobj->release.resource && syncobj->release.resource->timeline && current.buffer && current.buffer->buffer) + current.buffer->releaser = std::move(syncobj->releasePoints); -+ } if (current.texture) current.texture->m_eTransform = wlTransformToHyprutils(current.transform); @@ -402,10 +397,10 @@ index 7d84dce7390..03f4fe97d0e 100644 private: WP surface; diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp -index b61f1c3eb5b..41a8577e471 100644 +index f01a0d1225b..09e3b04e779 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp -@@ -1568,10 +1568,11 @@ bool CHyprRenderer::commitPendingAndDoExplicitSync(PHLMONITOR pMonitor) { +@@ -1574,10 +1574,11 @@ bool CHyprRenderer::commitPendingAndDoExplicitSync(PHLMONITOR pMonitor) { Debug::log(TRACE, "Explicit: can't add sync, EGLSync failed"); else { for (auto const& e : explicitPresented) { @@ -435,4 +430,5 @@ index a5d3d7c001a..e6e03b99773 100644 return; } + \ No newline at end of file