X-Git-Url: https://git.cworth.org/git?a=blobdiff_plain;f=gui%2Fapitracecall.cpp;h=33774861013cc99165c323800a09f6cbef0fc1ac;hb=HEAD;hp=ea1b3e2785e1a4293f2f09fa3dd99cc79a37597e;hpb=35c2793ac758997a0a1c2e558d384ab94754987d;p=apitrace diff --git a/gui/apitracecall.cpp b/gui/apitracecall.cpp index ea1b3e2..3377486 100644 --- a/gui/apitracecall.cpp +++ b/gui/apitracecall.cpp @@ -1,6 +1,7 @@ #include "apitracecall.h" #include "apitrace.h" +#include "traceloader.h" #include "trace_model.hpp" #include @@ -15,7 +16,7 @@ const char * const styleSheet = " font-weight:bold;\n" // text shadow looks great but doesn't work well in qtwebkit 4.7 " /*text-shadow: 0px 2px 3px #555;*/\n" - " font-size: 1.2em;\n" + " font-size: 1.1em;\n" "}\n" ".arg-name {\n" " border: 1px solid rgb(238,206,0);\n" @@ -100,9 +101,16 @@ plainTextToHTML(const QString & plain, bool multiLine) QString apiVariantToString(const QVariant &variant, bool multiLine) { - if (variant.userType() == QVariant::Double) { + if (variant.isNull()) { + return QLatin1String("?"); + } + + if (variant.userType() == QMetaType::Float) { return QString::number(variant.toFloat()); } + if (variant.userType() == QVariant::Double) { + return QString::number(variant.toDouble()); + } if (variant.userType() == QVariant::ByteArray) { if (variant.toByteArray().size() < 1024) { int bytes = variant.toByteArray().size(); @@ -128,10 +136,10 @@ apiVariantToString(const QVariant &variant, bool multiLine) return variant.value().toString(); } if (variant.canConvert()) { - return variant.value().toString(); + return variant.value().toString(multiLine); } if (variant.canConvert()) { - return variant.value().toString(); + return variant.value().toString(multiLine); } if (variant.canConvert()) { return variant.value().toString(); @@ -141,99 +149,123 @@ apiVariantToString(const QVariant &variant, bool multiLine) } -void VariantVisitor::visit(Trace::Null *) +void VariantVisitor::visit(trace::Null *) { m_variant = QVariant::fromValue(ApiPointer(0)); } -void VariantVisitor::visit(Trace::Bool *node) +void VariantVisitor::visit(trace::Bool *node) { m_variant = QVariant(node->value); } -void VariantVisitor::visit(Trace::SInt *node) +void VariantVisitor::visit(trace::SInt *node) { m_variant = QVariant(node->value); } -void VariantVisitor::visit(Trace::UInt *node) +void VariantVisitor::visit(trace::UInt *node) { m_variant = QVariant(node->value); } -void VariantVisitor::visit(Trace::Float *node) +void VariantVisitor::visit(trace::Float *node) { m_variant = QVariant(node->value); } -void VariantVisitor::visit(Trace::String *node) +void VariantVisitor::visit(trace::Double *node) +{ + m_variant = QVariant(node->value); +} + +void VariantVisitor::visit(trace::String *node) { m_variant = QVariant(QString::fromStdString(node->value)); } -void VariantVisitor::visit(Trace::Enum *e) +void VariantVisitor::visit(trace::Enum *e) { ApiTraceEnumSignature *sig = 0; - if (m_trace) { - sig = m_trace->enumSignature(e->sig->id); + if (m_loader) { + sig = m_loader->enumSignature(e->sig->id); } if (!sig) { - sig = new ApiTraceEnumSignature( - QString::fromStdString(e->sig->name), - QVariant(e->sig->value)); - if (m_trace) { - m_trace->addEnumSignature(e->sig->id, sig); + sig = new ApiTraceEnumSignature(e->sig); + if (m_loader) { + m_loader->addEnumSignature(e->sig->id, sig); } } - m_variant = QVariant::fromValue(ApiEnum(sig)); + m_variant = QVariant::fromValue(ApiEnum(sig, e->value)); } -void VariantVisitor::visit(Trace::Bitmask *bitmask) +void VariantVisitor::visit(trace::Bitmask *bitmask) { m_variant = QVariant::fromValue(ApiBitmask(bitmask)); } -void VariantVisitor::visit(Trace::Struct *str) +void VariantVisitor::visit(trace::Struct *str) { m_variant = QVariant::fromValue(ApiStruct(str)); } -void VariantVisitor::visit(Trace::Array *array) +void VariantVisitor::visit(trace::Array *array) { m_variant = QVariant::fromValue(ApiArray(array)); } -void VariantVisitor::visit(Trace::Blob *blob) +void VariantVisitor::visit(trace::Blob *blob) { - //XXX - //FIXME: this is a nasty hack. Trace::Blob's can't - // delete the contents in the destructor because - // the data is being used by other calls. We piggy back - // on that assumption and don't deep copy the data. If - // Blob's will start deleting the data we will need to - // start deep copying it or switch to using something like - // Boost's shared_ptr or Qt's QSharedPointer to handle it - QByteArray barray = QByteArray::fromRawData(blob->buf, blob->size); + QByteArray barray = QByteArray(blob->buf, blob->size); m_variant = QVariant(barray); } -void VariantVisitor::visit(Trace::Pointer *ptr) +void VariantVisitor::visit(trace::Pointer *ptr) { m_variant = QVariant::fromValue(ApiPointer(ptr->value)); } +void VariantVisitor::visit(trace::Repr *repr) +{ + /* TODO: Preserve both the human and machine value */ + repr->humanValue->visit(*this); +} + +ApiTraceEnumSignature::ApiTraceEnumSignature(const trace::EnumSig *sig) +{ + for (const trace::EnumValue *it = sig->values; + it != sig->values + sig->num_values; ++it) { + QPair pair; + + pair.first = QString::fromStdString(it->name); + pair.second = it->value; + + m_names.append(pair); + } +} + +QString ApiTraceEnumSignature::name(signed long long value) const +{ + for (ValueList::const_iterator it = m_names.begin(); + it != m_names.end(); ++it) { + if (value == it->second) { + return it->first; + } + } + return QString::fromLatin1("%1").arg(value); +} -ApiEnum::ApiEnum(ApiTraceEnumSignature *sig) - : m_sig(sig) +ApiEnum::ApiEnum(ApiTraceEnumSignature *sig, signed long long value) + : m_sig(sig), m_value(value) { } QString ApiEnum::toString() const { if (m_sig) { - return m_sig->name(); + return m_sig->name(m_value); } Q_ASSERT(!"should never happen"); return QString(); @@ -242,7 +274,7 @@ QString ApiEnum::toString() const QVariant ApiEnum::value() const { if (m_sig) { - return m_sig->value(); + return QVariant::fromValue(m_value); } Q_ASSERT(!"should never happen"); return QVariant(); @@ -251,7 +283,7 @@ QVariant ApiEnum::value() const QString ApiEnum::name() const { if (m_sig) { - return m_sig->name(); + return m_sig->name(m_value); } Q_ASSERT(!"should never happen"); return QString(); @@ -296,21 +328,20 @@ QString ApiPointer::toString() const return QLatin1String("NULL"); } -ApiBitmask::ApiBitmask(const Trace::Bitmask *bitmask) +ApiBitmask::ApiBitmask(const trace::Bitmask *bitmask) : m_value(0) { init(bitmask); } -void ApiBitmask::init(const Trace::Bitmask *bitmask) +void ApiBitmask::init(const trace::Bitmask *bitmask) { if (!bitmask) return; m_value = bitmask->value; - for (const Trace::BitmaskFlag *it = bitmask->sig->flags; + for (const trace::BitmaskFlag *it = bitmask->sig->flags; it != bitmask->sig->flags + bitmask->sig->num_flags; ++it) { - assert(it->value); QPair pair; pair.first = QString::fromStdString(it->name); @@ -325,10 +356,10 @@ QString ApiBitmask::toString() const QString str; unsigned long long value = m_value; bool first = true; - for (Signature::const_iterator it = m_sig.begin(); - value != 0 && it != m_sig.end(); ++it) { - Q_ASSERT(it->second); - if ((value & it->second) == it->second) { + for (Signature::const_iterator it = m_sig.begin(); it != m_sig.end(); ++it) { + Q_ASSERT(it->second || first); + if ((it->second && (value & it->second) == it->second) || + (!it->second && value == 0)) { if (!first) { str += QLatin1String(" | "); } @@ -336,6 +367,9 @@ QString ApiBitmask::toString() const value &= ~it->second; first = false; } + if (value == 0) { + break; + } } if (value || first) { if (!first) { @@ -346,12 +380,12 @@ QString ApiBitmask::toString() const return str; } -ApiStruct::ApiStruct(const Trace::Struct *s) +ApiStruct::ApiStruct(const trace::Struct *s) { init(s); } -QString ApiStruct::toString() const +QString ApiStruct::toString(bool multiLine) const { QString str; @@ -359,7 +393,7 @@ QString ApiStruct::toString() const for (unsigned i = 0; i < m_members.count(); ++i) { str += m_sig.memberNames[i] % QLatin1Literal(" = ") % - apiVariantToString(m_members[i]); + apiVariantToString(m_members[i], multiLine); if (i < m_members.count() - 1) str += QLatin1String(", "); } @@ -368,7 +402,7 @@ QString ApiStruct::toString() const return str; } -void ApiStruct::init(const Trace::Struct *s) +void ApiStruct::init(const trace::Struct *s) { if (!s) return; @@ -383,28 +417,28 @@ void ApiStruct::init(const Trace::Struct *s) } } -ApiArray::ApiArray(const Trace::Array *arr) +ApiArray::ApiArray(const trace::Array *arr) { init(arr); } -ApiArray::ApiArray(const QList &vals) +ApiArray::ApiArray(const QVector &vals) : m_array(vals) { } -QList ApiArray::values() const +QVector ApiArray::values() const { return m_array; } -QString ApiArray::toString() const +QString ApiArray::toString(bool multiLine) const { QString str; str += QLatin1String("["); for(int i = 0; i < m_array.count(); ++i) { const QVariant &var = m_array[i]; - str += apiVariantToString(var); + str += apiVariantToString(var, multiLine); if (i < m_array.count() - 1) str += QLatin1String(", "); } @@ -413,7 +447,7 @@ QString ApiArray::toString() const return str; } -void ApiArray::init(const Trace::Array *arr) +void ApiArray::init(const trace::Array *arr) { if (!arr) return; @@ -425,6 +459,7 @@ void ApiArray::init(const Trace::Array *arr) m_array.append(vis.variant()); } + m_array.squeeze(); } ApiTraceState::ApiTraceState() @@ -455,22 +490,18 @@ ApiTraceState::ApiTraceState(const QVariantMap &parsedJson) QSize size(image[QLatin1String("__width__")].toInt(), image[QLatin1String("__height__")].toInt()); QString cls = image[QLatin1String("__class__")].toString(); - QString type = image[QLatin1String("__type__")].toString(); - bool normalized = - image[QLatin1String("__normalized__")].toBool(); - int numChannels = - image[QLatin1String("__channels__")].toInt(); - - Q_ASSERT(type == QLatin1String("uint8")); - Q_ASSERT(normalized == true); - Q_UNUSED(normalized); + int depth = + image[QLatin1String("__depth__")].toInt(); + QString formatName = + image[QLatin1String("__format__")].toString(); QByteArray dataArray = image[QLatin1String("__data__")].toByteArray(); ApiTexture tex; tex.setSize(size); - tex.setNumChannels(numChannels); + tex.setDepth(depth); + tex.setFormatName(formatName); tex.setLabel(itr.key()); tex.contentsFromBase64(dataArray); @@ -484,20 +515,16 @@ ApiTraceState::ApiTraceState(const QVariantMap &parsedJson) QSize size(buffer[QLatin1String("__width__")].toInt(), buffer[QLatin1String("__height__")].toInt()); QString cls = buffer[QLatin1String("__class__")].toString(); - QString type = buffer[QLatin1String("__type__")].toString(); - bool normalized = buffer[QLatin1String("__normalized__")].toBool(); - int numChannels = buffer[QLatin1String("__channels__")].toInt(); - - Q_ASSERT(type == QLatin1String("uint8")); - Q_ASSERT(normalized == true); - Q_UNUSED(normalized); + int depth = buffer[QLatin1String("__depth__")].toInt(); + QString formatName = buffer[QLatin1String("__format__")].toString(); QByteArray dataArray = buffer[QLatin1String("__data__")].toByteArray(); ApiFramebuffer fbo; fbo.setSize(size); - fbo.setNumChannels(numChannels); + fbo.setDepth(depth); + fbo.setFormatName(formatName); fbo.setType(itr.key()); fbo.contentsFromBase64(dataArray); m_framebuffers.append(fbo); @@ -521,7 +548,10 @@ const QVariantMap & ApiTraceState::uniforms() const bool ApiTraceState::isEmpty() const { - return m_parameters.isEmpty(); + return m_parameters.isEmpty() && + m_shaderSources.isEmpty() && + m_textures.isEmpty() && + m_framebuffers.isEmpty(); } const QList & ApiTraceState::textures() const @@ -534,6 +564,22 @@ const QList & ApiTraceState::framebuffers() const return m_framebuffers; } +ApiFramebuffer ApiTraceState::colorBuffer() const +{ + foreach (ApiFramebuffer fbo, m_framebuffers) { + if (fbo.type() == QLatin1String("GL_BACK")) { + return fbo; + } + } + foreach (ApiFramebuffer fbo, m_framebuffers) { + if (fbo.type() == QLatin1String("GL_FRONT")) { + return fbo; + } + } + return ApiFramebuffer(); +} + + ApiTraceCallSignature::ApiTraceCallSignature(const QString &name, const QStringList &argNames) : m_name(name), @@ -598,17 +644,15 @@ void ApiTraceEvent::setState(ApiTraceState *state) m_state = state; } -ApiTraceCall::ApiTraceCall(ApiTraceFrame *parentFrame, const Trace::Call *call) +ApiTraceCall::ApiTraceCall(ApiTraceFrame *parentFrame, + TraceLoader *loader, + const trace::Call *call) : ApiTraceEvent(ApiTraceEvent::Call), m_parentFrame(parentFrame) { - ApiTrace *trace = parentTrace(); - - Q_ASSERT(trace); - m_index = call->no; - m_signature = trace->signature(call->sig->id); + m_signature = loader->signature(call->sig->id); if (!m_signature) { QString name = QString::fromStdString(call->sig->name); @@ -618,23 +662,29 @@ ApiTraceCall::ApiTraceCall(ApiTraceFrame *parentFrame, const Trace::Call *call) argNames += QString::fromStdString(call->sig->arg_names[i]); } m_signature = new ApiTraceCallSignature(name, argNames); - trace->addSignature(call->sig->id, m_signature); + loader->addSignature(call->sig->id, m_signature); } if (call->ret) { - VariantVisitor retVisitor(trace); + VariantVisitor retVisitor(loader); call->ret->visit(retVisitor); m_returnValue = retVisitor.variant(); } m_argValues.reserve(call->args.size()); for (int i = 0; i < call->args.size(); ++i) { - VariantVisitor argVisitor(trace); - call->args[i]->visit(argVisitor); - m_argValues.append(argVisitor.variant()); - if (m_argValues[i].type() == QVariant::ByteArray) { - m_hasBinaryData = true; - m_binaryDataIndex = i; + if (call->args[i].value) { + VariantVisitor argVisitor(loader); + call->args[i].value->visit(argVisitor); + m_argValues.append(argVisitor.variant()); + if (m_argValues[i].type() == QVariant::ByteArray) { + m_hasBinaryData = true; + m_binaryDataIndex = i; + } + } else { + m_argValues.append(QVariant()); } } + m_argValues.squeeze(); + m_flags = call->flags; } ApiTraceCall::~ApiTraceCall() @@ -655,11 +705,8 @@ QString ApiTraceCall::error() const void ApiTraceCall::setError(const QString &msg) { if (m_error != msg) { - ApiTrace *trace = parentTrace(); m_error = msg; m_richText = QString(); - if (trace) - trace->callError(this); } } @@ -670,12 +717,12 @@ ApiTrace * ApiTraceCall::parentTrace() const return NULL; } -QVariantList ApiTraceCall::originalValues() const +QVector ApiTraceCall::originalValues() const { return m_argValues; } -void ApiTraceCall::setEditedValues(const QVariantList &lst) +void ApiTraceCall::setEditedValues(const QVector &lst) { ApiTrace *trace = parentTrace(); @@ -695,7 +742,7 @@ void ApiTraceCall::setEditedValues(const QVariantList &lst) } } -QVariantList ApiTraceCall::editedValues() const +QVector ApiTraceCall::editedValues() const { return m_editedValues; } @@ -707,7 +754,7 @@ bool ApiTraceCall::edited() const void ApiTraceCall::revert() { - setEditedValues(QVariantList()); + setEditedValues(QVector()); } void ApiTraceCall::setHelpUrl(const QUrl &url) @@ -740,7 +787,7 @@ QStringList ApiTraceCall::argNames() const return m_signature->argNames(); } -QVariantList ApiTraceCall::arguments() const +QVector ApiTraceCall::arguments() const { if (m_editedValues.isEmpty()) return m_argValues; @@ -753,6 +800,11 @@ QVariant ApiTraceCall::returnValue() const return m_returnValue; } +trace::CallFlags ApiTraceCall::flags() const +{ + return m_flags; +} + QUrl ApiTraceCall::helpUrl() const { return m_signature->helpUrl(); @@ -773,7 +825,7 @@ QStaticText ApiTraceCall::staticText() const if (m_staticText && !m_staticText->text().isEmpty()) return *m_staticText; - QVariantList argValues = arguments(); + QVector argValues = arguments(); QString richText = QString::fromLatin1( "%1(").arg( @@ -826,23 +878,33 @@ QString ApiTraceCall::toHtml() const if (!m_richText.isEmpty()) return m_richText; - m_richText = QLatin1String("
"); + m_richText += QLatin1String("
"); + + m_richText += + QString::fromLatin1("%1) ") + .arg(m_index); + QString parentTip; + if (m_parentFrame) { + parentTip = + QString::fromLatin1("Frame %1") + .arg(m_parentFrame->number); + } QUrl helpUrl = m_signature->helpUrl(); if (helpUrl.isEmpty()) { m_richText += QString::fromLatin1( - "%1) %2(") - .arg(m_index) + "%2(") + .arg(parentTip) .arg(m_signature->name()); } else { m_richText += QString::fromLatin1( - "%1) %3(") - .arg(m_index) + "%3(") + .arg(parentTip) .arg(helpUrl.toString()) .arg(m_signature->name()); } - QVariantList argValues = arguments(); + QVector argValues = arguments(); QStringList argNames = m_signature->argNames(); for (int i = 0; i < argNames.count(); ++i) { m_richText += @@ -892,7 +954,7 @@ QString ApiTraceCall::searchText() const if (!m_searchText.isEmpty()) return m_searchText; - QVariantList argValues = arguments(); + QVector argValues = arguments(); m_searchText = m_signature->name() + QLatin1Literal("("); QStringList argNames = m_signature->argNames(); for (int i = 0; i < argNames.count(); ++i) { @@ -917,35 +979,51 @@ int ApiTraceCall::numChildren() const return 0; } +bool ApiTraceCall::contains(const QString &str, + Qt::CaseSensitivity sensitivity) const +{ + QString txt = searchText(); + return txt.contains(str, sensitivity); +} + + ApiTraceFrame::ApiTraceFrame(ApiTrace *parentTrace) : ApiTraceEvent(ApiTraceEvent::Frame), m_parentTrace(parentTrace), - m_binaryDataSize(0) + m_binaryDataSize(0), + m_loaded(false), + m_callsToLoad(0), + m_lastCallIndex(0) { } +ApiTraceFrame::~ApiTraceFrame() +{ + qDeleteAll(m_calls); +} + QStaticText ApiTraceFrame::staticText() const { if (m_staticText && !m_staticText->text().isEmpty()) return *m_staticText; - QString richText; + QString richText = QObject::tr( + "Frame %1" + "   " + " " + "(%2 calls)") + .arg(number) + .arg(m_loaded ? m_calls.count() : m_callsToLoad); //mark the frame if it uploads more than a meg a frame if (m_binaryDataSize > (1024*1024)) { richText = QObject::tr( - "" - "Frame %1" + "%1" "" "    (%2MB)") - .arg(number) + .arg(richText) .arg(double(m_binaryDataSize / (1024.*1024.)), 0, 'g', 2); - } else { - richText = - QObject::tr( - "Frame %1") - .arg(number); } if (!m_staticText) @@ -979,7 +1057,7 @@ void ApiTraceFrame::addCall(ApiTraceCall *call) } } -QList ApiTraceFrame::calls() const +QVector ApiTraceFrame::calls() const { return m_calls; } @@ -989,6 +1067,18 @@ ApiTraceCall * ApiTraceFrame::call(int idx) const return m_calls.value(idx); } + +ApiTraceCall * ApiTraceFrame::callWithIndex(int index) const +{ + QVector::const_iterator itr; + for (itr = m_calls.constBegin(); itr != m_calls.constEnd(); ++itr) { + if ((*itr)->index() == index) { + return *itr; + } + } + return 0; +} + int ApiTraceFrame::callIndex(ApiTraceCall *call) const { return m_calls.indexOf(call); @@ -996,10 +1086,117 @@ int ApiTraceFrame::callIndex(ApiTraceCall *call) const bool ApiTraceFrame::isEmpty() const { - return m_calls.isEmpty(); + if (m_loaded) { + return m_calls.isEmpty(); + } else { + return m_callsToLoad == 0; + } } int ApiTraceFrame::binaryDataSize() const { return m_binaryDataSize; } + +void ApiTraceFrame::setCalls(const QVector &calls, + quint64 binaryDataSize) +{ + m_calls = calls; + m_binaryDataSize = binaryDataSize; + m_loaded = true; + delete m_staticText; + m_staticText = 0; +} + +bool ApiTraceFrame::isLoaded() const +{ + return m_loaded; +} + +void ApiTraceFrame::setLoaded(bool l) +{ + m_loaded = l; +} + +void ApiTraceFrame::setNumChildren(int num) +{ + m_callsToLoad = num; +} + +void ApiTraceFrame::setParentTrace(ApiTrace *parent) +{ + m_parentTrace = parent; +} + +int ApiTraceFrame::numChildrenToLoad() const +{ + return m_callsToLoad; +} + +ApiTraceCall * +ApiTraceFrame::findNextCall(ApiTraceCall *from, + const QString &str, + Qt::CaseSensitivity sensitivity) const +{ + Q_ASSERT(m_loaded); + + int callIndex = 0; + + if (from) { + callIndex = m_calls.indexOf(from) + 1; + } + + for (int i = callIndex; i < m_calls.count(); ++i) { + ApiTraceCall *call = m_calls[i]; + if (call->contains(str, sensitivity)) { + return call; + } + } + return 0; +} + +ApiTraceCall * +ApiTraceFrame::findPrevCall(ApiTraceCall *from, + const QString &str, + Qt::CaseSensitivity sensitivity) const +{ + Q_ASSERT(m_loaded); + + int callIndex = m_calls.count() - 1; + + if (from) { + callIndex = m_calls.indexOf(from) - 1; + } + + for (int i = callIndex; i >= 0; --i) { + ApiTraceCall *call = m_calls[i]; + if (call->contains(str, sensitivity)) { + return call; + } + } + return 0; +} + +void ApiTraceFrame::setLastCallIndex(unsigned index) +{ + m_lastCallIndex = index; +} + +unsigned ApiTraceFrame::lastCallIndex() const +{ + if (m_loaded && !m_calls.isEmpty()) { + return m_calls.last()->index(); + } else { + return m_lastCallIndex; + } +} + +void ApiTraceFrame::setThumbnail(const QImage & thumbnail) +{ + m_thumbnail = thumbnail; +} + +const QImage & ApiTraceFrame::thumbnail() const +{ + return m_thumbnail; +}