eglfs: kms: Choose unique primary planes for each crtc

Otherwise we end up with using the same plane for multiple crtcs, which
fails (with atomic - planes have no importance when atomic is not enabled).

This fixes systems where we run with atomic enabled and there are multiple
primary planes with their possible_crtcs matching multiple crtcs.

Task-number: QTBUG-74953
Change-Id: I8bcbdd389265d09f8851187881102fb5b9a83b5c
Reviewed-by: Johan Helsing <johan.helsing@qt.io>
bb10
Laszlo Agocs 2019-11-08 10:18:10 +01:00
parent 32d8f5310b
commit 2f81ad9d74
2 changed files with 31 additions and 8 deletions

View File

@ -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);
@ -500,9 +514,9 @@ QPlatformScreen *QKmsDevice::createScreenForConnector(drmModeResPtr resources,
const QStringList values = crtcPlanePair.split(QLatin1Char(','));
if (values.count() == 2 && uint(values[0].toInt()) == output.crtc_id) {
uint planeId = values[1].toInt();
for (const QKmsPlane &kmsplane : qAsConst(m_planes)) {
for (QKmsPlane &kmsplane : m_planes) {
if (kmsplane.id == planeId) {
output.eglfs_plane = (QKmsPlane*)&kmsplane;
assignPlane(&output, &kmsplane);
break;
}
}
@ -515,6 +529,13 @@ QPlatformScreen *QKmsDevice::createScreenForConnector(drmModeResPtr resources,
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);
vinfo->output = output;

View File

@ -179,6 +179,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)