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