MemoryViewWidget: Add OnFrameEnd callback to auto-update memory while a game is running.

This commit is contained in:
TryTwo 2024-06-24 14:18:41 -07:00
parent 08b52ce511
commit 9fc417b1d0
4 changed files with 59 additions and 1 deletions

View File

@ -225,6 +225,9 @@ MemoryViewWidget::MemoryViewWidget(Core::System& system, QWidget* parent)
UpdateDisbatcher(UpdateType::Values);
});
// CPU Thread to Main Thread.
connect(this, &MemoryViewWidget::AutoUpdate, this,
[this] { UpdateDisbatcher(UpdateType::Auto); });
connect(&Settings::Instance(), &Settings::ThemeChanged, this,
[this] { UpdateDisbatcher(UpdateType::Full); });
@ -306,7 +309,12 @@ constexpr int GetCharacterCount(MemoryViewWidget::Type type)
void MemoryViewWidget::UpdateDisbatcher(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.
@ -326,6 +334,10 @@ void MemoryViewWidget::UpdateDisbatcher(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;
}
@ -517,6 +529,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();

View File

@ -83,6 +83,7 @@ public:
void CreateTable();
void UpdateDisbatcher(UpdateType type = UpdateType::Addresses);
void Update();
void UpdateOnFrameEnd();
void GetValues();
void UpdateFont(const QFont& font);
void ToggleBreakpoint(u32 addr, bool row);
@ -98,6 +99,7 @@ public:
void SetBPLoggingEnabled(bool enabled);
signals:
void AutoUpdate();
void ShowCode(u32 address);
void RequestWatch(QString name, u32 address);
@ -130,6 +132,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;

View File

@ -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())

View File

@ -9,6 +9,7 @@
#include <QDockWidget>
#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;
};