From e650eef323ef0dc13cc197f2c91c772277c102ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Gr=C3=A4=C3=9Flin?= Date: Fri, 17 Apr 2015 16:41:18 +0200 Subject: [PATCH] [drm] Find correct crtc/encoder/connector combination We need to verify that a given crtc is not used already for one of the created DrmOutputs. --- drm_backend.cpp | 54 +++++++++++++++++++++++++++++++++++++++++++++---- drm_backend.h | 2 ++ 2 files changed, 52 insertions(+), 4 deletions(-) diff --git a/drm_backend.cpp b/drm_backend.cpp index 98a675a8a8..93931772fa 100644 --- a/drm_backend.cpp +++ b/drm_backend.cpp @@ -231,16 +231,17 @@ void DrmBackend::queryResources() if (connector->connection != DRM_MODE_CONNECTED) { continue; } - ScopedDrmPointer<_drmModeEncoder, &drmModeFreeEncoder> encoder(drmModeGetEncoder(m_fd, connector->encoder_id)); - if (!encoder) { + bool crtcFound = false; + const quint32 crtcId = findCrtc(resources.data(), connector.data(), &crtcFound); + if (!crtcFound) { continue; } - ScopedDrmPointer<_drmModeCrtc, &drmModeFreeCrtc> crtc(drmModeGetCrtc(m_fd, encoder->crtc_id)); + ScopedDrmPointer<_drmModeCrtc, &drmModeFreeCrtc> crtc(drmModeGetCrtc(m_fd, crtcId)); if (!crtc) { continue; } DrmOutput *drmOutput = new DrmOutput(this); - drmOutput->m_crtcId = encoder->crtc_id; + drmOutput->m_crtcId = crtcId; drmOutput->m_mode = crtc->mode; drmOutput->m_connector = connector->connector_id; drmOutput->init(); @@ -249,6 +250,51 @@ void DrmBackend::queryResources() // TODO: install global space } +quint32 DrmBackend::findCrtc(drmModeRes *res, drmModeConnector *connector, bool *ok) +{ + if (ok) { + *ok = false; + } + ScopedDrmPointer<_drmModeEncoder, &drmModeFreeEncoder> encoder(drmModeGetEncoder(m_fd, connector->encoder_id)); + if (encoder) { + if (!crtcIsUsed(encoder->crtc_id)) { + if (ok) { + *ok = true; + } + return encoder->crtc_id; + } + } + // let's iterate over all encoders to find a suitable crtc + for (int i = 0; i < connector->count_encoders; ++i) { + ScopedDrmPointer<_drmModeEncoder, &drmModeFreeEncoder> encoder(drmModeGetEncoder(m_fd, connector->encoders[i])); + if (!encoder) { + continue; + } + for (int j = 0; j < res->count_crtcs; ++j) { + if (!(encoder->possible_crtcs & (1 << j))) { + continue; + } + if (!crtcIsUsed(res->crtcs[j])) { + if (ok) { + *ok = true; + } + return res->crtcs[j]; + } + } + } + return 0; +} + +bool DrmBackend::crtcIsUsed(quint32 crtc) +{ + auto it = std::find_if(m_outputs.constBegin(), m_outputs.constEnd(), + [crtc] (DrmOutput *o) { + return o->m_crtcId == crtc; + } + ); + return it != m_outputs.constEnd(); +} + void DrmBackend::present(DrmBuffer *buffer) { if (m_outputs.isEmpty()) { diff --git a/drm_backend.h b/drm_backend.h index bbb1c588e1..9e050666ad 100644 --- a/drm_backend.h +++ b/drm_backend.h @@ -78,6 +78,8 @@ private: void hideCursor(); void moveCursor(); void initCursor(); + quint32 findCrtc(drmModeRes *res, drmModeConnector *connector, bool *ok = nullptr); + bool crtcIsUsed(quint32 crtc); QScopedPointer m_udev; int m_fd = -1; int m_drmId = 0;