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