diff --git a/Source/Core/DolphinQt/Debugger/MemoryViewWidget.cpp b/Source/Core/DolphinQt/Debugger/MemoryViewWidget.cpp index abe179e96e..9928632273 100644 --- a/Source/Core/DolphinQt/Debugger/MemoryViewWidget.cpp +++ b/Source/Core/DolphinQt/Debugger/MemoryViewWidget.cpp @@ -311,7 +311,12 @@ constexpr int GetCharacterCount(MemoryViewWidget::Type type) void MemoryViewWidget::UpdateDispatcher(UpdateType type) { - if (!isVisible()) + std::unique_lock lock(m_updating, std::defer_lock); + + // A full update may change parameters like row count, so make sure it goes through. + if (type == UpdateType::Full) + lock.lock(); + else if (!isVisible() || !lock.try_lock()) return; // Check if table needs to be created. @@ -331,6 +336,10 @@ void MemoryViewWidget::UpdateDispatcher(UpdateType type) GetValues(); UpdateColumns(); break; + case UpdateType::Auto: + // Values were captured on CPU thread while doing a callback. + if (m_values.size() != 0) + UpdateColumns(); default: break; } @@ -522,6 +531,18 @@ void MemoryViewWidget::UpdateColumns() } } +// Always runs on CPU thread from a callback. +void MemoryViewWidget::UpdateOnFrameEnd() +{ + std::unique_lock lock(m_updating, std::try_to_lock); + if (lock) + { + GetValues(); + // Should not directly trigger widget updates on a cpu thread. Signal main thread to do it. + emit AutoUpdate(); + } +} + void MemoryViewWidget::GetValues() { m_values.clear(); diff --git a/Source/Core/DolphinQt/Debugger/MemoryViewWidget.h b/Source/Core/DolphinQt/Debugger/MemoryViewWidget.h index 584ce4fd42..a1e2af09ea 100644 --- a/Source/Core/DolphinQt/Debugger/MemoryViewWidget.h +++ b/Source/Core/DolphinQt/Debugger/MemoryViewWidget.h @@ -84,6 +84,7 @@ public: void CreateTable(); void UpdateDispatcher(UpdateType type = UpdateType::Addresses); void Update(); + void UpdateOnFrameEnd(); void GetValues(); void UpdateFont(const QFont& font); void ToggleBreakpoint(u32 addr, bool row); @@ -99,6 +100,7 @@ public: void SetBPLoggingEnabled(bool enabled); signals: + void AutoUpdate(); void ShowCode(u32 address); void RequestWatch(QString name, u32 address); @@ -131,6 +133,7 @@ private: int m_alignment = 16; int m_data_columns; bool m_dual_view = false; + std::mutex m_updating; QColor m_highlight_color = QColor(120, 255, 255, 100); friend class MemoryViewTable; diff --git a/Source/Core/DolphinQt/Debugger/MemoryWidget.cpp b/Source/Core/DolphinQt/Debugger/MemoryWidget.cpp index 200219e0b6..d15a99d6ba 100644 --- a/Source/Core/DolphinQt/Debugger/MemoryWidget.cpp +++ b/Source/Core/DolphinQt/Debugger/MemoryWidget.cpp @@ -340,13 +340,38 @@ void MemoryWidget::ConnectWidgets() void MemoryWidget::closeEvent(QCloseEvent*) { Settings::Instance().SetMemoryVisible(false); + RemoveAfterFrameEventCallback(); } void MemoryWidget::showEvent(QShowEvent* event) { + RegisterAfterFrameEventCallback(); Update(); } +void MemoryWidget::hideEvent(QHideEvent* event) +{ + RemoveAfterFrameEventCallback(); +} + +void MemoryWidget::RegisterAfterFrameEventCallback() +{ + m_vi_end_field_event = VIEndFieldEvent::Register([this] { AutoUpdateTable(); }, "MemoryWidget"); +} + +void MemoryWidget::RemoveAfterFrameEventCallback() +{ + m_vi_end_field_event.reset(); +} + +void MemoryWidget::AutoUpdateTable() +{ + if (!isVisible()) + return; + + m_memory_view->UpdateOnFrameEnd(); +} + void MemoryWidget::Update() { if (!isVisible()) diff --git a/Source/Core/DolphinQt/Debugger/MemoryWidget.h b/Source/Core/DolphinQt/Debugger/MemoryWidget.h index 75fe40d5f8..de5c71e28c 100644 --- a/Source/Core/DolphinQt/Debugger/MemoryWidget.h +++ b/Source/Core/DolphinQt/Debugger/MemoryWidget.h @@ -9,6 +9,7 @@ #include #include "Common/CommonTypes.h" +#include "VideoCommon/VideoEvents.h" class MemoryViewWidget; class QCheckBox; @@ -76,7 +77,11 @@ private: void FindValue(bool next); void closeEvent(QCloseEvent*) override; + void hideEvent(QHideEvent* event) override; void showEvent(QShowEvent* event) override; + void RegisterAfterFrameEventCallback(); + void RemoveAfterFrameEventCallback(); + void AutoUpdateTable(); Core::System& m_system; @@ -109,4 +114,5 @@ private: QRadioButton* m_bp_read_only; QRadioButton* m_bp_write_only; QCheckBox* m_bp_log_check; + Common::EventHook m_vi_end_field_event; };