blob: 958009b7e383ff6a8b3ccd0984586c4174d52ee2 [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 Rusin3176ebe2011-09-06 21:11:36 -04006#include <QDebug>
Zack Rusin63efea82011-04-17 17:10:45 -04007#include <QDir>
Zack Rusinebf971e2011-09-06 17:44:43 -04008#include <QThread>
Zack Rusin63efea82011-04-17 17:10:45 -04009
Zack Rusinf6667d12011-03-30 11:03:37 -040010ApiTrace::ApiTrace()
Zack Rusin63efea82011-04-17 17:10:45 -040011 : m_frameMarker(ApiTrace::FrameMarker_SwapBuffers),
12 m_needsSaving(false)
Zack Rusinf6667d12011-03-30 11:03:37 -040013{
Zack Rusinebf971e2011-09-06 17:44:43 -040014 m_loader = new TraceLoader();
Zack Rusinf682e192011-09-07 01:36:41 -040015
Zack Rusinebf971e2011-09-06 17:44:43 -040016 connect(this, SIGNAL(loadTrace(QString)),
17 m_loader, SLOT(loadTrace(QString)));
Zack Rusin3176ebe2011-09-06 21:11:36 -040018 connect(this, SIGNAL(requestFrame(ApiTraceFrame*)),
19 m_loader, SLOT(loadFrame(ApiTraceFrame*)));
Zack Rusinebf971e2011-09-06 17:44:43 -040020 connect(m_loader, SIGNAL(framesLoaded(const QList<ApiTraceFrame*>)),
Zack Rusinf6667d12011-03-30 11:03:37 -040021 this, SLOT(addFrames(const QList<ApiTraceFrame*>)));
Zack Rusin3176ebe2011-09-06 21:11:36 -040022 connect(m_loader, SIGNAL(frameLoaded(ApiTraceFrame*)),
Zack Rusinf682e192011-09-07 01:36:41 -040023 this, SLOT(frameLoadFinished(ApiTraceFrame*)));
24 connect(m_loader, SIGNAL(finishedParsing()),
25 this, SLOT(finishedParsing()));
Zack Rusinebf971e2011-09-06 17:44:43 -040026
27 connect(m_loader, SIGNAL(startedParsing()),
Zack Rusinde4ea412011-03-30 11:30:08 -040028 this, SIGNAL(startedLoadingTrace()));
Zack Rusinebf971e2011-09-06 17:44:43 -040029 connect(m_loader, SIGNAL(parsed(int)),
30 this, SIGNAL(loaded(int)));
31 connect(m_loader, SIGNAL(finishedParsing()),
Zack Rusinde4ea412011-03-30 11:30:08 -040032 this, SIGNAL(finishedLoadingTrace()));
Zack Rusind809a062011-04-17 23:30:58 -040033
Zack Rusinebf971e2011-09-06 17:44:43 -040034
Zack Rusind809a062011-04-17 23:30:58 -040035 m_saver = new SaverThread(this);
Zack Rusin9af5bff2011-04-18 01:05:50 -040036 connect(m_saver, SIGNAL(traceSaved()),
37 this, SLOT(slotSaved()));
38 connect(m_saver, SIGNAL(traceSaved()),
39 this, SIGNAL(saved()));
Zack Rusinebf971e2011-09-06 17:44:43 -040040
41 m_loaderThread = new QThread();
42 m_loader->moveToThread(m_loaderThread);
43 m_loaderThread->start();
Zack Rusinf6667d12011-03-30 11:03:37 -040044}
45
46ApiTrace::~ApiTrace()
47{
Zack Rusinebf971e2011-09-06 17:44:43 -040048 m_loaderThread->quit();
49 m_loaderThread->deleteLater();
Zack Rusinf6667d12011-03-30 11:03:37 -040050 qDeleteAll(m_calls);
51 qDeleteAll(m_frames);
52 delete m_loader;
Zack Rusind809a062011-04-17 23:30:58 -040053 delete m_saver;
Zack Rusinf6667d12011-03-30 11:03:37 -040054}
55
56bool ApiTrace::isCallAFrameMarker(const ApiTraceCall *call,
57 ApiTrace::FrameMarker marker)
58{
59 if (!call)
60 return false;
61
62 switch (marker) {
63 case FrameMarker_SwapBuffers:
José Fonseca3e9ff852011-06-06 19:37:09 +010064 return call->name().contains(QLatin1String("SwapBuffers")) ||
José Fonsecadb678122011-07-29 17:20:05 +010065 call->name() == QLatin1String("CGLFlushDrawable") ||
66 call->name() == QLatin1String("glFrameTerminatorGREMEDY");
Zack Rusinf6667d12011-03-30 11:03:37 -040067 case FrameMarker_Flush:
Zack Rusinead6aad2011-04-15 22:16:18 -040068 return call->name() == QLatin1String("glFlush");
Zack Rusinf6667d12011-03-30 11:03:37 -040069 case FrameMarker_Finish:
Zack Rusinead6aad2011-04-15 22:16:18 -040070 return call->name() == QLatin1String("glFinish");
Zack Rusinf6667d12011-03-30 11:03:37 -040071 case FrameMarker_Clear:
Zack Rusinead6aad2011-04-15 22:16:18 -040072 return call->name() == QLatin1String("glClear");
Zack Rusinf6667d12011-03-30 11:03:37 -040073 }
74
75 Q_ASSERT(!"unknown frame marker");
76
77 return false;
78}
79
80bool ApiTrace::isEmpty() const
81{
82 return m_calls.isEmpty();
83}
84
85QString ApiTrace::fileName() const
86{
Zack Rusin63efea82011-04-17 17:10:45 -040087 if (edited())
88 return m_tempFileName;
89
Zack Rusinf6667d12011-03-30 11:03:37 -040090 return m_fileName;
91}
92
93ApiTrace::FrameMarker ApiTrace::frameMarker() const
94{
95 return m_frameMarker;
96}
97
Zack Rusin4d0ef5d2011-08-28 22:05:31 -040098QVector<ApiTraceCall*> ApiTrace::calls() const
Zack Rusinf6667d12011-03-30 11:03:37 -040099{
100 return m_calls;
101}
102
Zack Rusinf6667d12011-03-30 11:03:37 -0400103int ApiTrace::numCalls() const
104{
105 return m_calls.count();
106}
107
108QList<ApiTraceFrame*> ApiTrace::frames() const
109{
110 return m_frames;
111}
112
113ApiTraceFrame * ApiTrace::frameAt(int idx) const
114{
115 return m_frames.value(idx);
116}
117
118int ApiTrace::numFrames() const
119{
120 return m_frames.count();
121}
122
123int ApiTrace::numCallsInFrame(int idx) const
124{
125 const ApiTraceFrame *frame = frameAt(idx);
126 if (frame)
Zack Rusin1d31b6c2011-04-26 22:30:25 -0400127 return frame->numChildren();
Zack Rusinf6667d12011-03-30 11:03:37 -0400128 else
129 return 0;
130}
131
132void ApiTrace::setFileName(const QString &name)
133{
134 if (m_fileName != name) {
135 m_fileName = name;
136
Zack Rusinca164112011-04-11 02:23:09 -0400137 m_frames.clear();
138 m_calls.clear();
Zack Rusin30069572011-04-20 18:21:11 -0400139 m_errors.clear();
140 m_editedCalls.clear();
141 m_needsSaving = false;
Zack Rusinf6667d12011-03-30 11:03:37 -0400142 emit invalidated();
143
Zack Rusinebf971e2011-09-06 17:44:43 -0400144// m_loader->loadTrace(m_fileName);
145 emit loadTrace(m_fileName);
Zack Rusinf6667d12011-03-30 11:03:37 -0400146 }
147}
148
149void ApiTrace::setFrameMarker(FrameMarker marker)
150{
151 if (m_frameMarker != marker) {
152 emit framesInvalidated();
153
154 qDeleteAll(m_frames);
155 m_frames.clear();
156 detectFrames();
157 }
158}
159
160void ApiTrace::addFrames(const QList<ApiTraceFrame*> &frames)
161{
Zack Rusin4d0ef5d2011-08-28 22:05:31 -0400162 QVector<ApiTraceCall*> calls;
Zack Rusinf6667d12011-03-30 11:03:37 -0400163 int currentFrames = m_frames.count();
164 int numNewFrames = frames.count();
Zack Rusinb56e03d2011-04-20 23:58:52 -0400165
166 emit beginAddingFrames(currentFrames, numNewFrames);
167
Zack Rusinf6667d12011-03-30 11:03:37 -0400168 m_frames += frames;
169
170 int currentCalls = m_calls.count();
171 int numNewCalls = 0;
172 foreach(ApiTraceFrame *frame, frames) {
Zack Rusinebf971e2011-09-06 17:44:43 -0400173 frame->setParentTrace(this);
Zack Rusin1d31b6c2011-04-26 22:30:25 -0400174 numNewCalls += frame->numChildren();
Zack Rusin410a8f32011-08-28 02:38:34 -0400175 calls += frame->calls();
Zack Rusinf6667d12011-03-30 11:03:37 -0400176 }
Zack Rusin4d0ef5d2011-08-28 22:05:31 -0400177 m_calls.reserve(m_calls.count() + calls.count() + 1);
Zack Rusin410a8f32011-08-28 02:38:34 -0400178 m_calls += calls;
Zack Rusinf6667d12011-03-30 11:03:37 -0400179
Zack Rusinb56e03d2011-04-20 23:58:52 -0400180 emit endAddingFrames();
Zack Rusinf6667d12011-03-30 11:03:37 -0400181 emit callsAdded(currentCalls, numNewCalls);
182}
183
184void ApiTrace::detectFrames()
185{
186 if (m_calls.isEmpty())
187 return;
188
Zack Rusinb56e03d2011-04-20 23:58:52 -0400189 emit beginAddingFrames(0, m_frames.count());
190
Zack Rusinf6667d12011-03-30 11:03:37 -0400191 ApiTraceFrame *currentFrame = 0;
192 foreach(ApiTraceCall *apiCall, m_calls) {
193 if (!currentFrame) {
Zack Rusinac4dd9a2011-08-28 00:38:13 -0400194 currentFrame = new ApiTraceFrame(this);
Zack Rusinf6667d12011-03-30 11:03:37 -0400195 currentFrame->number = m_frames.count();
Zack Rusin20b1f6d2011-09-06 11:50:07 -0400196 currentFrame->setLoaded(true);
Zack Rusinf6667d12011-03-30 11:03:37 -0400197 }
Zack Rusinead6aad2011-04-15 22:16:18 -0400198 apiCall->setParentFrame(currentFrame);
Zack Rusin1d31b6c2011-04-26 22:30:25 -0400199 currentFrame->addCall(apiCall);
Zack Rusinf6667d12011-03-30 11:03:37 -0400200 if (ApiTrace::isCallAFrameMarker(apiCall,
201 m_frameMarker)) {
202 m_frames.append(currentFrame);
203 currentFrame = 0;
204 }
205 }
206 //last frames won't have markers
207 // it's just a bunch of Delete calls for every object
208 // after the last SwapBuffers
209 if (currentFrame) {
210 m_frames.append(currentFrame);
211 currentFrame = 0;
212 }
Zack Rusinb56e03d2011-04-20 23:58:52 -0400213 emit endAddingFrames();
Zack Rusinf6667d12011-03-30 11:03:37 -0400214}
215
Zack Rusinf04cf8a2011-04-12 23:21:52 -0400216ApiTraceCall * ApiTrace::callWithIndex(int idx) const
217{
218 for (int i = 0; i < m_calls.count(); ++i) {
219 ApiTraceCall *call = m_calls[i];
Zack Rusinead6aad2011-04-15 22:16:18 -0400220 if (call->index() == idx)
Zack Rusinf04cf8a2011-04-12 23:21:52 -0400221 return call;
222 }
223 return NULL;
224}
225
Zack Rusine2dfa2e2011-04-13 01:35:03 -0400226ApiTraceState ApiTrace::defaultState() const
227{
228 ApiTraceFrame *frame = frameAt(0);
Zack Rusined40bc62011-08-28 17:11:02 -0400229 if (!frame || !frame->hasState())
Zack Rusine2dfa2e2011-04-13 01:35:03 -0400230 return ApiTraceState();
231
Zack Rusined40bc62011-08-28 17:11:02 -0400232 return *frame->state();
Zack Rusine2dfa2e2011-04-13 01:35:03 -0400233}
234
Zack Rusin661842d2011-04-17 01:59:16 -0400235void ApiTrace::callEdited(ApiTraceCall *call)
236{
Zack Rusin63efea82011-04-17 17:10:45 -0400237 if (!m_editedCalls.contains(call)) {
238 //lets generate a temp filename
239 QString tempPath = QDir::tempPath();
Zack Rusin63efea82011-04-17 17:10:45 -0400240 m_tempFileName = QString::fromLatin1("%1/%2.edited")
241 .arg(tempPath)
242 .arg(m_fileName);
Zack Rusin63efea82011-04-17 17:10:45 -0400243 }
Zack Rusin661842d2011-04-17 01:59:16 -0400244 m_editedCalls.insert(call);
Zack Rusin9af5bff2011-04-18 01:05:50 -0400245 m_needsSaving = true;
Zack Rusin63efea82011-04-17 17:10:45 -0400246
Zack Rusin661842d2011-04-17 01:59:16 -0400247 emit changed(call);
248}
249
250void ApiTrace::callReverted(ApiTraceCall *call)
251{
252 m_editedCalls.remove(call);
Zack Rusin63efea82011-04-17 17:10:45 -0400253
254 if (m_editedCalls.isEmpty()) {
255 m_needsSaving = false;
256 }
Zack Rusin661842d2011-04-17 01:59:16 -0400257 emit changed(call);
258}
259
Zack Rusin0ddd2502011-04-17 02:34:45 -0400260bool ApiTrace::edited() const
Zack Rusin661842d2011-04-17 01:59:16 -0400261{
262 return !m_editedCalls.isEmpty();
263}
264
Zack Rusin63efea82011-04-17 17:10:45 -0400265bool ApiTrace::needsSaving() const
266{
267 return m_needsSaving;
268}
269
270void ApiTrace::save()
271{
272 QFileInfo fi(m_tempFileName);
273 QDir dir;
Zack Rusin9af5bff2011-04-18 01:05:50 -0400274 emit startedSaving();
Zack Rusin63efea82011-04-17 17:10:45 -0400275 dir.mkpath(fi.absolutePath());
Zack Rusind809a062011-04-17 23:30:58 -0400276 m_saver->saveFile(m_tempFileName, m_calls);
Zack Rusin63efea82011-04-17 17:10:45 -0400277}
278
Zack Rusin9af5bff2011-04-18 01:05:50 -0400279void ApiTrace::slotSaved()
280{
281 m_needsSaving = false;
282}
283
284bool ApiTrace::isSaving() const
285{
286 return m_saver->isRunning();
287}
288
Zack Rusinb53b1612011-04-19 01:33:58 -0400289void ApiTrace::callError(ApiTraceCall *call)
290{
Zack Rusincc0b4912011-04-19 01:59:20 -0400291 Q_ASSERT(call);
292
293 if (call->hasError())
294 m_errors.insert(call);
295 else
296 m_errors.remove(call);
297
Zack Rusinb53b1612011-04-19 01:33:58 -0400298 emit changed(call);
299}
300
Zack Rusincc0b4912011-04-19 01:59:20 -0400301bool ApiTrace::hasErrors() const
302{
303 return !m_errors.isEmpty();
304}
305
Zack Rusin3176ebe2011-09-06 21:11:36 -0400306void ApiTrace::loadFrame(ApiTraceFrame *frame)
Zack Rusinac4dd9a2011-08-28 00:38:13 -0400307{
Zack Rusin3176ebe2011-09-06 21:11:36 -0400308 Q_ASSERT(!frame->loaded());
Zack Rusinf682e192011-09-07 01:36:41 -0400309 emit beginLoadingFrame(frame, frame->numChildrenToLoad());
Zack Rusin3176ebe2011-09-06 21:11:36 -0400310 emit requestFrame(frame);
Zack Rusin35c27932011-08-28 21:16:22 -0400311}
312
Zack Rusinf682e192011-09-07 01:36:41 -0400313void ApiTrace::finishedParsing()
314{
315 ApiTraceFrame *firstFrame = m_frames[0];
316 if (firstFrame && !firstFrame->loaded()) {
317 loadFrame(firstFrame);
318 }
319}
320
321void ApiTrace::frameLoadFinished(ApiTraceFrame *frame)
322{
323 emit endLoadingFrame(frame);
324}
325
Zack Rusinf6667d12011-03-30 11:03:37 -0400326#include "apitrace.moc"