blob: e98eeff04f278118c73af45ee88c5273edda2e78 [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 Rusinf6667d12011-03-30 11:03:37 -040021}
22
23ApiTrace::~ApiTrace()
24{
25 qDeleteAll(m_calls);
26 qDeleteAll(m_frames);
27 delete m_loader;
Zack Rusind809a062011-04-17 23:30:58 -040028 delete m_saver;
Zack Rusinf6667d12011-03-30 11:03:37 -040029}
30
31bool ApiTrace::isCallAFrameMarker(const ApiTraceCall *call,
32 ApiTrace::FrameMarker marker)
33{
34 if (!call)
35 return false;
36
37 switch (marker) {
38 case FrameMarker_SwapBuffers:
Zack Rusinead6aad2011-04-15 22:16:18 -040039 return call->name().contains(QLatin1String("SwapBuffers"));
Zack Rusinf6667d12011-03-30 11:03:37 -040040 case FrameMarker_Flush:
Zack Rusinead6aad2011-04-15 22:16:18 -040041 return call->name() == QLatin1String("glFlush");
Zack Rusinf6667d12011-03-30 11:03:37 -040042 case FrameMarker_Finish:
Zack Rusinead6aad2011-04-15 22:16:18 -040043 return call->name() == QLatin1String("glFinish");
Zack Rusinf6667d12011-03-30 11:03:37 -040044 case FrameMarker_Clear:
Zack Rusinead6aad2011-04-15 22:16:18 -040045 return call->name() == QLatin1String("glClear");
Zack Rusinf6667d12011-03-30 11:03:37 -040046 }
47
48 Q_ASSERT(!"unknown frame marker");
49
50 return false;
51}
52
53bool ApiTrace::isEmpty() const
54{
55 return m_calls.isEmpty();
56}
57
58QString ApiTrace::fileName() const
59{
Zack Rusin63efea82011-04-17 17:10:45 -040060 if (edited())
61 return m_tempFileName;
62
Zack Rusinf6667d12011-03-30 11:03:37 -040063 return m_fileName;
64}
65
66ApiTrace::FrameMarker ApiTrace::frameMarker() const
67{
68 return m_frameMarker;
69}
70
71QList<ApiTraceCall*> ApiTrace::calls() const
72{
73 return m_calls;
74}
75
76ApiTraceCall * ApiTrace::callAt(int idx) const
77{
78 return m_calls.value(idx);
79}
80
81int ApiTrace::numCalls() const
82{
83 return m_calls.count();
84}
85
86QList<ApiTraceFrame*> ApiTrace::frames() const
87{
88 return m_frames;
89}
90
91ApiTraceFrame * ApiTrace::frameAt(int idx) const
92{
93 return m_frames.value(idx);
94}
95
96int ApiTrace::numFrames() const
97{
98 return m_frames.count();
99}
100
101int ApiTrace::numCallsInFrame(int idx) const
102{
103 const ApiTraceFrame *frame = frameAt(idx);
104 if (frame)
105 return frame->calls.count();
106 else
107 return 0;
108}
109
110void ApiTrace::setFileName(const QString &name)
111{
112 if (m_fileName != name) {
113 m_fileName = name;
114
115 if (m_loader->isRunning()) {
116 m_loader->terminate();
117 m_loader->wait();
118 }
Zack Rusinca164112011-04-11 02:23:09 -0400119 m_frames.clear();
120 m_calls.clear();
Zack Rusinf6667d12011-03-30 11:03:37 -0400121 emit invalidated();
122
123 m_loader->loadFile(m_fileName);
124 }
125}
126
127void ApiTrace::setFrameMarker(FrameMarker marker)
128{
129 if (m_frameMarker != marker) {
130 emit framesInvalidated();
131
132 qDeleteAll(m_frames);
133 m_frames.clear();
134 detectFrames();
135 }
136}
137
138void ApiTrace::addFrames(const QList<ApiTraceFrame*> &frames)
139{
140 int currentFrames = m_frames.count();
141 int numNewFrames = frames.count();
142 m_frames += frames;
143
144 int currentCalls = m_calls.count();
145 int numNewCalls = 0;
146 foreach(ApiTraceFrame *frame, frames) {
Zack Rusin7c1793e2011-04-16 23:14:25 -0400147 frame->setParentTrace(this);
Zack Rusinf6667d12011-03-30 11:03:37 -0400148 numNewCalls += frame->calls.count();
149 m_calls += frame->calls;
150 }
151
152 emit framesAdded(currentFrames, numNewFrames);
153 emit callsAdded(currentCalls, numNewCalls);
154}
155
156void ApiTrace::detectFrames()
157{
158 if (m_calls.isEmpty())
159 return;
160
161 ApiTraceFrame *currentFrame = 0;
162 foreach(ApiTraceCall *apiCall, m_calls) {
163 if (!currentFrame) {
164 currentFrame = new ApiTraceFrame();
Zack Rusin7c1793e2011-04-16 23:14:25 -0400165 currentFrame->setParentTrace(this);
Zack Rusinf6667d12011-03-30 11:03:37 -0400166 currentFrame->number = m_frames.count();
167 }
Zack Rusinead6aad2011-04-15 22:16:18 -0400168 apiCall->setParentFrame(currentFrame);
Zack Rusinf6667d12011-03-30 11:03:37 -0400169 currentFrame->calls.append(apiCall);
170 if (ApiTrace::isCallAFrameMarker(apiCall,
171 m_frameMarker)) {
172 m_frames.append(currentFrame);
173 currentFrame = 0;
174 }
175 }
176 //last frames won't have markers
177 // it's just a bunch of Delete calls for every object
178 // after the last SwapBuffers
179 if (currentFrame) {
180 m_frames.append(currentFrame);
181 currentFrame = 0;
182 }
183 emit framesAdded(0, m_frames.count());
184}
185
Zack Rusinf04cf8a2011-04-12 23:21:52 -0400186ApiTraceCall * ApiTrace::callWithIndex(int idx) const
187{
188 for (int i = 0; i < m_calls.count(); ++i) {
189 ApiTraceCall *call = m_calls[i];
Zack Rusinead6aad2011-04-15 22:16:18 -0400190 if (call->index() == idx)
Zack Rusinf04cf8a2011-04-12 23:21:52 -0400191 return call;
192 }
193 return NULL;
194}
195
Zack Rusine2dfa2e2011-04-13 01:35:03 -0400196ApiTraceState ApiTrace::defaultState() const
197{
198 ApiTraceFrame *frame = frameAt(0);
199 if (!frame)
200 return ApiTraceState();
201
202 return frame->state();
203}
204
Zack Rusin661842d2011-04-17 01:59:16 -0400205void ApiTrace::callEdited(ApiTraceCall *call)
206{
Zack Rusin63efea82011-04-17 17:10:45 -0400207 if (!m_editedCalls.contains(call)) {
208 //lets generate a temp filename
209 QString tempPath = QDir::tempPath();
210 //lets make sure it exists
211 m_tempFileName = QString::fromLatin1("%1/%2.edited")
212 .arg(tempPath)
213 .arg(m_fileName);
214 m_needsSaving = true;
215 }
216
Zack Rusin661842d2011-04-17 01:59:16 -0400217 m_editedCalls.insert(call);
Zack Rusin63efea82011-04-17 17:10:45 -0400218
Zack Rusin661842d2011-04-17 01:59:16 -0400219 emit changed(call);
220}
221
222void ApiTrace::callReverted(ApiTraceCall *call)
223{
224 m_editedCalls.remove(call);
Zack Rusin63efea82011-04-17 17:10:45 -0400225
226 if (m_editedCalls.isEmpty()) {
227 m_needsSaving = false;
228 }
Zack Rusin661842d2011-04-17 01:59:16 -0400229 emit changed(call);
230}
231
Zack Rusin0ddd2502011-04-17 02:34:45 -0400232bool ApiTrace::edited() const
Zack Rusin661842d2011-04-17 01:59:16 -0400233{
234 return !m_editedCalls.isEmpty();
235}
236
Zack Rusin63efea82011-04-17 17:10:45 -0400237bool ApiTrace::needsSaving() const
238{
239 return m_needsSaving;
240}
241
242void ApiTrace::save()
243{
244 QFileInfo fi(m_tempFileName);
245 QDir dir;
246 dir.mkpath(fi.absolutePath());
247 m_needsSaving = false;
Zack Rusind809a062011-04-17 23:30:58 -0400248
249 m_saver->saveFile(m_tempFileName, m_calls);
Zack Rusin63efea82011-04-17 17:10:45 -0400250}
251
Zack Rusinf6667d12011-03-30 11:03:37 -0400252#include "apitrace.moc"