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*)));
36 connect(this, SIGNAL(loaderFindFrameStart(ApiTraceFrame*)),
37 m_loader, SLOT(findFrameStart(ApiTraceFrame*)));
38 connect(this, SIGNAL(loaderFindFrameEnd(ApiTraceFrame*)),
39 m_loader, SLOT(findFrameEnd(ApiTraceFrame*)));
40 connect(m_loader, SIGNAL(foundFrameStart(ApiTraceFrame*)),
41 this, SIGNAL(foundFrameStart(ApiTraceFrame*)));
42 connect(m_loader, SIGNAL(foundFrameEnd(ApiTraceFrame*)),
43 this, SIGNAL(foundFrameEnd(ApiTraceFrame*)));
44 connect(this, SIGNAL(loaderFindCallIndex(int)),
45 m_loader, SLOT(findCallIndex(int)));
46 connect(m_loader, SIGNAL(foundCallIndex(ApiTraceCall*)),
47 this, SIGNAL(foundCallIndex(ApiTraceCall*)));
50 connect(m_loader, SIGNAL(startedParsing()),
51 this, SIGNAL(startedLoadingTrace()));
52 connect(m_loader, SIGNAL(parsed(int)),
53 this, SIGNAL(loaded(int)));
54 connect(m_loader, SIGNAL(finishedParsing()),
55 this, SIGNAL(finishedLoadingTrace()));
58 m_saver = new SaverThread(this);
59 connect(m_saver, SIGNAL(traceSaved()),
60 this, SLOT(slotSaved()));
61 connect(m_saver, SIGNAL(traceSaved()),
62 this, SIGNAL(saved()));
64 m_loaderThread = new QThread();
65 m_loader->moveToThread(m_loaderThread);
66 m_loaderThread->start();
71 m_loaderThread->quit();
72 m_loaderThread->deleteLater();
79 bool ApiTrace::isCallAFrameMarker(const ApiTraceCall *call,
80 ApiTrace::FrameMarker marker)
86 case FrameMarker_SwapBuffers:
87 return call->name().contains(QLatin1String("SwapBuffers")) ||
88 call->name() == QLatin1String("CGLFlushDrawable") ||
89 call->name() == QLatin1String("glFrameTerminatorGREMEDY");
90 case FrameMarker_Flush:
91 return call->name() == QLatin1String("glFlush");
92 case FrameMarker_Finish:
93 return call->name() == QLatin1String("glFinish");
94 case FrameMarker_Clear:
95 return call->name() == QLatin1String("glClear");
98 Q_ASSERT(!"unknown frame marker");
103 bool ApiTrace::isEmpty() const
105 return m_calls.isEmpty();
108 QString ApiTrace::fileName() const
111 return m_tempFileName;
116 ApiTrace::FrameMarker ApiTrace::frameMarker() const
118 return m_frameMarker;
121 QVector<ApiTraceCall*> ApiTrace::calls() const
126 int ApiTrace::numCalls() const
128 return m_calls.count();
131 QList<ApiTraceFrame*> ApiTrace::frames() const
136 ApiTraceFrame * ApiTrace::frameAt(int idx) const
138 return m_frames.value(idx);
141 int ApiTrace::numFrames() const
143 return m_frames.count();
146 int ApiTrace::numCallsInFrame(int idx) const
148 const ApiTraceFrame *frame = frameAt(idx);
150 return frame->numChildren();
155 void ApiTrace::setFileName(const QString &name)
157 if (m_fileName != name) {
163 m_editedCalls.clear();
164 m_needsSaving = false;
167 // m_loader->loadTrace(m_fileName);
168 emit loadTrace(m_fileName);
172 void ApiTrace::setFrameMarker(FrameMarker marker)
174 if (m_frameMarker != marker) {
175 emit framesInvalidated();
177 qDeleteAll(m_frames);
183 void ApiTrace::addFrames(const QList<ApiTraceFrame*> &frames)
185 QVector<ApiTraceCall*> calls;
186 int currentFrames = m_frames.count();
187 int numNewFrames = frames.count();
189 emit beginAddingFrames(currentFrames, numNewFrames);
193 int currentCalls = m_calls.count();
195 foreach(ApiTraceFrame *frame, frames) {
196 frame->setParentTrace(this);
197 numNewCalls += frame->numChildren();
198 calls += frame->calls();
200 m_calls.reserve(m_calls.count() + calls.count() + 1);
203 emit endAddingFrames();
204 emit callsAdded(currentCalls, numNewCalls);
207 void ApiTrace::detectFrames()
209 if (m_calls.isEmpty())
212 emit beginAddingFrames(0, m_frames.count());
214 ApiTraceFrame *currentFrame = 0;
215 foreach(ApiTraceCall *apiCall, m_calls) {
217 currentFrame = new ApiTraceFrame(this);
218 currentFrame->number = m_frames.count();
219 currentFrame->setLoaded(true);
221 apiCall->setParentFrame(currentFrame);
222 currentFrame->addCall(apiCall);
223 if (ApiTrace::isCallAFrameMarker(apiCall,
225 m_frames.append(currentFrame);
229 //last frames won't have markers
230 // it's just a bunch of Delete calls for every object
231 // after the last SwapBuffers
233 m_frames.append(currentFrame);
236 emit endAddingFrames();
239 ApiTraceCall * ApiTrace::callWithIndex(int idx) const
241 for (int i = 0; i < m_calls.count(); ++i) {
242 ApiTraceCall *call = m_calls[i];
243 if (call->index() == idx)
249 ApiTraceState ApiTrace::defaultState() const
251 ApiTraceFrame *frame = frameAt(0);
252 if (!frame || !frame->hasState())
253 return ApiTraceState();
255 return *frame->state();
258 void ApiTrace::callEdited(ApiTraceCall *call)
260 if (!m_editedCalls.contains(call)) {
261 //lets generate a temp filename
262 QString tempPath = QDir::tempPath();
263 m_tempFileName = QString::fromLatin1("%1/%2.edited")
267 m_editedCalls.insert(call);
268 m_needsSaving = true;
273 void ApiTrace::callReverted(ApiTraceCall *call)
275 m_editedCalls.remove(call);
277 if (m_editedCalls.isEmpty()) {
278 m_needsSaving = false;
283 bool ApiTrace::edited() const
285 return !m_editedCalls.isEmpty();
288 bool ApiTrace::needsSaving() const
290 return m_needsSaving;
293 void ApiTrace::save()
295 QFileInfo fi(m_tempFileName);
297 emit startedSaving();
298 dir.mkpath(fi.absolutePath());
299 m_saver->saveFile(m_tempFileName, m_calls);
302 void ApiTrace::slotSaved()
304 m_needsSaving = false;
307 bool ApiTrace::isSaving() const
309 return m_saver->isRunning();
312 void ApiTrace::callError(ApiTraceCall *call)
316 if (call->hasError())
317 m_errors.insert(call);
319 m_errors.remove(call);
324 bool ApiTrace::hasErrors() const
326 return !m_errors.isEmpty();
329 void ApiTrace::loadFrame(ApiTraceFrame *frame)
331 Q_ASSERT(!frame->loaded());
332 emit requestFrame(frame);
335 void ApiTrace::finishedParsing()
337 ApiTraceFrame *firstFrame = m_frames[0];
338 if (firstFrame && !firstFrame->loaded()) {
339 loadFrame(firstFrame);
343 void ApiTrace::loaderFrameLoaded(ApiTraceFrame *frame,
344 const QVector<ApiTraceCall*> &calls,
345 quint64 binaryDataSize)
347 Q_ASSERT(frame->numChildrenToLoad() == calls.size());
348 emit beginLoadingFrame(frame, calls.size());
349 frame->setCalls(calls, binaryDataSize);
350 emit endLoadingFrame(frame);
353 void ApiTrace::findNext(ApiTraceFrame *frame,
356 Qt::CaseSensitivity sensitivity)
358 ApiTraceCall *foundCall = 0;
359 int frameIdx = m_frames.indexOf(frame);
361 if (frame->loaded()) {
362 foundCall = frame->findNextCall(from, str, sensitivity);
364 emit findResult(SearchFound, foundCall);
368 //if the frame is loaded we already searched it above
373 for (int i = frameIdx; i < m_frames.count(); ++i) {
374 ApiTraceFrame *frame = m_frames[i];
375 if (!frame->loaded()) {
376 emit loaderSearchNext(i, str, sensitivity);
379 ApiTraceCall *call = frame->findNextCall(0, str, sensitivity);
381 emit findResult(SearchFound, call);
386 emit findResult(SearchWrapped, 0);
389 void ApiTrace::findPrev(ApiTraceFrame *frame,
392 Qt::CaseSensitivity sensitivity)
394 ApiTraceCall *foundCall = 0;
395 int frameIdx = m_frames.indexOf(frame);
397 if (frame->loaded()) {
398 foundCall = frame->findPrevCall(from, str, sensitivity);
400 emit findResult(SearchFound, foundCall);
404 //if the frame is loaded we already searched it above
409 for (int i = frameIdx; i >= 0; --i) {
410 ApiTraceFrame *frame = m_frames[i];
411 if (!frame->loaded()) {
412 emit loaderSearchPrev(i, str, sensitivity);
415 ApiTraceCall *call = frame->findPrevCall(0, str, sensitivity);
417 emit findResult(SearchFound, call);
422 emit findResult(SearchWrapped, 0);
425 void ApiTrace::loaderSearchResult(ApiTrace::SearchResult result,
428 //qDebug()<<"Search result = "<<result
429 // <<", call is = "<<call;
430 emit findResult(result, call);
433 void ApiTrace::findFrameStart(ApiTraceFrame *frame)
435 if (frame->loaded()) {
436 emit foundFrameStart(frame);
438 emit loaderFindFrameStart(frame);
442 void ApiTrace::findFrameEnd(ApiTraceFrame *frame)
444 if (frame->loaded()) {
445 emit foundFrameEnd(frame);
447 emit loaderFindFrameEnd(frame);
451 void ApiTrace::findCallIndex(int index)
453 int frameIdx = callInFrame(index);
454 ApiTraceFrame *frame = 0;
457 emit foundCallIndex(0);
461 frame = m_frames[frameIdx];
464 if (frame->loaded()) {
465 ApiTraceCall *call = frame->callWithIndex(index);
466 emit foundCallIndex(call);
468 emit loaderFindCallIndex(index);
473 int ApiTrace::callInFrame(int callIdx) const
475 unsigned numCalls = 0;
477 for (int frameIdx = 0; frameIdx <= m_frames.size(); ++frameIdx) {
478 const ApiTraceFrame *frame = m_frames[frameIdx];
479 unsigned numCallsInFrame = frame->loaded()
480 ? frame->numChildren()
481 : frame->numChildrenToLoad();
482 unsigned firstCall = numCalls;
483 unsigned endCall = numCalls + numCallsInFrame;
484 if (firstCall <= callIdx && endCall > callIdx) {
493 #include "apitrace.moc"