Miscallenious fixes to gl backend and qt frontend (#6834)

* renderer_gl: Make rasterizer normal class member

* It doesn't need to be heap allocated anymore

* gl_rasterizer: Remove default_texture

* It's unused

* gl_rasterizer: General cleanup

* gl_rasterizer: Lower case lambdas

* Match style with review comments from vulkan backend

* rasterizer_cache: Prevent memory leak

* Since the switch from shared_ptr these surfaces were no longer being destroyed properly. Use our garbage collector for that purpose to destroy it safely for both backends

* rasterizer_cache: Make temp copy of old surface

* The custom surface would override the memory region of the old region resulting in garbage data, this ensures the custom surface is constructed correctly

* citra_qt: Manually create dialog tabs

* Allows for custom constructors which is very useful. While at it, global state is now eliminated from configuration

* citra_qt: Eliminate global system usage

* core: Remove global system usage in memory and HIO

* citra_qt: Use qOverload

* tests: Run clang format

* gl_texture_runtime: Fix surface scaling
This commit is contained in:
GPUCode 2023-08-02 01:40:39 +03:00 committed by GitHub
parent 970f2284d8
commit 88ea66053e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
73 changed files with 594 additions and 555 deletions

View file

@ -16,7 +16,6 @@
#include "citra_qt/debugger/graphics/graphics_cmdlists.h"
#include "citra_qt/util/util.h"
#include "common/vector_math.h"
#include "core/core.h"
#include "core/memory.h"
#include "video_core/debug_utils/debug_utils.h"
#include "video_core/pica_state.h"
@ -167,8 +166,7 @@ void GPUCommandListWidget::SetCommandInfo(const QModelIndex& index) {
const auto format = texture.format;
const auto info = Pica::Texture::TextureInfo::FromPicaRegister(config, format);
const u8* src =
Core::System::GetInstance().Memory().GetPhysicalPointer(config.GetPhysicalAddress());
const u8* src = memory.GetPhysicalPointer(config.GetPhysicalAddress());
new_info_widget = new TextureInfoWidget(src, info);
}
if (command_info_widget) {
@ -182,8 +180,8 @@ void GPUCommandListWidget::SetCommandInfo(const QModelIndex& index) {
}
#undef COMMAND_IN_RANGE
GPUCommandListWidget::GPUCommandListWidget(QWidget* parent)
: QDockWidget(tr("Pica Command List"), parent) {
GPUCommandListWidget::GPUCommandListWidget(Memory::MemorySystem& memory_, QWidget* parent)
: QDockWidget(tr("Pica Command List"), parent), memory{memory_} {
setObjectName(QStringLiteral("Pica Command List"));
GPUCommandListModel* model = new GPUCommandListModel(this);

View file

@ -7,11 +7,14 @@
#include <QAbstractListModel>
#include <QDockWidget>
#include "video_core/debug_utils/debug_utils.h"
#include "video_core/gpu_debugger.h"
class QPushButton;
class QTreeView;
namespace Memory {
class MemorySystem;
}
class GPUCommandListModel : public QAbstractListModel {
Q_OBJECT
@ -39,7 +42,7 @@ class GPUCommandListWidget : public QDockWidget {
Q_OBJECT
public:
explicit GPUCommandListWidget(QWidget* parent = nullptr);
explicit GPUCommandListWidget(Memory::MemorySystem& memory, QWidget* parent = nullptr);
public slots:
void OnToggleTracing();
@ -54,7 +57,7 @@ signals:
private:
std::unique_ptr<Pica::DebugUtils::PicaTrace> pica_trace;
Memory::MemorySystem& memory;
QTreeView* list_widget;
QWidget* command_info_widget;
QPushButton* toggle_tracing;

View file

@ -15,8 +15,6 @@
#include "citra_qt/debugger/graphics/graphics_surface.h"
#include "citra_qt/util/spinbox.h"
#include "common/color.h"
#include "core/core.h"
#include "core/hw/gpu.h"
#include "core/memory.h"
#include "video_core/pica_state.h"
#include "video_core/regs_framebuffer.h"
@ -51,9 +49,10 @@ void SurfacePicture::mouseMoveEvent(QMouseEvent* event) {
mousePressEvent(event);
}
GraphicsSurfaceWidget::GraphicsSurfaceWidget(std::shared_ptr<Pica::DebugContext> debug_context,
GraphicsSurfaceWidget::GraphicsSurfaceWidget(Memory::MemorySystem& memory_,
std::shared_ptr<Pica::DebugContext> debug_context,
QWidget* parent)
: BreakPointObserverDock(debug_context, tr("Pica Surface Viewer"), parent),
: BreakPointObserverDock(debug_context, tr("Pica Surface Viewer"), parent), memory{memory_},
surface_source(Source::ColorBuffer) {
setObjectName(QStringLiteral("PicaSurface"));
@ -290,57 +289,57 @@ void GraphicsSurfaceWidget::Pick(int x, int y) {
return;
}
u8* buffer = Core::System::GetInstance().Memory().GetPhysicalPointer(surface_address);
if (buffer == nullptr) {
const u8* buffer = memory.GetPhysicalPointer(surface_address);
if (!buffer) {
surface_info_label->setText(tr("(unable to access pixel data)"));
surface_info_label->setAlignment(Qt::AlignCenter);
return;
}
unsigned nibbles_per_pixel = GraphicsSurfaceWidget::NibblesPerPixel(surface_format);
unsigned stride = nibbles_per_pixel * surface_width / 2;
unsigned bytes_per_pixel;
bool nibble_mode = (nibbles_per_pixel == 1);
if (nibble_mode) {
// As nibbles are contained in a byte we still need to access one byte per nibble
bytes_per_pixel = 1;
} else {
bytes_per_pixel = nibbles_per_pixel / 2;
}
const u32 nibbles_per_pixel = GraphicsSurfaceWidget::NibblesPerPixel(surface_format);
const u32 stride = nibbles_per_pixel * surface_width / 2;
const bool nibble_mode = (nibbles_per_pixel == 1);
const u32 bytes_per_pixel = [&] {
if (nibble_mode) {
// As nibbles are contained in a byte we still need to access one byte per nibble
return 1u;
} else {
return nibbles_per_pixel / 2;
}
}();
const u32 coarse_y = y & ~7;
u32 offset = VideoCore::GetMortonOffset(x, y, bytes_per_pixel) + coarse_y * stride;
const u32 offset = VideoCore::GetMortonOffset(x, y, bytes_per_pixel) + coarse_y * stride;
const u8* pixel = buffer + (nibble_mode ? (offset / 2) : offset);
auto GetText = [offset](Format format, const u8* pixel) {
const auto get_text = [offset](Format format, const u8* pixel) {
switch (format) {
case Format::RGBA8: {
auto value = Common::Color::DecodeRGBA8(pixel) / 255.0f;
const auto value = Common::Color::DecodeRGBA8(pixel) / 255.0f;
return QStringLiteral("Red: %1, Green: %2, Blue: %3, Alpha: %4")
.arg(QString::number(value.r(), 'f', 2), QString::number(value.g(), 'f', 2),
QString::number(value.b(), 'f', 2), QString::number(value.a(), 'f', 2));
}
case Format::RGB8: {
auto value = Common::Color::DecodeRGB8(pixel) / 255.0f;
const auto value = Common::Color::DecodeRGB8(pixel) / 255.0f;
return QStringLiteral("Red: %1, Green: %2, Blue: %3")
.arg(QString::number(value.r(), 'f', 2), QString::number(value.g(), 'f', 2),
QString::number(value.b(), 'f', 2));
}
case Format::RGB5A1: {
auto value = Common::Color::DecodeRGB5A1(pixel) / 255.0f;
const auto value = Common::Color::DecodeRGB5A1(pixel) / 255.0f;
return QStringLiteral("Red: %1, Green: %2, Blue: %3, Alpha: %4")
.arg(QString::number(value.r(), 'f', 2), QString::number(value.g(), 'f', 2),
QString::number(value.b(), 'f', 2), QString::number(value.a(), 'f', 2));
}
case Format::RGB565: {
auto value = Common::Color::DecodeRGB565(pixel) / 255.0f;
const auto value = Common::Color::DecodeRGB565(pixel) / 255.0f;
return QStringLiteral("Red: %1, Green: %2, Blue: %3")
.arg(QString::number(value.r(), 'f', 2), QString::number(value.g(), 'f', 2),
QString::number(value.b(), 'f', 2));
}
case Format::RGBA4: {
auto value = Common::Color::DecodeRGBA4(pixel) / 255.0f;
const auto value = Common::Color::DecodeRGBA4(pixel) / 255.0f;
return QStringLiteral("Red: %1, Green: %2, Blue: %3, Alpha: %4")
.arg(QString::number(value.r(), 'f', 2), QString::number(value.g(), 'f', 2),
QString::number(value.b(), 'f', 2), QString::number(value.a(), 'f', 2));
@ -348,7 +347,7 @@ void GraphicsSurfaceWidget::Pick(int x, int y) {
case Format::IA8:
return QStringLiteral("Index: %1, Alpha: %2").arg(pixel[0], pixel[1]);
case Format::RG8: {
auto value = Common::Color::DecodeRG8(pixel) / 255.0f;
const auto value = Common::Color::DecodeRG8(pixel) / 255.0f;
return QStringLiteral("Red: %1, Green: %2")
.arg(QString::number(value.r(), 'f', 2), QString::number(value.g(), 'f', 2));
}
@ -359,11 +358,11 @@ void GraphicsSurfaceWidget::Pick(int x, int y) {
case Format::IA4:
return QStringLiteral("Index: %1, Alpha: %2").arg(*pixel & 0xF, (*pixel & 0xF0) >> 4);
case Format::I4: {
u8 i = (*pixel >> ((offset % 2) ? 4 : 0)) & 0xF;
const u8 i = (*pixel >> ((offset % 2) ? 4 : 0)) & 0xF;
return QStringLiteral("Index: %1").arg(i);
}
case Format::A4: {
u8 a = (*pixel >> ((offset % 2) ? 4 : 0)) & 0xF;
const u8 a = (*pixel >> ((offset % 2) ? 4 : 0)) & 0xF;
return QStringLiteral("Alpha: %1").arg(QString::number(a / 15.0f, 'f', 2));
}
case Format::ETC1:
@ -371,17 +370,17 @@ void GraphicsSurfaceWidget::Pick(int x, int y) {
// TODO: Display block information or channel values?
return QStringLiteral("Compressed data");
case Format::D16: {
auto value = Common::Color::DecodeD16(pixel);
const auto value = Common::Color::DecodeD16(pixel);
return QStringLiteral("Depth: %1").arg(QString::number(value / (float)0xFFFF, 'f', 4));
}
case Format::D24: {
auto value = Common::Color::DecodeD24(pixel);
const auto value = Common::Color::DecodeD24(pixel);
return QStringLiteral("Depth: %1")
.arg(QString::number(value / (float)0xFFFFFF, 'f', 4));
}
case Format::D24X8:
case Format::X24S8: {
auto values = Common::Color::DecodeD24S8(pixel);
const auto values = Common::Color::DecodeD24S8(pixel);
return QStringLiteral("Depth: %1, Stencil: %2")
.arg(QString::number(values[0] / (float)0xFFFFFF, 'f', 4), values[1]);
}
@ -398,13 +397,13 @@ void GraphicsSurfaceWidget::Pick(int x, int y) {
if (nibble_mode) {
nibble_index += (offset % 2) ? 0 : 1;
}
u8 byte = pixel[nibble_index / 2];
u8 nibble = (byte >> ((nibble_index % 2) ? 0 : 4)) & 0xF;
const u8 byte = pixel[nibble_index / 2];
const u8 nibble = (byte >> ((nibble_index % 2) ? 0 : 4)) & 0xF;
nibbles.append(QString::number(nibble, 16).toUpper());
}
surface_info_label->setText(
QStringLiteral("Raw: 0x%3\n(%4)").arg(nibbles, GetText(surface_format, pixel)));
QStringLiteral("Raw: 0x%3\n(%4)").arg(nibbles, get_text(surface_format, pixel)));
surface_info_label->setAlignment(Qt::AlignLeft | Qt::AlignVCenter);
}
@ -546,9 +545,9 @@ void GraphicsSurfaceWidget::OnUpdate() {
// TODO: Implement a good way to visualize alpha components!
QImage decoded_image(surface_width, surface_height, QImage::Format_ARGB32);
u8* buffer = Core::System::GetInstance().Memory().GetPhysicalPointer(surface_address);
const u8* buffer = memory.GetPhysicalPointer(surface_address);
if (buffer == nullptr) {
if (!buffer) {
surface_picture_label->hide();
surface_info_label->setText(tr("(invalid surface address)"));
surface_info_label->setAlignment(Qt::AlignCenter);
@ -682,9 +681,8 @@ void GraphicsSurfaceWidget::SaveSurface() {
tr("Failed to save surface data to file '%1'").arg(filename));
}
} else if (selected_filter == bin_filter) {
const u8* const buffer =
Core::System::GetInstance().Memory().GetPhysicalPointer(surface_address);
ASSERT_MSG(buffer != nullptr, "Memory not accessible");
const u8* const buffer = memory.GetPhysicalPointer(surface_address);
ASSERT_MSG(buffer, "Memory not accessible");
QFile file{filename};
if (!file.open(QIODevice::WriteOnly)) {

View file

@ -14,6 +14,10 @@ class CSpinBox;
class GraphicsSurfaceWidget;
namespace Memory {
class MemorySystem;
}
class SurfacePicture : public QLabel {
Q_OBJECT
@ -72,7 +76,8 @@ class GraphicsSurfaceWidget : public BreakPointObserverDock {
static unsigned int NibblesPerPixel(Format format);
public:
explicit GraphicsSurfaceWidget(std::shared_ptr<Pica::DebugContext> debug_context,
explicit GraphicsSurfaceWidget(Memory::MemorySystem& memory,
std::shared_ptr<Pica::DebugContext> debug_context,
QWidget* parent = nullptr);
void Pick(int x, int y);
@ -95,6 +100,7 @@ private:
void SaveSurface();
Memory::MemorySystem& memory;
QComboBox* surface_source_list;
CSpinBox* surface_address_control;
QSpinBox* surface_width_control;

View file

@ -16,13 +16,13 @@
#include "core/hle/service/sm/sm.h"
#include "ui_recorder.h"
IPCRecorderWidget::IPCRecorderWidget(QWidget* parent)
: QDockWidget(parent), ui(std::make_unique<Ui::IPCRecorder>()) {
IPCRecorderWidget::IPCRecorderWidget(Core::System& system_, QWidget* parent)
: QDockWidget(parent), ui(std::make_unique<Ui::IPCRecorder>()), system{system_} {
ui->setupUi(this);
qRegisterMetaType<IPCDebugger::RequestRecord>();
connect(ui->enabled, &QCheckBox::stateChanged,
connect(ui->enabled, &QCheckBox::stateChanged, this,
[this](int new_state) { SetEnabled(new_state == Qt::Checked); });
connect(ui->clearButton, &QPushButton::clicked, this, &IPCRecorderWidget::Clear);
connect(ui->filter, &QLineEdit::textChanged, this, &IPCRecorderWidget::ApplyFilterToAll);
@ -90,7 +90,7 @@ void IPCRecorderWidget::OnEntryUpdated(IPCDebugger::RequestRecord record) {
(record.status == IPCDebugger::RequestStatus::Handled &&
record.translated_reply_cmdbuf[1] != RESULT_SUCCESS.raw)) { // Unimplemented / Error
auto* item = ui->main->invisibleRootItem()->child(row_id);
auto item = ui->main->invisibleRootItem()->child(row_id);
for (int column = 0; column < item->columnCount(); ++column) {
item->setBackground(column, QBrush(QColor::fromRgb(255, 0, 0)));
}
@ -100,11 +100,11 @@ void IPCRecorderWidget::OnEntryUpdated(IPCDebugger::RequestRecord record) {
}
void IPCRecorderWidget::SetEnabled(bool enabled) {
if (!Core::System::GetInstance().IsPoweredOn()) {
if (!system.IsPoweredOn()) {
return;
}
auto& ipc_recorder = Core::System::GetInstance().Kernel().GetIPCRecorder();
auto& ipc_recorder = system.Kernel().GetIPCRecorder();
ipc_recorder.SetEnabled(enabled);
if (enabled) {
@ -123,10 +123,10 @@ void IPCRecorderWidget::Clear() {
}
QString IPCRecorderWidget::GetServiceName(const IPCDebugger::RequestRecord& record) const {
if (Core::System::GetInstance().IsPoweredOn() && record.client_port.id != -1) {
const auto service_name =
Core::System::GetInstance().ServiceManager().GetServiceNameByPortId(
static_cast<u32>(record.client_port.id));
if (system.IsPoweredOn() && record.client_port.id != -1) {
const Service::SM::ServiceManager& sm = system.ServiceManager();
const u32 port_id = static_cast<u32>(record.client_port.id);
const auto service_name = sm.GetServiceNameByPortId(port_id);
if (!service_name.empty()) {
return QString::fromStdString(service_name);

View file

@ -14,11 +14,15 @@ namespace Ui {
class IPCRecorder;
}
namespace Core {
class System;
}
class IPCRecorderWidget : public QDockWidget {
Q_OBJECT
public:
explicit IPCRecorderWidget(QWidget* parent = nullptr);
explicit IPCRecorderWidget(Core::System& system, QWidget* parent = nullptr);
~IPCRecorderWidget();
void OnEmulationStarting();
@ -37,9 +41,10 @@ private:
QString GetFunctionName(const IPCDebugger::RequestRecord& record) const;
void OpenRecordDialog(QTreeWidgetItem* item, int column);
private:
std::unique_ptr<Ui::IPCRecorder> ui;
IPCDebugger::CallbackHandle handle;
Core::System& system;
// The offset between record id and row id, assuming record ids are assigned
// continuously and only the 'Clear' action can be performed, this is enough.
// The initial value is 1, which means record 1 = row 0.

View file

@ -9,8 +9,8 @@
#include "core/core.h"
#include "ui_registers.h"
RegistersWidget::RegistersWidget(QWidget* parent)
: QDockWidget(parent), cpu_regs_ui(std::make_unique<Ui::ARMRegisters>()) {
RegistersWidget::RegistersWidget(const Core::System& system_, QWidget* parent)
: QDockWidget(parent), cpu_regs_ui(std::make_unique<Ui::ARMRegisters>()), system{system_} {
cpu_regs_ui->setupUi(this);
tree = cpu_regs_ui->treeWidget;
@ -62,17 +62,21 @@ RegistersWidget::RegistersWidget(QWidget* parent)
RegistersWidget::~RegistersWidget() = default;
void RegistersWidget::OnDebugModeEntered() {
if (!Core::System::GetInstance().IsPoweredOn())
if (!system.IsPoweredOn()) {
return;
}
// Todo: Handle all cores
for (int i = 0; i < core_registers->childCount(); ++i)
// TODO: Handle all cores
const ARM_Interface& core = system.GetCore(0);
for (int i = 0; i < core_registers->childCount(); ++i) {
core_registers->child(i)->setText(
1, QStringLiteral("0x%1").arg(Core::GetCore(0).GetReg(i), 8, 16, QLatin1Char('0')));
1, QStringLiteral("0x%1").arg(core.GetReg(i), 8, 16, QLatin1Char('0')));
}
for (int i = 0; i < vfp_registers->childCount(); ++i)
for (int i = 0; i < vfp_registers->childCount(); ++i) {
vfp_registers->child(i)->setText(
1, QStringLiteral("0x%1").arg(Core::GetCore(0).GetVFPReg(i), 8, 16, QLatin1Char('0')));
1, QStringLiteral("0x%1").arg(core.GetVFPReg(i), 8, 16, QLatin1Char('0')));
}
UpdateCPSRValues();
UpdateVFPSystemRegisterValues();
@ -86,24 +90,29 @@ void RegistersWidget::OnEmulationStarting(EmuThread* emu_thread) {
void RegistersWidget::OnEmulationStopping() {
// Reset widget text
for (int i = 0; i < core_registers->childCount(); ++i)
for (int i = 0; i < core_registers->childCount(); ++i) {
core_registers->child(i)->setText(1, QString{});
}
for (int i = 0; i < vfp_registers->childCount(); ++i)
for (int i = 0; i < vfp_registers->childCount(); ++i) {
vfp_registers->child(i)->setText(1, QString{});
}
for (int i = 0; i < cpsr->childCount(); ++i)
for (int i = 0; i < cpsr->childCount(); ++i) {
cpsr->child(i)->setText(1, QString{});
}
cpsr->setText(1, QString{});
// FPSCR
for (int i = 0; i < vfp_system_registers->child(0)->childCount(); ++i)
for (int i = 0; i < vfp_system_registers->child(0)->childCount(); ++i) {
vfp_system_registers->child(0)->child(i)->setText(1, QString{});
}
// FPEXC
for (int i = 0; i < vfp_system_registers->child(1)->childCount(); ++i)
for (int i = 0; i < vfp_system_registers->child(1)->childCount(); ++i) {
vfp_system_registers->child(1)->child(i)->setText(1, QString{});
}
vfp_system_registers->child(0)->setText(1, QString{});
vfp_system_registers->child(1)->setText(1, QString{});
@ -130,8 +139,8 @@ void RegistersWidget::CreateCPSRChildren() {
}
void RegistersWidget::UpdateCPSRValues() {
// Todo: Handle all cores
const u32 cpsr_val = Core::GetCore(0).GetCPSR();
// TODO: Handle all cores
const u32 cpsr_val = system.GetCore(0).GetCPSR();
cpsr->setText(1, QStringLiteral("0x%1").arg(cpsr_val, 8, 16, QLatin1Char('0')));
cpsr->child(0)->setText(
@ -193,9 +202,10 @@ void RegistersWidget::CreateVFPSystemRegisterChildren() {
}
void RegistersWidget::UpdateVFPSystemRegisterValues() {
// Todo: handle all cores
const u32 fpscr_val = Core::GetCore(0).GetVFPSystemReg(VFP_FPSCR);
const u32 fpexc_val = Core::GetCore(0).GetVFPSystemReg(VFP_FPEXC);
// TODO: handle all cores
const ARM_Interface& core = system.GetCore(0);
const u32 fpscr_val = core.GetVFPSystemReg(VFP_FPSCR);
const u32 fpexc_val = core.GetVFPSystemReg(VFP_FPEXC);
QTreeWidgetItem* const fpscr = vfp_system_registers->child(0);
fpscr->setText(1, QStringLiteral("0x%1").arg(fpscr_val, 8, 16, QLatin1Char('0')));

View file

@ -15,11 +15,15 @@ namespace Ui {
class ARMRegisters;
}
namespace Core {
class System;
}
class RegistersWidget : public QDockWidget {
Q_OBJECT
public:
explicit RegistersWidget(QWidget* parent = nullptr);
explicit RegistersWidget(const Core::System& system, QWidget* parent = nullptr);
~RegistersWidget();
public slots:
@ -37,7 +41,7 @@ private:
void UpdateVFPSystemRegisterValues();
std::unique_ptr<Ui::ARMRegisters> cpu_regs_ui;
const Core::System& system;
QTreeWidget* tree;
QTreeWidgetItem* core_registers;

View file

@ -75,13 +75,13 @@ std::size_t WaitTreeItem::Row() const {
return row;
}
std::vector<std::unique_ptr<WaitTreeThread>> WaitTreeItem::MakeThreadItemList() {
const u32 num_cores = Core::GetNumCores();
std::vector<std::unique_ptr<WaitTreeThread>> WaitTreeItem::MakeThreadItemList(
Core::System& system) {
const u32 num_cores = system.GetNumCores();
std::vector<std::unique_ptr<WaitTreeThread>> item_list;
item_list.reserve(num_cores);
for (u32 i = 0; i < num_cores; ++i) {
const auto& threads =
Core::System::GetInstance().Kernel().GetThreadManager(i).GetThreadList();
const auto threads = system.Kernel().GetThreadManager(i).GetThreadList();
item_list.reserve(item_list.size() + threads.size());
for (std::size_t j = 0; j < threads.size(); ++j) {
item_list.push_back(std::make_unique<WaitTreeThread>(*threads[j]));
@ -435,11 +435,12 @@ void WaitTreeModel::ClearItems() {
thread_items.clear();
}
void WaitTreeModel::InitItems() {
thread_items = WaitTreeItem::MakeThreadItemList();
void WaitTreeModel::InitItems(Core::System& system) {
thread_items = WaitTreeItem::MakeThreadItemList(system);
}
WaitTreeWidget::WaitTreeWidget(QWidget* parent) : QDockWidget(tr("Wait Tree"), parent) {
WaitTreeWidget::WaitTreeWidget(Core::System& system_, QWidget* parent)
: QDockWidget(tr("Wait Tree"), parent), system{system_} {
setObjectName(QStringLiteral("WaitTreeWidget"));
view = new QTreeView(this);
view->setHeaderHidden(true);
@ -448,9 +449,10 @@ WaitTreeWidget::WaitTreeWidget(QWidget* parent) : QDockWidget(tr("Wait Tree"), p
}
void WaitTreeWidget::OnDebugModeEntered() {
if (!Core::System::GetInstance().IsPoweredOn())
if (!system.IsPoweredOn()) {
return;
model->InitItems();
}
model->InitItems(system);
view->setModel(model);
setEnabled(true);
}

View file

@ -23,6 +23,10 @@ class Thread;
class Timer;
} // namespace Kernel
namespace Core {
class System;
}
class WaitTreeThread;
class WaitTreeItem : public QObject {
@ -39,7 +43,7 @@ public:
WaitTreeItem* Parent() const;
std::span<const std::unique_ptr<WaitTreeItem>> Children() const;
std::size_t Row() const;
static std::vector<std::unique_ptr<WaitTreeThread>> MakeThreadItemList();
static std::vector<std::unique_ptr<WaitTreeThread>> MakeThreadItemList(Core::System& system);
private:
std::size_t row;
@ -166,7 +170,7 @@ public:
int columnCount(const QModelIndex& parent) const override;
void ClearItems();
void InitItems();
void InitItems(Core::System& system);
private:
std::vector<std::unique_ptr<WaitTreeThread>> thread_items;
@ -176,7 +180,7 @@ class WaitTreeWidget : public QDockWidget {
Q_OBJECT
public:
explicit WaitTreeWidget(QWidget* parent = nullptr);
explicit WaitTreeWidget(Core::System& system, QWidget* parent = nullptr);
public slots:
void OnDebugModeEntered();
@ -188,4 +192,5 @@ public slots:
private:
QTreeView* view;
WaitTreeModel* model;
Core::System& system;
};