From b50d6d487befe0e1980d3b0ee41966ced8883127 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Gr=C3=A4=C3=9Flin?= Date: Tue, 28 Apr 2015 08:16:07 +0200 Subject: [PATCH] Add modelines to OutputInterfaces in DrmBackend Each available mode on the connector is added to the KWayland::Server::OutputInterface for the DrmOutput. The logic to calculate the refreshRate is highly inspired from Weston's implementation in compositor-drm.c. --- drm_backend.cpp | 46 +++++++++++++++++++++++++++++++++++++++++++++- drm_backend.h | 1 + 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/drm_backend.cpp b/drm_backend.cpp index 8c3ccedbdd..a55eecb43d 100644 --- a/drm_backend.cpp +++ b/drm_backend.cpp @@ -640,10 +640,54 @@ void DrmOutput::init(drmModeConnector *connector) } m_waylandOutput->setPhysicalSize(physicalSize); - m_waylandOutput->addMode(size()); + // read in mode information + for (int i = 0; i < connector->count_modes; ++i) { + auto *m = &connector->modes[i]; + KWayland::Server::OutputInterface::ModeFlags flags; + if (isCurrentMode(m)) { + flags |= KWayland::Server::OutputInterface::ModeFlag::Current; + } + if (m->type & DRM_MODE_TYPE_PREFERRED) { + flags |= KWayland::Server::OutputInterface::ModeFlag::Preferred; + } + + // Calculate higher precision (mHz) refresh rate + // logic based on Weston, see compositor-drm.c + quint64 refreshRate = (m->clock * 1000000LL / m->htotal + m->vtotal / 2) / m->vtotal; + if (m->flags & DRM_MODE_FLAG_INTERLACE) { + refreshRate *= 2; + } + if (m->flags & DRM_MODE_FLAG_DBLSCAN) { + refreshRate /= 2; + } + if (m->vscan > 1) { + refreshRate /= m->vscan; + } + m_waylandOutput->addMode(QSize(m->hdisplay, m->vdisplay), flags, refreshRate); + } + m_waylandOutput->create(); } +bool DrmOutput::isCurrentMode(const drmModeModeInfo *mode) const +{ + return mode->clock == m_mode.clock + && mode->hdisplay == m_mode.hdisplay + && mode->hsync_start == m_mode.hsync_start + && mode->hsync_end == m_mode.hsync_end + && mode->htotal == m_mode.htotal + && mode->hskew == m_mode.hskew + && mode->vdisplay == m_mode.vdisplay + && mode->vsync_start == m_mode.vsync_start + && mode->vsync_end == m_mode.vsync_end + && mode->vtotal == m_mode.vtotal + && mode->vscan == m_mode.vscan + && mode->vrefresh == m_mode.vrefresh + && mode->flags == m_mode.flags + && mode->type == m_mode.type + && qstrcmp(mode->name, m_mode.name) == 0; +} + void DrmOutput::blank() { if (!m_blackBuffer) { diff --git a/drm_backend.h b/drm_backend.h index 04260d032e..28c6952a30 100644 --- a/drm_backend.h +++ b/drm_backend.h @@ -135,6 +135,7 @@ private: void cleanupBlackBuffer(); bool setMode(DrmBuffer *buffer); void initEdid(drmModeConnector *connector); + bool isCurrentMode(const drmModeModeInfo *mode) const; DrmBackend *m_backend; QPoint m_globalPos;