1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: http://www.qt-project.org/
7 ** This file is part of the QtDeclarative module of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 #include "qdeclarativedebugtrace_p.h"
44 #include <QtCore/qdatastream.h>
45 #include <QtCore/qurl.h>
46 #include <QtCore/qtimer.h>
47 #include <QtCore/qthread.h>
48 #include <QtCore/qcoreapplication.h>
50 // this contains QUnifiedTimer
51 #include <private/qabstractanimation_p.h>
55 Q_GLOBAL_STATIC(QDeclarativeDebugTrace, traceInstance)
57 // convert to a QByteArray that can be sent to the debug client
58 // use of QDataStream can skew results
59 // (see tst_qdeclarativedebugtrace::trace() benchmark)
60 QByteArray QDeclarativeDebugData::toByteArray() const
63 //### using QDataStream is relatively expensive
64 QDataStream ds(&data, QIODevice::WriteOnly);
65 ds << time << messageType << detailType;
66 if (messageType == (int)QDeclarativeDebugTrace::RangeData)
68 if (messageType == (int)QDeclarativeDebugTrace::RangeLocation)
69 ds << detailData << line << column;
70 if (messageType == (int)QDeclarativeDebugTrace::Event &&
71 detailType == (int)QDeclarativeDebugTrace::AnimationFrame)
72 ds << framerate << animationcount;
76 QDeclarativeDebugTrace::QDeclarativeDebugTrace()
77 : QDeclarativeDebugService(QLatin1String("CanvasFrameRate"), 1),
78 m_enabled(false), m_messageReceived(false)
82 if (registerService() == Enabled) {
83 // wait for first message indicating whether to trace or not
84 while (!m_messageReceived)
87 QUnifiedTimer::instance()->registerProfilerCallback( &animationFrame );
91 QDeclarativeDebugTrace::~QDeclarativeDebugTrace()
95 void QDeclarativeDebugTrace::initialize()
97 // just make sure that the service is properly registered
101 bool QDeclarativeDebugTrace::startProfiling()
103 return traceInstance()->startProfilingImpl();
106 bool QDeclarativeDebugTrace::stopProfiling()
108 return traceInstance()->stopProfilingImpl();
111 void QDeclarativeDebugTrace::addEvent(EventType t)
113 traceInstance()->addEventImpl(t);
116 void QDeclarativeDebugTrace::startRange(RangeType t)
118 traceInstance()->startRangeImpl(t);
121 void QDeclarativeDebugTrace::rangeData(RangeType t, const QString &data)
123 traceInstance()->rangeDataImpl(t, data);
126 void QDeclarativeDebugTrace::rangeData(RangeType t, const QUrl &data)
128 traceInstance()->rangeDataImpl(t, data);
131 void QDeclarativeDebugTrace::rangeLocation(RangeType t, const QString &fileName, int line, int column)
133 traceInstance()->rangeLocationImpl(t, fileName, line, column);
136 void QDeclarativeDebugTrace::rangeLocation(RangeType t, const QUrl &fileName, int line, int column)
138 traceInstance()->rangeLocationImpl(t, fileName, line, column);
141 void QDeclarativeDebugTrace::endRange(RangeType t)
143 traceInstance()->endRangeImpl(t);
146 void QDeclarativeDebugTrace::animationFrame(qint64 delta)
148 traceInstance()->animationFrameImpl(delta);
151 void QDeclarativeDebugTrace::sendProfilingData()
153 traceInstance()->sendMessages();
156 bool QDeclarativeDebugTrace::startProfilingImpl()
158 bool success = false;
159 if (!profilingEnabled()) {
160 setProfilingEnabled(true);
161 addEventImpl(StartTrace);
167 bool QDeclarativeDebugTrace::stopProfilingImpl()
169 bool success = false;
170 if (profilingEnabled()) {
171 addEventImpl(EndTrace);
172 setProfilingEnabled(false);
178 void QDeclarativeDebugTrace::addEventImpl(EventType event)
180 if (!QDeclarativeDebugService::isDebuggingEnabled() || !m_enabled)
183 QDeclarativeDebugData ed = {m_timer.nsecsElapsed(), (int)Event, (int)event, QString(), -1, -1, 0, 0};
187 void QDeclarativeDebugTrace::startRangeImpl(RangeType range)
189 if (!QDeclarativeDebugService::isDebuggingEnabled() || !m_enabled)
192 QDeclarativeDebugData rd = {m_timer.nsecsElapsed(), (int)RangeStart, (int)range, QString(), -1, -1, 0, 0};
196 void QDeclarativeDebugTrace::rangeDataImpl(RangeType range, const QString &rData)
198 if (!QDeclarativeDebugService::isDebuggingEnabled() || !m_enabled)
201 QDeclarativeDebugData rd = {m_timer.nsecsElapsed(), (int)RangeData, (int)range, rData, -1, -1, 0, 0};
205 void QDeclarativeDebugTrace::rangeDataImpl(RangeType range, const QUrl &rData)
207 if (!QDeclarativeDebugService::isDebuggingEnabled() || !m_enabled)
210 QDeclarativeDebugData rd = {m_timer.nsecsElapsed(), (int)RangeData, (int)range, rData.toString(QUrl::FormattingOption(0x100)), -1, -1, 0, 0};
214 void QDeclarativeDebugTrace::rangeLocationImpl(RangeType range, const QString &fileName, int line, int column)
216 if (!QDeclarativeDebugService::isDebuggingEnabled() || !m_enabled)
219 QDeclarativeDebugData rd = {m_timer.nsecsElapsed(), (int)RangeLocation, (int)range, fileName, line, column, 0, 0};
223 void QDeclarativeDebugTrace::rangeLocationImpl(RangeType range, const QUrl &fileName, int line, int column)
225 if (!QDeclarativeDebugService::isDebuggingEnabled() || !m_enabled)
228 QDeclarativeDebugData rd = {m_timer.nsecsElapsed(), (int)RangeLocation, (int)range, fileName.toString(QUrl::FormattingOption(0x100)), line, column, 0, 0};
232 void QDeclarativeDebugTrace::endRangeImpl(RangeType range)
234 if (!QDeclarativeDebugService::isDebuggingEnabled() || !m_enabled)
237 QDeclarativeDebugData rd = {m_timer.nsecsElapsed(), (int)RangeEnd, (int)range, QString(), -1, -1, 0, 0};
241 void QDeclarativeDebugTrace::animationFrameImpl(qint64 delta)
243 Q_ASSERT(QDeclarativeDebugService::isDebuggingEnabled());
247 int animCount = QUnifiedTimer::instance()->runningAnimationCount();
249 if (animCount > 0 && delta > 0) {
250 // trim fps to integer
251 int fps = 1000 / delta;
252 QDeclarativeDebugData ed = {m_timer.nsecsElapsed(), (int)Event, (int)AnimationFrame, QString(), -1, -1, fps, animCount};
258 Either send the message directly, or queue up
259 a list of messages to send later (via sendMessages)
261 void QDeclarativeDebugTrace::processMessage(const QDeclarativeDebugData &message)
263 QMutexLocker locker(&m_mutex);
264 m_data.append(message);
267 bool QDeclarativeDebugTrace::profilingEnabled()
272 void QDeclarativeDebugTrace::setProfilingEnabled(bool enable)
278 Send the messages queued up by processMessage
280 void QDeclarativeDebugTrace::sendMessages()
282 QMutexLocker locker(&m_mutex);
283 QList<QByteArray> messages;
284 for (int i = 0; i < m_data.count(); ++i)
285 messages << m_data.at(i).toByteArray();
286 QDeclarativeDebugService::sendMessages(messages);
289 //indicate completion
291 QDataStream ds(&data, QIODevice::WriteOnly);
292 ds << (qint64)-1 << (int)Complete;
296 void QDeclarativeDebugTrace::messageReceived(const QByteArray &message)
298 QByteArray rwData = message;
299 QDataStream stream(&rwData, QIODevice::ReadOnly);
304 m_messageReceived = true;
307 startProfilingImpl();
309 if (stopProfilingImpl())