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