path: root/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.cpp
diff options
authorLaszlo Agocs <>2017-08-04 13:31:20 +0200
committerLaszlo Agocs <>2017-09-05 10:30:50 +0000
commitcf24d203850cd87e31bc123407e7ae126be9961c (patch)
tree52bbf250df26c320b706f2cfff6fc028cfef2ea3 /src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.cpp
parentf2289bbcbbbddfd248c5e0858e148d7cc7336f8a (diff)
eglfs_kms: Add headless mode for DRM render nodes
Attempting to switch /dev/dri/cardX to /dev/dri/renderDY is futile on its own now since many output-related drm operations fail and we eventually crash. Add a new headless mode that skips the real screen stuff and registers a fairly dummy, headless screen, does not bother with the mouse cursor, and disallows rendering to the screen via a QWindow (while keeping the actual rendering still fully functional). Such applications will not need any special privileges and will run even if there is a DRM master (X11, Wayland compositor) active. For example the configuration can look like this: { "device": "/dev/dri/renderD128", "headless": "1024x768" } After this applications have two choices to perform offscreen rendering: 1. Use an ordinary window (and its default framebuffer, meaning the gbm_surface), e.g. a QOpenGLWindow subclass MyOpenGLWindow w;; // will not actually show on screen w.grabFramebuffer().save("output.png"); Note that there is no vsync-based throttling. Also note that windows are still sized to match the screen size, hence the need for specifying a size in the headless property. 2. Or the typical offscreen approach with an extra FBO QOffscreenSurface s; s.setFormat(ctx.format()); s.create(); ctx.makeCurrent(&s0; QOpenGLFramebufferObject fbo(1024, 768); fbo.bind(); ctx.functions()->glClearColor(1, 0, 0, 1); ctx.functions()->glClear(GL_COLOR_BUFFER_BIT); fbo.toImage().save("output.png"); ctx.doneCurrent(); Task-number: QTBUG-62262 Change-Id: Ic1dbfa2b27b223bd5ef8ba36b665f0f61abf4f06 Reviewed-by: Qt CI Bot <> Reviewed-by: Andy Nichols <>
Diffstat (limited to 'src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.cpp')
1 files changed, 9 insertions, 2 deletions
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.cpp
index 533695ea0f..cc70ab5a3c 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.cpp
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.cpp
@@ -68,12 +68,13 @@ private:
QEglFSKmsScreen *m_screen;
-QEglFSKmsScreen::QEglFSKmsScreen(QKmsDevice *device, const QKmsOutput &output)
+QEglFSKmsScreen::QEglFSKmsScreen(QKmsDevice *device, const QKmsOutput &output, bool headless)
: QEglFSScreen(static_cast<QEglFSIntegration *>(QGuiApplicationPrivate::platformIntegration())->display())
, m_device(device)
, m_output(output)
, m_powerState(PowerStateOn)
, m_interruptHandler(new QEglFSKmsInterruptHandler(this))
+ , m_headless(headless)
m_siblings << this; // gets overridden later
@@ -109,6 +110,9 @@ void QEglFSKmsScreen::setVirtualPosition(const QPoint &pos)
// geometry() calls rawGeometry() and may apply additional transforms.
QRect QEglFSKmsScreen::rawGeometry() const
+ if (m_headless)
+ return QRect(QPoint(0, 0), m_device->screenConfig()->headlessSize());
const int mode = m_output.mode;
return QRect(m_pos.x(), m_pos.y(),
@@ -177,7 +181,7 @@ Qt::ScreenOrientation QEglFSKmsScreen::orientation() const
QString QEglFSKmsScreen::name() const
- return;
+ return !m_headless ? : QStringLiteral("qt_Headless");
QString QEglFSKmsScreen::manufacturer() const
@@ -214,6 +218,9 @@ void QEglFSKmsScreen::restoreMode()
qreal QEglFSKmsScreen::refreshRate() const
+ if (m_headless)
+ return 60;
quint32 refresh = m_output.modes[m_output.mode].vrefresh;
return refresh > 0 ? refresh : 60;