]> git.cworth.org Git - apitrace/blob - trace_loader.cpp
Implement scanning/skipping of fragments of the trace
[apitrace] / trace_loader.cpp
1 #include "trace_loader.hpp"
2
3 #include "trace_snappyfile.hpp"
4
5 using namespace Trace;
6
7 Loader::Loader()
8     : m_frameMarker(FrameMarker_SwapBuffers),
9       file(0)
10 {
11 }
12
13 Loader::~Loader()
14 {
15     close();
16 }
17
18 Loader::FrameMarker Loader::frameMarker() const
19 {
20     return m_frameMarker;
21 }
22
23 void Loader::setFrameMarker(Loader::FrameMarker marker)
24 {
25     m_frameMarker = marker;
26 }
27
28 int Loader::numberOfFrames() const
29 {
30     return m_frameOffsets.size();
31 }
32
33 int Loader::numberOfCallsInFrame(int frameIdx) const
34 {
35     if (frameIdx > m_frameOffsets.size()) {
36         return 0;
37     }
38     FrameOffsets::const_iterator itr =
39         m_frameOffsets.find(frameIdx);
40     return itr->second.numberOfCalls;
41 }
42
43 bool Loader::open(const char *filename)
44 {
45     if (!m_parser.open(filename)) {
46         std::cerr << "error: failed to open " << filename << "\n";
47         return false;
48     }
49     if (!m_parser.supportsOffsets()) {
50         std::cerr << "error: " <<filename<< " doesn't support seeking "
51                   << "\n";
52         return false;
53     }
54
55     Trace::Call *call;
56     File::Offset startOffset;
57     int numOfFrames = 0;
58     int numOfCalls = 0;
59     unsigned callNum = 0;
60
61     startOffset = m_parser.currentOffset();
62     callNum = m_parser.currentCallNumber();
63
64     while ((call = m_parser.scan_call())) {
65         ++numOfCalls;
66
67         if (isCallAFrameMarker(call)) {
68             File::Offset endOffset = m_parser.currentOffset();
69             FrameOffset frameOffset(startOffset);
70             frameOffset.numberOfCalls = numOfCalls;
71             frameOffset.callNumber = callNum;
72
73             m_frameOffsets[numOfFrames] = frameOffset;
74             ++numOfFrames;
75
76             startOffset = endOffset;
77             callNum = m_parser.currentCallNumber();
78             numOfCalls = 0;
79         }
80         //call->dump(std::cout, color);
81         delete call;
82     }
83     return true;
84 }
85
86 void Loader::close()
87 {
88     m_parser.close();
89 }
90
91 bool Loader::isCallAFrameMarker(const Trace::Call *call) const
92 {
93     std::string name = call->name();
94
95     switch (m_frameMarker) {
96     case FrameMarker_SwapBuffers:
97         return  name.find("SwapBuffers") != std::string::npos ||
98                 name == "CGLFlushDrawable" ||
99                 name == "glFrameTerminatorGREMEDY";
100         break;
101     case FrameMarker_Flush:
102         return name == "glFlush";
103         break;
104     case FrameMarker_Finish:
105         return name == "glFinish";
106         break;
107     case FrameMarker_Clear:
108         return name == "glClear";
109         break;
110     }
111     return false;
112 }
113
114 std::vector<Trace::Call *> Loader::frame(int idx)
115 {
116     int numOfCalls = numberOfCallsInFrame(idx);
117     if (numOfCalls) {
118         const FrameOffset &frameOffset = m_frameOffsets[idx];
119         std::vector<Trace::Call*> calls(numOfCalls);
120         m_parser.setCurrentOffset(frameOffset.start);
121         m_parser.setCurrentCallNumber(frameOffset.callNumber);
122
123         Trace::Call *call;
124         int parsedCalls = 0;
125         while ((call = m_parser.parse_call())) {
126
127             calls[parsedCalls] = call;
128             ++parsedCalls;
129
130             if (isCallAFrameMarker(call)) {
131                 break;
132             }
133
134         }
135         assert(parsedCalls == numOfCalls);
136         return calls;
137     }
138     return std::vector<Trace::Call*>();
139 }