backends/drm: fix pageflip events getting lost when outputs get turned off

When a display gets turned off while a pageflip event was still pending, the pending
state gets changed immediately, without waiting for the pageflip event to arrive first.
When this happens, activePending() returns false, and so the pageflip event gets discarded.
This commit changes the logic to only check for activePending() when the pageflip is for a
modeset, avoiding that issue.

BUG: 476340
BUG: 476341
BUG: 476342
BUG: 437520
BUG: 475146
master
Xaver Hugl 11 months ago
parent d75d0daf3b
commit c1312a5551

@ -83,6 +83,7 @@ bool DrmAtomicCommit::commit()
bool DrmAtomicCommit::commitModeset() bool DrmAtomicCommit::commitModeset()
{ {
m_modeset = true;
return doCommit(DRM_MODE_ATOMIC_ALLOW_MODESET); return doCommit(DRM_MODE_ATOMIC_ALLOW_MODESET);
} }
@ -127,8 +128,14 @@ void DrmAtomicCommit::pageFlipped(std::chrono::nanoseconds timestamp) const
for (const auto &[plane, buffer] : m_buffers) { for (const auto &[plane, buffer] : m_buffers) {
plane->setCurrentBuffer(buffer); plane->setCurrentBuffer(buffer);
} }
DrmPipeline::PageflipType type = DrmPipeline::PageflipType::Normal;
if (m_modeset) {
type = DrmPipeline::PageflipType::Modeset;
} else if (m_cursorOnly) {
type = DrmPipeline::PageflipType::CursorOnly;
}
for (const auto pipeline : std::as_const(m_pipelines)) { for (const auto pipeline : std::as_const(m_pipelines)) {
pipeline->pageFlipped(timestamp, m_cursorOnly ? DrmPipeline::PageflipType::CursorOnly : DrmPipeline::PageflipType::Normal); pipeline->pageFlipped(timestamp, type);
} }
} }
@ -190,6 +197,7 @@ DrmLegacyCommit::DrmLegacyCommit(DrmPipeline *pipeline, const std::shared_ptr<Dr
bool DrmLegacyCommit::doModeset(DrmConnector *connector, DrmConnectorMode *mode) bool DrmLegacyCommit::doModeset(DrmConnector *connector, DrmConnectorMode *mode)
{ {
m_modeset = true;
uint32_t connectorId = connector->id(); uint32_t connectorId = connector->id();
if (drmModeSetCrtc(gpu()->fd(), m_pipeline->crtc()->id(), m_buffer->framebufferId(), 0, 0, &connectorId, 1, mode->nativeMode()) == 0) { if (drmModeSetCrtc(gpu()->fd(), m_pipeline->crtc()->id(), m_buffer->framebufferId(), 0, 0, &connectorId, 1, mode->nativeMode()) == 0) {
m_pipeline->crtc()->setCurrent(m_buffer); m_pipeline->crtc()->setCurrent(m_buffer);
@ -208,6 +216,6 @@ void DrmLegacyCommit::pageFlipped(std::chrono::nanoseconds timestamp) const
{ {
Q_ASSERT(QThread::currentThread() == QApplication::instance()->thread()); Q_ASSERT(QThread::currentThread() == QApplication::instance()->thread());
m_pipeline->crtc()->setCurrent(m_buffer); m_pipeline->crtc()->setCurrent(m_buffer);
m_pipeline->pageFlipped(timestamp, DrmPipeline::PageflipType::Normal); m_pipeline->pageFlipped(timestamp, m_modeset ? DrmPipeline::PageflipType::Modeset : DrmPipeline::PageflipType::Normal);
} }
} }

@ -88,6 +88,7 @@ private:
std::optional<bool> m_vrr; std::optional<bool> m_vrr;
std::unordered_map<uint32_t /* object */, std::unordered_map<uint32_t /* property */, uint64_t /* value */>> m_properties; std::unordered_map<uint32_t /* object */, std::unordered_map<uint32_t /* property */, uint64_t /* value */>> m_properties;
bool m_cursorOnly = false; bool m_cursorOnly = false;
bool m_modeset = false;
}; };
class DrmLegacyCommit : public DrmCommit class DrmLegacyCommit : public DrmCommit
@ -102,6 +103,7 @@ public:
private: private:
DrmPipeline *const m_pipeline; DrmPipeline *const m_pipeline;
const std::shared_ptr<DrmFramebuffer> m_buffer; const std::shared_ptr<DrmFramebuffer> m_buffer;
bool m_modeset = false;
}; };
} }

@ -424,8 +424,11 @@ void DrmPipeline::pageFlipped(std::chrono::nanoseconds timestamp, PageflipType t
{ {
m_commitThread->pageFlipped(timestamp); m_commitThread->pageFlipped(timestamp);
m_legacyPageflipPending = false; m_legacyPageflipPending = false;
if (m_output && activePending()) { if (type == PageflipType::Modeset && !activePending()) {
if (type == PageflipType::Normal) { return;
}
if (m_output) {
if (type == PageflipType::Normal || type == PageflipType::Modeset) {
m_output->pageFlipped(timestamp); m_output->pageFlipped(timestamp);
} else { } else {
RenderLoopPrivate::get(m_output->renderLoop())->notifyVblank(timestamp); RenderLoopPrivate::get(m_output->renderLoop())->notifyVblank(timestamp);

@ -85,7 +85,8 @@ public:
enum class PageflipType { enum class PageflipType {
Normal, Normal,
CursorOnly CursorOnly,
Modeset,
}; };
void pageFlipped(std::chrono::nanoseconds timestamp, PageflipType type); void pageFlipped(std::chrono::nanoseconds timestamp, PageflipType type);
bool pageflipsPending() const; bool pageflipsPending() const;

Loading…
Cancel
Save