3 #include "traceloader.h"
4 #include "saverthread.h"
11 : m_frameMarker(ApiTrace::FrameMarker_SwapBuffers),
14 m_loader = new TraceLoader();
16 connect(this, SIGNAL(loadTrace(QString)),
17 m_loader, SLOT(loadTrace(QString)));
18 connect(this, SIGNAL(requestFrame(ApiTraceFrame*)),
19 m_loader, SLOT(loadFrame(ApiTraceFrame*)));
20 connect(m_loader, SIGNAL(framesLoaded(const QList<ApiTraceFrame*>)),
21 this, SLOT(addFrames(const QList<ApiTraceFrame*>)));
23 SIGNAL(frameContentsLoaded(ApiTraceFrame*,QVector<ApiTraceCall*>,quint64)),
25 SLOT(loaderFrameLoaded(ApiTraceFrame*,QVector<ApiTraceCall*>,quint64)));
26 connect(m_loader, SIGNAL(finishedParsing()),
27 this, SLOT(finishedParsing()));
28 connect(this, SIGNAL(loaderSearchNext(int,QString,Qt::CaseSensitivity)),
29 m_loader, SLOT(searchNext(int,QString,Qt::CaseSensitivity)));
30 connect(this, SIGNAL(loaderSearchPrev(int,QString,Qt::CaseSensitivity)),
31 m_loader, SLOT(searchPrev(int,QString,Qt::CaseSensitivity)));
33 SIGNAL(searchResult(ApiTrace::SearchResult,ApiTraceCall*)),
35 SLOT(loaderSearchResult(ApiTrace::SearchResult,ApiTraceCall*)));
38 connect(m_loader, SIGNAL(startedParsing()),
39 this, SIGNAL(startedLoadingTrace()));
40 connect(m_loader, SIGNAL(parsed(int)),
41 this, SIGNAL(loaded(int)));
42 connect(m_loader, SIGNAL(finishedParsing()),
43 this, SIGNAL(finishedLoadingTrace()));
46 m_saver = new SaverThread(this);
47 connect(m_saver, SIGNAL(traceSaved()),
48 this, SLOT(slotSaved()));
49 connect(m_saver, SIGNAL(traceSaved()),
50 this, SIGNAL(saved()));
52 m_loaderThread = new QThread();
53 m_loader->moveToThread(m_loaderThread);
54 m_loaderThread->start();
59 m_loaderThread->quit();
60 m_loaderThread->deleteLater();
67 bool ApiTrace::isCallAFrameMarker(const ApiTraceCall *call,
68 ApiTrace::FrameMarker marker)
74 case FrameMarker_SwapBuffers:
75 return call->name().contains(QLatin1String("SwapBuffers")) ||
76 call->name() == QLatin1String("CGLFlushDrawable") ||
77 call->name() == QLatin1String("glFrameTerminatorGREMEDY");
78 case FrameMarker_Flush:
79 return call->name() == QLatin1String("glFlush");
80 case FrameMarker_Finish:
81 return call->name() == QLatin1String("glFinish");
82 case FrameMarker_Clear:
83 return call->name() == QLatin1String("glClear");
86 Q_ASSERT(!"unknown frame marker");
91 bool ApiTrace::isEmpty() const
93 return m_calls.isEmpty();
96 QString ApiTrace::fileName() const
99 return m_tempFileName;
104 ApiTrace::FrameMarker ApiTrace::frameMarker() const
106 return m_frameMarker;
109 QVector<ApiTraceCall*> ApiTrace::calls() const
114 int ApiTrace::numCalls() const
116 return m_calls.count();
119 QList<ApiTraceFrame*> ApiTrace::frames() const
124 ApiTraceFrame * ApiTrace::frameAt(int idx) const
126 return m_frames.value(idx);
129 int ApiTrace::numFrames() const
131 return m_frames.count();
134 int ApiTrace::numCallsInFrame(int idx) const
136 const ApiTraceFrame *frame = frameAt(idx);
138 return frame->numChildren();
143 void ApiTrace::setFileName(const QString &name)
145 if (m_fileName != name) {
151 m_editedCalls.clear();
152 m_needsSaving = false;
155 // m_loader->loadTrace(m_fileName);
156 emit loadTrace(m_fileName);
160 void ApiTrace::setFrameMarker(FrameMarker marker)
162 if (m_frameMarker != marker) {
163 emit framesInvalidated();
165 qDeleteAll(m_frames);
171 void ApiTrace::addFrames(const QList<ApiTraceFrame*> &frames)
173 QVector<ApiTraceCall*> calls;
174 int currentFrames = m_frames.count();
175 int numNewFrames = frames.count();
177 emit beginAddingFrames(currentFrames, numNewFrames);
181 int currentCalls = m_calls.count();
183 foreach(ApiTraceFrame *frame, frames) {
184 frame->setParentTrace(this);
185 numNewCalls += frame->numChildren();
186 calls += frame->calls();
188 m_calls.reserve(m_calls.count() + calls.count() + 1);
191 emit endAddingFrames();
192 emit callsAdded(currentCalls, numNewCalls);
195 void ApiTrace::detectFrames()
197 if (m_calls.isEmpty())
200 emit beginAddingFrames(0, m_frames.count());
202 ApiTraceFrame *currentFrame = 0;
203 foreach(ApiTraceCall *apiCall, m_calls) {
205 currentFrame = new ApiTraceFrame(this);
206 currentFrame->number = m_frames.count();
207 currentFrame->setLoaded(true);
209 apiCall->setParentFrame(currentFrame);
210 currentFrame->addCall(apiCall);
211 if (ApiTrace::isCallAFrameMarker(apiCall,
213 m_frames.append(currentFrame);
217 //last frames won't have markers
218 // it's just a bunch of Delete calls for every object
219 // after the last SwapBuffers
221 m_frames.append(currentFrame);
224 emit endAddingFrames();
227 ApiTraceCall * ApiTrace::callWithIndex(int idx) const
229 for (int i = 0; i < m_calls.count(); ++i) {
230 ApiTraceCall *call = m_calls[i];
231 if (call->index() == idx)
237 ApiTraceState ApiTrace::defaultState() const
239 ApiTraceFrame *frame = frameAt(0);
240 if (!frame || !frame->hasState())
241 return ApiTraceState();
243 return *frame->state();
246 void ApiTrace::callEdited(ApiTraceCall *call)
248 if (!m_editedCalls.contains(call)) {
249 //lets generate a temp filename
250 QString tempPath = QDir::tempPath();
251 m_tempFileName = QString::fromLatin1("%1/%2.edited")
255 m_editedCalls.insert(call);
256 m_needsSaving = true;
261 void ApiTrace::callReverted(ApiTraceCall *call)
263 m_editedCalls.remove(call);
265 if (m_editedCalls.isEmpty()) {
266 m_needsSaving = false;
271 bool ApiTrace::edited() const
273 return !m_editedCalls.isEmpty();
276 bool ApiTrace::needsSaving() const
278 return m_needsSaving;
281 void ApiTrace::save()
283 QFileInfo fi(m_tempFileName);
285 emit startedSaving();
286 dir.mkpath(fi.absolutePath());
287 m_saver->saveFile(m_tempFileName, m_calls);
290 void ApiTrace::slotSaved()
292 m_needsSaving = false;
295 bool ApiTrace::isSaving() const
297 return m_saver->isRunning();
300 void ApiTrace::callError(ApiTraceCall *call)
304 if (call->hasError())
305 m_errors.insert(call);
307 m_errors.remove(call);
312 bool ApiTrace::hasErrors() const
314 return !m_errors.isEmpty();
317 void ApiTrace::loadFrame(ApiTraceFrame *frame)
319 Q_ASSERT(!frame->loaded());
320 emit requestFrame(frame);
323 void ApiTrace::finishedParsing()
325 ApiTraceFrame *firstFrame = m_frames[0];
326 if (firstFrame && !firstFrame->loaded()) {
327 loadFrame(firstFrame);
331 void ApiTrace::loaderFrameLoaded(ApiTraceFrame *frame,
332 const QVector<ApiTraceCall*> &calls,
333 quint64 binaryDataSize)
335 Q_ASSERT(frame->numChildrenToLoad() == calls.size());
336 emit beginLoadingFrame(frame, calls.size());
337 frame->setCalls(calls, binaryDataSize);
338 emit endLoadingFrame(frame);
341 void ApiTrace::findNext(ApiTraceFrame *frame,
344 Qt::CaseSensitivity sensitivity)
346 ApiTraceCall *foundCall = 0;
347 int frameIdx = m_frames.indexOf(frame);
349 if (frame->loaded()) {
350 foundCall = frame->findNextCall(from, str, sensitivity);
352 emit findResult(SearchFound, foundCall);
356 //if the frame is loaded we already searched it above
361 for (int i = frameIdx; i < m_frames.count(); ++i) {
362 ApiTraceFrame *frame = m_frames[i];
363 if (!frame->loaded()) {
364 emit loaderSearchNext(i, str, sensitivity);
367 ApiTraceCall *call = frame->findNextCall(0, str, sensitivity);
369 emit findResult(SearchFound, call);
374 emit findResult(SearchWrapped, 0);
377 void ApiTrace::findPrev(ApiTraceFrame *frame,
380 Qt::CaseSensitivity sensitivity)
382 ApiTraceCall *foundCall = 0;
383 int frameIdx = m_frames.indexOf(frame);
385 if (frame->loaded()) {
386 foundCall = frame->findPrevCall(from, str, sensitivity);
388 emit findResult(SearchFound, foundCall);
392 //if the frame is loaded we already searched it above
397 for (int i = frameIdx; i >= 0; --i) {
398 ApiTraceFrame *frame = m_frames[i];
399 if (!frame->loaded()) {
400 emit loaderSearchPrev(i, str, sensitivity);
403 ApiTraceCall *call = frame->findPrevCall(0, str, sensitivity);
405 emit findResult(SearchFound, call);
410 emit findResult(SearchWrapped, 0);
413 void ApiTrace::loaderSearchResult(ApiTrace::SearchResult result,
416 //qDebug()<<"Search result = "<<result
417 // <<", call is = "<<call;
418 emit findResult(result, call);
421 #include "apitrace.moc"