blob: 4c96c717c5643649470d5ff5914ab0090c2533fe [file] [log] [blame]
Zack Rusinf6667d12011-03-30 11:03:37 -04001#include "apitrace.h"
2
3#include "loaderthread.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>
7
Zack Rusinf6667d12011-03-30 11:03:37 -04008ApiTrace::ApiTrace()
Zack Rusin63efea82011-04-17 17:10:45 -04009 : m_frameMarker(ApiTrace::FrameMarker_SwapBuffers),
10 m_needsSaving(false)
Zack Rusinf6667d12011-03-30 11:03:37 -040011{
12 m_loader = new LoaderThread(this);
13 connect(m_loader, SIGNAL(parsedFrames(const QList<ApiTraceFrame*>)),
14 this, SLOT(addFrames(const QList<ApiTraceFrame*>)));
Zack Rusinde4ea412011-03-30 11:30:08 -040015 connect(m_loader, SIGNAL(started()),
16 this, SIGNAL(startedLoadingTrace()));
17 connect(m_loader, SIGNAL(finished()),
18 this, SIGNAL(finishedLoadingTrace()));
Zack Rusind809a062011-04-17 23:30:58 -040019
20 m_saver = new SaverThread(this);
Zack Rusin9af5bff2011-04-18 01:05:50 -040021 connect(m_saver, SIGNAL(traceSaved()),
22 this, SLOT(slotSaved()));
23 connect(m_saver, SIGNAL(traceSaved()),
24 this, SIGNAL(saved()));
Zack Rusinf6667d12011-03-30 11:03:37 -040025}
26
27ApiTrace::~ApiTrace()
28{
29 qDeleteAll(m_calls);
30 qDeleteAll(m_frames);
31 delete m_loader;
Zack Rusind809a062011-04-17 23:30:58 -040032 delete m_saver;
Zack Rusinf6667d12011-03-30 11:03:37 -040033}
34
35bool ApiTrace::isCallAFrameMarker(const ApiTraceCall *call,
36 ApiTrace::FrameMarker marker)
37{
38 if (!call)
39 return false;
40
41 switch (marker) {
42 case FrameMarker_SwapBuffers:
Zack Rusinead6aad2011-04-15 22:16:18 -040043 return call->name().contains(QLatin1String("SwapBuffers"));
Zack Rusinf6667d12011-03-30 11:03:37 -040044 case FrameMarker_Flush:
Zack Rusinead6aad2011-04-15 22:16:18 -040045 return call->name() == QLatin1String("glFlush");
Zack Rusinf6667d12011-03-30 11:03:37 -040046 case FrameMarker_Finish:
Zack Rusinead6aad2011-04-15 22:16:18 -040047 return call->name() == QLatin1String("glFinish");
Zack Rusinf6667d12011-03-30 11:03:37 -040048 case FrameMarker_Clear:
Zack Rusinead6aad2011-04-15 22:16:18 -040049 return call->name() == QLatin1String("glClear");
Zack Rusinf6667d12011-03-30 11:03:37 -040050 }
51
52 Q_ASSERT(!"unknown frame marker");
53
54 return false;
55}
56
57bool ApiTrace::isEmpty() const
58{
59 return m_calls.isEmpty();
60}
61
62QString ApiTrace::fileName() const
63{
Zack Rusin63efea82011-04-17 17:10:45 -040064 if (edited())
65 return m_tempFileName;
66
Zack Rusinf6667d12011-03-30 11:03:37 -040067 return m_fileName;
68}
69
70ApiTrace::FrameMarker ApiTrace::frameMarker() const
71{
72 return m_frameMarker;
73}
74
75QList<ApiTraceCall*> ApiTrace::calls() const
76{
77 return m_calls;
78}
79
80ApiTraceCall * ApiTrace::callAt(int idx) const
81{
82 return m_calls.value(idx);
83}
84
85int ApiTrace::numCalls() const
86{
87 return m_calls.count();
88}
89
90QList<ApiTraceFrame*> ApiTrace::frames() const
91{
92 return m_frames;
93}
94
95ApiTraceFrame * ApiTrace::frameAt(int idx) const
96{
97 return m_frames.value(idx);
98}
99
100int ApiTrace::numFrames() const
101{
102 return m_frames.count();
103}
104
105int ApiTrace::numCallsInFrame(int idx) const
106{
107 const ApiTraceFrame *frame = frameAt(idx);
108 if (frame)
109 return frame->calls.count();
110 else
111 return 0;
112}
113
114void ApiTrace::setFileName(const QString &name)
115{
116 if (m_fileName != name) {
117 m_fileName = name;
118
119 if (m_loader->isRunning()) {
120 m_loader->terminate();
121 m_loader->wait();
122 }
Zack Rusinca164112011-04-11 02:23:09 -0400123 m_frames.clear();
124 m_calls.clear();
Zack Rusin30069572011-04-20 18:21:11 -0400125 m_errors.clear();
126 m_editedCalls.clear();
127 m_needsSaving = false;
Zack Rusinf6667d12011-03-30 11:03:37 -0400128 emit invalidated();
129
130 m_loader->loadFile(m_fileName);
131 }
132}
133
134void ApiTrace::setFrameMarker(FrameMarker marker)
135{
136 if (m_frameMarker != marker) {
137 emit framesInvalidated();
138
139 qDeleteAll(m_frames);
140 m_frames.clear();
141 detectFrames();
142 }
143}
144
145void ApiTrace::addFrames(const QList<ApiTraceFrame*> &frames)
146{
147 int currentFrames = m_frames.count();
148 int numNewFrames = frames.count();
Zack Rusinb56e03d2011-04-20 23:58:52 -0400149
150 emit beginAddingFrames(currentFrames, numNewFrames);
151
Zack Rusinf6667d12011-03-30 11:03:37 -0400152 m_frames += frames;
153
154 int currentCalls = m_calls.count();
155 int numNewCalls = 0;
156 foreach(ApiTraceFrame *frame, frames) {
Zack Rusin7c1793e2011-04-16 23:14:25 -0400157 frame->setParentTrace(this);
Zack Rusinf6667d12011-03-30 11:03:37 -0400158 numNewCalls += frame->calls.count();
159 m_calls += frame->calls;
160 }
161
Zack Rusinb56e03d2011-04-20 23:58:52 -0400162 emit endAddingFrames();
Zack Rusinf6667d12011-03-30 11:03:37 -0400163 emit callsAdded(currentCalls, numNewCalls);
164}
165
166void ApiTrace::detectFrames()
167{
168 if (m_calls.isEmpty())
169 return;
170
Zack Rusinb56e03d2011-04-20 23:58:52 -0400171 emit beginAddingFrames(0, m_frames.count());
172
Zack Rusinf6667d12011-03-30 11:03:37 -0400173 ApiTraceFrame *currentFrame = 0;
174 foreach(ApiTraceCall *apiCall, m_calls) {
175 if (!currentFrame) {
176 currentFrame = new ApiTraceFrame();
Zack Rusin7c1793e2011-04-16 23:14:25 -0400177 currentFrame->setParentTrace(this);
Zack Rusinf6667d12011-03-30 11:03:37 -0400178 currentFrame->number = m_frames.count();
179 }
Zack Rusinead6aad2011-04-15 22:16:18 -0400180 apiCall->setParentFrame(currentFrame);
Zack Rusinf6667d12011-03-30 11:03:37 -0400181 currentFrame->calls.append(apiCall);
182 if (ApiTrace::isCallAFrameMarker(apiCall,
183 m_frameMarker)) {
184 m_frames.append(currentFrame);
185 currentFrame = 0;
186 }
187 }
188 //last frames won't have markers
189 // it's just a bunch of Delete calls for every object
190 // after the last SwapBuffers
191 if (currentFrame) {
192 m_frames.append(currentFrame);
193 currentFrame = 0;
194 }
Zack Rusinb56e03d2011-04-20 23:58:52 -0400195 emit endAddingFrames();
Zack Rusinf6667d12011-03-30 11:03:37 -0400196}
197
Zack Rusinf04cf8a2011-04-12 23:21:52 -0400198ApiTraceCall * ApiTrace::callWithIndex(int idx) const
199{
200 for (int i = 0; i < m_calls.count(); ++i) {
201 ApiTraceCall *call = m_calls[i];
Zack Rusinead6aad2011-04-15 22:16:18 -0400202 if (call->index() == idx)
Zack Rusinf04cf8a2011-04-12 23:21:52 -0400203 return call;
204 }
205 return NULL;
206}
207
Zack Rusine2dfa2e2011-04-13 01:35:03 -0400208ApiTraceState ApiTrace::defaultState() const
209{
210 ApiTraceFrame *frame = frameAt(0);
211 if (!frame)
212 return ApiTraceState();
213
214 return frame->state();
215}
216
Zack Rusin661842d2011-04-17 01:59:16 -0400217void ApiTrace::callEdited(ApiTraceCall *call)
218{
Zack Rusin63efea82011-04-17 17:10:45 -0400219 if (!m_editedCalls.contains(call)) {
220 //lets generate a temp filename
221 QString tempPath = QDir::tempPath();
Zack Rusin63efea82011-04-17 17:10:45 -0400222 m_tempFileName = QString::fromLatin1("%1/%2.edited")
223 .arg(tempPath)
224 .arg(m_fileName);
Zack Rusin63efea82011-04-17 17:10:45 -0400225 }
Zack Rusin661842d2011-04-17 01:59:16 -0400226 m_editedCalls.insert(call);
Zack Rusin9af5bff2011-04-18 01:05:50 -0400227 m_needsSaving = true;
Zack Rusin63efea82011-04-17 17:10:45 -0400228
Zack Rusin661842d2011-04-17 01:59:16 -0400229 emit changed(call);
230}
231
232void ApiTrace::callReverted(ApiTraceCall *call)
233{
234 m_editedCalls.remove(call);
Zack Rusin63efea82011-04-17 17:10:45 -0400235
236 if (m_editedCalls.isEmpty()) {
237 m_needsSaving = false;
238 }
Zack Rusin661842d2011-04-17 01:59:16 -0400239 emit changed(call);
240}
241
Zack Rusin0ddd2502011-04-17 02:34:45 -0400242bool ApiTrace::edited() const
Zack Rusin661842d2011-04-17 01:59:16 -0400243{
244 return !m_editedCalls.isEmpty();
245}
246
Zack Rusin63efea82011-04-17 17:10:45 -0400247bool ApiTrace::needsSaving() const
248{
249 return m_needsSaving;
250}
251
252void ApiTrace::save()
253{
254 QFileInfo fi(m_tempFileName);
255 QDir dir;
Zack Rusin9af5bff2011-04-18 01:05:50 -0400256 emit startedSaving();
Zack Rusin63efea82011-04-17 17:10:45 -0400257 dir.mkpath(fi.absolutePath());
Zack Rusind809a062011-04-17 23:30:58 -0400258 m_saver->saveFile(m_tempFileName, m_calls);
Zack Rusin63efea82011-04-17 17:10:45 -0400259}
260
Zack Rusin9af5bff2011-04-18 01:05:50 -0400261void ApiTrace::slotSaved()
262{
263 m_needsSaving = false;
264}
265
266bool ApiTrace::isSaving() const
267{
268 return m_saver->isRunning();
269}
270
Zack Rusinb53b1612011-04-19 01:33:58 -0400271void ApiTrace::callError(ApiTraceCall *call)
272{
Zack Rusincc0b4912011-04-19 01:59:20 -0400273 Q_ASSERT(call);
274
275 if (call->hasError())
276 m_errors.insert(call);
277 else
278 m_errors.remove(call);
279
Zack Rusinb53b1612011-04-19 01:33:58 -0400280 emit changed(call);
281}
282
Zack Rusincc0b4912011-04-19 01:59:20 -0400283bool ApiTrace::hasErrors() const
284{
285 return !m_errors.isEmpty();
286}
287
Zack Rusinf6667d12011-03-30 11:03:37 -0400288#include "apitrace.moc"