]> git.cworth.org Git - apitrace/blob - gui/apitrace.cpp
e98eeff04f278118c73af45ee88c5273edda2e78
[apitrace] / gui / apitrace.cpp
1 #include "apitrace.h"
2
3 #include "loaderthread.h"
4 #include "saverthread.h"
5
6 #include <QDir>
7
8 ApiTrace::ApiTrace()
9     : m_frameMarker(ApiTrace::FrameMarker_SwapBuffers),
10       m_needsSaving(false)
11 {
12     m_loader = new LoaderThread(this);
13     connect(m_loader, SIGNAL(parsedFrames(const QList<ApiTraceFrame*>)),
14             this, SLOT(addFrames(const QList<ApiTraceFrame*>)));
15     connect(m_loader, SIGNAL(started()),
16             this, SIGNAL(startedLoadingTrace()));
17     connect(m_loader, SIGNAL(finished()),
18             this, SIGNAL(finishedLoadingTrace()));
19
20     m_saver = new SaverThread(this);
21 }
22
23 ApiTrace::~ApiTrace()
24 {
25     qDeleteAll(m_calls);
26     qDeleteAll(m_frames);
27     delete m_loader;
28     delete m_saver;
29 }
30
31 bool ApiTrace::isCallAFrameMarker(const ApiTraceCall *call,
32                                   ApiTrace::FrameMarker marker)
33 {
34     if (!call)
35         return false;
36
37     switch (marker) {
38     case FrameMarker_SwapBuffers:
39         return call->name().contains(QLatin1String("SwapBuffers"));
40     case FrameMarker_Flush:
41         return call->name() == QLatin1String("glFlush");
42     case FrameMarker_Finish:
43         return call->name() == QLatin1String("glFinish");
44     case FrameMarker_Clear:
45         return call->name() == QLatin1String("glClear");
46     }
47
48     Q_ASSERT(!"unknown frame marker");
49
50     return false;
51 }
52
53 bool ApiTrace::isEmpty() const
54 {
55     return m_calls.isEmpty();
56 }
57
58 QString ApiTrace::fileName() const
59 {
60     if (edited())
61         return m_tempFileName;
62
63     return m_fileName;
64 }
65
66 ApiTrace::FrameMarker ApiTrace::frameMarker() const
67 {
68     return m_frameMarker;
69 }
70
71 QList<ApiTraceCall*> ApiTrace::calls() const
72 {
73     return m_calls;
74 }
75
76 ApiTraceCall * ApiTrace::callAt(int idx) const
77 {
78     return m_calls.value(idx);
79 }
80
81 int ApiTrace::numCalls() const
82 {
83     return m_calls.count();
84 }
85
86 QList<ApiTraceFrame*> ApiTrace::frames() const
87 {
88     return m_frames;
89 }
90
91 ApiTraceFrame * ApiTrace::frameAt(int idx) const
92 {
93     return m_frames.value(idx);
94 }
95
96 int ApiTrace::numFrames() const
97 {
98     return m_frames.count();
99 }
100
101 int 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
110 void 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         }
119         m_frames.clear();
120         m_calls.clear();
121         emit invalidated();
122
123         m_loader->loadFile(m_fileName);
124     }
125 }
126
127 void 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
138 void 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) {
147         frame->setParentTrace(this);
148         numNewCalls += frame->calls.count();
149         m_calls += frame->calls;
150     }
151
152     emit framesAdded(currentFrames, numNewFrames);
153     emit callsAdded(currentCalls, numNewCalls);
154 }
155
156 void 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();
165             currentFrame->setParentTrace(this);
166             currentFrame->number = m_frames.count();
167         }
168         apiCall->setParentFrame(currentFrame);
169         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
186 ApiTraceCall * ApiTrace::callWithIndex(int idx) const
187 {
188     for (int i = 0; i < m_calls.count(); ++i) {
189         ApiTraceCall *call = m_calls[i];
190         if (call->index() == idx)
191             return call;
192     }
193     return NULL;
194 }
195
196 ApiTraceState ApiTrace::defaultState() const
197 {
198     ApiTraceFrame *frame = frameAt(0);
199     if (!frame)
200         return ApiTraceState();
201
202     return frame->state();
203 }
204
205 void ApiTrace::callEdited(ApiTraceCall *call)
206 {
207     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
217     m_editedCalls.insert(call);
218
219     emit changed(call);
220 }
221
222 void ApiTrace::callReverted(ApiTraceCall *call)
223 {
224     m_editedCalls.remove(call);
225
226     if (m_editedCalls.isEmpty()) {
227         m_needsSaving = false;
228     }
229     emit changed(call);
230 }
231
232 bool ApiTrace::edited() const
233 {
234     return !m_editedCalls.isEmpty();
235 }
236
237 bool ApiTrace::needsSaving() const
238 {
239     return m_needsSaving;
240 }
241
242 void ApiTrace::save()
243 {
244     QFileInfo fi(m_tempFileName);
245     QDir dir;
246     dir.mkpath(fi.absolutePath());
247     m_needsSaving = false;
248
249     m_saver->saveFile(m_tempFileName, m_calls);
250 }
251
252 #include "apitrace.moc"