diff options
-rw-r--r-- | src/core/aspects/aspects.pri | 6 | ||||
-rw-r--r-- | src/core/aspects/qaspectengine.cpp | 45 | ||||
-rw-r--r-- | src/core/aspects/qaspectengine_p.h | 4 | ||||
-rw-r--r-- | src/core/aspects/qaspectmanager.cpp | 265 | ||||
-rw-r--r-- | src/core/aspects/qaspectmanager_p.h | 16 | ||||
-rw-r--r-- | src/core/aspects/qaspectthread.cpp | 99 | ||||
-rw-r--r-- | src/core/aspects/qaspectthread_p.h | 88 | ||||
-rw-r--r-- | src/core/qchangearbiter_p.h | 4 | ||||
-rw-r--r-- | src/core/services/qdownloadhelperservice.cpp | 4 | ||||
-rw-r--r-- | src/input/backend/eventsourcesetterhelper.cpp | 25 | ||||
-rw-r--r-- | src/input/backend/eventsourcesetterhelper_p.h | 6 | ||||
-rw-r--r-- | src/input/backend/inputhandler.cpp | 20 | ||||
-rw-r--r-- | src/input/backend/mousedevice.cpp | 1 | ||||
-rw-r--r-- | src/logic/executor.cpp | 6 | ||||
-rw-r--r-- | src/logic/executor_p.h | 2 | ||||
-rw-r--r-- | src/logic/manager.cpp | 6 | ||||
-rw-r--r-- | src/logic/manager_p.h | 1 | ||||
-rw-r--r-- | tests/benchmarks/render/jobs/tst_bench_jobs.cpp | 1 |
18 files changed, 177 insertions, 422 deletions
diff --git a/src/core/aspects/aspects.pri b/src/core/aspects/aspects.pri index ced33f310..5e8327192 100644 --- a/src/core/aspects/aspects.pri +++ b/src/core/aspects/aspects.pri @@ -4,8 +4,7 @@ SOURCES += \ $$PWD/qabstractaspect.cpp \ $$PWD/qaspectengine.cpp \ $$PWD/qaspectfactory.cpp \ - $$PWD/qaspectmanager.cpp \ - $$PWD/qaspectthread.cpp + $$PWD/qaspectmanager.cpp HEADERS += \ $$PWD/qabstractaspect.h \ @@ -13,8 +12,7 @@ HEADERS += \ $$PWD/qabstractaspect_p.h \ $$PWD/qaspectengine_p.h \ $$PWD/qaspectfactory_p.h \ - $$PWD/qaspectmanager_p.h \ - $$PWD/qaspectthread_p.h + $$PWD/qaspectmanager_p.h INCLUDEPATH += $$PWD diff --git a/src/core/aspects/qaspectengine.cpp b/src/core/aspects/qaspectengine.cpp index 222c4c2af..2e7e51247 100644 --- a/src/core/aspects/qaspectengine.cpp +++ b/src/core/aspects/qaspectengine.cpp @@ -47,7 +47,6 @@ #include <QtCore/QMetaObject> #include <Qt3DCore/private/corelogging_p.h> -#include <Qt3DCore/private/qaspectthread_p.h> #include <Qt3DCore/private/qaspectmanager_p.h> #include <Qt3DCore/private/qchangearbiter_p.h> #include <Qt3DCore/private/qeventfilterservice_p.h> @@ -74,6 +73,7 @@ QAspectEnginePrivate *QAspectEnginePrivate::get(QAspectEngine *q) QAspectEnginePrivate::QAspectEnginePrivate() : QObjectPrivate() + , m_aspectManager(nullptr) , m_postman(nullptr) , m_scene(nullptr) , m_initialized(false) @@ -185,8 +185,7 @@ QAspectEngine::QAspectEngine(QObject *parent) d->m_scene = new QScene(this); d->m_postman = new QPostman(this); d->m_postman->setScene(d->m_scene); - d->m_aspectThread = new QAspectThread(this); - d->m_aspectThread->waitForStart(QThread::HighestPriority); + d->m_aspectManager = new QAspectManager(this); } /*! @@ -206,11 +205,6 @@ QAspectEngine::~QAspectEngine() for (auto aspect : aspects) unregisterAspect(aspect); - // Wait for thread to have completed it's final loop of execution - d->m_aspectThread->aspectManager()->quit(); - d->m_aspectThread->wait(); - - delete d->m_aspectThread; delete d->m_postman; delete d->m_scene; } @@ -225,15 +219,12 @@ void QAspectEnginePrivate::initNodeTree(QNode *node) void QAspectEnginePrivate::initialize() { - QChangeArbiter *arbiter = m_aspectThread->aspectManager()->changeArbiter(); + m_aspectManager->initialize(); + QChangeArbiter *arbiter = m_aspectManager->changeArbiter(); m_scene->setArbiter(arbiter); QChangeArbiter::createUnmanagedThreadLocalChangeQueue(arbiter); - QMetaObject::invokeMethod(arbiter, - "setPostman", - Q_ARG(Qt3DCore::QAbstractPostman*, m_postman)); - QMetaObject::invokeMethod(arbiter, - "setScene", - Q_ARG(Qt3DCore::QScene*, m_scene)); + arbiter->setPostman(m_postman); + arbiter->setScene(m_scene); m_initialized = true; #if QT_CONFIG(qt3d_profile_jobs) m_commandDebugger->setAspectEngine(q_func()); @@ -263,14 +254,14 @@ void QAspectEnginePrivate::shutdown() // Cleanup the scene before quitting the backend m_scene->setArbiter(nullptr); - QChangeArbiter *arbiter = m_aspectThread->aspectManager()->changeArbiter(); + QChangeArbiter *arbiter = m_aspectManager->changeArbiter(); QChangeArbiter::destroyUnmanagedThreadLocalChangeQueue(arbiter); m_initialized = false; } void QAspectEnginePrivate::exitSimulationLoop() { - m_aspectThread->aspectManager()->exitSimulationLoop(); + m_aspectManager->exitSimulationLoop(); } /*! @@ -285,12 +276,8 @@ void QAspectEngine::registerAspect(QAbstractAspect *aspect) // AspectManager::registerAspect is called in the context // of the AspectThread. This is turns call aspect->onInitialize // still in the same AspectThread context - aspect->moveToThread(d->m_aspectThread); d->m_aspects << aspect; - QMetaObject::invokeMethod(d->m_aspectThread->aspectManager(), - "registerAspect", - Qt::BlockingQueuedConnection, - Q_ARG(Qt3DCore::QAbstractAspect*, aspect)); + d->m_aspectManager->registerAspect(aspect); } /*! @@ -327,10 +314,7 @@ void QAspectEngine::unregisterAspect(QAbstractAspect *aspect) // Tell the aspect manager to give the aspect a chance to do some cleanup // in its QAbstractAspect::onUnregistered() virtual - QMetaObject::invokeMethod(d->m_aspectThread->aspectManager(), - "unregisterAspect", - Qt::BlockingQueuedConnection, - Q_ARG(Qt3DCore::QAbstractAspect*, aspect)); + d->m_aspectManager->unregisterAspect(aspect); // Remove from our collection of named aspects (if present) const auto it = std::find_if(d->m_namedAspects.begin(), d->m_namedAspects.end(), @@ -455,14 +439,9 @@ void QAspectEngine::setRootEntity(QEntityPtr root) // TODO: Pass the creation changes via the arbiter rather than relying upon // an invokeMethod call. qCDebug(Aspects) << "Begin setting scene root on aspect manager"; - QMetaObject::invokeMethod(d->m_aspectThread->aspectManager(), - "setRootEntity", - Qt::BlockingQueuedConnection, - Q_ARG(Qt3DCore::QEntity*, root.data()), - Q_ARG(QVector<Qt3DCore::QNodeCreatedChangeBasePtr>, d->m_creationChanges)); + d->m_aspectManager->setRootEntity(root.data(), d->m_creationChanges); qCDebug(Aspects) << "Done setting scene root on aspect manager"; - - d->m_aspectThread->aspectManager()->enterSimulationLoop(); + d->m_aspectManager->enterSimulationLoop(); } /*! diff --git a/src/core/aspects/qaspectengine_p.h b/src/core/aspects/qaspectengine_p.h index 2d7d0fe93..9c042b5a5 100644 --- a/src/core/aspects/qaspectengine_p.h +++ b/src/core/aspects/qaspectengine_p.h @@ -65,7 +65,7 @@ namespace Qt3DCore { class QEntity; class QNode; class QAspectEngine; -class QAspectThread; +class QAspectManager; class QPostman; class QScene; @@ -84,7 +84,7 @@ public: Q_DECLARE_PUBLIC(QAspectEngine) QAspectFactory m_factory; - QAspectThread *m_aspectThread; + QAspectManager *m_aspectManager; QPostman *m_postman; QScene *m_scene; QSharedPointer<QEntity> m_root; diff --git a/src/core/aspects/qaspectmanager.cpp b/src/core/aspects/qaspectmanager.cpp index e9642116a..a028e38cb 100644 --- a/src/core/aspects/qaspectmanager.cpp +++ b/src/core/aspects/qaspectmanager.cpp @@ -61,6 +61,8 @@ #include <Qt3DCore/private/qtickclock_p.h> #include <Qt3DCore/private/qtickclockservice_p.h> +#include <QtCore/QCoreApplication> + #if defined(QT3D_CORE_JOB_TIMING) #include <QElapsedTimer> #endif @@ -69,6 +71,26 @@ QT_BEGIN_NAMESPACE namespace Qt3DCore { +namespace { + +class RequestFrameEvent : public QEvent +{ +public: + RequestFrameEvent() + : QEvent(static_cast<QEvent::Type>(RequestFrameEvent::requestEventType)) + {} + + static int eventType() { return RequestFrameEvent::requestEventType; } + +private: + static int requestEventType; +}; + +int RequestFrameEvent::requestEventType = QEvent::registerEventType(); + +} // anonymous + + /*! \class Qt3DCore::QAspectManager \internal @@ -80,14 +102,9 @@ QAspectManager::QAspectManager(QObject *parent) , m_jobManager(new QAspectJobManager(this)) , m_changeArbiter(new QChangeArbiter(this)) , m_serviceLocator(new QServiceLocator()) - , m_waitForEndOfSimulationLoop(0) - , m_waitForStartOfSimulationLoop(0) - , m_waitForEndOfExecLoop(0) - , m_waitForQuit(0) + , m_simulationLoopRunning(false) { qRegisterMetaType<QSurface *>("QSurface*"); - m_runSimulationLoop.fetchAndStoreOrdered(0); - m_runMainLoop.fetchAndStoreOrdered(1); qCDebug(Aspects) << Q_FUNC_INFO; } @@ -102,15 +119,26 @@ QAspectManager::~QAspectManager() void QAspectManager::enterSimulationLoop() { qCDebug(Aspects) << Q_FUNC_INFO; - m_runSimulationLoop.fetchAndStoreOrdered(1); + m_simulationLoopRunning = true; - // Wake up QAspectThread's event loop - thread()->eventDispatcher()->wakeUp(); + // Retrieve the frame advance service. Defaults to timer based if there is no renderer. + QAbstractFrameAdvanceService *frameAdvanceService = + m_serviceLocator->service<QAbstractFrameAdvanceService>(QServiceLocator::FrameAdvanceService); + + // Start the frameAdvanceService + frameAdvanceService->start(); + + // We are about to enter the simulation loop. Give aspects a chance to do any last + // pieces of initialization + qCDebug(Aspects) << "Calling onEngineStartup() for each aspect"; + for (QAbstractAspect *aspect : qAsConst(m_aspects)) { + qCDebug(Aspects) << "\t" << aspect->objectName(); + aspect->onEngineStartup(); + } + qCDebug(Aspects) << "Done calling onEngineStartup() for each aspect"; - // We wait for the setRootEntity on the aspectManager to have completed - // This ensures we cannot shutdown before the aspects have had a chance - // to be initialized - m_waitForStartOfSimulationLoop.acquire(1); + // Trigger event loop + requestNextFrame(); } // Main thread (called by QAspectEngine) @@ -119,7 +147,7 @@ void QAspectManager::exitSimulationLoop() qCDebug(Aspects) << Q_FUNC_INFO; // If this fails, simulation loop is already exited so nothing to do - if (!m_runSimulationLoop.testAndSetOrdered(1, 0)) { + if (!m_simulationLoopRunning) { qCDebug(Aspects) << "Simulation loop was not running. Nothing to do"; return; } @@ -141,17 +169,26 @@ void QAspectManager::exitSimulationLoop() for (QAbstractAspect *aspect : qAsConst(m_aspects)) aspect->d_func()->onEngineAboutToShutdown(); + // Process any pending changes from the frontend before we shut the aspects down + m_changeArbiter->syncChanges(); - qCDebug(Aspects) << "exitSimulationLoop waiting for exec loop to terminate"; - // Wait until the simulation loop is fully exited and the aspects are done - // processing any final changes and have had onEngineShutdown() called on them - m_waitForEndOfSimulationLoop.acquire(1); + // Give aspects a chance to perform any shutdown actions. This may include unqueuing + // any blocking work on the main thread that could potentially deadlock during shutdown. + qCDebug(Aspects) << "Calling onEngineShutdown() for each aspect"; + for (QAbstractAspect *aspect : qAsConst(m_aspects)) { + qCDebug(Aspects) << "\t" << aspect->objectName(); + aspect->onEngineShutdown(); + } + qCDebug(Aspects) << "Done calling onEngineShutdown() for each aspect"; + + + m_simulationLoopRunning = false; qCDebug(Aspects) << "exitSimulationLoop completed"; } bool QAspectManager::isShuttingDown() const { - return !m_runSimulationLoop.load(); + return !m_simulationLoopRunning; } /*! @@ -184,7 +221,7 @@ void QAspectManager::shutdown() // Aspects must be deleted in the Thread they were created in } -// QAspectThread:: queued invoked by QAspectEngine::setRootEntity +// MainThread called by QAspectEngine::setRootEntity void QAspectManager::setRootEntity(Qt3DCore::QEntity *root, const QVector<Qt3DCore::QNodeCreatedChangeBasePtr> &changes) { qCDebug(Aspects) << Q_FUNC_INFO; @@ -251,118 +288,6 @@ void QAspectManager::unregisterAspect(Qt3DCore::QAbstractAspect *aspect) qCDebug(Aspects) << "Completed unregistering aspect"; } -void QAspectManager::exec() -{ - // Gentlemen, start your engines - QEventLoop eventLoop; - - // Enter the engine loop - qCDebug(Aspects) << Q_FUNC_INFO << "***** Entering main loop *****"; - while (m_runMainLoop.load()) { - // Process events until we're told to start the simulation loop - while (m_runMainLoop.load() && !m_runSimulationLoop.load()) - eventLoop.processEvents(QEventLoop::AllEvents | QEventLoop::WaitForMoreEvents); - - if (!m_runSimulationLoop.load()) - break; - - // Retrieve the frame advance service. Defaults to timer based if there is no renderer. - QAbstractFrameAdvanceService *frameAdvanceService = - m_serviceLocator->service<QAbstractFrameAdvanceService>(QServiceLocator::FrameAdvanceService); - - // Start the frameAdvanceService - frameAdvanceService->start(); - - // We are about to enter the simulation loop. Give aspects a chance to do any last - // pieces of initialization - qCDebug(Aspects) << "Calling onEngineStartup() for each aspect"; - for (QAbstractAspect *aspect : qAsConst(m_aspects)) { - qCDebug(Aspects) << "\t" << aspect->objectName(); - aspect->onEngineStartup(); - } - qCDebug(Aspects) << "Done calling onEngineStartup() for each aspect"; - m_waitForStartOfSimulationLoop.release(1); - - // Only enter main simulation loop once the renderer and other aspects are initialized - while (m_runSimulationLoop.load()) { - qint64 t = frameAdvanceService->waitForNextFrame(); - - // Distribute accumulated changes. This includes changes sent from the frontend - // to the backend nodes. We call this before the call to m_scheduler->update() to ensure - // that any property changes do not set dirty flags in a data race with the renderer's - // submission thread which may be looking for dirty flags, acting upon them and then - // clearing the dirty flags. - // - // Doing this as the first call in the new frame ensures the lock free approach works - // without any such data race. -#if QT_CONFIG(qt3d_profile_jobs) - const quint32 arbiterId = 4096; - JobRunStats changeArbiterStats; - changeArbiterStats.jobId.typeAndInstance[0] = arbiterId; - changeArbiterStats.jobId.typeAndInstance[1] = 0; - changeArbiterStats.threadId = reinterpret_cast<quint64>(QThread::currentThreadId()); - changeArbiterStats.startTime = QThreadPooler::m_jobsStatTimer.nsecsElapsed(); -#endif - m_changeArbiter->syncChanges(); -#if QT_CONFIG(qt3d_profile_jobs) - changeArbiterStats.endTime = QThreadPooler::m_jobsStatTimer.nsecsElapsed(); - QThreadPooler::addJobLogStatsEntry(changeArbiterStats); -#endif - - // For each Aspect - // Ask them to launch set of jobs for the current frame - // Updates matrices, bounding volumes, render bins ... -#if defined(QT3D_CORE_JOB_TIMING) - QElapsedTimer timer; - timer.start(); -#endif - m_scheduler->scheduleAndWaitForFrameAspectJobs(t); -#if defined(QT3D_CORE_JOB_TIMING) - qDebug() << "Jobs took" << timer.nsecsElapsed() / 1.0e6; -#endif - - // Process any pending events - eventLoop.processEvents(); - } // End of simulation loop - - // Process any pending changes from the frontend before we shut the aspects down - m_changeArbiter->syncChanges(); - - // Give aspects a chance to perform any shutdown actions. This may include unqueuing - // any blocking work on the main thread that could potentially deadlock during shutdown. - qCDebug(Aspects) << "Calling onEngineShutdown() for each aspect"; - for (QAbstractAspect *aspect : qAsConst(m_aspects)) { - qCDebug(Aspects) << "\t" << aspect->objectName(); - aspect->onEngineShutdown(); - } - qCDebug(Aspects) << "Done calling onEngineShutdown() for each aspect"; - - // Wake up the main thread which is waiting for us inside of exitSimulationLoop() - m_waitForEndOfSimulationLoop.release(1); - } // End of main loop - qCDebug(Aspects) << Q_FUNC_INFO << "***** Exited main loop *****"; - - m_waitForEndOfExecLoop.release(1); - m_waitForQuit.acquire(1); -} - -void QAspectManager::quit() -{ - qCDebug(Aspects) << Q_FUNC_INFO; - - Q_ASSERT_X(m_runSimulationLoop.load() == 0, "QAspectManagr::quit()", "Inner loop is still running"); - m_runMainLoop.fetchAndStoreOrdered(0); - - // Wake up QAspectThread's event loop if needed - thread()->eventDispatcher()->wakeUp(); - - // We need to wait for the QAspectManager exec loop to terminate - m_waitForEndOfExecLoop.acquire(1); - m_waitForQuit.release(1); - - qCDebug(Aspects) << Q_FUNC_INFO << "Exiting"; -} - const QVector<QAbstractAspect *> &QAspectManager::aspects() const { return m_aspects; @@ -383,7 +308,81 @@ QServiceLocator *QAspectManager::serviceLocator() const return m_serviceLocator.data(); } +/*! + \internal + \brief Drives the Qt3D simulation loop in the main thread + */ +bool QAspectManager::event(QEvent *e) +{ + if (e->type() == RequestFrameEvent::eventType()) { + + // Process current frame + processFrame(); + + // Request next frame if we are still running + if (m_simulationLoopRunning) + requestNextFrame(); + } + + return QObject::event(e); +} + +void QAspectManager::requestNextFrame() +{ + qCDebug(Aspects) << "Requesting new Frame"; + // Post event in the event loop to force + // next frame to be processed + qApp->postEvent(this, new RequestFrameEvent()); +} + +void QAspectManager::processFrame() +{ + qCDebug(Aspects) << "Processing Frame"; + + // Retrieve the frame advance service. Defaults to timer based if there is no renderer. + QAbstractFrameAdvanceService *frameAdvanceService = + m_serviceLocator->service<QAbstractFrameAdvanceService>(QServiceLocator::FrameAdvanceService); + + const qint64 t = frameAdvanceService->waitForNextFrame(); + + // Distribute accumulated changes. This includes changes sent from the frontend + // to the backend nodes. We call this before the call to m_scheduler->update() to ensure + // that any property changes do not set dirty flags in a data race with the renderer's + // submission thread which may be looking for dirty flags, acting upon them and then + // clearing the dirty flags. + // + // Doing this as the first call in the new frame ensures the lock free approach works + // without any such data race. +#if QT_CONFIG(qt3d_profile_jobs) + const quint32 arbiterId = 4096; + JobRunStats changeArbiterStats; + changeArbiterStats.jobId.typeAndInstance[0] = arbiterId; + changeArbiterStats.jobId.typeAndInstance[1] = 0; + changeArbiterStats.threadId = reinterpret_cast<quint64>(QThread::currentThreadId()); + changeArbiterStats.startTime = QThreadPooler::m_jobsStatTimer.nsecsElapsed(); +#endif + // TO DO: Having this done in the main thread actually means aspects could just + // as simply read info out of the Frontend classes without risk of introducing + // races. This could therefore be removed for Qt 6. + m_changeArbiter->syncChanges(); +#if QT_CONFIG(qt3d_profile_jobs) + changeArbiterStats.endTime = QThreadPooler::m_jobsStatTimer.nsecsElapsed(); + QThreadPooler::addJobLogStatsEntry(changeArbiterStats); +#endif + + // For each Aspect + // Ask them to launch set of jobs for the current frame + // Updates matrices, bounding volumes, render bins ... +#if defined(QT3D_CORE_JOB_TIMING) + QElapsedTimer timer; + timer.start(); +#endif + m_scheduler->scheduleAndWaitForFrameAspectJobs(t); +#if defined(QT3D_CORE_JOB_TIMING) + qDebug() << "Jobs took" << timer.nsecsElapsed() / 1.0e6; +#endif +} + } // namespace Qt3DCore QT_END_NAMESPACE - diff --git a/src/core/aspects/qaspectmanager_p.h b/src/core/aspects/qaspectmanager_p.h index de978b8e9..1c07ab797 100644 --- a/src/core/aspects/qaspectmanager_p.h +++ b/src/core/aspects/qaspectmanager_p.h @@ -95,9 +95,6 @@ public Q_SLOTS: void registerAspect(Qt3DCore::QAbstractAspect *aspect); void unregisterAspect(Qt3DCore::QAbstractAspect *aspect); - void exec(); - void quit(); - public: const QVector<QAbstractAspect *> &aspects() const; QAbstractAspectJobManager *jobManager() const; @@ -105,19 +102,20 @@ public: QServiceLocator *serviceLocator() const; private: + bool event(QEvent *event) override; + void requestNextFrame(); + void processFrame(); + QVector<QAbstractAspect *> m_aspects; QEntity *m_root; QVariantMap m_data; QScheduler *m_scheduler; QAbstractAspectJobManager *m_jobManager; QChangeArbiter *m_changeArbiter; - QAtomicInt m_runSimulationLoop; - QAtomicInt m_runMainLoop; QScopedPointer<QServiceLocator> m_serviceLocator; - QSemaphore m_waitForEndOfSimulationLoop; - QSemaphore m_waitForStartOfSimulationLoop; - QSemaphore m_waitForEndOfExecLoop; - QSemaphore m_waitForQuit; + bool m_mainLoopRunning; + bool m_simulationLoopRunning; + }; } // namespace Qt3DCore diff --git a/src/core/aspects/qaspectthread.cpp b/src/core/aspects/qaspectthread.cpp deleted file mode 100644 index 31715b04e..000000000 --- a/src/core/aspects/qaspectthread.cpp +++ /dev/null @@ -1,99 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB). -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt3D module 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 "qaspectthread_p.h" - -#include <QtCore/QMutexLocker> - -#include <Qt3DCore/private/qaspectmanager_p.h> -#include <Qt3DCore/private/corelogging_p.h> - -QT_BEGIN_NAMESPACE - -namespace Qt3DCore { - -QAspectThread::QAspectThread(QObject *parent) - : QThread(parent), - m_aspectManager(nullptr), - m_semaphore(0) -{ - qCDebug(Aspects) << Q_FUNC_INFO; -} - -QAspectThread::~QAspectThread() -{ -} - -void QAspectThread::waitForStart(Priority priority) -{ - qCDebug(Aspects) << "Starting QAspectThread and going to sleep until it is ready for us..."; - start(priority); - m_semaphore.acquire(); - qCDebug(Aspects) << "QAspectThead is now ready & calling thread is now awake again"; -} - -void QAspectThread::run() -{ - qCDebug(Aspects) << "Entering void QAspectThread::run()"; - - m_aspectManager = new QAspectManager; - - // Load and initialize the aspects and any other core services - // Done before releasing condition to make sure that Qml Components - // Are exposed prior to Qml Engine source being set - m_aspectManager->initialize(); - - // Wake up the calling thread now that our worker objects are ready for action - m_semaphore.release(); - - // Enter the main loop - m_aspectManager->exec(); - - // Clean up - m_aspectManager->shutdown(); - - // Delete the aspect manager while we're still in the thread - delete m_aspectManager; - - qCDebug(Aspects) << "Exiting void QAspectThread::run()"; -} - -} // namespace Qt3DCore - -QT_END_NAMESPACE diff --git a/src/core/aspects/qaspectthread_p.h b/src/core/aspects/qaspectthread_p.h deleted file mode 100644 index 8ae9ff86d..000000000 --- a/src/core/aspects/qaspectthread_p.h +++ /dev/null @@ -1,88 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB). -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt3D module 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 QT3DCORE_QASPECTTHREAD_P_H -#define QT3DCORE_QASPECTTHREAD_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists for the convenience -// of other Qt classes. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include <Qt3DCore/qt3dcore_global.h> -#include <QtCore/QSemaphore> -#include <QtCore/QThread> - - -QT_BEGIN_NAMESPACE - -namespace Qt3DCore { - -class QAspectManager; - -class QAspectThread : public QThread -{ - Q_OBJECT -public: - explicit QAspectThread(QObject *parent = 0); - ~QAspectThread(); - - void waitForStart(Priority priority); - - QAspectManager *aspectManager() const { return m_aspectManager; } - -protected: - void run() override; - -private: - QAspectManager *m_aspectManager; - QSemaphore m_semaphore; -}; - -} // namespace Qt3DCore - -QT_END_NAMESPACE - -#endif // QT3DCORE_QASPECTTHREAD_P_H diff --git a/src/core/qchangearbiter_p.h b/src/core/qchangearbiter_p.h index 1f453ff56..c7d96b593 100644 --- a/src/core/qchangearbiter_p.h +++ b/src/core/qchangearbiter_p.h @@ -109,8 +109,8 @@ public: void sceneChangeEventWithLock(const QSceneChangePtr &e) override; // QLockableObserverInterface impl void sceneChangeEventWithLock(const QSceneChangeList &e) override; // QLockableObserverInterface impl - Q_INVOKABLE void setPostman(Qt3DCore::QAbstractPostman *postman); - Q_INVOKABLE void setScene(Qt3DCore::QScene *scene); + void setPostman(Qt3DCore::QAbstractPostman *postman); + void setScene(Qt3DCore::QScene *scene); QAbstractPostman *postman() const final; QScene *scene() const; diff --git a/src/core/services/qdownloadhelperservice.cpp b/src/core/services/qdownloadhelperservice.cpp index 4cd89c5d0..deddf3ae0 100644 --- a/src/core/services/qdownloadhelperservice.cpp +++ b/src/core/services/qdownloadhelperservice.cpp @@ -39,10 +39,10 @@ #include "qdownloadhelperservice_p.h" #include "qdownloadnetworkworker_p.h" +#include <QtCore/QThread> #include <Qt3DCore/QAspectEngine> #include <Qt3DCore/private/qabstractserviceprovider_p.h> #include <Qt3DCore/private/qaspectengine_p.h> -#include <Qt3DCore/private/qaspectthread_p.h> #include <Qt3DCore/private/qaspectmanager_p.h> #include <Qt3DCore/private/qservicelocator_p.h> @@ -196,7 +196,7 @@ QString QDownloadHelperService::urlToLocalFileOrQrc(const QUrl &url) QDownloadHelperService *QDownloadHelperService::getService(QAspectEngine *engine) { auto enginePrivate = Qt3DCore::QAspectEnginePrivate::get(engine); - return enginePrivate->m_aspectThread->aspectManager()->serviceLocator()->downloadHelperService(); + return enginePrivate->m_aspectManager->serviceLocator()->downloadHelperService(); } bool QDownloadHelperService::isLocal(const QUrl &url) diff --git a/src/input/backend/eventsourcesetterhelper.cpp b/src/input/backend/eventsourcesetterhelper.cpp index bbc7ea54c..fe800a1a4 100644 --- a/src/input/backend/eventsourcesetterhelper.cpp +++ b/src/input/backend/eventsourcesetterhelper.cpp @@ -56,21 +56,21 @@ EventSourceSetterHelper::EventSourceSetterHelper(InputHandler *inputHandler) { } -// Aspect thread +// Main thread void EventSourceSetterHelper::setEventFilterService(Qt3DCore::QEventFilterService *service) { - QMutexLocker lock(&m_mutex); m_service = service; } -// Any thread +// Main thread void EventSourceSetterHelper::setEventSource(QObject *eventSource) { if (eventSource && m_lastEventSource != eventSource) { - QMetaObject::invokeMethod(this, - "setEventSourceHelper", - Qt::BlockingQueuedConnection, - Q_ARG(QObject*, eventSource)); + if (m_service) { + m_service->initialize(eventSource); + m_inputHandler->registerEventFilters(m_service); + m_lastEventSource = eventSource; + } } } @@ -83,17 +83,6 @@ void EventSourceSetterHelper::unsetEventSource(QObject *eventSource) } } -// Main Thread -void EventSourceSetterHelper::setEventSourceHelper(QObject *eventSource) -{ - QMutexLocker lock(&m_mutex); - if (m_service) { - m_service->initialize(eventSource); - m_inputHandler->registerEventFilters(m_service); - m_lastEventSource = eventSource; - } -} - } // Input } // Qt3DInput diff --git a/src/input/backend/eventsourcesetterhelper_p.h b/src/input/backend/eventsourcesetterhelper_p.h index 48418f1b9..b8800d8a6 100644 --- a/src/input/backend/eventsourcesetterhelper_p.h +++ b/src/input/backend/eventsourcesetterhelper_p.h @@ -75,14 +75,10 @@ public: // Called from aspect thread void setEventFilterService(Qt3DCore::QEventFilterService *service); - // Called from any thread + // Called from main thread void setEventSource(QObject *eventSource); void unsetEventSource(QObject *eventSource); -private Q_SLOTS: - // Called in main thread - void setEventSourceHelper(QObject *); - private: Qt3DCore::QEventFilterService *m_service; InputHandler *m_inputHandler; diff --git a/src/input/backend/inputhandler.cpp b/src/input/backend/inputhandler.cpp index 18559e9d4..9484909ab 100644 --- a/src/input/backend/inputhandler.cpp +++ b/src/input/backend/inputhandler.cpp @@ -127,58 +127,55 @@ void InputHandler::unregisterEventFilters(Qt3DCore::QEventFilterService *service // Called by the keyboardEventFilter in the main thread void InputHandler::appendKeyEvent(const QT_PREPEND_NAMESPACE(QKeyEvent) &event) { - QMutexLocker lock(&m_mutex); m_pendingKeyEvents.append(event); } -// Called by QInputASpect::jobsToExecute (aspectThread) +// Called by QInputASpect::jobsToExecute (Main Thread) QList<QT_PREPEND_NAMESPACE(QKeyEvent)> InputHandler::pendingKeyEvents() { - QMutexLocker lock(&m_mutex); return std::move(m_pendingKeyEvents); } -// Called by QInputASpect::jobsToExecute (aspectThread) +// Called by QInputASpect::jobsToExecute (Main Thread) void InputHandler::clearPendingKeyEvents() { - QMutexLocker lock(&m_mutex); m_pendingKeyEvents.clear(); } +// Main Thread void InputHandler::appendMouseEvent(const QT_PREPEND_NAMESPACE(QMouseEvent) &event) { - QMutexLocker lock(&m_mutex); m_pendingMouseEvents.append(event); } +// Main Thread QList<QT_PREPEND_NAMESPACE(QMouseEvent)> InputHandler::pendingMouseEvents() { - QMutexLocker lock(&m_mutex); return std::move(m_pendingMouseEvents); } +// Main Thread void InputHandler::clearPendingMouseEvents() { - QMutexLocker lock(&m_mutex); m_pendingMouseEvents.clear(); } #if QT_CONFIG(wheelevent) +// Main Thread void InputHandler::appendWheelEvent(const QT_PREPEND_NAMESPACE(QWheelEvent) &event) { - QMutexLocker lock(&m_mutex); m_pendingWheelEvents.append(event); } +// Main Thread QList<QT_PREPEND_NAMESPACE (QWheelEvent)> Qt3DInput::Input::InputHandler::pendingWheelEvents() { - QMutexLocker lock(&m_mutex); return std::move(m_pendingWheelEvents); } +// Main Thread void InputHandler::clearPendingWheelEvents() { - QMutexLocker lock(&m_mutex); m_pendingWheelEvents.clear(); } #endif @@ -253,7 +250,6 @@ QVector<Qt3DCore::QAspectJobPtr> InputHandler::mouseJobs() #if QT_CONFIG(wheelevent) const QList<QT_PREPEND_NAMESPACE(QWheelEvent)> wheelEvents = pendingWheelEvents(); #endif - for (const HMouseDevice &cHandle : qAsConst(m_activeMouseDevices)) { MouseDevice *controller = m_mouseDeviceManager->data(cHandle); diff --git a/src/input/backend/mousedevice.cpp b/src/input/backend/mousedevice.cpp index 128988637..e285783b7 100644 --- a/src/input/backend/mousedevice.cpp +++ b/src/input/backend/mousedevice.cpp @@ -150,6 +150,7 @@ void MouseDevice::updateWheelEvents(const QList<QT_PREPEND_NAMESPACE (QWheelEven } #endif +// Main Thread void MouseDevice::updateMouseEvents(const QList<QT_PREPEND_NAMESPACE(QMouseEvent)> &events) { // Reset axis values before we accumulate new values for this frame diff --git a/src/logic/executor.cpp b/src/logic/executor.cpp index 6134e801e..1c428db47 100644 --- a/src/logic/executor.cpp +++ b/src/logic/executor.cpp @@ -64,8 +64,6 @@ void Executor::clearQueueAndProceed() // If the semaphore is acquired, release it to allow the logic job and hence the // manager and frame to complete and shutdown to continue. m_nodeIds.clear(); - if (m_semaphore->available() == 0) - m_semaphore->release(); } void Executor::enqueueLogicFrameUpdates(const QVector<Qt3DCore::QNodeId> &nodeIds) @@ -92,16 +90,12 @@ bool Executor::event(QEvent *e) void Executor::processLogicFrameUpdates(float dt) { Q_ASSERT(m_scene); - Q_ASSERT(m_semaphore); const QVector<QNode *> nodes = m_scene->lookupNodes(m_nodeIds); for (QNode *node : nodes) { QFrameAction *frameAction = qobject_cast<QFrameAction *>(node); if (frameAction && frameAction->isEnabled()) frameAction->onTriggered(dt); } - - // Release the semaphore so the calling Manager can continue - m_semaphore->release(); } } // namespace Logic diff --git a/src/logic/executor_p.h b/src/logic/executor_p.h index e33ff842e..27b9c60c8 100644 --- a/src/logic/executor_p.h +++ b/src/logic/executor_p.h @@ -87,7 +87,6 @@ public: explicit Executor(QObject *parent = 0); void setScene(Qt3DCore::QScene *scene) { m_scene = scene; } - void setSemephore(QSemaphore *semaphore) { m_semaphore = semaphore; } void clearQueueAndProceed(); public Q_SLOTS: @@ -100,7 +99,6 @@ protected: private: QVector<Qt3DCore::QNodeId> m_nodeIds; Qt3DCore::QScene *m_scene; - QSemaphore *m_semaphore; }; } // namespace Logic diff --git a/src/logic/manager.cpp b/src/logic/manager.cpp index e10ace592..3d096a342 100644 --- a/src/logic/manager.cpp +++ b/src/logic/manager.cpp @@ -56,10 +56,8 @@ namespace Logic { Manager::Manager() : m_logicHandlerManager(new HandlerManager) - , m_semaphore(1) , m_dt(0.0f) { - m_semaphore.acquire(); } Manager::~Manager() @@ -69,8 +67,6 @@ Manager::~Manager() void Manager::setExecutor(Executor *executor) { m_executor = executor; - if (m_executor) - m_executor->setSemephore(&m_semaphore); } void Manager::appendHandler(Handler *handler) @@ -93,6 +89,7 @@ bool Manager::hasFrameActions() const return m_logicHandlers.count() > 0; } +// Called from Job Thread void Manager::triggerLogicFrameUpdates() { Q_ASSERT(m_executor); @@ -107,7 +104,6 @@ void Manager::triggerLogicFrameUpdates() // release the semaphore when it has completed its work. m_executor->enqueueLogicFrameUpdates(m_logicComponentIds); qApp->postEvent(m_executor, new FrameUpdateEvent(m_dt)); - m_semaphore.acquire(); } } // namespace Logic diff --git a/src/logic/manager_p.h b/src/logic/manager_p.h index 918bd57e0..e4fa08a47 100644 --- a/src/logic/manager_p.h +++ b/src/logic/manager_p.h @@ -95,7 +95,6 @@ private: QVector<Qt3DCore::QNodeId> m_logicComponentIds; QLogicAspect *m_logicAspect; Executor *m_executor; - QSemaphore m_semaphore; float m_dt; }; diff --git a/tests/benchmarks/render/jobs/tst_bench_jobs.cpp b/tests/benchmarks/render/jobs/tst_bench_jobs.cpp index 454cb9f6a..b1597b095 100644 --- a/tests/benchmarks/render/jobs/tst_bench_jobs.cpp +++ b/tests/benchmarks/render/jobs/tst_bench_jobs.cpp @@ -48,7 +48,6 @@ #include <Qt3DCore/private/qaspectjobmanager_p.h> #include <Qt3DCore/private/qaspectengine_p.h> #include <Qt3DCore/private/qaspectmanager_p.h> -#include <Qt3DCore/private/qaspectthread_p.h> #include <Qt3DCore/private/qnodevisitor_p.h> #include <Qt3DCore/private/qnodecreatedchangegenerator_p.h> #include <QQmlComponent> |