diff options
Diffstat (limited to 'src/platformsupport/kmsconvenience/qkmsdevice.cpp')
-rw-r--r-- | src/platformsupport/kmsconvenience/qkmsdevice.cpp | 159 |
1 files changed, 159 insertions, 0 deletions
diff --git a/src/platformsupport/kmsconvenience/qkmsdevice.cpp b/src/platformsupport/kmsconvenience/qkmsdevice.cpp index a5895559e6..ef81f6162d 100644 --- a/src/platformsupport/kmsconvenience/qkmsdevice.cpp +++ b/src/platformsupport/kmsconvenience/qkmsdevice.cpp @@ -366,6 +366,25 @@ QPlatformScreen *QKmsDevice::createScreenForConnector(drmModeResPtr resources, if (!cloneSource.isEmpty()) qCDebug(qLcKmsDebug) << "Output" << connectorName << " clones output " << cloneSource; + const QByteArray fbsize = userConnectorConfig.value(QStringLiteral("size")).toByteArray().toLower(); + QSize framebufferSize; + framebufferSize.setWidth(modes[selected_mode].hdisplay); + framebufferSize.setHeight(modes[selected_mode].vdisplay); + +#if QT_CONFIG(drm_atomic) + if (hasAtomicSupport()) { + if (sscanf(fbsize.constData(), "%dx%d", &framebufferSize.rwidth(), &framebufferSize.rheight()) != 2) { + qWarning("Framebuffer size format is invalid."); + } + } else { + qWarning("Setting framebuffer size is only available with DRM atomic API"); + } +#else + if (fbsize.size()) + qWarning("Setting framebuffer size is only available with DRM atomic API"); +#endif + qCDebug(qLcKmsDebug) << "Output" << connectorName << "framebuffer size is " << framebufferSize; + QKmsOutput output; output.name = QString::fromUtf8(connectorName); output.connector_id = connector->connector_id; @@ -385,6 +404,17 @@ QPlatformScreen *QKmsDevice::createScreenForConnector(drmModeResPtr resources, output.forced_plane_set = false; output.drm_format = drmFormat; output.clone_source = cloneSource; + output.size = framebufferSize; + +#if QT_CONFIG(drm_atomic) + if (drmModeCreatePropertyBlob(m_dri_fd, &modes[selected_mode], sizeof(drmModeModeInfo), + &output.mode_blob_id) != 0) { + qCDebug(qLcKmsDebug) << "Failed to create mode blob for mode" << selected_mode; + } + + parseConnectorProperties(output.connector_id, &output); + parseCrtcProperties(output.crtc_id, &output); +#endif QString planeListStr; for (const QKmsPlane &plane : qAsConst(m_planes)) { @@ -392,6 +422,8 @@ QPlatformScreen *QKmsDevice::createScreenForConnector(drmModeResPtr resources, output.available_planes.append(plane); planeListStr.append(QString::number(plane.id)); planeListStr.append(QLatin1Char(' ')); + if (plane.type == QKmsPlane::PrimaryPlane) + output.eglfs_plane = (QKmsPlane*)&plane; } } qCDebug(qLcKmsDebug, "Output %s can use %d planes: %s", @@ -412,6 +444,12 @@ QPlatformScreen *QKmsDevice::createScreenForConnector(drmModeResPtr resources, output.forced_plane_id = plane->plane_id; 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; + } + drmModeFreePlane(plane); } } else { @@ -420,6 +458,9 @@ QPlatformScreen *QKmsDevice::createScreenForConnector(drmModeResPtr resources, } } + if (output.eglfs_plane) + qCDebug(qLcKmsDebug, "Output eglfs plane is: %d", output.eglfs_plane->id); + m_crtc_allocator |= (1 << output.crtc_index); vinfo->output = output; @@ -464,6 +505,11 @@ QKmsDevice::QKmsDevice(QKmsScreenConfig *screenConfig, const QString &path) : m_screenConfig(screenConfig) , 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()) { @@ -478,6 +524,9 @@ QKmsDevice::QKmsDevice(QKmsScreenConfig *screenConfig, const QString &path) QKmsDevice::~QKmsDevice() { +#if QT_CONFIG(drm_atomic) + atomicReset(); +#endif } struct OrderedScreen @@ -522,6 +571,14 @@ void QKmsDevice::createScreens() drmSetClientCap(m_dri_fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1); +#if QT_CONFIG(drm_atomic) + // check atomic support + m_has_atomic_support = !drmSetClientCap(m_dri_fd, DRM_CLIENT_CAP_ATOMIC, 1) + && qEnvironmentVariableIntValue("QT_QPA_EGLFS_KMS_ATOMIC"); + if (m_has_atomic_support) + qCDebug(qLcKmsDebug) << "Atomic Support found"; +#endif + drmModeResPtr resources = drmModeGetResources(m_dri_fd); if (!resources) { qErrnoWarning(errno, "drmModeGetResources failed"); @@ -747,6 +804,28 @@ void QKmsDevice::discoverPlanes() plane.availableRotations |= QKmsPlane::Rotation(1 << prop->enums[i].value); } plane.rotationPropertyId = prop->prop_id; + } else if (!strcasecmp(prop->name, "crtc_id")) { + plane.crtcPropertyId = prop->prop_id; + } else if (!strcasecmp(prop->name, "fb_id")) { + plane.framebufferPropertyId = prop->prop_id; + } else if (!strcasecmp(prop->name, "src_w")) { + plane.srcwidthPropertyId = prop->prop_id; + } else if (!strcasecmp(prop->name, "src_h")) { + plane.srcheightPropertyId = prop->prop_id; + } else if (!strcasecmp(prop->name, "crtc_w")) { + plane.crtcwidthPropertyId = prop->prop_id; + } else if (!strcasecmp(prop->name, "crtc_h")) { + plane.crtcheightPropertyId = prop->prop_id; + } else if (!strcasecmp(prop->name, "src_x")) { + plane.srcXPropertyId = prop->prop_id; + } else if (!strcasecmp(prop->name, "src_y")) { + plane.srcYPropertyId = prop->prop_id; + } else if (!strcasecmp(prop->name, "crtc_x")) { + plane.crtcXPropertyId = prop->prop_id; + } else if (!strcasecmp(prop->name, "crtc_y")) { + plane.crtcYPropertyId = prop->prop_id; + } else if (!strcasecmp(prop->name, "zpos")) { + plane.zposPropertyId = prop->prop_id; } }); @@ -773,6 +852,86 @@ void QKmsDevice::setFd(int fd) m_dri_fd = fd; } + +bool QKmsDevice::hasAtomicSupport() +{ + return m_has_atomic_support; +} + +#if QT_CONFIG(drm_atomic) +drmModeAtomicReq * QKmsDevice::atomic_request() +{ + if (!m_atomic_request && m_has_atomic_support) + m_atomic_request = drmModeAtomicAlloc(); + + return m_atomic_request; +} + +bool QKmsDevice::atomicCommit(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 (ret) { + qWarning("Failed to commit atomic request (code=%d)", ret); + return false; + } + + m_previous_request = m_atomic_request; + m_atomic_request = nullptr; + + return true; + } + + return false; +} + +void QKmsDevice::atomicReset() +{ + if (m_previous_request) { + drmModeAtomicFree(m_previous_request); + m_previous_request = nullptr; + } +} +#endif + +void QKmsDevice::parseConnectorProperties(uint32_t connectorId, QKmsOutput *output) +{ + drmModeObjectPropertiesPtr objProps = drmModeObjectGetProperties(m_dri_fd, connectorId, DRM_MODE_OBJECT_CONNECTOR); + if (!objProps) { + qCDebug(qLcKmsDebug, "Failed to query connector %d object properties", connectorId); + return; + } + + enumerateProperties(objProps, [output](drmModePropertyPtr prop, quint64 value) { + Q_UNUSED(value); + if (!strcasecmp(prop->name, "crtc_id")) + output->crtcIdPropertyId = prop->prop_id; + }); + + drmModeFreeObjectProperties(objProps); +} + +void QKmsDevice::parseCrtcProperties(uint32_t crtcId, QKmsOutput *output) +{ + drmModeObjectPropertiesPtr objProps = drmModeObjectGetProperties(m_dri_fd, crtcId, DRM_MODE_OBJECT_CRTC); + if (!objProps) { + qCDebug(qLcKmsDebug, "Failed to query crtc %d object properties", crtcId); + return; + } + + enumerateProperties(objProps, [output](drmModePropertyPtr prop, quint64 value) { + Q_UNUSED(value) + if (!strcasecmp(prop->name, "mode_id")) + output->modeIdPropertyId = prop->prop_id; + else if (!strcasecmp(prop->name, "active")) + output->activePropertyId = prop->prop_id; + }); + + drmModeFreeObjectProperties(objProps); +} + QKmsScreenConfig *QKmsDevice::screenConfig() const { return m_screenConfig; |