blob: 2eb6ab52a665075752011cb6678c8c0189304c4e [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();
15 connect(this, SIGNAL(loadTrace(QString)),
16 m_loader, SLOT(loadTrace(QString)));
Zack Rusin3176ebe2011-09-06 21:11:36 -040017 connect(this, SIGNAL(requestFrame(ApiTraceFrame*)),
18 m_loader, SLOT(loadFrame(ApiTraceFrame*)));
Zack Rusinebf971e2011-09-06 17:44:43 -040019 connect(m_loader, SIGNAL(framesLoaded(const QList<ApiTraceFrame*>)),
Zack Rusinf6667d12011-03-30 11:03:37 -040020 this, SLOT(addFrames(const QList<ApiTraceFrame*>)));
Zack Rusin3176ebe2011-09-06 21:11:36 -040021 connect(m_loader, SIGNAL(frameLoaded(ApiTraceFrame*)),
22 this, SIGNAL(frameLoaded(ApiTraceFrame*)));
Zack Rusinebf971e2011-09-06 17:44:43 -040023
24 connect(m_loader, SIGNAL(startedParsing()),
Zack Rusinde4ea412011-03-30 11:30:08 -040025 this, SIGNAL(startedLoadingTrace()));
Zack Rusinebf971e2011-09-06 17:44:43 -040026 connect(m_loader, SIGNAL(parsed(int)),
27 this, SIGNAL(loaded(int)));
28 connect(m_loader, SIGNAL(finishedParsing()),
Zack Rusinde4ea412011-03-30 11:30:08 -040029 this, SIGNAL(finishedLoadingTrace()));
Zack Rusind809a062011-04-17 23:30:58 -040030
Zack Rusinebf971e2011-09-06 17:44:43 -040031
Zack Rusind809a062011-04-17 23:30:58 -040032 m_saver = new SaverThread(this);
Zack Rusin9af5bff2011-04-18 01:05:50 -040033 connect(m_saver, SIGNAL(traceSaved()),
34 this, SLOT(slotSaved()));
35 connect(m_saver, SIGNAL(traceSaved()),
36 this, SIGNAL(saved()));
Zack Rusinebf971e2011-09-06 17:44:43 -040037
38 m_loaderThread = new QThread();
39 m_loader->moveToThread(m_loaderThread);
40 m_loaderThread->start();
Zack Rusinf6667d12011-03-30 11:03:37 -040041}
42
43ApiTrace::~ApiTrace()
44{
Zack Rusinebf971e2011-09-06 17:44:43 -040045 m_loaderThread->quit();
46 m_loaderThread->deleteLater();
Zack Rusinf6667d12011-03-30 11:03:37 -040047 qDeleteAll(m_calls);
48 qDeleteAll(m_frames);
49 delete m_loader;
Zack Rusind809a062011-04-17 23:30:58 -040050 delete m_saver;
Zack Rusinf6667d12011-03-30 11:03:37 -040051}
52
53bool ApiTrace::isCallAFrameMarker(const ApiTraceCall *call,
54 ApiTrace::FrameMarker marker)
55{
56 if (!call)
57 return false;
58
59 switch (marker) {
60 case FrameMarker_SwapBuffers:
José Fonseca3e9ff852011-06-06 19:37:09 +010061 return call->name().contains(QLatin1String("SwapBuffers")) ||
José Fonsecadb678122011-07-29 17:20:05 +010062 call->name() == QLatin1String("CGLFlushDrawable") ||
63 call->name() == QLatin1String("glFrameTerminatorGREMEDY");
Zack Rusinf6667d12011-03-30 11:03:37 -040064 case FrameMarker_Flush:
Zack Rusinead6aad2011-04-15 22:16:18 -040065 return call->name() == QLatin1String("glFlush");
Zack Rusinf6667d12011-03-30 11:03:37 -040066 case FrameMarker_Finish:
Zack Rusinead6aad2011-04-15 22:16:18 -040067 return call->name() == QLatin1String("glFinish");
Zack Rusinf6667d12011-03-30 11:03:37 -040068 case FrameMarker_Clear:
Zack Rusinead6aad2011-04-15 22:16:18 -040069 return call->name() == QLatin1String("glClear");
Zack Rusinf6667d12011-03-30 11:03:37 -040070 }
71
72 Q_ASSERT(!"unknown frame marker");
73
74 return false;
75}
76
77bool ApiTrace::isEmpty() const
78{
79 return m_calls.isEmpty();
80}
81
82QString ApiTrace::fileName() const
83{
Zack Rusin63efea82011-04-17 17:10:45 -040084 if (edited())
85 return m_tempFileName;
86
Zack Rusinf6667d12011-03-30 11:03:37 -040087 return m_fileName;
88}
89
90ApiTrace::FrameMarker ApiTrace::frameMarker() const
91{
92 return m_frameMarker;
93}
94
Zack Rusin4d0ef5d2011-08-28 22:05:31 -040095QVector<ApiTraceCall*> ApiTrace::calls() const
Zack Rusinf6667d12011-03-30 11:03:37 -040096{
97 return m_calls;
98}
99
Zack Rusinf6667d12011-03-30 11:03:37 -0400100int ApiTrace::numCalls() const
101{
102 return m_calls.count();
103}
104
105QList<ApiTraceFrame*> ApiTrace::frames() const
106{
107 return m_frames;
108}
109
110ApiTraceFrame * ApiTrace::frameAt(int idx) const
111{
112 return m_frames.value(idx);
113}
114
115int ApiTrace::numFrames() const
116{
117 return m_frames.count();
118}
119
120int ApiTrace::numCallsInFrame(int idx) const
121{
122 const ApiTraceFrame *frame = frameAt(idx);
123 if (frame)
Zack Rusin1d31b6c2011-04-26 22:30:25 -0400124 return frame->numChildren();
Zack Rusinf6667d12011-03-30 11:03:37 -0400125 else
126 return 0;
127}
128
129void ApiTrace::setFileName(const QString &name)
130{
131 if (m_fileName != name) {
132 m_fileName = name;
133
Zack Rusinca164112011-04-11 02:23:09 -0400134 m_frames.clear();
135 m_calls.clear();
Zack Rusin30069572011-04-20 18:21:11 -0400136 m_errors.clear();
137 m_editedCalls.clear();
138 m_needsSaving = false;
Zack Rusinf6667d12011-03-30 11:03:37 -0400139 emit invalidated();
140
Zack Rusinebf971e2011-09-06 17:44:43 -0400141// m_loader->loadTrace(m_fileName);
142 emit loadTrace(m_fileName);
Zack Rusinf6667d12011-03-30 11:03:37 -0400143 }
144}
145
146void ApiTrace::setFrameMarker(FrameMarker marker)
147{
148 if (m_frameMarker != marker) {
149 emit framesInvalidated();
150
151 qDeleteAll(m_frames);
152 m_frames.clear();
153 detectFrames();
154 }
155}
156
157void ApiTrace::addFrames(const QList<ApiTraceFrame*> &frames)
158{
Zack Rusin4d0ef5d2011-08-28 22:05:31 -0400159 QVector<ApiTraceCall*> calls;
Zack Rusinf6667d12011-03-30 11:03:37 -0400160 int currentFrames = m_frames.count();
161 int numNewFrames = frames.count();
Zack Rusinb56e03d2011-04-20 23:58:52 -0400162
163 emit beginAddingFrames(currentFrames, numNewFrames);
164
Zack Rusinf6667d12011-03-30 11:03:37 -0400165 m_frames += frames;
166
167 int currentCalls = m_calls.count();
168 int numNewCalls = 0;
169 foreach(ApiTraceFrame *frame, frames) {
Zack Rusinebf971e2011-09-06 17:44:43 -0400170 frame->setParentTrace(this);
Zack Rusin1d31b6c2011-04-26 22:30:25 -0400171 numNewCalls += frame->numChildren();
Zack Rusin410a8f32011-08-28 02:38:34 -0400172 calls += frame->calls();
Zack Rusinf6667d12011-03-30 11:03:37 -0400173 }
Zack Rusin4d0ef5d2011-08-28 22:05:31 -0400174 m_calls.reserve(m_calls.count() + calls.count() + 1);
Zack Rusin410a8f32011-08-28 02:38:34 -0400175 m_calls += calls;
Zack Rusinf6667d12011-03-30 11:03:37 -0400176
Zack Rusinb56e03d2011-04-20 23:58:52 -0400177 emit endAddingFrames();
Zack Rusinf6667d12011-03-30 11:03:37 -0400178 emit callsAdded(currentCalls, numNewCalls);
179}
180
181void ApiTrace::detectFrames()
182{
183 if (m_calls.isEmpty())
184 return;
185
Zack Rusinb56e03d2011-04-20 23:58:52 -0400186 emit beginAddingFrames(0, m_frames.count());
187
Zack Rusinf6667d12011-03-30 11:03:37 -0400188 ApiTraceFrame *currentFrame = 0;
189 foreach(ApiTraceCall *apiCall, m_calls) {
190 if (!currentFrame) {
Zack Rusinac4dd9a2011-08-28 00:38:13 -0400191 currentFrame = new ApiTraceFrame(this);
Zack Rusinf6667d12011-03-30 11:03:37 -0400192 currentFrame->number = m_frames.count();
Zack Rusin20b1f6d2011-09-06 11:50:07 -0400193 currentFrame->setLoaded(true);
Zack Rusinf6667d12011-03-30 11:03:37 -0400194 }
Zack Rusinead6aad2011-04-15 22:16:18 -0400195 apiCall->setParentFrame(currentFrame);
Zack Rusin1d31b6c2011-04-26 22:30:25 -0400196 currentFrame->addCall(apiCall);
Zack Rusinf6667d12011-03-30 11:03:37 -0400197 if (ApiTrace::isCallAFrameMarker(apiCall,
198 m_frameMarker)) {
199 m_frames.append(currentFrame);
200 currentFrame = 0;
201 }
202 }
203 //last frames won't have markers
204 // it's just a bunch of Delete calls for every object
205 // after the last SwapBuffers
206 if (currentFrame) {
207 m_frames.append(currentFrame);
208 currentFrame = 0;
209 }
Zack Rusinb56e03d2011-04-20 23:58:52 -0400210 emit endAddingFrames();
Zack Rusinf6667d12011-03-30 11:03:37 -0400211}
212
Zack Rusinf04cf8a2011-04-12 23:21:52 -0400213ApiTraceCall * ApiTrace::callWithIndex(int idx) const
214{
215 for (int i = 0; i < m_calls.count(); ++i) {
216 ApiTraceCall *call = m_calls[i];
Zack Rusinead6aad2011-04-15 22:16:18 -0400217 if (call->index() == idx)
Zack Rusinf04cf8a2011-04-12 23:21:52 -0400218 return call;
219 }
220 return NULL;
221}
222
Zack Rusine2dfa2e2011-04-13 01:35:03 -0400223ApiTraceState ApiTrace::defaultState() const
224{
225 ApiTraceFrame *frame = frameAt(0);
Zack Rusined40bc62011-08-28 17:11:02 -0400226 if (!frame || !frame->hasState())
Zack Rusine2dfa2e2011-04-13 01:35:03 -0400227 return ApiTraceState();
228
Zack Rusined40bc62011-08-28 17:11:02 -0400229 return *frame->state();
Zack Rusine2dfa2e2011-04-13 01:35:03 -0400230}
231
Zack Rusin661842d2011-04-17 01:59:16 -0400232void ApiTrace::callEdited(ApiTraceCall *call)
233{
Zack Rusin63efea82011-04-17 17:10:45 -0400234 if (!m_editedCalls.contains(call)) {
235 //lets generate a temp filename
236 QString tempPath = QDir::tempPath();
Zack Rusin63efea82011-04-17 17:10:45 -0400237 m_tempFileName = QString::fromLatin1("%1/%2.edited")
238 .arg(tempPath)
239 .arg(m_fileName);
Zack Rusin63efea82011-04-17 17:10:45 -0400240 }
Zack Rusin661842d2011-04-17 01:59:16 -0400241 m_editedCalls.insert(call);
Zack Rusin9af5bff2011-04-18 01:05:50 -0400242 m_needsSaving = true;
Zack Rusin63efea82011-04-17 17:10:45 -0400243
Zack Rusin661842d2011-04-17 01:59:16 -0400244 emit changed(call);
245}
246
247void ApiTrace::callReverted(ApiTraceCall *call)
248{
249 m_editedCalls.remove(call);
Zack Rusin63efea82011-04-17 17:10:45 -0400250
251 if (m_editedCalls.isEmpty()) {
252 m_needsSaving = false;
253 }
Zack Rusin661842d2011-04-17 01:59:16 -0400254 emit changed(call);
255}
256
Zack Rusin0ddd2502011-04-17 02:34:45 -0400257bool ApiTrace::edited() const
Zack Rusin661842d2011-04-17 01:59:16 -0400258{
259 return !m_editedCalls.isEmpty();
260}
261
Zack Rusin63efea82011-04-17 17:10:45 -0400262bool ApiTrace::needsSaving() const
263{
264 return m_needsSaving;
265}
266
267void ApiTrace::save()
268{
269 QFileInfo fi(m_tempFileName);
270 QDir dir;
Zack Rusin9af5bff2011-04-18 01:05:50 -0400271 emit startedSaving();
Zack Rusin63efea82011-04-17 17:10:45 -0400272 dir.mkpath(fi.absolutePath());
Zack Rusind809a062011-04-17 23:30:58 -0400273 m_saver->saveFile(m_tempFileName, m_calls);
Zack Rusin63efea82011-04-17 17:10:45 -0400274}
275
Zack Rusin9af5bff2011-04-18 01:05:50 -0400276void ApiTrace::slotSaved()
277{
278 m_needsSaving = false;
279}
280
281bool ApiTrace::isSaving() const
282{
283 return m_saver->isRunning();
284}
285
Zack Rusinb53b1612011-04-19 01:33:58 -0400286void ApiTrace::callError(ApiTraceCall *call)
287{
Zack Rusincc0b4912011-04-19 01:59:20 -0400288 Q_ASSERT(call);
289
290 if (call->hasError())
291 m_errors.insert(call);
292 else
293 m_errors.remove(call);
294
Zack Rusinb53b1612011-04-19 01:33:58 -0400295 emit changed(call);
296}
297
Zack Rusincc0b4912011-04-19 01:59:20 -0400298bool ApiTrace::hasErrors() const
299{
300 return !m_errors.isEmpty();
301}
302
Zack Rusin3176ebe2011-09-06 21:11:36 -0400303void ApiTrace::loadFrame(ApiTraceFrame *frame)
Zack Rusinac4dd9a2011-08-28 00:38:13 -0400304{
Zack Rusin3176ebe2011-09-06 21:11:36 -0400305 Q_ASSERT(!frame->loaded());
306 emit requestFrame(frame);
Zack Rusin35c27932011-08-28 21:16:22 -0400307}
308
Zack Rusinf6667d12011-03-30 11:03:37 -0400309#include "apitrace.moc"