1 #include "traceloader.h"
6 #define FRAMES_TO_CACHE 100
9 apiCallFromTraceCall(const Trace::Call *call,
10 const QHash<QString, QUrl> &helpHash,
14 ApiTraceCall *apiCall = new ApiTraceCall(frame, loader, call);
16 apiCall->setHelpUrl(helpHash.value(apiCall->name()));
21 TraceLoader::TraceLoader(QObject *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;
42 qDebug()<<"load trace with "<<filename;
43 emit startedParsing();
45 qDebug() <<"\t support offsets = "<<m_parser.supportsOffsets();
46 if (m_parser.supportsOffsets()) {
49 //Load the entire file into memory
53 emit finishedParsing();
56 void TraceLoader::loadFrame(int frameIdx)
58 if (m_parser.supportsOffsets()) {
59 int numOfCalls = numberOfCallsInFrame(frameIdx);
61 const FrameOffset &frameOffset = m_frameOffsets[frameIdx];
62 std::vector<Trace::Call*> calls(numOfCalls);
63 m_parser.setCurrentOffset(frameOffset.start);
64 m_parser.setCurrentCallNumber(frameOffset.callNumber);
68 while ((call = m_parser.parse_call())) {
70 calls[parsedCalls] = call;
73 if (isCallAFrameMarker(call)) {
78 assert(parsedCalls == numOfCalls);
79 // emit parsedFrame();
84 void TraceLoader::setFrameMarker(ApiTrace::FrameMarker marker)
86 m_frameMarker = marker;
89 bool TraceLoader::isCallAFrameMarker(const Trace::Call *call) const
91 std::string name = call->name();
93 switch (m_frameMarker) {
94 case ApiTrace::FrameMarker_SwapBuffers:
95 return name.find("SwapBuffers") != std::string::npos ||
96 name == "CGLFlushDrawable" ||
97 name == "glFrameTerminatorGREMEDY";
99 case ApiTrace::FrameMarker_Flush:
100 return name == "glFlush";
102 case ApiTrace::FrameMarker_Finish:
103 return name == "glFinish";
105 case ApiTrace::FrameMarker_Clear:
106 return name == "glClear";
112 int TraceLoader::numberOfFrames() const
114 return m_frameOffsets.size();
117 int TraceLoader::numberOfCallsInFrame(int frameIdx) const
119 if (frameIdx > m_frameOffsets.size()) {
122 FrameOffsets::const_iterator itr =
123 m_frameOffsets.find(frameIdx);
124 return itr->numberOfCalls;
127 void TraceLoader::loadHelpFile()
129 QFile file(":/resources/glreference.tsv");
130 if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
132 while (!file.atEnd()) {
133 line = file.readLine();
134 QString function = line.section('\t', 0, 0).trimmed();
135 QUrl url = QUrl(line.section('\t', 1, 1).trimmed());
136 //qDebug()<<"function = "<<function<<", url = "<<url.toString();
137 m_helpHash.insert(function, url);
140 qWarning() << "Couldn't open reference file "
146 void TraceLoader::scanTrace()
148 QList<ApiTraceFrame*> frames;
149 ApiTraceFrame *currentFrame = 0;
152 Trace::File::Offset startOffset;
155 unsigned callNum = 0;
156 int lastPercentReport = 0;
158 startOffset = m_parser.currentOffset();
159 callNum = m_parser.currentCallNumber();
161 while ((call = m_parser.scan_call())) {
164 if (isCallAFrameMarker(call)) {
165 Trace::File::Offset endOffset = m_parser.currentOffset();
166 FrameOffset frameOffset(startOffset);
167 frameOffset.numberOfCalls = numOfCalls;
168 frameOffset.callNumber = callNum;
170 currentFrame = new ApiTraceFrame();
171 currentFrame->number = numOfFrames;
172 currentFrame->setNumChildren(numOfCalls);
173 frames.append(currentFrame);
175 m_frameOffsets[numOfFrames] = frameOffset;
178 if (m_parser.percentRead() - lastPercentReport >= 5) {
179 emit parsed(m_parser.percentRead());
180 lastPercentReport = m_parser.percentRead();
182 startOffset = endOffset;
183 callNum = m_parser.currentCallNumber();
186 //call->dump(std::cout, color);
191 // Trace::File::Offset endOffset = m_parser.currentOffset();
192 FrameOffset frameOffset(startOffset);
193 frameOffset.numberOfCalls = numOfCalls;
194 frameOffset.callNumber = callNum;
196 currentFrame = new ApiTraceFrame();
197 currentFrame->number = numOfFrames;
198 currentFrame->setNumChildren(numOfCalls);
199 frames.append(currentFrame);
201 m_frameOffsets[numOfFrames] = frameOffset;
207 emit framesLoaded(frames);
210 void TraceLoader::parseTrace()
212 QList<ApiTraceFrame*> frames;
213 ApiTraceFrame *currentFrame = 0;
215 QVector<ApiTraceCall*> calls;
216 quint64 binaryDataSize = 0;
218 int lastPercentReport = 0;
220 Trace::Call *call = m_parser.parse_call();
222 //std::cout << *call;
224 currentFrame = new ApiTraceFrame();
225 currentFrame->number = frameCount;
228 ApiTraceCall *apiCall =
229 apiCallFromTraceCall(call, m_helpHash, currentFrame, this);
230 calls.append(apiCall);
231 if (apiCall->hasBinaryData()) {
233 apiCall->arguments()[apiCall->binaryDataIndex()].toByteArray();
234 binaryDataSize += data.size();
236 if (ApiTrace::isCallAFrameMarker(apiCall,
239 currentFrame->setCalls(calls, binaryDataSize);
241 frames.append(currentFrame);
244 if (frames.count() >= FRAMES_TO_CACHE) {
245 emit framesLoaded(frames);
248 if (m_parser.percentRead() - lastPercentReport >= 5) {
249 emit parsed(m_parser.percentRead());
250 lastPercentReport = m_parser.percentRead();
254 call = m_parser.parse_call();
257 //last frames won't have markers
258 // it's just a bunch of Delete calls for every object
259 // after the last SwapBuffers
262 currentFrame->setCalls(calls, binaryDataSize);
263 frames.append(currentFrame);
266 if (frames.count()) {
267 emit framesLoaded(frames);
272 ApiTraceCallSignature * TraceLoader::signature(unsigned id)
274 if (id >= m_signatures.count()) {
275 m_signatures.resize(id + 1);
278 return m_signatures[id];
282 void TraceLoader::addSignature(unsigned id, ApiTraceCallSignature *signature)
284 m_signatures[id] = signature;
287 ApiTraceEnumSignature * TraceLoader::enumSignature(unsigned id)
289 if (id >= m_enumSignatures.count()) {
290 m_enumSignatures.resize(id + 1);
293 return m_enumSignatures[id];
297 void TraceLoader::addEnumSignature(unsigned id, ApiTraceEnumSignature *signature)
299 m_enumSignatures[id] = signature;
302 #include "traceloader.moc"