summaryrefslogtreecommitdiff
path: root/retrace
diff options
context:
space:
mode:
Diffstat (limited to 'retrace')
-rw-r--r--retrace/daemon/ui/glframe_retrace_model.cpp1
-rw-r--r--retrace/daemon/ui/glframe_state_model.cpp60
-rw-r--r--retrace/daemon/ui/glframe_state_model.hpp15
-rw-r--r--retrace/daemon/ui/main.cpp11
-rw-r--r--retrace/daemon/ui/qml/StateControl.qml43
-rw-r--r--retrace/daemon/ui/qml/mainwin.qml9
-rw-r--r--retrace/daemon/ui/resources.qrc1
7 files changed, 115 insertions, 25 deletions
diff --git a/retrace/daemon/ui/glframe_retrace_model.cpp b/retrace/daemon/ui/glframe_retrace_model.cpp
index 63a355d8..1f00c148 100644
--- a/retrace/daemon/ui/glframe_retrace_model.cpp
+++ b/retrace/daemon/ui/glframe_retrace_model.cpp
@@ -638,5 +638,6 @@ FrameRetraceModel::retrace_state() {
glretrace::renderSelectionFromList(m_selection_count,
m_cached_selection,
&sel);
+ m_stateModel->clear();
m_retrace.retraceState(sel, m_experiment_count, this);
}
diff --git a/retrace/daemon/ui/glframe_state_model.cpp b/retrace/daemon/ui/glframe_state_model.cpp
index 5a0d47ff..4a3edc7a 100644
--- a/retrace/daemon/ui/glframe_state_model.cpp
+++ b/retrace/daemon/ui/glframe_state_model.cpp
@@ -40,17 +40,17 @@ QStateValue::QStateValue(const std::string &_name,
const std::vector<std::string> &_choices)
: m_name(_name.c_str()) {
for (auto c : _choices)
- m_choices.append(QString::fromStdString(c));
+ m_choices.append(QVariant(c.c_str()));
}
void
QStateValue::insert(int index, const std::string &value) {
while (m_values.size() < index)
- m_values.append(QString());
+ m_values.append("");
if (m_values.size() == index)
- m_values.append(QString::fromStdString(value));
+ m_values.append(value.c_str());
else
- m_values[index] = QString::fromStdString(value);
+ m_values[index] = QVariant(value.c_str());
}
QStateModel::QStateModel() {}
@@ -61,11 +61,7 @@ QStateModel::~QStateModel() {}
QQmlListProperty<QStateValue> QStateModel::state() {
ScopedLock s(m_protect);
- QList<QStateValue*> l;
- for (auto i : m_state_by_name)
- l.push_back(i.second);
-
- return QQmlListProperty<glretrace::QStateValue>(this, l);
+ return QQmlListProperty<glretrace::QStateValue>(this, m_states);
}
std::string
@@ -81,7 +77,7 @@ state_name_to_string(StateItem n) {
}
std::vector<std::string>
-name_to_choines(StateItem n) {
+name_to_choices(StateItem n) {
switch (n) {
case glretrace::CULL_FACE:
return {"true", "false"};
@@ -92,11 +88,49 @@ name_to_choines(StateItem n) {
}
}
+void
+QStateModel::clear() {
+ // QObjects being displayed in the UI must be cleared from the UI
+ // before being deleted. This routine is invoked in the UI thread
+ // (as opposed to the retrace thread). The emit with the empty
+ // states calls down into ::state() to retrieve the new empty list
+ // within a single thread. After emit, it is safe to delete the
+ // objects. Conversely, if these objects were cleaned up after an
+ // emit in the retrace thread, the request for updated state would
+ // be enqueued. The result is an asynchronous crash.
+ {
+ ScopedLock s(m_protect);
+ m_states.clear();
+ }
+ emit stateChanged();
+ {
+ ScopedLock s(m_protect);
+ for (auto i : m_state_by_name)
+ delete i.second;
+ m_state_by_name.clear();
+ }
+}
+
void QStateModel::onState(SelectionId selectionCount,
ExperimentId experimentCount,
RenderId renderId,
StateKey item,
const std::string &value) {
+ if (selectionCount == SelectionId(SelectionId::INVALID_SELECTION)) {
+ {
+ ScopedLock s(m_protect);
+ m_states.clear();
+ for (auto i : m_state_by_name)
+ m_states.push_back(i.second);
+ }
+ emit stateChanged();
+ return;
+ }
+
+ if ((selectionCount > m_sel_count) ||
+ (experimentCount > m_experiment_count))
+ clear();
+
ScopedLock s(m_protect);
if ((selectionCount > m_sel_count) ||
(experimentCount > m_experiment_count)) {
@@ -106,15 +140,11 @@ void QStateModel::onState(SelectionId selectionCount,
assert(selectionCount == m_sel_count);
assert(experimentCount == m_experiment_count);
}
- if (selectionCount == SelectionId(SelectionId::INVALID_SELECTION)) {
- emit stateChanged();
- return;
- }
const auto name = state_name_to_string(item.name);
auto state_value = m_state_by_name.find(name);
if (state_value == m_state_by_name.end()) {
QStateValue *i = new QStateValue(name,
- name_to_choines(item.name));
+ name_to_choices(item.name));
m_state_by_name[name] = i;
state_value = m_state_by_name.find(name);
}
diff --git a/retrace/daemon/ui/glframe_state_model.hpp b/retrace/daemon/ui/glframe_state_model.hpp
index f98ce463..7dd3b6ef 100644
--- a/retrace/daemon/ui/glframe_state_model.hpp
+++ b/retrace/daemon/ui/glframe_state_model.hpp
@@ -48,9 +48,8 @@ class QStateValue : public QObject, NoCopy, NoAssign, NoMove {
Q_OBJECT
Q_PROPERTY(QString name READ name CONSTANT)
- Q_PROPERTY(QList<QString> values READ values CONSTANT)
- // Q_PROPERTY(QUniformDimension dimension READ dimension CONSTANT)
- Q_PROPERTY(QList<QString> choices READ choices CONSTANT)
+ Q_PROPERTY(QList<QVariant> values READ values CONSTANT)
+ Q_PROPERTY(QList<QVariant> choices READ choices CONSTANT)
public:
QStateValue() {}
@@ -59,12 +58,12 @@ class QStateValue : public QObject, NoCopy, NoAssign, NoMove {
void insert(int index, const std::string &value);
QString name() const { return m_name; }
- QList<QString> values() const { return m_values; }
- QList<QString> choices() const { return m_choices; }
+ QList<QVariant> values() const { return m_values; }
+ QList<QVariant> choices() const { return m_choices; }
private:
QString m_name;
- QList<QString> m_values, m_choices;
+ QList<QVariant> m_values, m_choices;
};
class QStateModel : public QObject,
@@ -82,7 +81,7 @@ class QStateModel : public QObject,
RenderId renderId,
StateKey item,
const std::string &value);
- // void clear();
+ void clear();
Q_INVOKABLE void setState(const QString &name,
const int index,
const QString &value);
@@ -98,6 +97,8 @@ class QStateModel : public QObject,
ExperimentId m_experiment_count;
// typedef QList<QStateValue*> StateList;
std::map<std::string, QStateValue*> m_state_by_name;
+ QList<QStateValue*> m_states;
+ std::vector<QStateValue*> m_for_deletion;
mutable std::mutex m_protect;
};
diff --git a/retrace/daemon/ui/main.cpp b/retrace/daemon/ui/main.cpp
index 8dcca829..16f08073 100644
--- a/retrace/daemon/ui/main.cpp
+++ b/retrace/daemon/ui/main.cpp
@@ -53,6 +53,7 @@
#include "glframe_retrace_stub.hpp"
#include "glframe_shader_model.hpp"
#include "glframe_socket.hpp"
+#include "glframe_state_model.hpp"
#include "glframe_uniform_model.hpp"
#include "glretrace.hpp"
@@ -103,7 +104,7 @@ int main(int argc, char *argv[]) {
qmlRegisterType<glretrace::FrameRetraceModel>("ApiTrace", 1, 0,
"FrameRetrace");
qmlRegisterType<glretrace::QMetricValue>("ApiTrace", 1, 0,
- "QMetricValue");
+ "QMetricValue");
qmlRegisterType<glretrace::QMetricsModel>("ApiTrace", 1, 0,
"QMetricsModel");
@@ -117,15 +118,19 @@ int main(int argc, char *argv[]) {
qmlRegisterType<glretrace::QApiModel>("ApiTrace", 1, 0,
"QApiModel");
qmlRegisterType<glretrace::QBatchModel>("ApiTrace", 1, 0,
- "QBatchModel");
+ "QBatchModel");
qmlRegisterType<glretrace::QExperimentModel>("ApiTrace", 1, 0,
"QExperimentModel");
qmlRegisterType<glretrace::QRenderTargetModel>("ApiTrace", 1, 0,
"QRenderTargetModel");
qmlRegisterType<glretrace::QUniformValue>("ApiTrace", 1, 0,
- "QUniformValue");
+ "QUniformValue");
qmlRegisterType<glretrace::QUniformsModel>("ApiTrace", 1, 0,
"QUniformsModel");
+ qmlRegisterType<glretrace::QStateModel>("ApiTrace", 1, 0,
+ "QStateModel");
+ qmlRegisterType<glretrace::QStateValue>("ApiTrace", 1, 0,
+ "QStateValue");
glretrace::FrameImages::Create();
diff --git a/retrace/daemon/ui/qml/StateControl.qml b/retrace/daemon/ui/qml/StateControl.qml
new file mode 100644
index 00000000..7b182d39
--- /dev/null
+++ b/retrace/daemon/ui/qml/StateControl.qml
@@ -0,0 +1,43 @@
+import QtQuick 2.2
+import QtQuick.Controls 1.1
+import QtQuick.Layouts 1.1
+import ApiTrace 1.0
+
+Item {
+ property QStateModel stateModel
+ ScrollView {
+ anchors.fill: parent
+ ListView {
+ id: stateList
+ model: stateModel.state
+ anchors.fill: parent
+ delegate: Component {
+ Column {
+ Text {
+ id: nameText
+ text: modelData.name
+ }
+ Row {
+ id: stateGrid
+ anchors.left: parent.left
+ anchors.right: parent.right
+ Repeater {
+ model: modelData.values
+ Rectangle {
+ width: stateText.width
+ height: stateText.height
+ anchors.margins:10
+ border.width: 1
+ Text {
+ id: stateText
+ anchors.centerIn: parent
+ text: modelData
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/retrace/daemon/ui/qml/mainwin.qml b/retrace/daemon/ui/qml/mainwin.qml
index 6ef554a8..12b3833c 100644
--- a/retrace/daemon/ui/qml/mainwin.qml
+++ b/retrace/daemon/ui/qml/mainwin.qml
@@ -388,6 +388,15 @@ ApplicationWindow {
uniformModel: frameRetrace.uniformModel
}
}
+ Tab {
+ title: "State"
+ id: stateTab
+ anchors.fill: parent
+ clip: true
+ StateControl {
+ stateModel: frameRetrace.stateModel
+ }
+ }
}
}
}
diff --git a/retrace/daemon/ui/resources.qrc b/retrace/daemon/ui/resources.qrc
index 077b2858..c79c14d9 100644
--- a/retrace/daemon/ui/resources.qrc
+++ b/retrace/daemon/ui/resources.qrc
@@ -13,5 +13,6 @@
<file>qml/ExperimentControl.qml</file>
<file>qml/RenderTargetControl.qml</file>
<file>qml/UniformControl.qml</file>
+ <file>qml/StateControl.qml</file>
</qresource>
</RCC>