Merge pull request #3267 from ReinUsesLisp/remove-maxwell-debugger
yuzu: Remove Maxwell debuggermaster
commit
c332c66eb2
@ -1,49 +0,0 @@
|
|||||||
// Copyright 2014 Citra Emulator Project
|
|
||||||
// Licensed under GPLv2
|
|
||||||
// Refer to the license.txt file included.
|
|
||||||
|
|
||||||
#include <mutex>
|
|
||||||
|
|
||||||
#include "video_core/debug_utils/debug_utils.h"
|
|
||||||
|
|
||||||
namespace Tegra {
|
|
||||||
|
|
||||||
void DebugContext::DoOnEvent(Event event, void* data) {
|
|
||||||
{
|
|
||||||
std::unique_lock lock{breakpoint_mutex};
|
|
||||||
|
|
||||||
// TODO(Subv): Commit the rasterizer's caches so framebuffers, render targets, etc. will
|
|
||||||
// show on debug widgets
|
|
||||||
|
|
||||||
// TODO: Should stop the CPU thread here once we multithread emulation.
|
|
||||||
|
|
||||||
active_breakpoint = event;
|
|
||||||
at_breakpoint = true;
|
|
||||||
|
|
||||||
// Tell all observers that we hit a breakpoint
|
|
||||||
for (auto& breakpoint_observer : breakpoint_observers) {
|
|
||||||
breakpoint_observer->OnMaxwellBreakPointHit(event, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wait until another thread tells us to Resume()
|
|
||||||
resume_from_breakpoint.wait(lock, [&] { return !at_breakpoint; });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void DebugContext::Resume() {
|
|
||||||
{
|
|
||||||
std::lock_guard lock{breakpoint_mutex};
|
|
||||||
|
|
||||||
// Tell all observers that we are about to resume
|
|
||||||
for (auto& breakpoint_observer : breakpoint_observers) {
|
|
||||||
breakpoint_observer->OnMaxwellResume();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Resume the waiting thread (i.e. OnEvent())
|
|
||||||
at_breakpoint = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
resume_from_breakpoint.notify_one();
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Tegra
|
|
@ -1,157 +0,0 @@
|
|||||||
// Copyright 2014 Citra Emulator Project
|
|
||||||
// Licensed under GPLv2
|
|
||||||
// Refer to the license.txt file included.
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <array>
|
|
||||||
#include <condition_variable>
|
|
||||||
#include <list>
|
|
||||||
#include <memory>
|
|
||||||
#include <mutex>
|
|
||||||
|
|
||||||
namespace Tegra {
|
|
||||||
|
|
||||||
class DebugContext {
|
|
||||||
public:
|
|
||||||
enum class Event {
|
|
||||||
FirstEvent = 0,
|
|
||||||
|
|
||||||
MaxwellCommandLoaded = FirstEvent,
|
|
||||||
MaxwellCommandProcessed,
|
|
||||||
IncomingPrimitiveBatch,
|
|
||||||
FinishedPrimitiveBatch,
|
|
||||||
|
|
||||||
NumEvents
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Inherit from this class to be notified of events registered to some debug context.
|
|
||||||
* Most importantly this is used for our debugger GUI.
|
|
||||||
*
|
|
||||||
* To implement event handling, override the OnMaxwellBreakPointHit and OnMaxwellResume methods.
|
|
||||||
* @warning All BreakPointObservers need to be on the same thread to guarantee thread-safe state
|
|
||||||
* access
|
|
||||||
* @todo Evaluate an alternative interface, in which there is only one managing observer and
|
|
||||||
* multiple child observers running (by design) on the same thread.
|
|
||||||
*/
|
|
||||||
class BreakPointObserver {
|
|
||||||
public:
|
|
||||||
/// Constructs the object such that it observes events of the given DebugContext.
|
|
||||||
explicit BreakPointObserver(std::shared_ptr<DebugContext> debug_context)
|
|
||||||
: context_weak(debug_context) {
|
|
||||||
std::unique_lock lock{debug_context->breakpoint_mutex};
|
|
||||||
debug_context->breakpoint_observers.push_back(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual ~BreakPointObserver() {
|
|
||||||
auto context = context_weak.lock();
|
|
||||||
if (context) {
|
|
||||||
{
|
|
||||||
std::unique_lock lock{context->breakpoint_mutex};
|
|
||||||
context->breakpoint_observers.remove(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we are the last observer to be destroyed, tell the debugger context that
|
|
||||||
// it is free to continue. In particular, this is required for a proper yuzu
|
|
||||||
// shutdown, when the emulation thread is waiting at a breakpoint.
|
|
||||||
if (context->breakpoint_observers.empty())
|
|
||||||
context->Resume();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Action to perform when a breakpoint was reached.
|
|
||||||
* @param event Type of event which triggered the breakpoint
|
|
||||||
* @param data Optional data pointer (if unused, this is a nullptr)
|
|
||||||
* @note This function will perform nothing unless it is overridden in the child class.
|
|
||||||
*/
|
|
||||||
virtual void OnMaxwellBreakPointHit(Event event, void* data) {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Action to perform when emulation is resumed from a breakpoint.
|
|
||||||
* @note This function will perform nothing unless it is overridden in the child class.
|
|
||||||
*/
|
|
||||||
virtual void OnMaxwellResume() {}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
/**
|
|
||||||
* Weak context pointer. This need not be valid, so when requesting a shared_ptr via
|
|
||||||
* context_weak.lock(), always compare the result against nullptr.
|
|
||||||
*/
|
|
||||||
std::weak_ptr<DebugContext> context_weak;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Simple structure defining a breakpoint state
|
|
||||||
*/
|
|
||||||
struct BreakPoint {
|
|
||||||
bool enabled = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Static constructor used to create a shared_ptr of a DebugContext.
|
|
||||||
*/
|
|
||||||
static std::shared_ptr<DebugContext> Construct() {
|
|
||||||
return std::shared_ptr<DebugContext>(new DebugContext);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Used by the emulation core when a given event has happened. If a breakpoint has been set
|
|
||||||
* for this event, OnEvent calls the event handlers of the registered breakpoint observers.
|
|
||||||
* The current thread then is halted until Resume() is called from another thread (or until
|
|
||||||
* emulation is stopped).
|
|
||||||
* @param event Event which has happened
|
|
||||||
* @param data Optional data pointer (pass nullptr if unused). Needs to remain valid until
|
|
||||||
* Resume() is called.
|
|
||||||
*/
|
|
||||||
void OnEvent(Event event, void* data) {
|
|
||||||
// This check is left in the header to allow the compiler to inline it.
|
|
||||||
if (!breakpoints[(int)event].enabled)
|
|
||||||
return;
|
|
||||||
// For the rest of event handling, call a separate function.
|
|
||||||
DoOnEvent(event, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DoOnEvent(Event event, void* data);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Resume from the current breakpoint.
|
|
||||||
* @warning Calling this from the same thread that OnEvent was called in will cause a deadlock.
|
|
||||||
* Calling from any other thread is safe.
|
|
||||||
*/
|
|
||||||
void Resume();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Delete all set breakpoints and resume emulation.
|
|
||||||
*/
|
|
||||||
void ClearBreakpoints() {
|
|
||||||
for (auto& bp : breakpoints) {
|
|
||||||
bp.enabled = false;
|
|
||||||
}
|
|
||||||
Resume();
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Evaluate if access to these members should be hidden behind a public interface.
|
|
||||||
std::array<BreakPoint, static_cast<int>(Event::NumEvents)> breakpoints;
|
|
||||||
Event active_breakpoint{};
|
|
||||||
bool at_breakpoint = false;
|
|
||||||
|
|
||||||
private:
|
|
||||||
/**
|
|
||||||
* Private default constructor to make sure people always construct this through Construct()
|
|
||||||
* instead.
|
|
||||||
*/
|
|
||||||
DebugContext() = default;
|
|
||||||
|
|
||||||
/// Mutex protecting current breakpoint state and the observer list.
|
|
||||||
std::mutex breakpoint_mutex;
|
|
||||||
|
|
||||||
/// Used by OnEvent to wait for resumption.
|
|
||||||
std::condition_variable resume_from_breakpoint;
|
|
||||||
|
|
||||||
/// List of registered observers
|
|
||||||
std::list<BreakPointObserver*> breakpoint_observers;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace Tegra
|
|
@ -1,27 +0,0 @@
|
|||||||
// Copyright 2014 Citra Emulator Project
|
|
||||||
// Licensed under GPLv2 or any later version
|
|
||||||
// Refer to the license.txt file included.
|
|
||||||
|
|
||||||
#include <QMetaType>
|
|
||||||
#include "yuzu/debugger/graphics/graphics_breakpoint_observer.h"
|
|
||||||
|
|
||||||
BreakPointObserverDock::BreakPointObserverDock(std::shared_ptr<Tegra::DebugContext> debug_context,
|
|
||||||
const QString& title, QWidget* parent)
|
|
||||||
: QDockWidget(title, parent), BreakPointObserver(debug_context) {
|
|
||||||
qRegisterMetaType<Tegra::DebugContext::Event>("Tegra::DebugContext::Event");
|
|
||||||
|
|
||||||
connect(this, &BreakPointObserverDock::Resumed, this, &BreakPointObserverDock::OnResumed);
|
|
||||||
|
|
||||||
// NOTE: This signal is emitted from a non-GUI thread, but connect() takes
|
|
||||||
// care of delaying its handling to the GUI thread.
|
|
||||||
connect(this, &BreakPointObserverDock::BreakPointHit, this,
|
|
||||||
&BreakPointObserverDock::OnBreakPointHit, Qt::BlockingQueuedConnection);
|
|
||||||
}
|
|
||||||
|
|
||||||
void BreakPointObserverDock::OnMaxwellBreakPointHit(Tegra::DebugContext::Event event, void* data) {
|
|
||||||
emit BreakPointHit(event, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
void BreakPointObserverDock::OnMaxwellResume() {
|
|
||||||
emit Resumed();
|
|
||||||
}
|
|
@ -1,33 +0,0 @@
|
|||||||
// Copyright 2014 Citra Emulator Project
|
|
||||||
// Licensed under GPLv2 or any later version
|
|
||||||
// Refer to the license.txt file included.
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <QDockWidget>
|
|
||||||
#include "video_core/debug_utils/debug_utils.h"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Utility class which forwards calls to OnMaxwellBreakPointHit and OnMaxwellResume to public slots.
|
|
||||||
* This is because the Maxwell breakpoint callbacks are called from a non-GUI thread, while
|
|
||||||
* the widget usually wants to perform reactions in the GUI thread.
|
|
||||||
*/
|
|
||||||
class BreakPointObserverDock : public QDockWidget,
|
|
||||||
protected Tegra::DebugContext::BreakPointObserver {
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
BreakPointObserverDock(std::shared_ptr<Tegra::DebugContext> debug_context, const QString& title,
|
|
||||||
QWidget* parent = nullptr);
|
|
||||||
|
|
||||||
void OnMaxwellBreakPointHit(Tegra::DebugContext::Event event, void* data) override;
|
|
||||||
void OnMaxwellResume() override;
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void Resumed();
|
|
||||||
void BreakPointHit(Tegra::DebugContext::Event event, void* data);
|
|
||||||
|
|
||||||
private:
|
|
||||||
virtual void OnBreakPointHit(Tegra::DebugContext::Event event, void* data) = 0;
|
|
||||||
virtual void OnResumed() = 0;
|
|
||||||
};
|
|
@ -1,221 +0,0 @@
|
|||||||
// Copyright 2014 Citra Emulator Project
|
|
||||||
// Licensed under GPLv2 or any later version
|
|
||||||
// Refer to the license.txt file included.
|
|
||||||
|
|
||||||
#include <QLabel>
|
|
||||||
#include <QMetaType>
|
|
||||||
#include <QPushButton>
|
|
||||||
#include <QTreeView>
|
|
||||||
#include <QVBoxLayout>
|
|
||||||
#include "common/assert.h"
|
|
||||||
#include "yuzu/debugger/graphics/graphics_breakpoints.h"
|
|
||||||
#include "yuzu/debugger/graphics/graphics_breakpoints_p.h"
|
|
||||||
|
|
||||||
BreakPointModel::BreakPointModel(std::shared_ptr<Tegra::DebugContext> 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 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int BreakPointModel::rowCount(const QModelIndex& parent) const {
|
|
||||||
return static_cast<int>(Tegra::DebugContext::Event::NumEvents);
|
|
||||||
}
|
|
||||||
|
|
||||||
QVariant BreakPointModel::data(const QModelIndex& index, int role) const {
|
|
||||||
const auto event = static_cast<Tegra::DebugContext::Event>(index.row());
|
|
||||||
|
|
||||||
switch (role) {
|
|
||||||
case Qt::DisplayRole: {
|
|
||||||
if (index.column() == 0) {
|
|
||||||
return DebugContextEventToString(event);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case Qt::CheckStateRole: {
|
|
||||||
if (index.column() == 0)
|
|
||||||
return data(index, Role_IsEnabled).toBool() ? Qt::Checked : Qt::Unchecked;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case Qt::BackgroundRole: {
|
|
||||||
if (at_breakpoint && index.row() == static_cast<int>(active_breakpoint)) {
|
|
||||||
return QBrush(QColor(0xE0, 0xE0, 0x10));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case Role_IsEnabled: {
|
|
||||||
auto context = context_weak.lock();
|
|
||||||
return context && context->breakpoints[(int)event].enabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return QVariant();
|
|
||||||
}
|
|
||||||
|
|
||||||
Qt::ItemFlags BreakPointModel::flags(const QModelIndex& index) const {
|
|
||||||
if (!index.isValid())
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
Qt::ItemFlags flags = Qt::ItemIsEnabled;
|
|
||||||
if (index.column() == 0)
|
|
||||||
flags |= Qt::ItemIsUserCheckable;
|
|
||||||
return flags;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool BreakPointModel::setData(const QModelIndex& index, const QVariant& value, int role) {
|
|
||||||
const auto event = static_cast<Tegra::DebugContext::Event>(index.row());
|
|
||||||
|
|
||||||
switch (role) {
|
|
||||||
case Qt::CheckStateRole: {
|
|
||||||
if (index.column() != 0)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
auto context = context_weak.lock();
|
|
||||||
if (!context)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
context->breakpoints[(int)event].enabled = value == Qt::Checked;
|
|
||||||
QModelIndex changed_index = createIndex(index.row(), 0);
|
|
||||||
emit dataChanged(changed_index, changed_index);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void BreakPointModel::OnBreakPointHit(Tegra::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<int>(event), 0),
|
|
||||||
createIndex(static_cast<int>(event), 0));
|
|
||||||
}
|
|
||||||
|
|
||||||
void BreakPointModel::OnResumed() {
|
|
||||||
auto context = context_weak.lock();
|
|
||||||
if (!context)
|
|
||||||
return;
|
|
||||||
|
|
||||||
at_breakpoint = context->at_breakpoint;
|
|
||||||
emit dataChanged(createIndex(static_cast<int>(active_breakpoint), 0),
|
|
||||||
createIndex(static_cast<int>(active_breakpoint), 0));
|
|
||||||
active_breakpoint = context->active_breakpoint;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString BreakPointModel::DebugContextEventToString(Tegra::DebugContext::Event event) {
|
|
||||||
switch (event) {
|
|
||||||
case Tegra::DebugContext::Event::MaxwellCommandLoaded:
|
|
||||||
return tr("Maxwell command loaded");
|
|
||||||
case Tegra::DebugContext::Event::MaxwellCommandProcessed:
|
|
||||||
return tr("Maxwell command processed");
|
|
||||||
case Tegra::DebugContext::Event::IncomingPrimitiveBatch:
|
|
||||||
return tr("Incoming primitive batch");
|
|
||||||
case Tegra::DebugContext::Event::FinishedPrimitiveBatch:
|
|
||||||
return tr("Finished primitive batch");
|
|
||||||
case Tegra::DebugContext::Event::NumEvents:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return tr("Unknown debug context event");
|
|
||||||
}
|
|
||||||
|
|
||||||
GraphicsBreakPointsWidget::GraphicsBreakPointsWidget(
|
|
||||||
std::shared_ptr<Tegra::DebugContext> debug_context, QWidget* parent)
|
|
||||||
: QDockWidget(tr("Maxwell Breakpoints"), parent), Tegra::DebugContext::BreakPointObserver(
|
|
||||||
debug_context) {
|
|
||||||
setObjectName(QStringLiteral("TegraBreakPointsWidget"));
|
|
||||||
|
|
||||||
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->setRootIsDecorated(false);
|
|
||||||
breakpoint_list->setHeaderHidden(true);
|
|
||||||
breakpoint_list->setModel(breakpoint_model);
|
|
||||||
|
|
||||||
qRegisterMetaType<Tegra::DebugContext::Event>("Tegra::DebugContext::Event");
|
|
||||||
|
|
||||||
connect(breakpoint_list, &QTreeView::doubleClicked, this,
|
|
||||||
&GraphicsBreakPointsWidget::OnItemDoubleClicked);
|
|
||||||
|
|
||||||
connect(resume_button, &QPushButton::clicked, this,
|
|
||||||
&GraphicsBreakPointsWidget::OnResumeRequested);
|
|
||||||
|
|
||||||
connect(this, &GraphicsBreakPointsWidget::BreakPointHit, this,
|
|
||||||
&GraphicsBreakPointsWidget::OnBreakPointHit, Qt::BlockingQueuedConnection);
|
|
||||||
connect(this, &GraphicsBreakPointsWidget::Resumed, this, &GraphicsBreakPointsWidget::OnResumed);
|
|
||||||
|
|
||||||
connect(this, &GraphicsBreakPointsWidget::BreakPointHit, breakpoint_model,
|
|
||||||
&BreakPointModel::OnBreakPointHit, Qt::BlockingQueuedConnection);
|
|
||||||
connect(this, &GraphicsBreakPointsWidget::Resumed, breakpoint_model,
|
|
||||||
&BreakPointModel::OnResumed);
|
|
||||||
|
|
||||||
connect(this, &GraphicsBreakPointsWidget::BreakPointsChanged,
|
|
||||||
[this](const QModelIndex& top_left, const QModelIndex& bottom_right) {
|
|
||||||
breakpoint_model->dataChanged(top_left, bottom_right);
|
|
||||||
});
|
|
||||||
|
|
||||||
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_widget->setLayout(main_layout);
|
|
||||||
|
|
||||||
setWidget(main_widget);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GraphicsBreakPointsWidget::OnMaxwellBreakPointHit(Event event, void* data) {
|
|
||||||
// Process in GUI thread
|
|
||||||
emit BreakPointHit(event, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GraphicsBreakPointsWidget::OnBreakPointHit(Tegra::DebugContext::Event event, void* data) {
|
|
||||||
status_text->setText(tr("Emulation halted at breakpoint"));
|
|
||||||
resume_button->setEnabled(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GraphicsBreakPointsWidget::OnMaxwellResume() {
|
|
||||||
// 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::OnItemDoubleClicked(const QModelIndex& index) {
|
|
||||||
if (!index.isValid())
|
|
||||||
return;
|
|
||||||
|
|
||||||
QModelIndex check_index = breakpoint_list->model()->index(index.row(), 0);
|
|
||||||
QVariant enabled = breakpoint_list->model()->data(check_index, Qt::CheckStateRole);
|
|
||||||
QVariant new_state = Qt::Unchecked;
|
|
||||||
if (enabled == Qt::Unchecked)
|
|
||||||
new_state = Qt::Checked;
|
|
||||||
breakpoint_list->model()->setData(check_index, new_state, Qt::CheckStateRole);
|
|
||||||
}
|
|
@ -1,45 +0,0 @@
|
|||||||
// Copyright 2014 Citra Emulator Project
|
|
||||||
// Licensed under GPLv2 or any later version
|
|
||||||
// Refer to the license.txt file included.
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
#include <QDockWidget>
|
|
||||||
#include "video_core/debug_utils/debug_utils.h"
|
|
||||||
|
|
||||||
class QLabel;
|
|
||||||
class QPushButton;
|
|
||||||
class QTreeView;
|
|
||||||
|
|
||||||
class BreakPointModel;
|
|
||||||
|
|
||||||
class GraphicsBreakPointsWidget : public QDockWidget, Tegra::DebugContext::BreakPointObserver {
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
using Event = Tegra::DebugContext::Event;
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit GraphicsBreakPointsWidget(std::shared_ptr<Tegra::DebugContext> debug_context,
|
|
||||||
QWidget* parent = nullptr);
|
|
||||||
|
|
||||||
void OnMaxwellBreakPointHit(Tegra::DebugContext::Event event, void* data) override;
|
|
||||||
void OnMaxwellResume() override;
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void Resumed();
|
|
||||||
void BreakPointHit(Tegra::DebugContext::Event event, void* data);
|
|
||||||
void BreakPointsChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight);
|
|
||||||
|
|
||||||
private:
|
|
||||||
void OnBreakPointHit(Tegra::DebugContext::Event event, void* data);
|
|
||||||
void OnItemDoubleClicked(const QModelIndex&);
|
|
||||||
void OnResumeRequested();
|
|
||||||
void OnResumed();
|
|
||||||
|
|
||||||
QLabel* status_text;
|
|
||||||
QPushButton* resume_button;
|
|
||||||
|
|
||||||
BreakPointModel* breakpoint_model;
|
|
||||||
QTreeView* breakpoint_list;
|
|
||||||
};
|
|
@ -1,37 +0,0 @@
|
|||||||
// Copyright 2014 Citra Emulator Project
|
|
||||||
// Licensed under GPLv2 or any later version
|
|
||||||
// Refer to the license.txt file included.
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
#include <QAbstractListModel>
|
|
||||||
#include "video_core/debug_utils/debug_utils.h"
|
|
||||||
|
|
||||||
class BreakPointModel : public QAbstractListModel {
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
enum {
|
|
||||||
Role_IsEnabled = Qt::UserRole,
|
|
||||||
};
|
|
||||||
|
|
||||||
BreakPointModel(std::shared_ptr<Tegra::DebugContext> context, QObject* parent);
|
|
||||||
|
|
||||||
int columnCount(const QModelIndex& parent = QModelIndex()) const override;
|
|
||||||
int rowCount(const QModelIndex& parent = QModelIndex()) const override;
|
|
||||||
QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
|
|
||||||
Qt::ItemFlags flags(const QModelIndex& index) const override;
|
|
||||||
|
|
||||||
bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole) override;
|
|
||||||
|
|
||||||
void OnBreakPointHit(Tegra::DebugContext::Event event);
|
|
||||||
void OnResumed();
|
|
||||||
|
|
||||||
private:
|
|
||||||
static QString DebugContextEventToString(Tegra::DebugContext::Event event);
|
|
||||||
|
|
||||||
std::weak_ptr<Tegra::DebugContext> context_weak;
|
|
||||||
bool at_breakpoint;
|
|
||||||
Tegra::DebugContext::Event active_breakpoint;
|
|
||||||
};
|
|
Loading…
Reference in New Issue