1 #include "apitracecall.h"
3 #include "trace_model.hpp"
7 #define QT_USE_FAST_OPERATOR_PLUS
8 #include <QStringBuilder>
10 ApiPointer::ApiPointer(int val)
15 QString ApiPointer::toString() const
18 return QString("0x%1").arg(m_value, 0, 16);
20 return QLatin1String("NULL");
23 QString apiVariantToString(const QVariant &variant)
25 if (variant.userType() == QVariant::Double) {
26 return QString::number(variant.toFloat());
28 if (variant.userType() == QVariant::ByteArray) {
29 if (variant.toByteArray().size() < 1024) {
30 int bytes = variant.toByteArray().size();
31 return QObject::tr("[binary data, size = %1 bytes]").arg(bytes);
33 float kb = variant.toByteArray().size()/1024.;
34 return QObject::tr("[binary data, size = %1 kb]").arg(kb);
38 if (variant.userType() < QVariant::UserType) {
39 return variant.toString();
42 if (variant.canConvert<ApiPointer>()) {
43 return variant.value<ApiPointer>().toString();
45 if (variant.canConvert<ApiBitmask>()) {
46 return variant.value<ApiBitmask>().toString();
48 if (variant.canConvert<ApiStruct>()) {
49 return variant.value<ApiStruct>().toString();
51 if (variant.canConvert<ApiArray>()) {
52 return variant.value<ApiArray>().toString();
58 ApiBitmask::ApiBitmask(const Trace::Bitmask *bitmask)
65 void ApiBitmask::init(const Trace::Bitmask *bitmask)
70 m_value = bitmask->value;
71 for (Trace::Bitmask::Signature::const_iterator it = bitmask->sig->begin();
72 it != bitmask->sig->end(); ++it) {
74 QPair<QString, unsigned long long> pair;
76 pair.first = QString::fromStdString(it->first);
77 pair.second = it->second;
83 QString ApiBitmask::toString() const
86 unsigned long long value = m_value;
88 for (Signature::const_iterator it = m_sig.begin();
89 value != 0 && it != m_sig.end(); ++it) {
91 if ((value & it->second) == it->second) {
93 str += QLatin1String(" | ");
100 if (value || first) {
102 str += QLatin1String(" | ");
104 str += QString::fromLatin1("0x%1").arg(value, 0, 16);
109 ApiStruct::ApiStruct(const Trace::Struct *s)
114 QString ApiStruct::toString() const
118 str += QLatin1String("{");
119 for (unsigned i = 0; i < m_members.count(); ++i) {
120 str += m_sig.memberNames[i] %
121 QLatin1Literal(" = ") %
122 apiVariantToString(m_members[i]);
123 if (i < m_members.count() - 1)
124 str += QLatin1String(", ");
126 str += QLatin1String("}");
131 void ApiStruct::init(const Trace::Struct *s)
136 m_sig.name = QString::fromStdString(s->sig->name);
137 for (unsigned i = 0; i < s->members.size(); ++i) {
139 m_sig.memberNames.append(
140 QString::fromStdString(s->sig->member_names[i]));
141 s->members[i]->visit(vis);
142 m_members.append(vis.variant());
146 void VariantVisitor::visit(Trace::Null *)
148 m_variant = QVariant(QLatin1String("NULL"));
151 void VariantVisitor::visit(Trace::Bool *node)
153 m_variant = QVariant(node->value);
156 void VariantVisitor::visit(Trace::SInt *node)
158 m_variant = QVariant(node->value);
161 void VariantVisitor::visit(Trace::UInt *node)
163 m_variant = QVariant(node->value);
166 void VariantVisitor::visit(Trace::Float *node)
168 m_variant = QVariant(node->value);
171 void VariantVisitor::visit(Trace::String *node)
173 m_variant = QVariant(QString::fromStdString(node->value));
176 void VariantVisitor::visit(Trace::Enum *e)
178 m_variant = QVariant(QString::fromStdString(e->sig->first));
181 void VariantVisitor::visit(Trace::Bitmask *bitmask)
183 m_variant = QVariant::fromValue(ApiBitmask(bitmask));
186 void VariantVisitor::visit(Trace::Struct *str)
188 m_variant = QVariant::fromValue(ApiStruct(str));
191 void VariantVisitor::visit(Trace::Array *array)
193 m_variant = QVariant::fromValue(ApiArray(array));
196 void VariantVisitor::visit(Trace::Blob *blob)
198 QByteArray barray = QByteArray::fromRawData(blob->buf, blob->size);
199 m_variant = QVariant(barray);
202 void VariantVisitor::visit(Trace::Pointer *ptr)
204 m_variant = QVariant::fromValue(ApiPointer(ptr->value));
207 ApiArray::ApiArray(const Trace::Array *arr)
212 ApiArray::ApiArray(const QList<QVariant> &vals)
217 QString ApiArray::toString() const
220 str += QLatin1String("[");
221 for(int i = 0; i < m_array.count(); ++i) {
222 const QVariant &var = m_array[i];
223 str += apiVariantToString(var);
224 if (i < m_array.count() - 1)
225 str += QLatin1String(", ");
227 str += QLatin1String("]");
232 void ApiArray::init(const Trace::Array *arr)
237 for (int i = 0; i < arr->values.size(); ++i) {
239 arr->values[i]->visit(vis);
241 m_array.append(vis.variant());
245 QStaticText ApiTraceCall::staticText() const
247 if (m_staticText && !m_staticText->text().isEmpty())
248 return *m_staticText;
250 QString richText = QString::fromLatin1(
251 "<span style=\"font-weight:bold\">%1</span>(").arg(m_name);
252 for (int i = 0; i < m_argNames.count(); ++i) {
253 richText += QLatin1String("<span style=\"color:#0000ff\">");
254 QString argText = apiVariantToString(m_argValues[i]);
256 //if arguments are really long (e.g. shader text), cut them
258 if (argText.length() > 40) {
259 QString shortened = argText.mid(0, 40);
260 shortened[argText.length() - 5] = '.';
261 shortened[argText.length() - 4] = '.';
262 shortened[argText.length() - 3] = '.';
263 shortened[argText.length() - 2] = argText[argText.length() - 2];
264 shortened[argText.length() - 1] = argText[argText.length() - 1];
265 richText += shortened;
269 richText += QLatin1String("</span>");
270 if (i < m_argNames.count() - 1)
271 richText += QLatin1String(", ");
273 richText += QLatin1String(")");
274 if (m_returnValue.isValid()) {
276 QLatin1Literal(" = ") %
277 QLatin1Literal("<span style=\"color:#0000ff\">") %
278 apiVariantToString(m_returnValue) %
279 QLatin1Literal("</span>");
283 m_staticText = new QStaticText(richText);
285 opt.setWrapMode(QTextOption::NoWrap);
286 m_staticText->setTextOption(opt);
287 m_staticText->prepare();
289 return *m_staticText;
292 QString ApiTraceCall::toHtml() const
294 if (!m_richText.isEmpty())
297 if (m_helpUrl.isEmpty()) {
298 m_richText = QString::fromLatin1(
299 "%1) <span style=\"font-weight:bold\">%2</span>(")
303 m_richText = QString::fromLatin1(
304 "%1) <span style=\"font-weight:bold\"><a href=\"%2\">%3</a></span>(")
306 .arg(m_helpUrl.toString())
310 for (int i = 0; i < m_argNames.count(); ++i) {
311 m_richText += m_argNames[i] +
312 QLatin1Literal(" = ") +
313 QLatin1Literal("<span style=\"color:#0000ff\">") +
314 apiVariantToString(m_argValues[i]) +
315 QLatin1Literal("</span>");
316 if (i < m_argNames.count() - 1)
317 m_richText += QLatin1String(", ");
319 m_richText += QLatin1String(")");
321 if (m_returnValue.isValid()) {
323 QLatin1String(" = ") +
324 QLatin1String("<span style=\"color:#0000ff\">") +
325 apiVariantToString(m_returnValue) +
326 QLatin1String("</span>");
328 m_richText.squeeze();
332 QString ApiTraceCall::filterText() const
334 if (!m_filterText.isEmpty())
337 m_filterText = m_name + QLatin1Literal("(");
338 for (int i = 0; i < m_argNames.count(); ++i) {
339 m_filterText += m_argNames[i] +
340 QLatin1Literal(" = ") +
341 apiVariantToString(m_argValues[i]);
342 if (m_argValues[i].type() == QVariant::ByteArray) {
343 m_hasBinaryData = true;
344 m_binaryDataIndex = i;
346 if (i < m_argNames.count() - 1)
347 m_filterText += QLatin1String(", ");
349 m_filterText += QLatin1String(")");
351 if (m_returnValue.isValid()) {
352 m_filterText += QLatin1Literal(" = ") +
353 apiVariantToString(m_returnValue);
355 m_filterText.squeeze();
359 QStaticText ApiTraceFrame::staticText() const
361 if (m_staticText && !m_staticText->text().isEmpty())
362 return *m_staticText;
365 QString::fromLatin1("<span style=\"font-weight:bold\">Frame %1</span>").arg(number);
368 m_staticText = new QStaticText(richText);
371 opt.setWrapMode(QTextOption::NoWrap);
372 m_staticText->setTextOption(opt);
373 m_staticText->prepare();
375 return *m_staticText;
378 int ApiTraceCall::numChildren() const
383 int ApiTraceFrame::numChildren() const
385 return calls.count();
388 ApiTraceFrame::ApiTraceFrame()
389 : ApiTraceEvent(ApiTraceEvent::Frame)
393 ApiTraceCall::ApiTraceCall()
394 : ApiTraceEvent(ApiTraceEvent::Call),
395 m_hasBinaryData(false),
400 ApiTraceEvent::ApiTraceEvent()
401 : m_type(ApiTraceEvent::None),
406 ApiTraceEvent::ApiTraceEvent(Type t)
412 ApiTraceCall::~ApiTraceCall()
416 QVariantMap ApiTraceEvent::stateParameters() const
418 return m_state.parameters();
421 ApiTraceState ApiTraceEvent::state() const
426 void ApiTraceEvent::setState(const ApiTraceState &state)
431 bool ApiTraceCall::hasBinaryData() const
433 return m_hasBinaryData;
436 int ApiTraceCall::binaryDataIndex() const
438 return m_binaryDataIndex;
441 ApiTraceState::ApiTraceState()
445 ApiTraceState::ApiTraceState(const QVariantMap &parsedJson)
447 m_parameters = parsedJson[QLatin1String("parameters")].toMap();
448 QVariantMap attachedShaders =
449 parsedJson[QLatin1String("shaders")].toMap();
450 QVariantMap::const_iterator itr;
453 for (itr = attachedShaders.constBegin(); itr != attachedShaders.constEnd();
455 QString type = itr.key();
456 QString source = itr.value().toString();
457 m_shaderSources[type] = source;
460 QVariantList textureUnits =
461 parsedJson[QLatin1String("textures")].toList();
462 for (int i = 0; i < textureUnits.count(); ++i) {
463 QVariantMap unit = textureUnits[i].toMap();
464 for (itr = unit.constBegin(); itr != unit.constEnd(); ++itr) {
465 QVariantMap target = itr.value().toMap();
466 if (target.count()) {
467 QVariantList levels = target[QLatin1String("levels")].toList();
468 for (int j = 0; j < levels.count(); ++j) {
469 QVariantMap level = levels[j].toMap();
470 QVariantMap image = level[QLatin1String("image")].toMap();
471 QSize size(image[QLatin1String("__width__")].toInt(),
472 image[QLatin1String("__height__")].toInt());
473 QString cls = image[QLatin1String("__class__")].toString();
474 QString type = image[QLatin1String("__type__")].toString();
476 image[QLatin1String("__normalized__")].toBool();
478 image[QLatin1String("__channels__")].toInt();
480 Q_ASSERT(type == QLatin1String("uint8"));
481 Q_ASSERT(normalized == true);
483 QByteArray dataArray =
484 image[QLatin1String("__data__")].toByteArray();
488 tex.setNumChannels(numChannels);
491 tex.setTarget(itr.key());
492 tex.contentsFromBase64(dataArray);
494 m_textures.append(tex);
501 parsedJson[QLatin1String("framebuffer")].toMap();
502 for (itr = fbos.constBegin(); itr != fbos.constEnd(); ++itr) {
503 QVariantMap buffer = itr.value().toMap();
504 QSize size(buffer[QLatin1String("__width__")].toInt(),
505 buffer[QLatin1String("__height__")].toInt());
506 QString cls = buffer[QLatin1String("__class__")].toString();
507 QString type = buffer[QLatin1String("__type__")].toString();
508 bool normalized = buffer[QLatin1String("__normalized__")].toBool();
509 int numChannels = buffer[QLatin1String("__channels__")].toInt();
511 Q_ASSERT(type == QLatin1String("uint8"));
512 Q_ASSERT(normalized == true);
514 QByteArray dataArray =
515 buffer[QLatin1String("__data__")].toByteArray();
519 fbo.setNumChannels(numChannels);
520 fbo.setType(itr.key());
521 fbo.contentsFromBase64(dataArray);
522 m_framebuffers.append(fbo);
526 QVariantMap ApiTraceState::parameters() const
531 QMap<QString, QString> ApiTraceState::shaderSources() const
533 return m_shaderSources;
536 bool ApiTraceState::isEmpty() const
538 return m_parameters.isEmpty();
541 QList<ApiTexture> ApiTraceState::textures() const
546 QList<ApiFramebuffer> ApiTraceState::framebuffers() const
548 return m_framebuffers;
551 QList<QVariant> ApiArray::values() const
556 int ApiTraceCall::index() const
561 QString ApiTraceCall::name() const
566 QStringList ApiTraceCall::argNames() const
571 QVariantList ApiTraceCall::arguments() const
576 QVariant ApiTraceCall::returnValue() const
578 return m_returnValue;
581 QUrl ApiTraceCall::helpUrl() const
586 ApiTraceCall::ApiTraceCall(const Trace::Call *call)
587 : ApiTraceEvent(ApiTraceEvent::Call),
588 m_hasBinaryData(false),
591 m_name = QString::fromStdString(call->sig->name);
594 QString argumentsText;
595 for (int i = 0; i < call->sig->arg_names.size(); ++i) {
597 QString::fromStdString(call->sig->arg_names[i]);
600 VariantVisitor retVisitor;
601 call->ret->visit(retVisitor);
602 m_returnValue = retVisitor.variant();
604 for (int i = 0; i < call->args.size(); ++i) {
605 VariantVisitor argVisitor;
606 call->args[i]->visit(argVisitor);
607 m_argValues += argVisitor.variant();
610 //FIXME: this is a nasty hack. Trace::Blob's can't
611 // delete the contents in the destructor because
612 // the data is being used by other calls. we should
613 // use something like Boost's shared_ptr or
614 // Qt's QSharedPointer to handle it.
615 Trace::Blob *b = dynamic_cast<Trace::Blob*>(call->args[i]);
616 if (b && b->blob()) {
617 char *buf = (char*)b->blob();
624 void ApiTraceCall::setHelpUrl(const QUrl &url)
629 void ApiTraceCall::setParentFrame(ApiTraceFrame *frame)
631 m_parentFrame = frame;
634 ApiTraceFrame * ApiTraceCall::parentFrame()const
636 return m_parentFrame;
639 ApiTraceEvent::~ApiTraceEvent()
644 void ApiTraceCall::revert()