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()
{
m_modeset = true;
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) {
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)) {
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)
{
m_modeset = true;
uint32_t connectorId = connector->id();
if (drmModeSetCrtc(gpu()->fd(), m_pipeline->crtc()->id(), m_buffer->framebufferId(), 0, 0, &connectorId, 1, mode->nativeMode()) == 0) {
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());
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::unordered_map<uint32_t /* object */, std::unordered_map<uint32_t /* property */, uint64_t /* value */>> m_properties;
bool m_cursorOnly = false;
bool m_modeset = false;
};
class DrmLegacyCommit : public DrmCommit
@ -102,6 +103,7 @@ public:
private:
DrmPipeline *const m_pipeline;
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_legacyPageflipPending = false;
if (m_output && activePending()) {
if (type == PageflipType::Normal) {
if (type == PageflipType::Modeset && !activePending()) {
return;
}
if (m_output) {
if (type == PageflipType::Normal || type == PageflipType::Modeset) {
m_output->pageFlipped(timestamp);
} else {
RenderLoopPrivate::get(m_output->renderLoop())->notifyVblank(timestamp);

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

Loading…
Cancel
Save