blob: 643876e508d82efcbc18e687dafd8dc505e34b3d [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:
José Fonseca3e9ff852011-06-06 19:37:09 +010043 return call->name().contains(QLatin1String("SwapBuffers")) ||
44 call->name() == QLatin1String("CGLFlushDrawable");
Zack Rusinf6667d12011-03-30 11:03:37 -040045 case FrameMarker_Flush:
Zack Rusinead6aad2011-04-15 22:16:18 -040046 return call->name() == QLatin1String("glFlush");
Zack Rusinf6667d12011-03-30 11:03:37 -040047 case FrameMarker_Finish:
Zack Rusinead6aad2011-04-15 22:16:18 -040048 return call->name() == QLatin1String("glFinish");
Zack Rusinf6667d12011-03-30 11:03:37 -040049 case FrameMarker_Clear:
Zack Rusinead6aad2011-04-15 22:16:18 -040050 return call->name() == QLatin1String("glClear");
Zack Rusinf6667d12011-03-30 11:03:37 -040051 }
52
53 Q_ASSERT(!"unknown frame marker");
54
55 return false;
56}
57
58bool ApiTrace::isEmpty() const
59{
60 return m_calls.isEmpty();
61}
62
63QString ApiTrace::fileName() const
64{
Zack Rusin63efea82011-04-17 17:10:45 -040065 if (edited())
66 return m_tempFileName;
67
Zack Rusinf6667d12011-03-30 11:03:37 -040068 return m_fileName;
69}
70
71ApiTrace::FrameMarker ApiTrace::frameMarker() const
72{
73 return m_frameMarker;
74}
75
76QList<ApiTraceCall*> ApiTrace::calls() const
77{
78 return m_calls;
79}
80
81ApiTraceCall * ApiTrace::callAt(int idx) const
82{
83 return m_calls.value(idx);
84}
85
86int ApiTrace::numCalls() const
87{
88 return m_calls.count();
89}
90
91QList<ApiTraceFrame*> ApiTrace::frames() const
92{
93 return m_frames;
94}
95
96ApiTraceFrame * ApiTrace::frameAt(int idx) const
97{
98 return m_frames.value(idx);
99}
100
101int ApiTrace::numFrames() const
102{
103 return m_frames.count();
104}
105
106int ApiTrace::numCallsInFrame(int idx) const
107{
108 const ApiTraceFrame *frame = frameAt(idx);
109 if (frame)
Zack Rusin1d31b6c2011-04-26 22:30:25 -0400110 return frame->numChildren();
Zack Rusinf6667d12011-03-30 11:03:37 -0400111 else
112 return 0;
113}
114
115void ApiTrace::setFileName(const QString &name)
116{
117 if (m_fileName != name) {
118 m_fileName = name;
119
120 if (m_loader->isRunning()) {
121 m_loader->terminate();
122 m_loader->wait();
123 }
Zack Rusinca164112011-04-11 02:23:09 -0400124 m_frames.clear();
125 m_calls.clear();
Zack Rusin30069572011-04-20 18:21:11 -0400126 m_errors.clear();
127 m_editedCalls.clear();
128 m_needsSaving = false;
Zack Rusinf6667d12011-03-30 11:03:37 -0400129 emit invalidated();
130
131 m_loader->loadFile(m_fileName);
132 }
133}
134
135void ApiTrace::setFrameMarker(FrameMarker marker)
136{
137 if (m_frameMarker != marker) {
138 emit framesInvalidated();
139
140 qDeleteAll(m_frames);
141 m_frames.clear();
142 detectFrames();
143 }
144}
145
146void ApiTrace::addFrames(const QList<ApiTraceFrame*> &frames)
147{
148 int currentFrames = m_frames.count();
149 int numNewFrames = frames.count();
Zack Rusinb56e03d2011-04-20 23:58:52 -0400150
151 emit beginAddingFrames(currentFrames, numNewFrames);
152
Zack Rusinf6667d12011-03-30 11:03:37 -0400153 m_frames += frames;
154
155 int currentCalls = m_calls.count();
156 int numNewCalls = 0;
157 foreach(ApiTraceFrame *frame, frames) {
Zack Rusin7c1793e2011-04-16 23:14:25 -0400158 frame->setParentTrace(this);
Zack Rusin1d31b6c2011-04-26 22:30:25 -0400159 numNewCalls += frame->numChildren();
160 m_calls += frame->calls();
Zack Rusinf6667d12011-03-30 11:03:37 -0400161 }
162
Zack Rusinb56e03d2011-04-20 23:58:52 -0400163 emit endAddingFrames();
Zack Rusinf6667d12011-03-30 11:03:37 -0400164 emit callsAdded(currentCalls, numNewCalls);
165}
166
167void ApiTrace::detectFrames()
168{
169 if (m_calls.isEmpty())
170 return;
171
Zack Rusinb56e03d2011-04-20 23:58:52 -0400172 emit beginAddingFrames(0, m_frames.count());
173
Zack Rusinf6667d12011-03-30 11:03:37 -0400174 ApiTraceFrame *currentFrame = 0;
175 foreach(ApiTraceCall *apiCall, m_calls) {
176 if (!currentFrame) {
177 currentFrame = new ApiTraceFrame();
Zack Rusin7c1793e2011-04-16 23:14:25 -0400178 currentFrame->setParentTrace(this);
Zack Rusinf6667d12011-03-30 11:03:37 -0400179 currentFrame->number = m_frames.count();
180 }
Zack Rusinead6aad2011-04-15 22:16:18 -0400181 apiCall->setParentFrame(currentFrame);
Zack Rusin1d31b6c2011-04-26 22:30:25 -0400182 currentFrame->addCall(apiCall);
Zack Rusinf6667d12011-03-30 11:03:37 -0400183 if (ApiTrace::isCallAFrameMarker(apiCall,
184 m_frameMarker)) {
185 m_frames.append(currentFrame);
186 currentFrame = 0;
187 }
188 }
189 //last frames won't have markers
190 // it's just a bunch of Delete calls for every object
191 // after the last SwapBuffers
192 if (currentFrame) {
193 m_frames.append(currentFrame);
194 currentFrame = 0;
195 }
Zack Rusinb56e03d2011-04-20 23:58:52 -0400196 emit endAddingFrames();
Zack Rusinf6667d12011-03-30 11:03:37 -0400197}
198
Zack Rusinf04cf8a2011-04-12 23:21:52 -0400199ApiTraceCall * ApiTrace::callWithIndex(int idx) const
200{
201 for (int i = 0; i < m_calls.count(); ++i) {
202 ApiTraceCall *call = m_calls[i];
Zack Rusinead6aad2011-04-15 22:16:18 -0400203 if (call->index() == idx)
Zack Rusinf04cf8a2011-04-12 23:21:52 -0400204 return call;
205 }
206 return NULL;
207}
208
Zack Rusine2dfa2e2011-04-13 01:35:03 -0400209ApiTraceState ApiTrace::defaultState() const
210{
211 ApiTraceFrame *frame = frameAt(0);
212 if (!frame)
213 return ApiTraceState();
214
215 return frame->state();
216}
217
Zack Rusin661842d2011-04-17 01:59:16 -0400218void ApiTrace::callEdited(ApiTraceCall *call)
219{
Zack Rusin63efea82011-04-17 17:10:45 -0400220 if (!m_editedCalls.contains(call)) {
221 //lets generate a temp filename
222 QString tempPath = QDir::tempPath();
Zack Rusin63efea82011-04-17 17:10:45 -0400223 m_tempFileName = QString::fromLatin1("%1/%2.edited")
224 .arg(tempPath)
225 .arg(m_fileName);
Zack Rusin63efea82011-04-17 17:10:45 -0400226 }
Zack Rusin661842d2011-04-17 01:59:16 -0400227 m_editedCalls.insert(call);
Zack Rusin9af5bff2011-04-18 01:05:50 -0400228 m_needsSaving = true;
Zack Rusin63efea82011-04-17 17:10:45 -0400229
Zack Rusin661842d2011-04-17 01:59:16 -0400230 emit changed(call);
231}
232
233void ApiTrace::callReverted(ApiTraceCall *call)
234{
235 m_editedCalls.remove(call);
Zack Rusin63efea82011-04-17 17:10:45 -0400236
237 if (m_editedCalls.isEmpty()) {
238 m_needsSaving = false;
239 }
Zack Rusin661842d2011-04-17 01:59:16 -0400240 emit changed(call);
241}
242
Zack Rusin0ddd2502011-04-17 02:34:45 -0400243bool ApiTrace::edited() const
Zack Rusin661842d2011-04-17 01:59:16 -0400244{
245 return !m_editedCalls.isEmpty();
246}
247
Zack Rusin63efea82011-04-17 17:10:45 -0400248bool ApiTrace::needsSaving() const
249{
250 return m_needsSaving;
251}
252
253void ApiTrace::save()
254{
255 QFileInfo fi(m_tempFileName);
256 QDir dir;
Zack Rusin9af5bff2011-04-18 01:05:50 -0400257 emit startedSaving();
Zack Rusin63efea82011-04-17 17:10:45 -0400258 dir.mkpath(fi.absolutePath());
Zack Rusind809a062011-04-17 23:30:58 -0400259 m_saver->saveFile(m_tempFileName, m_calls);
Zack Rusin63efea82011-04-17 17:10:45 -0400260}
261
Zack Rusin9af5bff2011-04-18 01:05:50 -0400262void ApiTrace::slotSaved()
263{
264 m_needsSaving = false;
265}
266
267bool ApiTrace::isSaving() const
268{
269 return m_saver->isRunning();
270}
271
Zack Rusinb53b1612011-04-19 01:33:58 -0400272void ApiTrace::callError(ApiTraceCall *call)
273{
Zack Rusincc0b4912011-04-19 01:59:20 -0400274 Q_ASSERT(call);
275
276 if (call->hasError())
277 m_errors.insert(call);
278 else
279 m_errors.remove(call);
280
Zack Rusinb53b1612011-04-19 01:33:58 -0400281 emit changed(call);
282}
283
Zack Rusincc0b4912011-04-19 01:59:20 -0400284bool ApiTrace::hasErrors() const
285{
286 return !m_errors.isEmpty();
287}
288
Zack Rusinf6667d12011-03-30 11:03:37 -0400289#include "apitrace.moc"