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