summaryrefslogtreecommitdiffstats
path: root/src/platformsupport/kmsconvenience/qkmsdevice.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/platformsupport/kmsconvenience/qkmsdevice.cpp')
-rw-r--r--src/platformsupport/kmsconvenience/qkmsdevice.cpp119
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