blob: 0c7e8c91a4e4a28fc43d2b8ab52197f8eccdb330 [file] [log] [blame]
James Benton0b65a2b2012-09-07 18:38:15 +01001#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 */
16class CallDurationGraph : public GraphWidget {
17public:
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
29protected:
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
79private:
80 const trace::Profile* m_profile;
81};
82
83/* Data provider for call duration graphs */
84class CallDurationDataProvider : public GraphDataProvider {
85public:
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
167private:
168 bool m_gpu;
169 const trace::Profile* m_profile;
170 SelectionState* m_selectionState;
171};
172
173#endif