]> git.cworth.org Git - apitrace/commitdiff
Implement grouping of calls.
authorZack Rusin <zack@kde.org>
Fri, 11 Oct 2013 22:02:26 +0000 (18:02 -0400)
committerZack Rusin <zack@kde.org>
Fri, 11 Oct 2013 22:04:12 +0000 (18:04 -0400)
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.

common/trace_model.hpp
common/trace_parser_flags.cpp
gui/apitrace.cpp
gui/apitrace.h
gui/apitracecall.cpp
gui/apitracecall.h
gui/apitracemodel.cpp
gui/mainwindow.cpp
gui/traceloader.cpp
gui/traceloader.h

index ba7c845362e55fdc5aae14fe42a4597fada84e49..2ce133903d1ffb3f822d7186d215587ffe7808a3 100644 (file)
@@ -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),
 };
 
 
index 0a636493c9f99a8a30f14f6713d72a4cc73e173a..2cf55a2d06c9ba8f71f1578b418ddaf4c8b4618a 100644 (file)
@@ -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 },
index 671fc683887fa35fbbbda15bde9b92cae1df5b43..db5741790c213ca85946cbc60fbf4d16739c22d3 100644 (file)
@@ -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;
index 04e295cd7e39470476990d834b5085be7bf77997..a7b72d8b1244edee3195d8dbfa96b6b57319a90c 100644 (file)
@@ -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,
index 0175bff81755e9e005f101e41a0ec6fc6f324432..79876351a12807039e76bd5aba16c9a3dfb1d591 100644 (file)
@@ -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;
index 8004cedebe663ec8fa8da969c613df968ea8b368..15bc627134edb082adf705d8050e2a9a8debb911 100644 (file)
@@ -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);
@@ -282,6 +297,9 @@ public:
 
     QString backtrace() const;
     void setBacktrace(QString backtrace);
+private:
+    void loadData(TraceLoader *loader,
+                  const trace::Call *tcall);
 private:
     int m_index;
     ApiTraceCallSignature *m_signature;
@@ -289,6 +307,8 @@ private:
     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;
index 0863c1b5bc0eb19ad1b649b9d83442483a2fc5ad..fb339677c5934c7825053a7ed7c098fd6e00fc89 100644 (file)
@@ -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);
 }
 
index 327833039f47d5119bde157a9b7ce4e97dbf9e56..3accf6e9489f0ecca39b8dc777f13292c3258c93 100644 (file)
@@ -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());
index 6110c5972d6416752bc82a1c0472812625907549..d09f0fe7fa019beeca4d4e3eb13133fc8e11c61d 100644 (file)
@@ -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*>();
index 0954078219fba68bd3e188b72d56027cd3b01d7b..1725adb57b57cd434106fa1cfeb33c617cf0aba1 100644 (file)
@@ -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);