blob: d6a9e41375c2cda6ef5f39eb43084e21d2b35cc0 [file] [log] [blame]
Zack Rusinf6667d12011-03-30 11:03:37 -04001#include "apitrace.h"
2
Zack Rusinebf971e2011-09-06 17:44:43 -04003#include "traceloader.h"
Zack Rusind809a062011-04-17 23:30:58 -04004#include "saverthread.h"
Zack Rusinf6667d12011-03-30 11:03:37 -04005
Zack Rusin63efea82011-04-17 17:10:45 -04006#include <QDir>
Zack Rusinebf971e2011-09-06 17:44:43 -04007#include <QThread>
Zack Rusin63efea82011-04-17 17:10:45 -04008
Zack Rusinf6667d12011-03-30 11:03:37 -04009ApiTrace::ApiTrace()
Zack Rusin63efea82011-04-17 17:10:45 -040010 : m_frameMarker(ApiTrace::FrameMarker_SwapBuffers),
11 m_needsSaving(false)
Zack Rusinf6667d12011-03-30 11:03:37 -040012{
Zack Rusinebf971e2011-09-06 17:44:43 -040013 m_loader = new TraceLoader();
14 connect(this, SIGNAL(loadTrace(QString)),
15 m_loader, SLOT(loadTrace(QString)));
16 connect(m_loader, SIGNAL(framesLoaded(const QList<ApiTraceFrame*>)),
Zack Rusinf6667d12011-03-30 11:03:37 -040017 this, SLOT(addFrames(const QList<ApiTraceFrame*>)));
Zack Rusinebf971e2011-09-06 17:44:43 -040018 connect(m_loader, SIGNAL(frameLoaded(int,QVector<ApiTraceCall*>,quint64)),
19 this, SLOT(fillFrame(int,QVector<ApiTraceCall*>,quint64)));
20
21 connect(m_loader, SIGNAL(startedParsing()),
Zack Rusinde4ea412011-03-30 11:30:08 -040022 this, SIGNAL(startedLoadingTrace()));
Zack Rusinebf971e2011-09-06 17:44:43 -040023 connect(m_loader, SIGNAL(parsed(int)),
24 this, SIGNAL(loaded(int)));
25 connect(m_loader, SIGNAL(finishedParsing()),
Zack Rusinde4ea412011-03-30 11:30:08 -040026 this, SIGNAL(finishedLoadingTrace()));
Zack Rusind809a062011-04-17 23:30:58 -040027
Zack Rusinebf971e2011-09-06 17:44:43 -040028
Zack Rusind809a062011-04-17 23:30:58 -040029 m_saver = new SaverThread(this);
Zack Rusin9af5bff2011-04-18 01:05:50 -040030 connect(m_saver, SIGNAL(traceSaved()),
31 this, SLOT(slotSaved()));
32 connect(m_saver, SIGNAL(traceSaved()),
33 this, SIGNAL(saved()));
Zack Rusinebf971e2011-09-06 17:44:43 -040034
35 m_loaderThread = new QThread();
36 m_loader->moveToThread(m_loaderThread);
37 m_loaderThread->start();
Zack Rusinf6667d12011-03-30 11:03:37 -040038}
39
40ApiTrace::~ApiTrace()
41{
Zack Rusinebf971e2011-09-06 17:44:43 -040042 m_loaderThread->quit();
43 m_loaderThread->deleteLater();
Zack Rusinf6667d12011-03-30 11:03:37 -040044 qDeleteAll(m_calls);
45 qDeleteAll(m_frames);
46 delete m_loader;
Zack Rusind809a062011-04-17 23:30:58 -040047 delete m_saver;
Zack Rusinf6667d12011-03-30 11:03:37 -040048}
49
50bool ApiTrace::isCallAFrameMarker(const ApiTraceCall *call,
51 ApiTrace::FrameMarker marker)
52{
53 if (!call)
54 return false;
55
56 switch (marker) {
57 case FrameMarker_SwapBuffers:
José Fonseca3e9ff852011-06-06 19:37:09 +010058 return call->name().contains(QLatin1String("SwapBuffers")) ||
José Fonsecadb678122011-07-29 17:20:05 +010059 call->name() == QLatin1String("CGLFlushDrawable") ||
60 call->name() == QLatin1String("glFrameTerminatorGREMEDY");
Zack Rusinf6667d12011-03-30 11:03:37 -040061 case FrameMarker_Flush:
Zack Rusinead6aad2011-04-15 22:16:18 -040062 return call->name() == QLatin1String("glFlush");
Zack Rusinf6667d12011-03-30 11:03:37 -040063 case FrameMarker_Finish:
Zack Rusinead6aad2011-04-15 22:16:18 -040064 return call->name() == QLatin1String("glFinish");
Zack Rusinf6667d12011-03-30 11:03:37 -040065 case FrameMarker_Clear:
Zack Rusinead6aad2011-04-15 22:16:18 -040066 return call->name() == QLatin1String("glClear");
Zack Rusinf6667d12011-03-30 11:03:37 -040067 }
68
69 Q_ASSERT(!"unknown frame marker");
70
71 return false;
72}
73
74bool ApiTrace::isEmpty() const
75{
76 return m_calls.isEmpty();
77}
78
79QString ApiTrace::fileName() const
80{
Zack Rusin63efea82011-04-17 17:10:45 -040081 if (edited())
82 return m_tempFileName;
83
Zack Rusinf6667d12011-03-30 11:03:37 -040084 return m_fileName;
85}
86
87ApiTrace::FrameMarker ApiTrace::frameMarker() const
88{
89 return m_frameMarker;
90}
91
Zack Rusin4d0ef5d2011-08-28 22:05:31 -040092QVector<ApiTraceCall*> ApiTrace::calls() const
Zack Rusinf6667d12011-03-30 11:03:37 -040093{
94 return m_calls;
95}
96
97ApiTraceCall * ApiTrace::callAt(int idx) const
98{
99 return m_calls.value(idx);
100}
101
102int ApiTrace::numCalls() const
103{
104 return m_calls.count();
105}
106
107QList<ApiTraceFrame*> ApiTrace::frames() const
108{
109 return m_frames;
110}
111
112ApiTraceFrame * ApiTrace::frameAt(int idx) const
113{
114 return m_frames.value(idx);
115}
116
117int ApiTrace::numFrames() const
118{
119 return m_frames.count();
120}
121
122int ApiTrace::numCallsInFrame(int idx) const
123{
124 const ApiTraceFrame *frame = frameAt(idx);
125 if (frame)
Zack Rusin1d31b6c2011-04-26 22:30:25 -0400126 return frame->numChildren();
Zack Rusinf6667d12011-03-30 11:03:37 -0400127 else
128 return 0;
129}
130
131void ApiTrace::setFileName(const QString &name)
132{
133 if (m_fileName != name) {
134 m_fileName = name;
135
Zack Rusinca164112011-04-11 02:23:09 -0400136 m_frames.clear();
137 m_calls.clear();
Zack Rusin30069572011-04-20 18:21:11 -0400138 m_errors.clear();
139 m_editedCalls.clear();
140 m_needsSaving = false;
Zack Rusinf6667d12011-03-30 11:03:37 -0400141 emit invalidated();
142
Zack Rusinebf971e2011-09-06 17:44:43 -0400143// m_loader->loadTrace(m_fileName);
144 emit loadTrace(m_fileName);
Zack Rusinf6667d12011-03-30 11:03:37 -0400145 }
146}
147
148void ApiTrace::setFrameMarker(FrameMarker marker)
149{
150 if (m_frameMarker != marker) {
151 emit framesInvalidated();
152
153 qDeleteAll(m_frames);
154 m_frames.clear();
155 detectFrames();
156 }
157}
158
159void ApiTrace::addFrames(const QList<ApiTraceFrame*> &frames)
160{
Zack Rusin4d0ef5d2011-08-28 22:05:31 -0400161 QVector<ApiTraceCall*> calls;
Zack Rusinf6667d12011-03-30 11:03:37 -0400162 int currentFrames = m_frames.count();
163 int numNewFrames = frames.count();
Zack Rusinb56e03d2011-04-20 23:58:52 -0400164
165 emit beginAddingFrames(currentFrames, numNewFrames);
166
Zack Rusinf6667d12011-03-30 11:03:37 -0400167 m_frames += frames;
168
169 int currentCalls = m_calls.count();
170 int numNewCalls = 0;
171 foreach(ApiTraceFrame *frame, frames) {
Zack Rusinebf971e2011-09-06 17:44:43 -0400172 frame->setParentTrace(this);
Zack Rusin1d31b6c2011-04-26 22:30:25 -0400173 numNewCalls += frame->numChildren();
Zack Rusin410a8f32011-08-28 02:38:34 -0400174 calls += frame->calls();
Zack Rusinf6667d12011-03-30 11:03:37 -0400175 }
Zack Rusin4d0ef5d2011-08-28 22:05:31 -0400176 m_calls.reserve(m_calls.count() + calls.count() + 1);
Zack Rusin410a8f32011-08-28 02:38:34 -0400177 m_calls += calls;
Zack Rusinf6667d12011-03-30 11:03:37 -0400178
Zack Rusinb56e03d2011-04-20 23:58:52 -0400179 emit endAddingFrames();
Zack Rusinf6667d12011-03-30 11:03:37 -0400180 emit callsAdded(currentCalls, numNewCalls);
181}
182
183void ApiTrace::detectFrames()
184{
185 if (m_calls.isEmpty())
186 return;
187
Zack Rusinb56e03d2011-04-20 23:58:52 -0400188 emit beginAddingFrames(0, m_frames.count());
189
Zack Rusinf6667d12011-03-30 11:03:37 -0400190 ApiTraceFrame *currentFrame = 0;
191 foreach(ApiTraceCall *apiCall, m_calls) {
192 if (!currentFrame) {
Zack Rusinac4dd9a2011-08-28 00:38:13 -0400193 currentFrame = new ApiTraceFrame(this);
Zack Rusinf6667d12011-03-30 11:03:37 -0400194 currentFrame->number = m_frames.count();
Zack Rusin20b1f6d2011-09-06 11:50:07 -0400195 currentFrame->setLoaded(true);
Zack Rusinf6667d12011-03-30 11:03:37 -0400196 }
Zack Rusinead6aad2011-04-15 22:16:18 -0400197 apiCall->setParentFrame(currentFrame);
Zack Rusin1d31b6c2011-04-26 22:30:25 -0400198 currentFrame->addCall(apiCall);
Zack Rusinf6667d12011-03-30 11:03:37 -0400199 if (ApiTrace::isCallAFrameMarker(apiCall,
200 m_frameMarker)) {
201 m_frames.append(currentFrame);
202 currentFrame = 0;
203 }
204 }
205 //last frames won't have markers
206 // it's just a bunch of Delete calls for every object
207 // after the last SwapBuffers
208 if (currentFrame) {
209 m_frames.append(currentFrame);
210 currentFrame = 0;
211 }
Zack Rusinb56e03d2011-04-20 23:58:52 -0400212 emit endAddingFrames();
Zack Rusinf6667d12011-03-30 11:03:37 -0400213}
214
Zack Rusinf04cf8a2011-04-12 23:21:52 -0400215ApiTraceCall * ApiTrace::callWithIndex(int idx) const
216{
217 for (int i = 0; i < m_calls.count(); ++i) {
218 ApiTraceCall *call = m_calls[i];
Zack Rusinead6aad2011-04-15 22:16:18 -0400219 if (call->index() == idx)
Zack Rusinf04cf8a2011-04-12 23:21:52 -0400220 return call;
221 }
222 return NULL;
223}
224
Zack Rusine2dfa2e2011-04-13 01:35:03 -0400225ApiTraceState ApiTrace::defaultState() const
226{
227 ApiTraceFrame *frame = frameAt(0);
Zack Rusined40bc62011-08-28 17:11:02 -0400228 if (!frame || !frame->hasState())
Zack Rusine2dfa2e2011-04-13 01:35:03 -0400229 return ApiTraceState();
230
Zack Rusined40bc62011-08-28 17:11:02 -0400231 return *frame->state();
Zack Rusine2dfa2e2011-04-13 01:35:03 -0400232}
233
Zack Rusin661842d2011-04-17 01:59:16 -0400234void ApiTrace::callEdited(ApiTraceCall *call)
235{
Zack Rusin63efea82011-04-17 17:10:45 -0400236 if (!m_editedCalls.contains(call)) {
237 //lets generate a temp filename
238 QString tempPath = QDir::tempPath();
Zack Rusin63efea82011-04-17 17:10:45 -0400239 m_tempFileName = QString::fromLatin1("%1/%2.edited")
240 .arg(tempPath)
241 .arg(m_fileName);
Zack Rusin63efea82011-04-17 17:10:45 -0400242 }
Zack Rusin661842d2011-04-17 01:59:16 -0400243 m_editedCalls.insert(call);
Zack Rusin9af5bff2011-04-18 01:05:50 -0400244 m_needsSaving = true;
Zack Rusin63efea82011-04-17 17:10:45 -0400245
Zack Rusin661842d2011-04-17 01:59:16 -0400246 emit changed(call);
247}
248
249void ApiTrace::callReverted(ApiTraceCall *call)
250{
251 m_editedCalls.remove(call);
Zack Rusin63efea82011-04-17 17:10:45 -0400252
253 if (m_editedCalls.isEmpty()) {
254 m_needsSaving = false;
255 }
Zack Rusin661842d2011-04-17 01:59:16 -0400256 emit changed(call);
257}
258
Zack Rusin0ddd2502011-04-17 02:34:45 -0400259bool ApiTrace::edited() const
Zack Rusin661842d2011-04-17 01:59:16 -0400260{
261 return !m_editedCalls.isEmpty();
262}
263
Zack Rusin63efea82011-04-17 17:10:45 -0400264bool ApiTrace::needsSaving() const
265{
266 return m_needsSaving;
267}
268
269void ApiTrace::save()
270{
271 QFileInfo fi(m_tempFileName);
272 QDir dir;
Zack Rusin9af5bff2011-04-18 01:05:50 -0400273 emit startedSaving();
Zack Rusin63efea82011-04-17 17:10:45 -0400274 dir.mkpath(fi.absolutePath());
Zack Rusind809a062011-04-17 23:30:58 -0400275 m_saver->saveFile(m_tempFileName, m_calls);
Zack Rusin63efea82011-04-17 17:10:45 -0400276}
277
Zack Rusin9af5bff2011-04-18 01:05:50 -0400278void ApiTrace::slotSaved()
279{
280 m_needsSaving = false;
281}
282
283bool ApiTrace::isSaving() const
284{
285 return m_saver->isRunning();
286}
287
Zack Rusinb53b1612011-04-19 01:33:58 -0400288void ApiTrace::callError(ApiTraceCall *call)
289{
Zack Rusincc0b4912011-04-19 01:59:20 -0400290 Q_ASSERT(call);
291
292 if (call->hasError())
293 m_errors.insert(call);
294 else
295 m_errors.remove(call);
296
Zack Rusinb53b1612011-04-19 01:33:58 -0400297 emit changed(call);
298}
299
Zack Rusincc0b4912011-04-19 01:59:20 -0400300bool ApiTrace::hasErrors() const
301{
302 return !m_errors.isEmpty();
303}
304
Zack Rusinebf971e2011-09-06 17:44:43 -0400305void ApiTrace::fillFrame(int frameIdx, const QVector<ApiTraceCall *> &calls,
306 quint64 binaryDataSize)
Zack Rusinac4dd9a2011-08-28 00:38:13 -0400307{
Zack Rusin35c27932011-08-28 21:16:22 -0400308}
309
Zack Rusinf6667d12011-03-30 11:03:37 -0400310#include "apitrace.moc"