X-Git-Url: https://git.cworth.org/git?a=blobdiff_plain;f=gui%2Ftraceloader.cpp;h=d09f0fe7fa019beeca4d4e3eb13133fc8e11c61d;hb=d9d9d22837705de6a2c42ad3f9b23223a2b98fe0;hp=7cb07f00aa1331e814c6d7025deffe76498a36fc;hpb=b4a3d1495a5e92ba23bf463bcea34a6e75b55294;p=apitrace diff --git a/gui/traceloader.cpp b/gui/traceloader.cpp index 7cb07f0..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())); @@ -20,8 +27,7 @@ apiCallFromTraceCall(const trace::Call *call, } TraceLoader::TraceLoader(QObject *parent) - : QObject(parent), - m_frameMarker(ApiTrace::FrameMarker_SwapBuffers) + : QObject(parent) { } @@ -61,6 +67,7 @@ void TraceLoader::loadTrace(const QString &filename) //Load the entire file into memory parseTrace(); } + emit guessedApi(static_cast(m_parser.api)); emit finishedParsing(); } @@ -69,34 +76,6 @@ void TraceLoader::loadFrame(ApiTraceFrame *currentFrame) fetchFrameContents(currentFrame); } -void TraceLoader::setFrameMarker(ApiTrace::FrameMarker marker) -{ - m_frameMarker = marker; -} - -bool TraceLoader::isCallAFrameMarker(const trace::Call *call) const -{ - std::string name = call->name(); - - switch (m_frameMarker) { - case ApiTrace::FrameMarker_SwapBuffers: - return name.find("SwapBuffers") != std::string::npos || - name == "CGLFlushDrawable" || - name == "glFrameTerminatorGREMEDY"; - break; - case ApiTrace::FrameMarker_Flush: - return name == "glFlush"; - break; - case ApiTrace::FrameMarker_Finish: - return name == "glFinish"; - break; - case ApiTrace::FrameMarker_Clear: - return name == "glClear"; - break; - } - return false; -} - int TraceLoader::numberOfFrames() const { return m_frameBookmarks.size(); @@ -104,7 +83,7 @@ int TraceLoader::numberOfFrames() const int TraceLoader::numberOfCallsInFrame(int frameIdx) const { - if (frameIdx > m_frameBookmarks.size()) { + if (frameIdx >= m_frameBookmarks.size()) { return 0; } FrameBookmarks::const_iterator itr = @@ -147,7 +126,7 @@ void TraceLoader::scanTrace() while ((call = m_parser.scan_call())) { ++numOfCalls; - if (isCallAFrameMarker(call)) { + if (call->flags & trace::CALL_FLAG_END_FRAME) { FrameBookmark frameBookmark(startBookmark); frameBookmark.numberOfCalls = numOfCalls; @@ -196,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; @@ -210,18 +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 (ApiTrace::isCallAFrameMarker(apiCall, - m_frameMarker)) { - calls.squeeze(); - currentFrame->setCalls(calls, binaryDataSize); - calls.clear(); + if (call->flags & trace::CALL_FLAG_END_FRAME) { + 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; @@ -242,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; } @@ -386,7 +389,7 @@ int TraceLoader::callInFrame(int callIdx) const { unsigned numCalls = 0; - for (int frameIdx = 0; frameIdx <= m_frameBookmarks.size(); ++frameIdx) { + for (int frameIdx = 0; frameIdx < m_frameBookmarks.size(); ++frameIdx) { const FrameBookmark &frameBookmark = m_frameBookmarks[frameIdx]; unsigned firstCall = numCalls; unsigned endCall = numCalls + frameBookmark.numberOfCalls; @@ -407,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; @@ -428,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); @@ -438,9 +443,22 @@ TraceLoader::fetchFrameContents(ApiTraceFrame *currentFrame) while ((call = m_parser.parse_call())) { ApiTraceCall *apiCall = apiCallFromTraceCall(call, m_helpHash, - currentFrame, this); - calls[parsedCalls] = apiCall; - Q_ASSERT(calls[parsedCalls]); + currentFrame, groups.isEmpty() ? 0 : groups.top(), this); + Q_ASSERT(apiCall); + Q_ASSERT(parsedCalls < calls.size()); + 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()[ @@ -448,23 +466,29 @@ TraceLoader::fetchFrameContents(ApiTraceFrame *currentFrame) binaryDataSize += data.size(); } - ++parsedCalls; - delete call; - if (ApiTrace::isCallAFrameMarker(apiCall, m_frameMarker)) { + if (apiCall->flags() & trace::CALL_FLAG_END_FRAME) { break; } } - assert(parsedCalls == numOfCalls); - Q_ASSERT(parsedCalls == calls.size()); - calls.squeeze(); - - Q_ASSERT(parsedCalls == currentFrame->numChildrenToLoad()); - emit frameContentsLoaded(currentFrame, - calls, binaryDataSize); - return calls; + // There can be fewer parsed calls when call in different + // threads cross the frame boundary + Q_ASSERT(parsedCalls <= numOfCalls); + Q_ASSERT(parsedCalls <= calls.size()); + allCalls.resize(parsedCalls); + allCalls.squeeze(); + + Q_ASSERT(parsedCalls <= currentFrame->numChildrenToLoad()); + if (topLevelItems.count() == allCalls.count()) { + emit frameContentsLoaded(currentFrame, allCalls, + allCalls, binaryDataSize); + } else { + emit frameContentsLoaded(currentFrame, topLevelItems, + allCalls, binaryDataSize); + } + return allCalls; } } return QVector(); @@ -498,8 +522,9 @@ void TraceLoader::findCallIndex(int index) call = *itr; } } - Q_ASSERT(call); - emit foundCallIndex(call); + if (call) { + emit foundCallIndex(call); + } } void TraceLoader::search(const ApiTrace::SearchRequest &request)