From 944b0465fafaf83fa459a14a7e99adf5c4b03fa6 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Fri, 28 Jun 2024 14:02:56 +0200 Subject: [PATCH] drm: misc/atomic fixes atomic: launches, but mode blobs are broken fixed frame events being signaled too often --- include/aquamarine/backend/DRM.hpp | 20 +++++---- include/aquamarine/backend/drm/Atomic.hpp | 10 ++--- include/aquamarine/backend/drm/Legacy.hpp | 6 +-- src/backend/drm/DRM.cpp | 15 +++++-- src/backend/drm/impl/Atomic.cpp | 52 ++++++++++++----------- src/backend/drm/impl/Legacy.cpp | 16 +++---- 6 files changed, 66 insertions(+), 53 deletions(-) diff --git a/include/aquamarine/backend/DRM.hpp b/include/aquamarine/backend/DRM.hpp index a396e37..92f20c7 100644 --- a/include/aquamarine/backend/DRM.hpp +++ b/include/aquamarine/backend/DRM.hpp @@ -186,7 +186,13 @@ namespace Aquamarine { bool test = false; drmModeModeInfo modeInfo; - void calculateMode(Hyprutils::Memory::CSharedPointer connector); + struct { + uint32_t gammaLut = 0; + uint32_t fbDamage = 0; + uint32_t modeBlob = 0; + } atomic; + + void calculateMode(Hyprutils::Memory::CSharedPointer connector); }; struct SDRMConnector { @@ -198,7 +204,7 @@ namespace Aquamarine { Hyprutils::Memory::CSharedPointer getCurrentCRTC(const drmModeConnector* connector); drmModeModeInfo* getCurrentMode(); void parseEDID(std::vector data); - bool commitState(const SDRMConnectorCommitData& data); + bool commitState(SDRMConnectorCommitData& data); void applyCommit(const SDRMConnectorCommitData& data); void rollbackCommit(const SDRMConnectorCommitData& data); void onPresent(); @@ -222,14 +228,12 @@ namespace Aquamarine { bool isPageFlipPending = false; SDRMPageFlip pendingPageFlip; + bool frameEventScheduled = false; drmModeModeInfo fallbackModeInfo; struct { - uint32_t modeID = 0; - uint32_t gammaLut = 0; - uint32_t fbDamage = 0; - bool vrrEnabled = false; + bool vrrEnabled = false; } atomic; union UDRMConnectorProps { @@ -256,8 +260,8 @@ namespace Aquamarine { class IDRMImplementation { public: - virtual bool commit(Hyprutils::Memory::CSharedPointer connector, const SDRMConnectorCommitData& data) = 0; - virtual bool reset(Hyprutils::Memory::CSharedPointer connector) = 0; + virtual bool commit(Hyprutils::Memory::CSharedPointer connector, SDRMConnectorCommitData& data) = 0; + virtual bool reset(Hyprutils::Memory::CSharedPointer connector) = 0; // moving a cursor IIRC is almost instant on most hardware so we don't have to wait for a commit. virtual bool moveCursor(Hyprutils::Memory::CSharedPointer connector) = 0; diff --git a/include/aquamarine/backend/drm/Atomic.hpp b/include/aquamarine/backend/drm/Atomic.hpp index 0294de8..ac1a047 100644 --- a/include/aquamarine/backend/drm/Atomic.hpp +++ b/include/aquamarine/backend/drm/Atomic.hpp @@ -6,12 +6,12 @@ namespace Aquamarine { class CDRMAtomicImpl : public IDRMImplementation { public: CDRMAtomicImpl(Hyprutils::Memory::CSharedPointer backend_); - virtual bool commit(Hyprutils::Memory::CSharedPointer connector, const SDRMConnectorCommitData& data); + virtual bool commit(Hyprutils::Memory::CSharedPointer connector, SDRMConnectorCommitData& data); virtual bool reset(Hyprutils::Memory::CSharedPointer connector); virtual bool moveCursor(Hyprutils::Memory::CSharedPointer connector); private: - bool prepareConnector(Hyprutils::Memory::CSharedPointer connector, const SDRMConnectorCommitData& data); + bool prepareConnector(Hyprutils::Memory::CSharedPointer connector, SDRMConnectorCommitData& data); Hyprutils::Memory::CWeakPointer backend; @@ -23,13 +23,13 @@ namespace Aquamarine { CDRMAtomicRequest(Hyprutils::Memory::CWeakPointer backend); ~CDRMAtomicRequest(); - void addConnector(Hyprutils::Memory::CSharedPointer connector, const SDRMConnectorCommitData& data); + void addConnector(Hyprutils::Memory::CSharedPointer connector, SDRMConnectorCommitData& data); bool commit(uint32_t flagssss); void add(uint32_t id, uint32_t prop, uint64_t val); void planeProps(Hyprutils::Memory::CSharedPointer plane, Hyprutils::Memory::CSharedPointer fb, uint32_t crtc, Hyprutils::Math::Vector2D pos); - void rollback(); - void apply(); + void rollback(SDRMConnectorCommitData& data); + void apply(SDRMConnectorCommitData& data); bool failed = false; diff --git a/include/aquamarine/backend/drm/Legacy.hpp b/include/aquamarine/backend/drm/Legacy.hpp index 275fb3f..fd0a895 100644 --- a/include/aquamarine/backend/drm/Legacy.hpp +++ b/include/aquamarine/backend/drm/Legacy.hpp @@ -6,14 +6,14 @@ namespace Aquamarine { class CDRMLegacyImpl : public IDRMImplementation { public: CDRMLegacyImpl(Hyprutils::Memory::CSharedPointer backend_); - virtual bool commit(Hyprutils::Memory::CSharedPointer connector, const SDRMConnectorCommitData& data); + virtual bool commit(Hyprutils::Memory::CSharedPointer connector, SDRMConnectorCommitData& data); virtual bool reset(Hyprutils::Memory::CSharedPointer connector); virtual bool moveCursor(Hyprutils::Memory::CSharedPointer connector); private: - bool commitInternal(Hyprutils::Memory::CSharedPointer connector, const SDRMConnectorCommitData& data); - bool testInternal(Hyprutils::Memory::CSharedPointer connector, const SDRMConnectorCommitData& data); + bool commitInternal(Hyprutils::Memory::CSharedPointer connector, SDRMConnectorCommitData& data); + bool testInternal(Hyprutils::Memory::CSharedPointer connector, SDRMConnectorCommitData& data); Hyprutils::Memory::CWeakPointer backend; }; diff --git a/src/backend/drm/DRM.cpp b/src/backend/drm/DRM.cpp index e058a11..53ef5bf 100644 --- a/src/backend/drm/DRM.cpp +++ b/src/backend/drm/DRM.cpp @@ -528,7 +528,7 @@ static void handlePF(int fd, unsigned seq, unsigned tv_sec, unsigned tv_usec, un .flags = flags, }); - if (BACKEND->sessionActive()) + if (BACKEND->sessionActive() && !pageFlip->connector->frameEventScheduled) pageFlip->connector->output->events.frame.emit(); } @@ -902,7 +902,7 @@ void Aquamarine::SDRMConnector::disconnect() { status = DRM_MODE_DISCONNECTED; } -bool Aquamarine::SDRMConnector::commitState(const SDRMConnectorCommitData& data) { +bool Aquamarine::SDRMConnector::commitState(SDRMConnectorCommitData& data) { const bool ok = backend->impl->commit(self.lock(), data); if (ok && !data.test) @@ -1102,10 +1102,17 @@ void Aquamarine::CDRMOutput::moveCursor(const Vector2D& coord) { } void Aquamarine::CDRMOutput::scheduleFrame() { - if (connector->isPageFlipPending) + if (connector->isPageFlipPending || connector->frameEventScheduled) return; - backend->idleCallbacks.emplace_back([this]() { events.frame.emit(); }); + connector->frameEventScheduled = true; + + backend->idleCallbacks.emplace_back([this]() { + connector->frameEventScheduled = false; + if (connector->isPageFlipPending) + return; + events.frame.emit(); + }); } Vector2D Aquamarine::CDRMOutput::cursorPlaneSize() { diff --git a/src/backend/drm/impl/Atomic.cpp b/src/backend/drm/impl/Atomic.cpp index a50075c..47a8217 100644 --- a/src/backend/drm/impl/Atomic.cpp +++ b/src/backend/drm/impl/Atomic.cpp @@ -67,7 +67,7 @@ void Aquamarine::CDRMAtomicRequest::planeProps(Hyprutils::Memory::CSharedPointer add(plane->id, plane->props.crtc_y, (uint64_t)pos.y); } -void Aquamarine::CDRMAtomicRequest::addConnector(Hyprutils::Memory::CSharedPointer connector, const SDRMConnectorCommitData& data) { +void Aquamarine::CDRMAtomicRequest::addConnector(Hyprutils::Memory::CSharedPointer connector, SDRMConnectorCommitData& data) { const auto& STATE = connector->output->state->state(); const bool enable = STATE.enabled && data.mainFB; @@ -87,7 +87,7 @@ void Aquamarine::CDRMAtomicRequest::addConnector(Hyprutils::Memory::CSharedPoint if (data.modeset && enable && connector->props.max_bpc && connector->maxBpcBounds.at(1)) add(connector->id, connector->props.max_bpc, 8); // FIXME: this isnt always 8 - add(connector->crtc->id, connector->crtc->props.mode_id, connector->atomic.modeID); + // add(connector->crtc->id, connector->crtc->props.mode_id, data.atomic.modeBlob); add(connector->crtc->id, connector->crtc->props.active, enable); if (enable) { @@ -98,7 +98,7 @@ void Aquamarine::CDRMAtomicRequest::addConnector(Hyprutils::Memory::CSharedPoint planeProps(connector->crtc->primary, data.mainFB, connector->crtc->id, {}); if (connector->crtc->primary->props.fb_damage_clips) - add(connector->crtc->primary->id, connector->crtc->primary->props.fb_damage_clips, connector->atomic.fbDamage); + add(connector->crtc->primary->id, connector->crtc->primary->props.fb_damage_clips, data.atomic.fbDamage); if (connector->crtc->cursor) { if (!connector->output->cursorVisible) @@ -169,38 +169,44 @@ void Aquamarine::CDRMAtomicRequest::rollbackBlob(uint32_t* current, uint32_t nex destroyBlob(next); } -void Aquamarine::CDRMAtomicRequest::rollback() { +void Aquamarine::CDRMAtomicRequest::rollback(SDRMConnectorCommitData& data) { + if (!conn) + return; + conn->crtc->atomic.ownModeID = true; - rollbackBlob(&conn->crtc->atomic.modeID, conn->atomic.modeID); + rollbackBlob(&conn->crtc->atomic.modeID, data.atomic.modeBlob); // TODO: gamma //rollbackBlob(&conn->crtc->atomic.gammaLut, conn->atomic.gammaLut); - destroyBlob(conn->atomic.fbDamage); + destroyBlob(data.atomic.fbDamage); } -void Aquamarine::CDRMAtomicRequest::apply() { +void Aquamarine::CDRMAtomicRequest::apply(SDRMConnectorCommitData& data) { + if (!conn) + return; + if (!conn->crtc->atomic.ownModeID) conn->crtc->atomic.modeID = 0; conn->crtc->atomic.ownModeID = true; - commitBlob(&conn->crtc->atomic.modeID, conn->atomic.modeID); + commitBlob(&conn->crtc->atomic.modeID, data.atomic.modeBlob); // TODO: gamma //commitBlob(&conn->crtc->atomic.gammaLut, conn->atomic.gammaLut); - destroyBlob(conn->atomic.fbDamage); + destroyBlob(data.atomic.fbDamage); } Aquamarine::CDRMAtomicImpl::CDRMAtomicImpl(Hyprutils::Memory::CSharedPointer backend_) : backend(backend_) { ; } -bool Aquamarine::CDRMAtomicImpl::prepareConnector(Hyprutils::Memory::CSharedPointer connector, const SDRMConnectorCommitData& data) { +bool Aquamarine::CDRMAtomicImpl::prepareConnector(Hyprutils::Memory::CSharedPointer connector, SDRMConnectorCommitData& data) { const auto& STATE = connector->output->state->state(); const bool enable = STATE.enabled; if (data.modeset) { if (!enable) - connector->atomic.modeID = 0; + data.atomic.modeBlob = 0; else { - if (drmModeCreatePropertyBlob(connector->backend->gpu->fd, (drmModeModeInfo*)&data.modeInfo, sizeof(drmModeModeInfo), &connector->atomic.modeID)) { + if (drmModeCreatePropertyBlob(connector->backend->gpu->fd, (drmModeModeInfo*)&data.modeInfo, sizeof(drmModeModeInfo), &data.atomic.modeBlob)) { connector->backend->backend->log(AQ_LOG_ERROR, "atomic drm: failed to create a modeset blob"); return false; } @@ -211,10 +217,10 @@ bool Aquamarine::CDRMAtomicImpl::prepareConnector(Hyprutils::Memory::CSharedPoin if (STATE.committed & COutputState::AQ_OUTPUT_STATE_DAMAGE && connector->crtc->primary->props.fb_damage_clips) { if (STATE.damage.empty()) - connector->atomic.fbDamage = 0; + data.atomic.fbDamage = 0; else { std::vector rects = STATE.damage.getRects(); - if (drmModeCreatePropertyBlob(connector->backend->gpu->fd, rects.data(), sizeof(pixman_box32_t) * rects.size(), &connector->atomic.fbDamage)) { + if (drmModeCreatePropertyBlob(connector->backend->gpu->fd, rects.data(), sizeof(pixman_box32_t) * rects.size(), &data.atomic.fbDamage)) { connector->backend->backend->log(AQ_LOG_ERROR, "atomic drm: failed to create a damage blob"); return false; } @@ -224,7 +230,7 @@ bool Aquamarine::CDRMAtomicImpl::prepareConnector(Hyprutils::Memory::CSharedPoin return true; } -bool Aquamarine::CDRMAtomicImpl::commit(Hyprutils::Memory::CSharedPointer connector, const SDRMConnectorCommitData& data) { +bool Aquamarine::CDRMAtomicImpl::commit(Hyprutils::Memory::CSharedPointer connector, SDRMConnectorCommitData& data) { if (!prepareConnector(connector, data)) return false; @@ -242,10 +248,11 @@ bool Aquamarine::CDRMAtomicImpl::commit(Hyprutils::Memory::CSharedPointerisPageFlipPending = true; + } else + request.rollback(data); return ok; } @@ -273,11 +280,8 @@ bool Aquamarine::CDRMAtomicImpl::moveCursor(Hyprutils::Memory::CSharedPointeroutput->cursorVisible || !connector->output->state->state().enabled || !connector->crtc || !connector->crtc->cursor) return true; - CDRMAtomicRequest request(backend); - - request.planeProps(connector->crtc->cursor, connector->crtc->cursor->front, connector->crtc->id, connector->output->cursorPos - connector->output->cursorHotspot); - - return request.commit(DRM_MODE_ATOMIC_NONBLOCK); + connector->output->needsFrame = true; + connector->output->scheduleFrame(); return true; } \ No newline at end of file diff --git a/src/backend/drm/impl/Legacy.cpp b/src/backend/drm/impl/Legacy.cpp index e76c68b..9732458 100644 --- a/src/backend/drm/impl/Legacy.cpp +++ b/src/backend/drm/impl/Legacy.cpp @@ -14,18 +14,16 @@ Aquamarine::CDRMLegacyImpl::CDRMLegacyImpl(Hyprutils::Memory::CSharedPointer connector) { - Vector2D cursorPos = connector->output->cursorPos; - if (int ret2 = drmModeMoveCursor(connector->backend->gpu->fd, connector->crtc->id, cursorPos.x, cursorPos.y)) { - connector->backend->backend->log(AQ_LOG_ERROR, std::format("legacy drm: drmModeMoveCursor failed: {}", strerror(-ret2))); - return false; - } + if (!connector->output->cursorVisible || !connector->output->state->state().enabled || !connector->crtc || !connector->crtc->cursor) + return true; - connector->backend->backend->log(AQ_LOG_DEBUG, "legacy drm: cursor move"); + connector->output->needsFrame = true; + connector->output->scheduleFrame(); return true; } -bool Aquamarine::CDRMLegacyImpl::commitInternal(Hyprutils::Memory::CSharedPointer connector, const SDRMConnectorCommitData& data) { +bool Aquamarine::CDRMLegacyImpl::commitInternal(Hyprutils::Memory::CSharedPointer connector, SDRMConnectorCommitData& data) { const auto& STATE = connector->output->state->state(); SP mainFB; bool enable = STATE.enabled; @@ -141,11 +139,11 @@ bool Aquamarine::CDRMLegacyImpl::commitInternal(Hyprutils::Memory::CSharedPointe return true; } -bool Aquamarine::CDRMLegacyImpl::testInternal(Hyprutils::Memory::CSharedPointer connector, const SDRMConnectorCommitData& data) { +bool Aquamarine::CDRMLegacyImpl::testInternal(Hyprutils::Memory::CSharedPointer connector, SDRMConnectorCommitData& data) { return true; // TODO: lol } -bool Aquamarine::CDRMLegacyImpl::commit(Hyprutils::Memory::CSharedPointer connector, const SDRMConnectorCommitData& data) { +bool Aquamarine::CDRMLegacyImpl::commit(Hyprutils::Memory::CSharedPointer connector, SDRMConnectorCommitData& data) { if (!testInternal(connector, data)) return false;