]> git.cworth.org Git - apitrace/blob - gui/profiletablemodel.cpp
a305709fa9c9c1cf9903894e574b8c9ea317654e
[apitrace] / gui / profiletablemodel.cpp
1 #include "profiletablemodel.h"
2
3 typedef trace::Profile::Call Call;
4 typedef trace::Profile::Frame Frame;
5 typedef trace::Profile::Program Program;
6
7 enum {
8     COLUMN_PROGRAM,
9     COLUMN_USAGES,
10     COLUMN_GPU_TIME,
11     COLUMN_CPU_TIME,
12     COLUMN_PIXELS_DRAWN,
13     COLUMN_GPU_AVERAGE,
14     COLUMN_CPU_AVERAGE,
15     COLUMN_PIXELS_AVERAGE,
16     MAX_COLUMN
17 };
18
19 static QString columnNames[] = {
20     QString("Program"),
21     QString("Calls"),
22     QString("Total GPU Time"),
23     QString("Total CPU Time"),
24     QString("Total Pixels Drawn"),
25     QString("Avg GPU Time"),
26     QString("Avg CPU Time"),
27     QString("Avg Pixels Drawn")
28 };
29
30 ProfileTableModel::ProfileTableModel(QObject *parent)
31     : QAbstractTableModel(parent),
32       m_profile(0),
33       m_sortColumn(COLUMN_GPU_TIME),
34       m_sortOrder(Qt::DescendingOrder)
35 {
36 }
37
38
39 void ProfileTableModel::setProfile(trace::Profile* profile)
40 {
41     m_profile = profile;
42     m_timeMin = m_profile->frames.front().cpuStart;
43     m_timeMax = m_profile->frames.back().cpuStart + m_profile->frames.back().cpuDuration;
44     updateModel();
45 }
46
47
48 void ProfileTableModel::setTimeSelection(int64_t start, int64_t end)
49 {
50     m_timeMin = start;
51     m_timeMax = end;
52     updateModel();
53     sort(m_sortColumn, m_sortOrder);
54 }
55
56
57 /**
58  * Creates the row data from trace profile
59  */
60 void ProfileTableModel::updateModel()
61 {
62     if (m_timeMin == m_timeMax) {
63         m_timeMin = m_profile->frames.front().cpuStart;
64         m_timeMax = m_profile->frames.back().cpuStart + m_profile->frames.back().cpuDuration;
65     }
66
67     for (QList<ProfileTableRow>::iterator itr = m_rowData.begin(); itr != m_rowData.end(); ++itr) {
68         ProfileTableRow& row = *itr;
69
70         row.uses = 0;
71         row.pixels = 0;
72         row.gpuTime = 0;
73         row.cpuTime = 0;
74         row.longestCpu = NULL;
75         row.longestGpu = NULL;
76         row.longestPixel = NULL;
77     }
78
79     for (std::vector<Program>::const_iterator itr = m_profile->programs.begin(); itr != m_profile->programs.end(); ++itr) {
80         ProfileTableRow* row = NULL;
81         const Program& program = *itr;
82
83         for (std::vector<unsigned>::const_iterator jtr = program.calls.begin(); jtr != program.calls.end(); ++jtr) {
84             const Call& call = m_profile->calls[*jtr];
85
86             if (call.cpuStart > m_timeMax) {
87                 break;
88             }
89
90             if (call.cpuStart + call.cpuDuration < m_timeMin) {
91                 continue;
92             }
93
94             if (!row) {
95                 row = getRow(itr - m_profile->programs.begin());
96             }
97
98             row->uses++;
99             row->pixels  += call.pixels;
100             row->gpuTime += call.gpuDuration;
101             row->cpuTime += call.cpuDuration;
102
103             if (!row->longestGpu || row->longestGpu->gpuDuration < call.gpuDuration) {
104                 row->longestGpu = &call;
105             }
106
107             if (!row->longestCpu || row->longestCpu->cpuDuration < call.cpuDuration) {
108                 row->longestCpu = &call;
109             }
110
111             if (!row->longestPixel || row->longestPixel->pixels < call.pixels) {
112                 row->longestPixel = &call;
113             }
114         }
115     }
116 }
117
118
119 /**
120  * Get the appropriate call associated with an item in the table
121  */
122 const trace::Profile::Call *ProfileTableModel::getJumpCall(const QModelIndex & index) const {
123     const ProfileTableRow& row = m_rowData[index.row()];
124
125     switch(index.column()) {
126     case COLUMN_GPU_TIME:
127     case COLUMN_GPU_AVERAGE:
128         return row.longestGpu;
129     case COLUMN_CPU_TIME:
130     case COLUMN_CPU_AVERAGE:
131         return row.longestCpu;
132     case COLUMN_PIXELS_DRAWN:
133     case COLUMN_PIXELS_AVERAGE:
134         return row.longestPixel;
135     }
136
137     return NULL;
138 }
139
140
141 ProfileTableRow* ProfileTableModel::getRow(unsigned program) {
142     for (QList<ProfileTableRow>::iterator itr = m_rowData.begin(); itr != m_rowData.end(); ++itr) {
143         if (itr->program == program)
144             return &*itr;
145     }
146
147     m_rowData.append(ProfileTableRow(program));
148     return &m_rowData.back();
149 }
150
151
152 int ProfileTableModel::rowCount(const QModelIndex & parent) const
153 {
154     if (!parent.isValid()) {
155         return m_rowData.size();
156     } else {
157         return 0;
158     }
159 }
160
161
162 int ProfileTableModel::columnCount(const QModelIndex & /*parent*/) const
163 {
164     return MAX_COLUMN;
165 }
166
167
168 QVariant ProfileTableModel::data(const QModelIndex &index, int role) const
169 {
170     if (!index.isValid()) {
171         return QVariant();
172     }
173
174     if (role == Qt::DisplayRole) {
175         const ProfileTableRow& row = m_rowData[index.row()];
176
177         switch(index.column()) {
178         case COLUMN_PROGRAM:
179             return row.program;
180         case COLUMN_USAGES:
181             return row.uses;
182         case COLUMN_GPU_TIME:
183             return row.gpuTime;
184         case COLUMN_CPU_TIME:
185             return row.cpuTime;
186         case COLUMN_PIXELS_DRAWN:
187             return row.pixels;
188         case COLUMN_GPU_AVERAGE:
189             return (row.uses <= 0) ? 0 : (row.gpuTime / row.uses);
190         case COLUMN_CPU_AVERAGE:
191             return (row.uses <= 0) ? 0 : (row.cpuTime / row.uses);
192         case COLUMN_PIXELS_AVERAGE:
193             return (row.uses <= 0) ? 0 : (row.pixels / row.uses);
194         }
195     } else if (role == Qt::TextAlignmentRole) {
196         return Qt::AlignRight;
197     }
198
199     return QVariant();
200 }
201
202
203 QVariant ProfileTableModel::headerData(int section, Qt::Orientation orientation, int role) const
204 {
205     if (role == Qt::DisplayRole && orientation == Qt::Horizontal) {
206         if (section >= 0 && section < MAX_COLUMN) {
207             return columnNames[section];
208         }
209     }
210
211     return QVariant();
212 }
213
214
215 class ProgramSorter {
216 public:
217     ProgramSorter(int column, Qt::SortOrder order)
218         : mSortColumn(column),
219           mSortOrder(order)
220     {
221     }
222
223     bool operator()(const ProfileTableRow &p1, const ProfileTableRow &p2) const
224     {
225         bool result = true;
226
227         switch(mSortColumn) {
228         case COLUMN_PROGRAM:
229             result = p1.program < p2.program;
230             break;
231         case COLUMN_USAGES:
232             result = p1.uses < p2.uses;
233             break;
234         case COLUMN_GPU_TIME:
235             result = p1.gpuTime < p2.gpuTime;
236             break;
237         case COLUMN_CPU_TIME:
238             result = p1.cpuTime < p2.cpuTime;
239             break;
240         case COLUMN_PIXELS_DRAWN:
241             result = p1.pixels < p2.pixels;
242             break;
243         case COLUMN_GPU_AVERAGE:
244             result = ((p1.uses <= 0) ? 0 : (p1.gpuTime / p1.uses)) < ((p2.uses <= 0) ? 0 : (p2.gpuTime / p2.uses));
245             break;
246         case COLUMN_CPU_AVERAGE:
247             result = ((p1.uses <= 0) ? 0 : (p1.cpuTime / p1.uses)) < ((p2.uses <= 0) ? 0 : (p2.cpuTime / p2.uses));
248             break;
249         case COLUMN_PIXELS_AVERAGE:
250             result = ((p1.uses <= 0) ? 0 : (p1.pixels / p1.uses)) < ((p2.uses <= 0) ? 0 : (p2.pixels / p2.uses));
251             break;
252         }
253
254         if (mSortOrder == Qt::DescendingOrder) {
255             return !result;
256         } else {
257             return result;
258         }
259     }
260
261 private:
262     int mSortColumn;
263     Qt::SortOrder mSortOrder;
264 };
265
266
267 void ProfileTableModel::sort(int column, Qt::SortOrder order) {
268     m_sortColumn = column;
269     m_sortOrder = order;
270     qSort(m_rowData.begin(), m_rowData.end(), ProgramSorter(column, order));
271     emit dataChanged(createIndex(0, 0), createIndex(m_rowData.size(), MAX_COLUMN));
272 }
273
274
275 #include "profiletablemodel.moc"