From cf24d203850cd87e31bc123407e7ae126be9961c Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Fri, 4 Aug 2017 13:31:20 +0200 Subject: 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; w.show(); // 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 --- .../deviceintegration/eglfs_kms/qeglfskmsgbmdevice.cpp | 7 ++++++- .../deviceintegration/eglfs_kms/qeglfskmsgbmdevice.h | 1 + .../deviceintegration/eglfs_kms/qeglfskmsgbmscreen.cpp | 15 ++++++++++----- .../deviceintegration/eglfs_kms/qeglfskmsgbmscreen.h | 2 +- 4 files changed, 18 insertions(+), 7 deletions(-) (limited to 'src/plugins/platforms/eglfs/deviceintegration/eglfs_kms') diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.cpp index 47752510b6..79c9687dc6 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.cpp +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.cpp @@ -151,7 +151,7 @@ void QEglFSKmsGbmDevice::handleDrmEvent() QPlatformScreen *QEglFSKmsGbmDevice::createScreen(const QKmsOutput &output) { - QEglFSKmsGbmScreen *screen = new QEglFSKmsGbmScreen(this, output); + QEglFSKmsGbmScreen *screen = new QEglFSKmsGbmScreen(this, output, false); if (!m_globalCursor && screenConfig()->hwCursor()) { qCDebug(qLcEglfsKmsDebug, "Creating new global GBM mouse cursor"); @@ -161,6 +161,11 @@ QPlatformScreen *QEglFSKmsGbmDevice::createScreen(const QKmsOutput &output) return screen; } +QPlatformScreen *QEglFSKmsGbmDevice::createHeadlessScreen() +{ + return new QEglFSKmsGbmScreen(this, QKmsOutput(), true); +} + void QEglFSKmsGbmDevice::registerScreenCloning(QPlatformScreen *screen, QPlatformScreen *screenThisScreenClones, const QVector &screensCloningThisScreen) diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.h index 93be197792..ad5a4d6e6a 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.h +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.h @@ -68,6 +68,7 @@ public: void handleDrmEvent(); QPlatformScreen *createScreen(const QKmsOutput &output) override; + QPlatformScreen *createHeadlessScreen() override; void registerScreenCloning(QPlatformScreen *screen, QPlatformScreen *screenThisScreenClones, const QVector &screensCloningThisScreen) override; diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.cpp index d3573a4512..ac6f8944ed 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.cpp +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.cpp @@ -109,8 +109,8 @@ QEglFSKmsGbmScreen::FrameBuffer *QEglFSKmsGbmScreen::framebufferForBufferObject( return fb.take(); } -QEglFSKmsGbmScreen::QEglFSKmsGbmScreen(QKmsDevice *device, const QKmsOutput &output) - : QEglFSKmsScreen(device, output) +QEglFSKmsGbmScreen::QEglFSKmsGbmScreen(QKmsDevice *device, const QKmsOutput &output, bool headless) + : QEglFSKmsScreen(device, output, headless) , m_gbm_surface(Q_NULLPTR) , m_gbm_bo_current(Q_NULLPTR) , m_gbm_bo_next(Q_NULLPTR) @@ -131,6 +131,8 @@ QEglFSKmsGbmScreen::~QEglFSKmsGbmScreen() QPlatformCursor *QEglFSKmsGbmScreen::cursor() const { QKmsScreenConfig *config = device()->screenConfig(); + if (config->headless()) + return nullptr; if (config->hwCursor()) { if (!config->separateScreens()) return static_cast(device())->globalCursor(); @@ -240,10 +242,8 @@ void QEglFSKmsGbmScreen::ensureModeSet(uint32_t fb) void QEglFSKmsGbmScreen::waitForFlip() { - if (m_cloneSource) { - qWarning("Screen %s clones another screen. swapBuffers() not allowed.", qPrintable(name())); + if (m_headless || m_cloneSource) return; - } // Don't lock the mutex unless we actually need to if (!m_gbm_bo_next) @@ -256,6 +256,11 @@ void QEglFSKmsGbmScreen::waitForFlip() void QEglFSKmsGbmScreen::flip() { + // For headless screen just return silently. It is not necessarily an error + // to end up here, so show no warnings. + if (m_headless) + return; + if (m_cloneSource) { qWarning("Screen %s clones another screen. swapBuffers() not allowed.", qPrintable(name())); return; diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.h index f6ee68d1c4..4541e500d5 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.h +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.h @@ -54,7 +54,7 @@ class QEglFSKmsGbmCursor; class QEglFSKmsGbmScreen : public QEglFSKmsScreen { public: - QEglFSKmsGbmScreen(QKmsDevice *device, const QKmsOutput &output); + QEglFSKmsGbmScreen(QKmsDevice *device, const QKmsOutput &output, bool headless); ~QEglFSKmsGbmScreen(); QPlatformCursor *cursor() const override; -- cgit v1.2.3