diff options
| author | Vaxry <43317083+vaxerski@users.noreply.github.com> | 2024-08-06 14:52:19 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-08-06 15:52:19 +0200 |
| commit | 640d1618519d42dd592f7af5e9984ad52eb8b820 (patch) | |
| tree | f44a5b58822eb60e7fd2dfc3e18af9bba0ab2cb0 /src/protocols | |
| parent | 0e86808e5912823f1c6bea1b6d5fcae297fc9f57 (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.cpp | 47 | ||||
| -rw-r--r-- | src/protocols/DRMSyncobj.hpp | 11 | ||||
| -rw-r--r-- | src/protocols/core/Compositor.cpp | 17 | ||||
| -rw-r--r-- | src/protocols/core/Compositor.hpp | 5 | ||||
| -rw-r--r-- | src/protocols/types/Buffer.cpp | 25 | ||||
| -rw-r--r-- | src/protocols/types/Buffer.hpp | 12 | ||||
| -rw-r--r-- | src/protocols/types/WLBuffer.cpp | 10 | ||||
| -rw-r--r-- | src/protocols/types/WLBuffer.hpp | 1 |
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; |
