#include "traceloader.h"
+#include "apitrace.h"
#include <QDebug>
#include <QFile>
qDebug() <<"\t support offsets = "<<m_parser.supportsOffsets();
if (m_parser.supportsOffsets()) {
- scanTrace();
+ scanTrace();
} else {
- //Load the entire file into memory
- parseTrace();
+ //Load the entire file into memory
+ parseTrace();
}
emit finishedParsing();
}
-void TraceLoader::loadFrame(int frameIdx)
+void TraceLoader::loadFrame(ApiTraceFrame *currentFrame)
{
- if (m_parser.supportsOffsets()) {
- int numOfCalls = numberOfCallsInFrame(frameIdx);
- if (numOfCalls) {
- const FrameOffset &frameOffset = m_frameOffsets[frameIdx];
- std::vector<Trace::Call*> calls(numOfCalls);
- m_parser.setCurrentOffset(frameOffset.start);
- m_parser.setCurrentCallNumber(frameOffset.callNumber);
-
- Trace::Call *call;
- int parsedCalls = 0;
- while ((call = m_parser.parse_call())) {
-
- calls[parsedCalls] = call;
- ++parsedCalls;
-
- if (isCallAFrameMarker(call)) {
- break;
- }
-
- }
- assert(parsedCalls == numOfCalls);
-// emit parsedFrame();
- }
- }
+ fetchFrameContents(currentFrame);
}
void TraceLoader::setFrameMarker(ApiTrace::FrameMarker marker)
switch (m_frameMarker) {
case ApiTrace::FrameMarker_SwapBuffers:
- return name.find("SwapBuffers") != std::string::npos ||
- name == "CGLFlushDrawable" ||
- name == "glFrameTerminatorGREMEDY";
- break;
+ return name.find("SwapBuffers") != std::string::npos ||
+ name == "CGLFlushDrawable" ||
+ name == "glFrameTerminatorGREMEDY";
+ break;
case ApiTrace::FrameMarker_Flush:
- return name == "glFlush";
- break;
+ return name == "glFlush";
+ break;
case ApiTrace::FrameMarker_Finish:
- return name == "glFinish";
- break;
+ return name == "glFinish";
+ break;
case ApiTrace::FrameMarker_Clear:
- return name == "glClear";
- break;
+ return name == "glClear";
+ break;
}
return false;
}
int TraceLoader::numberOfFrames() const
{
- return m_frameOffsets.size();
+ return m_frameBookmarks.size();
}
int TraceLoader::numberOfCallsInFrame(int frameIdx) const
{
- if (frameIdx > m_frameOffsets.size()) {
+ if (frameIdx > m_frameBookmarks.size()) {
return 0;
}
- FrameOffsets::const_iterator itr =
- m_frameOffsets.find(frameIdx);
+ FrameBookmarks::const_iterator itr =
+ m_frameBookmarks.find(frameIdx);
return itr->numberOfCalls;
}
void TraceLoader::loadHelpFile()
{
- QFile file(":/resources/glreference.tsv");
- if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
- QString line;
- while (!file.atEnd()) {
- line = file.readLine();
- QString function = line.section('\t', 0, 0).trimmed();
- QUrl url = QUrl(line.section('\t', 1, 1).trimmed());
- //qDebug()<<"function = "<<function<<", url = "<<url.toString();
- m_helpHash.insert(function, url);
- }
- } else {
- qWarning() << "Couldn't open reference file "
- << file.fileName();
- }
- file.close();
+ QFile file(":/resources/glreference.tsv");
+ if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
+ QString line;
+ while (!file.atEnd()) {
+ line = file.readLine();
+ QString function = line.section('\t', 0, 0).trimmed();
+ QUrl url = QUrl(line.section('\t', 1, 1).trimmed());
+ //qDebug()<<"function = "<<function<<", url = "<<url.toString();
+ m_helpHash.insert(function, url);
+ }
+ } else {
+ qWarning() << "Couldn't open reference file "
+ << file.fileName();
+ }
+ file.close();
}
void TraceLoader::scanTrace()
{
- QList<ApiTraceFrame*> frames;
- ApiTraceFrame *currentFrame = 0;
-
- Trace::Call *call;
- Trace::File::Offset startOffset;
- int numOfFrames = 0;
- int numOfCalls = 0;
- unsigned callNum = 0;
- int lastPercentReport = 0;
-
- startOffset = m_parser.currentOffset();
- callNum = m_parser.currentCallNumber();
-
- while ((call = m_parser.scan_call())) {
- ++numOfCalls;
-
- if (isCallAFrameMarker(call)) {
- Trace::File::Offset endOffset = m_parser.currentOffset();
- FrameOffset frameOffset(startOffset);
- frameOffset.numberOfCalls = numOfCalls;
- frameOffset.callNumber = callNum;
-
- currentFrame = new ApiTraceFrame();
- currentFrame->number = numOfFrames;
- currentFrame->setNumChildren(numOfCalls);
- frames.append(currentFrame);
-
- m_frameOffsets[numOfFrames] = frameOffset;
- ++numOfFrames;
-
- if (m_parser.percentRead() - lastPercentReport >= 5) {
- emit parsed(m_parser.percentRead());
- lastPercentReport = m_parser.percentRead();
- }
- startOffset = endOffset;
- callNum = m_parser.currentCallNumber();
- numOfCalls = 0;
- }
- //call->dump(std::cout, color);
- delete call;
- }
-
- if (numOfCalls) {
-// Trace::File::Offset endOffset = m_parser.currentOffset();
- FrameOffset frameOffset(startOffset);
- frameOffset.numberOfCalls = numOfCalls;
- frameOffset.callNumber = callNum;
-
- currentFrame = new ApiTraceFrame();
- currentFrame->number = numOfFrames;
- currentFrame->setNumChildren(numOfCalls);
- frames.append(currentFrame);
-
- m_frameOffsets[numOfFrames] = frameOffset;
- ++numOfFrames;
- }
-
- emit parsed(100);
-
- emit framesLoaded(frames);
+ QList<ApiTraceFrame*> frames;
+ ApiTraceFrame *currentFrame = 0;
+
+ Trace::Call *call;
+ Trace::ParseBookmark startBookmark;
+ int numOfFrames = 0;
+ int numOfCalls = 0;
+ int lastPercentReport = 0;
+
+ m_parser.getBookmark(startBookmark);
+
+ while ((call = m_parser.scan_call())) {
+ ++numOfCalls;
+
+ if (isCallAFrameMarker(call)) {
+ FrameBookmark frameBookmark(startBookmark);
+ frameBookmark.numberOfCalls = numOfCalls;
+
+ currentFrame = new ApiTraceFrame();
+ currentFrame->number = numOfFrames;
+ currentFrame->setNumChildren(numOfCalls);
+ currentFrame->setLastCallIndex(call->no);
+ frames.append(currentFrame);
+
+ m_createdFrames.append(currentFrame);
+ m_frameBookmarks[numOfFrames] = frameBookmark;
+ ++numOfFrames;
+
+ if (m_parser.percentRead() - lastPercentReport >= 5) {
+ emit parsed(m_parser.percentRead());
+ lastPercentReport = m_parser.percentRead();
+ }
+ m_parser.getBookmark(startBookmark);
+ numOfCalls = 0;
+ }
+ delete call;
+ }
+
+ if (numOfCalls) {
+ //Trace::File::Bookmark endBookmark = m_parser.currentBookmark();
+ FrameBookmark frameBookmark(startBookmark);
+ frameBookmark.numberOfCalls = numOfCalls;
+
+ currentFrame = new ApiTraceFrame();
+ currentFrame->number = numOfFrames;
+ currentFrame->setNumChildren(numOfCalls);
+ frames.append(currentFrame);
+
+ m_createdFrames.append(currentFrame);
+ m_frameBookmarks[numOfFrames] = frameBookmark;
+ ++numOfFrames;
+ }
+
+ emit parsed(100);
+
+ emit framesLoaded(frames);
}
void TraceLoader::parseTrace()
{
- QList<ApiTraceFrame*> frames;
- ApiTraceFrame *currentFrame = 0;
- int frameCount = 0;
- QVector<ApiTraceCall*> calls;
- quint64 binaryDataSize = 0;
-
- int lastPercentReport = 0;
-
- Trace::Call *call = m_parser.parse_call();
- while (call) {
- //std::cout << *call;
- if (!currentFrame) {
- currentFrame = new ApiTraceFrame();
- currentFrame->number = frameCount;
- ++frameCount;
- }
- ApiTraceCall *apiCall =
- apiCallFromTraceCall(call, m_helpHash, currentFrame, this);
- calls.append(apiCall);
- if (apiCall->hasBinaryData()) {
- QByteArray data =
- apiCall->arguments()[apiCall->binaryDataIndex()].toByteArray();
- binaryDataSize += data.size();
- }
- if (ApiTrace::isCallAFrameMarker(apiCall,
- m_frameMarker)) {
- calls.squeeze();
- currentFrame->setCalls(calls, binaryDataSize);
- calls.clear();
- frames.append(currentFrame);
- currentFrame = 0;
- binaryDataSize = 0;
- if (frames.count() >= FRAMES_TO_CACHE) {
- emit framesLoaded(frames);
- frames.clear();
- }
- if (m_parser.percentRead() - lastPercentReport >= 5) {
- qDebug()<<"emitting = " << m_parser.percentRead();
- emit parsed(m_parser.percentRead());
- lastPercentReport = m_parser.percentRead();
- }
- }
- delete call;
- call = m_parser.parse_call();
- }
-
- //last frames won't have markers
- // it's just a bunch of Delete calls for every object
- // after the last SwapBuffers
- if (currentFrame) {
- if (!frames.count()) {
- calls.squeeze();
- currentFrame->setCalls(calls, binaryDataSize);
- }
- frames.append(currentFrame);
- currentFrame = 0;
- }
- if (frames.count()) {
- emit framesLoaded(frames);
- }
+ QList<ApiTraceFrame*> frames;
+ ApiTraceFrame *currentFrame = 0;
+ int frameCount = 0;
+ QVector<ApiTraceCall*> calls;
+ quint64 binaryDataSize = 0;
+
+ int lastPercentReport = 0;
+
+ Trace::Call *call = m_parser.parse_call();
+ while (call) {
+ //std::cout << *call;
+ if (!currentFrame) {
+ currentFrame = new ApiTraceFrame();
+ currentFrame->number = frameCount;
+ ++frameCount;
+ }
+ ApiTraceCall *apiCall =
+ apiCallFromTraceCall(call, m_helpHash, currentFrame, this);
+ calls.append(apiCall);
+ if (apiCall->hasBinaryData()) {
+ QByteArray data =
+ apiCall->arguments()[apiCall->binaryDataIndex()].toByteArray();
+ binaryDataSize += data.size();
+ }
+ if (ApiTrace::isCallAFrameMarker(apiCall,
+ m_frameMarker)) {
+ calls.squeeze();
+ currentFrame->setCalls(calls, binaryDataSize);
+ calls.clear();
+ frames.append(currentFrame);
+ currentFrame = 0;
+ binaryDataSize = 0;
+ if (frames.count() >= FRAMES_TO_CACHE) {
+ emit framesLoaded(frames);
+ frames.clear();
+ }
+ if (m_parser.percentRead() - lastPercentReport >= 5) {
+ emit parsed(m_parser.percentRead());
+ lastPercentReport = m_parser.percentRead();
+ }
+ }
+ delete call;
+ call = m_parser.parse_call();
+ }
+
+ //last frames won't have markers
+ // it's just a bunch of Delete calls for every object
+ // after the last SwapBuffers
+ if (currentFrame) {
+ calls.squeeze();
+ currentFrame->setCalls(calls, binaryDataSize);
+ frames.append(currentFrame);
+ currentFrame = 0;
+ }
+ if (frames.count()) {
+ emit framesLoaded(frames);
+ }
}
m_enumSignatures[id] = signature;
}
+void TraceLoader::searchNext(int startFrame,
+ const QString &str,
+ Qt::CaseSensitivity sensitivity)
+{
+ Q_ASSERT(m_parser.supportsOffsets());
+ if (m_parser.supportsOffsets()) {
+ const FrameBookmark &frameBookmark = m_frameBookmarks[startFrame];
+ m_parser.setBookmark(frameBookmark.start);
+ Trace::Call *call = 0;
+ while ((call = m_parser.parse_call())) {
+
+ if (callContains(call, str, sensitivity)) {
+ unsigned frameIdx = callInFrame(call->no);
+ ApiTraceFrame *frame = m_createdFrames[frameIdx];
+ const QVector<ApiTraceCall*> calls =
+ fetchFrameContents(frame);
+ for (int i = 0; i < calls.count(); ++i) {
+ if (calls[i]->index() == call->no) {
+ emit searchResult(ApiTrace::SearchFound, calls[i]);
+ break;
+ }
+ }
+ delete call;
+ return;
+ }
+
+ delete call;
+ }
+ }
+ emit searchResult(ApiTrace::SearchNotFound, 0);
+}
+
+void TraceLoader::searchPrev(int startFrame,
+ const QString &str,
+ Qt::CaseSensitivity sensitivity)
+{
+ Q_ASSERT(m_parser.supportsOffsets());
+ if (m_parser.supportsOffsets()) {
+ Trace::Call *call = 0;
+ QList<Trace::Call*> frameCalls;
+ int frameIdx = startFrame;
+
+ const FrameBookmark &frameBookmark = m_frameBookmarks[frameIdx];
+ int numCallsToParse = frameBookmark.numberOfCalls;
+ m_parser.setBookmark(frameBookmark.start);
+
+ while ((call = m_parser.parse_call())) {
+
+ frameCalls.append(call);
+ --numCallsToParse;
+
+ if (numCallsToParse == 0) {
+ bool foundCall = searchCallsBackwards(frameCalls,
+ frameIdx,
+ str, sensitivity);
+
+ qDeleteAll(frameCalls);
+ frameCalls.clear();
+ if (foundCall) {
+ return;
+ }
+
+ --frameIdx;
+
+ if (frameIdx >= 0) {
+ const FrameBookmark &frameBookmark =
+ m_frameBookmarks[frameIdx];
+ m_parser.setBookmark(frameBookmark.start);
+ numCallsToParse = frameBookmark.numberOfCalls;
+ }
+ }
+ }
+ }
+ emit searchResult(ApiTrace::SearchNotFound, 0);
+}
+
+bool TraceLoader::searchCallsBackwards(const QList<Trace::Call*> &calls,
+ int frameIdx,
+ const QString &str,
+ Qt::CaseSensitivity sensitivity)
+{
+ for (int i = calls.count() - 1; i >= 0; --i) {
+ Trace::Call *call = calls[i];
+ if (callContains(call, str, sensitivity)) {
+ ApiTraceFrame *frame = m_createdFrames[frameIdx];
+ const QVector<ApiTraceCall*> apiCalls =
+ fetchFrameContents(frame);
+ for (int i = 0; i < apiCalls.count(); ++i) {
+ if (apiCalls[i]->index() == call->no) {
+ emit searchResult(ApiTrace::SearchFound, apiCalls[i]);
+ break;
+ }
+ }
+ return true;
+ }
+ }
+ return false;
+}
+
+int TraceLoader::callInFrame(int callIdx) const
+{
+ unsigned numCalls = 0;
+
+ for (int frameIdx = 0; frameIdx <= m_frameBookmarks.size(); ++frameIdx) {
+ const FrameBookmark &frameBookmark = m_frameBookmarks[frameIdx];
+ unsigned firstCall = numCalls;
+ unsigned endCall = numCalls + frameBookmark.numberOfCalls;
+ if (firstCall <= callIdx && endCall > callIdx) {
+ return frameIdx;
+ }
+ numCalls = endCall;
+ }
+ Q_ASSERT(!"call not in the trace");
+ return 0;
+}
+
+bool TraceLoader::callContains(Trace::Call *call,
+ const QString &str,
+ Qt::CaseSensitivity sensitivity)
+{
+ /*
+ * FIXME: do string comparison directly on Trace::Call
+ */
+ ApiTraceCall *apiCall = apiCallFromTraceCall(call, m_helpHash,
+ 0, this);
+ bool result = apiCall->contains(str, sensitivity);
+ delete apiCall;
+ return result;
+}
+
+QVector<ApiTraceCall*>
+TraceLoader::fetchFrameContents(ApiTraceFrame *currentFrame)
+{
+ Q_ASSERT(currentFrame);
+ if (m_parser.supportsOffsets()) {
+ unsigned frameIdx = currentFrame->number;
+ int numOfCalls = numberOfCallsInFrame(frameIdx);
+
+ if (numOfCalls) {
+ quint64 binaryDataSize = 0;
+ QVector<ApiTraceCall*> calls(numOfCalls);
+ const FrameBookmark &frameBookmark = m_frameBookmarks[frameIdx];
+
+ m_parser.setBookmark(frameBookmark.start);
+
+ Trace::Call *call;
+ int parsedCalls = 0;
+ while ((call = m_parser.parse_call())) {
+ ApiTraceCall *apiCall =
+ apiCallFromTraceCall(call, m_helpHash,
+ currentFrame, this);
+ calls[parsedCalls] = apiCall;
+ Q_ASSERT(calls[parsedCalls]);
+ if (apiCall->hasBinaryData()) {
+ QByteArray data =
+ apiCall->arguments()[
+ apiCall->binaryDataIndex()].toByteArray();
+ binaryDataSize += data.size();
+ }
+
+ ++parsedCalls;
+
+ delete call;
+
+ if (ApiTrace::isCallAFrameMarker(apiCall, m_frameMarker)) {
+ break;
+ }
+
+ }
+ assert(parsedCalls == numOfCalls);
+ Q_ASSERT(parsedCalls == calls.size());
+ calls.squeeze();
+
+ Q_ASSERT(parsedCalls == currentFrame->numChildrenToLoad());
+ emit frameContentsLoaded(currentFrame,
+ calls, binaryDataSize);
+ return calls;
+ }
+ }
+ return QVector<ApiTraceCall*>();
+}
+
+void TraceLoader::findFrameStart(ApiTraceFrame *frame)
+{
+ loadFrame(frame);
+ emit foundFrameStart(frame);
+}
+
+void TraceLoader::findFrameEnd(ApiTraceFrame *frame)
+{
+ loadFrame(frame);
+ emit foundFrameEnd(frame);
+}
+
+void TraceLoader::findCallIndex(int index)
+{
+ int frameIdx = callInFrame(index);
+ ApiTraceFrame *frame = m_createdFrames[frameIdx];
+ QVector<ApiTraceCall*> calls = fetchFrameContents(frame);
+ QVector<ApiTraceCall*>::const_iterator itr;
+ ApiTraceCall *call = 0;
+ for (itr = calls.constBegin(); itr != calls.constEnd(); ++itr) {
+ if ((*itr)->index() == index) {
+ call = *itr;
+ }
+ }
+ Q_ASSERT(call);
+ emit foundCallIndex(call);
+}
+
#include "traceloader.moc"