Add debian/patches/esync.patch

This commit is contained in:
ferreo 2025-02-17 19:00:28 +01:00
parent 803c713e4e
commit 77014230b5

260
debian/patches/esync.patch vendored Normal file
View File

@ -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> 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(SP<CWpLinuxDrmSyncobjSurf
return;
}
- auto timeline = CDRMSyncobjTimelineResource::fromResource(timeline_);
- pending.acquireTimeline = timeline;
- pending.acquirePoint = ((uint64_t)hi << 32) | (uint64_t)lo;
+ auto timeline = CDRMSyncobjTimelineResource::fromResource(timeline_);
+ acquire.resource = timeline;
+ acquire.point = ((uint64_t)hi << 32) | (uint64_t)lo;
});
resource->setSetReleasePoint([this](CWpLinuxDrmSyncobjSurfaceV1* r, wl_resource* timeline_, uint32_t hi, uint32_t lo) {
@@ -34,13 +34,14 @@ CDRMSyncobjSurfaceResource::CDRMSyncobjSurfaceResource(SP<CWpLinuxDrmSyncobjSurf
return;
}
- auto timeline = CDRMSyncobjTimelineResource::fromResource(timeline_);
- pending.releaseTimeline = timeline;
- pending.releasePoint = ((uint64_t)hi << 32) | (uint64_t)lo;
+ auto timeline = CDRMSyncobjTimelineResource::fromResource(timeline_);
+ release.resource = timeline;
+ release.point = ((uint64_t)hi << 32) | (uint64_t)lo;
+ releasePoints.emplace_back(makeShared<TimeLineState>(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(SP<CWpLinuxDrmSyncobjSurf
if (!surface->pending.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<CWLSurfaceResource> surface;
- struct {
- WP<CDRMSyncobjTimelineResource> acquireTimeline, releaseTimeline;
- uint64_t acquirePoint = 0, releasePoint = 0;
- } current, pending;
+ struct TimeLineState {
+ WP<CDRMSyncobjTimelineResource> resource;
+ uint64_t point = 0;
+ } acquire, release;
+
+ std::vector<SP<TimeLineState>> releasePoints;
private:
SP<CWpLinuxDrmSyncobjSurfaceV1> 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<CSyncReleaser>(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<CSyncReleaser>(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<IHLBuffer> buffer, SP<CWLSurfaceResource> surface);
~CHLBufferReference();
- WP<IHLBuffer> buffer;
- SP<CSyncReleaser> releaser;
+ WP<IHLBuffer> buffer;
+ std::vector<SP<CSyncReleaser>> releaser;
private:
WP<CWLSurfaceResource> 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;
}