summaryrefslogtreecommitdiff
path: root/src/citra_qt/debugger/graphics_breakpoints.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/citra_qt/debugger/graphics_breakpoints.cpp')
-rw-r--r--src/citra_qt/debugger/graphics_breakpoints.cpp253
1 files changed, 253 insertions, 0 deletions
diff --git a/src/citra_qt/debugger/graphics_breakpoints.cpp b/src/citra_qt/debugger/graphics_breakpoints.cpp
new file mode 100644
index 000000000..2f41d5f77
--- /dev/null
+++ b/src/citra_qt/debugger/graphics_breakpoints.cpp
@@ -0,0 +1,253 @@
1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2
3// Refer to the license.txt file included.
4
5#include <QMetaType>
6#include <QPushButton>
7#include <QTreeWidget>
8#include <QVBoxLayout>
9#include <QLabel>
10
11#include "graphics_breakpoints.hxx"
12
13BreakPointModel::BreakPointModel(std::shared_ptr<Pica::DebugContext> debug_context, QObject* parent)
14 : QAbstractListModel(parent), context_weak(debug_context),
15 at_breakpoint(debug_context->at_breakpoint),
16 active_breakpoint(debug_context->active_breakpoint)
17{
18
19}
20
21int BreakPointModel::columnCount(const QModelIndex& parent) const
22{
23 return 2;
24}
25
26int BreakPointModel::rowCount(const QModelIndex& parent) const
27{
28 return static_cast<int>(Pica::DebugContext::Event::NumEvents);
29}
30
31QVariant BreakPointModel::data(const QModelIndex& index, int role) const
32{
33 const auto event = static_cast<Pica::DebugContext::Event>(index.row());
34
35 switch (role) {
36 case Qt::DisplayRole:
37 {
38 if (index.column() == 0) {
39 std::map<Pica::DebugContext::Event, QString> map;
40 map.insert({Pica::DebugContext::Event::CommandLoaded, tr("Pica command loaded")});
41 map.insert({Pica::DebugContext::Event::CommandProcessed, tr("Pica command processed")});
42 map.insert({Pica::DebugContext::Event::IncomingPrimitiveBatch, tr("Incomming primitive batch")});
43 map.insert({Pica::DebugContext::Event::FinishedPrimitiveBatch, tr("Finished primitive batch")});
44
45 _dbg_assert_(GPU, map.size() == static_cast<size_t>(Pica::DebugContext::Event::NumEvents));
46
47 return map[event];
48 } else if (index.column() == 1) {
49 return data(index, Role_IsEnabled).toBool() ? tr("Enabled") : tr("Disabled");
50 }
51
52 break;
53 }
54
55 case Qt::BackgroundRole:
56 {
57 if (at_breakpoint && index.row() == static_cast<int>(active_breakpoint)) {
58 return QBrush(QColor(0xE0, 0xE0, 0x10));
59 }
60 break;
61 }
62
63 case Role_IsEnabled:
64 {
65 auto context = context_weak.lock();
66 return context && context->breakpoints[event].enabled;
67 }
68
69 default:
70 break;
71 }
72 return QVariant();
73}
74
75QVariant BreakPointModel::headerData(int section, Qt::Orientation orientation, int role) const
76{
77 switch(role) {
78 case Qt::DisplayRole:
79 {
80 if (section == 0) {
81 return tr("Event");
82 } else if (section == 1) {
83 return tr("Status");
84 }
85
86 break;
87 }
88 }
89
90 return QVariant();
91}
92
93bool BreakPointModel::setData(const QModelIndex& index, const QVariant& value, int role)
94{
95 const auto event = static_cast<Pica::DebugContext::Event>(index.row());
96
97 switch (role) {
98 case Role_IsEnabled:
99 {
100 auto context = context_weak.lock();
101 if (!context)
102 return false;
103
104 context->breakpoints[event].enabled = value.toBool();
105 QModelIndex changed_index = createIndex(index.row(), 1);
106 emit dataChanged(changed_index, changed_index);
107 return true;
108 }
109 }
110
111 return false;
112}
113
114
115void BreakPointModel::OnBreakPointHit(Pica::DebugContext::Event event)
116{
117 auto context = context_weak.lock();
118 if (!context)
119 return;
120
121 active_breakpoint = context->active_breakpoint;
122 at_breakpoint = context->at_breakpoint;
123 emit dataChanged(createIndex(static_cast<int>(event), 0),
124 createIndex(static_cast<int>(event), 1));
125}
126
127void BreakPointModel::OnResumed()
128{
129 auto context = context_weak.lock();
130 if (!context)
131 return;
132
133 at_breakpoint = context->at_breakpoint;
134 emit dataChanged(createIndex(static_cast<int>(active_breakpoint), 0),
135 createIndex(static_cast<int>(active_breakpoint), 1));
136 active_breakpoint = context->active_breakpoint;
137}
138
139
140GraphicsBreakPointsWidget::GraphicsBreakPointsWidget(std::shared_ptr<Pica::DebugContext> debug_context,
141 QWidget* parent)
142 : QDockWidget(tr("Pica Breakpoints"), parent),
143 Pica::DebugContext::BreakPointObserver(debug_context)
144{
145 setObjectName("PicaBreakPointsWidget");
146
147 status_text = new QLabel(tr("Emulation running"));
148 resume_button = new QPushButton(tr("Resume"));
149 resume_button->setEnabled(false);
150
151 breakpoint_model = new BreakPointModel(debug_context, this);
152 breakpoint_list = new QTreeView;
153 breakpoint_list->setModel(breakpoint_model);
154
155 toggle_breakpoint_button = new QPushButton(tr("Enable"));
156 toggle_breakpoint_button->setEnabled(false);
157
158 qRegisterMetaType<Pica::DebugContext::Event>("Pica::DebugContext::Event");
159
160 connect(resume_button, SIGNAL(clicked()), this, SLOT(OnResumeRequested()));
161
162 connect(this, SIGNAL(BreakPointHit(Pica::DebugContext::Event,void*)),
163 this, SLOT(OnBreakPointHit(Pica::DebugContext::Event,void*)),
164 Qt::BlockingQueuedConnection);
165 connect(this, SIGNAL(Resumed()), this, SLOT(OnResumed()));
166
167 connect(this, SIGNAL(BreakPointHit(Pica::DebugContext::Event,void*)),
168 breakpoint_model, SLOT(OnBreakPointHit(Pica::DebugContext::Event)),
169 Qt::BlockingQueuedConnection);
170 connect(this, SIGNAL(Resumed()), breakpoint_model, SLOT(OnResumed()));
171
172 connect(this, SIGNAL(BreakPointsChanged(const QModelIndex&,const QModelIndex&)),
173 breakpoint_model, SIGNAL(dataChanged(const QModelIndex&,const QModelIndex&)));
174
175 connect(breakpoint_list->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)),
176 this, SLOT(OnBreakpointSelectionChanged(QModelIndex)));
177
178 connect(toggle_breakpoint_button, SIGNAL(clicked()), this, SLOT(OnToggleBreakpointEnabled()));
179
180 QWidget* main_widget = new QWidget;
181 auto main_layout = new QVBoxLayout;
182 {
183 auto sub_layout = new QHBoxLayout;
184 sub_layout->addWidget(status_text);
185 sub_layout->addWidget(resume_button);
186 main_layout->addLayout(sub_layout);
187 }
188 main_layout->addWidget(breakpoint_list);
189 main_layout->addWidget(toggle_breakpoint_button);
190 main_widget->setLayout(main_layout);
191
192 setWidget(main_widget);
193}
194
195void GraphicsBreakPointsWidget::OnPicaBreakPointHit(Event event, void* data)
196{
197 // Process in GUI thread
198 emit BreakPointHit(event, data);
199}
200
201void GraphicsBreakPointsWidget::OnBreakPointHit(Pica::DebugContext::Event event, void* data)
202{
203 status_text->setText(tr("Emulation halted at breakpoint"));
204 resume_button->setEnabled(true);
205}
206
207void GraphicsBreakPointsWidget::OnPicaResume()
208{
209 // Process in GUI thread
210 emit Resumed();
211}
212
213void GraphicsBreakPointsWidget::OnResumed()
214{
215 status_text->setText(tr("Emulation running"));
216 resume_button->setEnabled(false);
217}
218
219void GraphicsBreakPointsWidget::OnResumeRequested()
220{
221 if (auto context = context_weak.lock())
222 context->Resume();
223}
224
225void GraphicsBreakPointsWidget::OnBreakpointSelectionChanged(const QModelIndex& index)
226{
227 if (!index.isValid()) {
228 toggle_breakpoint_button->setEnabled(false);
229 return;
230 }
231
232 toggle_breakpoint_button->setEnabled(true);
233 UpdateToggleBreakpointButton(index);
234}
235
236void GraphicsBreakPointsWidget::OnToggleBreakpointEnabled()
237{
238 QModelIndex index = breakpoint_list->selectionModel()->currentIndex();
239 bool new_state = !(breakpoint_model->data(index, BreakPointModel::Role_IsEnabled).toBool());
240
241 breakpoint_model->setData(index, new_state,
242 BreakPointModel::Role_IsEnabled);
243 UpdateToggleBreakpointButton(index);
244}
245
246void GraphicsBreakPointsWidget::UpdateToggleBreakpointButton(const QModelIndex& index)
247{
248 if (true == breakpoint_model->data(index, BreakPointModel::Role_IsEnabled).toBool()) {
249 toggle_breakpoint_button->setText(tr("Disable"));
250 } else {
251 toggle_breakpoint_button->setText(tr("Enable"));
252 }
253}