blob: b6eba6a0247af29645d54b4f76c20b67f255336c [file] [log] [blame]
Zack Rusin20b1f6d2011-09-06 11:50:07 -04001#include "traceloader.h"
2
3#include <QDebug>
4#include <QFile>
5
6#define FRAMES_TO_CACHE 100
7
8static ApiTraceCall *
9apiCallFromTraceCall(const Trace::Call *call,
10 const QHash<QString, QUrl> &helpHash,
Zack Rusinebf971e2011-09-06 17:44:43 -040011 ApiTraceFrame *frame,
12 TraceLoader *loader)
Zack Rusin20b1f6d2011-09-06 11:50:07 -040013{
Zack Rusinebf971e2011-09-06 17:44:43 -040014 ApiTraceCall *apiCall = new ApiTraceCall(frame, loader, call);
Zack Rusin20b1f6d2011-09-06 11:50:07 -040015
16 apiCall->setHelpUrl(helpHash.value(apiCall->name()));
17
18 return apiCall;
19}
20
Zack Rusinebf971e2011-09-06 17:44:43 -040021TraceLoader::TraceLoader(QObject *parent)
Zack Rusin20b1f6d2011-09-06 11:50:07 -040022 : QObject(parent),
Zack Rusin20b1f6d2011-09-06 11:50:07 -040023 m_frameMarker(ApiTrace::FrameMarker_SwapBuffers)
24{
25}
26
27TraceLoader::~TraceLoader()
28{
29 m_parser.close();
30}
31
32void TraceLoader::loadTrace(const QString &filename)
33{
34 if (m_helpHash.isEmpty()) {
35 loadHelpFile();
36 }
37
38 if (!m_parser.open(filename.toLatin1())) {
39 qDebug() << "error: failed to open " << filename;
40 return;
41 }
Zack Rusinebf971e2011-09-06 17:44:43 -040042 qDebug()<<"load trace with "<<filename;
Zack Rusin20b1f6d2011-09-06 11:50:07 -040043 emit startedParsing();
44
Zack Rusinebf971e2011-09-06 17:44:43 -040045 qDebug() <<"\t support offsets = "<<m_parser.supportsOffsets();
Zack Rusin20b1f6d2011-09-06 11:50:07 -040046 if (m_parser.supportsOffsets()) {
Zack Rusinac92a212011-09-06 18:25:34 -040047 scanTrace();
Zack Rusin20b1f6d2011-09-06 11:50:07 -040048 } else {
Zack Rusinac92a212011-09-06 18:25:34 -040049 //Load the entire file into memory
50 parseTrace();
Zack Rusin20b1f6d2011-09-06 11:50:07 -040051 }
52
53 emit finishedParsing();
54}
55
56void TraceLoader::loadFrame(int frameIdx)
57{
58 if (m_parser.supportsOffsets()) {
59 int numOfCalls = numberOfCallsInFrame(frameIdx);
60 if (numOfCalls) {
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);
65
66 Trace::Call *call;
67 int parsedCalls = 0;
68 while ((call = m_parser.parse_call())) {
69
70 calls[parsedCalls] = call;
71 ++parsedCalls;
72
73 if (isCallAFrameMarker(call)) {
74 break;
75 }
76
77 }
78 assert(parsedCalls == numOfCalls);
Zack Rusinac92a212011-09-06 18:25:34 -040079 // emit parsedFrame();
Zack Rusin20b1f6d2011-09-06 11:50:07 -040080 }
81 }
82}
83
84void TraceLoader::setFrameMarker(ApiTrace::FrameMarker marker)
85{
86 m_frameMarker = marker;
87}
88
89bool TraceLoader::isCallAFrameMarker(const Trace::Call *call) const
90{
91 std::string name = call->name();
92
93 switch (m_frameMarker) {
94 case ApiTrace::FrameMarker_SwapBuffers:
Zack Rusinac92a212011-09-06 18:25:34 -040095 return name.find("SwapBuffers") != std::string::npos ||
96 name == "CGLFlushDrawable" ||
97 name == "glFrameTerminatorGREMEDY";
98 break;
Zack Rusin20b1f6d2011-09-06 11:50:07 -040099 case ApiTrace::FrameMarker_Flush:
Zack Rusinac92a212011-09-06 18:25:34 -0400100 return name == "glFlush";
101 break;
Zack Rusin20b1f6d2011-09-06 11:50:07 -0400102 case ApiTrace::FrameMarker_Finish:
Zack Rusinac92a212011-09-06 18:25:34 -0400103 return name == "glFinish";
104 break;
Zack Rusin20b1f6d2011-09-06 11:50:07 -0400105 case ApiTrace::FrameMarker_Clear:
Zack Rusinac92a212011-09-06 18:25:34 -0400106 return name == "glClear";
107 break;
Zack Rusin20b1f6d2011-09-06 11:50:07 -0400108 }
109 return false;
110}
111
112int TraceLoader::numberOfFrames() const
113{
114 return m_frameOffsets.size();
115}
116
117int TraceLoader::numberOfCallsInFrame(int frameIdx) const
118{
119 if (frameIdx > m_frameOffsets.size()) {
120 return 0;
121 }
122 FrameOffsets::const_iterator itr =
Zack Rusinac92a212011-09-06 18:25:34 -0400123 m_frameOffsets.find(frameIdx);
Zack Rusin20b1f6d2011-09-06 11:50:07 -0400124 return itr->numberOfCalls;
125}
126
127void TraceLoader::loadHelpFile()
128{
Zack Rusinac92a212011-09-06 18:25:34 -0400129 QFile file(":/resources/glreference.tsv");
130 if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
131 QString line;
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);
138 }
139 } else {
140 qWarning() << "Couldn't open reference file "
141 << file.fileName();
142 }
143 file.close();
Zack Rusin20b1f6d2011-09-06 11:50:07 -0400144}
145
146void TraceLoader::scanTrace()
147{
Zack Rusinac92a212011-09-06 18:25:34 -0400148 QList<ApiTraceFrame*> frames;
149 ApiTraceFrame *currentFrame = 0;
Zack Rusin20b1f6d2011-09-06 11:50:07 -0400150
Zack Rusinac92a212011-09-06 18:25:34 -0400151 Trace::Call *call;
152 Trace::File::Offset startOffset;
153 int numOfFrames = 0;
154 int numOfCalls = 0;
155 unsigned callNum = 0;
156 int lastPercentReport = 0;
Zack Rusin20b1f6d2011-09-06 11:50:07 -0400157
Zack Rusinac92a212011-09-06 18:25:34 -0400158 startOffset = m_parser.currentOffset();
159 callNum = m_parser.currentCallNumber();
Zack Rusin20b1f6d2011-09-06 11:50:07 -0400160
Zack Rusinac92a212011-09-06 18:25:34 -0400161 while ((call = m_parser.scan_call())) {
162 ++numOfCalls;
Zack Rusin20b1f6d2011-09-06 11:50:07 -0400163
Zack Rusinac92a212011-09-06 18:25:34 -0400164 if (isCallAFrameMarker(call)) {
165 Trace::File::Offset endOffset = m_parser.currentOffset();
166 FrameOffset frameOffset(startOffset);
167 frameOffset.numberOfCalls = numOfCalls;
168 frameOffset.callNumber = callNum;
Zack Rusin20b1f6d2011-09-06 11:50:07 -0400169
Zack Rusinac92a212011-09-06 18:25:34 -0400170 currentFrame = new ApiTraceFrame();
171 currentFrame->number = numOfFrames;
172 currentFrame->setNumChildren(numOfCalls);
173 frames.append(currentFrame);
Zack Rusin20b1f6d2011-09-06 11:50:07 -0400174
Zack Rusinac92a212011-09-06 18:25:34 -0400175 m_frameOffsets[numOfFrames] = frameOffset;
176 ++numOfFrames;
Zack Rusin20b1f6d2011-09-06 11:50:07 -0400177
Zack Rusinac92a212011-09-06 18:25:34 -0400178 if (m_parser.percentRead() - lastPercentReport >= 5) {
179 emit parsed(m_parser.percentRead());
180 lastPercentReport = m_parser.percentRead();
181 }
182 startOffset = endOffset;
183 callNum = m_parser.currentCallNumber();
184 numOfCalls = 0;
185 }
186 //call->dump(std::cout, color);
187 delete call;
188 }
Zack Rusin20b1f6d2011-09-06 11:50:07 -0400189
Zack Rusinac92a212011-09-06 18:25:34 -0400190 if (numOfCalls) {
191 // Trace::File::Offset endOffset = m_parser.currentOffset();
192 FrameOffset frameOffset(startOffset);
193 frameOffset.numberOfCalls = numOfCalls;
194 frameOffset.callNumber = callNum;
Zack Rusin20b1f6d2011-09-06 11:50:07 -0400195
Zack Rusinac92a212011-09-06 18:25:34 -0400196 currentFrame = new ApiTraceFrame();
197 currentFrame->number = numOfFrames;
198 currentFrame->setNumChildren(numOfCalls);
199 frames.append(currentFrame);
Zack Rusin20b1f6d2011-09-06 11:50:07 -0400200
Zack Rusinac92a212011-09-06 18:25:34 -0400201 m_frameOffsets[numOfFrames] = frameOffset;
202 ++numOfFrames;
203 }
Zack Rusin20b1f6d2011-09-06 11:50:07 -0400204
Zack Rusinac92a212011-09-06 18:25:34 -0400205 emit parsed(100);
Zack Rusin20b1f6d2011-09-06 11:50:07 -0400206
Zack Rusinac92a212011-09-06 18:25:34 -0400207 emit framesLoaded(frames);
Zack Rusin20b1f6d2011-09-06 11:50:07 -0400208}
209
210void TraceLoader::parseTrace()
211{
Zack Rusinac92a212011-09-06 18:25:34 -0400212 QList<ApiTraceFrame*> frames;
213 ApiTraceFrame *currentFrame = 0;
214 int frameCount = 0;
215 QVector<ApiTraceCall*> calls;
216 quint64 binaryDataSize = 0;
Zack Rusin20b1f6d2011-09-06 11:50:07 -0400217
Zack Rusinac92a212011-09-06 18:25:34 -0400218 int lastPercentReport = 0;
Zack Rusin20b1f6d2011-09-06 11:50:07 -0400219
Zack Rusinac92a212011-09-06 18:25:34 -0400220 Trace::Call *call = m_parser.parse_call();
221 while (call) {
222 //std::cout << *call;
223 if (!currentFrame) {
224 currentFrame = new ApiTraceFrame();
225 currentFrame->number = frameCount;
226 ++frameCount;
227 }
228 ApiTraceCall *apiCall =
229 apiCallFromTraceCall(call, m_helpHash, currentFrame, this);
230 calls.append(apiCall);
231 if (apiCall->hasBinaryData()) {
232 QByteArray data =
233 apiCall->arguments()[apiCall->binaryDataIndex()].toByteArray();
234 binaryDataSize += data.size();
235 }
236 if (ApiTrace::isCallAFrameMarker(apiCall,
237 m_frameMarker)) {
238 calls.squeeze();
239 currentFrame->setCalls(calls, binaryDataSize);
240 calls.clear();
241 frames.append(currentFrame);
242 currentFrame = 0;
243 binaryDataSize = 0;
244 if (frames.count() >= FRAMES_TO_CACHE) {
245 emit framesLoaded(frames);
246 frames.clear();
247 }
248 if (m_parser.percentRead() - lastPercentReport >= 5) {
249 emit parsed(m_parser.percentRead());
250 lastPercentReport = m_parser.percentRead();
251 }
252 }
253 delete call;
254 call = m_parser.parse_call();
255 }
Zack Rusin20b1f6d2011-09-06 11:50:07 -0400256
Zack Rusinac92a212011-09-06 18:25:34 -0400257 //last frames won't have markers
258 // it's just a bunch of Delete calls for every object
259 // after the last SwapBuffers
260 if (currentFrame) {
261 calls.squeeze();
262 currentFrame->setCalls(calls, binaryDataSize);
263 frames.append(currentFrame);
264 currentFrame = 0;
265 }
266 if (frames.count()) {
267 emit framesLoaded(frames);
268 }
Zack Rusin20b1f6d2011-09-06 11:50:07 -0400269}
270
271
Zack Rusinebf971e2011-09-06 17:44:43 -0400272ApiTraceCallSignature * TraceLoader::signature(unsigned id)
273{
274 if (id >= m_signatures.count()) {
275 m_signatures.resize(id + 1);
276 return NULL;
277 } else {
278 return m_signatures[id];
279 }
280}
281
282void TraceLoader::addSignature(unsigned id, ApiTraceCallSignature *signature)
283{
284 m_signatures[id] = signature;
285}
286
287ApiTraceEnumSignature * TraceLoader::enumSignature(unsigned id)
288{
289 if (id >= m_enumSignatures.count()) {
290 m_enumSignatures.resize(id + 1);
291 return NULL;
292 } else {
293 return m_enumSignatures[id];
294 }
295}
296
297void TraceLoader::addEnumSignature(unsigned id, ApiTraceEnumSignature *signature)
298{
299 m_enumSignatures[id] = signature;
300}
301
Zack Rusin20b1f6d2011-09-06 11:50:07 -0400302#include "traceloader.moc"