From 77014230b5f15609541942fa8e91b57b2e4db89b Mon Sep 17 00:00:00 2001 From: ferreo Date: Mon, 17 Feb 2025 19:00:28 +0100 Subject: [PATCH] Add debian/patches/esync.patch --- debian/patches/esync.patch | 260 +++++++++++++++++++++++++++++++++++++ 1 file changed, 260 insertions(+) create mode 100644 debian/patches/esync.patch diff --git a/debian/patches/esync.patch b/debian/patches/esync.patch new file mode 100644 index 0000000..db054d9 --- /dev/null +++ b/debian/patches/esync.patch @@ -0,0 +1,260 @@ +diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp +index 24db3ea4..5aa1896c 100644 +--- a/src/helpers/Monitor.cpp ++++ b/src/helpers/Monitor.cpp +@@ -1315,10 +1315,10 @@ bool CMonitor::attemptDirectScanout() { + auto explicitOptions = g_pHyprRenderer->getExplicitSyncSettings(output); + + // wait for the explicit fence if present, and if kms explicit is allowed +- bool DOEXPLICIT = PSURFACE->syncobj && PSURFACE->syncobj->current.acquireTimeline && PSURFACE->syncobj->current.acquireTimeline->timeline && explicitOptions.explicitKMSEnabled; ++ bool DOEXPLICIT = PSURFACE->syncobj && PSURFACE->syncobj->acquire.resource && PSURFACE->syncobj->acquire.resource->timeline && explicitOptions.explicitKMSEnabled; + CFileDescriptor explicitWaitFD; + if (DOEXPLICIT) { +- explicitWaitFD = PSURFACE->syncobj->current.acquireTimeline->timeline->exportAsSyncFileFD(PSURFACE->syncobj->current.acquirePoint); ++ explicitWaitFD = PSURFACE->syncobj->acquire.resource->timeline->exportAsSyncFileFD(PSURFACE->syncobj->acquire.point); + if (!explicitWaitFD.isValid()) + Debug::log(TRACE, "attemptDirectScanout: failed to acquire an explicit wait fd"); + } +@@ -1356,12 +1356,15 @@ bool CMonitor::attemptDirectScanout() { + // delay explicit sync feedback until kms release of the buffer + if (DOEXPLICIT) { + Debug::log(TRACE, "attemptDirectScanout: Delaying explicit sync release feedback until kms release"); +- PSURFACE->current.buffer->releaser->drop(); ++ //#TODO is this correct, or should only the last release feedback be delayed? ++ for (auto& r : PSURFACE->current.buffer->releaser) { ++ r->drop(); ++ } + + PSURFACE->current.buffer->buffer->hlEvents.backendRelease2 = PSURFACE->current.buffer->buffer->events.backendRelease.registerListener([PSURFACE](std::any d) { +- const bool DOEXPLICIT = PSURFACE->syncobj && PSURFACE->syncobj->current.releaseTimeline && PSURFACE->syncobj->current.releaseTimeline->timeline; ++ const bool DOEXPLICIT = PSURFACE->syncobj && PSURFACE->syncobj->release.resource && PSURFACE->syncobj->release.resource->timeline; + if (DOEXPLICIT) +- PSURFACE->syncobj->current.releaseTimeline->timeline->signal(PSURFACE->syncobj->current.releasePoint); ++ PSURFACE->syncobj->release.resource->timeline->signal(PSURFACE->syncobj->release.point); + }); + } + } else { +diff --git a/src/helpers/sync/SyncTimeline.cpp b/src/helpers/sync/SyncTimeline.cpp +index 46b617bc..0f388479 100644 +--- a/src/helpers/sync/SyncTimeline.cpp ++++ b/src/helpers/sync/SyncTimeline.cpp +@@ -33,6 +33,13 @@ SP CSyncTimeline::create(int drmFD_, int drmSyncobjFD) { + } + + CSyncTimeline::~CSyncTimeline() { ++ for (auto& w : waiters) { ++ if (w->source) { ++ wl_event_source_remove(w->source); ++ w->source = nullptr; ++ } ++ } ++ + if (handle == 0) + return; + +diff --git a/src/protocols/DRMSyncobj.cpp b/src/protocols/DRMSyncobj.cpp +index 38aab305..ac31bfe5 100644 +--- a/src/protocols/DRMSyncobj.cpp ++++ b/src/protocols/DRMSyncobj.cpp +@@ -23,9 +23,9 @@ CDRMSyncobjSurfaceResource::CDRMSyncobjSurfaceResource(SPsetSetReleasePoint([this](CWpLinuxDrmSyncobjSurfaceV1* r, wl_resource* timeline_, uint32_t hi, uint32_t lo) { +@@ -34,13 +34,14 @@ CDRMSyncobjSurfaceResource::CDRMSyncobjSurfaceResource(SP(release)); + }); + + 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) { + resource->error(WP_LINUX_DRM_SYNCOBJ_SURFACE_V1_ERROR_NO_BUFFER, "Missing buffer"); + surface->pending.rejected = true; + return; +@@ -49,54 +50,32 @@ 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"); + surface->pending.rejected = true; + return; + } + +- if (!pending.acquireTimeline) ++ if (!acquire.resource) + return; + +- 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) { + 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; + } + } + +- // wait for the acquire timeline to materialize +- auto materialized = pending.acquireTimeline->timeline->check(pending.acquirePoint, DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE); +- if (!materialized.has_value()) { +- LOGM(ERR, "Failed to check the acquire timeline"); +- resource->noMemory(); +- 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 (pending.acquireTimeline) { +- current.acquireTimeline = pending.acquireTimeline; +- current.acquirePoint = pending.acquirePoint; +- } +- +- pending.releaseTimeline.reset(); +- pending.acquireTimeline.reset(); ++ acquire.resource->timeline->addWaiter( ++ [this]() { ++ if (surface.expired()) ++ return; ++ ++ surface->unlockPendingState(); ++ }, ++ acquire.point, 0u); + }); + } + +diff --git a/src/protocols/DRMSyncobj.hpp b/src/protocols/DRMSyncobj.hpp +index 9895dff1..68b2a4e3 100644 +--- a/src/protocols/DRMSyncobj.hpp ++++ b/src/protocols/DRMSyncobj.hpp +@@ -17,10 +17,12 @@ class CDRMSyncobjSurfaceResource { + bool good(); + + WP surface; +- struct { +- WP acquireTimeline, releaseTimeline; +- uint64_t acquirePoint = 0, releasePoint = 0; +- } current, pending; ++ struct TimeLineState { ++ WP resource; ++ uint64_t point = 0; ++ } acquire, release; ++ ++ std::vector> releasePoints; + + private: + SP resource; +diff --git a/src/protocols/core/Compositor.cpp b/src/protocols/core/Compositor.cpp +index 92c3c425..e98c25fc 100644 +--- a/src/protocols/core/Compositor.cpp ++++ b/src/protocols/core/Compositor.cpp +@@ -417,6 +417,7 @@ void CWLSurfaceResource::lockPendingState() { + + void CWLSurfaceResource::unlockPendingState() { + stateLocks--; ++ + if (stateLocks <= 0) + commitPendingState(); + } +@@ -433,8 +434,16 @@ 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->acquire.resource && syncobj->acquire.resource->timeline && current.buffer && current.buffer->buffer) { ++ for (auto& r : syncobj->releasePoints) { ++ if (r->resource.expired()) ++ continue; ++ ++ current.buffer->releaser.emplace_back(makeShared(r->resource->timeline, r->point)); ++ } ++ ++ syncobj->releasePoints.clear(); ++ } + + if (current.texture) + current.texture->m_eTransform = wlTransformToHyprutils(current.transform); +diff --git a/src/protocols/types/Buffer.hpp b/src/protocols/types/Buffer.hpp +index 7d84dce7..6ed5c01f 100644 +--- a/src/protocols/types/Buffer.hpp ++++ b/src/protocols/types/Buffer.hpp +@@ -43,8 +43,8 @@ class CHLBufferReference { + CHLBufferReference(SP buffer, SP surface); + ~CHLBufferReference(); + +- WP buffer; +- SP releaser; ++ WP buffer; ++ std::vector> releaser; + + private: + WP surface; +diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp +index b61f1c3e..bb7b1e1d 100644 +--- a/src/render/Renderer.cpp ++++ b/src/render/Renderer.cpp +@@ -1568,10 +1568,11 @@ bool CHyprRenderer::commitPendingAndDoExplicitSync(PHLMONITOR pMonitor) { + Debug::log(TRACE, "Explicit: can't add sync, EGLSync failed"); + else { + for (auto const& e : explicitPresented) { +- if (!e->current.buffer || !e->current.buffer->releaser) ++ if (!e->current.buffer || e->current.buffer->releaser.empty()) + continue; + +- e->current.buffer->releaser->addReleaseSync(sync); ++ for (auto& r : e->current.buffer->releaser) //#TODO is this correct? should it only be on last point? ++ r->addReleaseSync(sync); + } + } + +diff --git a/src/render/pass/SurfacePassElement.cpp b/src/render/pass/SurfacePassElement.cpp +index a5d3d7c0..e6e03b99 100644 +--- a/src/render/pass/SurfacePassElement.cpp ++++ b/src/render/pass/SurfacePassElement.cpp +@@ -50,8 +50,8 @@ void CSurfacePassElement::draw(const CRegion& damage) { + return; + + // explicit sync: wait for the timeline, if any +- if (data.surface->syncobj && data.surface->syncobj->current.acquireTimeline) { +- if (!g_pHyprOpenGL->waitForTimelinePoint(data.surface->syncobj->current.acquireTimeline->timeline, data.surface->syncobj->current.acquirePoint)) { ++ if (data.surface->syncobj && data.surface->syncobj->acquire.resource) { ++ if (!g_pHyprOpenGL->waitForTimelinePoint(data.surface->syncobj->acquire.resource->timeline, data.surface->syncobj->acquire.point)) { + Debug::log(ERR, "Renderer: failed to wait for explicit timeline"); + return; + } + + \ No newline at end of file