X-Git-Url: https://git.cworth.org/git?a=blobdiff_plain;f=gui%2Ftraceloader.cpp;fp=gui%2Ftraceloader.cpp;h=d09f0fe7fa019beeca4d4e3eb13133fc8e11c61d;hb=d9d9d22837705de6a2c42ad3f9b23223a2b98fe0;hp=6110c5972d6416752bc82a1c0472812625907549;hpb=52fc2b017b6914afb3799601b6e93f9306af0058;p=apitrace diff --git a/gui/traceloader.cpp b/gui/traceloader.cpp index 6110c59..d09f0fe 100644 --- a/gui/traceloader.cpp +++ b/gui/traceloader.cpp @@ -3,6 +3,7 @@ #include "apitrace.h" #include #include +#include #define FRAMES_TO_CACHE 100 @@ -10,9 +11,15 @@ static ApiTraceCall * apiCallFromTraceCall(const trace::Call *call, const QHash &helpHash, ApiTraceFrame *frame, + ApiTraceCall *parentCall, TraceLoader *loader) { - ApiTraceCall *apiCall = new ApiTraceCall(frame, loader, call); + ApiTraceCall *apiCall; + + if (parentCall) + apiCall = new ApiTraceCall(parentCall, loader, call); + else + apiCall = new ApiTraceCall(frame, loader, call); apiCall->setHelpUrl(helpHash.value(apiCall->name())); @@ -168,7 +175,9 @@ void TraceLoader::parseTrace() QList frames; ApiTraceFrame *currentFrame = 0; int frameCount = 0; - QVector calls; + QStack groups; + QVector topLevelItems; + QVector allCalls; quint64 binaryDataSize = 0; int lastPercentReport = 0; @@ -182,17 +191,36 @@ void TraceLoader::parseTrace() ++frameCount; } ApiTraceCall *apiCall = - apiCallFromTraceCall(call, m_helpHash, currentFrame, this); - calls.append(apiCall); + apiCallFromTraceCall(call, m_helpHash, currentFrame, groups.isEmpty() ? 0 : groups.top(), this); + allCalls.append(apiCall); + if (groups.count() == 0) { + topLevelItems.append(apiCall); + } + if (call->flags & trace::CALL_FLAG_MARKER_PUSH) { + groups.push(apiCall); + } else if (call->flags & trace::CALL_FLAG_MARKER_POP) { + groups.top()->finishedAddingChildren(); + groups.pop(); + } + if (!groups.isEmpty()) { + groups.top()->addChild(apiCall); + } if (apiCall->hasBinaryData()) { QByteArray data = - apiCall->arguments()[apiCall->binaryDataIndex()].toByteArray(); + apiCall->arguments()[apiCall->binaryDataIndex()].toByteArray(); binaryDataSize += data.size(); } if (call->flags & trace::CALL_FLAG_END_FRAME) { - calls.squeeze(); - currentFrame->setCalls(calls, binaryDataSize); - calls.clear(); + allCalls.squeeze(); + topLevelItems.squeeze(); + if (topLevelItems.count() == allCalls.count()) { + currentFrame->setCalls(allCalls, allCalls, binaryDataSize); + } else { + currentFrame->setCalls(topLevelItems, allCalls, binaryDataSize); + } + allCalls.clear(); + groups.clear(); + topLevelItems.clear(); frames.append(currentFrame); currentFrame = 0; binaryDataSize = 0; @@ -213,8 +241,12 @@ void TraceLoader::parseTrace() // it's just a bunch of Delete calls for every object // after the last SwapBuffers if (currentFrame) { - calls.squeeze(); - currentFrame->setCalls(calls, binaryDataSize); + allCalls.squeeze(); + if (topLevelItems.count() == allCalls.count()) { + currentFrame->setCalls(allCalls, allCalls, binaryDataSize); + } else { + currentFrame->setCalls(topLevelItems, allCalls, binaryDataSize); + } frames.append(currentFrame); currentFrame = 0; } @@ -378,7 +410,7 @@ bool TraceLoader::callContains(trace::Call *call, * FIXME: do string comparison directly on trace::Call */ ApiTraceCall *apiCall = apiCallFromTraceCall(call, m_helpHash, - 0, this); + 0, 0, this); bool result = apiCall->contains(str, sensitivity); delete apiCall; return result; @@ -399,7 +431,9 @@ TraceLoader::fetchFrameContents(ApiTraceFrame *currentFrame) if (numOfCalls) { quint64 binaryDataSize = 0; - QVector calls(numOfCalls); + QStack groups; + QVector topLevelItems; + QVector allCalls(numOfCalls); const FrameBookmark &frameBookmark = m_frameBookmarks[frameIdx]; m_parser.setBookmark(frameBookmark.start); @@ -409,10 +443,22 @@ TraceLoader::fetchFrameContents(ApiTraceFrame *currentFrame) while ((call = m_parser.parse_call())) { ApiTraceCall *apiCall = apiCallFromTraceCall(call, m_helpHash, - currentFrame, this); + currentFrame, groups.isEmpty() ? 0 : groups.top(), this); Q_ASSERT(apiCall); Q_ASSERT(parsedCalls < calls.size()); - calls[parsedCalls++] = apiCall; + allCalls[parsedCalls++] = apiCall; + if (groups.count() == 0) { + topLevelItems.append(apiCall); + } + if (!groups.isEmpty()) { + groups.top()->addChild(apiCall); + } + if (call->flags & trace::CALL_FLAG_MARKER_PUSH) { + groups.push(apiCall); + } else if (call->flags & trace::CALL_FLAG_MARKER_POP) { + groups.top()->finishedAddingChildren(); + groups.pop(); + } if (apiCall->hasBinaryData()) { QByteArray data = apiCall->arguments()[ @@ -431,13 +477,18 @@ TraceLoader::fetchFrameContents(ApiTraceFrame *currentFrame) // threads cross the frame boundary Q_ASSERT(parsedCalls <= numOfCalls); Q_ASSERT(parsedCalls <= calls.size()); - calls.resize(parsedCalls); - calls.squeeze(); + allCalls.resize(parsedCalls); + allCalls.squeeze(); Q_ASSERT(parsedCalls <= currentFrame->numChildrenToLoad()); - emit frameContentsLoaded(currentFrame, - calls, binaryDataSize); - return calls; + if (topLevelItems.count() == allCalls.count()) { + emit frameContentsLoaded(currentFrame, allCalls, + allCalls, binaryDataSize); + } else { + emit frameContentsLoaded(currentFrame, topLevelItems, + allCalls, binaryDataSize); + } + return allCalls; } } return QVector();