diff options
author | Lionel CHAZALLON <longchair@hotmail.com> | 2018-02-24 12:30:05 +0100 |
---|---|---|
committer | Lionel CHAZALLON <longchair@hotmail.com> | 2018-03-05 16:14:36 +0000 |
commit | 56149c0fbb19946050a3249acef4e86e511d3cd4 (patch) | |
tree | 8eb7657b7673964ed3d38994c45c8514050518f9 /src/platformsupport/kmsconvenience/qkmsdevice.cpp | |
parent | 954fe2c35d0b0435b7f0443d917a5145dfd0c2a4 (diff) |
eglfs/kms: Add DRM/KMS atomic support
This commit adds support for DRM atomic to qtbase eglfs/KMS QPA when
libdrm and device supports it.
Compared To legacy DRM API, atomic API allows to update multiple planes
in one vsync. This is the first part of some work that should follow
and allow:
- DRM framebuffer upscaling for embedded devices that have weaker GPUs
- Sharing the drm atomic request if the KMSDevice so that applications
in userland can blend content on overlay in the same vsync loop.
One of the application for DRM atomic and Qt is typically videoplayer
integration at high resolutions (UHD) on embedded devices which cannot
use their GPU to render such videos, but are able to render it to a drm
overlay.
Change-Id: I047adf3e3d07a53440d52c2a7073c9ed054adf34
Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@qt.io>
Reviewed-by: Laszlo Agocs <laszlo.agocs@qt.io>
Diffstat (limited to 'src/platformsupport/kmsconvenience/qkmsdevice.cpp')
-rw-r--r-- | src/platformsupport/kmsconvenience/qkmsdevice.cpp | 69 |
1 files changed, 69 insertions, 0 deletions
diff --git a/src/platformsupport/kmsconvenience/qkmsdevice.cpp b/src/platformsupport/kmsconvenience/qkmsdevice.cpp index 59db3da776..2378856768 100644 --- a/src/platformsupport/kmsconvenience/qkmsdevice.cpp +++ b/src/platformsupport/kmsconvenience/qkmsdevice.cpp @@ -392,11 +392,16 @@ 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", connectorName.constData(), output.available_planes.count(), qPrintable(planeListStr)); + if (output.eglfs_plane) + qCDebug(qLcKmsDebug, "Output eglfs plane is: %d", output.eglfs_plane->id); + // This is for the EGLDevice/EGLStream backend. On some of those devices one // may want to target a pre-configured plane. It is probably useless for // eglfs_kms and others. Do not confuse with generic plane support (available_planes). @@ -464,6 +469,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 +488,9 @@ QKmsDevice::QKmsDevice(QKmsScreenConfig *screenConfig, const QString &path) QKmsDevice::~QKmsDevice() { +#if QT_CONFIG(drm_atomic) + atomicReset(); +#endif } struct OrderedScreen @@ -522,6 +535,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 +768,10 @@ 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; } }); @@ -773,6 +798,50 @@ 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, 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 + QKmsScreenConfig *QKmsDevice::screenConfig() const { return m_screenConfig; |