diff options
author | Zephyron <zephyron@citron-emu.org> | 2024-12-31 16:19:25 +1000 |
---|---|---|
committer | Zephyron <zephyron@citron-emu.org> | 2024-12-31 16:19:25 +1000 |
commit | 9427e27e24a7135880ee2881c3c44988e174b41a (patch) | |
tree | 83f0062a35be144f6b162eaa823c5b3c7620146e /src/yuzu/debugger | |
parent | b35ae725d20960411e8588b11c12a2d55f86c9d0 (diff) |
chore: update project branding to citron
Diffstat (limited to 'src/yuzu/debugger')
-rw-r--r-- | src/yuzu/debugger/console.cpp | 49 | ||||
-rw-r--r-- | src/yuzu/debugger/console.h | 13 | ||||
-rw-r--r-- | src/yuzu/debugger/controller.cpp | 116 | ||||
-rw-r--r-- | src/yuzu/debugger/controller.h | 56 | ||||
-rw-r--r-- | src/yuzu/debugger/profiler.cpp | 229 | ||||
-rw-r--r-- | src/yuzu/debugger/profiler.h | 27 | ||||
-rw-r--r-- | src/yuzu/debugger/wait_tree.cpp | 431 | ||||
-rw-r--r-- | src/yuzu/debugger/wait_tree.h | 188 |
8 files changed, 0 insertions, 1109 deletions
diff --git a/src/yuzu/debugger/console.cpp b/src/yuzu/debugger/console.cpp deleted file mode 100644 index 1c1342ff1..000000000 --- a/src/yuzu/debugger/console.cpp +++ /dev/null @@ -1,49 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#ifdef _WIN32 -#include <windows.h> - -#include <wincon.h> -#endif - -#include "common/logging/backend.h" -#include "yuzu/debugger/console.h" -#include "yuzu/uisettings.h" - -namespace Debugger { -void ToggleConsole() { - static bool console_shown = false; - if (console_shown == UISettings::values.show_console.GetValue()) { - return; - } else { - console_shown = UISettings::values.show_console.GetValue(); - } - - using namespace Common::Log; -#if defined(_WIN32) && !defined(_DEBUG) - FILE* temp; - if (UISettings::values.show_console) { - if (AllocConsole()) { - // The first parameter for freopen_s is a out parameter, so we can just ignore it - freopen_s(&temp, "CONIN$", "r", stdin); - freopen_s(&temp, "CONOUT$", "w", stdout); - freopen_s(&temp, "CONOUT$", "w", stderr); - SetConsoleOutputCP(65001); - SetColorConsoleBackendEnabled(true); - } - } else { - if (FreeConsole()) { - // In order to close the console, we have to also detach the streams on it. - // Just redirect them to NUL if there is no console window - SetColorConsoleBackendEnabled(false); - freopen_s(&temp, "NUL", "r", stdin); - freopen_s(&temp, "NUL", "w", stdout); - freopen_s(&temp, "NUL", "w", stderr); - } - } -#else - SetColorConsoleBackendEnabled(UISettings::values.show_console.GetValue()); -#endif -} -} // namespace Debugger diff --git a/src/yuzu/debugger/console.h b/src/yuzu/debugger/console.h deleted file mode 100644 index 2491d1ec1..000000000 --- a/src/yuzu/debugger/console.h +++ /dev/null @@ -1,13 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -namespace Debugger { - -/** - * Uses the WINAPI to hide or show the stderr console. This function is a placeholder until we can - * get a real qt logging window which would work for all platforms. - */ -void ToggleConsole(); -} // namespace Debugger diff --git a/src/yuzu/debugger/controller.cpp b/src/yuzu/debugger/controller.cpp deleted file mode 100644 index 216d2974d..000000000 --- a/src/yuzu/debugger/controller.cpp +++ /dev/null @@ -1,116 +0,0 @@ -// SPDX-FileCopyrightText: 2015 Citra Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include <QAction> -#include <QLayout> -#include <QString> -#include "common/settings.h" -#include "hid_core/frontend/emulated_controller.h" -#include "hid_core/hid_core.h" -#include "input_common/drivers/tas_input.h" -#include "input_common/main.h" -#include "yuzu/configuration/configure_input_player_widget.h" -#include "yuzu/debugger/controller.h" - -ControllerDialog::ControllerDialog(Core::HID::HIDCore& hid_core_, - std::shared_ptr<InputCommon::InputSubsystem> input_subsystem_, - QWidget* parent) - : QWidget(parent, Qt::Dialog), hid_core{hid_core_}, input_subsystem{input_subsystem_} { - setObjectName(QStringLiteral("Controller")); - setWindowTitle(tr("Controller P1")); - resize(500, 350); - setMinimumSize(500, 350); - // Enable the maximize button - setWindowFlags(windowFlags() | Qt::WindowMaximizeButtonHint); - - widget = new PlayerControlPreview(this); - refreshConfiguration(); - QLayout* layout = new QVBoxLayout(this); - layout->setContentsMargins(0, 0, 0, 0); - layout->addWidget(widget); - setLayout(layout); - - // Configure focus so that widget is focusable and the dialog automatically forwards focus to - // it. - setFocusProxy(widget); - widget->setFocusPolicy(Qt::StrongFocus); - widget->setFocus(); -} - -void ControllerDialog::refreshConfiguration() { - UnloadController(); - auto* player_1 = hid_core.GetEmulatedController(Core::HID::NpadIdType::Player1); - auto* handheld = hid_core.GetEmulatedController(Core::HID::NpadIdType::Handheld); - // Display the correct controller - controller = handheld->IsConnected() ? handheld : player_1; - - Core::HID::ControllerUpdateCallback engine_callback{ - .on_change = [this](Core::HID::ControllerTriggerType type) { ControllerUpdate(type); }, - .is_npad_service = true, - }; - callback_key = controller->SetCallback(engine_callback); - widget->SetController(controller); - is_controller_set = true; -} - -QAction* ControllerDialog::toggleViewAction() { - if (toggle_view_action == nullptr) { - toggle_view_action = new QAction(tr("&Controller P1"), this); - toggle_view_action->setCheckable(true); - toggle_view_action->setChecked(isVisible()); - connect(toggle_view_action, &QAction::toggled, this, &ControllerDialog::setVisible); - } - - return toggle_view_action; -} - -void ControllerDialog::UnloadController() { - widget->UnloadController(); - if (is_controller_set) { - controller->DeleteCallback(callback_key); - is_controller_set = false; - } -} - -void ControllerDialog::showEvent(QShowEvent* ev) { - if (toggle_view_action) { - toggle_view_action->setChecked(isVisible()); - } - QWidget::showEvent(ev); -} - -void ControllerDialog::hideEvent(QHideEvent* ev) { - if (toggle_view_action) { - toggle_view_action->setChecked(isVisible()); - } - QWidget::hideEvent(ev); -} - -void ControllerDialog::ControllerUpdate(Core::HID::ControllerTriggerType type) { - // TODO(german77): Remove TAS from here - switch (type) { - case Core::HID::ControllerTriggerType::Button: - case Core::HID::ControllerTriggerType::Stick: { - const auto buttons_values = controller->GetButtonsValues(); - const auto stick_values = controller->GetSticks(); - u64 buttons = 0; - std::size_t index = 0; - for (const auto& button : buttons_values) { - buttons |= button.value ? 1LLU << index : 0; - index++; - } - const InputCommon::TasInput::TasAnalog left_axis = { - .x = stick_values.left.x / 32767.f, - .y = stick_values.left.y / 32767.f, - }; - const InputCommon::TasInput::TasAnalog right_axis = { - .x = stick_values.right.x / 32767.f, - .y = stick_values.right.y / 32767.f, - }; - input_subsystem->GetTas()->RecordInput(buttons, left_axis, right_axis); - break; - } - default: - break; - } -} diff --git a/src/yuzu/debugger/controller.h b/src/yuzu/debugger/controller.h deleted file mode 100644 index 9651dfaa9..000000000 --- a/src/yuzu/debugger/controller.h +++ /dev/null @@ -1,56 +0,0 @@ -// SPDX-FileCopyrightText: 2015 Citra Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include <QWidget> - -class QAction; -class QHideEvent; -class QShowEvent; -class PlayerControlPreview; - -namespace InputCommon { -class InputSubsystem; -} - -namespace Core::HID { -class HIDCore; -class EmulatedController; -enum class ControllerTriggerType; -} // namespace Core::HID - -class ControllerDialog : public QWidget { - Q_OBJECT - -public: - explicit ControllerDialog(Core::HID::HIDCore& hid_core_, - std::shared_ptr<InputCommon::InputSubsystem> input_subsystem_, - QWidget* parent = nullptr); - - /// Returns a QAction that can be used to toggle visibility of this dialog. - QAction* toggleViewAction(); - - /// Reloads the widget to apply any changes in the configuration - void refreshConfiguration(); - - /// Disables events from the emulated controller - void UnloadController(); - -protected: - void showEvent(QShowEvent* ev) override; - void hideEvent(QHideEvent* ev) override; - -private: - /// Redirects input from the widget to the TAS driver - void ControllerUpdate(Core::HID::ControllerTriggerType type); - - int callback_key; - bool is_controller_set{}; - Core::HID::EmulatedController* controller; - - QAction* toggle_view_action = nullptr; - PlayerControlPreview* widget; - Core::HID::HIDCore& hid_core; - std::shared_ptr<InputCommon::InputSubsystem> input_subsystem; -}; diff --git a/src/yuzu/debugger/profiler.cpp b/src/yuzu/debugger/profiler.cpp deleted file mode 100644 index 493ee0b17..000000000 --- a/src/yuzu/debugger/profiler.cpp +++ /dev/null @@ -1,229 +0,0 @@ -// SPDX-FileCopyrightText: 2015 Citra Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include <QAction> -#include <QLayout> -#include <QMouseEvent> -#include <QPainter> -#include <QString> -#include <QTimer> -#include "common/common_types.h" -#include "common/microprofile.h" -#include "yuzu/debugger/profiler.h" -#include "yuzu/util/util.h" - -// Include the implementation of the UI in this file. This isn't in microprofile.cpp because the -// non-Qt frontends don't need it (and don't implement the UI drawing hooks either). -#if MICROPROFILE_ENABLED -#define MICROPROFILEUI_IMPL 1 -#include "common/microprofileui.h" - -class MicroProfileWidget : public QWidget { -public: - MicroProfileWidget(QWidget* parent = nullptr); - -protected: - void paintEvent(QPaintEvent* ev) override; - void showEvent(QShowEvent* ev) override; - void hideEvent(QHideEvent* ev) override; - - void mouseMoveEvent(QMouseEvent* ev) override; - void mousePressEvent(QMouseEvent* ev) override; - void mouseReleaseEvent(QMouseEvent* ev) override; - void wheelEvent(QWheelEvent* ev) override; - - void keyPressEvent(QKeyEvent* ev) override; - void keyReleaseEvent(QKeyEvent* ev) override; - -private: - /// This timer is used to redraw the widget's contents continuously. To save resources, it only - /// runs while the widget is visible. - QTimer update_timer; - /// Scale the coordinate system appropriately when dpi != 96. - qreal x_scale = 1.0, y_scale = 1.0; -}; - -#endif - -MicroProfileDialog::MicroProfileDialog(QWidget* parent) : QWidget(parent, Qt::Dialog) { - setObjectName(QStringLiteral("MicroProfile")); - setWindowTitle(tr("&MicroProfile")); - resize(1000, 600); - // Enable the maximize button - setWindowFlags(windowFlags() | Qt::WindowMaximizeButtonHint); - -#if MICROPROFILE_ENABLED - - MicroProfileWidget* widget = new MicroProfileWidget(this); - - QLayout* layout = new QVBoxLayout(this); - layout->setContentsMargins(0, 0, 0, 0); - layout->addWidget(widget); - setLayout(layout); - - // Configure focus so that widget is focusable and the dialog automatically forwards focus to - // it. - setFocusProxy(widget); - widget->setFocusPolicy(Qt::StrongFocus); - widget->setFocus(); -#endif -} - -QAction* MicroProfileDialog::toggleViewAction() { - if (toggle_view_action == nullptr) { - toggle_view_action = new QAction(windowTitle(), this); - toggle_view_action->setCheckable(true); - toggle_view_action->setChecked(isVisible()); - connect(toggle_view_action, &QAction::toggled, this, &MicroProfileDialog::setVisible); - } - - return toggle_view_action; -} - -void MicroProfileDialog::showEvent(QShowEvent* ev) { - if (toggle_view_action) { - toggle_view_action->setChecked(isVisible()); - } - QWidget::showEvent(ev); -} - -void MicroProfileDialog::hideEvent(QHideEvent* ev) { - if (toggle_view_action) { - toggle_view_action->setChecked(isVisible()); - } - QWidget::hideEvent(ev); -} - -#if MICROPROFILE_ENABLED - -/// There's no way to pass a user pointer to MicroProfile, so this variable is used to make the -/// QPainter available inside the drawing callbacks. -static QPainter* mp_painter = nullptr; - -MicroProfileWidget::MicroProfileWidget(QWidget* parent) : QWidget(parent) { - // Send mouse motion events even when not dragging. - setMouseTracking(true); - - MicroProfileSetDisplayMode(1); // Timers screen - MicroProfileInitUI(); - - connect(&update_timer, &QTimer::timeout, this, qOverload<>(&MicroProfileWidget::update)); -} - -void MicroProfileWidget::paintEvent(QPaintEvent* ev) { - QPainter painter(this); - - // The units used by Microprofile for drawing are based in pixels on a 96 dpi display. - x_scale = qreal(painter.device()->logicalDpiX()) / 96.0; - y_scale = qreal(painter.device()->logicalDpiY()) / 96.0; - painter.scale(x_scale, y_scale); - - painter.setBackground(Qt::black); - painter.eraseRect(rect()); - - QFont font = GetMonospaceFont(); - font.setPixelSize(MICROPROFILE_TEXT_HEIGHT); - painter.setFont(font); - - mp_painter = &painter; - MicroProfileDraw(rect().width() / x_scale, rect().height() / y_scale); - mp_painter = nullptr; -} - -void MicroProfileWidget::showEvent(QShowEvent* ev) { - update_timer.start(15); // ~60 Hz - QWidget::showEvent(ev); -} - -void MicroProfileWidget::hideEvent(QHideEvent* ev) { - update_timer.stop(); - QWidget::hideEvent(ev); -} - -void MicroProfileWidget::mouseMoveEvent(QMouseEvent* ev) { - const auto mouse_position = ev->pos(); - MicroProfileMousePosition(mouse_position.x() / x_scale, mouse_position.y() / y_scale, 0); - ev->accept(); -} - -void MicroProfileWidget::mousePressEvent(QMouseEvent* ev) { - const auto mouse_position = ev->pos(); - MicroProfileMousePosition(mouse_position.x() / x_scale, mouse_position.y() / y_scale, 0); - MicroProfileMouseButton(ev->buttons() & Qt::LeftButton, ev->buttons() & Qt::RightButton); - ev->accept(); -} - -void MicroProfileWidget::mouseReleaseEvent(QMouseEvent* ev) { - const auto mouse_position = ev->pos(); - MicroProfileMousePosition(mouse_position.x() / x_scale, mouse_position.y() / y_scale, 0); - MicroProfileMouseButton(ev->buttons() & Qt::LeftButton, ev->buttons() & Qt::RightButton); - ev->accept(); -} - -void MicroProfileWidget::wheelEvent(QWheelEvent* ev) { - const auto wheel_position = ev->position().toPoint(); - MicroProfileMousePosition(wheel_position.x() / x_scale, wheel_position.y() / y_scale, - ev->angleDelta().y() / 120); - ev->accept(); -} - -void MicroProfileWidget::keyPressEvent(QKeyEvent* ev) { - if (ev->key() == Qt::Key_Control) { - // Inform MicroProfile that the user is holding Ctrl. - MicroProfileModKey(1); - } - QWidget::keyPressEvent(ev); -} - -void MicroProfileWidget::keyReleaseEvent(QKeyEvent* ev) { - if (ev->key() == Qt::Key_Control) { - MicroProfileModKey(0); - } - QWidget::keyReleaseEvent(ev); -} - -// These functions are called by MicroProfileDraw to draw the interface elements on the screen. - -void MicroProfileDrawText(int x, int y, u32 hex_color, const char* text, u32 text_length) { - // hex_color does not include an alpha, so it must be assumed to be 255 - mp_painter->setPen(QColor::fromRgb(hex_color)); - - // It's impossible to draw a string using a monospaced font with a fixed width per cell in a - // way that's reliable across different platforms and fonts as far as I (yuriks) can tell, so - // draw each character individually in order to precisely control the text advance. - for (u32 i = 0; i < text_length; ++i) { - // Position the text baseline 1 pixel above the bottom of the text cell, this gives nice - // vertical alignment of text for a wide range of tested fonts. - mp_painter->drawText(x, y + MICROPROFILE_TEXT_HEIGHT - 2, QString{QLatin1Char{text[i]}}); - x += MICROPROFILE_TEXT_WIDTH + 1; - } -} - -void MicroProfileDrawBox(int left, int top, int right, int bottom, u32 hex_color, - MicroProfileBoxType type) { - QColor color = QColor::fromRgba(hex_color); - QBrush brush = color; - if (type == MicroProfileBoxTypeBar) { - QLinearGradient gradient(left, top, left, bottom); - gradient.setColorAt(0.f, color.lighter(125)); - gradient.setColorAt(1.f, color.darker(125)); - brush = gradient; - } - mp_painter->fillRect(left, top, right - left, bottom - top, brush); -} - -void MicroProfileDrawLine2D(u32 vertices_length, float* vertices, u32 hex_color) { - // Temporary vector used to convert between the float array and QPointF. Marked static to reuse - // the allocation across calls. - static std::vector<QPointF> point_buf; - - for (u32 i = 0; i < vertices_length; ++i) { - point_buf.emplace_back(vertices[i * 2 + 0], vertices[i * 2 + 1]); - } - - // hex_color does not include an alpha, so it must be assumed to be 255 - mp_painter->setPen(QColor::fromRgb(hex_color)); - mp_painter->drawPolyline(point_buf.data(), vertices_length); - point_buf.clear(); -} -#endif diff --git a/src/yuzu/debugger/profiler.h b/src/yuzu/debugger/profiler.h deleted file mode 100644 index 4c8ccd3c2..000000000 --- a/src/yuzu/debugger/profiler.h +++ /dev/null @@ -1,27 +0,0 @@ -// SPDX-FileCopyrightText: 2015 Citra Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include <QWidget> - -class QAction; -class QHideEvent; -class QShowEvent; - -class MicroProfileDialog : public QWidget { - Q_OBJECT - -public: - explicit MicroProfileDialog(QWidget* parent = nullptr); - - /// Returns a QAction that can be used to toggle visibility of this dialog. - QAction* toggleViewAction(); - -protected: - void showEvent(QShowEvent* ev) override; - void hideEvent(QHideEvent* ev) override; - -private: - QAction* toggle_view_action = nullptr; -}; diff --git a/src/yuzu/debugger/wait_tree.cpp b/src/yuzu/debugger/wait_tree.cpp deleted file mode 100644 index c05a05057..000000000 --- a/src/yuzu/debugger/wait_tree.cpp +++ /dev/null @@ -1,431 +0,0 @@ -// SPDX-FileCopyrightText: 2016 Citra Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include <array> -#include <fmt/format.h> - -#include "yuzu/debugger/wait_tree.h" -#include "yuzu/uisettings.h" - -#include "core/arm/debug.h" -#include "core/core.h" -#include "core/hle/kernel/k_class_token.h" -#include "core/hle/kernel/k_handle_table.h" -#include "core/hle/kernel/k_process.h" -#include "core/hle/kernel/k_readable_event.h" -#include "core/hle/kernel/k_scheduler.h" -#include "core/hle/kernel/k_synchronization_object.h" -#include "core/hle/kernel/k_thread.h" -#include "core/hle/kernel/svc_common.h" -#include "core/hle/kernel/svc_types.h" -#include "core/memory.h" - -namespace { - -constexpr std::array<std::array<Qt::GlobalColor, 2>, 10> WaitTreeColors{{ - {Qt::GlobalColor::darkGreen, Qt::GlobalColor::green}, - {Qt::GlobalColor::darkBlue, Qt::GlobalColor::cyan}, - {Qt::GlobalColor::lightGray, Qt::GlobalColor::lightGray}, - {Qt::GlobalColor::lightGray, Qt::GlobalColor::lightGray}, - {Qt::GlobalColor::darkRed, Qt::GlobalColor::red}, - {Qt::GlobalColor::darkYellow, Qt::GlobalColor::yellow}, - {Qt::GlobalColor::red, Qt::GlobalColor::red}, - {Qt::GlobalColor::darkCyan, Qt::GlobalColor::cyan}, - {Qt::GlobalColor::gray, Qt::GlobalColor::gray}, -}}; - -bool IsDarkTheme() { - const auto& theme = UISettings::values.theme; - return theme == std::string("qdarkstyle") || theme == std::string("qdarkstyle_midnight_blue") || - theme == std::string("colorful_dark") || theme == std::string("colorful_midnight_blue"); -} - -} // namespace - -WaitTreeItem::WaitTreeItem() = default; -WaitTreeItem::~WaitTreeItem() = default; - -QColor WaitTreeItem::GetColor() const { - if (IsDarkTheme()) { - return QColor(Qt::GlobalColor::white); - } else { - return QColor(Qt::GlobalColor::black); - } -} - -std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeItem::GetChildren() const { - return {}; -} - -void WaitTreeItem::Expand() { - if (IsExpandable() && !expanded) { - children = GetChildren(); - for (std::size_t i = 0; i < children.size(); ++i) { - children[i]->parent = this; - children[i]->row = i; - } - expanded = true; - } -} - -WaitTreeItem* WaitTreeItem::Parent() const { - return parent; -} - -const std::vector<std::unique_ptr<WaitTreeItem>>& WaitTreeItem::Children() const { - return children; -} - -bool WaitTreeItem::IsExpandable() const { - return false; -} - -std::size_t WaitTreeItem::Row() const { - return row; -} - -std::vector<std::unique_ptr<WaitTreeThread>> WaitTreeItem::MakeThreadItemList( - Core::System& system) { - std::vector<std::unique_ptr<WaitTreeThread>> item_list; - std::size_t row = 0; - auto add_threads = [&](const std::vector<Kernel::KThread*>& threads) { - for (std::size_t i = 0; i < threads.size(); ++i) { - if (threads[i]->GetThreadType() == Kernel::ThreadType::User) { - item_list.push_back(std::make_unique<WaitTreeThread>(*threads[i], system)); - item_list.back()->row = row; - } - ++row; - } - }; - - add_threads(system.GlobalSchedulerContext().GetThreadList()); - - return item_list; -} - -WaitTreeText::WaitTreeText(QString t) : text(std::move(t)) {} -WaitTreeText::~WaitTreeText() = default; - -QString WaitTreeText::GetText() const { - return text; -} - -WaitTreeCallstack::WaitTreeCallstack(const Kernel::KThread& thread_, Core::System& system_) - : thread{thread_}, system{system_} {} -WaitTreeCallstack::~WaitTreeCallstack() = default; - -QString WaitTreeCallstack::GetText() const { - return tr("Call stack"); -} - -std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeCallstack::GetChildren() const { - std::vector<std::unique_ptr<WaitTreeItem>> list; - - if (thread.GetThreadType() != Kernel::ThreadType::User) { - return list; - } - - if (thread.GetOwnerProcess() == nullptr || !thread.GetOwnerProcess()->Is64Bit()) { - return list; - } - - auto backtrace = Core::GetBacktraceFromContext(thread.GetOwnerProcess(), thread.GetContext()); - - for (auto& entry : backtrace) { - std::string s = fmt::format("{:20}{:016X} {:016X} {:016X} {}", entry.module, entry.address, - entry.original_address, entry.offset, entry.name); - list.push_back(std::make_unique<WaitTreeText>(QString::fromStdString(s))); - } - - return list; -} - -WaitTreeSynchronizationObject::WaitTreeSynchronizationObject( - const Kernel::KSynchronizationObject& object_, Core::System& system_) - : object{object_}, system{system_} {} -WaitTreeSynchronizationObject::~WaitTreeSynchronizationObject() = default; - -WaitTreeExpandableItem::WaitTreeExpandableItem() = default; -WaitTreeExpandableItem::~WaitTreeExpandableItem() = default; - -bool WaitTreeExpandableItem::IsExpandable() const { - return true; -} - -QString WaitTreeSynchronizationObject::GetText() const { - return tr("[%1] %2") - .arg(object.GetId()) - .arg(QString::fromStdString(object.GetTypeObj().GetName())); -} - -std::unique_ptr<WaitTreeSynchronizationObject> WaitTreeSynchronizationObject::make( - const Kernel::KSynchronizationObject& object, Core::System& system) { - const auto type = - static_cast<Kernel::KClassTokenGenerator::ObjectType>(object.GetTypeObj().GetClassToken()); - switch (type) { - case Kernel::KClassTokenGenerator::ObjectType::KReadableEvent: - return std::make_unique<WaitTreeEvent>(static_cast<const Kernel::KReadableEvent&>(object), - system); - case Kernel::KClassTokenGenerator::ObjectType::KThread: - return std::make_unique<WaitTreeThread>(static_cast<const Kernel::KThread&>(object), - system); - default: - return std::make_unique<WaitTreeSynchronizationObject>(object, system); - } -} - -std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeSynchronizationObject::GetChildren() const { - std::vector<std::unique_ptr<WaitTreeItem>> list; - - auto threads = object.GetWaitingThreadsForDebugging(); - if (threads.empty()) { - list.push_back(std::make_unique<WaitTreeText>(tr("waited by no thread"))); - } else { - list.push_back(std::make_unique<WaitTreeThreadList>(std::move(threads), system)); - } - - return list; -} - -WaitTreeThread::WaitTreeThread(const Kernel::KThread& thread, Core::System& system_) - : WaitTreeSynchronizationObject(thread, system_), system{system_} {} -WaitTreeThread::~WaitTreeThread() = default; - -QString WaitTreeThread::GetText() const { - const auto& thread = static_cast<const Kernel::KThread&>(object); - QString status; - switch (thread.GetState()) { - case Kernel::ThreadState::Runnable: - if (!thread.IsSuspended()) { - status = tr("runnable"); - } else { - status = tr("paused"); - } - break; - case Kernel::ThreadState::Waiting: - switch (thread.GetWaitReasonForDebugging()) { - case Kernel::ThreadWaitReasonForDebugging::Sleep: - status = tr("sleeping"); - break; - case Kernel::ThreadWaitReasonForDebugging::IPC: - status = tr("waiting for IPC reply"); - break; - case Kernel::ThreadWaitReasonForDebugging::Synchronization: - status = tr("waiting for objects"); - break; - case Kernel::ThreadWaitReasonForDebugging::ConditionVar: - status = tr("waiting for condition variable"); - break; - case Kernel::ThreadWaitReasonForDebugging::Arbitration: - status = tr("waiting for address arbiter"); - break; - case Kernel::ThreadWaitReasonForDebugging::Suspended: - status = tr("waiting for suspend resume"); - break; - default: - status = tr("waiting"); - break; - } - break; - case Kernel::ThreadState::Initialized: - status = tr("initialized"); - break; - case Kernel::ThreadState::Terminated: - status = tr("terminated"); - break; - default: - status = tr("unknown"); - break; - } - - const auto& context = thread.GetContext(); - const QString pc_info = tr(" PC = 0x%1 LR = 0x%2") - .arg(context.pc, 8, 16, QLatin1Char{'0'}) - .arg(context.lr, 8, 16, QLatin1Char{'0'}); - return QStringLiteral("%1%2 (%3) ") - .arg(WaitTreeSynchronizationObject::GetText(), pc_info, status); -} - -QColor WaitTreeThread::GetColor() const { - const std::size_t color_index = IsDarkTheme() ? 1 : 0; - - const auto& thread = static_cast<const Kernel::KThread&>(object); - switch (thread.GetState()) { - case Kernel::ThreadState::Runnable: - if (!thread.IsSuspended()) { - return QColor(WaitTreeColors[0][color_index]); - } else { - return QColor(WaitTreeColors[2][color_index]); - } - case Kernel::ThreadState::Waiting: - switch (thread.GetWaitReasonForDebugging()) { - case Kernel::ThreadWaitReasonForDebugging::IPC: - return QColor(WaitTreeColors[4][color_index]); - case Kernel::ThreadWaitReasonForDebugging::Sleep: - return QColor(WaitTreeColors[5][color_index]); - case Kernel::ThreadWaitReasonForDebugging::Synchronization: - case Kernel::ThreadWaitReasonForDebugging::ConditionVar: - case Kernel::ThreadWaitReasonForDebugging::Arbitration: - case Kernel::ThreadWaitReasonForDebugging::Suspended: - return QColor(WaitTreeColors[6][color_index]); - break; - default: - return QColor(WaitTreeColors[3][color_index]); - } - case Kernel::ThreadState::Initialized: - return QColor(WaitTreeColors[7][color_index]); - case Kernel::ThreadState::Terminated: - return QColor(WaitTreeColors[8][color_index]); - default: - return WaitTreeItem::GetColor(); - } -} - -std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeThread::GetChildren() const { - std::vector<std::unique_ptr<WaitTreeItem>> list(WaitTreeSynchronizationObject::GetChildren()); - - const auto& thread = static_cast<const Kernel::KThread&>(object); - - QString processor; - switch (thread.GetActiveCore()) { - case Kernel::Svc::IdealCoreUseProcessValue: - processor = tr("ideal"); - break; - default: - processor = tr("core %1").arg(thread.GetActiveCore()); - break; - } - - list.push_back(std::make_unique<WaitTreeText>(tr("processor = %1").arg(processor))); - list.push_back(std::make_unique<WaitTreeText>( - tr("affinity mask = %1").arg(thread.GetAffinityMask().GetAffinityMask()))); - list.push_back(std::make_unique<WaitTreeText>(tr("thread id = %1").arg(thread.GetThreadId()))); - list.push_back(std::make_unique<WaitTreeText>(tr("priority = %1(current) / %2(normal)") - .arg(thread.GetPriority()) - .arg(thread.GetBasePriority()))); - list.push_back(std::make_unique<WaitTreeText>( - tr("last running ticks = %1").arg(thread.GetLastScheduledTick()))); - - list.push_back(std::make_unique<WaitTreeCallstack>(thread, system)); - - return list; -} - -WaitTreeEvent::WaitTreeEvent(const Kernel::KReadableEvent& object_, Core::System& system_) - : WaitTreeSynchronizationObject(object_, system_) {} -WaitTreeEvent::~WaitTreeEvent() = default; - -WaitTreeThreadList::WaitTreeThreadList(std::vector<Kernel::KThread*>&& list, Core::System& system_) - : thread_list(std::move(list)), system{system_} {} -WaitTreeThreadList::~WaitTreeThreadList() = default; - -QString WaitTreeThreadList::GetText() const { - return tr("waited by thread"); -} - -std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeThreadList::GetChildren() const { - std::vector<std::unique_ptr<WaitTreeItem>> list(thread_list.size()); - std::transform(thread_list.begin(), thread_list.end(), list.begin(), - [this](const auto& t) { return std::make_unique<WaitTreeThread>(*t, system); }); - return list; -} - -WaitTreeModel::WaitTreeModel(Core::System& system_, QObject* parent) - : QAbstractItemModel(parent), system{system_} {} -WaitTreeModel::~WaitTreeModel() = default; - -QModelIndex WaitTreeModel::index(int row, int column, const QModelIndex& parent) const { - if (!hasIndex(row, column, parent)) - return {}; - - if (parent.isValid()) { - WaitTreeItem* parent_item = static_cast<WaitTreeItem*>(parent.internalPointer()); - parent_item->Expand(); - return createIndex(row, column, parent_item->Children()[row].get()); - } - - return createIndex(row, column, thread_items[row].get()); -} - -QModelIndex WaitTreeModel::parent(const QModelIndex& index) const { - if (!index.isValid()) - return {}; - - WaitTreeItem* parent_item = static_cast<WaitTreeItem*>(index.internalPointer())->Parent(); - if (!parent_item) { - return QModelIndex(); - } - return createIndex(static_cast<int>(parent_item->Row()), 0, parent_item); -} - -int WaitTreeModel::rowCount(const QModelIndex& parent) const { - if (!parent.isValid()) - return static_cast<int>(thread_items.size()); - - WaitTreeItem* parent_item = static_cast<WaitTreeItem*>(parent.internalPointer()); - parent_item->Expand(); - return static_cast<int>(parent_item->Children().size()); -} - -int WaitTreeModel::columnCount(const QModelIndex&) const { - return 1; -} - -QVariant WaitTreeModel::data(const QModelIndex& index, int role) const { - if (!index.isValid()) - return {}; - - switch (role) { - case Qt::DisplayRole: - return static_cast<WaitTreeItem*>(index.internalPointer())->GetText(); - case Qt::ForegroundRole: - return static_cast<WaitTreeItem*>(index.internalPointer())->GetColor(); - default: - return {}; - } -} - -void WaitTreeModel::ClearItems() { - thread_items.clear(); -} - -void WaitTreeModel::InitItems() { - thread_items = WaitTreeItem::MakeThreadItemList(system); -} - -WaitTreeWidget::WaitTreeWidget(Core::System& system_, QWidget* parent) - : QDockWidget(tr("&Wait Tree"), parent), system{system_} { - setObjectName(QStringLiteral("WaitTreeWidget")); - view = new QTreeView(this); - view->setHeaderHidden(true); - setWidget(view); - setEnabled(false); -} - -WaitTreeWidget::~WaitTreeWidget() = default; - -void WaitTreeWidget::OnDebugModeEntered() { - if (!system.IsPoweredOn()) - return; - model->InitItems(); - view->setModel(model); - setEnabled(true); -} - -void WaitTreeWidget::OnDebugModeLeft() { - setEnabled(false); - view->setModel(nullptr); - model->ClearItems(); -} - -void WaitTreeWidget::OnEmulationStarting(EmuThread* emu_thread) { - model = new WaitTreeModel(system, this); - view->setModel(model); - setEnabled(false); -} - -void WaitTreeWidget::OnEmulationStopping() { - view->setModel(nullptr); - delete model; - setEnabled(false); -} diff --git a/src/yuzu/debugger/wait_tree.h b/src/yuzu/debugger/wait_tree.h deleted file mode 100644 index 23c329fbe..000000000 --- a/src/yuzu/debugger/wait_tree.h +++ /dev/null @@ -1,188 +0,0 @@ -// SPDX-FileCopyrightText: 2016 Citra Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include <cstddef> -#include <memory> -#include <vector> - -#include <QDockWidget> -#include <QTreeView> - -#include "common/common_types.h" -#include "core/hle/kernel/k_auto_object.h" -#include "core/hle/kernel/svc_common.h" - -class EmuThread; - -namespace Core { -class System; -} - -namespace Kernel { -class KHandleTable; -class KReadableEvent; -class KSynchronizationObject; -class KThread; -} // namespace Kernel - -class WaitTreeThread; - -class WaitTreeItem : public QObject { - Q_OBJECT -public: - WaitTreeItem(); - ~WaitTreeItem() override; - - virtual bool IsExpandable() const; - virtual std::vector<std::unique_ptr<WaitTreeItem>> GetChildren() const; - virtual QString GetText() const = 0; - virtual QColor GetColor() const; - - void Expand(); - WaitTreeItem* Parent() const; - const std::vector<std::unique_ptr<WaitTreeItem>>& Children() const; - std::size_t Row() const; - static std::vector<std::unique_ptr<WaitTreeThread>> MakeThreadItemList(Core::System& system); - -private: - std::size_t row; - bool expanded = false; - WaitTreeItem* parent = nullptr; - std::vector<std::unique_ptr<WaitTreeItem>> children; -}; - -class WaitTreeText : public WaitTreeItem { - Q_OBJECT -public: - explicit WaitTreeText(QString text); - ~WaitTreeText() override; - - QString GetText() const override; - -private: - QString text; -}; - -class WaitTreeExpandableItem : public WaitTreeItem { - Q_OBJECT -public: - WaitTreeExpandableItem(); - ~WaitTreeExpandableItem() override; - - bool IsExpandable() const override; -}; - -class WaitTreeCallstack : public WaitTreeExpandableItem { - Q_OBJECT -public: - explicit WaitTreeCallstack(const Kernel::KThread& thread_, Core::System& system_); - ~WaitTreeCallstack() override; - - QString GetText() const override; - std::vector<std::unique_ptr<WaitTreeItem>> GetChildren() const override; - -private: - const Kernel::KThread& thread; - - Core::System& system; -}; - -class WaitTreeSynchronizationObject : public WaitTreeExpandableItem { - Q_OBJECT -public: - explicit WaitTreeSynchronizationObject(const Kernel::KSynchronizationObject& object_, - Core::System& system_); - ~WaitTreeSynchronizationObject() override; - - static std::unique_ptr<WaitTreeSynchronizationObject> make( - const Kernel::KSynchronizationObject& object, Core::System& system); - QString GetText() const override; - std::vector<std::unique_ptr<WaitTreeItem>> GetChildren() const override; - -protected: - const Kernel::KSynchronizationObject& object; - -private: - Core::System& system; -}; - -class WaitTreeThread : public WaitTreeSynchronizationObject { - Q_OBJECT -public: - explicit WaitTreeThread(const Kernel::KThread& thread, Core::System& system_); - ~WaitTreeThread() override; - - QString GetText() const override; - QColor GetColor() const override; - std::vector<std::unique_ptr<WaitTreeItem>> GetChildren() const override; - -private: - Core::System& system; -}; - -class WaitTreeEvent : public WaitTreeSynchronizationObject { - Q_OBJECT -public: - explicit WaitTreeEvent(const Kernel::KReadableEvent& object_, Core::System& system_); - ~WaitTreeEvent() override; -}; - -class WaitTreeThreadList : public WaitTreeExpandableItem { - Q_OBJECT -public: - explicit WaitTreeThreadList(std::vector<Kernel::KThread*>&& list, Core::System& system_); - ~WaitTreeThreadList() override; - - QString GetText() const override; - std::vector<std::unique_ptr<WaitTreeItem>> GetChildren() const override; - -private: - std::vector<Kernel::KThread*> thread_list; - - Core::System& system; -}; - -class WaitTreeModel : public QAbstractItemModel { - Q_OBJECT - -public: - explicit WaitTreeModel(Core::System& system_, QObject* parent = nullptr); - ~WaitTreeModel() override; - - QVariant data(const QModelIndex& index, int role) const override; - QModelIndex index(int row, int column, const QModelIndex& parent) const override; - QModelIndex parent(const QModelIndex& index) const override; - int rowCount(const QModelIndex& parent) const override; - int columnCount(const QModelIndex& parent) const override; - - void ClearItems(); - void InitItems(); - -private: - std::vector<std::unique_ptr<WaitTreeThread>> thread_items; - - Core::System& system; -}; - -class WaitTreeWidget : public QDockWidget { - Q_OBJECT - -public: - explicit WaitTreeWidget(Core::System& system_, QWidget* parent = nullptr); - ~WaitTreeWidget() override; - -public slots: - void OnDebugModeEntered(); - void OnDebugModeLeft(); - - void OnEmulationStarting(EmuThread* emu_thread); - void OnEmulationStopping(); - -private: - QTreeView* view; - WaitTreeModel* model; - - Core::System& system; -}; |