]> git.cworth.org Git - apitrace/blob - gui/apitracecall.cpp
Filter text was missing the first paren.
[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     if (helpUrl.isEmpty()) {
288         m_richText = QString::fromLatin1(
289             "%1) <span style=\"font-weight:bold\">%2</span>(")
290                      .arg(index)
291                      .arg(name);
292     } else {
293         m_richText = QString::fromLatin1(
294             "%1) <span style=\"font-weight:bold\"><a href=\"%2\">%3</a></span>(")
295                       .arg(index)
296                       .arg(helpUrl.toString())
297                       .arg(name);
298     }
299
300     for (int i = 0; i < argNames.count(); ++i) {
301         m_richText += argNames[i];
302         m_richText += QString::fromLatin1(" = ");
303         m_richText += QLatin1String("<span style=\"color:#0000ff\">");
304         m_richText += apiVariantToString(argValues[i]);
305         m_richText += QLatin1String("</span>");
306         if (i < argNames.count() - 1)
307             m_richText += QString::fromLatin1(", ");
308     }
309     m_richText += QLatin1String(")");
310
311     if (returnValue.isValid()) {
312         m_richText += QLatin1String(" = ");
313         m_richText += QLatin1String("<span style=\"color:#0000ff\">");
314         m_richText += apiVariantToString(returnValue);
315         m_richText += QLatin1String("</span>");
316     }
317     return m_richText;
318 }
319
320 QString ApiTraceCall::filterText() const
321 {
322     if (!m_filterText.isEmpty())
323         return m_filterText;
324
325     m_filterText = name;
326     m_filterText += QLatin1String("(");
327     for (int i = 0; i < argNames.count(); ++i) {
328         m_filterText += argNames[i];
329         m_filterText += QString::fromLatin1(" = ");
330
331         if (argValues[i].type() == QVariant::ByteArray) {
332             m_hasBinaryData = true;
333             m_binaryDataIndex = i;
334         }
335         m_filterText += apiVariantToString(argValues[i]);
336         if (i < argNames.count() - 1)
337             m_filterText += QString::fromLatin1(", ");
338     }
339     m_filterText += QLatin1String(")");
340
341     if (returnValue.isValid()) {
342         m_filterText += QLatin1String(" = ");
343         m_filterText += apiVariantToString(returnValue);
344     }
345     return m_filterText;
346 }
347
348 QStaticText ApiTraceFrame::staticText() const
349 {
350     if (!m_staticText.text().isEmpty())
351         return m_staticText;
352
353     QString richText =
354         QString::fromLatin1("<span style=\"font-weight:bold\">Frame %1</span>").arg(number);
355
356     m_staticText.setText(richText);
357     QTextOption opt;
358     opt.setWrapMode(QTextOption::NoWrap);
359     m_staticText.setTextOption(opt);
360     m_staticText.prepare();
361
362     return m_staticText;
363 }
364
365 int ApiTraceCall::numChildren() const
366 {
367     return 0;
368 }
369
370 int ApiTraceFrame::numChildren() const
371 {
372     return calls.count();
373 }
374
375 ApiTraceFrame::ApiTraceFrame()
376     : ApiTraceEvent(ApiTraceEvent::Frame)
377 {
378 }
379
380 ApiTraceCall::ApiTraceCall()
381     : ApiTraceEvent(ApiTraceEvent::Call),
382       m_hasBinaryData(false),
383       m_binaryDataIndex(0)
384 {
385 }
386
387 ApiTraceEvent::ApiTraceEvent()
388     : m_type(ApiTraceEvent::None)
389 {
390 }
391
392 ApiTraceEvent::ApiTraceEvent(Type t)
393     : m_type(t)
394 {
395 }
396
397 ApiTraceCall::~ApiTraceCall()
398 {
399 }
400
401 QVariantMap ApiTraceEvent::stateParameters() const
402 {
403     return m_state.parameters();
404 }
405
406 ApiTraceState ApiTraceEvent::state() const
407 {
408     return m_state;
409 }
410
411 void ApiTraceEvent::setState(const ApiTraceState &state)
412 {
413     m_state = state;
414 }
415
416 bool ApiTraceCall::hasBinaryData() const
417 {
418     return m_hasBinaryData;
419 }
420
421 int ApiTraceCall::binaryDataIndex() const
422 {
423     return m_binaryDataIndex;
424 }
425
426 ApiTraceState::ApiTraceState()
427 {
428 }
429
430 ApiTraceState::ApiTraceState(const QVariantMap &parsedJson)
431 {
432     m_parameters = parsedJson[QLatin1String("parameters")].toMap();
433     QVariantMap currentProgram =
434         parsedJson[QLatin1String("current_program")].toMap();
435     QVariantList attachedShaders =
436         currentProgram[QLatin1String("attached_shaders")].toList();
437
438
439     for (int i = 0; i < attachedShaders.count(); ++i) {
440         QVariantMap var = attachedShaders[i].toMap();
441         m_shaderSources.append(
442             var[QLatin1String("source")].toString());
443     }
444
445     QVariantList textureUnits =
446         parsedJson[QLatin1String("textures")].toList();
447     for (int i = 0; i < textureUnits.count(); ++i) {
448         QVariantMap unit = textureUnits[i].toMap();
449         QVariantMap::const_iterator itr;
450         for (itr = unit.constBegin(); itr != unit.constEnd(); ++itr) {
451             QVariantMap target = itr.value().toMap();
452             if (target.count()) {
453                 QVariantList levels = target[QLatin1String("levels")].toList();
454                 for (int j = 0; j < levels.count(); ++j) {
455                     QVariantMap level = levels[j].toMap();
456                     QVariantMap image = level[QLatin1String("image")].toMap();
457                     QSize size(image[QLatin1String("__width__")].toInt(),
458                                image[QLatin1String("__height__")].toInt());
459                     QString cls = image[QLatin1String("__class__")].toString();
460                     QString type = image[QLatin1String("__type__")].toString();
461                     bool normalized =
462                         image[QLatin1String("__normalized__")].toBool();
463                     int numChannels =
464                         image[QLatin1String("__channels__")].toInt();
465
466                     Q_ASSERT(type == QLatin1String("uint8"));
467                     Q_ASSERT(normalized == true);
468
469                     QByteArray dataArray =
470                         image[QLatin1String("__data__")].toByteArray();
471
472                     ApiTexture tex;
473                     tex.setSize(size);
474                     tex.setNumChannels(numChannels);
475                     tex.setLevel(j);
476                     tex.setUnit(i);
477                     tex.setTarget(itr.key());
478                     tex.contentsFromBase64(dataArray);
479
480                     m_textures.append(tex);
481                 }
482             }
483         }
484     }
485
486     QVariantMap fbos =
487         parsedJson[QLatin1String("framebuffer")].toMap();
488     QVariantMap::const_iterator itr;
489     for (itr = fbos.constBegin(); itr != fbos.constEnd(); ++itr) {
490         QVariantMap buffer = itr.value().toMap();
491         QSize size(buffer[QLatin1String("__width__")].toInt(),
492                    buffer[QLatin1String("__height__")].toInt());
493         QString cls = buffer[QLatin1String("__class__")].toString();
494         QString type = buffer[QLatin1String("__type__")].toString();
495         bool normalized = buffer[QLatin1String("__normalized__")].toBool();
496         int numChannels = buffer[QLatin1String("__channels__")].toInt();
497
498         Q_ASSERT(type == QLatin1String("uint8"));
499         Q_ASSERT(normalized == true);
500
501         QByteArray dataArray =
502             buffer[QLatin1String("__data__")].toByteArray();
503
504         ApiFramebuffer fbo;
505         fbo.setSize(size);
506         fbo.setNumChannels(numChannels);
507         fbo.setType(itr.key());
508         fbo.contentsFromBase64(dataArray);
509         m_framebuffers.append(fbo);
510     }
511 }
512
513 QVariantMap ApiTraceState::parameters() const
514 {
515     return m_parameters;
516 }
517
518 QStringList ApiTraceState::shaderSources() const
519 {
520     return m_shaderSources;
521 }
522
523 bool ApiTraceState::isEmpty() const
524 {
525     return m_parameters.isEmpty();
526 }
527
528 QList<ApiTexture> ApiTraceState::textures() const
529 {
530     return m_textures;
531 }
532
533 QList<ApiFramebuffer> ApiTraceState::framebuffers() const
534 {
535     return m_framebuffers;
536 }
537
538