summaryrefslogtreecommitdiffstats
path: root/src/citra_qt/debugger
diff options
context:
space:
mode:
Diffstat (limited to 'src/citra_qt/debugger')
-rw-r--r--src/citra_qt/debugger/graphics.cpp83
-rw-r--r--src/citra_qt/debugger/graphics.hxx43
-rw-r--r--src/citra_qt/debugger/graphics_cmdlists.cpp139
-rw-r--r--src/citra_qt/debugger/graphics_cmdlists.hxx64
4 files changed, 329 insertions, 0 deletions
diff --git a/src/citra_qt/debugger/graphics.cpp b/src/citra_qt/debugger/graphics.cpp
new file mode 100644
index 000000000..9aaade8f9
--- /dev/null
+++ b/src/citra_qt/debugger/graphics.cpp
@@ -0,0 +1,83 @@
+// Copyright 2014 Citra Emulator Project
+// Licensed under GPLv2
+// Refer to the license.txt file included.
+
+#include "graphics.hxx"
+#include <QListView>
+#include <QVBoxLayout>
+#include <QDebug>
+
+extern GraphicsDebugger g_debugger;
+
+GPUCommandStreamItemModel::GPUCommandStreamItemModel(QObject* parent) : QAbstractListModel(parent), command_count(0)
+{
+ connect(this, SIGNAL(GXCommandFinished(int)), this, SLOT(OnGXCommandFinishedInternal(int)));
+}
+
+int GPUCommandStreamItemModel::rowCount(const QModelIndex& parent) const
+{
+ return command_count;
+}
+
+QVariant GPUCommandStreamItemModel::data(const QModelIndex& index, int role) const
+{
+ if (!index.isValid())
+ return QVariant();
+
+ int command_index = index.row();
+ const GSP_GPU::GXCommand& command = GetDebugger()->ReadGXCommandHistory(command_index);
+ if (role == Qt::DisplayRole)
+ {
+ std::map<GSP_GPU::GXCommandId, const char*> command_names;
+ command_names[GSP_GPU::GXCommandId::REQUEST_DMA] = "REQUEST_DMA";
+ command_names[GSP_GPU::GXCommandId::SET_COMMAND_LIST_FIRST] = "SET_COMMAND_LIST_FIRST";
+ command_names[GSP_GPU::GXCommandId::SET_MEMORY_FILL] = "SET_MEMORY_FILL";
+ command_names[GSP_GPU::GXCommandId::SET_DISPLAY_TRANSFER] = "SET_DISPLAY_TRANSFER";
+ command_names[GSP_GPU::GXCommandId::SET_TEXTURE_COPY] = "SET_TEXTURE_COPY";
+ command_names[GSP_GPU::GXCommandId::SET_COMMAND_LIST_LAST] = "SET_COMMAND_LIST_LAST";
+ QString str = QString("%1 %2 %3 %4 %5 %6 %7 %8 %9").arg(command_names[static_cast<GSP_GPU::GXCommandId>(command.id)])
+ .arg(command.data[0], 8, 16, QLatin1Char('0'))
+ .arg(command.data[1], 8, 16, QLatin1Char('0'))
+ .arg(command.data[2], 8, 16, QLatin1Char('0'))
+ .arg(command.data[3], 8, 16, QLatin1Char('0'))
+ .arg(command.data[4], 8, 16, QLatin1Char('0'))
+ .arg(command.data[5], 8, 16, QLatin1Char('0'))
+ .arg(command.data[6], 8, 16, QLatin1Char('0'))
+ .arg(command.data[7], 8, 16, QLatin1Char('0'));
+ return QVariant(str);
+ }
+ else
+ {
+ return QVariant();
+ }
+}
+
+void GPUCommandStreamItemModel::GXCommandProcessed(int total_command_count)
+{
+ emit GXCommandFinished(total_command_count);
+}
+
+void GPUCommandStreamItemModel::OnGXCommandFinishedInternal(int total_command_count)
+{
+ if (total_command_count == 0)
+ return;
+
+ int prev_command_count = command_count;
+ command_count = total_command_count;
+ emit dataChanged(index(prev_command_count,0), index(total_command_count-1,0));
+}
+
+
+GPUCommandStreamWidget::GPUCommandStreamWidget(QWidget* parent) : QDockWidget(tr("Graphics Debugger"), parent)
+{
+ // TODO: set objectName!
+
+ GPUCommandStreamItemModel* command_model = new GPUCommandStreamItemModel(this);
+ g_debugger.RegisterObserver(command_model);
+
+ QListView* command_list = new QListView;
+ command_list->setModel(command_model);
+ command_list->setFont(QFont("monospace"));
+
+ setWidget(command_list);
+}
diff --git a/src/citra_qt/debugger/graphics.hxx b/src/citra_qt/debugger/graphics.hxx
new file mode 100644
index 000000000..72656f93c
--- /dev/null
+++ b/src/citra_qt/debugger/graphics.hxx
@@ -0,0 +1,43 @@
+// Copyright 2014 Citra Emulator Project
+// Licensed under GPLv2
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include <QAbstractListModel>
+#include <QDockWidget>
+
+#include "video_core/gpu_debugger.h"
+
+class GPUCommandStreamItemModel : public QAbstractListModel, public GraphicsDebugger::DebuggerObserver
+{
+ Q_OBJECT
+
+public:
+ GPUCommandStreamItemModel(QObject* parent);
+
+ int rowCount(const QModelIndex& parent = QModelIndex()) const override;
+ QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
+
+public:
+ void GXCommandProcessed(int total_command_count) override;
+
+public slots:
+ void OnGXCommandFinishedInternal(int total_command_count);
+
+signals:
+ void GXCommandFinished(int total_command_count);
+
+private:
+ int command_count;
+};
+
+class GPUCommandStreamWidget : public QDockWidget
+{
+ Q_OBJECT
+
+public:
+ GPUCommandStreamWidget(QWidget* parent = 0);
+
+private:
+};
diff --git a/src/citra_qt/debugger/graphics_cmdlists.cpp b/src/citra_qt/debugger/graphics_cmdlists.cpp
new file mode 100644
index 000000000..195197ef5
--- /dev/null
+++ b/src/citra_qt/debugger/graphics_cmdlists.cpp
@@ -0,0 +1,139 @@
+// Copyright 2014 Citra Emulator Project
+// Licensed under GPLv2
+// Refer to the license.txt file included.
+
+#include "graphics_cmdlists.hxx"
+#include <QTreeView>
+
+extern GraphicsDebugger g_debugger;
+
+GPUCommandListModel::GPUCommandListModel(QObject* parent) : QAbstractItemModel(parent)
+{
+ root_item = new TreeItem(TreeItem::ROOT, 0, NULL, this);
+
+ connect(this, SIGNAL(CommandListCalled()), this, SLOT(OnCommandListCalledInternal()), Qt::UniqueConnection);
+}
+
+QModelIndex GPUCommandListModel::index(int row, int column, const QModelIndex& parent) const
+{
+ TreeItem* item;
+
+ if (!parent.isValid()) {
+ item = root_item;
+ } else {
+ item = (TreeItem*)parent.internalPointer();
+ }
+
+ return createIndex(row, column, item->children[row]);
+}
+
+QModelIndex GPUCommandListModel::parent(const QModelIndex& child) const
+{
+ if (!child.isValid())
+ return QModelIndex();
+
+ TreeItem* item = (TreeItem*)child.internalPointer();
+
+ if (item->parent == NULL)
+ return QModelIndex();
+
+ return createIndex(item->parent->index, 0, item->parent);
+}
+
+int GPUCommandListModel::rowCount(const QModelIndex& parent) const
+{
+ TreeItem* item;
+ if (!parent.isValid()) {
+ item = root_item;
+ } else {
+ item = (TreeItem*)parent.internalPointer();
+ }
+ return item->children.size();
+}
+
+int GPUCommandListModel::columnCount(const QModelIndex& parent) const
+{
+ return 2;
+}
+
+QVariant GPUCommandListModel::data(const QModelIndex& index, int role) const
+{
+ if (!index.isValid())
+ return QVariant();
+
+ const TreeItem* item = (const TreeItem*)index.internalPointer();
+
+ if (item->type == TreeItem::COMMAND_LIST)
+ {
+ const GraphicsDebugger::PicaCommandList& cmdlist = command_lists[item->index].second;
+ u32 address = command_lists[item->index].first;
+
+ if (role == Qt::DisplayRole && index.column() == 0)
+ {
+ return QVariant(QString("0x%1 bytes at 0x%2").arg(cmdlist.size(), 0, 16).arg(address, 8, 16, QLatin1Char('0')));
+ }
+ }
+ else
+ {
+ // index refers to a specific command
+ const GraphicsDebugger::PicaCommandList& cmdlist = command_lists[item->parent->index].second;
+ const GraphicsDebugger::PicaCommand& cmd = cmdlist[item->index];
+ const Pica::CommandHeader& header = cmd.GetHeader();
+
+ if (role == Qt::DisplayRole) {
+ QString content;
+ if (index.column() == 0) {
+ content = Pica::command_names[header.cmd_id];
+ content.append(" ");
+ } else if (index.column() == 1) {
+ for (int j = 0; j < cmd.size(); ++j)
+ content.append(QString("%1 ").arg(cmd[j], 8, 16, QLatin1Char('0')));
+ }
+
+ return QVariant(content);
+ }
+ }
+
+ return QVariant();
+}
+
+void GPUCommandListModel::OnCommandListCalled(const GraphicsDebugger::PicaCommandList& lst, bool is_new)
+{
+ emit CommandListCalled();
+}
+
+
+void GPUCommandListModel::OnCommandListCalledInternal()
+{
+ beginResetModel();
+
+ command_lists = GetDebugger()->GetCommandLists();
+
+ // delete root item and rebuild tree
+ delete root_item;
+ root_item = new TreeItem(TreeItem::ROOT, 0, NULL, this);
+
+ for (int command_list_idx = 0; command_list_idx < command_lists.size(); ++command_list_idx) {
+ TreeItem* command_list_item = new TreeItem(TreeItem::COMMAND_LIST, command_list_idx, root_item, root_item);
+ root_item->children.push_back(command_list_item);
+
+ const GraphicsDebugger::PicaCommandList& command_list = command_lists[command_list_idx].second;
+ for (int command_idx = 0; command_idx < command_list.size(); ++command_idx) {
+ TreeItem* command_item = new TreeItem(TreeItem::COMMAND, command_idx, command_list_item, command_list_item);
+ command_list_item->children.push_back(command_item);
+ }
+ }
+
+ endResetModel();
+}
+
+GPUCommandListWidget::GPUCommandListWidget(QWidget* parent) : QDockWidget(tr("Pica Command List"), parent)
+{
+ GPUCommandListModel* model = new GPUCommandListModel(this);
+ g_debugger.RegisterObserver(model);
+
+ QTreeView* tree_widget = new QTreeView;
+ tree_widget->setModel(model);
+ tree_widget->setFont(QFont("monospace"));
+ setWidget(tree_widget);
+}
diff --git a/src/citra_qt/debugger/graphics_cmdlists.hxx b/src/citra_qt/debugger/graphics_cmdlists.hxx
new file mode 100644
index 000000000..b4e6e3c8a
--- /dev/null
+++ b/src/citra_qt/debugger/graphics_cmdlists.hxx
@@ -0,0 +1,64 @@
+// Copyright 2014 Citra Emulator Project
+// Licensed under GPLv2
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include <QAbstractItemModel>
+#include <QDockWidget>
+
+#include "video_core/gpu_debugger.h"
+
+// TODO: Rename class, since it's not actually a list model anymore...
+class GPUCommandListModel : public QAbstractItemModel, public GraphicsDebugger::DebuggerObserver
+{
+ Q_OBJECT
+
+public:
+ GPUCommandListModel(QObject* parent);
+
+ QModelIndex index(int row, int column, const QModelIndex& parent = QModelIndex()) const;
+ QModelIndex parent(const QModelIndex& child) const;
+ int columnCount(const QModelIndex& parent = QModelIndex()) const;
+ int rowCount(const QModelIndex& parent = QModelIndex()) const override;
+ QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
+
+public:
+ void OnCommandListCalled(const GraphicsDebugger::PicaCommandList& lst, bool is_new) override;
+
+public slots:
+ void OnCommandListCalledInternal();
+
+signals:
+ void CommandListCalled();
+
+private:
+ struct TreeItem : public QObject
+ {
+ enum Type {
+ ROOT,
+ COMMAND_LIST,
+ COMMAND
+ };
+
+ TreeItem(Type type, int index, TreeItem* item_parent, QObject* parent) : QObject(parent), type(type), index(index), parent(item_parent) {}
+
+ Type type;
+ int index;
+ std::vector<TreeItem*> children;
+ TreeItem* parent;
+ };
+
+ std::vector<std::pair<u32,GraphicsDebugger::PicaCommandList>> command_lists;
+ TreeItem* root_item;
+};
+
+class GPUCommandListWidget : public QDockWidget
+{
+ Q_OBJECT
+
+public:
+ GPUCommandListWidget(QWidget* parent = 0);
+
+private:
+};