diff options
author | Zack Rusin <zack@kde.org> | 2013-10-11 18:02:26 -0400 |
---|---|---|
committer | Zack Rusin <zack@kde.org> | 2013-10-11 18:04:12 -0400 |
commit | d9d9d22837705de6a2c42ad3f9b23223a2b98fe0 (patch) | |
tree | f3fbebaa2fb0ae6bce32c5448defc3a1854f42cc | |
parent | 52fc2b017b6914afb3799601b6e93f9306af0058 (diff) |
Implement grouping of calls.
Use glPushDebugGroup and glPopDebugGroup to create nested groups
of calls. It makes it easy to neatly group related calls (e.g.
from nested function calls) into subgroups.
-rw-r--r-- | common/trace_model.hpp | 7 | ||||
-rw-r--r-- | common/trace_parser_flags.cpp | 6 | ||||
-rw-r--r-- | gui/apitrace.cpp | 11 | ||||
-rw-r--r-- | gui/apitrace.h | 1 | ||||
-rw-r--r-- | gui/apitracecall.cpp | 108 | ||||
-rw-r--r-- | gui/apitracecall.h | 29 | ||||
-rw-r--r-- | gui/apitracemodel.cpp | 69 | ||||
-rw-r--r-- | gui/mainwindow.cpp | 3 | ||||
-rw-r--r-- | gui/traceloader.cpp | 89 | ||||
-rw-r--r-- | gui/traceloader.h | 1 |
10 files changed, 237 insertions, 87 deletions
diff --git a/common/trace_model.hpp b/common/trace_model.hpp index ba7c8453..2ce13390 100644 --- a/common/trace_model.hpp +++ b/common/trace_model.hpp @@ -515,6 +515,13 @@ enum { * Whether this call is verbose (i.e., not usually interesting). */ CALL_FLAG_VERBOSE = (1 << 7), + + /** + * String markers. + */ + CALL_FLAG_MARKER = (1 << 8), + CALL_FLAG_MARKER_PUSH = (1 << 9), + CALL_FLAG_MARKER_POP = (1 << 10), }; diff --git a/common/trace_parser_flags.cpp b/common/trace_parser_flags.cpp index 0a636493..2cf55a2d 100644 --- a/common/trace_parser_flags.cpp +++ b/common/trace_parser_flags.cpp @@ -519,9 +519,9 @@ callFlagTable[] = { { "glMultiModeDrawElementsIBM", CALL_FLAG_RENDER }, { "glObjectLabel", CALL_FLAG_NO_SIDE_EFFECTS }, { "glObjectPtrLabel", CALL_FLAG_NO_SIDE_EFFECTS }, - { "glPopDebugGroup", CALL_FLAG_NO_SIDE_EFFECTS }, - { "glPushDebugGroup", CALL_FLAG_NO_SIDE_EFFECTS }, - { "glStringMarkerGREMEDY", CALL_FLAG_NO_SIDE_EFFECTS }, + { "glPopDebugGroup", /* CALL_FLAG_NO_SIDE_EFFECTS | */ CALL_FLAG_MARKER | CALL_FLAG_MARKER_POP}, + { "glPushDebugGroup", /* CALL_FLAG_NO_SIDE_EFFECTS | */ CALL_FLAG_MARKER | CALL_FLAG_MARKER_PUSH }, + { "glStringMarkerGREMEDY", /* CALL_FLAG_NO_SIDE_EFFECTS | */ CALL_FLAG_MARKER }, { "glXGetClientString", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE }, { "glXGetCurrentContext", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE }, { "glXGetCurrentDisplay", CALL_FLAG_NO_SIDE_EFFECTS | CALL_FLAG_VERBOSE }, diff --git a/gui/apitrace.cpp b/gui/apitrace.cpp index 671fc683..db574179 100644 --- a/gui/apitrace.cpp +++ b/gui/apitrace.cpp @@ -19,9 +19,9 @@ ApiTrace::ApiTrace() connect(m_loader, SIGNAL(framesLoaded(const QList<ApiTraceFrame*>)), this, SLOT(addFrames(const QList<ApiTraceFrame*>))); connect(m_loader, - SIGNAL(frameContentsLoaded(ApiTraceFrame*,QVector<ApiTraceCall*>,quint64)), + SIGNAL(frameContentsLoaded(ApiTraceFrame*,QVector<ApiTraceCall*>, QVector<ApiTraceCall*>,quint64)), this, - SLOT(loaderFrameLoaded(ApiTraceFrame*,QVector<ApiTraceCall*>,quint64))); + SLOT(loaderFrameLoaded(ApiTraceFrame*,QVector<ApiTraceCall*>,QVector<ApiTraceCall*>,quint64))); connect(m_loader, SIGNAL(guessedApi(int)), this, SLOT(guessedApi(int))); connect(m_loader, SIGNAL(finishedParsing()), @@ -107,7 +107,7 @@ int ApiTrace::numCallsInFrame(int idx) const { const ApiTraceFrame *frame = frameAt(idx); if (frame) { - return frame->numChildren(); + return frame->numTotalCalls(); } else { return 0; } @@ -263,6 +263,7 @@ void ApiTrace::finishedParsing() } void ApiTrace::loaderFrameLoaded(ApiTraceFrame *frame, + const QVector<ApiTraceCall*> &topLevelItems, const QVector<ApiTraceCall*> &calls, quint64 binaryDataSize) { @@ -270,7 +271,7 @@ void ApiTrace::loaderFrameLoaded(ApiTraceFrame *frame, if (!frame->isLoaded()) { emit beginLoadingFrame(frame, calls.size()); - frame->setCalls(calls, binaryDataSize); + frame->setCalls(topLevelItems, calls, binaryDataSize); emit endLoadingFrame(frame); m_loadingFrames.remove(frame); } @@ -444,7 +445,7 @@ int ApiTrace::callInFrame(int callIdx) const for (int frameIdx = 0; frameIdx < m_frames.size(); ++frameIdx) { const ApiTraceFrame *frame = m_frames[frameIdx]; unsigned numCallsInFrame = frame->isLoaded() - ? frame->numChildren() + ? frame->numTotalCalls() : frame->numChildrenToLoad(); unsigned firstCall = numCalls; unsigned endCall = numCalls + numCallsInFrame; diff --git a/gui/apitrace.h b/gui/apitrace.h index 04e295cd..a7b72d8b 100644 --- a/gui/apitrace.h +++ b/gui/apitrace.h @@ -131,6 +131,7 @@ private slots: void guessedApi(int api); void finishedParsing(); void loaderFrameLoaded(ApiTraceFrame *frame, + const QVector<ApiTraceCall*> &topLevelItems, const QVector<ApiTraceCall*> &calls, quint64 binaryDataSize); void loaderSearchResult(const ApiTrace::SearchRequest &request, diff --git a/gui/apitracecall.cpp b/gui/apitracecall.cpp index 0175bff8..79876351 100644 --- a/gui/apitracecall.cpp +++ b/gui/apitracecall.cpp @@ -648,7 +648,31 @@ ApiTraceCall::ApiTraceCall(ApiTraceFrame *parentFrame, TraceLoader *loader, const trace::Call *call) : ApiTraceEvent(ApiTraceEvent::Call), - m_parentFrame(parentFrame) + m_parentFrame(parentFrame), + m_parentCall(0) +{ + loadData(loader, call); +} + +ApiTraceCall::ApiTraceCall(ApiTraceCall *parentCall, + TraceLoader *loader, + const trace::Call *call) + : ApiTraceEvent(ApiTraceEvent::Call), + m_parentFrame(parentCall->parentFrame()), + m_parentCall(parentCall) +{ + loadData(loader, call); +} + + +ApiTraceCall::~ApiTraceCall() +{ +} + + +void +ApiTraceCall::loadData(TraceLoader *loader, + const trace::Call *call) { m_index = call->no; @@ -712,10 +736,46 @@ ApiTraceCall::ApiTraceCall(ApiTraceFrame *parentFrame, } } -ApiTraceCall::~ApiTraceCall() +ApiTraceCall * +ApiTraceCall::parentCall() const +{ + return m_parentCall; +} + + +ApiTraceEvent * +ApiTraceCall::parentEvent() const +{ + if (m_parentCall) + return m_parentCall; + else + return m_parentFrame; +} + +QVector<ApiTraceCall*> +ApiTraceCall::children() const { + return m_children; } +void +ApiTraceCall::addChild(ApiTraceCall *call) +{ + m_children.append(call); +} + + +int +ApiTraceCall::callIndex(ApiTraceCall *call) const +{ + return m_children.indexOf(call); +} + +void +ApiTraceCall::finishedAddingChildren() +{ + m_children.squeeze(); +} bool ApiTraceCall::hasError() const { @@ -820,6 +880,15 @@ QVector<QVariant> ApiTraceCall::arguments() const return m_editedValues; } +ApiTraceEvent * +ApiTraceCall::eventAtRow(int row) const +{ + if (row < m_children.count()) + return m_children.value(row); + else + return NULL; +} + QVariant ApiTraceCall::returnValue() const { return m_returnValue; @@ -1011,7 +1080,7 @@ QString ApiTraceCall::searchText() const int ApiTraceCall::numChildren() const { - return 0; + return m_children.count(); } bool ApiTraceCall::contains(const QString &str, @@ -1074,22 +1143,17 @@ QStaticText ApiTraceFrame::staticText() const int ApiTraceFrame::numChildren() const { - return m_calls.count(); + return m_children.count(); } -ApiTrace * ApiTraceFrame::parentTrace() const +int ApiTraceFrame::numTotalCalls() const { - return m_parentTrace; + return m_calls.count(); } -void ApiTraceFrame::addCall(ApiTraceCall *call) +ApiTrace * ApiTraceFrame::parentTrace() const { - m_calls.append(call); - if (call->hasBinaryData()) { - QByteArray data = - call->arguments()[call->binaryDataIndex()].toByteArray(); - m_binaryDataSize += data.size(); - } + return m_parentTrace; } QVector<ApiTraceCall*> ApiTraceFrame::calls() const @@ -1097,9 +1161,12 @@ QVector<ApiTraceCall*> ApiTraceFrame::calls() const return m_calls; } -ApiTraceCall * ApiTraceFrame::call(int idx) const +ApiTraceEvent * ApiTraceFrame::eventAtRow(int row) const { - return m_calls.value(idx); + if (row < m_children.count()) + return m_children.value(row); + else + return NULL; } @@ -1116,7 +1183,7 @@ ApiTraceCall * ApiTraceFrame::callWithIndex(int index) const int ApiTraceFrame::callIndex(ApiTraceCall *call) const { - return m_calls.indexOf(call); + return m_children.indexOf(call); } bool ApiTraceFrame::isEmpty() const @@ -1133,9 +1200,11 @@ int ApiTraceFrame::binaryDataSize() const return m_binaryDataSize; } -void ApiTraceFrame::setCalls(const QVector<ApiTraceCall*> &calls, +void ApiTraceFrame::setCalls(const QVector<ApiTraceCall*> &children, + const QVector<ApiTraceCall*> &calls, quint64 binaryDataSize) { + m_children = children; m_calls = calls; m_binaryDataSize = binaryDataSize; m_loaded = true; @@ -1148,11 +1217,6 @@ bool ApiTraceFrame::isLoaded() const return m_loaded; } -void ApiTraceFrame::setLoaded(bool l) -{ - m_loaded = l; -} - void ApiTraceFrame::setNumChildren(int num) { m_callsToLoad = num; diff --git a/gui/apitracecall.h b/gui/apitracecall.h index 8004cede..15bc6271 100644 --- a/gui/apitracecall.h +++ b/gui/apitracecall.h @@ -203,6 +203,8 @@ private: QUrl m_helpUrl; }; +class ApiTraceCall; + class ApiTraceEvent { public: @@ -220,6 +222,8 @@ public: virtual QStaticText staticText() const = 0; virtual int numChildren() const = 0; + virtual int callIndex(ApiTraceCall *call) const = 0; + virtual ApiTraceEvent *eventAtRow(int row) const = 0; QVariantMap stateParameters() const; ApiTraceState *state() const; @@ -242,6 +246,8 @@ Q_DECLARE_METATYPE(ApiTraceEvent*); class ApiTraceCall : public ApiTraceEvent { public: + ApiTraceCall(ApiTraceCall *parentCall, TraceLoader *loader, + const trace::Call *tcall); ApiTraceCall(ApiTraceFrame *parentFrame, TraceLoader *loader, const trace::Call *tcall); ~ApiTraceCall(); @@ -257,6 +263,15 @@ public: ApiTraceFrame *parentFrame()const; void setParentFrame(ApiTraceFrame *frame); + int callIndex(ApiTraceCall *call) const; + + ApiTraceEvent *parentEvent() const; + ApiTraceCall *parentCall() const; + QVector<ApiTraceCall*> children() const; + ApiTraceEvent *eventAtRow(int row) const; + void addChild(ApiTraceCall *call); + void finishedAddingChildren(); + bool hasError() const; QString error() const; void setError(const QString &msg); @@ -283,12 +298,17 @@ public: QString backtrace() const; void setBacktrace(QString backtrace); private: + void loadData(TraceLoader *loader, + const trace::Call *tcall); +private: int m_index; ApiTraceCallSignature *m_signature; QVector<QVariant> m_argValues; QVariant m_returnValue; trace::CallFlags m_flags; ApiTraceFrame *m_parentFrame; + ApiTraceCall *m_parentCall; + QVector<ApiTraceCall*> m_children; QVector<QVariant> m_editedValues; @@ -316,14 +336,15 @@ public: void setNumChildren(int num); int numChildren() const; int numChildrenToLoad() const; + int numTotalCalls() const; QStaticText staticText() const; + ApiTraceEvent *eventAtRow(int row) const; int callIndex(ApiTraceCall *call) const; - ApiTraceCall *call(int idx) const; ApiTraceCall *callWithIndex(int index) const; - void addCall(ApiTraceCall *call); QVector<ApiTraceCall*> calls() const; - void setCalls(const QVector<ApiTraceCall*> &calls, + void setCalls(const QVector<ApiTraceCall*> &topLevelCalls, + const QVector<ApiTraceCall*> &allCalls, quint64 binaryDataSize); ApiTraceCall *findNextCall(ApiTraceCall *from, @@ -337,7 +358,6 @@ public: int binaryDataSize() const; bool isLoaded() const; - void setLoaded(bool l); void setLastCallIndex(unsigned index); unsigned lastCallIndex() const; @@ -348,6 +368,7 @@ public: private: ApiTrace *m_parentTrace; quint64 m_binaryDataSize; + QVector<ApiTraceCall*> m_children; QVector<ApiTraceCall*> m_calls; bool m_loaded; unsigned m_callsToLoad; diff --git a/gui/apitracemodel.cpp b/gui/apitracemodel.cpp index 0863c1b5..fb339677 100644 --- a/gui/apitracemodel.cpp +++ b/gui/apitracemodel.cpp @@ -92,7 +92,7 @@ QVariant ApiTraceModel::data(const QModelIndex &index, int role) const } int numCalls = frame->isLoaded() - ? frame->numChildren() + ? frame->numTotalCalls() : frame->numChildrenToLoad(); return tr(htmlTempl) @@ -141,18 +141,16 @@ QModelIndex ApiTraceModel::index(int row, int column, if ((parent.isValid() && parent.column() != 0) || column != 0) return QModelIndex(); - ApiTraceEvent *event = item(parent); - if (event) { - if (event->type() != ApiTraceEvent::Frame) { - qDebug()<<"got a valid parent but it's not a frame "<<event->type(); + //qDebug()<<"At row = "<<row<<", column = "<<column<<", parent "<<parent; + ApiTraceEvent *parentEvent = item(parent); + if (parentEvent) { + ApiTraceEvent *event = parentEvent->eventAtRow(row); + if (event) { + Q_ASSERT(event->type() == ApiTraceEvent::Call); + return createIndex(row, column, event); + } else { return QModelIndex(); } - ApiTraceFrame *frame = static_cast<ApiTraceFrame*>(event); - ApiTraceCall *call = frame->call(row); - if (call) - return createIndex(row, column, call); - else - return QModelIndex(); } else { ApiTraceFrame *frame = m_trace->frameAt(row); if (frame) @@ -167,11 +165,16 @@ bool ApiTraceModel::hasChildren(const QModelIndex &parent) const { if (parent.isValid()) { ApiTraceEvent *event = item(parent); - if (event && event->type() == ApiTraceEvent::Frame) { + if (!event) + return false; + if (event->type() == ApiTraceEvent::Frame) { ApiTraceFrame *frame = static_cast<ApiTraceFrame*>(event); return !frame->isEmpty(); - } else - return false; + } else { + Q_ASSERT(event->type() == ApiTraceEvent::Call); + ApiTraceCall *call = static_cast<ApiTraceCall*>(event); + return call->numChildren() != 0; + } } else { return (rowCount() > 0); } @@ -183,11 +186,19 @@ QModelIndex ApiTraceModel::parent(const QModelIndex &index) const return QModelIndex(); ApiTraceEvent *event = item(index); - if (event && event->type() == ApiTraceEvent::Call) { + + if (event->type() == ApiTraceEvent::Call) { ApiTraceCall *call = static_cast<ApiTraceCall*>(event); - Q_ASSERT(call->parentFrame()); - return createIndex(call->parentFrame()->number, - 0, call->parentFrame()); + + if (call->parentCall()) { + ApiTraceCall *parentCall = call->parentCall(); + ApiTraceEvent *topEvent = parentCall->parentEvent(); + return createIndex(topEvent->callIndex(parentCall), 0, parentCall); + } else { + Q_ASSERT(call->parentFrame()); + return createIndex(call->parentFrame()->number, + 0, call->parentFrame()); + } } return QModelIndex(); } @@ -198,14 +209,10 @@ int ApiTraceModel::rowCount(const QModelIndex &parent) const return m_trace->numFrames(); ApiTraceEvent *event = item(parent); - if (!event || event->type() == ApiTraceEvent::Call) + if (!event) return 0; - ApiTraceFrame *frame = static_cast<ApiTraceFrame*>(event); - if (frame) - return frame->numChildren(); - - return 0; + return event->numChildren(); } int ApiTraceModel::columnCount(const QModelIndex &parent) const @@ -288,9 +295,7 @@ void ApiTraceModel::stateSetOnEvent(ApiTraceEvent *event) if (event->type() == ApiTraceEvent::Call) { ApiTraceCall *call = static_cast<ApiTraceCall*>(event); - ApiTraceFrame *frame = call->parentFrame(); - int row = frame->callIndex(call); - QModelIndex index = createIndex(row, 0, call); + QModelIndex index = indexForCall(call); emit dataChanged(index, index); } else if (event->type() == ApiTraceEvent::Frame) { ApiTraceFrame *frame = static_cast<ApiTraceFrame*>(event); @@ -307,10 +312,10 @@ QModelIndex ApiTraceModel::indexForCall(ApiTraceCall *call) const return QModelIndex(); } - ApiTraceFrame *frame = call->parentFrame(); - Q_ASSERT(frame); + ApiTraceEvent *parentEvent = call->parentEvent(); + Q_ASSERT(parentEvent); - int row = frame->callIndex(call); + int row = parentEvent->callIndex(call); if (row < 0) { qDebug() << "Couldn't find call num "<<call->index()<<" inside parent!"; return QModelIndex(); @@ -342,9 +347,7 @@ void ApiTraceModel::callChanged(ApiTraceCall *call) if (trace->needsSaving()) trace->save(); - ApiTraceFrame *frame = call->parentFrame(); - int row = frame->callIndex(call); - QModelIndex index = createIndex(row, 0, call); + QModelIndex index = indexForCall(call); emit dataChanged(index, index); } diff --git a/gui/mainwindow.cpp b/gui/mainwindow.cpp index 32783303..3accf6e9 100644 --- a/gui/mainwindow.cpp +++ b/gui/mainwindow.cpp @@ -1265,7 +1265,8 @@ void MainWindow::saveSelectedSurface() imageIndex = tr("_call_%1") .arg(selectedCall()->index()); } else if (selectedFrame()) { - ApiTraceCall *firstCall = selectedFrame()->call(0); + ApiTraceCall *firstCall = + static_cast<ApiTraceCall *>(selectedFrame()->eventAtRow(0)); if (firstCall) { imageIndex = tr("_frame_%1") .arg(firstCall->index()); diff --git a/gui/traceloader.cpp b/gui/traceloader.cpp index 6110c597..d09f0fe7 100644 --- a/gui/traceloader.cpp +++ b/gui/traceloader.cpp @@ -3,6 +3,7 @@ #include "apitrace.h" #include <QDebug> #include <QFile> +#include <QStack> #define FRAMES_TO_CACHE 100 @@ -10,9 +11,15 @@ static ApiTraceCall * apiCallFromTraceCall(const trace::Call *call, const QHash<QString, QUrl> &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<ApiTraceFrame*> frames; ApiTraceFrame *currentFrame = 0; int frameCount = 0; - QVector<ApiTraceCall*> calls; + QStack<ApiTraceCall*> groups; + QVector<ApiTraceCall*> topLevelItems; + QVector<ApiTraceCall*> 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<ApiTraceCall*> calls(numOfCalls); + QStack<ApiTraceCall*> groups; + QVector<ApiTraceCall*> topLevelItems; + QVector<ApiTraceCall*> 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<ApiTraceCall*>(); diff --git a/gui/traceloader.h b/gui/traceloader.h index 09540782..1725adb5 100644 --- a/gui/traceloader.h +++ b/gui/traceloader.h @@ -40,6 +40,7 @@ signals: void framesLoaded(const QList<ApiTraceFrame*> &frames); void frameContentsLoaded(ApiTraceFrame *frame, + const QVector<ApiTraceCall*> &topLevelItems, const QVector<ApiTraceCall*> &calls, quint64 binaryDataSize); |