drm: misc/atomic fixes

atomic: launches, but mode blobs are broken

fixed frame events being signaled too often
This commit is contained in:
Vaxry 2024-06-28 14:02:56 +02:00
parent 55ac96271f
commit 944b0465fa
6 changed files with 66 additions and 53 deletions

View file

@ -186,7 +186,13 @@ namespace Aquamarine {
bool test = false; bool test = false;
drmModeModeInfo modeInfo; drmModeModeInfo modeInfo;
void calculateMode(Hyprutils::Memory::CSharedPointer<SDRMConnector> connector); struct {
uint32_t gammaLut = 0;
uint32_t fbDamage = 0;
uint32_t modeBlob = 0;
} atomic;
void calculateMode(Hyprutils::Memory::CSharedPointer<SDRMConnector> connector);
}; };
struct SDRMConnector { struct SDRMConnector {
@ -198,7 +204,7 @@ namespace Aquamarine {
Hyprutils::Memory::CSharedPointer<SDRMCRTC> getCurrentCRTC(const drmModeConnector* connector); Hyprutils::Memory::CSharedPointer<SDRMCRTC> getCurrentCRTC(const drmModeConnector* connector);
drmModeModeInfo* getCurrentMode(); drmModeModeInfo* getCurrentMode();
void parseEDID(std::vector<uint8_t> data); void parseEDID(std::vector<uint8_t> data);
bool commitState(const SDRMConnectorCommitData& data); bool commitState(SDRMConnectorCommitData& data);
void applyCommit(const SDRMConnectorCommitData& data); void applyCommit(const SDRMConnectorCommitData& data);
void rollbackCommit(const SDRMConnectorCommitData& data); void rollbackCommit(const SDRMConnectorCommitData& data);
void onPresent(); void onPresent();
@ -222,14 +228,12 @@ namespace Aquamarine {
bool isPageFlipPending = false; bool isPageFlipPending = false;
SDRMPageFlip pendingPageFlip; SDRMPageFlip pendingPageFlip;
bool frameEventScheduled = false;
drmModeModeInfo fallbackModeInfo; drmModeModeInfo fallbackModeInfo;
struct { struct {
uint32_t modeID = 0; bool vrrEnabled = false;
uint32_t gammaLut = 0;
uint32_t fbDamage = 0;
bool vrrEnabled = false;
} atomic; } atomic;
union UDRMConnectorProps { union UDRMConnectorProps {
@ -256,8 +260,8 @@ namespace Aquamarine {
class IDRMImplementation { class IDRMImplementation {
public: public:
virtual bool commit(Hyprutils::Memory::CSharedPointer<SDRMConnector> connector, const SDRMConnectorCommitData& data) = 0; virtual bool commit(Hyprutils::Memory::CSharedPointer<SDRMConnector> connector, SDRMConnectorCommitData& data) = 0;
virtual bool reset(Hyprutils::Memory::CSharedPointer<SDRMConnector> connector) = 0; virtual bool reset(Hyprutils::Memory::CSharedPointer<SDRMConnector> connector) = 0;
// moving a cursor IIRC is almost instant on most hardware so we don't have to wait for a commit. // 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<SDRMConnector> connector) = 0; virtual bool moveCursor(Hyprutils::Memory::CSharedPointer<SDRMConnector> connector) = 0;

View file

@ -6,12 +6,12 @@ namespace Aquamarine {
class CDRMAtomicImpl : public IDRMImplementation { class CDRMAtomicImpl : public IDRMImplementation {
public: public:
CDRMAtomicImpl(Hyprutils::Memory::CSharedPointer<CDRMBackend> backend_); CDRMAtomicImpl(Hyprutils::Memory::CSharedPointer<CDRMBackend> backend_);
virtual bool commit(Hyprutils::Memory::CSharedPointer<SDRMConnector> connector, const SDRMConnectorCommitData& data); virtual bool commit(Hyprutils::Memory::CSharedPointer<SDRMConnector> connector, SDRMConnectorCommitData& data);
virtual bool reset(Hyprutils::Memory::CSharedPointer<SDRMConnector> connector); virtual bool reset(Hyprutils::Memory::CSharedPointer<SDRMConnector> connector);
virtual bool moveCursor(Hyprutils::Memory::CSharedPointer<SDRMConnector> connector); virtual bool moveCursor(Hyprutils::Memory::CSharedPointer<SDRMConnector> connector);
private: private:
bool prepareConnector(Hyprutils::Memory::CSharedPointer<SDRMConnector> connector, const SDRMConnectorCommitData& data); bool prepareConnector(Hyprutils::Memory::CSharedPointer<SDRMConnector> connector, SDRMConnectorCommitData& data);
Hyprutils::Memory::CWeakPointer<CDRMBackend> backend; Hyprutils::Memory::CWeakPointer<CDRMBackend> backend;
@ -23,13 +23,13 @@ namespace Aquamarine {
CDRMAtomicRequest(Hyprutils::Memory::CWeakPointer<CDRMBackend> backend); CDRMAtomicRequest(Hyprutils::Memory::CWeakPointer<CDRMBackend> backend);
~CDRMAtomicRequest(); ~CDRMAtomicRequest();
void addConnector(Hyprutils::Memory::CSharedPointer<SDRMConnector> connector, const SDRMConnectorCommitData& data); void addConnector(Hyprutils::Memory::CSharedPointer<SDRMConnector> connector, SDRMConnectorCommitData& data);
bool commit(uint32_t flagssss); bool commit(uint32_t flagssss);
void add(uint32_t id, uint32_t prop, uint64_t val); void add(uint32_t id, uint32_t prop, uint64_t val);
void planeProps(Hyprutils::Memory::CSharedPointer<SDRMPlane> plane, Hyprutils::Memory::CSharedPointer<CDRMFB> fb, uint32_t crtc, Hyprutils::Math::Vector2D pos); void planeProps(Hyprutils::Memory::CSharedPointer<SDRMPlane> plane, Hyprutils::Memory::CSharedPointer<CDRMFB> fb, uint32_t crtc, Hyprutils::Math::Vector2D pos);
void rollback(); void rollback(SDRMConnectorCommitData& data);
void apply(); void apply(SDRMConnectorCommitData& data);
bool failed = false; bool failed = false;

View file

@ -6,14 +6,14 @@ namespace Aquamarine {
class CDRMLegacyImpl : public IDRMImplementation { class CDRMLegacyImpl : public IDRMImplementation {
public: public:
CDRMLegacyImpl(Hyprutils::Memory::CSharedPointer<CDRMBackend> backend_); CDRMLegacyImpl(Hyprutils::Memory::CSharedPointer<CDRMBackend> backend_);
virtual bool commit(Hyprutils::Memory::CSharedPointer<SDRMConnector> connector, const SDRMConnectorCommitData& data); virtual bool commit(Hyprutils::Memory::CSharedPointer<SDRMConnector> connector, SDRMConnectorCommitData& data);
virtual bool reset(Hyprutils::Memory::CSharedPointer<SDRMConnector> connector); virtual bool reset(Hyprutils::Memory::CSharedPointer<SDRMConnector> connector);
virtual bool moveCursor(Hyprutils::Memory::CSharedPointer<SDRMConnector> connector); virtual bool moveCursor(Hyprutils::Memory::CSharedPointer<SDRMConnector> connector);
private: private:
bool commitInternal(Hyprutils::Memory::CSharedPointer<SDRMConnector> connector, const SDRMConnectorCommitData& data); bool commitInternal(Hyprutils::Memory::CSharedPointer<SDRMConnector> connector, SDRMConnectorCommitData& data);
bool testInternal(Hyprutils::Memory::CSharedPointer<SDRMConnector> connector, const SDRMConnectorCommitData& data); bool testInternal(Hyprutils::Memory::CSharedPointer<SDRMConnector> connector, SDRMConnectorCommitData& data);
Hyprutils::Memory::CWeakPointer<CDRMBackend> backend; Hyprutils::Memory::CWeakPointer<CDRMBackend> backend;
}; };

View file

@ -528,7 +528,7 @@ static void handlePF(int fd, unsigned seq, unsigned tv_sec, unsigned tv_usec, un
.flags = flags, .flags = flags,
}); });
if (BACKEND->sessionActive()) if (BACKEND->sessionActive() && !pageFlip->connector->frameEventScheduled)
pageFlip->connector->output->events.frame.emit(); pageFlip->connector->output->events.frame.emit();
} }
@ -902,7 +902,7 @@ void Aquamarine::SDRMConnector::disconnect() {
status = DRM_MODE_DISCONNECTED; 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); const bool ok = backend->impl->commit(self.lock(), data);
if (ok && !data.test) if (ok && !data.test)
@ -1102,10 +1102,17 @@ void Aquamarine::CDRMOutput::moveCursor(const Vector2D& coord) {
} }
void Aquamarine::CDRMOutput::scheduleFrame() { void Aquamarine::CDRMOutput::scheduleFrame() {
if (connector->isPageFlipPending) if (connector->isPageFlipPending || connector->frameEventScheduled)
return; 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() { Vector2D Aquamarine::CDRMOutput::cursorPlaneSize() {

View file

@ -67,7 +67,7 @@ void Aquamarine::CDRMAtomicRequest::planeProps(Hyprutils::Memory::CSharedPointer
add(plane->id, plane->props.crtc_y, (uint64_t)pos.y); add(plane->id, plane->props.crtc_y, (uint64_t)pos.y);
} }
void Aquamarine::CDRMAtomicRequest::addConnector(Hyprutils::Memory::CSharedPointer<SDRMConnector> connector, const SDRMConnectorCommitData& data) { void Aquamarine::CDRMAtomicRequest::addConnector(Hyprutils::Memory::CSharedPointer<SDRMConnector> connector, SDRMConnectorCommitData& data) {
const auto& STATE = connector->output->state->state(); const auto& STATE = connector->output->state->state();
const bool enable = STATE.enabled && data.mainFB; 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)) 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->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); add(connector->crtc->id, connector->crtc->props.active, enable);
if (enable) { if (enable) {
@ -98,7 +98,7 @@ void Aquamarine::CDRMAtomicRequest::addConnector(Hyprutils::Memory::CSharedPoint
planeProps(connector->crtc->primary, data.mainFB, connector->crtc->id, {}); planeProps(connector->crtc->primary, data.mainFB, connector->crtc->id, {});
if (connector->crtc->primary->props.fb_damage_clips) 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->crtc->cursor) {
if (!connector->output->cursorVisible) if (!connector->output->cursorVisible)
@ -169,38 +169,44 @@ void Aquamarine::CDRMAtomicRequest::rollbackBlob(uint32_t* current, uint32_t nex
destroyBlob(next); destroyBlob(next);
} }
void Aquamarine::CDRMAtomicRequest::rollback() { void Aquamarine::CDRMAtomicRequest::rollback(SDRMConnectorCommitData& data) {
if (!conn)
return;
conn->crtc->atomic.ownModeID = true; conn->crtc->atomic.ownModeID = true;
rollbackBlob(&conn->crtc->atomic.modeID, conn->atomic.modeID); rollbackBlob(&conn->crtc->atomic.modeID, data.atomic.modeBlob);
// TODO: gamma // TODO: gamma
//rollbackBlob(&conn->crtc->atomic.gammaLut, conn->atomic.gammaLut); //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) if (!conn->crtc->atomic.ownModeID)
conn->crtc->atomic.modeID = 0; conn->crtc->atomic.modeID = 0;
conn->crtc->atomic.ownModeID = true; conn->crtc->atomic.ownModeID = true;
commitBlob(&conn->crtc->atomic.modeID, conn->atomic.modeID); commitBlob(&conn->crtc->atomic.modeID, data.atomic.modeBlob);
// TODO: gamma // TODO: gamma
//commitBlob(&conn->crtc->atomic.gammaLut, conn->atomic.gammaLut); //commitBlob(&conn->crtc->atomic.gammaLut, conn->atomic.gammaLut);
destroyBlob(conn->atomic.fbDamage); destroyBlob(data.atomic.fbDamage);
} }
Aquamarine::CDRMAtomicImpl::CDRMAtomicImpl(Hyprutils::Memory::CSharedPointer<CDRMBackend> backend_) : backend(backend_) { Aquamarine::CDRMAtomicImpl::CDRMAtomicImpl(Hyprutils::Memory::CSharedPointer<CDRMBackend> backend_) : backend(backend_) {
; ;
} }
bool Aquamarine::CDRMAtomicImpl::prepareConnector(Hyprutils::Memory::CSharedPointer<SDRMConnector> connector, const SDRMConnectorCommitData& data) { bool Aquamarine::CDRMAtomicImpl::prepareConnector(Hyprutils::Memory::CSharedPointer<SDRMConnector> connector, SDRMConnectorCommitData& data) {
const auto& STATE = connector->output->state->state(); const auto& STATE = connector->output->state->state();
const bool enable = STATE.enabled; const bool enable = STATE.enabled;
if (data.modeset) { if (data.modeset) {
if (!enable) if (!enable)
connector->atomic.modeID = 0; data.atomic.modeBlob = 0;
else { 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"); connector->backend->backend->log(AQ_LOG_ERROR, "atomic drm: failed to create a modeset blob");
return false; 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.committed & COutputState::AQ_OUTPUT_STATE_DAMAGE && connector->crtc->primary->props.fb_damage_clips) {
if (STATE.damage.empty()) if (STATE.damage.empty())
connector->atomic.fbDamage = 0; data.atomic.fbDamage = 0;
else { else {
std::vector<pixman_box32_t> rects = STATE.damage.getRects(); std::vector<pixman_box32_t> 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"); connector->backend->backend->log(AQ_LOG_ERROR, "atomic drm: failed to create a damage blob");
return false; return false;
} }
@ -224,7 +230,7 @@ bool Aquamarine::CDRMAtomicImpl::prepareConnector(Hyprutils::Memory::CSharedPoin
return true; return true;
} }
bool Aquamarine::CDRMAtomicImpl::commit(Hyprutils::Memory::CSharedPointer<SDRMConnector> connector, const SDRMConnectorCommitData& data) { bool Aquamarine::CDRMAtomicImpl::commit(Hyprutils::Memory::CSharedPointer<SDRMConnector> connector, SDRMConnectorCommitData& data) {
if (!prepareConnector(connector, data)) if (!prepareConnector(connector, data))
return false; return false;
@ -242,10 +248,11 @@ bool Aquamarine::CDRMAtomicImpl::commit(Hyprutils::Memory::CSharedPointer<SDRMCo
const bool ok = request.commit(flags); const bool ok = request.commit(flags);
if (ok) if (ok) {
request.apply(); request.apply(data);
else connector->isPageFlipPending = true;
request.rollback(); } else
request.rollback(data);
return ok; return ok;
} }
@ -273,11 +280,8 @@ bool Aquamarine::CDRMAtomicImpl::moveCursor(Hyprutils::Memory::CSharedPointer<SD
if (!connector->output->cursorVisible || !connector->output->state->state().enabled || !connector->crtc || !connector->crtc->cursor) if (!connector->output->cursorVisible || !connector->output->state->state().enabled || !connector->crtc || !connector->crtc->cursor)
return true; return true;
CDRMAtomicRequest request(backend); connector->output->needsFrame = true;
connector->output->scheduleFrame();
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);
return true; return true;
} }

View file

@ -14,18 +14,16 @@ Aquamarine::CDRMLegacyImpl::CDRMLegacyImpl(Hyprutils::Memory::CSharedPointer<CDR
} }
bool Aquamarine::CDRMLegacyImpl::moveCursor(Hyprutils::Memory::CSharedPointer<SDRMConnector> connector) { bool Aquamarine::CDRMLegacyImpl::moveCursor(Hyprutils::Memory::CSharedPointer<SDRMConnector> connector) {
Vector2D cursorPos = connector->output->cursorPos; if (!connector->output->cursorVisible || !connector->output->state->state().enabled || !connector->crtc || !connector->crtc->cursor)
if (int ret2 = drmModeMoveCursor(connector->backend->gpu->fd, connector->crtc->id, cursorPos.x, cursorPos.y)) { return true;
connector->backend->backend->log(AQ_LOG_ERROR, std::format("legacy drm: drmModeMoveCursor failed: {}", strerror(-ret2)));
return false;
}
connector->backend->backend->log(AQ_LOG_DEBUG, "legacy drm: cursor move"); connector->output->needsFrame = true;
connector->output->scheduleFrame();
return true; return true;
} }
bool Aquamarine::CDRMLegacyImpl::commitInternal(Hyprutils::Memory::CSharedPointer<SDRMConnector> connector, const SDRMConnectorCommitData& data) { bool Aquamarine::CDRMLegacyImpl::commitInternal(Hyprutils::Memory::CSharedPointer<SDRMConnector> connector, SDRMConnectorCommitData& data) {
const auto& STATE = connector->output->state->state(); const auto& STATE = connector->output->state->state();
SP<CDRMFB> mainFB; SP<CDRMFB> mainFB;
bool enable = STATE.enabled; bool enable = STATE.enabled;
@ -141,11 +139,11 @@ bool Aquamarine::CDRMLegacyImpl::commitInternal(Hyprutils::Memory::CSharedPointe
return true; return true;
} }
bool Aquamarine::CDRMLegacyImpl::testInternal(Hyprutils::Memory::CSharedPointer<SDRMConnector> connector, const SDRMConnectorCommitData& data) { bool Aquamarine::CDRMLegacyImpl::testInternal(Hyprutils::Memory::CSharedPointer<SDRMConnector> connector, SDRMConnectorCommitData& data) {
return true; // TODO: lol return true; // TODO: lol
} }
bool Aquamarine::CDRMLegacyImpl::commit(Hyprutils::Memory::CSharedPointer<SDRMConnector> connector, const SDRMConnectorCommitData& data) { bool Aquamarine::CDRMLegacyImpl::commit(Hyprutils::Memory::CSharedPointer<SDRMConnector> connector, SDRMConnectorCommitData& data) {
if (!testInternal(connector, data)) if (!testInternal(connector, data))
return false; return false;