summaryrefslogtreecommitdiff
path: root/src/citra_qt/debugger/graphics_cmdlists.cpp
diff options
context:
space:
mode:
authorGravatar Lioncash2016-12-21 17:19:12 -0500
committerGravatar Lioncash2016-12-21 17:19:21 -0500
commit8309d0dade37684076ad530bfbca5d4ffc6d1f4d (patch)
treec7eb1050f664df4aad518c55b6648807b0cef2db /src/citra_qt/debugger/graphics_cmdlists.cpp
parentMerge pull request #2319 from yuriks/profile-scopes (diff)
downloadyuzu-8309d0dade37684076ad530bfbca5d4ffc6d1f4d.tar.gz
yuzu-8309d0dade37684076ad530bfbca5d4ffc6d1f4d.tar.xz
yuzu-8309d0dade37684076ad530bfbca5d4ffc6d1f4d.zip
citra-qt: Move graphics debugging code into its own folder
Keeps all graphics debugging stuff from cluttering up the root debugger folder
Diffstat (limited to 'src/citra_qt/debugger/graphics_cmdlists.cpp')
-rw-r--r--src/citra_qt/debugger/graphics_cmdlists.cpp259
1 files changed, 0 insertions, 259 deletions
diff --git a/src/citra_qt/debugger/graphics_cmdlists.cpp b/src/citra_qt/debugger/graphics_cmdlists.cpp
deleted file mode 100644
index 98b619dea..000000000
--- a/src/citra_qt/debugger/graphics_cmdlists.cpp
+++ /dev/null
@@ -1,259 +0,0 @@
1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include <QApplication>
6#include <QClipboard>
7#include <QComboBox>
8#include <QHeaderView>
9#include <QLabel>
10#include <QListView>
11#include <QMainWindow>
12#include <QPushButton>
13#include <QSpinBox>
14#include <QTreeView>
15#include <QVBoxLayout>
16#include "citra_qt/debugger/graphics_cmdlists.h"
17#include "citra_qt/util/spinbox.h"
18#include "citra_qt/util/util.h"
19#include "common/vector_math.h"
20#include "video_core/debug_utils/debug_utils.h"
21#include "video_core/pica.h"
22#include "video_core/pica_state.h"
23
24namespace {
25QImage LoadTexture(const u8* src, const Pica::DebugUtils::TextureInfo& info) {
26 QImage decoded_image(info.width, info.height, QImage::Format_ARGB32);
27 for (int y = 0; y < info.height; ++y) {
28 for (int x = 0; x < info.width; ++x) {
29 Math::Vec4<u8> color = Pica::DebugUtils::LookupTexture(src, x, y, info, true);
30 decoded_image.setPixel(x, y, qRgba(color.r(), color.g(), color.b(), color.a()));
31 }
32 }
33
34 return decoded_image;
35}
36
37class TextureInfoWidget : public QWidget {
38public:
39 TextureInfoWidget(const u8* src, const Pica::DebugUtils::TextureInfo& info,
40 QWidget* parent = nullptr)
41 : QWidget(parent) {
42 QLabel* image_widget = new QLabel;
43 QPixmap image_pixmap = QPixmap::fromImage(LoadTexture(src, info));
44 image_pixmap = image_pixmap.scaled(200, 100, Qt::KeepAspectRatio, Qt::SmoothTransformation);
45 image_widget->setPixmap(image_pixmap);
46
47 QVBoxLayout* layout = new QVBoxLayout;
48 layout->addWidget(image_widget);
49 setLayout(layout);
50 }
51};
52} // Anonymous namespace
53
54GPUCommandListModel::GPUCommandListModel(QObject* parent) : QAbstractListModel(parent) {}
55
56int GPUCommandListModel::rowCount(const QModelIndex& parent) const {
57 return static_cast<int>(pica_trace.writes.size());
58}
59
60int GPUCommandListModel::columnCount(const QModelIndex& parent) const {
61 return 4;
62}
63
64QVariant GPUCommandListModel::data(const QModelIndex& index, int role) const {
65 if (!index.isValid())
66 return QVariant();
67
68 const auto& write = pica_trace.writes[index.row()];
69
70 if (role == Qt::DisplayRole) {
71 switch (index.column()) {
72 case 0:
73 return QString::fromLatin1(Pica::Regs::GetCommandName(write.cmd_id).c_str());
74 case 1:
75 return QString("%1").arg(write.cmd_id, 3, 16, QLatin1Char('0'));
76 case 2:
77 return QString("%1").arg(write.mask, 4, 2, QLatin1Char('0'));
78 case 3:
79 return QString("%1").arg(write.value, 8, 16, QLatin1Char('0'));
80 }
81 } else if (role == CommandIdRole) {
82 return QVariant::fromValue<int>(write.cmd_id);
83 }
84
85 return QVariant();
86}
87
88QVariant GPUCommandListModel::headerData(int section, Qt::Orientation orientation, int role) const {
89 switch (role) {
90 case Qt::DisplayRole: {
91 switch (section) {
92 case 0:
93 return tr("Command Name");
94 case 1:
95 return tr("Register");
96 case 2:
97 return tr("Mask");
98 case 3:
99 return tr("New Value");
100 }
101
102 break;
103 }
104 }
105
106 return QVariant();
107}
108
109void GPUCommandListModel::OnPicaTraceFinished(const Pica::DebugUtils::PicaTrace& trace) {
110 beginResetModel();
111
112 pica_trace = trace;
113
114 endResetModel();
115}
116
117#define COMMAND_IN_RANGE(cmd_id, reg_name) \
118 (cmd_id >= PICA_REG_INDEX(reg_name) && \
119 cmd_id < PICA_REG_INDEX(reg_name) + sizeof(decltype(Pica::g_state.regs.reg_name)) / 4)
120
121void GPUCommandListWidget::OnCommandDoubleClicked(const QModelIndex& index) {
122 const unsigned int command_id =
123 list_widget->model()->data(index, GPUCommandListModel::CommandIdRole).toUInt();
124 if (COMMAND_IN_RANGE(command_id, texture0) || COMMAND_IN_RANGE(command_id, texture1) ||
125 COMMAND_IN_RANGE(command_id, texture2)) {
126
127 unsigned texture_index;
128 if (COMMAND_IN_RANGE(command_id, texture0)) {
129 texture_index = 0;
130 } else if (COMMAND_IN_RANGE(command_id, texture1)) {
131 texture_index = 1;
132 } else if (COMMAND_IN_RANGE(command_id, texture2)) {
133 texture_index = 2;
134 } else {
135 UNREACHABLE_MSG("Unknown texture command");
136 }
137
138 const auto texture = Pica::g_state.regs.GetTextures()[texture_index];
139 const auto config = texture.config;
140 const auto format = texture.format;
141 const auto info = Pica::DebugUtils::TextureInfo::FromPicaRegister(config, format);
142
143 // TODO: Open a surface debugger
144 }
145}
146
147void GPUCommandListWidget::SetCommandInfo(const QModelIndex& index) {
148 QWidget* new_info_widget = nullptr;
149
150 const unsigned int command_id =
151 list_widget->model()->data(index, GPUCommandListModel::CommandIdRole).toUInt();
152 if (COMMAND_IN_RANGE(command_id, texture0) || COMMAND_IN_RANGE(command_id, texture1) ||
153 COMMAND_IN_RANGE(command_id, texture2)) {
154
155 unsigned texture_index;
156 if (COMMAND_IN_RANGE(command_id, texture0)) {
157 texture_index = 0;
158 } else if (COMMAND_IN_RANGE(command_id, texture1)) {
159 texture_index = 1;
160 } else {
161 texture_index = 2;
162 }
163
164 const auto texture = Pica::g_state.regs.GetTextures()[texture_index];
165 const auto config = texture.config;
166 const auto format = texture.format;
167
168 const auto info = Pica::DebugUtils::TextureInfo::FromPicaRegister(config, format);
169 const u8* src = Memory::GetPhysicalPointer(config.GetPhysicalAddress());
170 new_info_widget = new TextureInfoWidget(src, info);
171 }
172 if (command_info_widget) {
173 delete command_info_widget;
174 command_info_widget = nullptr;
175 }
176 if (new_info_widget) {
177 widget()->layout()->addWidget(new_info_widget);
178 command_info_widget = new_info_widget;
179 }
180}
181#undef COMMAND_IN_RANGE
182
183GPUCommandListWidget::GPUCommandListWidget(QWidget* parent)
184 : QDockWidget(tr("Pica Command List"), parent) {
185 setObjectName("Pica Command List");
186 GPUCommandListModel* model = new GPUCommandListModel(this);
187
188 QWidget* main_widget = new QWidget;
189
190 list_widget = new QTreeView;
191 list_widget->setModel(model);
192 list_widget->setFont(GetMonospaceFont());
193 list_widget->setRootIsDecorated(false);
194 list_widget->setUniformRowHeights(true);
195
196#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
197 list_widget->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
198#else
199 list_widget->header()->setResizeMode(QHeaderView::ResizeToContents);
200#endif
201
202 connect(list_widget->selectionModel(),
203 SIGNAL(currentChanged(const QModelIndex&, const QModelIndex&)), this,
204 SLOT(SetCommandInfo(const QModelIndex&)));
205 connect(list_widget, SIGNAL(doubleClicked(const QModelIndex&)), this,
206 SLOT(OnCommandDoubleClicked(const QModelIndex&)));
207
208 toggle_tracing = new QPushButton(tr("Start Tracing"));
209 QPushButton* copy_all = new QPushButton(tr("Copy All"));
210
211 connect(toggle_tracing, SIGNAL(clicked()), this, SLOT(OnToggleTracing()));
212 connect(this, SIGNAL(TracingFinished(const Pica::DebugUtils::PicaTrace&)), model,
213 SLOT(OnPicaTraceFinished(const Pica::DebugUtils::PicaTrace&)));
214
215 connect(copy_all, SIGNAL(clicked()), this, SLOT(CopyAllToClipboard()));
216
217 command_info_widget = nullptr;
218
219 QVBoxLayout* main_layout = new QVBoxLayout;
220 main_layout->addWidget(list_widget);
221 {
222 QHBoxLayout* sub_layout = new QHBoxLayout;
223 sub_layout->addWidget(toggle_tracing);
224 sub_layout->addWidget(copy_all);
225 main_layout->addLayout(sub_layout);
226 }
227 main_widget->setLayout(main_layout);
228
229 setWidget(main_widget);
230}
231
232void GPUCommandListWidget::OnToggleTracing() {
233 if (!Pica::DebugUtils::IsPicaTracing()) {
234 Pica::DebugUtils::StartPicaTracing();
235 toggle_tracing->setText(tr("Finish Tracing"));
236 } else {
237 pica_trace = Pica::DebugUtils::FinishPicaTracing();
238 emit TracingFinished(*pica_trace);
239 toggle_tracing->setText(tr("Start Tracing"));
240 }
241}
242
243void GPUCommandListWidget::CopyAllToClipboard() {
244 QClipboard* clipboard = QApplication::clipboard();
245 QString text;
246
247 QAbstractItemModel* model = static_cast<QAbstractItemModel*>(list_widget->model());
248
249 for (int row = 0; row < model->rowCount({}); ++row) {
250 for (int col = 0; col < model->columnCount({}); ++col) {
251 QModelIndex index = model->index(row, col);
252 text += model->data(index).value<QString>();
253 text += '\t';
254 }
255 text += '\n';
256 }
257
258 clipboard->setText(text);
259}