diff options
author | Miikka Heikkinen <miikka.heikkinen@theqtcompany.com> | 2015-03-18 14:13:10 +0200 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@theqtcompany.com> | 2015-04-15 17:53:01 +0000 |
commit | e036a0d80cd78474a6bfe4a78c9ee108c1552f80 (patch) | |
tree | 156773f30f1e5406a8a54847ce1f1ce80a85f05f /src | |
parent | 327ddb7488805241fb48c20ec8628c630224f4ce (diff) |
Added a new render job stage: NoStage
NoStage allows scheduling jobs for immediate execution on the
renderer thread.
[ChangeLog][QtQuick][QQuickWindow] Added a render job stage: NoStage
Task-number: QTBUG-44953
Change-Id: I918c79f1d095bc27d911a88d81376d146a04313c
Reviewed-by: Gunnar Sletta <gunnar@sletta.org>
Reviewed-by: Venugopal Shivashankar <venugopal.shivashankar@digia.com>
Reviewed-by: Pasi Keränen <pasi.keranen@digia.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/quick/items/qquickwindow.cpp | 30 | ||||
-rw-r--r-- | src/quick/items/qquickwindow.h | 3 | ||||
-rw-r--r-- | src/quick/scenegraph/qsgrenderloop.cpp | 16 | ||||
-rw-r--r-- | src/quick/scenegraph/qsgrenderloop_p.h | 2 | ||||
-rw-r--r-- | src/quick/scenegraph/qsgthreadedrenderloop.cpp | 37 | ||||
-rw-r--r-- | src/quick/scenegraph/qsgthreadedrenderloop_p.h | 1 |
6 files changed, 81 insertions, 8 deletions
diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp index bccebb1a14..664e0f791c 100644 --- a/src/quick/items/qquickwindow.cpp +++ b/src/quick/items/qquickwindow.cpp @@ -4111,6 +4111,7 @@ void QQuickWindow::resetOpenGLState() \value BeforeRenderingStage Before rendering. \value AfterRenderingStage After rendering. \value AfterSwapStage After the frame is swapped. + \value NoStage As soon as possible. This value was added in Qt 5.6. \sa {Scene Graph and Rendering} */ @@ -4136,8 +4137,17 @@ void QQuickWindow::resetOpenGLState() If the rendering is happening on a different thread, then the job will happen on the rendering thread. - \note This function does not trigger rendering; the job - will be stored run until rendering is triggered elsewhere. + If \a stage is \l NoStage, \a job will be run at the earliest opportunity + whenever the render thread is not busy rendering a frame. If there is no + OpenGL context available or the window is not exposed at the time the job is + either posted or handled, it is deleted without executing the run() method. + If a non-threaded renderer is in use, the run() method of the job is executed + synchronously. + The OpenGL context is changed to the renderer context before executing a + \l NoStage job. + + \note This function does not trigger rendering; the jobs targeting any other + stage than NoStage will be stored run until rendering is triggered elsewhere. To force the job to run earlier, call QQuickWindow::update(); \sa beforeRendering(), afterRendering(), beforeSynchronizing(), @@ -4149,16 +4159,22 @@ void QQuickWindow::scheduleRenderJob(QRunnable *job, RenderStage stage) Q_D(QQuickWindow); d->renderJobMutex.lock(); - if (stage == BeforeSynchronizingStage) + if (stage == BeforeSynchronizingStage) { d->beforeSynchronizingJobs << job; - else if (stage == AfterSynchronizingStage) + } else if (stage == AfterSynchronizingStage) { d->afterSynchronizingJobs << job; - else if (stage == BeforeRenderingStage) + } else if (stage == BeforeRenderingStage) { d->beforeRenderingJobs << job; - else if (stage == AfterRenderingStage) + } else if (stage == AfterRenderingStage) { d->afterRenderingJobs << job; - else if (stage == AfterSwapStage) + } else if (stage == AfterSwapStage) { d->afterSwapJobs << job; + } else if (stage == NoStage) { + if (isExposed()) + d->windowManager->postJob(this, job); + else + delete job; + } d->renderJobMutex.unlock(); } diff --git a/src/quick/items/qquickwindow.h b/src/quick/items/qquickwindow.h index f7a1956120..1a1d44c3b4 100644 --- a/src/quick/items/qquickwindow.h +++ b/src/quick/items/qquickwindow.h @@ -77,7 +77,8 @@ public: AfterSynchronizingStage, BeforeRenderingStage, AfterRenderingStage, - AfterSwapStage + AfterSwapStage, + NoStage }; Q_DECLARE_FLAGS(CreateTextureOptions, CreateTextureOption) diff --git a/src/quick/scenegraph/qsgrenderloop.cpp b/src/quick/scenegraph/qsgrenderloop.cpp index ce3bf7d61d..fd6dc76dc3 100644 --- a/src/quick/scenegraph/qsgrenderloop.cpp +++ b/src/quick/scenegraph/qsgrenderloop.cpp @@ -99,6 +99,22 @@ void QSGRenderLoop::cleanup() s_instance = 0; } +/*! + * Non-threaded render loops immediately run the job if there is a context. + */ +void QSGRenderLoop::postJob(QQuickWindow *window, QRunnable *job) +{ + Q_ASSERT(window); + Q_ASSERT(job); + + if (window->openglContext()) { + window->openglContext()->makeCurrent(window); + job->run(); + } + + delete job; +} + class QSGGuiThreadRenderLoop : public QSGRenderLoop { Q_OBJECT diff --git a/src/quick/scenegraph/qsgrenderloop_p.h b/src/quick/scenegraph/qsgrenderloop_p.h index 4293015b96..3336731fda 100644 --- a/src/quick/scenegraph/qsgrenderloop_p.h +++ b/src/quick/scenegraph/qsgrenderloop_p.h @@ -45,6 +45,7 @@ class QQuickWindow; class QSGContext; class QSGRenderContext; class QAnimationDriver; +class QRunnable; class Q_QUICK_PRIVATE_EXPORT QSGRenderLoop : public QObject { @@ -72,6 +73,7 @@ public: virtual QSGRenderContext *createRenderContext(QSGContext *) const = 0; virtual void releaseResources(QQuickWindow *window) = 0; + virtual void postJob(QQuickWindow *window, QRunnable *job); void addWindow(QQuickWindow *win) { m_windows.insert(win); } void removeWindow(QQuickWindow *win) { m_windows.remove(win); } diff --git a/src/quick/scenegraph/qsgthreadedrenderloop.cpp b/src/quick/scenegraph/qsgthreadedrenderloop.cpp index 7b1e24246b..682599c76e 100644 --- a/src/quick/scenegraph/qsgthreadedrenderloop.cpp +++ b/src/quick/scenegraph/qsgthreadedrenderloop.cpp @@ -145,6 +145,9 @@ const QEvent::Type WM_TryRelease = QEvent::Type(QEvent::User + 4); // called. const QEvent::Type WM_Grab = QEvent::Type(QEvent::User + 5); +// Passed by the window when there is a render job to run +const QEvent::Type WM_PostJob = QEvent::Type(QEvent::User + 6); + template <typename T> T *windowFor(const QList<T> &list, QQuickWindow *window) { for (int i=0; i<list.size(); ++i) { @@ -198,6 +201,14 @@ public: QImage *image; }; +class WMJobEvent : public WMWindowEvent +{ +public: + WMJobEvent(QQuickWindow *c, QRunnable *postedJob) + : WMWindowEvent(c, WM_PostJob), job(postedJob) {} + ~WMJobEvent() { delete job; } + QRunnable *job; +}; class QSGRenderThreadEventQueue : public QQueue<QEvent *> { @@ -415,6 +426,20 @@ bool QSGRenderThread::event(QEvent *e) return true; } + case WM_PostJob: { + qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "WM_PostJob"; + WMJobEvent *ce = static_cast<WMJobEvent *>(e); + Q_ASSERT(ce->window == window); + if (window) { + gl->makeCurrent(window); + ce->job->run(); + delete ce->job; + ce->job = 0; + qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "- job done"; + } + return true; + } + case WM_RequestRepaint: qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "WM_RequestPaint"; // When GUI posts this event, it is followed by a polishAndSync, so we mustn't @@ -1232,6 +1257,18 @@ QImage QSGThreadedRenderLoop::grab(QQuickWindow *window) return result; } +/*! + * Posts a new job event to the render thread. + * Returns true if posting succeeded. + */ +void QSGThreadedRenderLoop::postJob(QQuickWindow *window, QRunnable *job) +{ + Window *w = windowFor(m_windows, window); + if (w && w->thread && w->thread->window) + w->thread->postEvent(new WMJobEvent(window, job)); + else + delete job; +} #include "qsgthreadedrenderloop.moc" diff --git a/src/quick/scenegraph/qsgthreadedrenderloop_p.h b/src/quick/scenegraph/qsgthreadedrenderloop_p.h index d5ffbf10a3..67df9dcd31 100644 --- a/src/quick/scenegraph/qsgthreadedrenderloop_p.h +++ b/src/quick/scenegraph/qsgthreadedrenderloop_p.h @@ -71,6 +71,7 @@ public: void releaseResources(QQuickWindow *window); bool event(QEvent *); + void postJob(QQuickWindow *window, QRunnable *job); bool interleaveIncubation() const; |