diff options
author | Gunnar Sletta <gunnar@sletta.org> | 2014-10-07 12:22:26 +0200 |
---|---|---|
committer | Gunnar Sletta <gunnar@sletta.org> | 2014-10-10 21:10:52 +0200 |
commit | 099ae0597df6f6bbd0b9e05d063a4a58c9cae2ff (patch) | |
tree | ccfaf743aa3a572d362927131311787dd98c599b /src/quick/util/qquickanimatorcontroller.cpp | |
parent | 7f5a59c2025022f99dff9fa030c892adb4473d6a (diff) |
Improve performance of animators.v5.4.0-beta1
The use of one QCoreApp::postEvent() per completed animation added up
to a very large overhead when 1000+ animators were used at the same
time. This is very relevant for sprite games and similar and deserves
to work at least as good as normal animations.
Instead, store the animations to stop and stop then on the gui thread
later as a result of frameSwapped. For the benchmark in question this
allows for roughly double the amount of animators being started and
stopped.
Change-Id: Iae3d1ec1502ee1908fdbba708fa9f976aa230064
Reviewed-by: Michael Brasser <michael.brasser@live.com>
Diffstat (limited to 'src/quick/util/qquickanimatorcontroller.cpp')
-rw-r--r-- | src/quick/util/qquickanimatorcontroller.cpp | 44 |
1 files changed, 40 insertions, 4 deletions
diff --git a/src/quick/util/qquickanimatorcontroller.cpp b/src/quick/util/qquickanimatorcontroller.cpp index e009de205c..cfaa439072 100644 --- a/src/quick/util/qquickanimatorcontroller.cpp +++ b/src/quick/util/qquickanimatorcontroller.cpp @@ -44,10 +44,19 @@ QT_BEGIN_NAMESPACE -QQuickAnimatorController::QQuickAnimatorController() - : m_window(0) +QQuickAnimatorController::QQuickAnimatorController(QQuickWindow *window) + : m_window(window) , m_nodesAreInvalid(false) { + m_guiEntity = new QQuickAnimatorControllerGuiThreadEntity(); + m_guiEntity->controller = this; + connect(window, SIGNAL(frameSwapped()), m_guiEntity, SLOT(frameSwapped())); +} + +void QQuickAnimatorControllerGuiThreadEntity::frameSwapped() +{ + if (!controller.isNull()) + controller->stopProxyJobs(); } QQuickAnimatorController::~QQuickAnimatorController() @@ -71,6 +80,8 @@ QQuickAnimatorController::~QQuickAnimatorController() if (!m_animatorRoots.contains(job)) delete job; } + + delete m_guiEntity; } static void qquickanimator_invalidate_node(QAbstractAnimationJob *job) @@ -211,6 +222,27 @@ void QQuickAnimatorController::afterNodeSync() } } +void QQuickAnimatorController::proxyWasDestroyed(QQuickAnimatorProxyJob *proxy) +{ + lock(); + m_proxiesToStop.remove(proxy); + unlock(); +} + +void QQuickAnimatorController::stopProxyJobs() +{ + // Need to make a copy under lock and then stop while unlocked. + // Stopping triggers writeBack which in turn may lock, so it needs + // to be outside the lock. It is also safe because deletion of + // proxies happens on the GUI thread, where this code is also executing. + lock(); + QSet<QQuickAnimatorProxyJob *> jobs = m_proxiesToStop; + m_proxiesToStop.clear(); + unlock(); + foreach (QQuickAnimatorProxyJob *p, jobs) + p->stop(); +} + void QQuickAnimatorController::animationFinished(QAbstractAnimationJob *job) { /* We are currently on the render thread and m_deleting is primarily @@ -221,8 +253,10 @@ void QQuickAnimatorController::animationFinished(QAbstractAnimationJob *job) */ if (!m_deleting.contains(job)) { QQuickAnimatorProxyJob *proxy = m_animatorRoots[job]; - if (proxy) - QCoreApplication::postEvent(proxy, new QEvent(QEvent::User)); + if (proxy) { + m_window->update(); + m_proxiesToStop << proxy; + } // else already gone... } } @@ -254,12 +288,14 @@ void QQuickAnimatorController::startJob(QQuickAnimatorProxyJob *proxy, QAbstract { proxy->markJobManagedByController(); m_starting[job] = proxy; + m_stopping.remove(job); requestSync(); } void QQuickAnimatorController::stopJob(QQuickAnimatorProxyJob *proxy, QAbstractAnimationJob *job) { m_stopping[job] = proxy; + m_starting.remove(job); requestSync(); } |