summaryrefslogtreecommitdiffstats
path: root/src/platformsupport/kmsconvenience/qkmsdevice.cpp
diff options
context:
space:
mode:
authorLionel CHAZALLON <longchair@hotmail.com>2018-02-24 12:30:05 +0100
committerLionel CHAZALLON <longchair@hotmail.com>2018-03-05 16:14:36 +0000
commit56149c0fbb19946050a3249acef4e86e511d3cd4 (patch)
tree8eb7657b7673964ed3d38994c45c8514050518f9 /src/platformsupport/kmsconvenience/qkmsdevice.cpp
parent954fe2c35d0b0435b7f0443d917a5145dfd0c2a4 (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.cpp69
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;