8e60164769b67898cb56c5bd4ce1dea32e9a62c2
[profile/ivi/qtdeclarative.git] / src / declarative / debugger / qdeclarativedebugtrace.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: http://www.qt-project.org/
6 **
7 ** This file is part of the QtDeclarative module of the Qt Toolkit.
8 **
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.
17 **
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.
21 **
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.
29 **
30 ** Other Usage
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.
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "qdeclarativedebugtrace_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(QDeclarativeDebugTrace, traceInstance)
56
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
61 {
62     QByteArray data;
63     //### using QDataStream is relatively expensive
64     QDataStream ds(&data, QIODevice::WriteOnly);
65     ds << time << messageType << detailType;
66     if (messageType == (int)QDeclarativeDebugTrace::RangeData)
67         ds << detailData;
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;
73     return data;
74 }
75
76 QDeclarativeDebugTrace::QDeclarativeDebugTrace()
77     : QDeclarativeDebugService(QLatin1String("CanvasFrameRate"), 1),
78       m_enabled(false), m_messageReceived(false)
79 {
80     m_timer.start();
81
82     if (registerService() == Enabled) {
83         // wait for first message indicating whether to trace or not
84         while (!m_messageReceived)
85             waitForMessage();
86
87         QUnifiedTimer::instance()->registerProfilerCallback( &animationFrame );
88     }
89 }
90
91 QDeclarativeDebugTrace::~QDeclarativeDebugTrace()
92 {
93 }
94
95 void QDeclarativeDebugTrace::initialize()
96 {
97     // just make sure that the service is properly registered
98     traceInstance();
99 }
100
101 bool QDeclarativeDebugTrace::startProfiling()
102 {
103     return traceInstance()->startProfilingImpl();
104 }
105
106 bool QDeclarativeDebugTrace::stopProfiling()
107 {
108     return traceInstance()->stopProfilingImpl();
109 }
110
111 void QDeclarativeDebugTrace::addEvent(EventType t)
112 {
113     traceInstance()->addEventImpl(t);
114 }
115
116 void QDeclarativeDebugTrace::startRange(RangeType t)
117 {
118     traceInstance()->startRangeImpl(t);
119 }
120
121 void QDeclarativeDebugTrace::rangeData(RangeType t, const QString &data)
122 {
123     traceInstance()->rangeDataImpl(t, data);
124 }
125
126 void QDeclarativeDebugTrace::rangeData(RangeType t, const QUrl &data)
127 {
128     traceInstance()->rangeDataImpl(t, data);
129 }
130
131 void QDeclarativeDebugTrace::rangeLocation(RangeType t, const QString &fileName, int line, int column)
132 {
133     traceInstance()->rangeLocationImpl(t, fileName, line, column);
134 }
135
136 void QDeclarativeDebugTrace::rangeLocation(RangeType t, const QUrl &fileName, int line, int column)
137 {
138     traceInstance()->rangeLocationImpl(t, fileName, line, column);
139 }
140
141 void QDeclarativeDebugTrace::endRange(RangeType t)
142 {
143     traceInstance()->endRangeImpl(t);
144 }
145
146 void QDeclarativeDebugTrace::animationFrame(qint64 delta)
147 {
148     traceInstance()->animationFrameImpl(delta);
149 }
150
151 void QDeclarativeDebugTrace::sendProfilingData()
152 {
153     traceInstance()->sendMessages();
154 }
155
156 bool QDeclarativeDebugTrace::startProfilingImpl()
157 {
158     bool success = false;
159     if (!profilingEnabled()) {
160         setProfilingEnabled(true);
161         addEventImpl(StartTrace);
162         success = true;
163     }
164     return success;
165 }
166
167 bool QDeclarativeDebugTrace::stopProfilingImpl()
168 {
169     bool success = false;
170     if (profilingEnabled()) {
171         addEventImpl(EndTrace);
172         setProfilingEnabled(false);
173         success = true;
174     }
175     return success;
176 }
177
178 void QDeclarativeDebugTrace::addEventImpl(EventType event)
179 {
180     if (!QDeclarativeDebugService::isDebuggingEnabled() || !m_enabled)
181         return;
182
183     QDeclarativeDebugData ed = {m_timer.nsecsElapsed(), (int)Event, (int)event, QString(), -1, -1, 0, 0};
184     processMessage(ed);
185 }
186
187 void QDeclarativeDebugTrace::startRangeImpl(RangeType range)
188 {
189     if (!QDeclarativeDebugService::isDebuggingEnabled() || !m_enabled)
190         return;
191
192     QDeclarativeDebugData rd = {m_timer.nsecsElapsed(), (int)RangeStart, (int)range, QString(), -1, -1, 0, 0};
193     processMessage(rd);
194 }
195
196 void QDeclarativeDebugTrace::rangeDataImpl(RangeType range, const QString &rData)
197 {
198     if (!QDeclarativeDebugService::isDebuggingEnabled() || !m_enabled)
199         return;
200
201     QDeclarativeDebugData rd = {m_timer.nsecsElapsed(), (int)RangeData, (int)range, rData, -1, -1, 0, 0};
202     processMessage(rd);
203 }
204
205 void QDeclarativeDebugTrace::rangeDataImpl(RangeType range, const QUrl &rData)
206 {
207     if (!QDeclarativeDebugService::isDebuggingEnabled() || !m_enabled)
208         return;
209
210     QDeclarativeDebugData rd = {m_timer.nsecsElapsed(), (int)RangeData, (int)range, rData.toString(QUrl::FormattingOption(0x100)), -1, -1, 0, 0};
211     processMessage(rd);
212 }
213
214 void QDeclarativeDebugTrace::rangeLocationImpl(RangeType range, const QString &fileName, int line, int column)
215 {
216     if (!QDeclarativeDebugService::isDebuggingEnabled() || !m_enabled)
217         return;
218
219     QDeclarativeDebugData rd = {m_timer.nsecsElapsed(), (int)RangeLocation, (int)range, fileName, line, column, 0, 0};
220     processMessage(rd);
221 }
222
223 void QDeclarativeDebugTrace::rangeLocationImpl(RangeType range, const QUrl &fileName, int line, int column)
224 {
225     if (!QDeclarativeDebugService::isDebuggingEnabled() || !m_enabled)
226         return;
227
228     QDeclarativeDebugData rd = {m_timer.nsecsElapsed(), (int)RangeLocation, (int)range, fileName.toString(QUrl::FormattingOption(0x100)), line, column, 0, 0};
229     processMessage(rd);
230 }
231
232 void QDeclarativeDebugTrace::endRangeImpl(RangeType range)
233 {
234     if (!QDeclarativeDebugService::isDebuggingEnabled() || !m_enabled)
235         return;
236
237     QDeclarativeDebugData rd = {m_timer.nsecsElapsed(), (int)RangeEnd, (int)range, QString(), -1, -1, 0, 0};
238     processMessage(rd);
239 }
240
241 void QDeclarativeDebugTrace::animationFrameImpl(qint64 delta)
242 {
243     Q_ASSERT(QDeclarativeDebugService::isDebuggingEnabled());
244     if (!m_enabled)
245         return;
246
247     int animCount = QUnifiedTimer::instance()->runningAnimationCount();
248
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};
253         processMessage(ed);
254     }
255 }
256
257 /*
258     Either send the message directly, or queue up
259     a list of messages to send later (via sendMessages)
260 */
261 void QDeclarativeDebugTrace::processMessage(const QDeclarativeDebugData &message)
262 {
263     QMutexLocker locker(&m_mutex);
264     m_data.append(message);
265 }
266
267 bool QDeclarativeDebugTrace::profilingEnabled()
268 {
269     return m_enabled;
270 }
271
272 void QDeclarativeDebugTrace::setProfilingEnabled(bool enable)
273 {
274     m_enabled = enable;
275 }
276
277 /*
278     Send the messages queued up by processMessage
279 */
280 void QDeclarativeDebugTrace::sendMessages()
281 {
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);
287     m_data.clear();
288
289     //indicate completion
290     QByteArray data;
291     QDataStream ds(&data, QIODevice::WriteOnly);
292     ds << (qint64)-1 << (int)Complete;
293     sendMessage(data);
294 }
295
296 void QDeclarativeDebugTrace::messageReceived(const QByteArray &message)
297 {
298     QByteArray rwData = message;
299     QDataStream stream(&rwData, QIODevice::ReadOnly);
300
301     bool enabled;
302     stream >> enabled;
303
304     m_messageReceived = true;
305
306     if (enabled) {
307         startProfilingImpl();
308     } else {
309         if (stopProfilingImpl())
310             sendMessages();
311     }
312 }
313
314 QT_END_NAMESPACE