]> git.cworth.org Git - apitrace/blob - gui/apitracecall.cpp
Add code to interpret and display binary vertex data.
[apitrace] / gui / apitracecall.cpp
1 #include "apitracecall.h"
2
3 #include "trace_model.hpp"
4
5 #include <QDebug>
6 #include <QObject>
7
8 ApiPointer::ApiPointer(int val)
9     : m_value(val)
10 {
11 }
12
13 QString ApiPointer::toString() const
14 {
15     if (m_value)
16         return QString("0x%1").arg(m_value, 0, 16);
17     else
18         return QLatin1String("NULL");
19 }
20
21 QString apiVariantToString(const QVariant &variant)
22 {
23     if (variant.userType() == QVariant::Double) {
24         return QString::number(variant.toFloat());
25     }
26     if (variant.userType() == QVariant::ByteArray) {
27         if (variant.toByteArray().size() < 1024) {
28             int bytes = variant.toByteArray().size();
29             return QObject::tr("[binary data, size = %1 bytes]").arg(bytes);
30         } else {
31             float kb = variant.toByteArray().size()/1024.;
32             return QObject::tr("[binary data, size = %1 kb]").arg(kb);
33         }
34     }
35
36     if (variant.userType() < QVariant::UserType) {
37         return variant.toString();
38     }
39
40     if (variant.canConvert<ApiPointer>()) {
41         return variant.value<ApiPointer>().toString();
42     }
43     if (variant.canConvert<ApiBitmask>()) {
44         return variant.value<ApiBitmask>().toString();
45     }
46     if (variant.canConvert<ApiStruct>()) {
47         return variant.value<ApiStruct>().toString();
48     }
49     if (variant.canConvert<ApiArray>()) {
50         return variant.value<ApiArray>().toString();
51     }
52
53     return QString();
54 }
55
56 ApiBitmask::ApiBitmask(const Trace::Bitmask *bitmask)
57     : m_value(0)
58 {
59     init(bitmask);
60 }
61
62
63 void ApiBitmask::init(const Trace::Bitmask *bitmask)
64 {
65     if (!bitmask)
66         return;
67
68     m_value = bitmask->value;
69     for (Trace::Bitmask::Signature::const_iterator it = bitmask->sig->begin();
70          it != bitmask->sig->end(); ++it) {
71         assert(it->second);
72         QPair<QString, unsigned long long> pair;
73
74         pair.first = QString::fromStdString(it->first);
75         pair.second = it->second;
76
77         m_sig.append(pair);
78     }
79 }
80
81 QString ApiBitmask::toString() const
82 {
83     QString str;
84     unsigned long long value = m_value;
85     bool first = true;
86     for (Signature::const_iterator it = m_sig.begin();
87          value != 0 && it != m_sig.end(); ++it) {
88         Q_ASSERT(it->second);
89         if ((value & it->second) == it->second) {
90             if (!first) {
91                 str += QLatin1String(" | ");
92             }
93             str += it->first;
94             value &= ~it->second;
95             first = false;
96         }
97     }
98     if (value || first) {
99         if (!first) {
100             str += QLatin1String(" | ");
101         }
102         str += QString::fromLatin1("0x%1").arg(value, 0, 16);
103     }
104     return str;
105 }
106
107 ApiStruct::ApiStruct(const Trace::Struct *s)
108 {
109     init(s);
110 }
111
112 QString ApiStruct::toString() const
113 {
114     QString str;
115
116     str += QLatin1String("{");
117     for (unsigned i = 0; i < m_members.count(); ++i) {
118         str += m_sig.memberNames[i];
119         str += QLatin1String(" = ");
120         str += apiVariantToString(m_members[i]);
121         if (i < m_members.count() - 1)
122             str += QLatin1String(", ");
123     }
124     str += QLatin1String("}");
125
126     return str;
127 }
128
129 void ApiStruct::init(const Trace::Struct *s)
130 {
131     if (!s)
132         return;
133
134     m_sig.name = QString::fromStdString(s->sig->name);
135     for (unsigned i = 0; i < s->members.size(); ++i) {
136         VariantVisitor vis;
137         m_sig.memberNames.append(
138             QString::fromStdString(s->sig->member_names[i]));
139         s->members[i]->visit(vis);
140         m_members.append(vis.variant());
141     }
142 }
143
144 void VariantVisitor::visit(Trace::Null *)
145 {
146     m_variant = QVariant(QLatin1String("NULL"));
147 }
148
149 void VariantVisitor::visit(Trace::Bool *node)
150 {
151     m_variant = QVariant(node->value);
152 }
153
154 void VariantVisitor::visit(Trace::SInt *node)
155 {
156     m_variant = QVariant(node->value);
157 }
158
159 void VariantVisitor::visit(Trace::UInt *node)
160 {
161     m_variant = QVariant(node->value);
162 }
163
164 void VariantVisitor::visit(Trace::Float *node)
165 {
166     m_variant = QVariant(node->value);
167 }
168
169 void VariantVisitor::visit(Trace::String *node)
170 {
171     m_variant = QVariant(QString::fromStdString(node->value));
172 }
173
174 void VariantVisitor::visit(Trace::Enum *e)
175 {
176     m_variant = QVariant(QString::fromStdString(e->sig->first));
177 }
178
179 void VariantVisitor::visit(Trace::Bitmask *bitmask)
180 {
181     m_variant = QVariant::fromValue(ApiBitmask(bitmask));
182 }
183
184 void VariantVisitor::visit(Trace::Struct *str)
185 {
186     m_variant = QVariant::fromValue(ApiStruct(str));
187 }
188
189 void VariantVisitor::visit(Trace::Array *array)
190 {
191     m_variant = QVariant::fromValue(ApiArray(array));
192 }
193
194 void VariantVisitor::visit(Trace::Blob *blob)
195 {
196     QByteArray barray = QByteArray::fromRawData(blob->buf, blob->size);
197     m_variant = QVariant(barray);
198 }
199
200 void VariantVisitor::visit(Trace::Pointer *ptr)
201 {
202     m_variant = QVariant::fromValue(ApiPointer(ptr->value));
203 }
204
205 ApiArray::ApiArray(const Trace::Array *arr)
206 {
207     init(arr);
208 }
209
210 QString ApiArray::toString() const
211 {
212     QString str;
213     str += QLatin1String("[");
214     for(int i = 0; i < m_array.count(); ++i) {
215         const QVariant &var = m_array[i];
216         str += apiVariantToString(var);
217         if (i < m_array.count() - 1)
218             str += QLatin1String(", ");
219     }
220     str += QLatin1String("]");
221
222     return str;
223 }
224
225 void ApiArray::init(const Trace::Array *arr)
226 {
227     if (!arr)
228         return;
229
230     for (int i = 0; i < arr->values.size(); ++i) {
231         VariantVisitor vis;
232         arr->values[i]->visit(vis);
233
234         m_array.append(vis.variant());
235     }
236 }
237
238 QStaticText ApiTraceCall::staticText() const
239 {
240     if (!m_staticText.text().isEmpty())
241         return m_staticText;
242
243     QString richText = QString::fromLatin1("<span style=\"font-weight:bold\">%1</span>(").arg(name);
244     for (int i = 0; i < argNames.count(); ++i) {
245         richText += QLatin1String("<span style=\"color:#0000ff\">");
246         QString argText = apiVariantToString(argValues[i]);
247
248         //if arguments are really long (e.g. shader text), cut them
249         // and elide it
250         if (argText.length() > 40) {
251             QString shortened = argText.mid(0, 40);
252             shortened[argText.length() - 5] = '.';
253             shortened[argText.length() - 4] = '.';
254             shortened[argText.length() - 3] = '.';
255             shortened[argText.length() - 2] = argText[argText.length() - 2];
256             shortened[argText.length() - 1] = argText[argText.length() - 1];
257             richText += shortened;
258         } else {
259             richText += argText;
260         }
261         richText += QLatin1String("</span>");
262         if (i < argNames.count() - 1)
263             richText += QString::fromLatin1(", ");
264     }
265     richText += QLatin1String(")");
266     if (returnValue.isValid()) {
267         richText += QLatin1String(" = ");
268         richText += QLatin1String("<span style=\"color:#0000ff\">");
269         richText += apiVariantToString(returnValue);
270         richText += QLatin1String("</span>");
271     }
272
273     m_staticText.setText(richText);
274     QTextOption opt;
275     opt.setWrapMode(QTextOption::NoWrap);
276     m_staticText.setTextOption(opt);
277     m_staticText.prepare();
278
279     return m_staticText;
280 }
281
282 QString ApiTraceCall::toHtml() const
283 {
284     if (!m_richText.isEmpty())
285         return m_richText;
286
287     m_richText = QString::fromLatin1("%1) <span style=\"font-weight:bold\">%2</span>(")
288                  .arg(index)
289                  .arg(name);
290     for (int i = 0; i < argNames.count(); ++i) {
291         m_richText += argNames[i];
292         m_richText += QString::fromLatin1(" = ");
293         m_richText += QLatin1String("<span style=\"color:#0000ff\">");
294         m_richText += apiVariantToString(argValues[i]);
295         m_richText += QLatin1String("</span>");
296         if (i < argNames.count() - 1)
297             m_richText += QString::fromLatin1(", ");
298     }
299     m_richText += QLatin1String(")");
300
301     if (returnValue.isValid()) {
302         m_richText += QLatin1String(" = ");
303         m_richText += QLatin1String("<span style=\"color:#0000ff\">");
304         m_richText += apiVariantToString(returnValue);
305         m_richText += QLatin1String("</span>");
306     }
307     return m_richText;
308 }
309
310 QString ApiTraceCall::filterText() const
311 {
312     if (!m_filterText.isEmpty())
313         return m_filterText;
314
315     m_filterText = name;
316     for (int i = 0; i < argNames.count(); ++i) {
317         m_filterText += argNames[i];
318         m_filterText += QString::fromLatin1(" = ");
319
320         if (argValues[i].type() == QVariant::ByteArray) {
321             m_hasBinaryData = true;
322             m_binaryDataIndex = i;
323         }
324         m_filterText += apiVariantToString(argValues[i]);
325         if (i < argNames.count() - 1)
326             m_filterText += QString::fromLatin1(", ");
327     }
328     m_filterText += QLatin1String(")");
329
330     if (returnValue.isValid()) {
331         m_filterText += QLatin1String(" = ");
332         m_filterText += apiVariantToString(returnValue);
333     }
334     return m_filterText;
335 }
336
337 QStaticText ApiTraceFrame::staticText() const
338 {
339     if (!m_staticText.text().isEmpty())
340         return m_staticText;
341
342     QString richText =
343         QString::fromLatin1("<span style=\"font-weight:bold\">Frame %1</span>").arg(number);
344
345     m_staticText.setText(richText);
346     QTextOption opt;
347     opt.setWrapMode(QTextOption::NoWrap);
348     m_staticText.setTextOption(opt);
349     m_staticText.prepare();
350
351     return m_staticText;
352 }
353
354 int ApiTraceCall::numChildren() const
355 {
356     return 0;
357 }
358
359 int ApiTraceFrame::numChildren() const
360 {
361     return calls.count();
362 }
363
364 ApiTraceFrame::ApiTraceFrame()
365     : ApiTraceEvent(ApiTraceEvent::Frame)
366 {
367 }
368
369 ApiTraceCall::ApiTraceCall()
370     : ApiTraceEvent(ApiTraceEvent::Call),
371       m_hasBinaryData(false),
372       m_binaryDataIndex(0)
373 {
374 }
375
376 ApiTraceEvent::ApiTraceEvent()
377     : m_type(ApiTraceEvent::None)
378 {
379 }
380
381 ApiTraceEvent::ApiTraceEvent(Type t)
382     : m_type(t)
383 {
384 }
385
386 ApiTraceCall::~ApiTraceCall()
387 {
388 }
389
390 QVariantMap ApiTraceEvent::state() const
391 {
392     return m_state;
393 }
394
395 void ApiTraceEvent::setState(const QVariantMap &state)
396 {
397     m_state = state;
398 }
399
400 bool ApiTraceCall::hasBinaryData() const
401 {
402     return m_hasBinaryData;
403 }
404
405 int ApiTraceCall::binaryDataIndex() const
406 {
407     return m_binaryDataIndex;
408 }