]> git.cworth.org Git - apitrace/blob - gui/calldurationgraph.h
Use skiplist-based FastCallSet within trace::CallSet
[apitrace] / gui / calldurationgraph.h
1 #ifndef CALLDURATIONGRAPH_H
2 #define CALLDURATIONGRAPH_H
3
4 #include "graphing/graphwidget.h"
5 #include "trace_profiler.hpp"
6 #include "profiling.h"
7
8 /**
9  * Wrapper for call duration graphs.
10  *
11  * This implements the transformSelectionIn and transformSelectionOut to
12  * allow sharing the selection between the graphs and the heatmap as they
13  * are using different scales. The duration graphs have call.no on the X-axis
14  * whereas the heatmap has time on the X axis.
15  */
16 class CallDurationGraph : public GraphWidget {
17 public:
18     CallDurationGraph(QWidget* parent = 0) :
19         GraphWidget(parent),
20         m_profile(NULL)
21     {
22     }
23
24     void setProfile(const trace::Profile* profile)
25     {
26         m_profile = profile;
27     }
28
29 protected:
30     /* Transform from time-based horizontal selection to call no based. */
31     virtual SelectionState transformSelectionIn(SelectionState state)
32     {
33         if (!m_profile || state.type != SelectionState::Horizontal) {
34             return state;
35         }
36
37         qint64 timeStart = state.start;
38         qint64 timeEnd = state.end;
39
40         std::vector<trace::Profile::Call>::const_iterator itr;
41
42         itr =
43             Profiling::binarySearchTimespan<
44                 trace::Profile::Call,
45                 &trace::Profile::Call::cpuStart,
46                 &trace::Profile::Call::cpuDuration>
47             (m_profile->calls.begin(), m_profile->calls.end(), timeStart, true);
48
49         state.start = itr - m_profile->calls.begin();
50
51         itr =
52             Profiling::binarySearchTimespan<
53                 trace::Profile::Call,
54                 &trace::Profile::Call::cpuStart,
55                 &trace::Profile::Call::cpuDuration>
56             (m_profile->calls.begin(), m_profile->calls.end(), timeEnd, true);
57
58         state.end = itr - m_profile->calls.begin();
59
60         return state;
61     }
62
63     virtual SelectionState transformSelectionOut(SelectionState state)
64     {
65         if (!m_profile || state.type != SelectionState::Horizontal) {
66             return state;
67         }
68
69         qint64 start = qMax<qint64>(0, state.start);
70         qint64 end = qMin<qint64>(state.end, m_profile->calls.size());
71
72         /* Call based -> time based */
73         state.start = m_profile->calls[start].cpuStart;
74         state.end = m_profile->calls[end].cpuStart + m_profile->calls[end].cpuDuration;
75
76         return state;
77     }
78
79 private:
80     const trace::Profile* m_profile;
81 };
82
83 /* Data provider for call duration graphs */
84 class CallDurationDataProvider : public GraphDataProvider {
85 public:
86     CallDurationDataProvider(const trace::Profile* profile, bool gpu) :
87         m_gpu(gpu),
88         m_profile(profile),
89         m_selectionState(NULL)
90     {
91     }
92
93     virtual qint64 size() const
94     {
95         return m_profile ? m_profile->calls.size() : 0;
96     }
97
98     virtual bool selected(qint64 index) const
99     {
100         if (m_selectionState) {
101             if (m_selectionState->type == SelectionState::Horizontal) {
102                 if (m_selectionState->start <= index && index < m_selectionState->end) {
103                     return true;
104                 }
105             } else if (m_selectionState->type == SelectionState::Vertical) {
106                 return m_profile->calls[index].program == m_selectionState->start;
107             }
108         }
109
110         return false;
111     }
112
113     virtual void setSelectionState(SelectionState* state)
114     {
115         m_selectionState = state;
116     }
117
118     virtual qint64 value(qint64 index) const
119     {
120         if (m_gpu) {
121             return m_profile->calls[index].gpuDuration;
122         } else {
123             return m_profile->calls[index].cpuDuration;
124         }
125     }
126
127     virtual void itemDoubleClicked(qint64 index) const
128     {
129         if (!m_profile) {
130             return;
131         }
132
133         if (index < 0 || index >= m_profile->calls.size()) {
134             return;
135         }
136
137         const trace::Profile::Call& call = m_profile->calls[index];
138         Profiling::jumpToCall(call.no);
139     }
140
141     virtual QString itemTooltip(qint64 index) const
142     {
143         if (!m_profile) {
144             return QString();
145         }
146
147         if (index < 0 || index >= m_profile->calls.size()) {
148             return QString();
149         }
150
151         const trace::Profile::Call& call = m_profile->calls[index];
152
153         QString text;
154         text  = QString::fromStdString(call.name);
155         text += QString("\nCall: %1").arg(call.no);
156         text += QString("\nCPU Duration: %1").arg(Profiling::getTimeString(call.cpuDuration));
157
158         if (call.pixels >= 0) {
159             text += QString("\nGPU Duration: %1").arg(Profiling::getTimeString(call.gpuDuration));
160             text += QString("\nPixels Drawn: %1").arg(QLocale::system().toString((qlonglong)call.pixels));
161             text += QString("\nProgram: %1").arg(call.program);
162         }
163
164         return text;
165     }
166
167 private:
168     bool m_gpu;
169     const trace::Profile* m_profile;
170     SelectionState* m_selectionState;
171 };
172
173 #endif