From c63a495de6f4b4729cb3c24dc65ae019a39bbb0d Mon Sep 17 00:00:00 2001 From: Tony Wasserka Date: Sat, 25 Oct 2014 20:28:24 +0200 Subject: Add GUI widget for controlling pica breakpoints. --- src/citra_qt/debugger/graphics_breakpoints.cpp | 253 +++++++++++++++++++++++++ 1 file changed, 253 insertions(+) create mode 100644 src/citra_qt/debugger/graphics_breakpoints.cpp (limited to 'src/citra_qt/debugger/graphics_breakpoints.cpp') 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 @@ +// Copyright 2014 Citra Emulator Project +// Licensed under GPLv2 +// Refer to the license.txt file included. + +#include +#include +#include +#include +#include + +#include "graphics_breakpoints.hxx" + +BreakPointModel::BreakPointModel(std::shared_ptr debug_context, QObject* parent) + : QAbstractListModel(parent), context_weak(debug_context), + at_breakpoint(debug_context->at_breakpoint), + active_breakpoint(debug_context->active_breakpoint) +{ + +} + +int BreakPointModel::columnCount(const QModelIndex& parent) const +{ + return 2; +} + +int BreakPointModel::rowCount(const QModelIndex& parent) const +{ + return static_cast(Pica::DebugContext::Event::NumEvents); +} + +QVariant BreakPointModel::data(const QModelIndex& index, int role) const +{ + const auto event = static_cast(index.row()); + + switch (role) { + case Qt::DisplayRole: + { + if (index.column() == 0) { + std::map map; + map.insert({Pica::DebugContext::Event::CommandLoaded, tr("Pica command loaded")}); + map.insert({Pica::DebugContext::Event::CommandProcessed, tr("Pica command processed")}); + map.insert({Pica::DebugContext::Event::IncomingPrimitiveBatch, tr("Incomming primitive batch")}); + map.insert({Pica::DebugContext::Event::FinishedPrimitiveBatch, tr("Finished primitive batch")}); + + _dbg_assert_(GPU, map.size() == static_cast(Pica::DebugContext::Event::NumEvents)); + + return map[event]; + } else if (index.column() == 1) { + return data(index, Role_IsEnabled).toBool() ? tr("Enabled") : tr("Disabled"); + } + + break; + } + + case Qt::BackgroundRole: + { + if (at_breakpoint && index.row() == static_cast(active_breakpoint)) { + return QBrush(QColor(0xE0, 0xE0, 0x10)); + } + break; + } + + case Role_IsEnabled: + { + auto context = context_weak.lock(); + return context && context->breakpoints[event].enabled; + } + + default: + break; + } + return QVariant(); +} + +QVariant BreakPointModel::headerData(int section, Qt::Orientation orientation, int role) const +{ + switch(role) { + case Qt::DisplayRole: + { + if (section == 0) { + return tr("Event"); + } else if (section == 1) { + return tr("Status"); + } + + break; + } + } + + return QVariant(); +} + +bool BreakPointModel::setData(const QModelIndex& index, const QVariant& value, int role) +{ + const auto event = static_cast(index.row()); + + switch (role) { + case Role_IsEnabled: + { + auto context = context_weak.lock(); + if (!context) + return false; + + context->breakpoints[event].enabled = value.toBool(); + QModelIndex changed_index = createIndex(index.row(), 1); + emit dataChanged(changed_index, changed_index); + return true; + } + } + + return false; +} + + +void BreakPointModel::OnBreakPointHit(Pica::DebugContext::Event event) +{ + auto context = context_weak.lock(); + if (!context) + return; + + active_breakpoint = context->active_breakpoint; + at_breakpoint = context->at_breakpoint; + emit dataChanged(createIndex(static_cast(event), 0), + createIndex(static_cast(event), 1)); +} + +void BreakPointModel::OnResumed() +{ + auto context = context_weak.lock(); + if (!context) + return; + + at_breakpoint = context->at_breakpoint; + emit dataChanged(createIndex(static_cast(active_breakpoint), 0), + createIndex(static_cast(active_breakpoint), 1)); + active_breakpoint = context->active_breakpoint; +} + + +GraphicsBreakPointsWidget::GraphicsBreakPointsWidget(std::shared_ptr debug_context, + QWidget* parent) + : QDockWidget(tr("Pica Breakpoints"), parent), + Pica::DebugContext::BreakPointObserver(debug_context) +{ + setObjectName("PicaBreakPointsWidget"); + + status_text = new QLabel(tr("Emulation running")); + resume_button = new QPushButton(tr("Resume")); + resume_button->setEnabled(false); + + breakpoint_model = new BreakPointModel(debug_context, this); + breakpoint_list = new QTreeView; + breakpoint_list->setModel(breakpoint_model); + + toggle_breakpoint_button = new QPushButton(tr("Enable")); + toggle_breakpoint_button->setEnabled(false); + + qRegisterMetaType("Pica::DebugContext::Event"); + + connect(resume_button, SIGNAL(clicked()), this, SLOT(OnResumeRequested())); + + connect(this, SIGNAL(BreakPointHit(Pica::DebugContext::Event,void*)), + this, SLOT(OnBreakPointHit(Pica::DebugContext::Event,void*)), + Qt::BlockingQueuedConnection); + connect(this, SIGNAL(Resumed()), this, SLOT(OnResumed())); + + connect(this, SIGNAL(BreakPointHit(Pica::DebugContext::Event,void*)), + breakpoint_model, SLOT(OnBreakPointHit(Pica::DebugContext::Event)), + Qt::BlockingQueuedConnection); + connect(this, SIGNAL(Resumed()), breakpoint_model, SLOT(OnResumed())); + + connect(this, SIGNAL(BreakPointsChanged(const QModelIndex&,const QModelIndex&)), + breakpoint_model, SIGNAL(dataChanged(const QModelIndex&,const QModelIndex&))); + + connect(breakpoint_list->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)), + this, SLOT(OnBreakpointSelectionChanged(QModelIndex))); + + connect(toggle_breakpoint_button, SIGNAL(clicked()), this, SLOT(OnToggleBreakpointEnabled())); + + QWidget* main_widget = new QWidget; + auto main_layout = new QVBoxLayout; + { + auto sub_layout = new QHBoxLayout; + sub_layout->addWidget(status_text); + sub_layout->addWidget(resume_button); + main_layout->addLayout(sub_layout); + } + main_layout->addWidget(breakpoint_list); + main_layout->addWidget(toggle_breakpoint_button); + main_widget->setLayout(main_layout); + + setWidget(main_widget); +} + +void GraphicsBreakPointsWidget::OnPicaBreakPointHit(Event event, void* data) +{ + // Process in GUI thread + emit BreakPointHit(event, data); +} + +void GraphicsBreakPointsWidget::OnBreakPointHit(Pica::DebugContext::Event event, void* data) +{ + status_text->setText(tr("Emulation halted at breakpoint")); + resume_button->setEnabled(true); +} + +void GraphicsBreakPointsWidget::OnPicaResume() +{ + // Process in GUI thread + emit Resumed(); +} + +void GraphicsBreakPointsWidget::OnResumed() +{ + status_text->setText(tr("Emulation running")); + resume_button->setEnabled(false); +} + +void GraphicsBreakPointsWidget::OnResumeRequested() +{ + if (auto context = context_weak.lock()) + context->Resume(); +} + +void GraphicsBreakPointsWidget::OnBreakpointSelectionChanged(const QModelIndex& index) +{ + if (!index.isValid()) { + toggle_breakpoint_button->setEnabled(false); + return; + } + + toggle_breakpoint_button->setEnabled(true); + UpdateToggleBreakpointButton(index); +} + +void GraphicsBreakPointsWidget::OnToggleBreakpointEnabled() +{ + QModelIndex index = breakpoint_list->selectionModel()->currentIndex(); + bool new_state = !(breakpoint_model->data(index, BreakPointModel::Role_IsEnabled).toBool()); + + breakpoint_model->setData(index, new_state, + BreakPointModel::Role_IsEnabled); + UpdateToggleBreakpointButton(index); +} + +void GraphicsBreakPointsWidget::UpdateToggleBreakpointButton(const QModelIndex& index) +{ + if (true == breakpoint_model->data(index, BreakPointModel::Role_IsEnabled).toBool()) { + toggle_breakpoint_button->setText(tr("Disable")); + } else { + toggle_breakpoint_button->setText(tr("Enable")); + } +} -- cgit v1.2.3 From 0cd27a511ecd170484b672263c09192b579e31ac Mon Sep 17 00:00:00 2001 From: Tony Wasserka Date: Thu, 4 Dec 2014 19:41:03 +0100 Subject: Some code cleanup. --- src/citra_qt/debugger/graphics_breakpoints.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/citra_qt/debugger/graphics_breakpoints.cpp') diff --git a/src/citra_qt/debugger/graphics_breakpoints.cpp b/src/citra_qt/debugger/graphics_breakpoints.cpp index 2f41d5f77..db98a3b05 100644 --- a/src/citra_qt/debugger/graphics_breakpoints.cpp +++ b/src/citra_qt/debugger/graphics_breakpoints.cpp @@ -9,6 +9,7 @@ #include #include "graphics_breakpoints.hxx" +#include "graphics_breakpoints_p.hxx" BreakPointModel::BreakPointModel(std::shared_ptr debug_context, QObject* parent) : QAbstractListModel(parent), context_weak(debug_context), @@ -39,7 +40,7 @@ QVariant BreakPointModel::data(const QModelIndex& index, int role) const std::map map; map.insert({Pica::DebugContext::Event::CommandLoaded, tr("Pica command loaded")}); map.insert({Pica::DebugContext::Event::CommandProcessed, tr("Pica command processed")}); - map.insert({Pica::DebugContext::Event::IncomingPrimitiveBatch, tr("Incomming primitive batch")}); + map.insert({Pica::DebugContext::Event::IncomingPrimitiveBatch, tr("Incoming primitive batch")}); map.insert({Pica::DebugContext::Event::FinishedPrimitiveBatch, tr("Finished primitive batch")}); _dbg_assert_(GPU, map.size() == static_cast(Pica::DebugContext::Event::NumEvents)); -- cgit v1.2.3 From 79bb403089ff91c24b8356ad8d5bc5f7666a0d11 Mon Sep 17 00:00:00 2001 From: Tony Wasserka Date: Thu, 4 Dec 2014 20:41:01 +0100 Subject: More coding style fixes. --- src/citra_qt/debugger/graphics_breakpoints.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/citra_qt/debugger/graphics_breakpoints.cpp') diff --git a/src/citra_qt/debugger/graphics_breakpoints.cpp b/src/citra_qt/debugger/graphics_breakpoints.cpp index db98a3b05..5973aafc8 100644 --- a/src/citra_qt/debugger/graphics_breakpoints.cpp +++ b/src/citra_qt/debugger/graphics_breakpoints.cpp @@ -43,7 +43,7 @@ QVariant BreakPointModel::data(const QModelIndex& index, int role) const map.insert({Pica::DebugContext::Event::IncomingPrimitiveBatch, tr("Incoming primitive batch")}); map.insert({Pica::DebugContext::Event::FinishedPrimitiveBatch, tr("Finished primitive batch")}); - _dbg_assert_(GPU, map.size() == static_cast(Pica::DebugContext::Event::NumEvents)); + _dbg_assert_(GUI, map.size() == static_cast(Pica::DebugContext::Event::NumEvents)); return map[event]; } else if (index.column() == 1) { -- cgit v1.2.3 From 8b8131baecca16b46c22318b3331b2165cc74cbc Mon Sep 17 00:00:00 2001 From: Tony Wasserka Date: Thu, 4 Dec 2014 21:00:06 +0100 Subject: More cleanups. --- src/citra_qt/debugger/graphics_breakpoints.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'src/citra_qt/debugger/graphics_breakpoints.cpp') diff --git a/src/citra_qt/debugger/graphics_breakpoints.cpp b/src/citra_qt/debugger/graphics_breakpoints.cpp index 5973aafc8..df5579e15 100644 --- a/src/citra_qt/debugger/graphics_breakpoints.cpp +++ b/src/citra_qt/debugger/graphics_breakpoints.cpp @@ -36,7 +36,9 @@ QVariant BreakPointModel::data(const QModelIndex& index, int role) const switch (role) { case Qt::DisplayRole: { - if (index.column() == 0) { + switch (index.column()) { + case 0: + { std::map map; map.insert({Pica::DebugContext::Event::CommandLoaded, tr("Pica command loaded")}); map.insert({Pica::DebugContext::Event::CommandProcessed, tr("Pica command processed")}); @@ -46,8 +48,13 @@ QVariant BreakPointModel::data(const QModelIndex& index, int role) const _dbg_assert_(GUI, map.size() == static_cast(Pica::DebugContext::Event::NumEvents)); return map[event]; - } else if (index.column() == 1) { + } + + case 1: return data(index, Role_IsEnabled).toBool() ? tr("Enabled") : tr("Disabled"); + + default: + break; } break; -- cgit v1.2.3 From 0600e2d8b5b30bd68c8b19cb1f2051e096e7caa9 Mon Sep 17 00:00:00 2001 From: Yuri Kunde Schlesner Date: Fri, 5 Dec 2014 23:53:49 -0200 Subject: Convert old logging calls to new logging macros --- src/citra_qt/debugger/graphics_breakpoints.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/citra_qt/debugger/graphics_breakpoints.cpp') diff --git a/src/citra_qt/debugger/graphics_breakpoints.cpp b/src/citra_qt/debugger/graphics_breakpoints.cpp index df5579e15..53394b6e6 100644 --- a/src/citra_qt/debugger/graphics_breakpoints.cpp +++ b/src/citra_qt/debugger/graphics_breakpoints.cpp @@ -45,7 +45,7 @@ QVariant BreakPointModel::data(const QModelIndex& index, int role) const map.insert({Pica::DebugContext::Event::IncomingPrimitiveBatch, tr("Incoming primitive batch")}); map.insert({Pica::DebugContext::Event::FinishedPrimitiveBatch, tr("Finished primitive batch")}); - _dbg_assert_(GUI, map.size() == static_cast(Pica::DebugContext::Event::NumEvents)); + _dbg_assert_(Debug_GPU, map.size() == static_cast(Pica::DebugContext::Event::NumEvents)); return map[event]; } -- cgit v1.2.3 From 8cd0d9c000e2c3cb072ca001db13f1c12f2a07ea Mon Sep 17 00:00:00 2001 From: Tony Wasserka Date: Fri, 19 Dec 2014 18:37:14 +0100 Subject: citra-qt: static-constify a map. --- src/citra_qt/debugger/graphics_breakpoints.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'src/citra_qt/debugger/graphics_breakpoints.cpp') diff --git a/src/citra_qt/debugger/graphics_breakpoints.cpp b/src/citra_qt/debugger/graphics_breakpoints.cpp index 53394b6e6..469c3e268 100644 --- a/src/citra_qt/debugger/graphics_breakpoints.cpp +++ b/src/citra_qt/debugger/graphics_breakpoints.cpp @@ -39,15 +39,16 @@ QVariant BreakPointModel::data(const QModelIndex& index, int role) const switch (index.column()) { case 0: { - std::map map; - map.insert({Pica::DebugContext::Event::CommandLoaded, tr("Pica command loaded")}); - map.insert({Pica::DebugContext::Event::CommandProcessed, tr("Pica command processed")}); - map.insert({Pica::DebugContext::Event::IncomingPrimitiveBatch, tr("Incoming primitive batch")}); - map.insert({Pica::DebugContext::Event::FinishedPrimitiveBatch, tr("Finished primitive batch")}); + static const std::map map = { + { Pica::DebugContext::Event::CommandLoaded, tr("Pica command loaded") }, + { Pica::DebugContext::Event::CommandProcessed, tr("Pica command processed") }, + { Pica::DebugContext::Event::IncomingPrimitiveBatch, tr("Incoming primitive batch") }, + { Pica::DebugContext::Event::FinishedPrimitiveBatch, tr("Finished primitive batch") }, + }; _dbg_assert_(Debug_GPU, map.size() == static_cast(Pica::DebugContext::Event::NumEvents)); - return map[event]; + return (map.find(event) != map.end()) ? map.at(event) : QString(); } case 1: -- cgit v1.2.3 From 79c29243ed94fb247dfa5a60e1863a8f64f11669 Mon Sep 17 00:00:00 2001 From: Tony Wasserka Date: Wed, 10 Dec 2014 17:31:50 +0100 Subject: Pica/DebugUtils: Add an event triggered after loading a vertex. --- src/citra_qt/debugger/graphics_breakpoints.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src/citra_qt/debugger/graphics_breakpoints.cpp') diff --git a/src/citra_qt/debugger/graphics_breakpoints.cpp b/src/citra_qt/debugger/graphics_breakpoints.cpp index 469c3e268..4cb41db22 100644 --- a/src/citra_qt/debugger/graphics_breakpoints.cpp +++ b/src/citra_qt/debugger/graphics_breakpoints.cpp @@ -44,6 +44,7 @@ QVariant BreakPointModel::data(const QModelIndex& index, int role) const { Pica::DebugContext::Event::CommandProcessed, tr("Pica command processed") }, { Pica::DebugContext::Event::IncomingPrimitiveBatch, tr("Incoming primitive batch") }, { Pica::DebugContext::Event::FinishedPrimitiveBatch, tr("Finished primitive batch") }, + { Pica::DebugContext::Event::VertexLoaded, tr("Vertex Loaded") } }; _dbg_assert_(Debug_GPU, map.size() == static_cast(Pica::DebugContext::Event::NumEvents)); -- cgit v1.2.3 From ebfd831ccba32bce097491db3d6bdff0be05935e Mon Sep 17 00:00:00 2001 From: purpasmart96 Date: Tue, 16 Dec 2014 21:38:14 -0800 Subject: License change --- src/citra_qt/debugger/graphics_breakpoints.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/citra_qt/debugger/graphics_breakpoints.cpp') diff --git a/src/citra_qt/debugger/graphics_breakpoints.cpp b/src/citra_qt/debugger/graphics_breakpoints.cpp index 53394b6e6..e391f895b 100644 --- a/src/citra_qt/debugger/graphics_breakpoints.cpp +++ b/src/citra_qt/debugger/graphics_breakpoints.cpp @@ -1,5 +1,5 @@ // Copyright 2014 Citra Emulator Project -// Licensed under GPLv2 +// Licensed under GPLv2 or any later version // Refer to the license.txt file included. #include -- cgit v1.2.3