diff options
Diffstat (limited to 'src/citra_qt/debugger')
-rw-r--r-- | src/citra_qt/debugger/graphics.cpp | 83 | ||||
-rw-r--r-- | src/citra_qt/debugger/graphics.hxx | 43 | ||||
-rw-r--r-- | src/citra_qt/debugger/graphics_cmdlists.cpp | 139 | ||||
-rw-r--r-- | src/citra_qt/debugger/graphics_cmdlists.hxx | 64 |
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: +}; |