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;
};
|