1 #include "traceloader.h"
6 #define FRAMES_TO_CACHE 100
9 apiCallFromTraceCall(const Trace::Call *call,
10 const QHash<QString, QUrl> &helpHash,
13 ApiTraceCall *apiCall = new ApiTraceCall(frame, call);
15 apiCall->setHelpUrl(helpHash.value(apiCall->name()));
20 TraceLoader::TraceLoader(ApiTrace *parent)
23 m_frameMarker(ApiTrace::FrameMarker_SwapBuffers)
27 TraceLoader::~TraceLoader()
32 void TraceLoader::loadTrace(const QString &filename)
34 if (m_helpHash.isEmpty()) {
38 if (!m_parser.open(filename.toLatin1())) {
39 qDebug() << "error: failed to open " << filename;
43 emit startedParsing();
45 if (m_parser.supportsOffsets()) {
48 //Load the entire file into memory
52 emit finishedParsing();
55 void TraceLoader::loadFrame(int frameIdx)
57 if (m_parser.supportsOffsets()) {
58 int numOfCalls = numberOfCallsInFrame(frameIdx);
60 const FrameOffset &frameOffset = m_frameOffsets[frameIdx];
61 std::vector<Trace::Call*> calls(numOfCalls);
62 m_parser.setCurrentOffset(frameOffset.start);
63 m_parser.setCurrentCallNumber(frameOffset.callNumber);
67 while ((call = m_parser.parse_call())) {
69 calls[parsedCalls] = call;
72 if (isCallAFrameMarker(call)) {
77 assert(parsedCalls == numOfCalls);
78 // emit parsedFrame();
83 void TraceLoader::setFrameMarker(ApiTrace::FrameMarker marker)
85 m_frameMarker = marker;
88 bool TraceLoader::isCallAFrameMarker(const Trace::Call *call) const
90 std::string name = call->name();
92 switch (m_frameMarker) {
93 case ApiTrace::FrameMarker_SwapBuffers:
94 return name.find("SwapBuffers") != std::string::npos ||
95 name == "CGLFlushDrawable" ||
96 name == "glFrameTerminatorGREMEDY";
98 case ApiTrace::FrameMarker_Flush:
99 return name == "glFlush";
101 case ApiTrace::FrameMarker_Finish:
102 return name == "glFinish";
104 case ApiTrace::FrameMarker_Clear:
105 return name == "glClear";
111 int TraceLoader::numberOfFrames() const
113 return m_frameOffsets.size();
116 int TraceLoader::numberOfCallsInFrame(int frameIdx) const
118 if (frameIdx > m_frameOffsets.size()) {
121 FrameOffsets::const_iterator itr =
122 m_frameOffsets.find(frameIdx);
123 return itr->numberOfCalls;
126 void TraceLoader::loadHelpFile()
128 QFile file(":/resources/glreference.tsv");
129 if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
131 while (!file.atEnd()) {
132 line = file.readLine();
133 QString function = line.section('\t', 0, 0).trimmed();
134 QUrl url = QUrl(line.section('\t', 1, 1).trimmed());
135 //qDebug()<<"function = "<<function<<", url = "<<url.toString();
136 m_helpHash.insert(function, url);
139 qWarning() << "Couldn't open reference file "
145 void TraceLoader::scanTrace()
147 QList<ApiTraceFrame*> frames;
148 ApiTraceFrame *currentFrame = 0;
151 Trace::File::Offset startOffset;
154 unsigned callNum = 0;
155 int lastPercentReport = 0;
157 startOffset = m_parser.currentOffset();
158 callNum = m_parser.currentCallNumber();
160 while ((call = m_parser.scan_call())) {
163 if (isCallAFrameMarker(call)) {
164 Trace::File::Offset endOffset = m_parser.currentOffset();
165 FrameOffset frameOffset(startOffset);
166 frameOffset.numberOfCalls = numOfCalls;
167 frameOffset.callNumber = callNum;
169 currentFrame = new ApiTraceFrame(m_trace);
170 currentFrame->number = numOfFrames;
171 currentFrame->setNumChildren(numOfCalls);
172 frames.append(currentFrame);
174 m_frameOffsets[numOfFrames] = frameOffset;
177 if (m_parser.percentRead() - lastPercentReport >= 5) {
178 emit parsed(m_parser.percentRead());
179 lastPercentReport = m_parser.percentRead();
181 startOffset = endOffset;
182 callNum = m_parser.currentCallNumber();
185 //call->dump(std::cout, color);
190 // Trace::File::Offset endOffset = m_parser.currentOffset();
191 FrameOffset frameOffset(startOffset);
192 frameOffset.numberOfCalls = numOfCalls;
193 frameOffset.callNumber = callNum;
195 currentFrame = new ApiTraceFrame(m_trace);
196 currentFrame->number = numOfFrames;
197 currentFrame->setNumChildren(numOfCalls);
198 frames.append(currentFrame);
200 m_frameOffsets[numOfFrames] = frameOffset;
206 emit framesLoaded(frames);
209 void TraceLoader::parseTrace()
211 QList<ApiTraceFrame*> frames;
212 ApiTraceFrame *currentFrame = 0;
214 QVector<ApiTraceCall*> calls;
215 quint64 binaryDataSize = 0;
217 int lastPercentReport = 0;
219 Trace::Call *call = m_parser.parse_call();
221 //std::cout << *call;
223 currentFrame = new ApiTraceFrame(m_trace);
224 currentFrame->number = frameCount;
227 ApiTraceCall *apiCall =
228 apiCallFromTraceCall(call, m_helpHash, currentFrame);
229 calls.append(apiCall);
230 if (apiCall->hasBinaryData()) {
232 apiCall->arguments()[apiCall->binaryDataIndex()].toByteArray();
233 binaryDataSize += data.size();
235 if (ApiTrace::isCallAFrameMarker(apiCall,
238 currentFrame->setCalls(calls, binaryDataSize);
240 frames.append(currentFrame);
243 if (frames.count() >= FRAMES_TO_CACHE) {
244 emit framesLoaded(frames);
247 if (m_parser.percentRead() - lastPercentReport >= 5) {
248 emit parsed(m_parser.percentRead());
249 lastPercentReport = m_parser.percentRead();
253 call = m_parser.parse_call();
256 //last frames won't have markers
257 // it's just a bunch of Delete calls for every object
258 // after the last SwapBuffers
260 if (!frames.count()) {
262 currentFrame->setCalls(calls, binaryDataSize);
264 frames.append(currentFrame);
267 if (frames.count()) {
268 emit framesLoaded(frames);
273 #include "traceloader.moc"