1 #include "apitracecall.h"
3 #include "trace_model.hpp"
8 ApiPointer::ApiPointer(int val)
13 QString ApiPointer::toString() const
16 return QString("0x%1").arg(m_value, 0, 16);
18 return QLatin1String("NULL");
21 QString apiVariantToString(const QVariant &variant)
23 if (variant.userType() == QVariant::Double) {
24 return QString::number(variant.toFloat());
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);
31 float kb = variant.toByteArray().size()/1024.;
32 return QObject::tr("[binary data, size = %1 kb]").arg(kb);
36 if (variant.userType() < QVariant::UserType) {
37 return variant.toString();
40 if (variant.canConvert<ApiPointer>()) {
41 return variant.value<ApiPointer>().toString();
43 if (variant.canConvert<ApiBitmask>()) {
44 return variant.value<ApiBitmask>().toString();
46 if (variant.canConvert<ApiStruct>()) {
47 return variant.value<ApiStruct>().toString();
49 if (variant.canConvert<ApiArray>()) {
50 return variant.value<ApiArray>().toString();
56 ApiBitmask::ApiBitmask(const Trace::Bitmask *bitmask)
63 void ApiBitmask::init(const Trace::Bitmask *bitmask)
68 m_value = bitmask->value;
69 for (Trace::Bitmask::Signature::const_iterator it = bitmask->sig->begin();
70 it != bitmask->sig->end(); ++it) {
72 QPair<QString, unsigned long long> pair;
74 pair.first = QString::fromStdString(it->first);
75 pair.second = it->second;
81 QString ApiBitmask::toString() const
84 unsigned long long value = m_value;
86 for (Signature::const_iterator it = m_sig.begin();
87 value != 0 && it != m_sig.end(); ++it) {
89 if ((value & it->second) == it->second) {
91 str += QLatin1String(" | ");
100 str += QLatin1String(" | ");
102 str += QString::fromLatin1("0x%1").arg(value, 0, 16);
107 ApiStruct::ApiStruct(const Trace::Struct *s)
112 QString ApiStruct::toString() const
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(", ");
124 str += QLatin1String("}");
129 void ApiStruct::init(const Trace::Struct *s)
134 m_sig.name = QString::fromStdString(s->sig->name);
135 for (unsigned i = 0; i < s->members.size(); ++i) {
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());
144 void VariantVisitor::visit(Trace::Null *)
146 m_variant = QVariant(QLatin1String("NULL"));
149 void VariantVisitor::visit(Trace::Bool *node)
151 m_variant = QVariant(node->value);
154 void VariantVisitor::visit(Trace::SInt *node)
156 m_variant = QVariant(node->value);
159 void VariantVisitor::visit(Trace::UInt *node)
161 m_variant = QVariant(node->value);
164 void VariantVisitor::visit(Trace::Float *node)
166 m_variant = QVariant(node->value);
169 void VariantVisitor::visit(Trace::String *node)
171 m_variant = QVariant(QString::fromStdString(node->value));
174 void VariantVisitor::visit(Trace::Enum *e)
176 m_variant = QVariant(QString::fromStdString(e->sig->first));
179 void VariantVisitor::visit(Trace::Bitmask *bitmask)
181 m_variant = QVariant::fromValue(ApiBitmask(bitmask));
184 void VariantVisitor::visit(Trace::Struct *str)
186 m_variant = QVariant::fromValue(ApiStruct(str));
189 void VariantVisitor::visit(Trace::Array *array)
191 m_variant = QVariant::fromValue(ApiArray(array));
194 void VariantVisitor::visit(Trace::Blob *blob)
196 QByteArray barray = QByteArray::fromRawData(blob->buf, blob->size);
197 m_variant = QVariant(barray);
200 void VariantVisitor::visit(Trace::Pointer *ptr)
202 m_variant = QVariant::fromValue(ApiPointer(ptr->value));
205 ApiArray::ApiArray(const Trace::Array *arr)
210 ApiArray::ApiArray(const QList<QVariant> &vals)
215 QString ApiArray::toString() const
218 str += QLatin1String("[");
219 for(int i = 0; i < m_array.count(); ++i) {
220 const QVariant &var = m_array[i];
221 str += apiVariantToString(var);
222 if (i < m_array.count() - 1)
223 str += QLatin1String(", ");
225 str += QLatin1String("]");
230 void ApiArray::init(const Trace::Array *arr)
235 for (int i = 0; i < arr->values.size(); ++i) {
237 arr->values[i]->visit(vis);
239 m_array.append(vis.variant());
243 QStaticText ApiTraceCall::staticText() const
245 if (m_staticText && !m_staticText->text().isEmpty())
246 return *m_staticText;
248 QString richText = QString::fromLatin1(
249 "<span style=\"font-weight:bold\">%1</span>(").arg(m_name);
250 for (int i = 0; i < m_argNames.count(); ++i) {
251 richText += QLatin1String("<span style=\"color:#0000ff\">");
252 QString argText = apiVariantToString(m_argValues[i]);
254 //if arguments are really long (e.g. shader text), cut them
256 if (argText.length() > 40) {
257 QString shortened = argText.mid(0, 40);
258 shortened[argText.length() - 5] = '.';
259 shortened[argText.length() - 4] = '.';
260 shortened[argText.length() - 3] = '.';
261 shortened[argText.length() - 2] = argText[argText.length() - 2];
262 shortened[argText.length() - 1] = argText[argText.length() - 1];
263 richText += shortened;
267 richText += QLatin1String("</span>");
268 if (i < m_argNames.count() - 1)
269 richText += QString::fromLatin1(", ");
271 richText += QLatin1String(")");
272 if (m_returnValue.isValid()) {
273 richText += QLatin1String(" = ");
274 richText += QLatin1String("<span style=\"color:#0000ff\">");
275 richText += apiVariantToString(m_returnValue);
276 richText += QLatin1String("</span>");
280 m_staticText = new QStaticText(richText);
282 opt.setWrapMode(QTextOption::NoWrap);
283 m_staticText->setTextOption(opt);
284 m_staticText->prepare();
286 return *m_staticText;
289 QString ApiTraceCall::toHtml() const
291 if (!m_richText.isEmpty())
294 if (m_helpUrl.isEmpty()) {
295 m_richText = QString::fromLatin1(
296 "%1) <span style=\"font-weight:bold\">%2</span>(")
300 m_richText = QString::fromLatin1(
301 "%1) <span style=\"font-weight:bold\"><a href=\"%2\">%3</a></span>(")
303 .arg(m_helpUrl.toString())
307 for (int i = 0; i < m_argNames.count(); ++i) {
308 m_richText += m_argNames[i];
309 m_richText += QString::fromLatin1(" = ");
310 m_richText += QLatin1String("<span style=\"color:#0000ff\">");
311 m_richText += apiVariantToString(m_argValues[i]);
312 m_richText += QLatin1String("</span>");
313 if (i < m_argNames.count() - 1)
314 m_richText += QString::fromLatin1(", ");
316 m_richText += QLatin1String(")");
318 if (m_returnValue.isValid()) {
319 m_richText += QLatin1String(" = ");
320 m_richText += QLatin1String("<span style=\"color:#0000ff\">");
321 m_richText += apiVariantToString(m_returnValue);
322 m_richText += QLatin1String("</span>");
327 QString ApiTraceCall::filterText() const
329 if (!m_filterText.isEmpty())
332 m_filterText = m_name;
333 m_filterText += QLatin1String("(");
334 for (int i = 0; i < m_argNames.count(); ++i) {
335 m_filterText += m_argNames[i];
336 m_filterText += QString::fromLatin1(" = ");
338 if (m_argValues[i].type() == QVariant::ByteArray) {
339 m_hasBinaryData = true;
340 m_binaryDataIndex = i;
342 m_filterText += apiVariantToString(m_argValues[i]);
343 if (i < m_argNames.count() - 1)
344 m_filterText += QString::fromLatin1(", ");
346 m_filterText += QLatin1String(")");
348 if (m_returnValue.isValid()) {
349 m_filterText += QLatin1String(" = ");
350 m_filterText += apiVariantToString(m_returnValue);
355 QStaticText ApiTraceFrame::staticText() const
357 if (m_staticText && !m_staticText->text().isEmpty())
358 return *m_staticText;
361 QString::fromLatin1("<span style=\"font-weight:bold\">Frame %1</span>").arg(number);
364 m_staticText = new QStaticText(richText);
367 opt.setWrapMode(QTextOption::NoWrap);
368 m_staticText->setTextOption(opt);
369 m_staticText->prepare();
371 return *m_staticText;
374 int ApiTraceCall::numChildren() const
379 int ApiTraceFrame::numChildren() const
381 return calls.count();
384 ApiTraceFrame::ApiTraceFrame()
385 : ApiTraceEvent(ApiTraceEvent::Frame)
389 ApiTraceCall::ApiTraceCall()
390 : ApiTraceEvent(ApiTraceEvent::Call),
391 m_hasBinaryData(false),
396 ApiTraceEvent::ApiTraceEvent()
397 : m_type(ApiTraceEvent::None),
402 ApiTraceEvent::ApiTraceEvent(Type t)
408 ApiTraceCall::~ApiTraceCall()
412 QVariantMap ApiTraceEvent::stateParameters() const
414 return m_state.parameters();
417 ApiTraceState ApiTraceEvent::state() const
422 void ApiTraceEvent::setState(const ApiTraceState &state)
427 bool ApiTraceCall::hasBinaryData() const
429 return m_hasBinaryData;
432 int ApiTraceCall::binaryDataIndex() const
434 return m_binaryDataIndex;
437 ApiTraceState::ApiTraceState()
441 ApiTraceState::ApiTraceState(const QVariantMap &parsedJson)
443 m_parameters = parsedJson[QLatin1String("parameters")].toMap();
444 QVariantMap attachedShaders =
445 parsedJson[QLatin1String("shaders")].toMap();
446 QVariantMap::const_iterator itr;
449 for (itr = attachedShaders.constBegin(); itr != attachedShaders.constEnd(); ++itr) {
450 QString type = itr.key();
451 QString source = itr.value().toString();
452 m_shaderSources[type] = source;
455 QVariantList textureUnits =
456 parsedJson[QLatin1String("textures")].toList();
457 for (int i = 0; i < textureUnits.count(); ++i) {
458 QVariantMap unit = textureUnits[i].toMap();
459 for (itr = unit.constBegin(); itr != unit.constEnd(); ++itr) {
460 QVariantMap target = itr.value().toMap();
461 if (target.count()) {
462 QVariantList levels = target[QLatin1String("levels")].toList();
463 for (int j = 0; j < levels.count(); ++j) {
464 QVariantMap level = levels[j].toMap();
465 QVariantMap image = level[QLatin1String("image")].toMap();
466 QSize size(image[QLatin1String("__width__")].toInt(),
467 image[QLatin1String("__height__")].toInt());
468 QString cls = image[QLatin1String("__class__")].toString();
469 QString type = image[QLatin1String("__type__")].toString();
471 image[QLatin1String("__normalized__")].toBool();
473 image[QLatin1String("__channels__")].toInt();
475 Q_ASSERT(type == QLatin1String("uint8"));
476 Q_ASSERT(normalized == true);
478 QByteArray dataArray =
479 image[QLatin1String("__data__")].toByteArray();
483 tex.setNumChannels(numChannels);
486 tex.setTarget(itr.key());
487 tex.contentsFromBase64(dataArray);
489 m_textures.append(tex);
496 parsedJson[QLatin1String("framebuffer")].toMap();
497 for (itr = fbos.constBegin(); itr != fbos.constEnd(); ++itr) {
498 QVariantMap buffer = itr.value().toMap();
499 QSize size(buffer[QLatin1String("__width__")].toInt(),
500 buffer[QLatin1String("__height__")].toInt());
501 QString cls = buffer[QLatin1String("__class__")].toString();
502 QString type = buffer[QLatin1String("__type__")].toString();
503 bool normalized = buffer[QLatin1String("__normalized__")].toBool();
504 int numChannels = buffer[QLatin1String("__channels__")].toInt();
506 Q_ASSERT(type == QLatin1String("uint8"));
507 Q_ASSERT(normalized == true);
509 QByteArray dataArray =
510 buffer[QLatin1String("__data__")].toByteArray();
514 fbo.setNumChannels(numChannels);
515 fbo.setType(itr.key());
516 fbo.contentsFromBase64(dataArray);
517 m_framebuffers.append(fbo);
521 QVariantMap ApiTraceState::parameters() const
526 QMap<QString, QString> ApiTraceState::shaderSources() const
528 return m_shaderSources;
531 bool ApiTraceState::isEmpty() const
533 return m_parameters.isEmpty();
536 QList<ApiTexture> ApiTraceState::textures() const
541 QList<ApiFramebuffer> ApiTraceState::framebuffers() const
543 return m_framebuffers;
546 QList<QVariant> ApiArray::values() const
551 int ApiTraceCall::index() const
556 QString ApiTraceCall::name() const
561 QStringList ApiTraceCall::argNames() const
566 QVariantList ApiTraceCall::arguments() const
571 QVariant ApiTraceCall::returnValue() const
573 return m_returnValue;
576 QUrl ApiTraceCall::helpUrl() const
581 ApiTraceCall::ApiTraceCall(const Trace::Call *call)
582 : ApiTraceEvent(ApiTraceEvent::Call),
583 m_hasBinaryData(false),
586 m_name = QString::fromStdString(call->sig->name);
589 QString argumentsText;
590 for (int i = 0; i < call->sig->arg_names.size(); ++i) {
592 QString::fromStdString(call->sig->arg_names[i]);
595 VariantVisitor retVisitor;
596 call->ret->visit(retVisitor);
597 m_returnValue = retVisitor.variant();
599 for (int i = 0; i < call->args.size(); ++i) {
600 VariantVisitor argVisitor;
601 call->args[i]->visit(argVisitor);
602 m_argValues += argVisitor.variant();
605 //FIXME: this is a nasty hack. Trace::Blob's can't
606 // delete the contents in the destructor because
607 // the data is being used by other calls. we should
608 // use something like Boost's shared_ptr or
609 // Qt's QSharedPointer to handle it.
610 Trace::Blob *b = dynamic_cast<Trace::Blob*>(call->args[i]);
611 if (b && b->blob()) {
612 char *buf = (char*)b->blob();
619 void ApiTraceCall::setHelpUrl(const QUrl &url)
624 void ApiTraceCall::setParentFrame(ApiTraceFrame *frame)
626 m_parentFrame = frame;
629 ApiTraceFrame * ApiTraceCall::parentFrame()const
631 return m_parentFrame;
634 ApiTraceEvent::~ApiTraceEvent()