diff options
Diffstat (limited to 'src/platformsupport/kmsconvenience/qkmsdevice.cpp')
-rw-r--r-- | src/platformsupport/kmsconvenience/qkmsdevice.cpp | 119 |
1 files changed, 85 insertions, 34 deletions
diff --git a/src/platformsupport/kmsconvenience/qkmsdevice.cpp b/src/platformsupport/kmsconvenience/qkmsdevice.cpp index 06d1251a65..7171908c99 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 } @@ -834,7 +873,7 @@ void QKmsDevice::discoverPlanes() plane.type = QKmsPlane::Type(value); } else if (!strcmp(prop->name, "rotation")) { plane.initialRotation = QKmsPlane::Rotations(int(value)); - plane.availableRotations = 0; + plane.availableRotations = { }; if (propTypeIs(prop, DRM_MODE_PROP_BITMASK)) { for (int i = 0; i < prop->count_enums; ++i) plane.availableRotations |= QKmsPlane::Rotation(1 << prop->enums[i].value); @@ -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 |