diff options
Diffstat (limited to 'src/platformsupport/kmsconvenience')
-rw-r--r-- | src/platformsupport/kmsconvenience/qkmsdevice.cpp | 117 | ||||
-rw-r--r-- | src/platformsupport/kmsconvenience/qkmsdevice_p.h | 17 |
2 files changed, 95 insertions, 39 deletions
diff --git a/src/platformsupport/kmsconvenience/qkmsdevice.cpp b/src/platformsupport/kmsconvenience/qkmsdevice.cpp index 6121faf362..92ba9fbcd9 100644 --- a/src/platformsupport/kmsconvenience/qkmsdevice.cpp +++ b/src/platformsupport/kmsconvenience/qkmsdevice.cpp @@ -176,6 +176,15 @@ static bool parseModeline(const QByteArray &text, drmModeModeInfoPtr mode) return true; } +static inline void assignPlane(QKmsOutput *output, QKmsPlane *plane) +{ + if (output->eglfs_plane) + output->eglfs_plane->activeCrtcId = 0; + + plane->activeCrtcId = output->crtc_id; + output->eglfs_plane = plane; +} + QPlatformScreen *QKmsDevice::createScreenForConnector(drmModeResPtr resources, drmModeConnectorPtr connector, ScreenInfo *vinfo) @@ -449,13 +458,16 @@ QPlatformScreen *QKmsDevice::createScreenForConnector(drmModeResPtr resources, #endif QString planeListStr; - for (const QKmsPlane &plane : qAsConst(m_planes)) { + for (QKmsPlane &plane : m_planes) { if (plane.possibleCrtcs & (1 << output.crtc_index)) { output.available_planes.append(plane); planeListStr.append(QString::number(plane.id)); planeListStr.append(QLatin1Char(' ')); - if (plane.type == QKmsPlane::PrimaryPlane) - output.eglfs_plane = (QKmsPlane*)&plane; + + // Choose the first primary plane that is not already assigned to + // another screen's associated crtc. + if (!output.eglfs_plane && plane.type == QKmsPlane::PrimaryPlane && !plane.activeCrtcId) + assignPlane(&output, &plane); } } qCDebug(qLcKmsDebug, "Output %s can use %d planes: %s", @@ -477,9 +489,11 @@ QPlatformScreen *QKmsDevice::createScreenForConnector(drmModeResPtr resources, qCDebug(qLcKmsDebug, "Forcing plane index %d, plane id %u (belongs to crtc id %u)", idx, plane->plane_id, plane->crtc_id); - for (const QKmsPlane &kmsplane : qAsConst(m_planes)) { - if (kmsplane.id == output.forced_plane_id) - output.eglfs_plane = (QKmsPlane*)&kmsplane; + for (QKmsPlane &kmsplane : m_planes) { + if (kmsplane.id == output.forced_plane_id) { + assignPlane(&output, &kmsplane); + break; + } } drmModeFreePlane(plane); @@ -490,8 +504,37 @@ QPlatformScreen *QKmsDevice::createScreenForConnector(drmModeResPtr resources, } } - if (output.eglfs_plane) - qCDebug(qLcKmsDebug, "Output eglfs plane is: %d", output.eglfs_plane->id); + // A more useful version: allows specifying "crtc_id,plane_id:crtc_id,plane_id:..." + // in order to allow overriding the plane used for a given crtc. + if (qEnvironmentVariableIsSet("QT_QPA_EGLFS_KMS_PLANES_FOR_CRTCS")) { + const QString val = qEnvironmentVariable("QT_QPA_EGLFS_KMS_PLANES_FOR_CRTCS"); + qCDebug(qLcKmsDebug, "crtc_id:plane_id override list: %s", qPrintable(val)); + const QStringList crtcPlanePairs = val.split(QLatin1Char(':')); + for (const QString &crtcPlanePair : crtcPlanePairs) { + const QStringList values = crtcPlanePair.split(QLatin1Char(',')); + if (values.count() == 2 && uint(values[0].toInt()) == output.crtc_id) { + uint planeId = values[1].toInt(); + for (QKmsPlane &kmsplane : m_planes) { + if (kmsplane.id == planeId) { + assignPlane(&output, &kmsplane); + break; + } + } + } + } + } + + if (output.eglfs_plane) { + qCDebug(qLcKmsDebug, "Chose plane %u for output %s (crtc id %u) (may not be applicable)", + output.eglfs_plane->id, connectorName.constData(), output.crtc_id); + } + +#if QT_CONFIG(drm_atomic) + if (hasAtomicSupport() && !output.eglfs_plane) { + qCDebug(qLcKmsDebug, "No plane associated with output %s (crtc id %u) and atomic modesetting is enabled. This is bad.", + connectorName.constData(), output.crtc_id); + } +#endif m_crtc_allocator |= (1 << output.crtc_index); @@ -538,10 +581,6 @@ QKmsDevice::QKmsDevice(QKmsScreenConfig *screenConfig, const QString &path) , m_path(path) , m_dri_fd(-1) , m_has_atomic_support(false) -#if QT_CONFIG(drm_atomic) - , m_atomic_request(nullptr) - , m_previous_request(nullptr) -#endif , m_crtc_allocator(0) { if (m_path.isEmpty()) { @@ -557,7 +596,7 @@ QKmsDevice::QKmsDevice(QKmsScreenConfig *screenConfig, const QString &path) QKmsDevice::~QKmsDevice() { #if QT_CONFIG(drm_atomic) - atomicReset(); + threadLocalAtomicReset(); #endif } @@ -897,39 +936,51 @@ bool QKmsDevice::hasAtomicSupport() } #if QT_CONFIG(drm_atomic) -drmModeAtomicReq * QKmsDevice::atomic_request() +drmModeAtomicReq *QKmsDevice::threadLocalAtomicRequest() { - if (!m_atomic_request && m_has_atomic_support) - m_atomic_request = drmModeAtomicAlloc(); + if (!m_has_atomic_support) + return nullptr; + + AtomicReqs &a(m_atomicReqs.localData()); + if (!a.request) + a.request = drmModeAtomicAlloc(); - return m_atomic_request; + return a.request; } -bool QKmsDevice::atomicCommit(void *user_data) +bool QKmsDevice::threadLocalAtomicCommit(void *user_data) { - if (m_atomic_request) { - int ret = drmModeAtomicCommit(m_dri_fd, m_atomic_request, - DRM_MODE_ATOMIC_NONBLOCK | DRM_MODE_PAGE_FLIP_EVENT | DRM_MODE_ATOMIC_ALLOW_MODESET, user_data); + if (!m_has_atomic_support) + return false; - if (ret) { - qWarning("Failed to commit atomic request (code=%d)", ret); - return false; - } + AtomicReqs &a(m_atomicReqs.localData()); + if (!a.request) + return false; - m_previous_request = m_atomic_request; - m_atomic_request = nullptr; + int ret = drmModeAtomicCommit(m_dri_fd, a.request, + DRM_MODE_ATOMIC_NONBLOCK | DRM_MODE_PAGE_FLIP_EVENT | DRM_MODE_ATOMIC_ALLOW_MODESET, + user_data); - return true; + if (ret) { + qWarning("Failed to commit atomic request (code=%d)", ret); + return false; } - return false; + a.previous_request = a.request; + a.request = nullptr; + + return true; } -void QKmsDevice::atomicReset() +void QKmsDevice::threadLocalAtomicReset() { - if (m_previous_request) { - drmModeAtomicFree(m_previous_request); - m_previous_request = nullptr; + if (!m_has_atomic_support) + return; + + AtomicReqs &a(m_atomicReqs.localData()); + if (a.previous_request) { + drmModeAtomicFree(a.previous_request); + a.previous_request = nullptr; } } #endif diff --git a/src/platformsupport/kmsconvenience/qkmsdevice_p.h b/src/platformsupport/kmsconvenience/qkmsdevice_p.h index b1150e2875..55a590cfce 100644 --- a/src/platformsupport/kmsconvenience/qkmsdevice_p.h +++ b/src/platformsupport/kmsconvenience/qkmsdevice_p.h @@ -57,6 +57,7 @@ #include <qpa/qplatformscreen.h> #include <QtCore/QMap> #include <QtCore/QVariant> +#include <QtCore/QThreadStorage> #include <xf86drm.h> #include <xf86drmMode.h> @@ -179,6 +180,8 @@ struct QKmsPlane uint32_t crtcheightPropertyId = 0; uint32_t zposPropertyId = 0; uint32_t blendOpPropertyId = 0; + + uint32_t activeCrtcId = 0; }; Q_DECLARE_OPERATORS_FOR_FLAGS(QKmsPlane::Rotations) @@ -239,10 +242,9 @@ public: bool hasAtomicSupport(); #if QT_CONFIG(drm_atomic) - bool atomicCommit(void *user_data); - void atomicReset(); - - drmModeAtomicReq *atomic_request(); + drmModeAtomicReq *threadLocalAtomicRequest(); + bool threadLocalAtomicCommit(void *user_data); + void threadLocalAtomicReset(); #endif void createScreens(); @@ -282,8 +284,11 @@ protected: bool m_has_atomic_support; #if QT_CONFIG(drm_atomic) - drmModeAtomicReq *m_atomic_request; - drmModeAtomicReq *m_previous_request; + struct AtomicReqs { + drmModeAtomicReq *request = nullptr; + drmModeAtomicReq *previous_request = nullptr; + }; + QThreadStorage<AtomicReqs> m_atomicReqs; #endif quint32 m_crtc_allocator; |