]> git.cworth.org Git - apitrace/commitdiff
Add code to interpret and display binary vertex data.
authorZack Rusin <zack@kde.org>
Thu, 7 Apr 2011 05:15:48 +0000 (01:15 -0400)
committerZack Rusin <zack@kde.org>
Thu, 7 Apr 2011 05:15:48 +0000 (01:15 -0400)
gui/CMakeLists.txt
gui/apitracecall.cpp
gui/apitracecall.h
gui/mainwindow.cpp
gui/mainwindow.h
gui/ui/mainwindow.ui
gui/vertexdatainterpreter.cpp [new file with mode: 0644]
gui/vertexdatainterpreter.h [new file with mode: 0644]

index 620f4249359c49c879b2ce6385926507e9fba5cc..632a441447a192bfa670f46e8ee8f80d4826cabb 100644 (file)
@@ -9,6 +9,7 @@ set(qapitrace_SRCS
    main.cpp
    retracer.cpp
    settingsdialog.cpp
+   vertexdatainterpreter.cpp
  )
 
 qt4_automoc(${qapitrace_SRCS})
index 4817eb389e00760115a4bfa187c031228ee500c8..8c6359cd74fdc062dde5238f69d648312566ff4f 100644 (file)
@@ -24,8 +24,13 @@ QString apiVariantToString(const QVariant &variant)
         return QString::number(variant.toFloat());
     }
     if (variant.userType() == QVariant::ByteArray) {
-        float kb = variant.toByteArray().size()/1024.;
-        return QObject::tr("[binary data, size = %1kb]").arg(kb);
+        if (variant.toByteArray().size() < 1024) {
+            int bytes = variant.toByteArray().size();
+            return QObject::tr("[binary data, size = %1 bytes]").arg(bytes);
+        } else {
+            float kb = variant.toByteArray().size()/1024.;
+            return QObject::tr("[binary data, size = %1 kb]").arg(kb);
+        }
     }
 
     if (variant.userType() < QVariant::UserType) {
@@ -311,6 +316,11 @@ QString ApiTraceCall::filterText() const
     for (int i = 0; i < argNames.count(); ++i) {
         m_filterText += argNames[i];
         m_filterText += QString::fromLatin1(" = ");
+
+        if (argValues[i].type() == QVariant::ByteArray) {
+            m_hasBinaryData = true;
+            m_binaryDataIndex = i;
+        }
         m_filterText += apiVariantToString(argValues[i]);
         if (i < argNames.count() - 1)
             m_filterText += QString::fromLatin1(", ");
@@ -357,7 +367,9 @@ ApiTraceFrame::ApiTraceFrame()
 }
 
 ApiTraceCall::ApiTraceCall()
-    : ApiTraceEvent(ApiTraceEvent::Call)
+    : ApiTraceEvent(ApiTraceEvent::Call),
+      m_hasBinaryData(false),
+      m_binaryDataIndex(0)
 {
 }
 
@@ -384,3 +396,13 @@ void ApiTraceEvent::setState(const QVariantMap &state)
 {
     m_state = state;
 }
+
+bool ApiTraceCall::hasBinaryData() const
+{
+    return m_hasBinaryData;
+}
+
+int ApiTraceCall::binaryDataIndex() const
+{
+    return m_binaryDataIndex;
+}
index c69a484e392947b8147dd87406c12827b24a15de..809a6c1053b1558e6272e1bd7f2fb7a655c03a83 100644 (file)
@@ -143,10 +143,14 @@ public:
     QString filterText() const;
     QStaticText staticText() const;
     int numChildren() const;
+    bool hasBinaryData() const;
+    int binaryDataIndex() const;
 private:
     mutable QString m_richText;
     mutable QString m_filterText;
     mutable QStaticText m_staticText;
+    mutable bool m_hasBinaryData;
+    mutable int m_binaryDataIndex;
 };
 Q_DECLARE_METATYPE(ApiTraceCall*);
 
index f67b654c79171de93a3c80b39260fdff8a696b1e..dee53d95494665c1872b122156c479097f46bac8 100644 (file)
@@ -7,6 +7,7 @@
 #include "apitracefilter.h"
 #include "retracer.h"
 #include "settingsdialog.h"
+#include "vertexdatainterpreter.h"
 
 #include <qjson/parser.h>
 
