QML_RUNTIME_TESTING should be disabled by default.
[profile/ivi/qtdeclarative.git] / src / declarative / debugger / qdeclarativeprofilerservice.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
5 **
6 ** This file is part of the QtDeclarative module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
16 **
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
20 **
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
28 **
29 ** Other Usage
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "qdeclarativeprofilerservice_p.h"
43
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>
49
50 // this contains QUnifiedTimer
51 #include <private/qabstractanimation_p.h>
52
53 QT_BEGIN_NAMESPACE
54
55 Q_GLOBAL_STATIC(QDeclarativeProfilerService, profilerInstance)
56
57 QDeclarativeBindingProfiler::QDeclarativeBindingProfiler(const QString &url, int line, int column)
58 {
59     QDeclarativeProfilerService::startRange(QDeclarativeProfilerService::Binding);
60     QDeclarativeProfilerService::rangeLocation(QDeclarativeProfilerService::Binding, url, line, column);
61 }
62
63 QDeclarativeBindingProfiler::~QDeclarativeBindingProfiler()
64 {
65     QDeclarativeProfilerService::endRange(QDeclarativeProfilerService::Binding);
66 }
67
68 void QDeclarativeBindingProfiler::addDetail(const QString &details)
69 {
70     QDeclarativeProfilerService::rangeData(QDeclarativeProfilerService::Binding, details);
71 }
72
73 // convert to a QByteArray that can be sent to the debug client
74 // use of QDataStream can skew results
75 //     (see tst_qdeclarativedebugtrace::trace() benchmark)
76 QByteArray QDeclarativeProfilerData::toByteArray() const
77 {
78     QByteArray data;
79     //### using QDataStream is relatively expensive
80     QDataStream ds(&data, QIODevice::WriteOnly);
81     ds << time << messageType << detailType;
82     if (messageType == (int)QDeclarativeProfilerService::RangeData)
83         ds << detailData;
84     if (messageType == (int)QDeclarativeProfilerService::RangeLocation)
85         ds << detailData << line << column;
86     if (messageType == (int)QDeclarativeProfilerService::Event &&
87             detailType == (int)QDeclarativeProfilerService::AnimationFrame)
88         ds << framerate << animationcount;
89     return data;
90 }
91
92 QDeclarativeProfilerService::QDeclarativeProfilerService()
93     : QDeclarativeDebugService(QLatin1String("CanvasFrameRate"), 1),
94       m_enabled(false), m_messageReceived(false)
95 {
96     m_timer.start();
97
98     if (registerService() == Enabled) {
99         // wait for first message indicating whether to trace or not
100         while (!m_messageReceived)
101             waitForMessage();
102
103         QUnifiedTimer::instance()->registerProfilerCallback( &animationFrame );
104     }
105 }
106
107 QDeclarativeProfilerService::~QDeclarativeProfilerService()
108 {
109 }
110
111 void QDeclarativeProfilerService::initialize()
112 {
113     // just make sure that the service is properly registered
114     profilerInstance();
115 }
116
117 bool QDeclarativeProfilerService::startProfiling()
118 {
119     return profilerInstance()->startProfilingImpl();
120 }
121
122 bool QDeclarativeProfilerService::stopProfiling()
123 {
124     return profilerInstance()->stopProfilingImpl();
125 }
126
127 void QDeclarativeProfilerService::sendStartedProfilingMessage()
128 {
129     profilerInstance()->sendStartedProfilingMessageImpl();
130 }
131
132 void QDeclarativeProfilerService::addEvent(EventType t)
133 {
134     profilerInstance()->addEventImpl(t);
135 }
136
137 void QDeclarativeProfilerService::startRange(RangeType t)
138 {
139     profilerInstance()->startRangeImpl(t);
140 }
141
142 void QDeclarativeProfilerService::rangeData(RangeType t, const QString &data)
143 {
144     profilerInstance()->rangeDataImpl(t, data);
145 }
146
147 void QDeclarativeProfilerService::rangeData(RangeType t, const QUrl &data)
148 {
149     profilerInstance()->rangeDataImpl(t, data);
150 }
151
152 void QDeclarativeProfilerService::rangeLocation(RangeType t, const QString &fileName, int line, int column)
153 {
154     profilerInstance()->rangeLocationImpl(t, fileName, line, column);
155 }
156
157 void QDeclarativeProfilerService::rangeLocation(RangeType t, const QUrl &fileName, int line, int column)
158 {
159     profilerInstance()->rangeLocationImpl(t, fileName, line, column);
160 }
161
162 void QDeclarativeProfilerService::endRange(RangeType t)
163 {
164     profilerInstance()->endRangeImpl(t);
165 }
166
167 void QDeclarativeProfilerService::animationFrame(qint64 delta)
168 {
169     profilerInstance()->animationFrameImpl(delta);
170 }
171
172 void QDeclarativeProfilerService::sendProfilingData()
173 {
174     profilerInstance()->sendMessages();
175 }
176
177 bool QDeclarativeProfilerService::startProfilingImpl()
178 {
179     bool success = false;
180     if (!profilingEnabled()) {
181         setProfilingEnabled(true);
182         sendStartedProfilingMessageImpl();
183         success = true;
184     }
185     return success;
186 }
187
188 bool QDeclarativeProfilerService::stopProfilingImpl()
189 {
190     bool success = false;
191     if (profilingEnabled()) {
192         addEventImpl(EndTrace);
193         setProfilingEnabled(false);
194         success = true;
195     }
196     return success;
197 }
198
199 void QDeclarativeProfilerService::sendStartedProfilingMessageImpl()
200 {
201     if (!QDeclarativeDebugService::isDebuggingEnabled() || !m_enabled)
202         return;
203
204     QDeclarativeProfilerData ed = {m_timer.nsecsElapsed(), (int)Event, (int)StartTrace, QString(), -1, -1, 0, 0};
205     QDeclarativeDebugService::sendMessage(ed.toByteArray());
206 }
207
208 void QDeclarativeProfilerService::addEventImpl(EventType event)
209 {
210     if (!QDeclarativeDebugService::isDebuggingEnabled() || !m_enabled)
211         return;
212
213     QDeclarativeProfilerData ed = {m_timer.nsecsElapsed(), (int)Event, (int)event, QString(), -1, -1, 0, 0};
214     processMessage(ed);
215 }
216
217 void QDeclarativeProfilerService::startRangeImpl(RangeType range)
218 {
219     if (!QDeclarativeDebugService::isDebuggingEnabled() || !m_enabled)
220         return;
221
222     QDeclarativeProfilerData rd = {m_timer.nsecsElapsed(), (int)RangeStart, (int)range, QString(), -1, -1, 0, 0};
223     processMessage(rd);
224 }
225
226 void QDeclarativeProfilerService::rangeDataImpl(RangeType range, const QString &rData)
227 {
228     if (!QDeclarativeDebugService::isDebuggingEnabled() || !m_enabled)
229         return;
230
231     QDeclarativeProfilerData rd = {m_timer.nsecsElapsed(), (int)RangeData, (int)range, rData, -1, -1, 0, 0};
232     processMessage(rd);
233 }
234
235 void QDeclarativeProfilerService::rangeDataImpl(RangeType range, const QUrl &rData)
236 {
237     if (!QDeclarativeDebugService::isDebuggingEnabled() || !m_enabled)
238         return;
239
240     QDeclarativeProfilerData rd = {m_timer.nsecsElapsed(), (int)RangeData, (int)range, rData.toString(QUrl::FormattingOption(0x100)), -1, -1, 0, 0};
241     processMessage(rd);
242 }
243
244 void QDeclarativeProfilerService::rangeLocationImpl(RangeType range, const QString &fileName, int line, int column)
245 {
246     if (!QDeclarativeDebugService::isDebuggingEnabled() || !m_enabled)
247         return;
248
249     QDeclarativeProfilerData rd = {m_timer.nsecsElapsed(), (int)RangeLocation, (int)range, fileName, line, column, 0, 0};
250     processMessage(rd);
251 }
252
253 void QDeclarativeProfilerService::rangeLocationImpl(RangeType range, const QUrl &fileName, int line, int column)
254 {
255     if (!QDeclarativeDebugService::isDebuggingEnabled() || !m_enabled)
256         return;
257
258     QDeclarativeProfilerData rd = {m_timer.nsecsElapsed(), (int)RangeLocation, (int)range, fileName.toString(QUrl::FormattingOption(0x100)), line, column, 0, 0};
259     processMessage(rd);
260 }
261
262 void QDeclarativeProfilerService::endRangeImpl(RangeType range)
263 {
264     if (!QDeclarativeDebugService::isDebuggingEnabled() || !m_enabled)
265         return;
266
267     QDeclarativeProfilerData rd = {m_timer.nsecsElapsed(), (int)RangeEnd, (int)range, QString(), -1, -1, 0, 0};
268     processMessage(rd);
269 }
270
271 void QDeclarativeProfilerService::animationFrameImpl(qint64 delta)
272 {
273     Q_ASSERT(QDeclarativeDebugService::isDebuggingEnabled());
274     if (!m_enabled)
275         return;
276
277     int animCount = QUnifiedTimer::instance()->runningAnimationCount();
278
279     if (animCount > 0 && delta > 0) {
280         // trim fps to integer
281         int fps = 1000 / delta;
282         QDeclarativeProfilerData ed = {m_timer.nsecsElapsed(), (int)Event, (int)AnimationFrame, QString(), -1, -1, fps, animCount};
283         processMessage(ed);
284     }
285 }
286
287 /*
288     Either send the message directly, or queue up
289     a list of messages to send later (via sendMessages)
290 */
291 void QDeclarativeProfilerService::processMessage(const QDeclarativeProfilerData &message)
292 {
293     QMutexLocker locker(&m_mutex);
294     m_data.append(message);
295 }
296
297 bool QDeclarativeProfilerService::profilingEnabled()
298 {
299     return m_enabled;
300 }
301
302 void QDeclarativeProfilerService::setProfilingEnabled(bool enable)
303 {
304     m_enabled = enable;
305 }
306
307 /*
308     Send the messages queued up by processMessage
309 */
310 void QDeclarativeProfilerService::sendMessages()
311 {
312     QMutexLocker locker(&m_mutex);
313     QList<QByteArray> messages;
314     for (int i = 0; i < m_data.count(); ++i)
315         messages << m_data.at(i).toByteArray();
316     m_data.clear();
317
318     //indicate completion
319     QByteArray data;
320     QDataStream ds(&data, QIODevice::WriteOnly);
321     ds << (qint64)-1 << (int)Complete;
322     messages << data;
323
324     QDeclarativeDebugService::sendMessages(messages);
325 }
326
327 void QDeclarativeProfilerService::stateAboutToBeChanged(QDeclarativeDebugService::State newState)
328 {
329     if (state() == newState)
330         return;
331
332     if (state() == Enabled
333             && m_enabled) {
334         stopProfilingImpl();
335         sendMessages();
336     }
337 }
338
339 void QDeclarativeProfilerService::messageReceived(const QByteArray &message)
340 {
341     QByteArray rwData = message;
342     QDataStream stream(&rwData, QIODevice::ReadOnly);
343
344     bool enabled;
345     stream >> enabled;
346
347     m_messageReceived = true;
348
349     if (enabled) {
350         startProfilingImpl();
351     } else {
352         if (stopProfilingImpl())
353             sendMessages();
354     }
355 }
356
357 QT_END_NAMESPACE