diff options
Diffstat (limited to 'retrace')
-rw-r--r-- | retrace/daemon/ui/glframe_retrace_model.cpp | 1 | ||||
-rw-r--r-- | retrace/daemon/ui/glframe_state_model.cpp | 60 | ||||
-rw-r--r-- | retrace/daemon/ui/glframe_state_model.hpp | 15 | ||||
-rw-r--r-- | retrace/daemon/ui/main.cpp | 11 | ||||
-rw-r--r-- | retrace/daemon/ui/qml/StateControl.qml | 43 | ||||
-rw-r--r-- | retrace/daemon/ui/qml/mainwin.qml | 9 | ||||
-rw-r--r-- | retrace/daemon/ui/resources.qrc | 1 |
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> |