diff options
Diffstat (limited to 'src/plugins/platforms/eglfs/deviceintegration')
25 files changed, 302 insertions, 114 deletions
diff --git a/src/plugins/platforms/eglfs/deviceintegration/CMakeLists.txt b/src/plugins/platforms/eglfs/deviceintegration/CMakeLists.txt index 9e1c31527e..bb50216f23 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/CMakeLists.txt +++ b/src/plugins/platforms/eglfs/deviceintegration/CMakeLists.txt @@ -1,4 +1,5 @@ -# Generated from deviceintegration.pro. +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause if(QT_FEATURE_eglfs_x11) add_subdirectory(eglfs_x11) @@ -13,10 +14,10 @@ if(QT_FEATURE_eglfs_egldevice) add_subdirectory(eglfs_kms_egldevice) endif() if(QT_FEATURE_eglfs_vsp2) - # add_subdirectory(eglfs_kms_vsp2) # special case TODO + # add_subdirectory(eglfs_kms_vsp2) # TODO: QTBUG-112769 endif() if(QT_FEATURE_eglfs_brcm) - # add_subdirectory(eglfs_brcm) # special case TODO + # add_subdirectory(eglfs_brcm) # TODO: QTBUG-112769 endif() if(QT_FEATURE_eglfs_mali) add_subdirectory(eglfs_mali) @@ -25,7 +26,7 @@ if(QT_FEATURE_eglfs_viv) add_subdirectory(eglfs_viv) endif() if(QT_FEATURE_eglfs_rcar) - # add_subdirectory(eglfs_rcar) # special case TODO + # add_subdirectory(eglfs_rcar) # TODO: QTBUG-112769 endif() if(QT_FEATURE_eglfs_viv_wl) add_subdirectory(eglfs_viv_wl) diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_emu/CMakeLists.txt b/src/plugins/platforms/eglfs/deviceintegration/eglfs_emu/CMakeLists.txt index e1de63ea42..fa744be033 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_emu/CMakeLists.txt +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_emu/CMakeLists.txt @@ -1,4 +1,5 @@ -# Generated from eglfs_emu.pro. +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## QEglFSEmulatorIntegrationPlugin Plugin: @@ -22,7 +23,3 @@ qt_internal_add_plugin(QEglFSEmulatorIntegrationPlugin Qt::Gui Qt::GuiPrivate ) - -#### Keys ignored in scope 1:.:.:eglfs_emu.pro:<TRUE>: -# DISTFILES = "eglfs_emu.json" -# OTHER_FILES = "$$PWD/eglfs_emu.json" diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_emu/qeglfsemulatorintegration.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_emu/qeglfsemulatorintegration.cpp index ed55420c57..a63aafa242 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_emu/qeglfsemulatorintegration.cpp +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_emu/qeglfsemulatorintegration.cpp @@ -93,7 +93,7 @@ EGLNativeWindowType QEglFSEmulatorIntegration::createNativeWindow(QPlatformWindo // Let the emulator know which screen the window surface is attached to setDisplay(screen->id()); } - static QBasicAtomicInt uniqueWindowId = Q_BASIC_ATOMIC_INITIALIZER(0); + Q_CONSTINIT static QBasicAtomicInt uniqueWindowId = Q_BASIC_ATOMIC_INITIALIZER(0); return EGLNativeWindowType(qintptr(1 + uniqueWindowId.fetchAndAddRelaxed(1))); } diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/CMakeLists.txt b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/CMakeLists.txt index a20a4a084d..9f9d315202 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/CMakeLists.txt +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/CMakeLists.txt @@ -1,4 +1,5 @@ -# Generated from eglfs_kms.pro. +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## EglFsKmsGbmSupportPrivate Module: @@ -23,6 +24,7 @@ qt_internal_add_module(EglFsKmsGbmSupportPrivate Qt::GuiPrivate Qt::KmsSupportPrivate gbm::gbm + NO_GENERATE_CPP_EXPORTS ) ##################################################################### ## QEglFSKmsGbmIntegrationPlugin Plugin: @@ -45,6 +47,3 @@ qt_internal_add_plugin(QEglFSKmsGbmIntegrationPlugin Qt::KmsSupportPrivate gbm::gbm ) - -#### Keys ignored in scope 3:.:.:eglfs_kms-plugin.pro:<TRUE>: -# OTHER_FILES = "$$PWD/eglfs_kms.json" diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.cpp index 6d903a3f1e..89479fc250 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.cpp +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.cpp @@ -47,7 +47,13 @@ bool QEglFSKmsGbmDevice::open() setFd(fd); - m_eventReader.create(this); + if (usesEventReader()) { + qCDebug(qLcEglfsKmsDebug, "Using dedicated drm event reading thread"); + m_eventReader.create(this); + } else { + qCDebug(qLcEglfsKmsDebug, "Not using dedicated drm event reading thread; " + "threaded multi-screen setups may experience problems"); + } return true; } @@ -56,7 +62,8 @@ void QEglFSKmsGbmDevice::close() { // Note: screens are gone at this stage. - m_eventReader.destroy(); + if (usesEventReader()) + m_eventReader.destroy(); if (m_gbm_device) { gbm_device_destroy(m_gbm_device); @@ -138,4 +145,10 @@ void QEglFSKmsGbmDevice::registerScreen(QPlatformScreen *screen, m_globalCursor->reevaluateVisibilityForScreens(); } +bool QEglFSKmsGbmDevice::usesEventReader() const +{ + static const bool eventReaderThreadDisabled = qEnvironmentVariableIntValue("QT_QPA_EGLFS_KMS_NO_EVENT_READER_THREAD"); + return !eventReaderThreadDisabled; +} + QT_END_NAMESPACE diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice_p.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice_p.h index 832b3a2873..e00992ed29 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice_p.h +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice_p.h @@ -19,6 +19,7 @@ #include "qeglfskmsgbmcursor_p.h" #include <private/qeglfskmsdevice_p.h> +#include <private/qeglfskmseventreader_p.h> #include <gbm.h> @@ -51,11 +52,14 @@ public: const QPoint &virtualPos, const QList<QPlatformScreen *> &virtualSiblings) override; + bool usesEventReader() const; + QEglFSKmsEventReader *eventReader() { return &m_eventReader; } + private: Q_DISABLE_COPY(QEglFSKmsGbmDevice) gbm_device *m_gbm_device; - + QEglFSKmsEventReader m_eventReader; QEglFSKmsGbmCursor *m_globalCursor; }; diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.cpp index 9aa815ba90..8dcfed04db 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.cpp +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.cpp @@ -20,6 +20,8 @@ QT_BEGIN_NAMESPACE Q_DECLARE_LOGGING_CATEGORY(qLcEglfsKmsDebug) +QMutex QEglFSKmsGbmScreen::m_nonThreadedFlipMutex; + static inline uint32_t drmFormatToGbmFormat(uint32_t drmFormat) { Q_ASSERT(DRM_FORMAT_XRGB8888 == GBM_FORMAT_XRGB8888); @@ -71,8 +73,9 @@ QEglFSKmsGbmScreen::FrameBuffer *QEglFSKmsGbmScreen::framebufferForBufferObject( return nullptr; } - gbm_bo_set_user_data(bo, fb.get(), bufferDestroyedHandler); - return fb.release(); + auto res = fb.get(); + gbm_bo_set_user_data(bo, fb.release(), bufferDestroyedHandler); + return res; } QEglFSKmsGbmScreen::QEglFSKmsGbmScreen(QEglFSKmsDevice *device, const QKmsOutput &output, bool headless) @@ -140,11 +143,12 @@ gbm_surface *QEglFSKmsGbmScreen::createSurface(EGLConfig eglConfig) } } + const uint32_t gbmFormat = drmFormatToGbmFormat(m_output.drm_format); + // Fallback for older drivers, and when "format" is explicitly specified // in the output config. (not guaranteed that the requested format works // of course, but do what we are told to) if (!m_gbm_surface) { - uint32_t gbmFormat = drmFormatToGbmFormat(m_output.drm_format); if (queryFromEgl) qCDebug(qLcEglfsKmsDebug, "Could not create surface with EGL_NATIVE_VISUAL_ID, falling back to format %x", gbmFormat); m_gbm_surface = gbm_surface_create(gbmDevice, @@ -153,13 +157,39 @@ gbm_surface *QEglFSKmsGbmScreen::createSurface(EGLConfig eglConfig) gbmFormat, gbmFlags()); } + + // Fallback for some drivers, its required to request with modifiers + if (!m_gbm_surface) { + uint64_t modifier = DRM_FORMAT_MOD_LINEAR; + + m_gbm_surface = gbm_surface_create_with_modifiers(gbmDevice, + rawGeometry().width(), + rawGeometry().height(), + gbmFormat, + &modifier, 1); + } + // Fail here, as it would fail with the next usage of the GBM surface, which is very unexpected + if (!m_gbm_surface) + qFatal("Could not create GBM surface!"); } return m_gbm_surface; // not owned, gets destroyed in QEglFSKmsGbmIntegration::destroyNativeWindow() via QEglFSKmsGbmWindow::invalidateSurface() } void QEglFSKmsGbmScreen::resetSurface() { + m_flipPending = false; // not necessarily true but enough to keep bo_next + m_gbm_bo_current = nullptr; m_gbm_surface = nullptr; + + // Leave m_gbm_bo_next untouched. waitForFlip() should + // still do its work, when called. Otherwise we end up + // in device-is-busy errors if there is a new QWindow + // created afterwards. (QTBUG-122663) + + // If not using atomic, will need a new drmModeSetCrtc if a new window + // gets created later on (and so there's a new fb). + if (!device()->hasAtomicSupport()) + needsNewModeSetForNextFb = true; } void QEglFSKmsGbmScreen::initCloning(QPlatformScreen *screenThisScreenClones, @@ -171,8 +201,10 @@ void QEglFSKmsGbmScreen::initCloning(QPlatformScreen *screenThisScreenClones, qWarning("QEglFSKmsGbmScreen %s cannot be clone source and destination at the same time", qPrintable(name())); return; } - if (clonesAnother) + if (clonesAnother) { m_cloneSource = static_cast<QEglFSKmsGbmScreen *>(screenThisScreenClones); + qCDebug(qLcEglfsKmsDebug, "Screen %s clones %s", qPrintable(name()), qPrintable(m_cloneSource->name())); + } // clone sources need to know their additional destinations for (QPlatformScreen *s : screensCloningThisScreen) { @@ -187,8 +219,9 @@ void QEglFSKmsGbmScreen::ensureModeSet(uint32_t fb) QKmsOutput &op(output()); const int fd = device()->fd(); - if (!op.mode_set) { + if (!op.mode_set || needsNewModeSetForNextFb) { op.mode_set = true; + needsNewModeSetForNextFb = false; bool doModeSet = true; drmModeCrtcPtr currentMode = drmModeGetCrtc(fd, op.crtc_id); @@ -227,6 +260,29 @@ void QEglFSKmsGbmScreen::ensureModeSet(uint32_t fb) } } +void QEglFSKmsGbmScreen::nonThreadedPageFlipHandler(int fd, + unsigned int sequence, + unsigned int tv_sec, + unsigned int tv_usec, + void *user_data) +{ + // note that with cloning involved this callback is called also for screens that clone another one + Q_UNUSED(fd); + QEglFSKmsGbmScreen *screen = static_cast<QEglFSKmsGbmScreen *>(user_data); + screen->flipFinished(); + screen->pageFlipped(sequence, tv_sec, tv_usec); +} + +void QEglFSKmsGbmScreen::waitForFlipWithEventReader(QEglFSKmsGbmScreen *screen) +{ + m_flipMutex.lock(); + QEglFSKmsGbmDevice *dev = static_cast<QEglFSKmsGbmDevice *>(device()); + dev->eventReader()->startWaitFlip(screen, &m_flipMutex, &m_flipCond); + m_flipCond.wait(&m_flipMutex); + m_flipMutex.unlock(); + screen->flipFinished(); +} + void QEglFSKmsGbmScreen::waitForFlip() { if (m_headless || m_cloneSource) @@ -236,18 +292,69 @@ void QEglFSKmsGbmScreen::waitForFlip() if (!m_gbm_bo_next) return; - m_flipMutex.lock(); - device()->eventReader()->startWaitFlip(this, &m_flipMutex, &m_flipCond); - m_flipCond.wait(&m_flipMutex); - m_flipMutex.unlock(); - - flipFinished(); + QEglFSKmsGbmDevice *dev = static_cast<QEglFSKmsGbmDevice *>(device()); + if (dev->usesEventReader()) { + waitForFlipWithEventReader(this); + // Now, unlike on the other code path, we need to ensure the + // flips have completed for the screens that just scan out + // this one's content, because the eventReader's wait is + // per-output. + for (CloneDestination &d : m_cloneDests) { + if (d.screen != this) + waitForFlipWithEventReader(d.screen); + } + } else { + QMutexLocker lock(&m_nonThreadedFlipMutex); + while (m_gbm_bo_next) { + drmEventContext drmEvent; + memset(&drmEvent, 0, sizeof(drmEvent)); + drmEvent.version = 2; + drmEvent.vblank_handler = nullptr; + drmEvent.page_flip_handler = nonThreadedPageFlipHandler; + drmHandleEvent(device()->fd(), &drmEvent); + } + } #if QT_CONFIG(drm_atomic) device()->threadLocalAtomicReset(); #endif } +#if QT_CONFIG(drm_atomic) +static void addAtomicFlip(drmModeAtomicReq *request, const QKmsOutput &output, uint32_t fb) +{ + drmModeAtomicAddProperty(request, output.eglfs_plane->id, + output.eglfs_plane->framebufferPropertyId, fb); + + drmModeAtomicAddProperty(request, output.eglfs_plane->id, + output.eglfs_plane->crtcPropertyId, output.crtc_id); + + drmModeAtomicAddProperty(request, output.eglfs_plane->id, + output.eglfs_plane->srcwidthPropertyId, output.size.width() << 16); + + drmModeAtomicAddProperty(request, output.eglfs_plane->id, + output.eglfs_plane->srcXPropertyId, 0); + + drmModeAtomicAddProperty(request, output.eglfs_plane->id, + output.eglfs_plane->srcYPropertyId, 0); + + drmModeAtomicAddProperty(request, output.eglfs_plane->id, + output.eglfs_plane->srcheightPropertyId, output.size.height() << 16); + + drmModeAtomicAddProperty(request, output.eglfs_plane->id, + output.eglfs_plane->crtcXPropertyId, 0); + + drmModeAtomicAddProperty(request, output.eglfs_plane->id, + output.eglfs_plane->crtcYPropertyId, 0); + + drmModeAtomicAddProperty(request, output.eglfs_plane->id, + output.eglfs_plane->crtcwidthPropertyId, output.modes[output.mode].hdisplay); + + drmModeAtomicAddProperty(request, output.eglfs_plane->id, + output.eglfs_plane->crtcheightPropertyId, output.modes[output.mode].vdisplay); +} +#endif + void QEglFSKmsGbmScreen::flip() { // For headless screen just return silently. It is not necessarily an error @@ -267,14 +374,24 @@ void QEglFSKmsGbmScreen::flip() m_gbm_bo_next = gbm_surface_lock_front_buffer(m_gbm_surface); if (!m_gbm_bo_next) { - qWarning("Could not lock GBM surface front buffer!"); + qWarning("Could not lock GBM surface front buffer for screen %s", qPrintable(name())); return; } + auto gbmRelease = qScopeGuard([this]{ + m_flipPending = false; + gbm_surface_release_buffer(m_gbm_surface, m_gbm_bo_next); + m_gbm_bo_next = nullptr; + }); + FrameBuffer *fb = framebufferForBufferObject(m_gbm_bo_next); + if (!fb) { + qWarning("FrameBuffer not available. Cannot flip"); + return; + } ensureModeSet(fb->fb); - QKmsOutput &op(output()); + const QKmsOutput &thisOutput(output()); const int fd = device()->fd(); m_flipPending = true; @@ -282,40 +399,27 @@ void QEglFSKmsGbmScreen::flip() #if QT_CONFIG(drm_atomic) drmModeAtomicReq *request = device()->threadLocalAtomicRequest(); if (request) { - drmModeAtomicAddProperty(request, op.eglfs_plane->id, op.eglfs_plane->framebufferPropertyId, fb->fb); - drmModeAtomicAddProperty(request, op.eglfs_plane->id, op.eglfs_plane->crtcPropertyId, op.crtc_id); - drmModeAtomicAddProperty(request, op.eglfs_plane->id, op.eglfs_plane->srcwidthPropertyId, - op.size.width() << 16); - drmModeAtomicAddProperty(request, op.eglfs_plane->id, op.eglfs_plane->srcXPropertyId, 0); - drmModeAtomicAddProperty(request, op.eglfs_plane->id, op.eglfs_plane->srcYPropertyId, 0); - drmModeAtomicAddProperty(request, op.eglfs_plane->id, op.eglfs_plane->srcheightPropertyId, - op.size.height() << 16); - drmModeAtomicAddProperty(request, op.eglfs_plane->id, op.eglfs_plane->crtcXPropertyId, 0); - drmModeAtomicAddProperty(request, op.eglfs_plane->id, op.eglfs_plane->crtcYPropertyId, 0); - drmModeAtomicAddProperty(request, op.eglfs_plane->id, op.eglfs_plane->crtcwidthPropertyId, - m_output.modes[m_output.mode].hdisplay); - drmModeAtomicAddProperty(request, op.eglfs_plane->id, op.eglfs_plane->crtcheightPropertyId, - m_output.modes[m_output.mode].vdisplay); - + addAtomicFlip(request, thisOutput, fb->fb); static int zpos = qEnvironmentVariableIntValue("QT_QPA_EGLFS_KMS_ZPOS"); - if (zpos) - drmModeAtomicAddProperty(request, op.eglfs_plane->id, op.eglfs_plane->zposPropertyId, zpos); + if (zpos) { + drmModeAtomicAddProperty(request, thisOutput.eglfs_plane->id, + thisOutput.eglfs_plane->zposPropertyId, zpos); + } static uint blendOp = uint(qEnvironmentVariableIntValue("QT_QPA_EGLFS_KMS_BLEND_OP")); - if (blendOp) - drmModeAtomicAddProperty(request, op.eglfs_plane->id, op.eglfs_plane->blendOpPropertyId, blendOp); + if (blendOp) { + drmModeAtomicAddProperty(request, thisOutput.eglfs_plane->id, + thisOutput.eglfs_plane->blendOpPropertyId, blendOp); + } } #endif } else { int ret = drmModePageFlip(fd, - op.crtc_id, - fb->fb, - DRM_MODE_PAGE_FLIP_EVENT, - this); + thisOutput.crtc_id, + fb->fb, + DRM_MODE_PAGE_FLIP_EVENT, + this); if (ret) { 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 = nullptr; return; } } @@ -324,34 +428,46 @@ void QEglFSKmsGbmScreen::flip() if (d.screen != this) { d.screen->ensureModeSet(fb->fb); d.cloneFlipPending = true; + const QKmsOutput &destOutput(d.screen->output()); if (device()->hasAtomicSupport()) { #if QT_CONFIG(drm_atomic) drmModeAtomicReq *request = device()->threadLocalAtomicRequest(); - if (request) { - drmModeAtomicAddProperty(request, d.screen->output().eglfs_plane->id, - d.screen->output().eglfs_plane->framebufferPropertyId, fb->fb); - drmModeAtomicAddProperty(request, d.screen->output().eglfs_plane->id, - d.screen->output().eglfs_plane->crtcPropertyId, op.crtc_id); - } + if (request) + addAtomicFlip(request, destOutput, fb->fb); + + // ### This path is broken. On the other branch we can easily + // pass in d.screen as the user_data for drmModePageFlip, but + // using one atomic request breaks down here since we get events + // with the same user_data passed to drmModeAtomicCommit. Until + // this gets reworked (multiple requests?) screen cloning is not + // compatible with atomic. #endif } else { int ret = drmModePageFlip(fd, - d.screen->output().crtc_id, + destOutput.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())); + qErrnoWarning("Could not queue DRM page flip for screen %s (clones screen %s)", + qPrintable(d.screen->name()), + qPrintable(name())); d.cloneFlipPending = false; } } } } + if (device()->hasAtomicSupport()) { #if QT_CONFIG(drm_atomic) - device()->threadLocalAtomicCommit(this); + if (!device()->threadLocalAtomicCommit(this)) { + return; + } #endif + } + + gbmRelease.dismiss(); } void QEglFSKmsGbmScreen::flipFinished() @@ -378,19 +494,23 @@ void QEglFSKmsGbmScreen::cloneDestFlipFinished(QEglFSKmsGbmScreen *cloneDestScre void QEglFSKmsGbmScreen::updateFlipStatus() { - Q_ASSERT(!m_cloneSource); + // only for 'real' outputs that own the color buffer, i.e. that are not cloning another one + if (m_cloneSource) + return; + // proceed only if flips for both this and all others that clone this have finished if (m_flipPending) return; - for (const CloneDestination &d : qAsConst(m_cloneDests)) { + for (const CloneDestination &d : std::as_const(m_cloneDests)) { if (d.cloneFlipPending) return; } - if (m_gbm_bo_current) + 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 = nullptr; diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen_p.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen_p.h index d2882038bd..aca34fcae2 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen_p.h +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen_p.h @@ -52,6 +52,12 @@ protected: void flipFinished(); void ensureModeSet(uint32_t fb); void cloneDestFlipFinished(QEglFSKmsGbmScreen *cloneDestScreen); + void waitForFlipWithEventReader(QEglFSKmsGbmScreen *screen); + static void nonThreadedPageFlipHandler(int fd, + unsigned int sequence, + unsigned int tv_sec, + unsigned int tv_usec, + void *user_data); gbm_surface *m_gbm_surface; @@ -61,6 +67,7 @@ protected: QMutex m_flipMutex; QWaitCondition m_flipCond; + static QMutex m_nonThreadedFlipMutex; QScopedPointer<QEglFSKmsGbmCursor> m_cursor; @@ -76,6 +83,8 @@ protected: bool cloneFlipPending = false; }; QList<CloneDestination> m_cloneDests; + + bool needsNewModeSetForNextFb = false; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/CMakeLists.txt b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/CMakeLists.txt index a9be917555..3c3e5a8a6c 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/CMakeLists.txt +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/CMakeLists.txt @@ -1,4 +1,5 @@ -# Generated from eglfs_kms_egldevice.pro. +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## QEglFSKmsEglDeviceIntegrationPlugin Plugin: @@ -24,6 +25,3 @@ qt_internal_add_plugin(QEglFSKmsEglDeviceIntegrationPlugin Qt::GuiPrivate Qt::KmsSupportPrivate ) - -#### Keys ignored in scope 1:.:.:eglfs_kms_egldevice.pro:<TRUE>: -# OTHER_FILES = "$$PWD/eglfs_kms_egldevice.json" 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 3a79ebb7b4..a213bc9bba 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.cpp +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.cpp @@ -38,8 +38,11 @@ EGLDisplay QEglFSKmsEglDeviceIntegration::createDisplay(EGLNativeDisplayType nat EGLDisplay display; + EGLint egldevice_fd = device()->fd(); + + const EGLint attribs[] = { EGL_DRM_MASTER_FD_EXT, egldevice_fd, EGL_NONE }; if (m_funcs->has_egl_platform_device) { - display = m_funcs->get_platform_display(EGL_PLATFORM_DEVICE_EXT, nativeDisplay, nullptr); + display = m_funcs->get_platform_display(EGL_PLATFORM_DEVICE_EXT, nativeDisplay, attribs); } else { qWarning("EGL_EXT_platform_device not available, falling back to legacy path!"); display = eglGetDisplay(nativeDisplay); @@ -168,7 +171,7 @@ void QEglFSKmsEglDeviceWindow::resetSurface() QByteArray reqLayerIndex = qgetenv("QT_QPA_EGLFS_LAYER_INDEX"); if (!reqLayerIndex.isEmpty()) { int idx = reqLayerIndex.toInt(); - if (idx >= 0 && idx < layers.count()) { + if (idx >= 0 && idx < layers.size()) { qCDebug(qLcEglfsKmsDebug, "EGLOutput layer index override = %d", idx); layer = layers[idx]; } 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 eadb079f70..3fc46cd224 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevicescreen.cpp +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevicescreen.cpp @@ -13,12 +13,63 @@ Q_DECLARE_LOGGING_CATEGORY(qLcEglfsKmsDebug) QEglFSKmsEglDeviceScreen::QEglFSKmsEglDeviceScreen(QEglFSKmsDevice *device, const QKmsOutput &output) : QEglFSKmsScreen(device, output) + , m_default_fb_handle(uint32_t(-1)) + , m_default_fb_id(uint32_t(-1)) { + const int fd = device->fd(); + + struct drm_mode_create_dumb createRequest; + createRequest.width = output.size.width(); + createRequest.height = output.size.height(); + createRequest.bpp = 32; + createRequest.flags = 0; + + qCDebug(qLcEglfsKmsDebug, "Creating dumb fb %dx%d", createRequest.width, createRequest.height); + + int ret = drmIoctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &createRequest); + if (ret < 0) + qFatal("Unable to create dumb buffer.\n"); + + m_default_fb_handle = createRequest.handle; + + uint32_t handles[4] = { 0, 0, 0, 0 }; + uint32_t pitches[4] = { 0, 0, 0, 0 }; + uint32_t offsets[4] = { 0, 0, 0, 0 }; + + handles[0] = createRequest.handle; + pitches[0] = createRequest.pitch; + offsets[0] = 0; + + ret = drmModeAddFB2(fd, createRequest.width, createRequest.height, DRM_FORMAT_ARGB8888, handles, + pitches, offsets, &m_default_fb_id, 0); + if (ret) + qFatal("Unable to add fb\n"); + + qCDebug(qLcEglfsKmsDebug, "Added dumb fb %dx%d handle:%u pitch:%d id:%u", createRequest.width, createRequest.height, + createRequest.handle, createRequest.pitch, m_default_fb_id); } QEglFSKmsEglDeviceScreen::~QEglFSKmsEglDeviceScreen() { - const int remainingScreenCount = qGuiApp->screens().count(); + int ret; + const int fd = device()->fd(); + + if (m_default_fb_id != uint32_t(-1)) { + ret = drmModeRmFB(fd, m_default_fb_id); + if (ret) + qErrnoWarning("drmModeRmFB failed"); + } + + if (m_default_fb_handle != uint32_t(-1)) { + struct drm_mode_destroy_dumb destroyRequest; + destroyRequest.handle = m_default_fb_handle; + + ret = drmIoctl(fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroyRequest); + if (ret) + qErrnoWarning("DRM_IOCTL_MODE_DESTROY_DUMB failed"); + } + + const int remainingScreenCount = qGuiApp->screens().size(); qCDebug(qLcEglfsKmsDebug, "Screen dtor. Remaining screens: %d", remainingScreenCount); if (!remainingScreenCount && !device()->screenConfig()->separateScreens()) static_cast<QEglFSKmsEglDevice *>(device())->destroyGlobalCursor(); @@ -53,8 +104,11 @@ void QEglFSKmsEglDeviceScreen::waitForFlip() if (alreadySet) { // Maybe detecting the DPMS mode could help here, but there are no properties // exposed on the connector apparently. So rely on an env var for now. - static bool alwaysDoSet = qEnvironmentVariableIntValue("QT_QPA_EGLFS_ALWAYS_SET_MODE"); - if (!alwaysDoSet) { + // Note that typically, we need to set crtc with the default fb even if the + // mode did not change, unless QT_QPA_EGLFS_ALWAYS_SET_MODE is explicitly specified. + static bool envVarSet = false; + static bool alwaysDoSet = qEnvironmentVariableIntValue("QT_QPA_EGLFS_ALWAYS_SET_MODE", &envVarSet); + if (envVarSet && !alwaysDoSet) { qCDebug(qLcEglfsKmsDebug, "Mode already set"); return; } @@ -62,7 +116,7 @@ void QEglFSKmsEglDeviceScreen::waitForFlip() qCDebug(qLcEglfsKmsDebug, "Setting mode"); int ret = drmModeSetCrtc(fd, op.crtc_id, - uint32_t(-1), 0, 0, + m_default_fb_id, 0, 0, &op.connector_id, 1, &op.modes[op.mode]); if (ret) @@ -74,7 +128,7 @@ void QEglFSKmsEglDeviceScreen::waitForFlip() 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, + int ret = drmModeSetPlane(fd, op.forced_plane_id, op.crtc_id, m_default_fb_id, 0, 0, 0, w, h, 0 << 16, 0 << 16, op.size.width() << 16, op.size.height() << 16); if (ret == -1) diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevicescreen.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevicescreen.h index 884a70093a..8779499bef 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevicescreen.h +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevicescreen.h @@ -17,6 +17,9 @@ public: QPlatformCursor *cursor() const override; void waitForFlip() override; +private: + uint32_t m_default_fb_handle; + uint32_t m_default_fb_id; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/CMakeLists.txt b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/CMakeLists.txt index f9458ae5c6..5fcc0e1b18 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/CMakeLists.txt +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/CMakeLists.txt @@ -1,4 +1,5 @@ -# Generated from eglfs_kms_support.pro. +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## EglFsKmsSupportPrivate Module: @@ -23,4 +24,5 @@ qt_internal_add_module(EglFsKmsSupportPrivate Qt::Gui Qt::GuiPrivate Qt::KmsSupportPrivate + NO_GENERATE_CPP_EXPORTS ) diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsdevice_p.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsdevice_p.h index 7dc5235d33..6e11953a69 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsdevice_p.h +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsdevice_p.h @@ -17,7 +17,6 @@ // #include "private/qeglfsglobal_p.h" -#include "qeglfskmseventreader_p.h" #include <QtKmsSupport/private/qkmsdevice_p.h> QT_BEGIN_NAMESPACE @@ -31,11 +30,6 @@ public: bool isPrimary, const QPoint &virtualPos, const QList<QPlatformScreen *> &virtualSiblings) override; - - QEglFSKmsEventReader *eventReader() { return &m_eventReader; } - -protected: - QEglFSKmsEventReader m_eventReader; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmseventreader.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmseventreader.cpp index 77e66ed473..96cdcd8947 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmseventreader.cpp +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmseventreader.cpp @@ -144,7 +144,7 @@ void QEglFSKmsEventReader::create(QEglFSKmsDevice *device) m_device = device; - qCDebug(qLcEglfsKmsDebug, "Initalizing event reader for device %p fd %d", + qCDebug(qLcEglfsKmsDebug, "Initializing event reader for device %p fd %d", m_device, m_device->fd()); m_thread = new QEglFSKmsEventReaderThread(m_device->fd()); diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsintegration_p.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsintegration_p.h index 7000b9d35e..36e65a0bd4 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsintegration_p.h +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsintegration_p.h @@ -27,7 +27,7 @@ QT_BEGIN_NAMESPACE class QKmsDevice; class QKmsScreenConfig; -Q_EGLFS_EXPORT Q_DECLARE_LOGGING_CATEGORY(qLcEglfsKmsDebug) +Q_DECLARE_EXPORTED_LOGGING_CATEGORY(qLcEglfsKmsDebug, Q_EGLFS_EXPORT) class Q_EGLFS_EXPORT QEglFSKmsIntegration : public QEglFSDeviceIntegration { 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 cc52d371e3..369356b761 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.cpp +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.cpp @@ -185,7 +185,7 @@ QList<QPlatformScreen::Mode> QEglFSKmsScreen::modes() const QList<QPlatformScreen::Mode> list; list.reserve(m_output.modes.size()); - for (const drmModeModeInfo &info : qAsConst(m_output.modes)) + for (const drmModeModeInfo &info : std::as_const(m_output.modes)) list.append({QSize(info.hdisplay, info.vdisplay), qreal(info.vrefresh > 0 ? info.vrefresh : 60)}); diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qlinuxmediadevice.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qlinuxmediadevice.cpp index 44555b85b5..5d2900097e 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qlinuxmediadevice.cpp +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qlinuxmediadevice.cpp @@ -200,7 +200,7 @@ bool QLinuxMediaDevice::resetLinks() struct media_link *QLinuxMediaDevice::parseLink(const QString &link) { - char *endp = nullptr;; + char *endp = nullptr; struct media_link *mediaLink = media_parse_link(m_mediaDevice, link.toStdString().c_str(), &endp); if (!mediaLink) diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qvsp2blendingdevice.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qvsp2blendingdevice.cpp index 40cdd78e56..e7e3c76190 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qvsp2blendingdevice.cpp +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qvsp2blendingdevice.cpp @@ -205,7 +205,7 @@ bool QVsp2BlendingDevice::blend(int outputDmabufFd) if (queueingFailed) { qWarning() << "Vsp2: Trying to clean up queued buffers"; - for (auto &input : qAsConst(m_inputs)) { + for (auto &input : std::as_const(m_inputs)) { if (input.enabled) { if (!input.rpfInput->clearBuffers()) qWarning() << "Vsp2: Failed to remove buffers after an aborted blend"; @@ -248,7 +248,7 @@ int QVsp2BlendingDevice::numInputs() const bool QVsp2BlendingDevice::hasContinuousLayers() const { bool seenDisabled = false; - for (auto &input : qAsConst(m_inputs)) { + for (auto &input : std::as_const(m_inputs)) { if (seenDisabled && input.enabled) return false; seenDisabled |= !input.enabled; diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_mali/CMakeLists.txt b/src/plugins/platforms/eglfs/deviceintegration/eglfs_mali/CMakeLists.txt index 7550529f79..38981f87b9 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_mali/CMakeLists.txt +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_mali/CMakeLists.txt @@ -1,4 +1,5 @@ -# Generated from eglfs_mali.pro. +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## QEglFSMaliIntegrationPlugin Plugin: @@ -21,6 +22,3 @@ qt_internal_add_plugin(QEglFSMaliIntegrationPlugin Qt::Gui Qt::GuiPrivate ) - -#### Keys ignored in scope 1:.:.:eglfs_mali.pro:<TRUE>: -# OTHER_FILES = "$$PWD/eglfs_mali.json" diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_openwfd/CMakeLists.txt b/src/plugins/platforms/eglfs/deviceintegration/eglfs_openwfd/CMakeLists.txt index fb8b79454d..7e2362e627 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_openwfd/CMakeLists.txt +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_openwfd/CMakeLists.txt @@ -1,4 +1,5 @@ -# Generated from openwfd.pro. +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## QEglFSOpenWFDIntegrationPlugin Plugin: @@ -19,6 +20,3 @@ qt_internal_add_plugin(QEglFSOpenWFDIntegrationPlugin Qt::Gui Qt::GuiPrivate ) - -#### Keys ignored in scope 1:.:.:openwfd.pro:<TRUE>: -# OTHER_FILES = "$$PWD/eglfs_openwfd.json" diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_viv/CMakeLists.txt b/src/plugins/platforms/eglfs/deviceintegration/eglfs_viv/CMakeLists.txt index 988ab76d79..01defc9242 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_viv/CMakeLists.txt +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_viv/CMakeLists.txt @@ -1,4 +1,5 @@ -# Generated from eglfs_viv.pro. +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## QEglFSVivIntegrationPlugin Plugin: @@ -22,6 +23,3 @@ qt_internal_add_plugin(QEglFSVivIntegrationPlugin Qt::Gui Qt::GuiPrivate ) - -#### Keys ignored in scope 1:.:.:eglfs_viv.pro:<TRUE>: -# OTHER_FILES = "$$PWD/eglfs_viv.json" diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_viv_wl/CMakeLists.txt b/src/plugins/platforms/eglfs/deviceintegration/eglfs_viv_wl/CMakeLists.txt index cb07c9aecc..6052e98ab8 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_viv_wl/CMakeLists.txt +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_viv_wl/CMakeLists.txt @@ -1,4 +1,5 @@ -# Generated from eglfs_viv_wl.pro. +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## QEglFSVivWaylandIntegrationPlugin Plugin: @@ -23,6 +24,3 @@ qt_internal_add_plugin(QEglFSVivWaylandIntegrationPlugin Qt::Gui Qt::GuiPrivate ) - -#### Keys ignored in scope 1:.:.:eglfs_viv_wl.pro:<TRUE>: -# OTHER_FILES = "$$PWD/eglfs_viv_wl.json" diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_x11/CMakeLists.txt b/src/plugins/platforms/eglfs/deviceintegration/eglfs_x11/CMakeLists.txt index 18bb02efe0..9dde3090c8 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_x11/CMakeLists.txt +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_x11/CMakeLists.txt @@ -1,4 +1,5 @@ -# Generated from eglfs_x11.pro. +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## QEglFSX11IntegrationPlugin Plugin: @@ -23,7 +24,5 @@ qt_internal_add_plugin(QEglFSX11IntegrationPlugin X11::X11 X11::XCB XCB::XCB + NO_UNITY_BUILD # X11 define clashes ) - -#### Keys ignored in scope 1:.:.:eglfs_x11.pro:<TRUE>: -# OTHER_FILES = "$$PWD/eglfs_x11.json" diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_x11/qeglfsx11integration.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_x11/qeglfsx11integration.cpp index 39ec35df9e..8f491274d5 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_x11/qeglfsx11integration.cpp +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_x11/qeglfsx11integration.cpp @@ -25,7 +25,7 @@ private: QEglFSX11Integration *m_integration; }; -static QBasicAtomicInt running; +Q_CONSTINIT static QBasicAtomicInt running = Q_BASIC_ATOMIC_INITIALIZER(0); void EventReader::run() { @@ -115,7 +115,7 @@ QSize QEglFSX11Integration::screenSize() const { if (m_screenSize.isEmpty()) { QList<QByteArray> env = qgetenv("EGLFS_X11_SIZE").split('x'); - if (env.length() == 2) { + if (env.size() == 2) { m_screenSize = QSize(env.at(0).toInt(), env.at(1).toInt()); } else { XWindowAttributes a; |