@@ -42,6 +43,24 @@ MainWindow::MainWindow()
     connect(m_retracer, SIGNAL(error(const QString&)),
             this, SLOT(replayError(const QString&)));
 
+    m_vdataInterpreter = new VertexDataInterpreter(this);
+    m_vdataInterpreter->setListWidget(m_ui.vertexDataListWidget);
+    m_vdataInterpreter->setStride(
+        m_ui.vertexStrideSB->value());
+    m_vdataInterpreter->setComponents(
+        m_ui.vertexComponentsSB->value());
+    m_vdataInterpreter->setTypeFromString(
+        m_ui.vertexTypeCB->currentText());
+
+    connect(m_ui.vertexInterpretButton, SIGNAL(clicked()),
+            m_vdataInterpreter, SLOT(interpretData()));
+    connect(m_ui.vertexTypeCB, SIGNAL(activated(const QString&)),
+            m_vdataInterpreter, SLOT(setTypeFromString(const QString&)));
+    connect(m_ui.vertexStrideSB, SIGNAL(valueChanged(int)),
+            m_vdataInterpreter, SLOT(setStride(int)));
+    connect(m_ui.vertexComponentsSB, SIGNAL(valueChanged(int)),
+            m_vdataInterpreter, SLOT(setComponents(int)));
+
     m_model = new ApiTraceModel();
     m_model->setApiTrace(m_trace);
     m_proxyModel = new ApiTraceFilter();
@@ -62,7 +81,11 @@ MainWindow::MainWindow()
     m_progressBar->hide();
 
     m_ui.detailsDock->hide();
+    m_ui.vertexDataDock->hide();
     m_ui.stateDock->hide();
+    setDockOptions(dockOptions() | QMainWindow::ForceTabbedDocks);
+
+    tabifyDockWidget(m_ui.stateDock, m_ui.vertexDataDock);
 
     connect(m_ui.actionOpen, SIGNAL(triggered()),
             this, SLOT(openTrace()));
@@ -120,6 +143,28 @@ void MainWindow::callItemSelected(const QModelIndex &index)
         ApiTraceCall *call = static_cast<ApiTraceCall*>(event);
         m_ui.detailsWebView->setHtml(call->toHtml());
         m_ui.detailsDock->show();
+        if (call->hasBinaryData()) {
+            QByteArray data =
+                call->argValues[call->binaryDataIndex()].toByteArray();
+            m_vdataInterpreter->setData(data);
+
+            for (int i = 0; i < call->argNames.count(); ++i) {
+                QString name = call->argNames[i];
+                if (name == QLatin1String("stride")) {
+                    int stride = call->argValues[i].toInt();
+                    m_ui.vertexStrideSB->setValue(stride);
+                } else if (name == QLatin1String("size")) {
+                    int components = call->argValues[i].toInt();
+                    m_ui.vertexComponentsSB->setValue(components);
+                } else if (name == QLatin1String("type")) {
+                    QString val = call->argValues[i].toString();
+                    int textIndex = m_ui.vertexTypeCB->findText(val);
+                    if (textIndex >= 0)
+                        m_ui.vertexTypeCB->setCurrentIndex(textIndex);
+                }
+            }
+        }
+        m_ui.vertexDataDock->setVisible(call->hasBinaryData());
         m_selectedEvent = call;
     } else {
         if (event && event->type() == ApiTraceEvent::Frame) {
@@ -127,6 +172,7 @@ void MainWindow::callItemSelected(const QModelIndex &index)
         } else
             m_selectedEvent = 0;
         m_ui.detailsDock->hide();
+        m_ui.vertexDataDock->hide();
     }
     if (m_selectedEvent && !m_selectedEvent->state().isEmpty()) {
         fillStateForFrame();
index 9d0c15e49b851d4f1306cd13fd8953f806a644e4..78a8d6f55383e31a6d2111d1a7249bb77910b744 100644 (file)
@@ -15,6 +15,7 @@ class QLineEdit;
 class QModelIndex;
 class QProgressBar;
 class Retracer;
+class VertexDataInterpreter;
 
 namespace QJson {
     class Parser;
@@ -67,6 +68,8 @@ private:
     QJson::Parser *m_jsonParser;
 
     Retracer *m_retracer;
+
+    VertexDataInterpreter *m_vdataInterpreter;
 };
 
 
index 76e0e8b412b089dd27dc74b6bb08723b82311a96..6c7e25e5e667b81b55d005702b4fadbedd1ee074 100644 (file)
@@ -6,13 +6,22 @@
    <rect>
     <x>0</x>
     <y>0</y>
-    <width>760</width>
-    <height>422</height>
+    <width>787</width>
+    <height>758</height>
    </rect>
   </property>
   <property name="windowTitle">
    <string>ApiTrace</string>
   </property>
+  <property name="documentMode">
+   <bool>false</bool>
+  </property>
+  <property name="dockNestingEnabled">
+   <bool>false</bool>
+  </property>
+  <property name="dockOptions">
+   <set>QMainWindow::AnimatedDocks|QMainWindow::ForceTabbedDocks</set>
+  </property>
   <widget class="QWidget" name="centralwidget">
    <layout class="QHBoxLayout" name="horizontalLayout">
     <item>
@@ -35,7 +44,7 @@
     <rect>
      <x>0</x>
      <y>0</y>
-     <width>760</width>
+     <width>787</width>
      <height>21</height>
     </rect>
    </property>
    </widget>
   </widget>
   <widget class="QDockWidget" name="stateDock">
+   <property name="features">
+    <set>QDockWidget::AllDockWidgetFeatures</set>
+   </property>
    <property name="windowTitle">
     <string>Current State</string>
    </property>
     </layout>
    </widget>
   </widget>
+  <widget class="QDockWidget" name="vertexDataDock">
+   <property name="allowedAreas">
+    <set>Qt::AllDockWidgetAreas</set>
+   </property>
+   <property name="windowTitle">
+    <string>Vertex Data</string>
+   </property>
+   <attribute name="dockWidgetArea">
+    <number>2</number>
+   </attribute>
+   <widget class="QWidget" name="dockWidgetContents_3">
+    <layout class="QVBoxLayout" name="verticalLayout_2">
+     <item>
+      <layout class="QFormLayout" name="formLayout">
+       <item row="0" column="0">
+        <widget class="QLabel" name="label">
+         <property name="text">
+          <string>Type</string>
+         </property>
+        </widget>
+       </item>
+       <item row="0" column="1">
+        <widget class="QComboBox" name="vertexTypeCB">
+         <property name="currentIndex">
+          <number>6</number>
+         </property>
+         <item>
+          <property name="text">
+           <string>GL_BYTE</string>
+          </property>
+         </item>
+         <item>
+          <property name="text">
+           <string>GL_UNSIGNED_BYTE</string>
+          </property>
+         </item>
+         <item>
+          <property name="text">
+           <string>GL_SHORT</string>
+          </property>
+         </item>
+         <item>
+          <property name="text">
+           <string>GL_UNSIGNED_SHORT</string>
+          </property>
+         </item>
+         <item>
+          <property name="text">
+           <string>GL_INT</string>
+          </property>
+         </item>
+         <item>
+          <property name="text">
+           <string>GL_UNSIGNED_INT</string>
+          </property>
+         </item>
+         <item>
+          <property name="text">
+           <string>GL_FLOAT</string>
+          </property>
+         </item>
+        </widget>
+       </item>
+       <item row="1" column="0">
+        <widget class="QLabel" name="label_2">
+         <property name="text">
+          <string>Stride</string>
+         </property>
+        </widget>
+       </item>
+       <item row="1" column="1">
+        <widget class="QSpinBox" name="vertexStrideSB">
+         <property name="maximum">
+          <number>1000</number>
+         </property>
+         <property name="value">
+          <number>8</number>
+         </property>
+        </widget>
+       </item>
+       <item row="2" column="0">
+        <widget class="QLabel" name="label_4">
+         <property name="text">
+          <string>Components</string>
+         </property>
+        </widget>
+       </item>
+       <item row="2" column="1">
+        <widget class="QSpinBox" name="vertexComponentsSB">
+         <property name="maximum">
+          <number>256</number>
+         </property>
+         <property name="value">
+          <number>4</number>
+         </property>
+        </widget>
+       </item>
+       <item row="3" column="0" colspan="2">
+        <layout class="QHBoxLayout" name="horizontalLayout_3">
+         <item>
+          <spacer name="horizontalSpacer">
+           <property name="orientation">
+            <enum>Qt::Horizontal</enum>
+           </property>
+           <property name="sizeHint" stdset="0">
+            <size>
+             <width>40</width>
+             <height>20</height>
+            </size>
+           </property>
+          </spacer>
+         </item>
+         <item>
+          <widget class="QPushButton" name="vertexInterpretButton">
+           <property name="text">
+            <string>Interpret</string>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <spacer name="horizontalSpacer_2">
+           <property name="orientation">
+            <enum>Qt::Horizontal</enum>
+           </property>
+           <property name="sizeHint" stdset="0">
+            <size>
+             <width>40</width>
+             <height>20</height>
+            </size>
+           </property>
+          </spacer>
+         </item>
+        </layout>
+       </item>
+      </layout>
+     </item>
+     <item>
+      <widget class="QListWidget" name="vertexDataListWidget"/>
+     </item>
+    </layout>
+   </widget>
+  </widget>
   <action name="actionExit">
    <property name="text">
     <string>Exit</string>
     <string>Options</string>
    </property>
   </action>
+  <zorder>stateDock</zorder>
+  <zorder>vertexDataDock</zorder>
  </widget>
  <customwidgets>
   <customwidget>
diff --git a/gui/vertexdatainterpreter.cpp b/gui/vertexdatainterpreter.cpp
new file mode 100644 (file)
index 0000000..e00466b
--- /dev/null
@@ -0,0 +1,204 @@
+#include "vertexdatainterpreter.h"
+
+#include <QListWidget>
+#include <QStringList>
+
+#include <QDebug>
+
+#include <GL/gl.h>
+
+static int
+sizeForType(int glType)
+{
+    switch(glType) {
+    case GL_FLOAT:
+        return sizeof(GLfloat);
+    case GL_UNSIGNED_BYTE:
+        return sizeof(GLubyte);
+    case GL_BYTE:
+        return sizeof(GLbyte);
+    case GL_SHORT:
+        return sizeof(GLshort);
+    case GL_UNSIGNED_SHORT:
+        return sizeof(GLushort);
+    case GL_INT:
+        return sizeof(GLint);
+    case GL_UNSIGNED_INT:
+        return sizeof(GLuint);
+    default:
+        return sizeof(GLint);
+    }
+}
+
+template <typename T>
+static QStringList
+convertData(const QByteArray &dataArray,
+            int type,
+            int stride,
+            int numComponents)
+{
+    QStringList strings;
+
+    const char *data = dataArray.constData();
+    int typeSize = sizeForType(type);
+    int sizePerAttribute = typeSize;
+
+    if (stride)
+        sizePerAttribute = stride;
+
+    int numElements = dataArray.size() / sizePerAttribute;
+
+#if 0
+    qDebug() << "numElements = "<<numElements;
+    qDebug() << "sizePerAttribute = "<<sizePerAttribute;
+    qDebug() << "stride = "<<stride;
+    qDebug() << "numComponents = "<<numComponents;
+#endif
+
+    if (numElements * sizePerAttribute > dataArray.size()) {
+        qDebug()<<"Vertex data too large for the given binary data";
+        return strings;
+    }
+    if ((numElements % numComponents) != 0) {
+        qDebug()<<"Bad stride for the given vertex data";
+        return strings;
+    }
+
+    for (int i = 0; i < numElements; i += numComponents) {
+        QString vectorString = QString::fromLatin1("%1) [").arg(i / numComponents);
+        for (int j = 0; j < numComponents; ++j) {
+            int idx = i + j;
+            const T *elementPtr =
+                (const T*)(data + idx * sizePerAttribute);
+            T elem = *elementPtr;
+            vectorString += QString::number(elem);
+            if ((j + 1) < numComponents)
+                vectorString += QLatin1String(", ");
+        }
+        vectorString += "]";
+        strings += vectorString;
+    }
+
+    return strings;
+}
+
+
+VertexDataInterpreter::VertexDataInterpreter(QObject *parent)
+    : QObject(parent),
+      m_listWidget(0),
+      m_type(GL_FLOAT),
+      m_stride(16),
+      m_components(4)
+{
+}
+
+void VertexDataInterpreter::setData(const QByteArray &data)
+{
+    m_data = data;
+    if (m_listWidget)
+        m_listWidget->clear();
+}
+
+QByteArray VertexDataInterpreter::data() const
+{
+    return m_data;
+}
+
+void VertexDataInterpreter::setType(int type)
+{
+    m_type = type;
+}
+
+int VertexDataInterpreter::type() const
+{
+    return m_type;
+}
+
+void VertexDataInterpreter::setStride(int stride)
+{
+    m_stride = stride;
+}
+
+int VertexDataInterpreter::stride() const
+{
+    return m_stride;
+}
+
+void VertexDataInterpreter::setComponents(int num)
+{
+    m_components = num;
+}
+
+int VertexDataInterpreter::components() const
+{
+    return m_components;
+}
+
+void VertexDataInterpreter::setListWidget(QListWidget *listWidget)
+{
+    m_listWidget = listWidget;
+}
+
+void VertexDataInterpreter::interpretData()
+{
+    if (!m_listWidget)
+        return;
+
+    m_listWidget->clear();
+
+    if (m_data.isEmpty() || !m_components)
+        return;
+
+    QStringList lst;
+    switch(m_type) {
+    case GL_FLOAT:
+        lst = convertData<float>(m_data, m_type, m_stride, m_components);
+        break;
+    case GL_UNSIGNED_BYTE:
+        lst = convertData<quint8>(m_data, m_type, m_stride, m_components);
+        break;
+    case GL_BYTE:
+        lst = convertData<qint8>(m_data, m_type, m_stride, m_components);
+        break;
+    case GL_SHORT:
+        lst = convertData<qint16>(m_data, m_type, m_stride, m_components);
+        break;
+    case GL_UNSIGNED_SHORT:
+        lst = convertData<quint16>(m_data, m_type, m_stride, m_components);
+        break;
+    case GL_INT:
+        lst = convertData<unsigned int>(m_data, m_type, m_stride, m_components);
+        break;
+    case GL_UNSIGNED_INT:
+        lst = convertData<int>(m_data, m_type, m_stride, m_components);
+        break;
+    default:
+        qDebug()<<"unkown gltype = "<<m_type;
+    }
+    //qDebug()<<"list is "<<lst;
+    m_listWidget->addItems(lst);
+}
+
+
+void VertexDataInterpreter::setTypeFromString(const QString &str)
+{
+    if (str == QLatin1String("GL_FLOAT")) {
+        setType(GL_FLOAT);
+    } else if (str == QLatin1String("GL_INT")) {
+        setType(GL_INT);
+    } else if (str == QLatin1String("GL_UNSIGNED_INT")) {
+        setType(GL_UNSIGNED_INT);
+    } else if (str == QLatin1String("GL_SHORT")) {
+        setType(GL_SHORT);
+    } else if (str == QLatin1String("GL_UNSIGNED_SHORT")) {
+        setType(GL_UNSIGNED_SHORT);
+    } else if (str == QLatin1String("GL_BYTE")) {
+        setType(GL_BYTE);
+    } else if (str == QLatin1String("GL_UNSIGNED_BYTE")) {
+        setType(GL_UNSIGNED_BYTE);
+    } else {
+        qDebug()<<"unknown vertex data type";
+    }
+}
+
+#include "vertexdatainterpreter.moc"
diff --git a/gui/vertexdatainterpreter.h b/gui/vertexdatainterpreter.h
new file mode 100644 (file)
index 0000000..8492593
--- /dev/null
@@ -0,0 +1,39 @@
+#ifndef VERTEXDATAINTERPRETER_H
+#define VERTEXDATAINTERPRETER_H
+
+#include <QObject>
+
+class QListWidget;
+
+class VertexDataInterpreter : public QObject
+{
+    Q_OBJECT
+public:
+    VertexDataInterpreter(QObject *parent=0);
+
+    QByteArray data() const;
+
+    int type() const;
+    int stride() const;
+    int components() const;
+
+    void setListWidget(QListWidget *listWidget);
+
+public slots:
+    void interpretData();
+
+    void setData(const QByteArray &data);
+    void setTypeFromString(const QString &str);
+    void setStride(int stride);
+    void setComponents(int num);
+    void setType(int type);
+
+private:
+    QListWidget *m_listWidget;
+    QByteArray m_data;
+    int m_type;
+    int m_stride;
+    int m_components;
+};
+
+#endif