From: Zack Rusin Date: Mon, 18 Apr 2011 02:56:58 +0000 (-0400) Subject: Implement a bulk of trace saving. X-Git-Url: https://git.cworth.org/git?a=commitdiff_plain;h=c6247ddb0c7d2e26302727069703217d6107546e;p=apitrace Implement a bulk of trace saving. --- diff --git a/gui/CMakeLists.txt b/gui/CMakeLists.txt index fdc6c13..b8d5a69 100644 --- a/gui/CMakeLists.txt +++ b/gui/CMakeLists.txt @@ -16,6 +16,7 @@ set(qapitrace_SRCS mainwindow.cpp main.cpp retracer.cpp + saverthread.cpp searchwidget.cpp settingsdialog.cpp shaderssourcewidget.cpp diff --git a/gui/apitracecall.cpp b/gui/apitracecall.cpp index 6024b15..39e4f55 100644 --- a/gui/apitracecall.cpp +++ b/gui/apitracecall.cpp @@ -8,7 +8,7 @@ #define QT_USE_FAST_OPERATOR_PLUS #include -ApiPointer::ApiPointer(int val) +ApiPointer::ApiPointer(unsigned long long val) : m_value(val) { } @@ -722,3 +722,28 @@ QString ApiEnum::name() const return m_name; } +unsigned long long ApiBitmask::value() const +{ + return m_value; +} + +ApiBitmask::Signature ApiBitmask::signature() const +{ + return m_sig; +} + +ApiStruct::Signature ApiStruct::signature() const +{ + return m_sig; +} + +QList ApiStruct::values() const +{ + return m_members; +} + +unsigned long long ApiPointer::value() const +{ + return m_value; +} + diff --git a/gui/apitracecall.h b/gui/apitracecall.h index 1b4e5ab..59c6fe7 100644 --- a/gui/apitracecall.h +++ b/gui/apitracecall.h @@ -55,11 +55,14 @@ Q_DECLARE_METATYPE(ApiEnum); class ApiPointer { public: - ApiPointer(int val=0); + ApiPointer(unsigned long long val=0); QString toString() const; + + unsigned long long value() const; + private: - int m_value; + unsigned long long m_value; }; Q_DECLARE_METATYPE(ApiPointer); @@ -72,6 +75,9 @@ public: QString toString() const; + unsigned long long value() const; + Signature signature() const; + private: void init(const Trace::Bitmask *bitmask); private: @@ -91,6 +97,8 @@ public: ApiStruct(const Trace::Struct *s = 0); QString toString() const; + Signature signature() const; + QList values() const; private: void init(const Trace::Struct *bitmask); diff --git a/gui/saverthread.cpp b/gui/saverthread.cpp new file mode 100644 index 0000000..e45e025 --- /dev/null +++ b/gui/saverthread.cpp @@ -0,0 +1,238 @@ +#include "saverthread.h" + +#include "trace_write.hpp" + +#include +#include +#include + +#include + + +static Trace::FunctionSig * +createFunctionSig(ApiTraceCall *call, unsigned id) +{ + Trace::FunctionSig *sig = new Trace::FunctionSig(); + + sig->id = id; + sig->name = qstrdup(call->name().toLocal8Bit()); + + QStringList args = call->argNames(); + sig->num_args = args.count(); + sig->args = new const char*[args.count()]; + for (int i = 0; i < args.count(); ++i) { + sig->args[i] = qstrdup(args[i].toLocal8Bit()); + } + + return sig; +} + +static void +deleteFunctionSig(Trace::FunctionSig *sig) +{ + for (int i = 0; i < sig->num_args; ++i) { + delete [] sig->args[i]; + } + delete [] sig->args; + delete [] sig->name; + delete sig; +} + +static Trace::StructSig * +createStructSig(const ApiStruct &str, unsigned id) +{ + ApiStruct::Signature aSig = str.signature(); + + Trace::StructSig *sig = new Trace::StructSig(); + sig->id = id; + sig->name = qstrdup(aSig.name.toLocal8Bit()); + sig->num_members = aSig.memberNames.count(); + char **members = new char*[aSig.memberNames.count()]; + sig->members = (const char **)members; + for (int i = 0; i < aSig.memberNames.count(); ++i) { + members[i] = qstrdup(aSig.memberNames[i].toLocal8Bit()); + } + return sig; +} + +static void +deleteStructSig(Trace::StructSig *sig) +{ + for (int i = 0; i < sig->num_members; ++i) { + delete [] sig->members[i]; + } + delete [] sig->members; + delete [] sig->name; + delete sig; +} + +static Trace::EnumSig * +createEnumSig(const ApiEnum &en, unsigned id) +{ + Trace::EnumSig *sig = new Trace::EnumSig(); + + sig->id = id; + sig->name = qstrdup(en.name().toLocal8Bit()); + sig->value = en.value().toLongLong(); + + return sig; +} + +static void +deleteEnumSig(Trace::EnumSig *sig) +{ + delete [] sig->name; + delete sig; +} + +static Trace::BitmaskSig * +createBitmaskSig(const ApiBitmask &bt, unsigned id) +{ + ApiBitmask::Signature bsig = bt.signature(); + ApiBitmask::Signature::const_iterator itr; + + Trace::BitmaskSig *sig = new Trace::BitmaskSig(); + Trace::BitmaskVal *values = new Trace::BitmaskVal[bsig.count()]; + + sig->id = id; + sig->count = bsig.count(); + sig->values = values; + + int i = 0; + for (itr != bsig.constBegin(); itr != bsig.constEnd(); ++itr, ++i) { + values[i].name = qstrdup(itr->first.toLocal8Bit()); + values[i].value = itr->second; + } + + return sig; +} + +static void +deleteBitmaskSig(Trace::BitmaskSig *sig) +{ + for (int i = 0; i < sig->count; ++i) { + delete [] sig->values[i].name; + } + delete [] sig->values; + delete sig; +} + +static void +writeArgument(const QVariant &var, unsigned &id) +{ + int arrayType = QMetaType::type("ApiArray"); + int bitmaskType = QMetaType::type("ApiBitmask"); + int structType = QMetaType::type("ApiStruct"); + int pointerType = QMetaType::type("ApiPointer"); + int enumType = QMetaType::type("ApiEnum"); + int type = var.userType(); + + switch(type) { + case QVariant::Bool: + case QVariant::ByteArray: + case QVariant::Double: + case QVariant::Int: + case QVariant::LongLong: + case QVariant::String: + case QVariant::UInt: + case QVariant::ULongLong: + default: + if (type == arrayType) { + ApiArray array = var.value(); + QList vals = array.values(); + Trace::BeginArray(vals.count()); + foreach(QVariant el, vals) { + Trace::BeginElement(); + writeArgument(el, ++id); + Trace::EndElement(); + } + Trace::EndArray(); + } else if (type == bitmaskType) { + ApiBitmask bm = var.value(); + Trace::BitmaskSig *sig = createBitmaskSig(bm, ++id); + LiteralBitmask(*sig, bm.value()); + deleteBitmaskSig(sig); + } else if (type == structType) { + ApiStruct apiStr = var.value(); + QList vals = apiStr.values(); + Trace::StructSig *str = createStructSig(apiStr, ++id); + Trace::BeginStruct(str); + foreach(QVariant val, vals) { + writeArgument(val, ++id); + } + Trace::EndStruct(); + deleteStructSig(str); + } else if (type == pointerType) { + ApiPointer apiPtr = var.value(); + Trace::BeginArray(1); + Trace::BeginElement(); + Trace::LiteralOpaque((const void*)apiPtr.value()); + Trace::EndElement(); + Trace::EndArray(); + } else if (type == enumType) { + ApiEnum apiEnum = var.value(); + Trace::EnumSig *sig = createEnumSig(apiEnum, ++id); + Trace::LiteralEnum(sig); + deleteEnumSig(sig); + } else if (type == QVariant::ByteArray) { + + } else { + qWarning()<<"Unsupported write variant : " + << QMetaType::typeName(type); + } + } + +} + + +SaverThread::SaverThread(QObject *parent) + : QThread(parent) +{ +} + +void SaverThread::saveFile(const QString &fileName, + const QList &calls) +{ + m_fileName = fileName; + m_calls = calls; + start(); +} + +void SaverThread::run() +{ + + Trace::Open(); + unsigned id = 0; + + for (int i = 0; i < m_calls.count(); ++i) { + ApiTraceCall *call = m_calls[i]; + Trace::FunctionSig *funcSig = createFunctionSig(call, ++id); + unsigned callNo = BeginEnter(*funcSig); + { + //args + QVariantList vars = call->arguments(); + foreach(QVariant var, vars) { + writeArgument(var, id); + } + } + Trace::EndEnter(); + Trace::BeginLeave(callNo); + { + QVariant ret = call->returnValue(); + if (!ret.isNull()) { + Trace::BeginReturn(); + writeArgument(ret, id); + Trace::EndReturn(); + } + } + Trace::EndLeave(); + + deleteFunctionSig(funcSig); + } + + Trace::Close(); + + emit traceSaved(m_fileName); +} + +#include "saverthread.moc" diff --git a/gui/saverthread.h b/gui/saverthread.h new file mode 100644 index 0000000..d39d51b --- /dev/null +++ b/gui/saverthread.h @@ -0,0 +1,34 @@ +#ifndef SAVERTHREAD_H +#define SAVERTHREAD_H + + +#include "apitrace.h" +#include +#include + +class ApiTraceCall; +class ApiTraceFrame; + +class SaverThread : public QThread +{ + Q_OBJECT +public: + SaverThread(QObject *parent=0); + +public slots: + void saveFile(const QString &fileName, + const QList &calls); + +signals: + void traceSaved(const QString &fileName); + +protected: + virtual void run(); + +private: + QString m_fileName; + QList m_calls; +}; + + +#endif