summaryrefslogtreecommitdiff
path: root/src/protocols
diff options
context:
space:
mode:
authorVaxry <43317083+vaxerski@users.noreply.github.com>2024-08-06 14:52:19 +0100
committerGitHub <noreply@github.com>2024-08-06 15:52:19 +0200
commit640d1618519d42dd592f7af5e9984ad52eb8b820 (patch)
treef44a5b58822eb60e7fd2dfc3e18af9bba0ab2cb0 /src/protocols
parent0e86808e5912823f1c6bea1b6d5fcae297fc9f57 (diff)
renderer: Explicit sync fixes (#7151)
Enables explicit sync by default for most platforms `misc:no_direct_scanout` -> `render:direct_scanout`
Diffstat (limited to 'src/protocols')
-rw-r--r--src/protocols/DRMSyncobj.cpp47
-rw-r--r--src/protocols/DRMSyncobj.hpp11
-rw-r--r--src/protocols/core/Compositor.cpp17
-rw-r--r--src/protocols/core/Compositor.hpp5
-rw-r--r--src/protocols/types/Buffer.cpp25
-rw-r--r--src/protocols/types/Buffer.hpp12
-rw-r--r--src/protocols/types/WLBuffer.cpp10
-rw-r--r--src/protocols/types/WLBuffer.hpp1
8 files changed, 61 insertions, 67 deletions
diff --git a/src/protocols/DRMSyncobj.cpp b/src/protocols/DRMSyncobj.cpp
index 33339554..8b0330de 100644
--- a/src/protocols/DRMSyncobj.cpp
+++ b/src/protocols/DRMSyncobj.cpp
@@ -24,9 +24,9 @@ CDRMSyncobjSurfaceResource::CDRMSyncobjSurfaceResource(SP<CWpLinuxDrmSyncobjSurf
return;
}
- auto timeline = CDRMSyncobjTimelineResource::fromResource(timeline_);
- acquireTimeline = timeline;
- acquirePoint = ((uint64_t)hi << 32) | (uint64_t)lo;
+ auto timeline = CDRMSyncobjTimelineResource::fromResource(timeline_);
+ pending.acquireTimeline = timeline;
+ pending.acquirePoint = ((uint64_t)hi << 32) | (uint64_t)lo;
});
resource->setSetReleasePoint([this](CWpLinuxDrmSyncobjSurfaceV1* r, wl_resource* timeline_, uint32_t hi, uint32_t lo) {
@@ -35,29 +35,33 @@ CDRMSyncobjSurfaceResource::CDRMSyncobjSurfaceResource(SP<CWpLinuxDrmSyncobjSurf
return;
}
- auto timeline = CDRMSyncobjTimelineResource::fromResource(timeline_);
- releaseTimeline = timeline;
- releasePoint = ((uint64_t)hi << 32) | (uint64_t)lo;
+ auto timeline = CDRMSyncobjTimelineResource::fromResource(timeline_);
+ pending.releaseTimeline = timeline;
+ pending.releasePoint = ((uint64_t)hi << 32) | (uint64_t)lo;
});
listeners.surfacePrecommit = surface->events.precommit.registerListener([this](std::any d) {
- if (!!acquireTimeline != !!releaseTimeline) {
- resource->error(acquireTimeline ? WP_LINUX_DRM_SYNCOBJ_SURFACE_V1_ERROR_NO_RELEASE_POINT : WP_LINUX_DRM_SYNCOBJ_SURFACE_V1_ERROR_NO_ACQUIRE_POINT, "Missing timeline");
+ if ((pending.acquireTimeline || pending.releaseTimeline) && !surface->pending.texture) {
+ resource->error(WP_LINUX_DRM_SYNCOBJ_SURFACE_V1_ERROR_NO_BUFFER, "Missing buffer");
surface->pending.rejected = true;
return;
}
- if ((acquireTimeline || releaseTimeline) && !surface->pending.texture) {
- resource->error(WP_LINUX_DRM_SYNCOBJ_SURFACE_V1_ERROR_NO_BUFFER, "Missing buffer");
+ 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");
surface->pending.rejected = true;
return;
}
- if (!acquireTimeline)
+ if (!pending.acquireTimeline)
return;
// wait for the acquire timeline to materialize
- auto materialized = acquireTimeline->timeline->check(acquirePoint, DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE);
+ 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();
@@ -68,7 +72,24 @@ CDRMSyncobjSurfaceResource::CDRMSyncobjSurfaceResource(SP<CWpLinuxDrmSyncobjSurf
return;
surface->lockPendingState();
- acquireTimeline->timeline->addWaiter([this]() { surface->unlockPendingState(); }, acquirePoint, DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE);
+ pending.acquireTimeline->timeline->addWaiter([this]() { surface->unlockPendingState(); }, pending.acquirePoint, DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE);
+ });
+
+ listeners.surfaceCommit = surface->events.commit.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();
});
}
diff --git a/src/protocols/DRMSyncobj.hpp b/src/protocols/DRMSyncobj.hpp
index c1c884ff..25dc10c1 100644
--- a/src/protocols/DRMSyncobj.hpp
+++ b/src/protocols/DRMSyncobj.hpp
@@ -14,17 +14,20 @@ class CDRMSyncobjSurfaceResource {
public:
CDRMSyncobjSurfaceResource(SP<CWpLinuxDrmSyncobjSurfaceV1> resource_, SP<CWLSurfaceResource> surface_);
- bool good();
+ bool good();
- WP<CWLSurfaceResource> surface;
- WP<CDRMSyncobjTimelineResource> acquireTimeline, releaseTimeline;
- uint64_t acquirePoint = 0, releasePoint = 0;
+ WP<CWLSurfaceResource> surface;
+ struct {
+ WP<CDRMSyncobjTimelineResource> acquireTimeline, releaseTimeline;
+ uint64_t acquirePoint = 0, releasePoint = 0;
+ } current, pending;
private:
SP<CWpLinuxDrmSyncobjSurfaceV1> resource;
struct {
CHyprSignalListener surfacePrecommit;
+ CHyprSignalListener surfaceCommit;
} listeners;
};
diff --git a/src/protocols/core/Compositor.cpp b/src/protocols/core/Compositor.cpp
index 4a6fa40f..b0111032 100644
--- a/src/protocols/core/Compositor.cpp
+++ b/src/protocols/core/Compositor.cpp
@@ -7,6 +7,7 @@
#include "Subcompositor.hpp"
#include "../Viewporter.hpp"
#include "../../helpers/Monitor.hpp"
+#include "../../helpers/sync/SyncReleaser.hpp"
#include "../PresentationTime.hpp"
#include "../DRMSyncobj.hpp"
#include "../../render/Renderer.hpp"
@@ -69,7 +70,8 @@ CWLSurfaceResource::CWLSurfaceResource(SP<CWlSurface> resource_) : resource(reso
resource->setOnDestroy([this](CWlSurface* r) { destroy(); });
resource->setAttach([this](CWlSurface* r, wl_resource* buffer, int32_t x, int32_t y) {
- pending.offset = {x, y};
+ pending.offset = {x, y};
+ pending.newBuffer = true;
if (!buffer) {
pending.buffer.reset();
@@ -428,6 +430,10 @@ void CWLSurfaceResource::commitPendingState() {
current = pending;
pending.damage.clear();
pending.bufferDamage.clear();
+ pending.newBuffer = false;
+
+ 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 (current.texture)
current.texture->m_eTransform = wlTransformToHyprutils(current.transform);
@@ -501,23 +507,18 @@ void CWLSurfaceResource::updateCursorShm() {
memcpy(shmData.data(), pixelData, bufLen);
}
-void CWLSurfaceResource::presentFeedback(timespec* when, CMonitor* pMonitor, bool needsExplicitSync) {
+void CWLSurfaceResource::presentFeedback(timespec* when, CMonitor* pMonitor) {
frame(when);
auto FEEDBACK = makeShared<CQueuedPresentationData>(self.lock());
FEEDBACK->attachMonitor(pMonitor);
FEEDBACK->presented();
PROTO::presentation->queueData(FEEDBACK);
- if (!pMonitor || !pMonitor->outTimeline || !syncobj || !needsExplicitSync)
+ if (!pMonitor || !pMonitor->outTimeline || !syncobj)
return;
// attach explicit sync
g_pHyprRenderer->explicitPresented.emplace_back(self.lock());
-
- if (syncobj->acquirePoint > pMonitor->lastWaitPoint) {
- Debug::log(TRACE, "presentFeedback lastWaitPoint {} -> {}", pMonitor->lastWaitPoint, syncobj->acquirePoint);
- pMonitor->lastWaitPoint = syncobj->acquirePoint;
- }
}
CWLCompositorResource::CWLCompositorResource(SP<CWlCompositor> resource_) : resource(resource_) {
diff --git a/src/protocols/core/Compositor.hpp b/src/protocols/core/Compositor.hpp
index 460ec755..af0dfa58 100644
--- a/src/protocols/core/Compositor.hpp
+++ b/src/protocols/core/Compositor.hpp
@@ -97,7 +97,8 @@ class CWLSurfaceResource {
Vector2D destination;
CBox source;
} viewport;
- bool rejected = false;
+ bool rejected = false;
+ bool newBuffer = false;
//
void reset() {
@@ -122,7 +123,7 @@ class CWLSurfaceResource {
void breadthfirst(std::function<void(SP<CWLSurfaceResource>, const Vector2D&, void*)> fn, void* data);
CRegion accumulateCurrentBufferDamage();
- void presentFeedback(timespec* when, CMonitor* pMonitor, bool needsExplicitSync = false);
+ void presentFeedback(timespec* when, CMonitor* pMonitor);
void lockPendingState();
void unlockPendingState();
diff --git a/src/protocols/types/Buffer.cpp b/src/protocols/types/Buffer.cpp
index 40f2eaf8..ea12f017 100644
--- a/src/protocols/types/Buffer.cpp
+++ b/src/protocols/types/Buffer.cpp
@@ -9,11 +9,6 @@ void IHLBuffer::sendRelease() {
resource->sendRelease();
}
-void IHLBuffer::sendReleaseWithSurface(SP<CWLSurfaceResource> surf) {
- if (resource && resource->good())
- resource->sendReleaseWithSurface(surf);
-}
-
void IHLBuffer::lock() {
nLocks++;
}
@@ -27,26 +22,13 @@ void IHLBuffer::unlock() {
sendRelease();
}
-void IHLBuffer::unlockWithSurface(SP<CWLSurfaceResource> surf) {
- nLocks--;
-
- ASSERT(nLocks >= 0);
-
- if (nLocks == 0)
- sendReleaseWithSurface(surf);
-}
-
bool IHLBuffer::locked() {
return nLocks > 0;
}
void IHLBuffer::unlockOnBufferRelease(WP<CWLSurfaceResource> surf) {
- unlockSurface = surf;
hlEvents.backendRelease = events.backendRelease.registerListener([this](std::any data) {
- if (unlockSurface.expired())
- unlock();
- else
- unlockWithSurface(unlockSurface.lock());
+ unlock();
hlEvents.backendRelease.reset();
});
}
@@ -59,8 +41,5 @@ CHLBufferReference::~CHLBufferReference() {
if (buffer.expired())
return;
- if (surface)
- buffer->unlockWithSurface(surface.lock());
- else
- buffer->unlock();
+ buffer->unlock();
}
diff --git a/src/protocols/types/Buffer.hpp b/src/protocols/types/Buffer.hpp
index d2157181..7d84dce7 100644
--- a/src/protocols/types/Buffer.hpp
+++ b/src/protocols/types/Buffer.hpp
@@ -6,6 +6,8 @@
#include <aquamarine/buffer/Buffer.hpp>
+class CSyncReleaser;
+
class IHLBuffer : public Aquamarine::IBuffer {
public:
virtual ~IHLBuffer();
@@ -15,10 +17,8 @@ class IHLBuffer : public Aquamarine::IBuffer {
virtual bool isSynchronous() = 0; // whether the updates to this buffer are synchronous, aka happen over cpu
virtual bool good() = 0;
virtual void sendRelease();
- virtual void sendReleaseWithSurface(SP<CWLSurfaceResource>);
virtual void lock();
virtual void unlock();
- virtual void unlockWithSurface(SP<CWLSurfaceResource> surf);
virtual bool locked();
void unlockOnBufferRelease(WP<CWLSurfaceResource> surf /* optional */);
@@ -29,12 +29,11 @@ class IHLBuffer : public Aquamarine::IBuffer {
struct {
CHyprSignalListener backendRelease;
+ CHyprSignalListener backendRelease2; // for explicit ds
} hlEvents;
private:
- int nLocks = 0;
-
- WP<CWLSurfaceResource> unlockSurface;
+ int nLocks = 0;
};
// for ref-counting. Releases in ~dtor
@@ -44,7 +43,8 @@ class CHLBufferReference {
CHLBufferReference(SP<IHLBuffer> buffer, SP<CWLSurfaceResource> surface);
~CHLBufferReference();
- WP<IHLBuffer> buffer;
+ WP<IHLBuffer> buffer;
+ SP<CSyncReleaser> releaser;
private:
WP<CWLSurfaceResource> surface;
diff --git a/src/protocols/types/WLBuffer.cpp b/src/protocols/types/WLBuffer.cpp
index d34a867d..eb7d1fde 100644
--- a/src/protocols/types/WLBuffer.cpp
+++ b/src/protocols/types/WLBuffer.cpp
@@ -32,16 +32,6 @@ void CWLBufferResource::sendRelease() {
resource->sendRelease();
}
-void CWLBufferResource::sendReleaseWithSurface(SP<CWLSurfaceResource> surf) {
- sendRelease();
-
- if (!surf || !surf->syncobj)
- return;
-
- if (drmSyncobjTimelineSignal(g_pCompositor->m_iDRMFD, &surf->syncobj->releaseTimeline->timeline->handle, &surf->syncobj->releasePoint, 1))
- Debug::log(ERR, "sendReleaseWithSurface: drmSyncobjTimelineSignal failed");
-}
-
wl_resource* CWLBufferResource::getResource() {
return resource->resource();
}
diff --git a/src/protocols/types/WLBuffer.hpp b/src/protocols/types/WLBuffer.hpp
index 59512128..787abe1f 100644
--- a/src/protocols/types/WLBuffer.hpp
+++ b/src/protocols/types/WLBuffer.hpp
@@ -17,7 +17,6 @@ class CWLBufferResource {
bool good();
void sendRelease();
- void sendReleaseWithSurface(SP<CWLSurfaceResource>);
wl_resource* getResource();
WP<IHLBuffer> buffer;