renderer: Explicit sync fixes (#7151)
Enables explicit sync by default for most platforms `misc:no_direct_scanout` -> `render:direct_scanout`
This commit is contained in:
parent
0e86808e59
commit
640d161851
24 changed files with 378 additions and 165 deletions
|
|
@ -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");
|
||||
surface->pending.rejected = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if ((acquireTimeline || releaseTimeline) && !surface->pending.texture) {
|
||||
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)
|
||||
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 (!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();
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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_) {
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,7 +17,6 @@ class CWLBufferResource {
|
|||
|
||||
bool good();
|
||||
void sendRelease();
|
||||
void sendReleaseWithSurface(SP<CWLSurfaceResource>);
|
||||
wl_resource* getResource();
|
||||
|
||||
WP<IHLBuffer> buffer;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue