]> git.cworth.org Git - apitrace/blob - gui/apitrace.cpp
Merge remote-tracking branch 'origin/master' into on-demand-loading
[apitrace] / gui / apitrace.cpp
1 #include "apitrace.h"
2
3 #include "traceloader.h"
4 #include "saverthread.h"
5
6 #include <QDir>
7 #include <QThread>
8
9 ApiTrace::ApiTrace()
10     : m_frameMarker(ApiTrace::FrameMarker_SwapBuffers),
11       m_needsSaving(false)
12 {
13     m_loader = new TraceLoader();
14     connect(this, SIGNAL(loadTrace(QString)),
15             m_loader, SLOT(loadTrace(QString)));
16     connect(m_loader, SIGNAL(framesLoaded(const QList<ApiTraceFrame*>)),
17             this, SLOT(addFrames(const QList<ApiTraceFrame*>)));
18     connect(m_loader, SIGNAL(frameLoaded(int,QVector<ApiTraceCall*>,quint64)),
19             this, SLOT(fillFrame(int,QVector<ApiTraceCall*>,quint64)));
20
21     connect(m_loader, SIGNAL(startedParsing()),
22             this, SIGNAL(startedLoadingTrace()));
23     connect(m_loader, SIGNAL(parsed(int)),
24             this, SIGNAL(loaded(int)));
25     connect(m_loader, SIGNAL(finishedParsing()),
26             this, SIGNAL(finishedLoadingTrace()));
27
28
29     m_saver = new SaverThread(this);
30     connect(m_saver, SIGNAL(traceSaved()),
31             this, SLOT(slotSaved()));
32     connect(m_saver, SIGNAL(traceSaved()),
33             this, SIGNAL(saved()));
34
35     m_loaderThread = new QThread();
36     m_loader->moveToThread(m_loaderThread);
37     m_loaderThread->start();
38 }
39
40 ApiTrace::~ApiTrace()
41 {
42     m_loaderThread->quit();
43     m_loaderThread->deleteLater();
44     qDeleteAll(m_calls);
45     qDeleteAll(m_frames);
46     delete m_loader;
47     delete m_saver;
48 }
49
50 bool ApiTrace::isCallAFrameMarker(const ApiTraceCall *call,
51                                   ApiTrace::FrameMarker marker)
52 {
53     if (!call)
54         return false;
55
56     switch (marker) {
57     case FrameMarker_SwapBuffers:
58         return call->name().contains(QLatin1String("SwapBuffers")) ||
59                call->name() == QLatin1String("CGLFlushDrawable") ||
60                call->name() == QLatin1String("glFrameTerminatorGREMEDY");
61     case FrameMarker_Flush:
62         return call->name() == QLatin1String("glFlush");
63     case FrameMarker_Finish:
64         return call->name() == QLatin1String("glFinish");
65     case FrameMarker_Clear:
66         return call->name() == QLatin1String("glClear");
67     }
68
69     Q_ASSERT(!"unknown frame marker");
70
71     return false;
72 }
73
74 bool ApiTrace::isEmpty() const
75 {
76     return m_calls.isEmpty();
77 }
78
79 QString ApiTrace::fileName() const
80 {
81     if (edited())
82         return m_tempFileName;
83
84     return m_fileName;
85 }
86
87 ApiTrace::FrameMarker ApiTrace::frameMarker() const
88 {
89     return m_frameMarker;
90 }
91
92 QVector<ApiTraceCall*> ApiTrace::calls() const
93 {
94     return m_calls;
95 }
96
97 ApiTraceCall * ApiTrace::callAt(int idx) const
98 {
99     return m_calls.value(idx);
100 }
101
102 int ApiTrace::numCalls() const
103 {
104     return m_calls.count();
105 }
106
107 QList<ApiTraceFrame*> ApiTrace::frames() const
108 {
109     return m_frames;
110 }
111
112 ApiTraceFrame * ApiTrace::frameAt(int idx) const
113 {
114     return m_frames.value(idx);
115 }
116
117 int ApiTrace::numFrames() const
118 {
119     return m_frames.count();
120 }
121
122 int ApiTrace::numCallsInFrame(int idx) const
123 {
124     const ApiTraceFrame *frame = frameAt(idx);
125     if (frame)
126         return frame->numChildren();
127     else
128         return 0;
129 }
130
131 void ApiTrace::setFileName(const QString &name)
132 {
133     if (m_fileName != name) {
134         m_fileName = name;
135
136         m_frames.clear();
137         m_calls.clear();
138         m_errors.clear();
139         m_editedCalls.clear();
140         m_needsSaving = false;
141         emit invalidated();
142
143 //        m_loader->loadTrace(m_fileName);
144         emit loadTrace(m_fileName);
145     }
146 }
147
148 void ApiTrace::setFrameMarker(FrameMarker marker)
149 {
150     if (m_frameMarker != marker) {
151         emit framesInvalidated();
152
153         qDeleteAll(m_frames);
154         m_frames.clear();
155         detectFrames();
156     }
157 }
158
159 void ApiTrace::addFrames(const QList<ApiTraceFrame*> &frames)
160 {
161     QVector<ApiTraceCall*> calls;
162     int currentFrames = m_frames.count();
163     int numNewFrames = frames.count();
164
165     emit beginAddingFrames(currentFrames, numNewFrames);
166
167     m_frames += frames;
168
169     int currentCalls = m_calls.count();
170     int numNewCalls = 0;
171     foreach(ApiTraceFrame *frame, frames) {
172         frame->setParentTrace(this);
173         numNewCalls += frame->numChildren();
174         calls += frame->calls();
175     }
176     m_calls.reserve(m_calls.count() + calls.count() + 1);
177     m_calls += calls;
178
179     emit endAddingFrames();
180     emit callsAdded(currentCalls, numNewCalls);
181 }
182
183 void ApiTrace::detectFrames()
184 {
185     if (m_calls.isEmpty())
186         return;
187
188     emit beginAddingFrames(0, m_frames.count());
189
190     ApiTraceFrame *currentFrame = 0;
191     foreach(ApiTraceCall *apiCall, m_calls) {
192         if (!currentFrame) {
193             currentFrame = new ApiTraceFrame(this);
194             currentFrame->number = m_frames.count();
195             currentFrame->setLoaded(true);
196         }
197         apiCall->setParentFrame(currentFrame);
198         currentFrame->addCall(apiCall);
199         if (ApiTrace::isCallAFrameMarker(apiCall,
200                                          m_frameMarker)) {
201             m_frames.append(currentFrame);
202             currentFrame = 0;
203         }
204     }
205     //last frames won't have markers
206     //  it's just a bunch of Delete calls for every object
207     //  after the last SwapBuffers
208     if (currentFrame) {
209         m_frames.append(currentFrame);
210         currentFrame = 0;
211     }
212     emit endAddingFrames();
213 }
214
215 ApiTraceCall * ApiTrace::callWithIndex(int idx) const
216 {
217     for (int i = 0; i < m_calls.count(); ++i) {
218         ApiTraceCall *call = m_calls[i];
219         if (call->index() == idx)
220             return call;
221     }
222     return NULL;
223 }
224
225 ApiTraceState ApiTrace::defaultState() const
226 {
227     ApiTraceFrame *frame = frameAt(0);
228     if (!frame || !frame->hasState())
229         return ApiTraceState();
230
231     return *frame->state();
232 }
233
234 void ApiTrace::callEdited(ApiTraceCall *call)
235 {
236     if (!m_editedCalls.contains(call)) {
237         //lets generate a temp filename
238         QString tempPath = QDir::tempPath();
239         m_tempFileName = QString::fromLatin1("%1/%2.edited")
240                          .arg(tempPath)
241                          .arg(m_fileName);
242     }
243     m_editedCalls.insert(call);
244     m_needsSaving = true;
245
246     emit changed(call);
247 }
248
249 void ApiTrace::callReverted(ApiTraceCall *call)
250 {
251     m_editedCalls.remove(call);
252
253     if (m_editedCalls.isEmpty()) {
254         m_needsSaving = false;
255     }
256     emit changed(call);
257 }
258
259 bool ApiTrace::edited() const
260 {
261     return !m_editedCalls.isEmpty();
262 }
263
264 bool ApiTrace::needsSaving() const
265 {
266     return m_needsSaving;
267 }
268
269 void ApiTrace::save()
270 {
271     QFileInfo fi(m_tempFileName);
272     QDir dir;
273     emit startedSaving();
274     dir.mkpath(fi.absolutePath());
275     m_saver->saveFile(m_tempFileName, m_calls);
276 }
277
278 void ApiTrace::slotSaved()
279 {
280     m_needsSaving = false;
281 }
282
283 bool ApiTrace::isSaving() const
284 {
285     return m_saver->isRunning();
286 }
287
288 void ApiTrace::callError(ApiTraceCall *call)
289 {
290     Q_ASSERT(call);
291
292     if (call->hasError())
293         m_errors.insert(call);
294     else
295         m_errors.remove(call);
296
297     emit changed(call);
298 }
299
300 bool ApiTrace::hasErrors() const
301 {
302     return !m_errors.isEmpty();
303 }
304
305 void ApiTrace::fillFrame(int frameIdx, const QVector<ApiTraceCall *> &calls,
306                          quint64 binaryDataSize)
307 {
308 }
309
310 #include "apitrace.moc"