]> git.cworth.org Git - apitrace/blobdiff - gui/apitracecall.cpp
Use skiplist-based FastCallSet within trace::CallSet
[apitrace] / gui / apitracecall.cpp
index 4063bf0c283cab627f1df0898c96bcf6955618f7..33774861013cc99165c323800a09f6cbef0fc1ac 100644 (file)
@@ -16,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"
@@ -101,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();
@@ -129,10 +136,10 @@ apiVariantToString(const QVariant &variant, bool multiLine)
         return variant.value<ApiBitmask>().toString();
     }
     if (variant.canConvert<ApiStruct>()) {
-        return variant.value<ApiStruct>().toString();
+        return variant.value<ApiStruct>().toString(multiLine);
     }
     if (variant.canConvert<ApiArray>()) {
-        return variant.value<ApiArray>().toString();
+        return variant.value<ApiArray>().toString(multiLine);
     }
     if (variant.canConvert<ApiEnum>()) {
         return variant.value<ApiEnum>().toString();
@@ -142,37 +149,42 @@ 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)
 {
     m_variant = QVariant(node->value);
 }
 
-void VariantVisitor::visit(Trace::SInt *node)
+void VariantVisitor::visit(trace::UInt *node)
 {
     m_variant = QVariant(node->value);
 }
 
-void VariantVisitor::visit(Trace::UInt *node)
+void VariantVisitor::visit(trace::Float *node)
 {
     m_variant = QVariant(node->value);
 }
 
-void VariantVisitor::visit(Trace::Float *node)
+void VariantVisitor::visit(trace::Double *node)
 {
     m_variant = QVariant(node->value);
 }
 
-void VariantVisitor::visit(Trace::String *node)
+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;
 
@@ -180,62 +192,80 @@ void VariantVisitor::visit(Trace::Enum *e)
         sig = m_loader->enumSignature(e->sig->id);
     }
     if (!sig) {
-        sig = new ApiTraceEnumSignature(
-            QString::fromStdString(e->sig->name),
-            QVariant(e->sig->value));
+        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
-    blob->toPointer(true);
-    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);
+}
 
-ApiEnum::ApiEnum(ApiTraceEnumSignature *sig)
-    : m_sig(sig)
+ApiTraceEnumSignature::ApiTraceEnumSignature(const trace::EnumSig *sig)
+{
+    for (const trace::EnumValue *it = sig->values;
+         it != sig->values + sig->num_values; ++it) {
+        QPair<QString, signed long long> 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, 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();
@@ -244,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();
@@ -253,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();
@@ -298,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<QString, unsigned long long> pair;
 
         pair.first = QString::fromStdString(it->name);
@@ -327,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(" | ");
             }
@@ -338,6 +367,9 @@ QString ApiBitmask::toString() const
             value &= ~it->second;
             first = false;
         }
+        if (value == 0) {
+            break;
+        }
     }
     if (value || first) {
         if (!first) {
@@ -348,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;
 
@@ -361,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(", ");
     }
@@ -370,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;
@@ -385,7 +417,7 @@ void ApiStruct::init(const Trace::Struct *s)
     }
 }
 
-ApiArray::ApiArray(const Trace::Array *arr)
+ApiArray::ApiArray(const trace::Array *arr)
 {
     init(arr);
 }
@@ -400,13 +432,13 @@ QVector<QVariant> 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(", ");
     }
@@ -415,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;
@@ -458,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);
 
@@ -487,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);
@@ -524,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<ApiTexture> & ApiTraceState::textures() const
@@ -537,6 +564,22 @@ const QList<ApiFramebuffer> & 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),
@@ -603,7 +646,7 @@ void ApiTraceEvent::setState(ApiTraceState *state)
 
 ApiTraceCall::ApiTraceCall(ApiTraceFrame *parentFrame,
                            TraceLoader *loader,
-                           const Trace::Call *call)
+                           const trace::Call *call)
     : ApiTraceEvent(ApiTraceEvent::Call),
       m_parentFrame(parentFrame)
 {
@@ -628,15 +671,20 @@ ApiTraceCall::ApiTraceCall(ApiTraceFrame *parentFrame,
     }
     m_argValues.reserve(call->args.size());
     for (int i = 0; i < call->args.size(); ++i) {
-        VariantVisitor argVisitor(loader);
-        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()
@@ -657,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);
     }
 }
 
@@ -755,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();
@@ -828,18 +878,28 @@ QString ApiTraceCall::toHtml() const
     if (!m_richText.isEmpty())
         return m_richText;
 
-    m_richText = QLatin1String("<div class=\"call\">");
+    m_richText += QLatin1String("<div class=\"call\">");
 
+
+    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) <span class=\"callName\">%2</span>(")
-                      .arg(m_index)
+            "<span class=\"callName\" title=\"%1\">%2</span>(")
+                      .arg(parentTip)
                       .arg(m_signature->name());
     } else {
         m_richText += QString::fromLatin1(
-            "%1) <span class=\"callName\"><a href=\"%2\">%3</a></span>(")
-                      .arg(m_index)
+         "<span class=\"callName\" title=\"%1\"><a href=\"%2\">%3</a></span>(")
+                      .arg(parentTip)
                       .arg(helpUrl.toString())
                       .arg(m_signature->name());
     }
@@ -932,32 +992,38 @@ ApiTraceFrame::ApiTraceFrame(ApiTrace *parentTrace)
       m_parentTrace(parentTrace),
       m_binaryDataSize(0),
       m_loaded(false),
-      m_callsToLoad(0)
+      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(
+                "<span style=\"font-weight:bold\">Frame %1</span>"
+                "&nbsp;&nbsp;&nbsp;"
+                "<span style=\"font-style:italic;font-size:small;font-weight:lighter;\"> "
+                "(%2 calls)</span>")
+            .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(
-                "<span style=\"font-weight:bold;\">"
-                "Frame&nbsp;%1</span>"
+                "%1"
                 "<span style=\"font-style:italic;\">"
                 "&nbsp;&nbsp;&nbsp;&nbsp;(%2MB)</span>")
-            .arg(number)
+            .arg(richText)
             .arg(double(m_binaryDataSize / (1024.*1024.)), 0, 'g', 2);
-    } else {
-        richText =
-            QObject::tr(
-                "<span style=\"font-weight:bold\">Frame %1</span>")
-            .arg(number);
     }
 
     if (!m_staticText)
@@ -1038,9 +1104,11 @@ void ApiTraceFrame::setCalls(const QVector<ApiTraceCall*> &calls,
     m_calls = calls;
     m_binaryDataSize = binaryDataSize;
     m_loaded = true;
+    delete m_staticText;
+    m_staticText = 0;
 }
 
-bool ApiTraceFrame::loaded() const
+bool ApiTraceFrame::isLoaded() const
 {
     return m_loaded;
 }
@@ -1108,3 +1176,27 @@ ApiTraceFrame::findPrevCall(ApiTraceCall *from,
     }
     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;
+}