1 #include "traceloader.h"
7 #define FRAMES_TO_CACHE 100
10 apiCallFromTraceCall(const Trace::Call *call,
11 const QHash<QString, QUrl> &helpHash,
15 ApiTraceCall *apiCall = new ApiTraceCall(frame, loader, call);
17 apiCall->setHelpUrl(helpHash.value(apiCall->name()));
22 TraceLoader::TraceLoader(QObject *parent)
24 m_frameMarker(ApiTrace::FrameMarker_SwapBuffers)
28 TraceLoader::~TraceLoader()
33 void TraceLoader::loadTrace(const QString &filename)
35 if (m_helpHash.isEmpty()) {
39 if (!m_parser.open(filename.toLatin1())) {
40 qDebug() << "error: failed to open " << filename;
43 qDebug()<<"load trace with "<<filename;
44 emit startedParsing();
46 qDebug() <<"\t support offsets = "<<m_parser.supportsOffsets();
47 if (m_parser.supportsOffsets()) {
50 //Load the entire file into memory
54 emit finishedParsing();
57 void TraceLoader::loadFrame(ApiTraceFrame *currentFrame)
59 if (m_parser.supportsOffsets()) {
60 unsigned frameIdx = currentFrame->number;
61 int numOfCalls = numberOfCallsInFrame(frameIdx);
64 quint64 binaryDataSize = 0;
65 QVector<ApiTraceCall*> calls(numOfCalls);
66 const FrameOffset &frameOffset = m_frameOffsets[frameIdx];
68 m_parser.setCurrentOffset(frameOffset.start);
69 m_parser.setCurrentCallNumber(frameOffset.callNumber);
73 while ((call = m_parser.parse_call())) {
74 ApiTraceCall *apiCall =
75 apiCallFromTraceCall(call, m_helpHash,
77 calls[parsedCalls] = apiCall;
78 Q_ASSERT(calls[parsedCalls]);
79 if (apiCall->hasBinaryData()) {
82 apiCall->binaryDataIndex()].toByteArray();
83 binaryDataSize += data.size();
90 if (ApiTrace::isCallAFrameMarker(apiCall, m_frameMarker)) {
95 assert(parsedCalls == numOfCalls);
96 Q_ASSERT(parsedCalls == calls.size());
97 Q_ASSERT(parsedCalls == currentFrame->numChildrenToLoad());
99 currentFrame->setCalls(calls, binaryDataSize);
100 emit frameLoaded(currentFrame);
105 void TraceLoader::setFrameMarker(ApiTrace::FrameMarker marker)
107 m_frameMarker = marker;
110 bool TraceLoader::isCallAFrameMarker(const Trace::Call *call) const
112 std::string name = call->name();
114 switch (m_frameMarker) {
115 case ApiTrace::FrameMarker_SwapBuffers:
116 return name.find("SwapBuffers") != std::string::npos ||
117 name == "CGLFlushDrawable" ||
118 name == "glFrameTerminatorGREMEDY";
120 case ApiTrace::FrameMarker_Flush:
121 return name == "glFlush";
123 case ApiTrace::FrameMarker_Finish:
124 return name == "glFinish";
126 case ApiTrace::FrameMarker_Clear:
127 return name == "glClear";
133 int TraceLoader::numberOfFrames() const
135 return m_frameOffsets.size();
138 int TraceLoader::numberOfCallsInFrame(int frameIdx) const
140 if (frameIdx > m_frameOffsets.size()) {
143 FrameOffsets::const_iterator itr =
144 m_frameOffsets.find(frameIdx);
145 return itr->numberOfCalls;
148 void TraceLoader::loadHelpFile()
150 QFile file(":/resources/glreference.tsv");
151 if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
153 while (!file.atEnd()) {
154 line = file.readLine();
155 QString function = line.section('\t', 0, 0).trimmed();
156 QUrl url = QUrl(line.section('\t', 1, 1).trimmed());
157 //qDebug()<<"function = "<<function<<", url = "<<url.toString();
158 m_helpHash.insert(function, url);
161 qWarning() << "Couldn't open reference file "
167 void TraceLoader::scanTrace()
169 QList<ApiTraceFrame*> frames;
170 ApiTraceFrame *currentFrame = 0;
173 Trace::File::Offset startOffset;
176 unsigned callNum = 0;
177 int lastPercentReport = 0;
179 startOffset = m_parser.currentOffset();
180 callNum = m_parser.currentCallNumber();
182 while ((call = m_parser.scan_call())) {
185 if (isCallAFrameMarker(call)) {
186 Trace::File::Offset endOffset = m_parser.currentOffset();
187 FrameOffset frameOffset(startOffset);
188 frameOffset.numberOfCalls = numOfCalls;
189 frameOffset.callNumber = callNum;
191 currentFrame = new ApiTraceFrame();
192 currentFrame->number = numOfFrames;
193 currentFrame->setNumChildren(numOfCalls);
194 frames.append(currentFrame);
196 m_frameOffsets[numOfFrames] = frameOffset;
199 if (m_parser.percentRead() - lastPercentReport >= 5) {
200 emit parsed(m_parser.percentRead());
201 lastPercentReport = m_parser.percentRead();
203 startOffset = endOffset;
204 callNum = m_parser.currentCallNumber();
211 //Trace::File::Offset endOffset = m_parser.currentOffset();
212 FrameOffset frameOffset(startOffset);
213 frameOffset.numberOfCalls = numOfCalls;
214 frameOffset.callNumber = callNum;
216 currentFrame = new ApiTraceFrame();
217 currentFrame->number = numOfFrames;
218 currentFrame->setNumChildren(numOfCalls);
219 frames.append(currentFrame);
221 m_frameOffsets[numOfFrames] = frameOffset;
227 emit framesLoaded(frames);
230 void TraceLoader::parseTrace()
232 QList<ApiTraceFrame*> frames;
233 ApiTraceFrame *currentFrame = 0;
235 QVector<ApiTraceCall*> calls;
236 quint64 binaryDataSize = 0;
238 int lastPercentReport = 0;
240 Trace::Call *call = m_parser.parse_call();
242 //std::cout << *call;
244 currentFrame = new ApiTraceFrame();
245 currentFrame->number = frameCount;
248 ApiTraceCall *apiCall =
249 apiCallFromTraceCall(call, m_helpHash, currentFrame, this);
250 calls.append(apiCall);
251 if (apiCall->hasBinaryData()) {
253 apiCall->arguments()[apiCall->binaryDataIndex()].toByteArray();
254 binaryDataSize += data.size();
256 if (ApiTrace::isCallAFrameMarker(apiCall,
259 currentFrame->setCalls(calls, binaryDataSize);
261 frames.append(currentFrame);
264 if (frames.count() >= FRAMES_TO_CACHE) {
265 emit framesLoaded(frames);
268 if (m_parser.percentRead() - lastPercentReport >= 5) {
269 emit parsed(m_parser.percentRead());
270 lastPercentReport = m_parser.percentRead();
274 call = m_parser.parse_call();
277 //last frames won't have markers
278 // it's just a bunch of Delete calls for every object
279 // after the last SwapBuffers
282 currentFrame->setCalls(calls, binaryDataSize);
283 frames.append(currentFrame);
286 if (frames.count()) {
287 emit framesLoaded(frames);
292 ApiTraceCallSignature * TraceLoader::signature(unsigned id)
294 if (id >= m_signatures.count()) {
295 m_signatures.resize(id + 1);
298 return m_signatures[id];
302 void TraceLoader::addSignature(unsigned id, ApiTraceCallSignature *signature)
304 m_signatures[id] = signature;
307 ApiTraceEnumSignature * TraceLoader::enumSignature(unsigned id)
309 if (id >= m_enumSignatures.count()) {
310 m_enumSignatures.resize(id + 1);
313 return m_enumSignatures[id];
317 void TraceLoader::addEnumSignature(unsigned id, ApiTraceEnumSignature *signature)
319 m_enumSignatures[id] = signature;
322 #include "traceloader.moc"