]> git.cworth.org Git - apitrace/blob - gui/traceloader.cpp
Fix indention.
[apitrace] / gui / traceloader.cpp
1 #include "traceloader.h"
2
3 #include <QDebug>
4 #include <QFile>
5
6 #define FRAMES_TO_CACHE 100
7
8 static ApiTraceCall *
9 apiCallFromTraceCall(const Trace::Call *call,
10                      const QHash<QString, QUrl> &helpHash,
11                      ApiTraceFrame *frame,
12                      TraceLoader *loader)
13 {
14     ApiTraceCall *apiCall = new ApiTraceCall(frame, loader, call);
15
16     apiCall->setHelpUrl(helpHash.value(apiCall->name()));
17
18     return apiCall;
19 }
20
21 TraceLoader::TraceLoader(QObject *parent)
22     : QObject(parent),
23       m_frameMarker(ApiTrace::FrameMarker_SwapBuffers)
24 {
25 }
26
27 TraceLoader::~TraceLoader()
28 {
29     m_parser.close();
30 }
31
32 void 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     }
42     qDebug()<<"load trace with "<<filename;
43     emit startedParsing();
44
45     qDebug() <<"\t support offsets = "<<m_parser.supportsOffsets();
46     if (m_parser.supportsOffsets()) {
47         scanTrace();
48     } else {
49         //Load the entire file into memory
50         parseTrace();
51     }
52
53     emit finishedParsing();
54 }
55
56 void 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);
79             //            emit parsedFrame();
80         }
81     }
82 }
83
84 void TraceLoader::setFrameMarker(ApiTrace::FrameMarker marker)
85 {
86     m_frameMarker = marker;
87 }
88
89 bool TraceLoader::isCallAFrameMarker(const Trace::Call *call) const
90 {
91     std::string name = call->name();
92
93     switch (m_frameMarker) {
94     case ApiTrace::FrameMarker_SwapBuffers:
95         return  name.find("SwapBuffers") != std::string::npos ||
96                 name == "CGLFlushDrawable" ||
97                 name == "glFrameTerminatorGREMEDY";
98         break;
99     case ApiTrace::FrameMarker_Flush:
100         return name == "glFlush";
101         break;
102     case ApiTrace::FrameMarker_Finish:
103         return name == "glFinish";
104         break;
105     case ApiTrace::FrameMarker_Clear:
106         return name == "glClear";
107         break;
108     }
109     return false;
110 }
111
112 int TraceLoader::numberOfFrames() const
113 {
114     return m_frameOffsets.size();
115 }
116
117 int TraceLoader::numberOfCallsInFrame(int frameIdx) const
118 {
119     if (frameIdx > m_frameOffsets.size()) {
120         return 0;
121     }
122     FrameOffsets::const_iterator itr =
123             m_frameOffsets.find(frameIdx);
124     return itr->numberOfCalls;
125 }
126
127 void TraceLoader::loadHelpFile()
128 {
129     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();
144 }
145
146 void TraceLoader::scanTrace()
147 {
148     QList<ApiTraceFrame*> frames;
149     ApiTraceFrame *currentFrame = 0;
150
151     Trace::Call *call;
152     Trace::File::Offset startOffset;
153     int numOfFrames = 0;
154     int numOfCalls = 0;
155     unsigned callNum = 0;
156     int lastPercentReport = 0;
157
158     startOffset = m_parser.currentOffset();
159     callNum = m_parser.currentCallNumber();
160
161     while ((call = m_parser.scan_call())) {
162         ++numOfCalls;
163
164         if (isCallAFrameMarker(call)) {
165             Trace::File::Offset endOffset = m_parser.currentOffset();
166             FrameOffset frameOffset(startOffset);
167             frameOffset.numberOfCalls = numOfCalls;
168             frameOffset.callNumber = callNum;
169
170             currentFrame = new ApiTraceFrame();
171             currentFrame->number = numOfFrames;
172             currentFrame->setNumChildren(numOfCalls);
173             frames.append(currentFrame);
174
175             m_frameOffsets[numOfFrames] = frameOffset;
176             ++numOfFrames;
177
178             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     }
189
190     if (numOfCalls) {
191         //      Trace::File::Offset endOffset = m_parser.currentOffset();
192         FrameOffset frameOffset(startOffset);
193         frameOffset.numberOfCalls = numOfCalls;
194         frameOffset.callNumber = callNum;
195
196         currentFrame = new ApiTraceFrame();
197         currentFrame->number = numOfFrames;
198         currentFrame->setNumChildren(numOfCalls);
199         frames.append(currentFrame);
200
201         m_frameOffsets[numOfFrames] = frameOffset;
202         ++numOfFrames;
203     }
204
205     emit parsed(100);
206
207     emit framesLoaded(frames);
208 }
209
210 void TraceLoader::parseTrace()
211 {
212     QList<ApiTraceFrame*> frames;
213     ApiTraceFrame *currentFrame = 0;
214     int frameCount = 0;
215     QVector<ApiTraceCall*> calls;
216     quint64 binaryDataSize = 0;
217
218     int lastPercentReport = 0;
219
220     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     }
256
257     //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     }
269 }
270
271
272 ApiTraceCallSignature * 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
282 void TraceLoader::addSignature(unsigned id, ApiTraceCallSignature *signature)
283 {
284     m_signatures[id] = signature;
285 }
286
287 ApiTraceEnumSignature * 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
297 void TraceLoader::addEnumSignature(unsigned id, ApiTraceEnumSignature *signature)
298 {
299     m_enumSignatures[id] = signature;
300 }
301
302 #include "traceloader.moc"