diff options
author | Ulf Hermann <[email protected]> | 2014-01-24 13:24:19 +0100 |
---|---|---|
committer | The Qt Project <[email protected]> | 2014-02-15 22:37:38 +0100 |
commit | 9424383e6d0ea1dd02dcf1070259e21550da692a (patch) | |
tree | f7a9b1372a0a97f997d6a237e3a89e009b07b30e /src/quick/util/qquickprofiler.cpp | |
parent | ab6b6b7c7ab544d347d59b7eefad403837d94012 (diff) |
Move QtQuick profiling to own profiler adapter
The QtQuick parts of the QML profiler service thus become a proper
global profiler which can be independently enabled and disabled.
Change-Id: Ifad03801cab2be66a264fc46fdebdae582fcc99b
Reviewed-by: Kai Koehne <[email protected]>
Diffstat (limited to 'src/quick/util/qquickprofiler.cpp')
-rw-r--r-- | src/quick/util/qquickprofiler.cpp | 205 |
1 files changed, 205 insertions, 0 deletions
diff --git a/src/quick/util/qquickprofiler.cpp b/src/quick/util/qquickprofiler.cpp new file mode 100644 index 0000000000..a706fb1e77 --- /dev/null +++ b/src/quick/util/qquickprofiler.cpp @@ -0,0 +1,205 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtQml 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 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. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: 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 +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qquickprofiler_p.h" +#include <private/qqmldebugservice_p.h> +#include <private/qqmlprofilerservice_p.h> + +QT_BEGIN_NAMESPACE + +// instance will be set, unset in constructor. Allows static methods to be inlined. +QQuickProfiler *QQuickProfiler::s_instance = 0; +bool QQuickProfiler::enabled = false; + +// convert to QByteArrays that can be sent to the debug client +// use of QDataStream can skew results +// (see tst_qqmldebugtrace::trace() benchmark) +void QQuickProfilerData::toByteArrays(QList<QByteArray> &messages) const +{ + QByteArray data; + Q_ASSERT_X(((messageType | detailType) & (1 << 31)) == 0, Q_FUNC_INFO, "You can use at most 31 message types and 31 detail types."); + for (uint decodedMessageType = 0; (messageType >> decodedMessageType) != 0; ++decodedMessageType) { + if ((messageType & (1 << decodedMessageType)) == 0) + continue; + + for (uint decodedDetailType = 0; (detailType >> decodedDetailType) != 0; ++decodedDetailType) { + if ((detailType & (1 << decodedDetailType)) == 0) + continue; + + //### using QDataStream is relatively expensive + QQmlDebugStream ds(&data, QIODevice::WriteOnly); + ds << time << decodedMessageType << decodedDetailType; + + switch (decodedMessageType) { + case QQuickProfiler::Event: + if (decodedDetailType == (int)QQuickProfiler::AnimationFrame) + ds << framerate << count; + break; + case QQuickProfiler::PixmapCacheEvent: + ds << detailUrl.toString(); + switch (decodedDetailType) { + case QQuickProfiler::PixmapSizeKnown: ds << x << y; break; + case QQuickProfiler::PixmapReferenceCountChanged: ds << count; break; + case QQuickProfiler::PixmapCacheCountChanged: ds << count; break; + default: break; + } + break; + case QQuickProfiler::SceneGraphFrame: + switch (decodedDetailType) { + // RendererFrame: preprocessTime, updateTime, bindingTime, renderTime + case QQuickProfiler::SceneGraphRendererFrame: ds << subtime_1 << subtime_2 << subtime_3 << subtime_4; break; + // AdaptationLayerFrame: glyphCount (which is an integer), glyphRenderTime, glyphStoreTime + case QQuickProfiler::SceneGraphAdaptationLayerFrame: ds << (int)subtime_1 << subtime_2 << subtime_3; break; + // ContextFrame: compiling material time + case QQuickProfiler::SceneGraphContextFrame: ds << subtime_1; break; + // RenderLoop: syncTime, renderTime, swapTime + case QQuickProfiler::SceneGraphRenderLoopFrame: ds << subtime_1 << subtime_2 << subtime_3; break; + // TexturePrepare: bind, convert, swizzle, upload, mipmap + case QQuickProfiler::SceneGraphTexturePrepare: ds << subtime_1 << subtime_2 << subtime_3 << subtime_4 << subtime_5; break; + // TextureDeletion: deletionTime + case QQuickProfiler::SceneGraphTextureDeletion: ds << subtime_1; break; + // PolishAndSync: polishTime, waitTime, syncTime, animationsTime, + case QQuickProfiler::SceneGraphPolishAndSync: ds << subtime_1 << subtime_2 << subtime_3 << subtime_4; break; + // WindowsRenderLoop: GL time, make current time, SceneGraph time + case QQuickProfiler::SceneGraphWindowsRenderShow: ds << subtime_1 << subtime_2 << subtime_3; break; + // WindowsAnimations: update time + case QQuickProfiler::SceneGraphWindowsAnimations: ds << subtime_1; break; + // WindowsRenderWindow: polish time; always comes packed after a RenderLoop + case QQuickProfiler::SceneGraphWindowsPolishFrame: ds << subtime_4; break; + default:break; + } + break; + default: + Q_ASSERT_X(false, Q_FUNC_INFO, "Invalid message type."); + break; + } + messages << data; + data.clear(); + } + } +} + +qint64 QQuickProfiler::sendMessages(qint64 until, QList<QByteArray> &messages) +{ + QMutexLocker lock(&m_dataMutex); + while (next < m_data.size() && m_data[next].time <= until) { + m_data[next++].toByteArrays(messages); + } + return next < m_data.size() ? m_data[next].time : -1; +} + +void QQuickProfiler::initialize() +{ + Q_ASSERT(s_instance == 0); + QQmlProfilerService *service = QQmlProfilerService::instance(); + s_instance = new QQuickProfiler(service); + QQmlProfilerService::instance()->addGlobalProfiler(s_instance); +} + +void animationTimerCallback(qint64 delta) +{ + Q_QUICK_PROFILE(animationFrame(delta)); +} + +QQuickProfiler::QQuickProfiler(QQmlProfilerService *service) : + QQmlAbstractProfilerAdapter(service), next(0) +{ + // This is safe because at this point the m_instance isn't initialized, yet. + m_timer.start(); + + // We can always do DirectConnection here as all methods are protected by mutexes + connect(this, SIGNAL(profilingEnabled()), this, SLOT(startProfilingImpl()), + Qt::DirectConnection); + connect(this, SIGNAL(profilingEnabledWhileWaiting()), this, SLOT(startProfilingImpl()), + Qt::DirectConnection); + connect(this, SIGNAL(referenceTimeKnown(QElapsedTimer)), this, SLOT(setTimer(QElapsedTimer)), + Qt::DirectConnection); + connect(this, SIGNAL(profilingDisabled()), this, SLOT(stopProfilingImpl()), + Qt::DirectConnection); + connect(this, SIGNAL(profilingDisabledWhileWaiting()), this, SLOT(stopProfilingImpl()), + Qt::DirectConnection); + connect(this, SIGNAL(dataRequested()), this, SLOT(reportDataImpl()), + Qt::DirectConnection); + + QUnifiedTimer::instance()->registerProfilerCallback(&animationTimerCallback); +} + +QQuickProfiler::~QQuickProfiler() +{ + QMutexLocker lock(&m_dataMutex); + enabled = false; + s_instance = 0; +} + +void QQuickProfiler::startProfilingImpl() +{ + QMutexLocker lock(&m_dataMutex); + next = 0; + m_data.clear(); + enabled = true; +} + +void QQuickProfiler::stopProfilingImpl() +{ + { + QMutexLocker lock(&m_dataMutex); + enabled = false; + next = 0; + } + service->dataReady(this); +} + +void QQuickProfiler::reportDataImpl() +{ + { + QMutexLocker lock(&m_dataMutex); + next = 0; + } + service->dataReady(this); +} + +void QQuickProfiler::setTimer(const QElapsedTimer &t) +{ + QMutexLocker lock(&m_dataMutex); + m_timer = t; +} + +QT_END_NAMESPACE |