summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZack Rusin <zack@kde.org>2013-10-11 18:02:26 -0400
committerZack Rusin <zack@kde.org>2013-10-11 18:04:12 -0400
commitd9d9d22837705de6a2c42ad3f9b23223a2b98fe0 (patch)
treef3fbebaa2fb0ae6bce32c5448defc3a1854f42cc
parent52fc2b017b6914afb3799601b6e93f9306af0058 (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.hpp7
-rw-r--r--common/trace_parser_flags.cpp6
-rw-r--r--gui/apitrace.cpp11
-rw-r--r--gui/apitrace.h1
-rw-r--r--gui/apitracecall.cpp108
-rw-r--r--gui/apitracecall.h29
-rw-r--r--gui/apitracemodel.cpp69
-rw-r--r--gui/mainwindow.cpp3
-rw-r--r--gui/traceloader.cpp89
-rw-r--r--gui/traceloader.h1
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);