]> git.cworth.org Git - apitrace/blob - trace_loader.cpp
Fix memory usage in the on-demand-loading.
[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.parse_call())) {
65
66         ++numOfCalls;
67
68         if (isCallAFrameMarker(call)) {
69             File::Offset endOffset = m_parser.currentOffset();
70             FrameOffset frameOffset(startOffset);
71             frameOffset.numberOfCalls = numOfCalls;
72             frameOffset.callNumber = callNum;
73
74             m_frameOffsets[numOfFrames] = frameOffset;
75             ++numOfFrames;
76
77             startOffset = endOffset;
78             callNum = m_parser.currentCallNumber();
79             numOfCalls = 0;
80         }
81         //call->dump(std::cout, color);
82         delete call;
83     }
84     return true;
85 }
86
87 void Loader::close()
88 {
89     m_parser.close();
90 }
91
92 bool Loader::isCallAFrameMarker(const Trace::Call *call) const
93 {
94     std::string name = call->name();
95
96     switch (m_frameMarker) {
97     case FrameMarker_SwapBuffers:
98         return  name.find("SwapBuffers") != std::string::npos ||
99                 name == "CGLFlushDrawable" ||
100                 name == "glFrameTerminatorGREMEDY";
101         break;
102     case FrameMarker_Flush:
103         return name == "glFlush";
104         break;
105     case FrameMarker_Finish:
106         return name == "glFinish";
107         break;
108     case FrameMarker_Clear:
109         return name == "glClear";
110         break;
111     }
112     return false;
113 }
114
115 std::vector<Trace::Call *> Loader::frame(int idx)
116 {
117     int numOfCalls = numberOfCallsInFrame(idx);
118     if (numOfCalls) {
119         const FrameOffset &frameOffset = m_frameOffsets[idx];
120         std::vector<Trace::Call*> calls(numOfCalls);
121         m_parser.setCurrentOffset(frameOffset.start);
122         m_parser.setCurrentCallNumber(frameOffset.callNumber);
123
124         Trace::Call *call;
125         int parsedCalls = 0;
126         while ((call = m_parser.parse_call())) {
127
128             calls[parsedCalls] = call;
129             ++parsedCalls;
130
131             if (isCallAFrameMarker(call)) {
132                 break;
133             }
134
135         }
136         assert(parsedCalls == numOfCalls);
137         return calls;
138     }
139     return std::vector<Trace::Call*>();
140 }