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