QmlProfiler: send end of trace event
[profile/ivi/qtdeclarative.git] / src / declarative / debugger / qdeclarativedebugtrace.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
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 if m_deferredSend == false
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;
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")),
78       m_enabled(false), m_deferredSend(true), m_messageReceived(false)
79 {
80     m_timer.start();
81     if (status() == Enabled) {
82         // wait for first message indicating whether to trace or not
83         while (!m_messageReceived)
84             waitForMessage();
85
86         QUnifiedTimer::instance()->registerProfilerCallback( &animationFrame );
87     }
88 }
89
90 QDeclarativeDebugTrace::~QDeclarativeDebugTrace()
91 {
92     // unregister the callback
93     QUnifiedTimer::instance()->registerProfilerCallback( 0 );
94 }
95
96 void QDeclarativeDebugTrace::addEngine(QDeclarativeEngine * /*engine*/)
97 {
98     // just make sure that the service is properly registered
99     traceInstance();
100 }
101
102 void QDeclarativeDebugTrace::removeEngine(QDeclarativeEngine */*engine*/)
103 {
104
105 }
106
107 void QDeclarativeDebugTrace::addEvent(EventType t)
108 {
109     if (QDeclarativeDebugService::isDebuggingEnabled())
110         traceInstance()->addEventImpl(t);
111 }
112
113 void QDeclarativeDebugTrace::startRange(RangeType t)
114 {
115     if (QDeclarativeDebugService::isDebuggingEnabled())
116         traceInstance()->startRangeImpl(t);
117 }
118
119 void QDeclarativeDebugTrace::rangeData(RangeType t, const QString &data)
120 {
121     if (QDeclarativeDebugService::isDebuggingEnabled())
122         traceInstance()->rangeDataImpl(t, data);
123 }
124
125 void QDeclarativeDebugTrace::rangeData(RangeType t, const QUrl &data)
126 {
127     if (QDeclarativeDebugService::isDebuggingEnabled())
128         traceInstance()->rangeDataImpl(t, data);
129 }
130
131 void QDeclarativeDebugTrace::rangeLocation(RangeType t, const QString &fileName, int line)
132 {
133     if (QDeclarativeDebugService::isDebuggingEnabled())
134         traceInstance()->rangeLocationImpl(t, fileName, line);
135 }
136
137 void QDeclarativeDebugTrace::rangeLocation(RangeType t, const QUrl &fileName, int line)
138 {
139     if (QDeclarativeDebugService::isDebuggingEnabled())
140         traceInstance()->rangeLocationImpl(t, fileName, line);
141 }
142
143 void QDeclarativeDebugTrace::endRange(RangeType t)
144 {
145     if (QDeclarativeDebugService::isDebuggingEnabled())
146         traceInstance()->endRangeImpl(t);
147 }
148
149 void QDeclarativeDebugTrace::animationFrame(qint64 delta)
150 {
151     Q_ASSERT(QDeclarativeDebugService::isDebuggingEnabled());
152     traceInstance()->animationFrameImpl(delta);
153 }
154
155 void QDeclarativeDebugTrace::addEventImpl(EventType event)
156 {
157     if (status() != Enabled || !m_enabled)
158         return;
159
160     QDeclarativeDebugData ed = {m_timer.nsecsElapsed(), (int)Event, (int)event, QString(), -1, 0, 0};
161     processMessage(ed);
162 }
163
164 void QDeclarativeDebugTrace::startRangeImpl(RangeType range)
165 {
166     if (status() != Enabled || !m_enabled)
167         return;
168
169     QDeclarativeDebugData rd = {m_timer.nsecsElapsed(), (int)RangeStart, (int)range, QString(), -1, 0, 0};
170     processMessage(rd);
171 }
172
173 void QDeclarativeDebugTrace::rangeDataImpl(RangeType range, const QString &rData)
174 {
175     if (status() != Enabled || !m_enabled)
176         return;
177
178     QDeclarativeDebugData rd = {m_timer.nsecsElapsed(), (int)RangeData, (int)range, rData, -1, 0, 0};
179     processMessage(rd);
180 }
181
182 void QDeclarativeDebugTrace::rangeDataImpl(RangeType range, const QUrl &rData)
183 {
184     if (status() != Enabled || !m_enabled)
185         return;
186
187     QDeclarativeDebugData rd = {m_timer.nsecsElapsed(), (int)RangeData, (int)range, rData.toString(QUrl::FormattingOption(0x100)), -1, 0, 0};
188     processMessage(rd);
189 }
190
191 void QDeclarativeDebugTrace::rangeLocationImpl(RangeType range, const QString &fileName, int line)
192 {
193     if (status() != Enabled || !m_enabled)
194         return;
195
196     QDeclarativeDebugData rd = {m_timer.nsecsElapsed(), (int)RangeLocation, (int)range, fileName, line, 0, 0};
197     processMessage(rd);
198 }
199
200 void QDeclarativeDebugTrace::rangeLocationImpl(RangeType range, const QUrl &fileName, int line)
201 {
202     if (status() != Enabled || !m_enabled)
203         return;
204
205     QDeclarativeDebugData rd = {m_timer.nsecsElapsed(), (int)RangeLocation, (int)range, fileName.toString(QUrl::FormattingOption(0x100)), line, 0, 0};
206     processMessage(rd);
207 }
208
209 void QDeclarativeDebugTrace::endRangeImpl(RangeType range)
210 {
211     if (status() != Enabled || !m_enabled)
212         return;
213
214     QDeclarativeDebugData rd = {m_timer.nsecsElapsed(), (int)RangeEnd, (int)range, QString(), -1, 0, 0};
215     processMessage(rd);
216 }
217
218 void QDeclarativeDebugTrace::animationFrameImpl(qint64 delta)
219 {
220     if (status() != Enabled || !m_enabled)
221         return;
222
223     int animCount = QUnifiedTimer::instance()->runningAnimationCount();
224
225     if (animCount > 0 && delta > 0) {
226         // trim fps to integer
227         int fps = 1000 / delta;
228         QDeclarativeDebugData ed = {m_timer.nsecsElapsed(), (int)Event, (int)AnimationFrame, QString(), -1, fps, animCount};
229         processMessage(ed);
230     }
231 }
232
233 /*
234     Either send the message directly, or queue up
235     a list of messages to send later (via sendMessages)
236 */
237 void QDeclarativeDebugTrace::processMessage(const QDeclarativeDebugData &message)
238 {
239     QMutexLocker locker(&m_mutex);
240     if (m_deferredSend
241             || (QThread::currentThread() != QCoreApplication::instance()->thread()))
242         m_data.append(message);
243     else
244         sendMessage(message.toByteArray());
245 }
246
247 /*
248     Send the messages queued up by processMessage
249 */
250 void QDeclarativeDebugTrace::sendMessages()
251 {
252     if (m_deferredSend) {
253         QMutexLocker locker(&m_mutex);
254         //### this is a suboptimal way to send batched messages
255         for (int i = 0; i < m_data.count(); ++i)
256             sendMessage(m_data.at(i).toByteArray());
257         m_data.clear();
258
259         //indicate completion
260         QByteArray data;
261         QDataStream ds(&data, QIODevice::WriteOnly);
262         ds << (qint64)-1 << (int)Complete;
263         sendMessage(data);
264     }
265 }
266
267 void QDeclarativeDebugTrace::messageReceived(const QByteArray &message)
268 {
269     QByteArray rwData = message;
270     QDataStream stream(&rwData, QIODevice::ReadOnly);
271
272     stream >> m_enabled;
273
274     m_messageReceived = true;
275
276     if (!m_enabled) {
277         m_enabled = true;
278         addEvent(EndTrace);
279         m_enabled = false;
280         sendMessages();
281     }
282 }
283
284 QT_END_NAMESPACE