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

View file

@ -6,12 +6,12 @@ namespace Aquamarine {
class CDRMAtomicImpl : public IDRMImplementation {
public:
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 moveCursor(Hyprutils::Memory::CSharedPointer<SDRMConnector> connector);
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;
@ -23,13 +23,13 @@ namespace Aquamarine {
CDRMAtomicRequest(Hyprutils::Memory::CWeakPointer<CDRMBackend> backend);
~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);
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 rollback();
void apply();
void rollback(SDRMConnectorCommitData& data);
void apply(SDRMConnectorCommitData& data);
bool failed = false;

View file

@ -6,14 +6,14 @@ namespace Aquamarine {
class CDRMLegacyImpl : public IDRMImplementation {
public:
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 moveCursor(Hyprutils::Memory::CSharedPointer<SDRMConnector> connector);
private:
bool commitInternal(Hyprutils::Memory::CSharedPointer<SDRMConnector> connector, const SDRMConnectorCommitData& data);
bool testInternal(Hyprutils::Memory::CSharedPointer<SDRMConnector> connector, const SDRMConnectorCommitData& data);
bool commitInternal(Hyprutils::Memory::CSharedPointer<SDRMConnector> connector, SDRMConnectorCommitData& data);
bool testInternal(Hyprutils::Memory::CSharedPointer<SDRMConnector> connector, SDRMConnectorCommitData& data);
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,
});
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() {

View file

@ -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<SDRMConnector> connector, const SDRMConnectorCommitData& data) {
void Aquamarine::CDRMAtomicRequest::addConnector(Hyprutils::Memory::CSharedPointer<SDRMConnector> 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<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 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<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");
return false;
}
@ -224,7 +230,7 @@ bool Aquamarine::CDRMAtomicImpl::prepareConnector(Hyprutils::Memory::CSharedPoin
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))
return false;
@ -242,10 +248,11 @@ bool Aquamarine::CDRMAtomicImpl::commit(Hyprutils::Memory::CSharedPointer<SDRMCo
const bool ok = request.commit(flags);
if (ok)
request.apply();
else
request.rollback();
if (ok) {
request.apply(data);
connector->isPageFlipPending = true;
} else
request.rollback(data);
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)
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;
}

View file

@ -14,18 +14,16 @@ Aquamarine::CDRMLegacyImpl::CDRMLegacyImpl(Hyprutils::Memory::CSharedPointer<CDR
}
bool Aquamarine::CDRMLegacyImpl::moveCursor(Hyprutils::Memory::CSharedPointer<SDRMConnector> 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<SDRMConnector> connector, const SDRMConnectorCommitData& data) {
bool Aquamarine::CDRMLegacyImpl::commitInternal(Hyprutils::Memory::CSharedPointer<SDRMConnector> connector, SDRMConnectorCommitData& data) {
const auto& STATE = connector->output->state->state();
SP<CDRMFB> 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<SDRMConnector> connector, const SDRMConnectorCommitData& data) {
bool Aquamarine::CDRMLegacyImpl::testInternal(Hyprutils::Memory::CSharedPointer<SDRMConnector> connector, SDRMConnectorCommitData& data) {
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))
return false;