blob: 7d02b5dcdd97813af5e29179bcde4fd46bbf8aaf [file] [log] [blame]
Zack Rusinf6667d12011-03-30 11:03:37 -04001#include "apitrace.h"
2
3#include "loaderthread.h"
4
Zack Rusin63efea82011-04-17 17:10:45 -04005#include <QDir>
6
Zack Rusinf6667d12011-03-30 11:03:37 -04007ApiTrace::ApiTrace()
Zack Rusin63efea82011-04-17 17:10:45 -04008 : m_frameMarker(ApiTrace::FrameMarker_SwapBuffers),
9 m_needsSaving(false)
Zack Rusinf6667d12011-03-30 11:03:37 -040010{
11 m_loader = new LoaderThread(this);
12 connect(m_loader, SIGNAL(parsedFrames(const QList<ApiTraceFrame*>)),
13 this, SLOT(addFrames(const QList<ApiTraceFrame*>)));
Zack Rusinde4ea412011-03-30 11:30:08 -040014 connect(m_loader, SIGNAL(started()),
15 this, SIGNAL(startedLoadingTrace()));
16 connect(m_loader, SIGNAL(finished()),
17 this, SIGNAL(finishedLoadingTrace()));
Zack Rusinf6667d12011-03-30 11:03:37 -040018}
19
20ApiTrace::~ApiTrace()
21{
22 qDeleteAll(m_calls);
23 qDeleteAll(m_frames);
24 delete m_loader;
25}
26
27bool ApiTrace::isCallAFrameMarker(const ApiTraceCall *call,
28 ApiTrace::FrameMarker marker)
29{
30 if (!call)
31 return false;
32
33 switch (marker) {
34 case FrameMarker_SwapBuffers:
Zack Rusinead6aad2011-04-15 22:16:18 -040035 return call->name().contains(QLatin1String("SwapBuffers"));
Zack Rusinf6667d12011-03-30 11:03:37 -040036 case FrameMarker_Flush:
Zack Rusinead6aad2011-04-15 22:16:18 -040037 return call->name() == QLatin1String("glFlush");
Zack Rusinf6667d12011-03-30 11:03:37 -040038 case FrameMarker_Finish:
Zack Rusinead6aad2011-04-15 22:16:18 -040039 return call->name() == QLatin1String("glFinish");
Zack Rusinf6667d12011-03-30 11:03:37 -040040 case FrameMarker_Clear:
Zack Rusinead6aad2011-04-15 22:16:18 -040041 return call->name() == QLatin1String("glClear");
Zack Rusinf6667d12011-03-30 11:03:37 -040042 }
43
44 Q_ASSERT(!"unknown frame marker");
45
46 return false;
47}
48
49bool ApiTrace::isEmpty() const
50{
51 return m_calls.isEmpty();
52}
53
54QString ApiTrace::fileName() const
55{
Zack Rusin63efea82011-04-17 17:10:45 -040056 if (edited())
57 return m_tempFileName;
58
Zack Rusinf6667d12011-03-30 11:03:37 -040059 return m_fileName;
60}
61
62ApiTrace::FrameMarker ApiTrace::frameMarker() const
63{
64 return m_frameMarker;
65}
66
67QList<ApiTraceCall*> ApiTrace::calls() const
68{
69 return m_calls;
70}
71
72ApiTraceCall * ApiTrace::callAt(int idx) const
73{
74 return m_calls.value(idx);
75}
76
77int ApiTrace::numCalls() const
78{
79 return m_calls.count();
80}
81
82QList<ApiTraceFrame*> ApiTrace::frames() const
83{
84 return m_frames;
85}
86
87ApiTraceFrame * ApiTrace::frameAt(int idx) const
88{
89 return m_frames.value(idx);
90}
91
92int ApiTrace::numFrames() const
93{
94 return m_frames.count();
95}
96
97int ApiTrace::numCallsInFrame(int idx) const
98{
99 const ApiTraceFrame *frame = frameAt(idx);
100 if (frame)
101 return frame->calls.count();
102 else
103 return 0;
104}
105
106void ApiTrace::setFileName(const QString &name)
107{
108 if (m_fileName != name) {
109 m_fileName = name;
110
111 if (m_loader->isRunning()) {
112 m_loader->terminate();
113 m_loader->wait();
114 }
Zack Rusinca164112011-04-11 02:23:09 -0400115 m_frames.clear();
116 m_calls.clear();
Zack Rusinf6667d12011-03-30 11:03:37 -0400117 emit invalidated();
118
119 m_loader->loadFile(m_fileName);
120 }
121}
122
123void ApiTrace::setFrameMarker(FrameMarker marker)
124{
125 if (m_frameMarker != marker) {
126 emit framesInvalidated();
127
128 qDeleteAll(m_frames);
129 m_frames.clear();
130 detectFrames();
131 }
132}
133
134void ApiTrace::addFrames(const QList<ApiTraceFrame*> &frames)
135{
136 int currentFrames = m_frames.count();
137 int numNewFrames = frames.count();
138 m_frames += frames;
139
140 int currentCalls = m_calls.count();
141 int numNewCalls = 0;
142 foreach(ApiTraceFrame *frame, frames) {
Zack Rusin7c1793e2011-04-16 23:14:25 -0400143 frame->setParentTrace(this);
Zack Rusinf6667d12011-03-30 11:03:37 -0400144 numNewCalls += frame->calls.count();
145 m_calls += frame->calls;
146 }
147
148 emit framesAdded(currentFrames, numNewFrames);
149 emit callsAdded(currentCalls, numNewCalls);
150}
151
152void ApiTrace::detectFrames()
153{
154 if (m_calls.isEmpty())
155 return;
156
157 ApiTraceFrame *currentFrame = 0;
158 foreach(ApiTraceCall *apiCall, m_calls) {
159 if (!currentFrame) {
160 currentFrame = new ApiTraceFrame();
Zack Rusin7c1793e2011-04-16 23:14:25 -0400161 currentFrame->setParentTrace(this);
Zack Rusinf6667d12011-03-30 11:03:37 -0400162 currentFrame->number = m_frames.count();
163 }
Zack Rusinead6aad2011-04-15 22:16:18 -0400164 apiCall->setParentFrame(currentFrame);
Zack Rusinf6667d12011-03-30 11:03:37 -0400165 currentFrame->calls.append(apiCall);
166 if (ApiTrace::isCallAFrameMarker(apiCall,
167 m_frameMarker)) {
168 m_frames.append(currentFrame);
169 currentFrame = 0;
170 }
171 }
172 //last frames won't have markers
173 // it's just a bunch of Delete calls for every object
174 // after the last SwapBuffers
175 if (currentFrame) {
176 m_frames.append(currentFrame);
177 currentFrame = 0;
178 }
179 emit framesAdded(0, m_frames.count());
180}
181
Zack Rusinf04cf8a2011-04-12 23:21:52 -0400182ApiTraceCall * ApiTrace::callWithIndex(int idx) const
183{
184 for (int i = 0; i < m_calls.count(); ++i) {
185 ApiTraceCall *call = m_calls[i];
Zack Rusinead6aad2011-04-15 22:16:18 -0400186 if (call->index() == idx)
Zack Rusinf04cf8a2011-04-12 23:21:52 -0400187 return call;
188 }
189 return NULL;
190}
191
Zack Rusine2dfa2e2011-04-13 01:35:03 -0400192ApiTraceState ApiTrace::defaultState() const
193{
194 ApiTraceFrame *frame = frameAt(0);
195 if (!frame)
196 return ApiTraceState();
197
198 return frame->state();
199}
200
Zack Rusin661842d2011-04-17 01:59:16 -0400201void ApiTrace::callEdited(ApiTraceCall *call)
202{
Zack Rusin63efea82011-04-17 17:10:45 -0400203 if (!m_editedCalls.contains(call)) {
204 //lets generate a temp filename
205 QString tempPath = QDir::tempPath();
206 //lets make sure it exists
207 m_tempFileName = QString::fromLatin1("%1/%2.edited")
208 .arg(tempPath)
209 .arg(m_fileName);
210 m_needsSaving = true;
211 }
212
Zack Rusin661842d2011-04-17 01:59:16 -0400213 m_editedCalls.insert(call);
Zack Rusin63efea82011-04-17 17:10:45 -0400214
Zack Rusin661842d2011-04-17 01:59:16 -0400215 emit changed(call);
216}
217
218void ApiTrace::callReverted(ApiTraceCall *call)
219{
220 m_editedCalls.remove(call);
Zack Rusin63efea82011-04-17 17:10:45 -0400221
222 if (m_editedCalls.isEmpty()) {
223 m_needsSaving = false;
224 }
Zack Rusin661842d2011-04-17 01:59:16 -0400225 emit changed(call);
226}
227
Zack Rusin0ddd2502011-04-17 02:34:45 -0400228bool ApiTrace::edited() const
Zack Rusin661842d2011-04-17 01:59:16 -0400229{
230 return !m_editedCalls.isEmpty();
231}
232
Zack Rusin63efea82011-04-17 17:10:45 -0400233bool ApiTrace::needsSaving() const
234{
235 return m_needsSaving;
236}
237
238void ApiTrace::save()
239{
240 QFileInfo fi(m_tempFileName);
241 QDir dir;
242 dir.mkpath(fi.absolutePath());
243 m_needsSaving = false;
244}
245
Zack Rusinf6667d12011-03-30 11:03:37 -0400246#include "apitrace.moc"