diff options
Diffstat (limited to 'src/plugins/platforms/eglfs')
20 files changed, 462 insertions, 204 deletions
diff --git a/src/plugins/platforms/eglfs/api/qeglfsdeviceintegration.cpp b/src/plugins/platforms/eglfs/api/qeglfsdeviceintegration.cpp index e411ea55e9..0fc4cc54e0 100644 --- a/src/plugins/platforms/eglfs/api/qeglfsdeviceintegration.cpp +++ b/src/plugins/platforms/eglfs/api/qeglfsdeviceintegration.cpp @@ -103,7 +103,7 @@ QStringList QEglFSDeviceIntegrationFactory::keys(const QString &pluginPath) QEglFSDeviceIntegration *QEglFSDeviceIntegrationFactory::create(const QString &key, const QString &pluginPath) { - QEglFSDeviceIntegration *integration = Q_NULLPTR; + QEglFSDeviceIntegration *integration = nullptr; #if QT_CONFIG(library) if (!pluginPath.isEmpty()) { QCoreApplication::addLibraryPath(pluginPath); @@ -351,9 +351,21 @@ bool QEglFSDeviceIntegration::supportsSurfacelessContexts() const return true; } +QFunctionPointer QEglFSDeviceIntegration::platformFunction(const QByteArray &function) const +{ + Q_UNUSED(function); + return nullptr; +} + +void *QEglFSDeviceIntegration::nativeResourceForIntegration(const QByteArray &name) +{ + Q_UNUSED(name); + return nullptr; +} + void *QEglFSDeviceIntegration::wlDisplay() const { - return Q_NULLPTR; + return nullptr; } EGLConfig QEglFSDeviceIntegration::chooseConfig(EGLDisplay display, const QSurfaceFormat &format) diff --git a/src/plugins/platforms/eglfs/api/qeglfsdeviceintegration_p.h b/src/plugins/platforms/eglfs/api/qeglfsdeviceintegration_p.h index 4335554912..d927bc9bc6 100644 --- a/src/plugins/platforms/eglfs/api/qeglfsdeviceintegration_p.h +++ b/src/plugins/platforms/eglfs/api/qeglfsdeviceintegration_p.h @@ -103,6 +103,8 @@ public: virtual int framebufferIndex() const; virtual bool supportsPBuffers() const; virtual bool supportsSurfacelessContexts() const; + virtual QFunctionPointer platformFunction(const QByteArray &function) const; + virtual void *nativeResourceForIntegration(const QByteArray &name); virtual void *wlDisplay() const; diff --git a/src/plugins/platforms/eglfs/api/qeglfsintegration.cpp b/src/plugins/platforms/eglfs/api/qeglfsintegration.cpp index 9a0be489a8..c0ecfd235f 100644 --- a/src/plugins/platforms/eglfs/api/qeglfsintegration.cpp +++ b/src/plugins/platforms/eglfs/api/qeglfsintegration.cpp @@ -324,6 +324,7 @@ void *QEglFSIntegration::nativeResourceForIntegration(const QByteArray &resource result = qt_egl_device_integration()->wlDisplay(); break; default: + result = qt_egl_device_integration()->nativeResourceForIntegration(resource); break; } @@ -427,11 +428,9 @@ QFunctionPointer QEglFSIntegration::platformFunction(const QByteArray &function) #if QT_CONFIG(evdev) if (function == QEglFSFunctions::loadKeymapTypeIdentifier()) return QFunctionPointer(loadKeymapStatic); -#else - Q_UNUSED(function) #endif - return 0; + return qt_egl_device_integration()->platformFunction(function); } void QEglFSIntegration::loadKeymapStatic(const QString &filename) diff --git a/src/plugins/platforms/eglfs/api/qeglfswindow_p.h b/src/plugins/platforms/eglfs/api/qeglfswindow_p.h index 6bda262523..c61f04f569 100644 --- a/src/plugins/platforms/eglfs/api/qeglfswindow_p.h +++ b/src/plugins/platforms/eglfs/api/qeglfswindow_p.h @@ -95,7 +95,7 @@ public: EGLNativeWindowType eglWindow() const; EGLSurface surface() const; - QEglFSScreen *screen() const; + QEglFSScreen *screen() const override; bool hasNativeWindow() const { return m_flags.testFlag(HasNativeWindow); } diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/eglfs_kms.pro b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/eglfs_kms.pro index 27c0af1f08..43170a3875 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/eglfs_kms.pro +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/eglfs_kms.pro @@ -19,11 +19,13 @@ SOURCES += $$PWD/qeglfskmsgbmmain.cpp \ $$PWD/qeglfskmsgbmintegration.cpp \ $$PWD/qeglfskmsgbmdevice.cpp \ $$PWD/qeglfskmsgbmscreen.cpp \ - $$PWD/qeglfskmsgbmcursor.cpp + $$PWD/qeglfskmsgbmcursor.cpp \ + $$PWD/qeglfskmsgbmwindow.cpp HEADERS += $$PWD/qeglfskmsgbmintegration.h \ $$PWD/qeglfskmsgbmdevice.h \ $$PWD/qeglfskmsgbmscreen.h \ - $$PWD/qeglfskmsgbmcursor.h + $$PWD/qeglfskmsgbmcursor.h \ + $$PWD/qeglfskmsgbmwindow.h OTHER_FILES += $$PWD/eglfs_kms.json diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmcursor.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmcursor.cpp index 800118362d..9bd7fee1fb 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmcursor.cpp +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmcursor.cpp @@ -68,7 +68,7 @@ Q_DECLARE_LOGGING_CATEGORY(qLcEglfsKmsDebug) QEglFSKmsGbmCursor::QEglFSKmsGbmCursor(QEglFSKmsGbmScreen *screen) : m_screen(screen) , m_cursorSize(64, 64) // 64x64 is the old standard size, we now try to query the real size below - , m_bo(Q_NULLPTR) + , m_bo(nullptr) , m_cursorImage(0, 0, 0, 0, 0, 0) , m_state(CursorPendingVisible) { @@ -118,7 +118,7 @@ QEglFSKmsGbmCursor::~QEglFSKmsGbmCursor() if (m_bo) { gbm_bo_destroy(m_bo); - m_bo = Q_NULLPTR; + m_bo = nullptr; } } @@ -132,7 +132,7 @@ void QEglFSKmsGbmCursor::updateMouseStatus() m_state = visible ? CursorPendingVisible : CursorPendingHidden; #ifndef QT_NO_CURSOR - changeCursor(Q_NULLPTR, m_screen->topLevelAt(pos())); + changeCursor(nullptr, m_screen->topLevelAt(pos())); #endif } diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.cpp index e218d580a2..20127ae7f7 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.cpp +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.cpp @@ -53,28 +53,17 @@ QT_BEGIN_NAMESPACE Q_DECLARE_LOGGING_CATEGORY(qLcEglfsKmsDebug) -void QEglFSKmsGbmDevice::pageFlipHandler(int fd, unsigned int sequence, unsigned int tv_sec, unsigned int tv_usec, void *user_data) -{ - Q_UNUSED(fd); - Q_UNUSED(sequence); - Q_UNUSED(tv_sec); - Q_UNUSED(tv_usec); - - QEglFSKmsScreen *screen = static_cast<QEglFSKmsScreen *>(user_data); - screen->flipFinished(); -} - QEglFSKmsGbmDevice::QEglFSKmsGbmDevice(QKmsScreenConfig *screenConfig, const QString &path) : QEglFSKmsDevice(screenConfig, path) - , m_gbm_device(Q_NULLPTR) - , m_globalCursor(Q_NULLPTR) + , m_gbm_device(nullptr) + , m_globalCursor(nullptr) { } bool QEglFSKmsGbmDevice::open() { Q_ASSERT(fd() == -1); - Q_ASSERT(m_gbm_device == Q_NULLPTR); + Q_ASSERT(m_gbm_device == nullptr); int fd = qt_safe_open(devicePath().toLocal8Bit().constData(), O_RDWR | O_CLOEXEC); if (fd == -1) { @@ -103,7 +92,7 @@ void QEglFSKmsGbmDevice::close() if (m_gbm_device) { gbm_device_destroy(m_gbm_device); - m_gbm_device = Q_NULLPTR; + m_gbm_device = nullptr; } if (fd() != -1) { @@ -134,24 +123,13 @@ void QEglFSKmsGbmDevice::destroyGlobalCursor() if (m_globalCursor) { qCDebug(qLcEglfsKmsDebug, "Destroying global GBM mouse cursor"); delete m_globalCursor; - m_globalCursor = Q_NULLPTR; + m_globalCursor = nullptr; } } -void QEglFSKmsGbmDevice::handleDrmEvent() -{ - drmEventContext drmEvent; - memset(&drmEvent, 0, sizeof(drmEvent)); - drmEvent.version = 2; - drmEvent.vblank_handler = nullptr; - drmEvent.page_flip_handler = pageFlipHandler; - - drmHandleEvent(fd(), &drmEvent); -} - 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,4 +139,20 @@ 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<QPlatformScreen *> &screensCloningThisScreen) +{ + if (!screenThisScreenClones && screensCloningThisScreen.isEmpty()) + return; + + QEglFSKmsGbmScreen *gbmScreen = static_cast<QEglFSKmsGbmScreen *>(screen); + gbmScreen->initCloning(screenThisScreenClones, screensCloningThisScreen); +} + QT_END_NAMESPACE diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.h index 08ca28d48e..518e2ce58b 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.h +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.h @@ -65,9 +65,11 @@ public: QPlatformCursor *globalCursor() const; void destroyGlobalCursor(); - void handleDrmEvent(); - QPlatformScreen *createScreen(const QKmsOutput &output) override; + QPlatformScreen *createHeadlessScreen() override; + void registerScreenCloning(QPlatformScreen *screen, + QPlatformScreen *screenThisScreenClones, + const QVector<QPlatformScreen *> &screensCloningThisScreen) override; private: Q_DISABLE_COPY(QEglFSKmsGbmDevice) @@ -75,12 +77,6 @@ private: gbm_device *m_gbm_device; QEglFSKmsGbmCursor *m_globalCursor; - - static void pageFlipHandler(int fd, - unsigned int sequence, - unsigned int tv_sec, - unsigned int tv_usec, - void *user_data); }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmintegration.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmintegration.cpp index 058791e473..402338197d 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmintegration.cpp +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmintegration.cpp @@ -43,21 +43,13 @@ #include "qeglfskmsgbmdevice.h" #include "qeglfskmsgbmscreen.h" #include "qeglfskmsgbmcursor.h" -#include "private/qeglfswindow_p.h" +#include "qeglfskmsgbmwindow.h" #include "private/qeglfscursor_p.h" -#include <QtDeviceDiscoverySupport/private/qdevicediscovery_p.h> -#include <QtEglSupport/private/qeglconvenience_p.h> #include <QtCore/QLoggingCategory> -#include <QtCore/QJsonDocument> -#include <QtCore/QJsonObject> -#include <QtCore/QJsonArray> -#include <QtGui/qpa/qplatformwindow.h> -#include <QtGui/qpa/qplatformcursor.h> #include <QtGui/QScreen> +#include <QtDeviceDiscoverySupport/private/qdevicediscovery_p.h> -#include <xf86drm.h> -#include <xf86drmMode.h> #include <gbm.h> QT_BEGIN_NAMESPACE @@ -105,7 +97,6 @@ EGLNativeWindowType QEglFSKmsGbmIntegration::createNativeOffscreenWindow(const Q Q_UNUSED(format); Q_ASSERT(device()); - qCDebug(qLcEglfsKmsDebug) << "Creating native off screen window"; gbm_surface *surface = gbm_surface_create(static_cast<QEglFSKmsGbmDevice *>(device())->gbmDevice(), 1, 1, GBM_FORMAT_XRGB8888, @@ -134,8 +125,7 @@ QPlatformCursor *QEglFSKmsGbmIntegration::createCursor(QPlatformScreen *screen) void QEglFSKmsGbmIntegration::presentBuffer(QPlatformSurface *surface) { QWindow *window = static_cast<QWindow *>(surface->surface()); - QEglFSKmsScreen *screen = static_cast<QEglFSKmsScreen *>(window->screen()->handle()); - + QEglFSKmsGbmScreen *screen = static_cast<QEglFSKmsGbmScreen *>(window->screen()->handle()); screen->flip(); } @@ -160,46 +150,6 @@ QKmsDevice *QEglFSKmsGbmIntegration::createDevice() return new QEglFSKmsGbmDevice(screenConfig(), path); } -class QEglFSKmsGbmWindow : public QEglFSWindow -{ -public: - QEglFSKmsGbmWindow(QWindow *w, const QEglFSKmsGbmIntegration *integration) - : QEglFSWindow(w) - , m_integration(integration) - {} - void resetSurface() override; - const QEglFSKmsGbmIntegration *m_integration; -}; - -void QEglFSKmsGbmWindow::resetSurface() -{ - QEglFSKmsGbmScreen *gbmScreen = static_cast<QEglFSKmsGbmScreen *>(screen()); - if (gbmScreen->surface()) { - qWarning("Only single window per screen supported!"); - return; - } - - EGLDisplay display = gbmScreen->display(); - QSurfaceFormat platformFormat = m_integration->surfaceFormatFor(window()->requestedFormat()); - m_config = QEglFSDeviceIntegration::chooseConfig(display, platformFormat); - m_format = q_glFormatFromConfig(display, m_config, platformFormat); - m_window = reinterpret_cast<EGLNativeWindowType>(gbmScreen->createSurface()); - - PFNEGLCREATEPLATFORMWINDOWSURFACEEXTPROC createPlatformWindowSurface = nullptr; - const char *extensions = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS); - if (extensions && (strstr(extensions, "EGL_KHR_platform_gbm") || strstr(extensions, "EGL_MESA_platform_gbm"))) { - createPlatformWindowSurface = reinterpret_cast<PFNEGLCREATEPLATFORMWINDOWSURFACEEXTPROC>( - eglGetProcAddress("eglCreatePlatformWindowSurfaceEXT")); - } - - if (createPlatformWindowSurface) { - m_surface = createPlatformWindowSurface(display, m_config, reinterpret_cast<void *>(m_window), nullptr); - } else { - qCDebug(qLcEglfsKmsDebug, "No eglCreatePlatformWindowSurface for GBM, falling back to eglCreateWindowSurface"); - m_surface = eglCreateWindowSurface(display, m_config, m_window, nullptr); - } -} - QEglFSWindow *QEglFSKmsGbmIntegration::createWindow(QWindow *window) const { return new QEglFSKmsGbmWindow(window, this); diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.cpp index 87fb3146c7..4742143121 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.cpp +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.cpp @@ -1,7 +1,7 @@ /**************************************************************************** ** +** Copyright (C) 2017 The Qt Company Ltd. ** Copyright (C) 2015 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com> -** Copyright (C) 2016 The Qt Company Ltd. ** Copyright (C) 2016 Pelagicore AG ** Contact: https://www.qt.io/licensing/ ** @@ -55,6 +55,18 @@ QT_BEGIN_NAMESPACE Q_DECLARE_LOGGING_CATEGORY(qLcEglfsKmsDebug) +static inline uint32_t drmFormatToGbmFormat(uint32_t drmFormat) +{ + Q_ASSERT(DRM_FORMAT_XRGB8888 == GBM_FORMAT_XRGB8888); + return drmFormat; +} + +static inline uint32_t gbmFormatToDrmFormat(uint32_t gbmFormat) +{ + Q_ASSERT(DRM_FORMAT_XRGB8888 == GBM_FORMAT_XRGB8888); + return gbmFormat; +} + void QEglFSKmsGbmScreen::bufferDestroyedHandler(gbm_bo *bo, void *data) { FrameBuffer *fb = static_cast<FrameBuffer *>(data); @@ -77,29 +89,34 @@ QEglFSKmsGbmScreen::FrameBuffer *QEglFSKmsGbmScreen::framebufferForBufferObject( uint32_t width = gbm_bo_get_width(bo); uint32_t height = gbm_bo_get_height(bo); - uint32_t stride = gbm_bo_get_stride(bo); - uint32_t handle = gbm_bo_get_handle(bo).u32; + uint32_t handles[4] = { gbm_bo_get_handle(bo).u32 }; + uint32_t strides[4] = { gbm_bo_get_stride(bo) }; + uint32_t offsets[4] = { 0 }; + uint32_t pixelFormat = gbmFormatToDrmFormat(gbm_bo_get_format(bo)); QScopedPointer<FrameBuffer> fb(new FrameBuffer); + qCDebug(qLcEglfsKmsDebug, "Adding FB, size %ux%u, DRM format 0x%x", width, height, pixelFormat); - int ret = drmModeAddFB(device()->fd(), width, height, 24, 32, - stride, handle, &fb->fb); + int ret = drmModeAddFB2(device()->fd(), width, height, pixelFormat, + handles, strides, offsets, &fb->fb, 0); if (ret) { qWarning("Failed to create KMS FB!"); - return Q_NULLPTR; + return nullptr; } gbm_bo_set_user_data(bo, fb.data(), bufferDestroyedHandler); return fb.take(); } -QEglFSKmsGbmScreen::QEglFSKmsGbmScreen(QKmsDevice *device, const QKmsOutput &output) - : QEglFSKmsScreen(device, output) - , m_gbm_surface(Q_NULLPTR) - , m_gbm_bo_current(Q_NULLPTR) - , m_gbm_bo_next(Q_NULLPTR) - , m_cursor(Q_NULLPTR) +QEglFSKmsGbmScreen::QEglFSKmsGbmScreen(QKmsDevice *device, const QKmsOutput &output, bool headless) + : QEglFSKmsScreen(device, output, headless) + , m_gbm_surface(nullptr) + , m_gbm_bo_current(nullptr) + , m_gbm_bo_next(nullptr) + , m_flipPending(false) + , m_cursor(nullptr) + , m_cloneSource(nullptr) { } @@ -114,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<QEglFSKmsGbmDevice *>(device())->globalCursor(); @@ -132,47 +151,112 @@ QPlatformCursor *QEglFSKmsGbmScreen::cursor() const gbm_surface *QEglFSKmsGbmScreen::createSurface() { if (!m_gbm_surface) { - qCDebug(qLcEglfsKmsDebug) << "Creating window for screen" << name(); + uint32_t gbmFormat = drmFormatToGbmFormat(m_output.drm_format); + qCDebug(qLcEglfsKmsDebug, "Creating gbm_surface for screen %s with format 0x%x", qPrintable(name()), gbmFormat); m_gbm_surface = gbm_surface_create(static_cast<QEglFSKmsGbmDevice *>(device())->gbmDevice(), rawGeometry().width(), rawGeometry().height(), - GBM_FORMAT_XRGB8888, + gbmFormat, GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING); } - return m_gbm_surface; + return m_gbm_surface; // not owned, gets destroyed in QEglFSKmsGbmIntegration::destroyNativeWindow() via QEglFSKmsGbmWindow::invalidateSurface() } -void QEglFSKmsGbmScreen::destroySurface() +void QEglFSKmsGbmScreen::resetSurface() { - if (m_gbm_bo_current) { - gbm_bo_destroy(m_gbm_bo_current); - m_gbm_bo_current = Q_NULLPTR; - } + m_gbm_surface = nullptr; +} - if (m_gbm_bo_next) { - gbm_bo_destroy(m_gbm_bo_next); - m_gbm_bo_next = Q_NULLPTR; +void QEglFSKmsGbmScreen::initCloning(QPlatformScreen *screenThisScreenClones, + const QVector<QPlatformScreen *> &screensCloningThisScreen) +{ + // clone destinations need to know the clone source + const bool clonesAnother = screenThisScreenClones != nullptr; + if (clonesAnother && !screensCloningThisScreen.isEmpty()) { + qWarning("QEglFSKmsGbmScreen %s cannot be clone source and destination at the same time", qPrintable(name())); + return; } + if (clonesAnother) + m_cloneSource = static_cast<QEglFSKmsGbmScreen *>(screenThisScreenClones); + + // clone sources need to know their additional destinations + for (QPlatformScreen *s : screensCloningThisScreen) { + CloneDestination d; + d.screen = static_cast<QEglFSKmsGbmScreen *>(s); + m_cloneDests.append(d); + } +} + +void QEglFSKmsGbmScreen::ensureModeSet(uint32_t fb) +{ + QKmsOutput &op(output()); + const int fd = device()->fd(); + + if (!op.mode_set) { + op.mode_set = true; + + bool doModeSet = true; + drmModeCrtcPtr currentMode = drmModeGetCrtc(fd, op.crtc_id); + const bool alreadySet = currentMode && !memcmp(¤tMode->mode, &op.modes[op.mode], sizeof(drmModeModeInfo)); + if (currentMode) + drmModeFreeCrtc(currentMode); + if (alreadySet) { + static bool alwaysDoSet = qEnvironmentVariableIntValue("QT_QPA_EGLFS_ALWAYS_SET_MODE"); + if (!alwaysDoSet) { + qCDebug(qLcEglfsKmsDebug, "Mode already set, skipping modesetting for screen %s", qPrintable(name())); + doModeSet = false; + } + } - if (m_gbm_surface) { - gbm_surface_destroy(m_gbm_surface); - m_gbm_surface = Q_NULLPTR; + if (doModeSet) { + qCDebug(qLcEglfsKmsDebug, "Setting mode for screen %s", qPrintable(name())); + int ret = drmModeSetCrtc(fd, + op.crtc_id, + fb, + 0, 0, + &op.connector_id, 1, + &op.modes[op.mode]); + + if (ret == 0) + setPowerState(PowerStateOn); + else + qErrnoWarning(errno, "Could not set DRM mode for screen %s", qPrintable(name())); + } } } void QEglFSKmsGbmScreen::waitForFlip() { + if (m_headless || m_cloneSource) + return; + // Don't lock the mutex unless we actually need to if (!m_gbm_bo_next) return; QMutexLocker lock(&m_waitForFlipMutex); - while (m_gbm_bo_next) - static_cast<QEglFSKmsGbmDevice *>(device())->handleDrmEvent(); + while (m_gbm_bo_next) { + drmEventContext drmEvent; + memset(&drmEvent, 0, sizeof(drmEvent)); + drmEvent.version = 2; + drmEvent.vblank_handler = nullptr; + drmEvent.page_flip_handler = pageFlipHandler; + drmHandleEvent(device()->fd(), &drmEvent); + } } 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; + } + if (!m_gbm_surface) { qWarning("Cannot sync before platform init!"); return; @@ -185,60 +269,92 @@ void QEglFSKmsGbmScreen::flip() } FrameBuffer *fb = framebufferForBufferObject(m_gbm_bo_next); + ensureModeSet(fb->fb); QKmsOutput &op(output()); const int fd = device()->fd(); - const uint32_t w = op.modes[op.mode].hdisplay; - const uint32_t h = op.modes[op.mode].vdisplay; - - if (!op.mode_set) { - int ret = drmModeSetCrtc(fd, - op.crtc_id, - fb->fb, - 0, 0, - &op.connector_id, 1, - &op.modes[op.mode]); - - if (ret == -1) { - qErrnoWarning(errno, "Could not set DRM mode!"); - } else { - op.mode_set = true; - setPowerState(PowerStateOn); - - if (!op.plane_set) { - op.plane_set = true; - if (op.wants_plane) { - int ret = drmModeSetPlane(fd, op.plane_id, op.crtc_id, - uint32_t(-1), 0, - 0, 0, w, h, - 0 << 16, 0 << 16, w << 16, h << 16); - if (ret == -1) - qErrnoWarning(errno, "drmModeSetPlane failed"); - } - } - } - } - + m_flipPending = true; int ret = drmModePageFlip(fd, op.crtc_id, fb->fb, DRM_MODE_PAGE_FLIP_EVENT, this); if (ret) { - qErrnoWarning("Could not queue DRM page flip!"); + qErrnoWarning("Could not queue DRM page flip on screen %s", qPrintable(name())); + m_flipPending = false; gbm_surface_release_buffer(m_gbm_surface, m_gbm_bo_next); - m_gbm_bo_next = Q_NULLPTR; + m_gbm_bo_next = nullptr; + return; + } + + for (CloneDestination &d : m_cloneDests) { + if (d.screen != this) { + d.screen->ensureModeSet(fb->fb); + d.cloneFlipPending = true; + int ret = drmModePageFlip(fd, + d.screen->output().crtc_id, + fb->fb, + DRM_MODE_PAGE_FLIP_EVENT, + d.screen); + if (ret) { + qErrnoWarning("Could not queue DRM page flip for clone screen %s", qPrintable(name())); + d.cloneFlipPending = false; + } + } } } +void QEglFSKmsGbmScreen::pageFlipHandler(int fd, unsigned int sequence, unsigned int tv_sec, unsigned int tv_usec, void *user_data) +{ + Q_UNUSED(fd); + Q_UNUSED(sequence); + Q_UNUSED(tv_sec); + Q_UNUSED(tv_usec); + + QEglFSKmsGbmScreen *screen = static_cast<QEglFSKmsGbmScreen *>(user_data); + screen->flipFinished(); +} + void QEglFSKmsGbmScreen::flipFinished() { + if (m_cloneSource) { + m_cloneSource->cloneDestFlipFinished(this); + return; + } + + m_flipPending = false; + updateFlipStatus(); +} + +void QEglFSKmsGbmScreen::cloneDestFlipFinished(QEglFSKmsGbmScreen *cloneDestScreen) +{ + for (CloneDestination &d : m_cloneDests) { + if (d.screen == cloneDestScreen) { + d.cloneFlipPending = false; + break; + } + } + updateFlipStatus(); +} + +void QEglFSKmsGbmScreen::updateFlipStatus() +{ + Q_ASSERT(!m_cloneSource); + + if (m_flipPending) + return; + + for (const CloneDestination &d : m_cloneDests) { + if (d.cloneFlipPending) + return; + } + if (m_gbm_bo_current) gbm_surface_release_buffer(m_gbm_surface, m_gbm_bo_current); m_gbm_bo_current = m_gbm_bo_next; - m_gbm_bo_next = Q_NULLPTR; + m_gbm_bo_next = nullptr; } QT_END_NAMESPACE diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.h index 341cc95bbe..f5a2122723 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.h +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.h @@ -54,34 +54,54 @@ 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; - gbm_surface *surface() const { return m_gbm_surface; } gbm_surface *createSurface(); - void destroySurface(); + void resetSurface(); + + void initCloning(QPlatformScreen *screenThisScreenClones, + const QVector<QPlatformScreen *> &screensCloningThisScreen); void waitForFlip() override; - void flip() override; - void flipFinished() override; + + void flip(); private: + void flipFinished(); + void ensureModeSet(uint32_t fb); + void cloneDestFlipFinished(QEglFSKmsGbmScreen *cloneDestScreen); + void updateFlipStatus(); + + static void pageFlipHandler(int fd, + unsigned int sequence, + unsigned int tv_sec, + unsigned int tv_usec, + void *user_data); + gbm_surface *m_gbm_surface; gbm_bo *m_gbm_bo_current; gbm_bo *m_gbm_bo_next; + bool m_flipPending; QScopedPointer<QEglFSKmsGbmCursor> m_cursor; struct FrameBuffer { - FrameBuffer() : fb(0) {} - uint32_t fb; + uint32_t fb = 0; }; static void bufferDestroyedHandler(gbm_bo *bo, void *data); FrameBuffer *framebufferForBufferObject(gbm_bo *bo); + QEglFSKmsGbmScreen *m_cloneSource; + struct CloneDestination { + QEglFSKmsGbmScreen *screen = nullptr; + bool cloneFlipPending = false; + }; + QVector<CloneDestination> m_cloneDests; + static QMutex m_waitForFlipMutex; }; diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmwindow.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmwindow.cpp new file mode 100644 index 0000000000..110a592dec --- /dev/null +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmwindow.cpp @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qeglfskmsgbmwindow.h" +#include "qeglfskmsgbmintegration.h" +#include "qeglfskmsgbmscreen.h" + +#include <QtEglSupport/private/qeglconvenience_p.h> + +QT_BEGIN_NAMESPACE + +void QEglFSKmsGbmWindow::resetSurface() +{ + QEglFSKmsGbmScreen *gbmScreen = static_cast<QEglFSKmsGbmScreen *>(screen()); + EGLDisplay display = gbmScreen->display(); + QSurfaceFormat platformFormat = m_integration->surfaceFormatFor(window()->requestedFormat()); + m_config = QEglFSDeviceIntegration::chooseConfig(display, platformFormat); + m_format = q_glFormatFromConfig(display, m_config, platformFormat); + // One fullscreen window per screen -> the native window is simply the gbm_surface the screen created. + m_window = reinterpret_cast<EGLNativeWindowType>(gbmScreen->createSurface()); + + PFNEGLCREATEPLATFORMWINDOWSURFACEEXTPROC createPlatformWindowSurface = nullptr; + const char *extensions = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS); + if (extensions && (strstr(extensions, "EGL_KHR_platform_gbm") || strstr(extensions, "EGL_MESA_platform_gbm"))) { + createPlatformWindowSurface = reinterpret_cast<PFNEGLCREATEPLATFORMWINDOWSURFACEEXTPROC>( + eglGetProcAddress("eglCreatePlatformWindowSurfaceEXT")); + } + + if (createPlatformWindowSurface) { + m_surface = createPlatformWindowSurface(display, m_config, reinterpret_cast<void *>(m_window), nullptr); + } else { + qCDebug(qLcEglfsKmsDebug, "No eglCreatePlatformWindowSurface for GBM, falling back to eglCreateWindowSurface"); + m_surface = eglCreateWindowSurface(display, m_config, m_window, nullptr); + } +} + +void QEglFSKmsGbmWindow::invalidateSurface() +{ + QEglFSKmsGbmScreen *gbmScreen = static_cast<QEglFSKmsGbmScreen *>(screen()); + QEglFSWindow::invalidateSurface(); + gbmScreen->resetSurface(); +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmwindow.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmwindow.h new file mode 100644 index 0000000000..a19cf7e8bc --- /dev/null +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmwindow.h @@ -0,0 +1,67 @@ +/**************************************************************************** +** +** Copyright (C) 2015 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com> +** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2016 Pelagicore AG +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QEGLFSKMSGBMWINDOW_H +#define QEGLFSKMSGBMWINDOW_H + +#include "private/qeglfswindow_p.h" + +QT_BEGIN_NAMESPACE + +class QEglFSKmsGbmIntegration; + +class QEglFSKmsGbmWindow : public QEglFSWindow +{ +public: + QEglFSKmsGbmWindow(QWindow *w, const QEglFSKmsGbmIntegration *integration) + : QEglFSWindow(w), + m_integration(integration) + { } + void resetSurface() override; + void invalidateSurface() override; + +private: + const QEglFSKmsGbmIntegration *m_integration; +}; + +QT_END_NAMESPACE + +#endif // QEGLFSKMSGBMWINDOW_H diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevice.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevice.cpp index cca413ff2d..8c8e6260f1 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevice.cpp +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevice.cpp @@ -58,7 +58,7 @@ bool QEglFSKmsEglDevice::open() { Q_ASSERT(fd() == -1); - int fd = drmOpen(devicePath().toLocal8Bit().constData(), Q_NULLPTR); + int fd = drmOpen(devicePath().toLocal8Bit().constData(), nullptr); if (Q_UNLIKELY(fd < 0)) qFatal("Could not open DRM (NV) device"); diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.cpp index 3af21d768e..a67457a6a5 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.cpp +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.cpp @@ -51,7 +51,7 @@ QT_BEGIN_NAMESPACE QEglFSKmsEglDeviceIntegration::QEglFSKmsEglDeviceIntegration() : m_egl_device(EGL_NO_DEVICE_EXT) - , m_funcs(Q_NULLPTR) + , m_funcs(nullptr) { qCDebug(qLcEglfsKmsDebug, "New DRM/KMS on EGLDevice integration created"); } @@ -75,7 +75,7 @@ EGLDisplay QEglFSKmsEglDeviceIntegration::createDisplay(EGLNativeDisplayType nat EGLDisplay display; if (m_funcs->has_egl_platform_device) { - display = m_funcs->get_platform_display(EGL_PLATFORM_DEVICE_EXT, nativeDisplay, Q_NULLPTR); + display = m_funcs->get_platform_display(EGL_PLATFORM_DEVICE_EXT, nativeDisplay, nullptr); } else { qWarning("EGL_EXT_platform_device not available, falling back to legacy path!"); display = eglGetDisplay(nativeDisplay); @@ -162,7 +162,7 @@ void QEglFSKmsEglDeviceWindow::resetSurface() qCDebug(qLcEglfsKmsDebug, "Could not query number of EGLStream FIFO frames"); } - if (!m_integration->m_funcs->get_output_layers(display, Q_NULLPTR, Q_NULLPTR, 0, &count) || count == 0) { + if (!m_integration->m_funcs->get_output_layers(display, nullptr, nullptr, 0, &count) || count == 0) { qWarning("No output layers found"); return; } @@ -172,7 +172,7 @@ void QEglFSKmsEglDeviceWindow::resetSurface() QVector<EGLOutputLayerEXT> layers; layers.resize(count); EGLint actualCount; - if (!m_integration->m_funcs->get_output_layers(display, Q_NULLPTR, layers.data(), count, &actualCount)) { + if (!m_integration->m_funcs->get_output_layers(display, nullptr, layers.data(), count, &actualCount)) { qWarning("Failed to get layers"); return; } @@ -180,7 +180,7 @@ void QEglFSKmsEglDeviceWindow::resetSurface() QEglFSKmsEglDeviceScreen *cur_screen = static_cast<QEglFSKmsEglDeviceScreen *>(screen()); Q_ASSERT(cur_screen); QKmsOutput &output(cur_screen->output()); - const uint32_t wantedId = !output.wants_plane ? output.crtc_id : output.plane_id; + const uint32_t wantedId = !output.wants_forced_plane ? output.crtc_id : output.forced_plane_id; qCDebug(qLcEglfsKmsDebug, "Searching for id: %d", wantedId); EGLOutputLayerEXT layer = EGL_NO_OUTPUT_LAYER_EXT; diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevicescreen.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevicescreen.cpp index a27c89faab..531b73d1dc 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevicescreen.cpp +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevicescreen.cpp @@ -105,12 +105,12 @@ void QEglFSKmsEglDeviceScreen::waitForFlip() qErrnoWarning(errno, "drmModeSetCrtc failed"); } - if (!op.plane_set) { - op.plane_set = true; + if (!op.forced_plane_set) { + op.forced_plane_set = true; - if (op.wants_plane) { - qCDebug(qLcEglfsKmsDebug, "Setting plane %u", op.plane_id); - int ret = drmModeSetPlane(fd, op.plane_id, op.crtc_id, uint32_t(-1), 0, + if (op.wants_forced_plane) { + qCDebug(qLcEglfsKmsDebug, "Setting plane %u", op.forced_plane_id); + int ret = drmModeSetPlane(fd, op.forced_plane_id, op.crtc_id, uint32_t(-1), 0, 0, 0, w, h, 0 << 16, 0 << 16, w << 16, h << 16); if (ret == -1) diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsintegration.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsintegration.cpp index c77151181e..975b1947bf 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsintegration.cpp +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsintegration.cpp @@ -55,7 +55,7 @@ QT_BEGIN_NAMESPACE Q_LOGGING_CATEGORY(qLcEglfsKmsDebug, "qt.qpa.eglfs.kms") QEglFSKmsIntegration::QEglFSKmsIntegration() - : m_device(Q_NULLPTR), + : m_device(nullptr), m_screenConfig(new QKmsScreenConfig) { } @@ -78,7 +78,7 @@ void QEglFSKmsIntegration::platformDestroy() qCDebug(qLcEglfsKmsDebug, "platformDestroy: Closing DRM device"); m_device->close(); delete m_device; - m_device = Q_NULLPTR; + m_device = nullptr; } EGLNativeDisplayType QEglFSKmsIntegration::platformDisplay() const @@ -133,6 +133,14 @@ bool QEglFSKmsIntegration::supportsPBuffers() const return m_screenConfig->supportsPBuffers(); } +void *QEglFSKmsIntegration::nativeResourceForIntegration(const QByteArray &name) +{ + if (name == QByteArrayLiteral("dri_fd") && m_device) + return (void *) (qintptr) m_device->fd(); + + return nullptr; +} + QKmsDevice *QEglFSKmsIntegration::device() const { return m_device; diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsintegration.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsintegration.h index 9955616919..26ba2fdaec 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsintegration.h +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsintegration.h @@ -69,6 +69,7 @@ public: bool hasCapability(QPlatformIntegration::Capability cap) const override; void waitForVSync(QPlatformSurface *surface) const override; bool supportsPBuffers() const override; + void *nativeResourceForIntegration(const QByteArray &name) override; QKmsDevice *device() const; QKmsScreenConfig *screenConfig() const; 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 734f5cd611..5e45b42abe 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.cpp +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.cpp @@ -1,7 +1,7 @@ /**************************************************************************** ** +** Copyright (C) 2017 The Qt Company Ltd. ** Copyright (C) 2017 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com> -** Copyright (C) 2016 The Qt Company Ltd. ** Copyright (C) 2016 Pelagicore AG ** Contact: https://www.qt.io/licensing/ ** @@ -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(), m_output.modes[mode].hdisplay, @@ -117,12 +121,30 @@ QRect QEglFSKmsScreen::rawGeometry() const int QEglFSKmsScreen::depth() const { - return 32; + return format() == QImage::Format_RGB16 ? 16 : 32; } QImage::Format QEglFSKmsScreen::format() const { - return QImage::Format_RGB32; + // the result can be slightly incorrect, it won't matter in practice + switch (m_output.drm_format) { + case DRM_FORMAT_ARGB8888: + case DRM_FORMAT_ABGR8888: + return QImage::Format_ARGB32; + case DRM_FORMAT_RGB565: + case DRM_FORMAT_BGR565: + return QImage::Format_RGB16; + case DRM_FORMAT_XRGB2101010: + return QImage::Format_RGB30; + case DRM_FORMAT_XBGR2101010: + return QImage::Format_BGR30; + case DRM_FORMAT_ARGB2101010: + return QImage::Format_A2RGB30_Premultiplied; + case DRM_FORMAT_ABGR2101010: + return QImage::Format_A2BGR30_Premultiplied; + default: + return QImage::Format_RGB32; + } } QSizeF QEglFSKmsScreen::physicalSize() const @@ -159,7 +181,7 @@ Qt::ScreenOrientation QEglFSKmsScreen::orientation() const QString QEglFSKmsScreen::name() const { - return m_output.name; + return !m_headless ? m_output.name : QStringLiteral("qt_Headless"); } QString QEglFSKmsScreen::manufacturer() const @@ -177,22 +199,10 @@ QString QEglFSKmsScreen::serialNumber() const return m_edid.serialNumber; } -void QEglFSKmsScreen::destroySurface() -{ -} - void QEglFSKmsScreen::waitForFlip() { } -void QEglFSKmsScreen::flip() -{ -} - -void QEglFSKmsScreen::flipFinished() -{ -} - void QEglFSKmsScreen::restoreMode() { m_output.restoreMode(m_device); @@ -200,6 +210,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; } diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.h index 4e09929189..7f395aacb7 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.h +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.h @@ -56,7 +56,7 @@ class QEglFSKmsInterruptHandler; class Q_EGLFS_EXPORT QEglFSKmsScreen : public QEglFSScreen { public: - QEglFSKmsScreen(QKmsDevice *device, const QKmsOutput &output); + QEglFSKmsScreen(QKmsDevice *device, const QKmsOutput &output, bool headless = false); ~QEglFSKmsScreen(); void setVirtualPosition(const QPoint &pos); @@ -89,11 +89,7 @@ public: QKmsDevice *device() const { return m_device; } - void destroySurface(); - virtual void waitForFlip(); - virtual void flip(); - virtual void flipFinished(); QKmsOutput &output() { return m_output; } void restoreMode(); @@ -115,6 +111,8 @@ protected: PowerState m_powerState; QEglFSKmsInterruptHandler *m_interruptHandler; + + bool m_headless; }; QT_END_NAMESPACE |