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