aboutsummaryrefslogtreecommitdiffstats
path: root/src/quick/scenegraph/qsgthreadedrenderloop.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/quick/scenegraph/qsgthreadedrenderloop.cpp')
-rw-r--r--src/quick/scenegraph/qsgthreadedrenderloop.cpp111
1 files changed, 40 insertions, 71 deletions
diff --git a/src/quick/scenegraph/qsgthreadedrenderloop.cpp b/src/quick/scenegraph/qsgthreadedrenderloop.cpp
index 561ebff8dd..6974271dc7 100644
--- a/src/quick/scenegraph/qsgthreadedrenderloop.cpp
+++ b/src/quick/scenegraph/qsgthreadedrenderloop.cpp
@@ -1,8 +1,8 @@
/****************************************************************************
**
-** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2015 The Qt Company Ltd.
** Copyright (C) 2014 Jolla Ltd, author: <gunnar.sletta@jollamobile.com>
-** Contact: http://www.qt-project.org/legal
+** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtQuick module of the Qt Toolkit.
**
@@ -11,9 +11,9 @@
** 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 Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
-** use the contact form at http://qt.digia.com/contact-us.
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
@@ -24,8 +24,8 @@
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** $QT_END_LICENSE$
@@ -105,16 +105,6 @@ QT_BEGIN_NAMESPACE
#define QSG_RT_PAD " (RT)"
-static int get_env_int(const char *name, int defaultValue)
-{
- QByteArray content = qgetenv(name);
-
- bool ok = false;
- int value = content.toInt(&ok);
- return ok ? value : defaultValue;
-}
-
-
static inline int qsgrl_animation_interval() {
qreal refreshRate = QGuiApplication::primaryScreen()->refreshRate();
// To work around that some platforms wrongfully return 0 or something
@@ -155,7 +145,7 @@ const QEvent::Type WM_TryRelease = QEvent::Type(QEvent::User + 4);
// called.
const QEvent::Type WM_Grab = QEvent::Type(QEvent::User + 5);
-template <typename T> T *windowFor(const QList<T> list, QQuickWindow *window)
+template <typename T> T *windowFor(const QList<T> &list, QQuickWindow *window)
{
for (int i=0; i<list.size(); ++i) {
const T &t = list.at(i);
@@ -531,12 +521,12 @@ void QSGRenderThread::sync(bool inExpose)
void QSGRenderThread::syncAndRender()
{
- bool profileFrames = QSG_LOG_TIME_RENDERLOOP().isDebugEnabled() ||
- QQuickProfiler::profilingSceneGraph();
+ bool profileFrames = QSG_LOG_TIME_RENDERLOOP().isDebugEnabled();
if (profileFrames) {
sinceLastTime = threadTimer.nsecsElapsed();
threadTimer.start();
}
+ Q_QUICK_SG_PROFILE_START(QQuickProfiler::SceneGraphRenderLoopFrame);
QElapsedTimer waitTimer;
waitTimer.start();
@@ -544,20 +534,24 @@ void QSGRenderThread::syncAndRender()
qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "syncAndRender()";
syncResultedInChanges = false;
+ QQuickWindowPrivate *d = QQuickWindowPrivate::get(window);
- uint pending = pendingUpdate;
+ bool repaintRequested = (pendingUpdate & RepaintRequest) || d->customRenderStage;
+ bool syncRequested = pendingUpdate & SyncRequest;
+ bool exposeRequested = (pendingUpdate & ExposeRequest) == ExposeRequest;
pendingUpdate = 0;
- if (pending & SyncRequest) {
+ if (syncRequested) {
qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "- updatePending, doing sync";
- sync(pending == ExposeRequest);
+ sync(exposeRequested);
}
#ifndef QSG_NO_RENDER_TIMING
if (profileFrames)
syncTime = threadTimer.nsecsElapsed();
#endif
+ Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphRenderLoopFrame);
- if (!syncResultedInChanges && ((pending & RepaintRequest) == 0)) {
+ if (!syncResultedInChanges && !repaintRequested) {
qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "- no changes, render aborted";
int waitTime = vsyncDelta - (int) waitTimer.elapsed();
if (waitTime > 0)
@@ -567,7 +561,6 @@ void QSGRenderThread::syncAndRender()
qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "- rendering started";
- QQuickWindowPrivate *d = QQuickWindowPrivate::get(window);
if (animatorDriver->isRunning()) {
d->animationController->lock();
@@ -582,9 +575,12 @@ void QSGRenderThread::syncAndRender()
d->renderSceneGraph(windowSize);
if (profileFrames)
renderTime = threadTimer.nsecsElapsed();
- gl->swapBuffers(window);
+ Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphRenderLoopFrame);
+ if (!d->customRenderStage || !d->customRenderStage->swap())
+ gl->swapBuffers(window);
d->fireFrameSwapped();
} else {
+ Q_QUICK_SG_PROFILE_SKIP(QQuickProfiler::SceneGraphRenderLoopFrame, 1);
qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "- window not ready, skipping render";
}
@@ -595,7 +591,7 @@ void QSGRenderThread::syncAndRender()
// that to avoid blocking the GUI thread in the case where it
// has started rendering with a bad window, causing makeCurrent to
// fail or if the window has a bad size.
- if (pending == ExposeRequest) {
+ if (exposeRequested) {
qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "- wake Gui after initial expose";
waitCondition.wakeOne();
mutex.unlock();
@@ -609,10 +605,7 @@ void QSGRenderThread::syncAndRender()
int(threadTimer.elapsed() - renderTime / 1000000));
- Q_QUICK_SG_PROFILE(QQuickProfiler::SceneGraphRenderLoopFrame, (
- syncTime,
- renderTime - syncTime,
- threadTimer.nsecsElapsed() - renderTime));
+ Q_QUICK_SG_PROFILE_END(QQuickProfiler::SceneGraphRenderLoopFrame);
}
@@ -695,8 +688,6 @@ QSGThreadedRenderLoop::QSGThreadedRenderLoop()
m_animation_driver = sg->createAnimationDriver(this);
- m_exhaust_delay = get_env_int("QML_EXHAUST_DELAY", 5);
-
connect(m_animation_driver, SIGNAL(started()), this, SLOT(animationStarted()));
connect(m_animation_driver, SIGNAL(stopped()), this, SLOT(animationStopped()));
@@ -715,10 +706,7 @@ QSGRenderContext *QSGThreadedRenderLoop::createRenderContext(QSGContext *sg) con
void QSGThreadedRenderLoop::maybePostPolishRequest(Window *w)
{
- if (w->timerId == 0) {
- qCDebug(QSG_LOG_RENDERLOOP) << "- posting update";
- w->timerId = startTimer(m_exhaust_delay, Qt::PreciseTimer);
- }
+ w->window->requestUpdate();
}
QAnimationDriver *QSGThreadedRenderLoop::animationDriver() const
@@ -868,7 +856,6 @@ void QSGThreadedRenderLoop::handleExposure(QQuickWindow *window)
win.window = window;
win.actualWindowFormat = window->format();
win.thread = new QSGRenderThread(this, QQuickWindowPrivate::get(window)->context);
- win.timerId = 0;
win.updateDuringSync = false;
win.forceRenderPass = true; // also covered by polishAndSync(inExpose=true), but doesn't hurt
m_windows << win;
@@ -958,6 +945,14 @@ void QSGThreadedRenderLoop::handleObscurity(Window *w)
}
+void QSGThreadedRenderLoop::handleUpdateRequest(QQuickWindow *window)
+{
+ qCDebug(QSG_LOG_RENDERLOOP) << "- polish and sync update request";
+ Window *w = windowFor(m_windows, window);
+ if (w)
+ polishAndSync(w);
+}
+
void QSGThreadedRenderLoop::maybeUpdate(QQuickWindow *window)
{
Window *w = windowFor(m_windows, window);
@@ -1085,8 +1080,6 @@ void QSGThreadedRenderLoop::polishAndSync(Window *w, bool inExpose)
QQuickWindow *window = w->window;
if (!w->thread || !w->thread->window) {
qCDebug(QSG_LOG_RENDERLOOP) << "- not exposed, abort";
- killTimer(w->timerId);
- w->timerId = 0;
return;
}
@@ -1096,8 +1089,6 @@ void QSGThreadedRenderLoop::polishAndSync(Window *w, bool inExpose)
w = windowFor(m_windows, window);
if (!w || !w->thread || !w->thread->window) {
qCDebug(QSG_LOG_RENDERLOOP) << "- removed after event flushing, abort";
- killTimer(w->timerId);
- w->timerId = 0;
return;
}
@@ -1106,16 +1097,17 @@ void QSGThreadedRenderLoop::polishAndSync(Window *w, bool inExpose)
qint64 polishTime = 0;
qint64 waitTime = 0;
qint64 syncTime = 0;
- bool profileFrames = QSG_LOG_TIME_RENDERLOOP().isDebugEnabled() ||
- QQuickProfiler::profilingSceneGraph();
+ bool profileFrames = QSG_LOG_TIME_RENDERLOOP().isDebugEnabled();
if (profileFrames)
timer.start();
+ Q_QUICK_SG_PROFILE_START(QQuickProfiler::SceneGraphPolishAndSync);
QQuickWindowPrivate *d = QQuickWindowPrivate::get(window);
d->polishItems();
if (profileFrames)
polishTime = timer.nsecsElapsed();
+ Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphPolishAndSync);
w->updateDuringSync = false;
@@ -1130,6 +1122,7 @@ void QSGThreadedRenderLoop::polishAndSync(Window *w, bool inExpose)
qCDebug(QSG_LOG_RENDERLOOP) << "- wait for sync";
if (profileFrames)
waitTime = timer.nsecsElapsed();
+ Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphPolishAndSync);
w->thread->waitCondition.wait(&w->thread->mutex);
m_lockedForSync = false;
w->thread->mutex.unlock();
@@ -1137,9 +1130,7 @@ void QSGThreadedRenderLoop::polishAndSync(Window *w, bool inExpose)
if (profileFrames)
syncTime = timer.nsecsElapsed();
-
- killTimer(w->timerId);
- w->timerId = 0;
+ Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphPolishAndSync);
if (m_animation_timer == 0 && m_animation_driver->isRunning()) {
qCDebug(QSG_LOG_RENDERLOOP) << "- advancing animations";
@@ -1160,22 +1151,7 @@ void QSGThreadedRenderLoop::polishAndSync(Window *w, bool inExpose)
<< ", animations=" << (timer.nsecsElapsed() - syncTime) / 1000000
<< " - (on Gui thread) " << window;
- Q_QUICK_SG_PROFILE(QQuickProfiler::SceneGraphPolishAndSync, (
- polishTime,
- waitTime - polishTime,
- syncTime - waitTime,
- timer.nsecsElapsed() - syncTime));
-}
-
-QSGThreadedRenderLoop::Window *QSGThreadedRenderLoop::windowForTimer(int timerId) const
-{
- for (int i=0; i<m_windows.size(); ++i) {
- if (m_windows.at(i).timerId == timerId) {
- return const_cast<Window *>(&m_windows.at(i));
- break;
- }
- }
- return 0;
+ Q_QUICK_SG_PROFILE_END(QQuickProfiler::SceneGraphPolishAndSync);
}
bool QSGThreadedRenderLoop::event(QEvent *e)
@@ -1188,15 +1164,8 @@ bool QSGThreadedRenderLoop::event(QEvent *e)
qCDebug(QSG_LOG_RENDERLOOP) << "- ticking non-visual timer";
m_animation_driver->advance();
emit timeToIncubate();
- } else {
- qCDebug(QSG_LOG_RENDERLOOP) << "- polish and sync timer";
- Window *w = windowForTimer(te->timerId());
- if (w)
- polishAndSync(w);
- else
- killTimer(te->timerId());
+ return true;
}
- return true;
}
default: