mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 05:40:04 +00:00 
			
		
		
		
	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:
		
							parent
							
								
									970f2284d8
								
							
						
					
					
						commit
						88ea66053e
					
				
					 73 changed files with 594 additions and 555 deletions
				
			
		|  | @ -157,7 +157,7 @@ static Core::System::ResultStatus RunCitra(const std::string& filepath) { | |||
|     system.RegisterSoftwareKeyboard(std::make_shared<SoftwareKeyboard::AndroidKeyboard>()); | ||||
| 
 | ||||
|     // Register microphone permission check
 | ||||
|     Core::System::GetInstance().RegisterMicPermissionCheck(&CheckMicPermission); | ||||
|     system.RegisterMicPermissionCheck(&CheckMicPermission); | ||||
| 
 | ||||
|     InputManager::Init(); | ||||
| 
 | ||||
|  | @ -167,7 +167,7 @@ static Core::System::ResultStatus RunCitra(const std::string& filepath) { | |||
|         return load_result; | ||||
|     } | ||||
| 
 | ||||
|     auto& telemetry_session = Core::System::GetInstance().TelemetrySession(); | ||||
|     auto& telemetry_session = system.TelemetrySession(); | ||||
|     telemetry_session.AddField(Common::Telemetry::FieldType::App, "Frontend", "Android"); | ||||
| 
 | ||||
|     stop_run = false; | ||||
|  | @ -188,8 +188,7 @@ static Core::System::ResultStatus RunCitra(const std::string& filepath) { | |||
|     audio_stretching_event = | ||||
|         system.CoreTiming().RegisterEvent("AudioStretchingEvent", [&](u64, s64 cycles_late) { | ||||
|             if (Settings::values.enable_audio_stretching) { | ||||
|                 Core::DSP().EnableStretching( | ||||
|                     Core::System::GetInstance().GetAndResetPerfStats().emulation_speed < 0.95); | ||||
|                 system.DSP().EnableStretching(system.GetAndResetPerfStats().emulation_speed < 0.95); | ||||
|             } | ||||
| 
 | ||||
|             system.CoreTiming().ScheduleEvent(audio_stretching_ticks - cycles_late, | ||||
|  | @ -220,7 +219,7 @@ static Core::System::ResultStatus RunCitra(const std::string& filepath) { | |||
|             SCOPE_EXIT({ Settings::values.volume = volume; }); | ||||
|             Settings::values.volume = 0; | ||||
| 
 | ||||
|             std::unique_lock<std::mutex> pause_lock(paused_mutex); | ||||
|             std::unique_lock pause_lock{paused_mutex}; | ||||
|             running_cv.wait(pause_lock, [] { return !pause_emulation || stop_run; }); | ||||
|             window->PollEvents(); | ||||
|         } | ||||
|  |  | |||
|  | @ -21,68 +21,8 @@ | |||
|      <item> | ||||
|       <widget class="QTabWidget" name="tabWidget"> | ||||
|        <property name="currentIndex"> | ||||
|         <number>0</number> | ||||
|         <number>-1</number> | ||||
|        </property> | ||||
|        <widget class="ConfigureGeneral" name="generalTab"> | ||||
|         <attribute name="title"> | ||||
|          <string>General</string> | ||||
|         </attribute> | ||||
|        </widget> | ||||
|        <widget class="ConfigureSystem" name="systemTab"> | ||||
|         <attribute name="title"> | ||||
|          <string>System</string> | ||||
|         </attribute> | ||||
|        </widget> | ||||
|        <widget class="ConfigureInput" name="inputTab"> | ||||
|         <attribute name="title"> | ||||
|          <string>Input</string> | ||||
|         </attribute> | ||||
|        </widget> | ||||
|        <widget class="ConfigureHotkeys" name="hotkeysTab"> | ||||
|         <attribute name="title"> | ||||
|          <string>Hotkeys</string> | ||||
|         </attribute> | ||||
|        </widget> | ||||
|        <widget class="ConfigureGraphics" name="graphicsTab"> | ||||
|         <attribute name="title"> | ||||
|          <string>Graphics</string> | ||||
|         </attribute> | ||||
|        </widget> | ||||
|        <widget class="ConfigureEnhancements" name="enhancementsTab"> | ||||
|          <attribute name="title"> | ||||
|            <string>Enhancements</string> | ||||
|          </attribute> | ||||
|        </widget> | ||||
|        <widget class="ConfigureAudio" name="audioTab"> | ||||
|         <attribute name="title"> | ||||
|          <string>Audio</string> | ||||
|         </attribute> | ||||
|        </widget> | ||||
|        <widget class="ConfigureCamera" name="cameraTab"> | ||||
|         <attribute name="title"> | ||||
|          <string>Camera</string> | ||||
|         </attribute> | ||||
|        </widget> | ||||
|        <widget class="ConfigureDebug" name="debugTab"> | ||||
|         <attribute name="title"> | ||||
|          <string>Debug</string> | ||||
|         </attribute> | ||||
|        </widget> | ||||
|        <widget class="ConfigureStorage" name="storageTab"> | ||||
|         <attribute name="title"> | ||||
|          <string>Storage</string> | ||||
|         </attribute> | ||||
|        </widget> | ||||
|        <widget class="ConfigureWeb" name="webTab"> | ||||
|         <attribute name="title"> | ||||
|          <string>Web</string> | ||||
|         </attribute> | ||||
|        </widget> | ||||
|        <widget class="ConfigureUi" name="uiTab"> | ||||
|         <attribute name="title"> | ||||
|          <string>UI</string> | ||||
|         </attribute> | ||||
|        </widget> | ||||
|       </widget> | ||||
|      </item> | ||||
|     </layout> | ||||
|  |  | |||
|  | @ -10,14 +10,13 @@ | |||
| #include "citra_qt/configuration/configuration_shared.h" | ||||
| #include "citra_qt/configuration/configure_audio.h" | ||||
| #include "common/settings.h" | ||||
| #include "core/core.h" | ||||
| #include "ui_configure_audio.h" | ||||
| 
 | ||||
| #if defined(__APPLE__) | ||||
| #include "common/apple_authorization.h" | ||||
| #endif | ||||
| 
 | ||||
| ConfigureAudio::ConfigureAudio(QWidget* parent) | ||||
| ConfigureAudio::ConfigureAudio(bool is_powered_on, QWidget* parent) | ||||
|     : QWidget(parent), ui(std::make_unique<Ui::ConfigureAudio>()) { | ||||
|     ui->setupUi(this); | ||||
| 
 | ||||
|  | @ -27,8 +26,7 @@ ConfigureAudio::ConfigureAudio(QWidget* parent) | |||
|             AudioCore::GetSinkName(static_cast<AudioCore::SinkType>(type)).data())); | ||||
|     } | ||||
| 
 | ||||
|     const bool is_running = Core::System::GetInstance().IsPoweredOn(); | ||||
|     ui->emulation_combo_box->setEnabled(!is_running); | ||||
|     ui->emulation_combo_box->setEnabled(!is_powered_on); | ||||
| 
 | ||||
|     connect(ui->volume_slider, &QSlider::valueChanged, this, | ||||
|             &ConfigureAudio::SetVolumeIndicatorText); | ||||
|  |  | |||
|  | @ -19,7 +19,7 @@ class ConfigureAudio : public QWidget { | |||
|     Q_OBJECT | ||||
| 
 | ||||
| public: | ||||
|     explicit ConfigureAudio(QWidget* parent = nullptr); | ||||
|     explicit ConfigureAudio(bool is_powered_on, QWidget* parent = nullptr); | ||||
|     ~ConfigureAudio() override; | ||||
| 
 | ||||
|     void ApplyConfiguration(); | ||||
|  |  | |||
|  | @ -47,8 +47,7 @@ ConfigureCamera::~ConfigureCamera() { | |||
| } | ||||
| 
 | ||||
| void ConfigureCamera::ConnectEvents() { | ||||
|     connect(ui->image_source, | ||||
|             static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, | ||||
|     connect(ui->image_source, qOverload<int>(&QComboBox::currentIndexChanged), this, | ||||
|             [this](int index) { | ||||
|                 StopPreviewing(); | ||||
|                 UpdateImageSourceUI(); | ||||
|  | @ -58,36 +57,33 @@ void ConfigureCamera::ConnectEvents() { | |||
|                 } | ||||
| #endif | ||||
|             }); | ||||
|     connect(ui->camera_selection, | ||||
|             static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, [this] { | ||||
|                 StopPreviewing(); | ||||
|                 if (GetCameraSelection() != current_selected) { | ||||
|                     RecordConfig(); | ||||
|                 } | ||||
|                 if (ui->camera_selection->currentIndex() == 1) { | ||||
|                     ui->camera_mode->setCurrentIndex(1); // Double
 | ||||
|                     if (camera_name[0] == camera_name[2] && camera_config[0] == camera_config[2]) { | ||||
|                         ui->camera_mode->setCurrentIndex(0); // Single
 | ||||
|                     } | ||||
|                 } | ||||
|                 UpdateCameraMode(); | ||||
|                 SetConfiguration(); | ||||
|             }); | ||||
|     connect(ui->camera_mode, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), | ||||
|             this, [this] { | ||||
|                 StopPreviewing(); | ||||
|                 ui->camera_position_label->setVisible(ui->camera_mode->currentIndex() == 1); | ||||
|                 ui->camera_position->setVisible(ui->camera_mode->currentIndex() == 1); | ||||
|                 current_selected = GetCameraSelection(); | ||||
|             }); | ||||
|     connect(ui->camera_position, | ||||
|             static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, [this] { | ||||
|                 StopPreviewing(); | ||||
|                 if (GetCameraSelection() != current_selected) { | ||||
|                     RecordConfig(); | ||||
|                 } | ||||
|                 SetConfiguration(); | ||||
|             }); | ||||
|     connect(ui->camera_selection, qOverload<int>(&QComboBox::currentIndexChanged), this, [this] { | ||||
|         StopPreviewing(); | ||||
|         if (GetCameraSelection() != current_selected) { | ||||
|             RecordConfig(); | ||||
|         } | ||||
|         if (ui->camera_selection->currentIndex() == 1) { | ||||
|             ui->camera_mode->setCurrentIndex(1); // Double
 | ||||
|             if (camera_name[0] == camera_name[2] && camera_config[0] == camera_config[2]) { | ||||
|                 ui->camera_mode->setCurrentIndex(0); // Single
 | ||||
|             } | ||||
|         } | ||||
|         UpdateCameraMode(); | ||||
|         SetConfiguration(); | ||||
|     }); | ||||
|     connect(ui->camera_mode, qOverload<int>(&QComboBox::currentIndexChanged), this, [this] { | ||||
|         StopPreviewing(); | ||||
|         ui->camera_position_label->setVisible(ui->camera_mode->currentIndex() == 1); | ||||
|         ui->camera_position->setVisible(ui->camera_mode->currentIndex() == 1); | ||||
|         current_selected = GetCameraSelection(); | ||||
|     }); | ||||
|     connect(ui->camera_position, qOverload<int>(&QComboBox::currentIndexChanged), this, [this] { | ||||
|         StopPreviewing(); | ||||
|         if (GetCameraSelection() != current_selected) { | ||||
|             RecordConfig(); | ||||
|         } | ||||
|         SetConfiguration(); | ||||
|     }); | ||||
|     connect(ui->toolButton, &QToolButton::clicked, this, &ConfigureCamera::OnToolButtonClicked); | ||||
|     connect(ui->preview_button, &QPushButton::clicked, this, [this] { StartPreviewing(); }); | ||||
|     connect(ui->prompt_before_load, &QCheckBox::stateChanged, this, [this](int state) { | ||||
|  |  | |||
|  | @ -9,11 +9,9 @@ | |||
| #include "core/cheats/cheat_base.h" | ||||
| #include "core/cheats/cheats.h" | ||||
| #include "core/cheats/gateway_cheat.h" | ||||
| #include "core/core.h" | ||||
| #include "core/hle/kernel/process.h" | ||||
| #include "ui_configure_cheats.h" | ||||
| 
 | ||||
| ConfigureCheats::ConfigureCheats(u64 title_id_, QWidget* parent) | ||||
| ConfigureCheats::ConfigureCheats(Core::System& system, u64 title_id_, QWidget* parent) | ||||
|     : QWidget(parent), ui(std::make_unique<Ui::ConfigureCheats>()), title_id{title_id_} { | ||||
|     // Setup gui control settings
 | ||||
|     ui->setupUi(this); | ||||
|  | @ -36,7 +34,7 @@ ConfigureCheats::ConfigureCheats(u64 title_id_, QWidget* parent) | |||
|             [this] { SaveCheat(ui->tableCheats->currentRow()); }); | ||||
|     connect(ui->buttonDelete, &QPushButton::clicked, this, &ConfigureCheats::OnDeleteCheat); | ||||
| 
 | ||||
|     cheat_engine = std::make_unique<Cheats::CheatEngine>(title_id, Core::System::GetInstance()); | ||||
|     cheat_engine = std::make_unique<Cheats::CheatEngine>(title_id, system); | ||||
| 
 | ||||
|     LoadCheats(); | ||||
| } | ||||
|  |  | |||
|  | @ -5,6 +5,7 @@ | |||
| #pragma once | ||||
| 
 | ||||
| #include <memory> | ||||
| #include <QWidget> | ||||
| #include "common/common_types.h" | ||||
| 
 | ||||
| namespace Cheats { | ||||
|  | @ -12,6 +13,10 @@ class CheatBase; | |||
| class CheatEngine; | ||||
| } // namespace Cheats
 | ||||
| 
 | ||||
| namespace Core { | ||||
| class System; | ||||
| } | ||||
| 
 | ||||
| namespace Ui { | ||||
| class ConfigureCheats; | ||||
| } // namespace Ui
 | ||||
|  | @ -20,7 +25,7 @@ class ConfigureCheats : public QWidget { | |||
|     Q_OBJECT | ||||
| 
 | ||||
| public: | ||||
|     explicit ConfigureCheats(u64 title_id_, QWidget* parent = nullptr); | ||||
|     explicit ConfigureCheats(Core::System& system, u64 title_id, QWidget* parent = nullptr); | ||||
|     ~ConfigureCheats(); | ||||
|     bool ApplyConfiguration(); | ||||
| 
 | ||||
|  |  | |||
|  | @ -11,7 +11,6 @@ | |||
| #include "common/file_util.h" | ||||
| #include "common/logging/backend.h" | ||||
| #include "common/settings.h" | ||||
| #include "core/core.h" | ||||
| #include "ui_configure_debug.h" | ||||
| 
 | ||||
| // The QSlider doesn't have an easy way to set a custom step amount,
 | ||||
|  | @ -25,8 +24,8 @@ static constexpr int SettingsToSlider(int value) { | |||
|     return (value - 5) / 5; | ||||
| } | ||||
| 
 | ||||
| ConfigureDebug::ConfigureDebug(QWidget* parent) | ||||
|     : QWidget(parent), ui(std::make_unique<Ui::ConfigureDebug>()) { | ||||
| ConfigureDebug::ConfigureDebug(bool is_powered_on_, QWidget* parent) | ||||
|     : QWidget(parent), ui(std::make_unique<Ui::ConfigureDebug>()), is_powered_on{is_powered_on_} { | ||||
|     ui->setupUi(this); | ||||
|     SetConfiguration(); | ||||
| 
 | ||||
|  | @ -35,7 +34,6 @@ ConfigureDebug::ConfigureDebug(QWidget* parent) | |||
|         QDesktopServices::openUrl(QUrl::fromLocalFile(path)); | ||||
|     }); | ||||
| 
 | ||||
|     const bool is_powered_on = Core::System::GetInstance().IsPoweredOn(); | ||||
|     ui->toggle_cpu_jit->setEnabled(!is_powered_on); | ||||
|     ui->toggle_renderer_debug->setEnabled(!is_powered_on); | ||||
| 
 | ||||
|  | @ -59,7 +57,7 @@ void ConfigureDebug::SetConfiguration() { | |||
|     ui->toggle_gdbstub->setChecked(Settings::values.use_gdbstub.GetValue()); | ||||
|     ui->gdbport_spinbox->setEnabled(Settings::values.use_gdbstub.GetValue()); | ||||
|     ui->gdbport_spinbox->setValue(Settings::values.gdbstub_port.GetValue()); | ||||
|     ui->toggle_console->setEnabled(!Core::System::GetInstance().IsPoweredOn()); | ||||
|     ui->toggle_console->setEnabled(!is_powered_on); | ||||
|     ui->toggle_console->setChecked(UISettings::values.show_console.GetValue()); | ||||
|     ui->log_filter_edit->setText(QString::fromStdString(Settings::values.log_filter.GetValue())); | ||||
|     ui->toggle_cpu_jit->setChecked(Settings::values.use_cpu_jit.GetValue()); | ||||
|  |  | |||
|  | @ -15,7 +15,7 @@ class ConfigureDebug : public QWidget { | |||
|     Q_OBJECT | ||||
| 
 | ||||
| public: | ||||
|     explicit ConfigureDebug(QWidget* parent = nullptr); | ||||
|     explicit ConfigureDebug(bool is_powered_on, QWidget* parent = nullptr); | ||||
|     ~ConfigureDebug() override; | ||||
| 
 | ||||
|     void ApplyConfiguration(); | ||||
|  | @ -25,4 +25,5 @@ public: | |||
| 
 | ||||
| private: | ||||
|     std::unique_ptr<Ui::ConfigureDebug> ui; | ||||
|     bool is_powered_on; | ||||
| }; | ||||
|  |  | |||
|  | @ -4,8 +4,19 @@ | |||
| 
 | ||||
| #include <map> | ||||
| #include <QListWidgetItem> | ||||
| #include "citra_qt/configuration/config.h" | ||||
| #include "citra_qt/configuration/configure_audio.h" | ||||
| #include "citra_qt/configuration/configure_camera.h" | ||||
| #include "citra_qt/configuration/configure_debug.h" | ||||
| #include "citra_qt/configuration/configure_dialog.h" | ||||
| #include "citra_qt/configuration/configure_enhancements.h" | ||||
| #include "citra_qt/configuration/configure_general.h" | ||||
| #include "citra_qt/configuration/configure_graphics.h" | ||||
| #include "citra_qt/configuration/configure_hotkeys.h" | ||||
| #include "citra_qt/configuration/configure_input.h" | ||||
| #include "citra_qt/configuration/configure_storage.h" | ||||
| #include "citra_qt/configuration/configure_system.h" | ||||
| #include "citra_qt/configuration/configure_ui.h" | ||||
| #include "citra_qt/configuration/configure_web.h" | ||||
| #include "citra_qt/hotkeys.h" | ||||
| #include "common/settings.h" | ||||
| #include "core/core.h" | ||||
|  | @ -14,16 +25,41 @@ | |||
| ConfigureDialog::ConfigureDialog(QWidget* parent, HotkeyRegistry& registry_, Core::System& system_, | ||||
|                                  bool enable_web_config) | ||||
|     : QDialog(parent), ui{std::make_unique<Ui::ConfigureDialog>()}, registry{registry_}, | ||||
|       system{system_} { | ||||
|       system{system_}, is_powered_on{system.IsPoweredOn()}, | ||||
|       general_tab{std::make_unique<ConfigureGeneral>(this)}, | ||||
|       system_tab{std::make_unique<ConfigureSystem>(system, this)}, | ||||
|       input_tab{std::make_unique<ConfigureInput>(this)}, | ||||
|       hotkeys_tab{std::make_unique<ConfigureHotkeys>(this)}, | ||||
|       graphics_tab{std::make_unique<ConfigureGraphics>(is_powered_on, this)}, | ||||
|       enhancements_tab{std::make_unique<ConfigureEnhancements>(this)}, | ||||
|       audio_tab{std::make_unique<ConfigureAudio>(is_powered_on, this)}, | ||||
|       camera_tab{std::make_unique<ConfigureCamera>(this)}, | ||||
|       debug_tab{std::make_unique<ConfigureDebug>(is_powered_on, this)}, | ||||
|       storage_tab{std::make_unique<ConfigureStorage>(is_powered_on, this)}, | ||||
|       web_tab{std::make_unique<ConfigureWeb>(this)}, ui_tab{std::make_unique<ConfigureUi>(this)} { | ||||
|     Settings::SetConfiguringGlobal(true); | ||||
| 
 | ||||
|     ui->setupUi(this); | ||||
|     ui->hotkeysTab->Populate(registry); | ||||
|     ui->webTab->SetWebServiceConfigEnabled(enable_web_config); | ||||
| 
 | ||||
|     ui->tabWidget->addTab(general_tab.get(), tr("General")); | ||||
|     ui->tabWidget->addTab(system_tab.get(), tr("System")); | ||||
|     ui->tabWidget->addTab(input_tab.get(), tr("Input")); | ||||
|     ui->tabWidget->addTab(hotkeys_tab.get(), tr("Hotkeys")); | ||||
|     ui->tabWidget->addTab(graphics_tab.get(), tr("Graphics")); | ||||
|     ui->tabWidget->addTab(enhancements_tab.get(), tr("Enhancements")); | ||||
|     ui->tabWidget->addTab(audio_tab.get(), tr("Audio")); | ||||
|     ui->tabWidget->addTab(camera_tab.get(), tr("Camera")); | ||||
|     ui->tabWidget->addTab(debug_tab.get(), tr("Debug")); | ||||
|     ui->tabWidget->addTab(storage_tab.get(), tr("Storage")); | ||||
|     ui->tabWidget->addTab(web_tab.get(), tr("Web")); | ||||
|     ui->tabWidget->addTab(ui_tab.get(), tr("UI")); | ||||
| 
 | ||||
|     hotkeys_tab->Populate(registry); | ||||
|     web_tab->SetWebServiceConfigEnabled(enable_web_config); | ||||
| 
 | ||||
|     PopulateSelectionList(); | ||||
| 
 | ||||
|     connect(ui->uiTab, &ConfigureUi::LanguageChanged, this, &ConfigureDialog::OnLanguageChanged); | ||||
|     connect(ui_tab.get(), &ConfigureUi::LanguageChanged, this, &ConfigureDialog::OnLanguageChanged); | ||||
|     connect(ui->selectorList, &QListWidget::itemSelectionChanged, this, | ||||
|             &ConfigureDialog::UpdateVisibleTabs); | ||||
| 
 | ||||
|  | @ -31,46 +67,46 @@ ConfigureDialog::ConfigureDialog(QWidget* parent, HotkeyRegistry& registry_, Cor | |||
|     ui->selectorList->setCurrentRow(0); | ||||
| 
 | ||||
|     // Set up used key list synchronisation
 | ||||
|     connect(ui->inputTab, &ConfigureInput::InputKeysChanged, ui->hotkeysTab, | ||||
|     connect(input_tab.get(), &ConfigureInput::InputKeysChanged, hotkeys_tab.get(), | ||||
|             &ConfigureHotkeys::OnInputKeysChanged); | ||||
|     connect(ui->hotkeysTab, &ConfigureHotkeys::HotkeysChanged, ui->inputTab, | ||||
|     connect(hotkeys_tab.get(), &ConfigureHotkeys::HotkeysChanged, input_tab.get(), | ||||
|             &ConfigureInput::OnHotkeysChanged); | ||||
| 
 | ||||
|     // Synchronise lists upon initialisation
 | ||||
|     ui->inputTab->EmitInputKeysChanged(); | ||||
|     ui->hotkeysTab->EmitHotkeysChanged(); | ||||
|     input_tab->EmitInputKeysChanged(); | ||||
|     hotkeys_tab->EmitHotkeysChanged(); | ||||
| } | ||||
| 
 | ||||
| ConfigureDialog::~ConfigureDialog() = default; | ||||
| 
 | ||||
| void ConfigureDialog::SetConfiguration() { | ||||
|     ui->generalTab->SetConfiguration(); | ||||
|     ui->systemTab->SetConfiguration(); | ||||
|     ui->inputTab->LoadConfiguration(); | ||||
|     ui->graphicsTab->SetConfiguration(); | ||||
|     ui->enhancementsTab->SetConfiguration(); | ||||
|     ui->audioTab->SetConfiguration(); | ||||
|     ui->cameraTab->SetConfiguration(); | ||||
|     ui->debugTab->SetConfiguration(); | ||||
|     ui->webTab->SetConfiguration(); | ||||
|     ui->uiTab->SetConfiguration(); | ||||
|     ui->storageTab->SetConfiguration(); | ||||
|     general_tab->SetConfiguration(); | ||||
|     system_tab->SetConfiguration(); | ||||
|     input_tab->LoadConfiguration(); | ||||
|     graphics_tab->SetConfiguration(); | ||||
|     enhancements_tab->SetConfiguration(); | ||||
|     audio_tab->SetConfiguration(); | ||||
|     camera_tab->SetConfiguration(); | ||||
|     debug_tab->SetConfiguration(); | ||||
|     web_tab->SetConfiguration(); | ||||
|     ui_tab->SetConfiguration(); | ||||
|     storage_tab->SetConfiguration(); | ||||
| } | ||||
| 
 | ||||
| void ConfigureDialog::ApplyConfiguration() { | ||||
|     ui->generalTab->ApplyConfiguration(); | ||||
|     ui->systemTab->ApplyConfiguration(); | ||||
|     ui->inputTab->ApplyConfiguration(); | ||||
|     ui->inputTab->ApplyProfile(); | ||||
|     ui->hotkeysTab->ApplyConfiguration(registry); | ||||
|     ui->graphicsTab->ApplyConfiguration(); | ||||
|     ui->enhancementsTab->ApplyConfiguration(); | ||||
|     ui->audioTab->ApplyConfiguration(); | ||||
|     ui->cameraTab->ApplyConfiguration(); | ||||
|     ui->debugTab->ApplyConfiguration(); | ||||
|     ui->webTab->ApplyConfiguration(); | ||||
|     ui->uiTab->ApplyConfiguration(); | ||||
|     ui->storageTab->ApplyConfiguration(); | ||||
|     general_tab->ApplyConfiguration(); | ||||
|     system_tab->ApplyConfiguration(); | ||||
|     input_tab->ApplyConfiguration(); | ||||
|     input_tab->ApplyProfile(); | ||||
|     hotkeys_tab->ApplyConfiguration(registry); | ||||
|     graphics_tab->ApplyConfiguration(); | ||||
|     enhancements_tab->ApplyConfiguration(); | ||||
|     audio_tab->ApplyConfiguration(); | ||||
|     camera_tab->ApplyConfiguration(); | ||||
|     debug_tab->ApplyConfiguration(); | ||||
|     web_tab->ApplyConfiguration(); | ||||
|     ui_tab->ApplyConfiguration(); | ||||
|     storage_tab->ApplyConfiguration(); | ||||
|     system.ApplySettings(); | ||||
|     Settings::LogSettings(); | ||||
| } | ||||
|  | @ -81,11 +117,11 @@ void ConfigureDialog::PopulateSelectionList() { | |||
|     ui->selectorList->clear(); | ||||
| 
 | ||||
|     const std::array<std::pair<QString, QList<QWidget*>>, 5> items{ | ||||
|         {{tr("General"), {ui->generalTab, ui->webTab, ui->debugTab, ui->uiTab}}, | ||||
|          {tr("System"), {ui->systemTab, ui->cameraTab, ui->storageTab}}, | ||||
|          {tr("Graphics"), {ui->enhancementsTab, ui->graphicsTab}}, | ||||
|          {tr("Audio"), {ui->audioTab}}, | ||||
|          {tr("Controls"), {ui->inputTab, ui->hotkeysTab}}}}; | ||||
|         {{tr("General"), {general_tab.get(), web_tab.get(), debug_tab.get(), ui_tab.get()}}, | ||||
|          {tr("System"), {system_tab.get(), camera_tab.get(), storage_tab.get()}}, | ||||
|          {tr("Graphics"), {enhancements_tab.get(), graphics_tab.get()}}, | ||||
|          {tr("Audio"), {audio_tab.get()}}, | ||||
|          {tr("Controls"), {input_tab.get(), hotkeys_tab.get()}}}}; | ||||
| 
 | ||||
|     for (const auto& entry : items) { | ||||
|         auto* const item = new QListWidgetItem(entry.first); | ||||
|  | @ -112,18 +148,18 @@ void ConfigureDialog::RetranslateUI() { | |||
|     ui->selectorList->setCurrentRow(old_row); | ||||
|     ui->tabWidget->setCurrentIndex(old_index); | ||||
| 
 | ||||
|     ui->generalTab->RetranslateUI(); | ||||
|     ui->systemTab->RetranslateUI(); | ||||
|     ui->inputTab->RetranslateUI(); | ||||
|     ui->hotkeysTab->RetranslateUI(); | ||||
|     ui->graphicsTab->RetranslateUI(); | ||||
|     ui->enhancementsTab->RetranslateUI(); | ||||
|     ui->audioTab->RetranslateUI(); | ||||
|     ui->cameraTab->RetranslateUI(); | ||||
|     ui->debugTab->RetranslateUI(); | ||||
|     ui->webTab->RetranslateUI(); | ||||
|     ui->uiTab->RetranslateUI(); | ||||
|     ui->storageTab->RetranslateUI(); | ||||
|     general_tab->RetranslateUI(); | ||||
|     system_tab->RetranslateUI(); | ||||
|     input_tab->RetranslateUI(); | ||||
|     hotkeys_tab->RetranslateUI(); | ||||
|     graphics_tab->RetranslateUI(); | ||||
|     enhancements_tab->RetranslateUI(); | ||||
|     audio_tab->RetranslateUI(); | ||||
|     camera_tab->RetranslateUI(); | ||||
|     debug_tab->RetranslateUI(); | ||||
|     web_tab->RetranslateUI(); | ||||
|     ui_tab->RetranslateUI(); | ||||
|     storage_tab->RetranslateUI(); | ||||
| } | ||||
| 
 | ||||
| void ConfigureDialog::UpdateVisibleTabs() { | ||||
|  | @ -131,18 +167,18 @@ void ConfigureDialog::UpdateVisibleTabs() { | |||
|     if (items.isEmpty()) | ||||
|         return; | ||||
| 
 | ||||
|     const std::map<QWidget*, QString> widgets = {{ui->generalTab, tr("General")}, | ||||
|                                                  {ui->systemTab, tr("System")}, | ||||
|                                                  {ui->inputTab, tr("Input")}, | ||||
|                                                  {ui->hotkeysTab, tr("Hotkeys")}, | ||||
|                                                  {ui->enhancementsTab, tr("Enhancements")}, | ||||
|                                                  {ui->graphicsTab, tr("Advanced")}, | ||||
|                                                  {ui->audioTab, tr("Audio")}, | ||||
|                                                  {ui->cameraTab, tr("Camera")}, | ||||
|                                                  {ui->debugTab, tr("Debug")}, | ||||
|                                                  {ui->storageTab, tr("Storage")}, | ||||
|                                                  {ui->webTab, tr("Web")}, | ||||
|                                                  {ui->uiTab, tr("UI")}}; | ||||
|     const std::map<QWidget*, QString> widgets = {{general_tab.get(), tr("General")}, | ||||
|                                                  {system_tab.get(), tr("System")}, | ||||
|                                                  {input_tab.get(), tr("Input")}, | ||||
|                                                  {hotkeys_tab.get(), tr("Hotkeys")}, | ||||
|                                                  {enhancements_tab.get(), tr("Enhancements")}, | ||||
|                                                  {graphics_tab.get(), tr("Advanced")}, | ||||
|                                                  {audio_tab.get(), tr("Audio")}, | ||||
|                                                  {camera_tab.get(), tr("Camera")}, | ||||
|                                                  {debug_tab.get(), tr("Debug")}, | ||||
|                                                  {storage_tab.get(), tr("Storage")}, | ||||
|                                                  {web_tab.get(), tr("Web")}, | ||||
|                                                  {ui_tab.get(), tr("UI")}}; | ||||
| 
 | ||||
|     ui->tabWidget->clear(); | ||||
| 
 | ||||
|  |  | |||
|  | @ -17,6 +17,19 @@ namespace Core { | |||
| class System; | ||||
| } | ||||
| 
 | ||||
| class ConfigureGeneral; | ||||
| class ConfigureSystem; | ||||
| class ConfigureInput; | ||||
| class ConfigureHotkeys; | ||||
| class ConfigureGraphics; | ||||
| class ConfigureEnhancements; | ||||
| class ConfigureAudio; | ||||
| class ConfigureCamera; | ||||
| class ConfigureDebug; | ||||
| class ConfigureStorage; | ||||
| class ConfigureWeb; | ||||
| class ConfigureUi; | ||||
| 
 | ||||
| class ConfigureDialog : public QDialog { | ||||
|     Q_OBJECT | ||||
| 
 | ||||
|  | @ -42,4 +55,18 @@ private: | |||
|     std::unique_ptr<Ui::ConfigureDialog> ui; | ||||
|     HotkeyRegistry& registry; | ||||
|     Core::System& system; | ||||
|     bool is_powered_on; | ||||
| 
 | ||||
|     std::unique_ptr<ConfigureGeneral> general_tab; | ||||
|     std::unique_ptr<ConfigureSystem> system_tab; | ||||
|     std::unique_ptr<ConfigureInput> input_tab; | ||||
|     std::unique_ptr<ConfigureHotkeys> hotkeys_tab; | ||||
|     std::unique_ptr<ConfigureGraphics> graphics_tab; | ||||
|     std::unique_ptr<ConfigureEnhancements> enhancements_tab; | ||||
|     std::unique_ptr<ConfigureAudio> audio_tab; | ||||
|     std::unique_ptr<ConfigureCamera> camera_tab; | ||||
|     std::unique_ptr<ConfigureDebug> debug_tab; | ||||
|     std::unique_ptr<ConfigureStorage> storage_tab; | ||||
|     std::unique_ptr<ConfigureWeb> web_tab; | ||||
|     std::unique_ptr<ConfigureUi> ui_tab; | ||||
| }; | ||||
|  |  | |||
|  | @ -22,8 +22,7 @@ ConfigureEnhancements::ConfigureEnhancements(QWidget* parent) | |||
|     const bool res_scale_enabled = graphics_api != Settings::GraphicsAPI::Software; | ||||
|     ui->resolution_factor_combobox->setEnabled(res_scale_enabled); | ||||
| 
 | ||||
|     connect(ui->render_3d_combobox, | ||||
|             static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, | ||||
|     connect(ui->render_3d_combobox, qOverload<int>(&QComboBox::currentIndexChanged), this, | ||||
|             [this](int currentIndex) { | ||||
|                 updateShaders(static_cast<Settings::StereoRenderOption>(currentIndex)); | ||||
|             }); | ||||
|  |  | |||
|  | @ -6,14 +6,13 @@ | |||
| #include "citra_qt/configuration/configuration_shared.h" | ||||
| #include "citra_qt/configuration/configure_graphics.h" | ||||
| #include "common/settings.h" | ||||
| #include "core/core.h" | ||||
| #include "ui_configure_graphics.h" | ||||
| 
 | ||||
| ConfigureGraphics::ConfigureGraphics(QWidget* parent) | ||||
| ConfigureGraphics::ConfigureGraphics(bool is_powered_on, QWidget* parent) | ||||
|     : QWidget(parent), ui(std::make_unique<Ui::ConfigureGraphics>()) { | ||||
|     ui->setupUi(this); | ||||
| 
 | ||||
|     ui->toggle_vsync_new->setEnabled(!Core::System::GetInstance().IsPoweredOn()); | ||||
|     ui->toggle_vsync_new->setEnabled(!is_powered_on); | ||||
|     // Set the index to -1 to ensure the below lambda is called with setCurrentIndex
 | ||||
|     ui->graphics_api_combo->setCurrentIndex(-1); | ||||
| 
 | ||||
|  |  | |||
|  | @ -19,7 +19,7 @@ class ConfigureGraphics : public QWidget { | |||
|     Q_OBJECT | ||||
| 
 | ||||
| public: | ||||
|     explicit ConfigureGraphics(QWidget* parent = nullptr); | ||||
|     explicit ConfigureGraphics(bool is_powered_on, QWidget* parent = nullptr); | ||||
|     ~ConfigureGraphics() override; | ||||
| 
 | ||||
|     void ApplyConfiguration(); | ||||
|  |  | |||
|  | @ -19,6 +19,9 @@ | |||
|   <property name="windowTitle"> | ||||
|    <string>Form</string> | ||||
|   </property> | ||||
|   <property name="accessibleName"> | ||||
|    <string>Graphics</string> | ||||
|   </property> | ||||
|   <layout class="QVBoxLayout" name="verticalLayout"> | ||||
|    <item> | ||||
|     <widget class="QGroupBox" name="apiBox"> | ||||
|  |  | |||
|  | @ -9,7 +9,6 @@ | |||
| #include "citra_qt/configuration/configure_hotkeys.h" | ||||
| #include "citra_qt/hotkeys.h" | ||||
| #include "citra_qt/util/sequence_dialog/sequence_dialog.h" | ||||
| #include "common/settings.h" | ||||
| #include "ui_configure_hotkeys.h" | ||||
| 
 | ||||
| constexpr int name_column = 0; | ||||
|  | @ -189,9 +188,9 @@ void ConfigureHotkeys::PopupContextMenu(const QPoint& menu_location) { | |||
|     QAction* clear = context_menu.addAction(tr("Clear")); | ||||
| 
 | ||||
|     const auto hotkey_index = index.sibling(index.row(), hotkey_column); | ||||
|     connect(restore_default, &QAction::triggered, | ||||
|     connect(restore_default, &QAction::triggered, this, | ||||
|             [this, hotkey_index] { RestoreHotkey(hotkey_index); }); | ||||
|     connect(clear, &QAction::triggered, | ||||
|     connect(clear, &QAction::triggered, this, | ||||
|             [this, hotkey_index] { model->setData(hotkey_index, QString{}); }); | ||||
| 
 | ||||
|     context_menu.exec(ui->hotkey_list->viewport()->mapToGlobal(menu_location)); | ||||
|  |  | |||
|  | @ -31,13 +31,14 @@ ConfigurePerGame::ConfigurePerGame(QWidget* parent, u64 title_id_, const QString | |||
|                                                 : fmt::format("{:016X}", title_id); | ||||
|     game_config = std::make_unique<Config>(config_file_name, Config::ConfigType::PerGameConfig); | ||||
| 
 | ||||
|     audio_tab = std::make_unique<ConfigureAudio>(this); | ||||
|     const bool is_powered_on = system.IsPoweredOn(); | ||||
|     audio_tab = std::make_unique<ConfigureAudio>(is_powered_on, this); | ||||
|     general_tab = std::make_unique<ConfigureGeneral>(this); | ||||
|     enhancements_tab = std::make_unique<ConfigureEnhancements>(this); | ||||
|     graphics_tab = std::make_unique<ConfigureGraphics>(this); | ||||
|     system_tab = std::make_unique<ConfigureSystem>(this); | ||||
|     debug_tab = std::make_unique<ConfigureDebug>(this); | ||||
|     cheat_tab = std::make_unique<ConfigureCheats>(title_id, this); | ||||
|     graphics_tab = std::make_unique<ConfigureGraphics>(is_powered_on, this); | ||||
|     system_tab = std::make_unique<ConfigureSystem>(system, this); | ||||
|     debug_tab = std::make_unique<ConfigureDebug>(is_powered_on, this); | ||||
|     cheat_tab = std::make_unique<ConfigureCheats>(system, title_id, this); | ||||
| 
 | ||||
|     ui->setupUi(this); | ||||
| 
 | ||||
|  |  | |||
|  | @ -8,11 +8,10 @@ | |||
| #include "citra_qt/configuration/configure_storage.h" | ||||
| #include "common/file_util.h" | ||||
| #include "common/settings.h" | ||||
| #include "core/core.h" | ||||
| #include "ui_configure_storage.h" | ||||
| 
 | ||||
| ConfigureStorage::ConfigureStorage(QWidget* parent) | ||||
|     : QWidget(parent), ui(std::make_unique<Ui::ConfigureStorage>()) { | ||||
| ConfigureStorage::ConfigureStorage(bool is_powered_on_, QWidget* parent) | ||||
|     : QWidget(parent), ui(std::make_unique<Ui::ConfigureStorage>()), is_powered_on{is_powered_on_} { | ||||
|     ui->setupUi(this); | ||||
|     SetConfiguration(); | ||||
| 
 | ||||
|  | @ -75,7 +74,7 @@ void ConfigureStorage::SetConfiguration() { | |||
|     ui->toggle_virtual_sd->setChecked(Settings::values.use_virtual_sd.GetValue()); | ||||
|     ui->toggle_custom_storage->setChecked(Settings::values.use_custom_storage.GetValue()); | ||||
| 
 | ||||
|     ui->storage_group->setEnabled(!Core::System::GetInstance().IsPoweredOn()); | ||||
|     ui->storage_group->setEnabled(!is_powered_on); | ||||
| } | ||||
| 
 | ||||
| void ConfigureStorage::ApplyConfiguration() { | ||||
|  |  | |||
|  | @ -15,7 +15,7 @@ class ConfigureStorage : public QWidget { | |||
|     Q_OBJECT | ||||
| 
 | ||||
| public: | ||||
|     explicit ConfigureStorage(QWidget* parent = nullptr); | ||||
|     explicit ConfigureStorage(bool is_powered_on, QWidget* parent = nullptr); | ||||
|     ~ConfigureStorage() override; | ||||
| 
 | ||||
|     void ApplyConfiguration(); | ||||
|  | @ -23,4 +23,5 @@ public: | |||
|     void SetConfiguration(); | ||||
| 
 | ||||
|     std::unique_ptr<Ui::ConfigureStorage> ui; | ||||
|     bool is_powered_on; | ||||
| }; | ||||
|  |  | |||
|  | @ -223,14 +223,12 @@ static const std::array<const char*, 187> country_names = { | |||
|     QT_TRANSLATE_NOOP("ConfigureSystem", "Bermuda"), // 180-186
 | ||||
| }; | ||||
| 
 | ||||
| ConfigureSystem::ConfigureSystem(QWidget* parent) | ||||
|     : QWidget(parent), ui(std::make_unique<Ui::ConfigureSystem>()) { | ||||
| ConfigureSystem::ConfigureSystem(Core::System& system_, QWidget* parent) | ||||
|     : QWidget(parent), ui(std::make_unique<Ui::ConfigureSystem>()), system{system_} { | ||||
|     ui->setupUi(this); | ||||
|     connect(ui->combo_birthmonth, | ||||
|             static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, | ||||
|     connect(ui->combo_birthmonth, qOverload<int>(&QComboBox::currentIndexChanged), this, | ||||
|             &ConfigureSystem::UpdateBirthdayComboBox); | ||||
|     connect(ui->combo_init_clock, | ||||
|             static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, | ||||
|     connect(ui->combo_init_clock, qOverload<int>(&QComboBox::currentIndexChanged), this, | ||||
|             &ConfigureSystem::UpdateInitTime); | ||||
|     connect(ui->button_regenerate_console_id, &QPushButton::clicked, this, | ||||
|             &ConfigureSystem::RefreshConsoleID); | ||||
|  | @ -280,7 +278,7 @@ ConfigureSystem::ConfigureSystem(QWidget* parent) | |||
| ConfigureSystem::~ConfigureSystem() = default; | ||||
| 
 | ||||
| void ConfigureSystem::SetConfiguration() { | ||||
|     enabled = !Core::System::GetInstance().IsPoweredOn(); | ||||
|     enabled = !system.IsPoweredOn(); | ||||
| 
 | ||||
|     ui->combo_init_clock->setCurrentIndex(static_cast<u8>(Settings::values.init_clock.GetValue())); | ||||
|     QDateTime date_time; | ||||
|  | @ -296,7 +294,7 @@ void ConfigureSystem::SetConfiguration() { | |||
|     ui->edit_init_time_offset_time->setTime(time); | ||||
| 
 | ||||
|     if (!enabled) { | ||||
|         cfg = Service::CFG::GetModule(Core::System::GetInstance()); | ||||
|         cfg = Service::CFG::GetModule(system); | ||||
|         ASSERT_MSG(cfg, "CFG Module missing!"); | ||||
|         ReadSystemSettings(); | ||||
|         ui->group_system_settings->setEnabled(false); | ||||
|  |  | |||
|  | @ -16,6 +16,10 @@ namespace ConfigurationShared { | |||
| enum class CheckState; | ||||
| } | ||||
| 
 | ||||
| namespace Core { | ||||
| class System; | ||||
| } | ||||
| 
 | ||||
| namespace Service { | ||||
| namespace CFG { | ||||
| class Module; | ||||
|  | @ -26,7 +30,7 @@ class ConfigureSystem : public QWidget { | |||
|     Q_OBJECT | ||||
| 
 | ||||
| public: | ||||
|     explicit ConfigureSystem(QWidget* parent = nullptr); | ||||
|     explicit ConfigureSystem(Core::System& system, QWidget* parent = nullptr); | ||||
|     ~ConfigureSystem() override; | ||||
| 
 | ||||
|     void ApplyConfiguration(); | ||||
|  | @ -45,8 +49,10 @@ private: | |||
| 
 | ||||
|     void DownloadFromNUS(); | ||||
| 
 | ||||
|     ConfigurationShared::CheckState is_new_3ds; | ||||
| private: | ||||
|     std::unique_ptr<Ui::ConfigureSystem> ui; | ||||
|     Core::System& system; | ||||
|     ConfigurationShared::CheckState is_new_3ds; | ||||
|     bool enabled = false; | ||||
| 
 | ||||
|     std::shared_ptr<Service::CFG::Module> cfg; | ||||
|  |  | |||
|  | @ -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); | ||||
| 
 | ||||
|  |  | |||
|  | @ -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; | ||||
|  |  | |||
|  | @ -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)) { | ||||
|  |  | |||
|  | @ -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; | ||||
|  |  | |||
|  | @ -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); | ||||
|  |  | |||
|  | @ -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.
 | ||||
|  |  | |||
|  | @ -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'))); | ||||
|  |  | |||
|  | @ -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; | ||||
|  |  | |||
|  | @ -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); | ||||
| } | ||||
|  |  | |||
|  | @ -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; | ||||
| }; | ||||
|  |  | |||
|  | @ -353,8 +353,8 @@ void GMainWindow::InitializeWidgets() { | |||
|     }); | ||||
| 
 | ||||
|     InputCommon::Init(); | ||||
|     multiplayer_state = new MultiplayerState(this, game_list->GetModel(), ui->action_Leave_Room, | ||||
|                                              ui->action_Show_Room); | ||||
|     multiplayer_state = new MultiplayerState(system, this, game_list->GetModel(), | ||||
|                                              ui->action_Leave_Room, ui->action_Show_Room); | ||||
|     multiplayer_state->setVisible(false); | ||||
| 
 | ||||
| #if ENABLE_QT_UPDATER | ||||
|  | @ -434,7 +434,7 @@ void GMainWindow::InitializeDebugWidgets() { | |||
|     debug_menu->addAction(microProfileDialog->toggleViewAction()); | ||||
| #endif | ||||
| 
 | ||||
|     registersWidget = new RegistersWidget(this); | ||||
|     registersWidget = new RegistersWidget(system, this); | ||||
|     addDockWidget(Qt::RightDockWidgetArea, registersWidget); | ||||
|     registersWidget->hide(); | ||||
|     debug_menu->addAction(registersWidget->toggleViewAction()); | ||||
|  | @ -448,7 +448,7 @@ void GMainWindow::InitializeDebugWidgets() { | |||
|     graphicsWidget->hide(); | ||||
|     debug_menu->addAction(graphicsWidget->toggleViewAction()); | ||||
| 
 | ||||
|     graphicsCommandsWidget = new GPUCommandListWidget(this); | ||||
|     graphicsCommandsWidget = new GPUCommandListWidget(system.Memory(), this); | ||||
|     addDockWidget(Qt::RightDockWidgetArea, graphicsCommandsWidget); | ||||
|     graphicsCommandsWidget->hide(); | ||||
|     debug_menu->addAction(graphicsCommandsWidget->toggleViewAction()); | ||||
|  | @ -472,7 +472,7 @@ void GMainWindow::InitializeDebugWidgets() { | |||
|     connect(this, &GMainWindow::EmulationStopping, graphicsTracingWidget, | ||||
|             &GraphicsTracingWidget::OnEmulationStopping); | ||||
| 
 | ||||
|     waitTreeWidget = new WaitTreeWidget(this); | ||||
|     waitTreeWidget = new WaitTreeWidget(system, this); | ||||
|     addDockWidget(Qt::LeftDockWidgetArea, waitTreeWidget); | ||||
|     waitTreeWidget->hide(); | ||||
|     debug_menu->addAction(waitTreeWidget->toggleViewAction()); | ||||
|  | @ -490,7 +490,7 @@ void GMainWindow::InitializeDebugWidgets() { | |||
|     connect(this, &GMainWindow::EmulationStopping, waitTreeWidget, | ||||
|             [this] { lleServiceModulesWidget->setDisabled(false); }); | ||||
| 
 | ||||
|     ipcRecorderWidget = new IPCRecorderWidget(this); | ||||
|     ipcRecorderWidget = new IPCRecorderWidget(system, this); | ||||
|     addDockWidget(Qt::RightDockWidgetArea, ipcRecorderWidget); | ||||
|     ipcRecorderWidget->hide(); | ||||
|     debug_menu->addAction(ipcRecorderWidget->toggleViewAction()); | ||||
|  | @ -2046,7 +2046,6 @@ void GMainWindow::OnLoadAmiibo() { | |||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     Core::System& system{Core::System::GetInstance()}; | ||||
|     Service::SM::ServiceManager& sm = system.ServiceManager(); | ||||
|     auto nfc = sm.GetService<Service::NFC::Module::Interface>("nfc:u"); | ||||
|     if (nfc == nullptr) { | ||||
|  | @ -2118,7 +2117,8 @@ void GMainWindow::OnToggleFilterBar() { | |||
| } | ||||
| 
 | ||||
| void GMainWindow::OnCreateGraphicsSurfaceViewer() { | ||||
|     auto graphicsSurfaceViewerWidget = new GraphicsSurfaceWidget(Pica::g_debug_context, this); | ||||
|     auto graphicsSurfaceViewerWidget = | ||||
|         new GraphicsSurfaceWidget(system.Memory(), Pica::g_debug_context, this); | ||||
|     addDockWidget(Qt::RightDockWidgetArea, graphicsSurfaceViewerWidget); | ||||
|     // TODO: Maybe graphicsSurfaceViewerWidget->setFloating(true);
 | ||||
|     graphicsSurfaceViewerWidget->show(); | ||||
|  |  | |||
|  | @ -9,10 +9,8 @@ | |||
| #include <QString> | ||||
| #include <QtConcurrent/QtConcurrentRun> | ||||
| #include "citra_qt/main.h" | ||||
| #include "citra_qt/multiplayer/client_room.h" | ||||
| #include "citra_qt/multiplayer/direct_connect.h" | ||||
| #include "citra_qt/multiplayer/message.h" | ||||
| #include "citra_qt/multiplayer/state.h" | ||||
| #include "citra_qt/multiplayer/validation.h" | ||||
| #include "citra_qt/uisettings.h" | ||||
| #include "core/hle/service/cfg/cfg.h" | ||||
|  | @ -22,9 +20,9 @@ | |||
| 
 | ||||
| enum class ConnectionType : u8 { TraversalServer, IP }; | ||||
| 
 | ||||
| DirectConnectWindow::DirectConnectWindow(QWidget* parent) | ||||
| DirectConnectWindow::DirectConnectWindow(Core::System& system_, QWidget* parent) | ||||
|     : QDialog(parent, Qt::WindowTitleHint | Qt::WindowCloseButtonHint | Qt::WindowSystemMenuHint), | ||||
|       ui(std::make_unique<Ui::DirectConnect>()) { | ||||
|       ui(std::make_unique<Ui::DirectConnect>()), system{system_} { | ||||
| 
 | ||||
|     ui->setupUi(this); | ||||
| 
 | ||||
|  | @ -91,7 +89,7 @@ void DirectConnectWindow::Connect() { | |||
|         if (auto room_member = Network::GetRoomMember().lock()) { | ||||
|             auto port = UISettings::values.port.toUInt(); | ||||
|             room_member->Join(ui->nickname->text().toStdString(), | ||||
|                               Service::CFG::GetConsoleIdHash(Core::System::GetInstance()), | ||||
|                               Service::CFG::GetConsoleIdHash(system), | ||||
|                               ui->ip->text().toStdString().c_str(), port, 0, | ||||
|                               Network::NoPreferredMac, ui->password->text().toStdString().c_str()); | ||||
|         } | ||||
|  |  | |||
|  | @ -13,11 +13,15 @@ namespace Ui { | |||
| class DirectConnect; | ||||
| } | ||||
| 
 | ||||
| namespace Core { | ||||
| class System; | ||||
| } | ||||
| 
 | ||||
| class DirectConnectWindow : public QDialog { | ||||
|     Q_OBJECT | ||||
| 
 | ||||
| public: | ||||
|     explicit DirectConnectWindow(QWidget* parent = nullptr); | ||||
|     explicit DirectConnectWindow(Core::System& system, QWidget* parent = nullptr); | ||||
|     ~DirectConnectWindow(); | ||||
| 
 | ||||
|     void RetranslateUi(); | ||||
|  | @ -39,5 +43,6 @@ private: | |||
| 
 | ||||
|     QFutureWatcher<void>* watcher; | ||||
|     std::unique_ptr<Ui::DirectConnect> ui; | ||||
|     Core::System& system; | ||||
|     Validation validation; | ||||
| }; | ||||
|  |  | |||
|  | @ -12,7 +12,6 @@ | |||
| #include <QTime> | ||||
| #include <QtConcurrent/QtConcurrentRun> | ||||
| #include "citra_qt/game_list_p.h" | ||||
| #include "citra_qt/main.h" | ||||
| #include "citra_qt/multiplayer/host_room.h" | ||||
| #include "citra_qt/multiplayer/message.h" | ||||
| #include "citra_qt/multiplayer/state.h" | ||||
|  | @ -27,10 +26,10 @@ | |||
| #include "web_service/verify_user_jwt.h" | ||||
| #endif | ||||
| 
 | ||||
| HostRoomWindow::HostRoomWindow(QWidget* parent, QStandardItemModel* list, | ||||
| HostRoomWindow::HostRoomWindow(Core::System& system_, QWidget* parent, QStandardItemModel* list, | ||||
|                                std::shared_ptr<Network::AnnounceMultiplayerSession> session) | ||||
|     : QDialog(parent, Qt::WindowTitleHint | Qt::WindowCloseButtonHint | Qt::WindowSystemMenuHint), | ||||
|       ui(std::make_unique<Ui::HostRoom>()), announce_multiplayer_session(session) { | ||||
|       ui(std::make_unique<Ui::HostRoom>()), system{system_}, announce_multiplayer_session(session) { | ||||
|     ui->setupUi(this); | ||||
| 
 | ||||
|     // set up validation for all of the fields
 | ||||
|  | @ -196,9 +195,8 @@ void HostRoomWindow::Host() { | |||
|             } | ||||
|         } | ||||
| #endif | ||||
|         member->Join(ui->username->text().toStdString(), | ||||
|                      Service::CFG::GetConsoleIdHash(Core::System::GetInstance()), "127.0.0.1", port, | ||||
|                      0, Network::NoPreferredMac, password, token); | ||||
|         member->Join(ui->username->text().toStdString(), Service::CFG::GetConsoleIdHash(system), | ||||
|                      "127.0.0.1", port, 0, Network::NoPreferredMac, password, token); | ||||
| 
 | ||||
|         // Store settings
 | ||||
|         UISettings::values.room_nickname = ui->username->text(); | ||||
|  |  | |||
|  | @ -9,14 +9,16 @@ | |||
| #include <QSortFilterProxyModel> | ||||
| #include <QStandardItemModel> | ||||
| #include <QVariant> | ||||
| #include "citra_qt/multiplayer/chat_room.h" | ||||
| #include "citra_qt/multiplayer/validation.h" | ||||
| #include "network/network.h" | ||||
| 
 | ||||
| namespace Ui { | ||||
| class HostRoom; | ||||
| } | ||||
| 
 | ||||
| namespace Core { | ||||
| class System; | ||||
| } | ||||
| 
 | ||||
| namespace Network { | ||||
| class AnnounceMultiplayerSession; | ||||
| } | ||||
|  | @ -34,7 +36,7 @@ class HostRoomWindow : public QDialog { | |||
|     Q_OBJECT | ||||
| 
 | ||||
| public: | ||||
|     explicit HostRoomWindow(QWidget* parent, QStandardItemModel* list, | ||||
|     explicit HostRoomWindow(Core::System& system, QWidget* parent, QStandardItemModel* list, | ||||
|                             std::shared_ptr<Network::AnnounceMultiplayerSession> session); | ||||
|     ~HostRoomWindow(); | ||||
| 
 | ||||
|  | @ -50,6 +52,7 @@ private: | |||
|     std::unique_ptr<Network::VerifyUser::Backend> CreateVerifyBackend(bool use_validation) const; | ||||
| 
 | ||||
|     std::unique_ptr<Ui::HostRoom> ui; | ||||
|     Core::System& system; | ||||
|     std::weak_ptr<Network::AnnounceMultiplayerSession> announce_multiplayer_session; | ||||
|     QStandardItemModel* game_list; | ||||
|     ComboBoxProxyModel* proxy; | ||||
|  |  | |||
|  | @ -7,11 +7,9 @@ | |||
| #include <QtConcurrent/QtConcurrentRun> | ||||
| #include "citra_qt/game_list_p.h" | ||||
| #include "citra_qt/main.h" | ||||
| #include "citra_qt/multiplayer/client_room.h" | ||||
| #include "citra_qt/multiplayer/lobby.h" | ||||
| #include "citra_qt/multiplayer/lobby_p.h" | ||||
| #include "citra_qt/multiplayer/message.h" | ||||
| #include "citra_qt/multiplayer/state.h" | ||||
| #include "citra_qt/multiplayer/validation.h" | ||||
| #include "citra_qt/uisettings.h" | ||||
| #include "common/logging/log.h" | ||||
|  | @ -23,10 +21,10 @@ | |||
| #include "web_service/web_backend.h" | ||||
| #endif | ||||
| 
 | ||||
| Lobby::Lobby(QWidget* parent, QStandardItemModel* list, | ||||
| Lobby::Lobby(Core::System& system_, QWidget* parent, QStandardItemModel* list, | ||||
|              std::shared_ptr<Network::AnnounceMultiplayerSession> session) | ||||
|     : QDialog(parent, Qt::WindowTitleHint | Qt::WindowCloseButtonHint | Qt::WindowSystemMenuHint), | ||||
|       ui(std::make_unique<Ui::Lobby>()), announce_multiplayer_session(session) { | ||||
|       ui(std::make_unique<Ui::Lobby>()), system{system_}, announce_multiplayer_session(session) { | ||||
|     ui->setupUi(this); | ||||
| 
 | ||||
|     // setup the watcher for background connections
 | ||||
|  | @ -152,8 +150,8 @@ void Lobby::OnJoinRoom(const QModelIndex& source) { | |||
|     const std::string verify_UID = | ||||
|         proxy->data(connection_index, LobbyItemHost::HostVerifyUIDRole).toString().toStdString(); | ||||
| 
 | ||||
|     // attempt to connect in a different thread
 | ||||
|     QFuture<void> f = QtConcurrent::run([nickname, ip, port, password, verify_UID] { | ||||
|     // Attempt to connect in a different thread
 | ||||
|     QFuture<void> f = QtConcurrent::run([this, nickname, ip, port, password, verify_UID] { | ||||
|         std::string token; | ||||
| #ifdef ENABLE_WEB_SERVICE | ||||
|         if (!NetSettings::values.citra_username.empty() && | ||||
|  | @ -170,8 +168,8 @@ void Lobby::OnJoinRoom(const QModelIndex& source) { | |||
|         } | ||||
| #endif | ||||
|         if (auto room_member = Network::GetRoomMember().lock()) { | ||||
|             room_member->Join(nickname, Service::CFG::GetConsoleIdHash(Core::System::GetInstance()), | ||||
|                               ip.c_str(), port, 0, Network::NoPreferredMac, password, token); | ||||
|             room_member->Join(nickname, Service::CFG::GetConsoleIdHash(system), ip.c_str(), port, 0, | ||||
|                               Network::NoPreferredMac, password, token); | ||||
|         } | ||||
|     }); | ||||
|     watcher->setFuture(f); | ||||
|  |  | |||
|  | @ -12,12 +12,16 @@ | |||
| #include "citra_qt/multiplayer/validation.h" | ||||
| #include "common/announce_multiplayer_room.h" | ||||
| #include "network/announce_multiplayer_session.h" | ||||
| #include "network/network.h" | ||||
| #include "network/room_member.h" | ||||
| 
 | ||||
| namespace Ui { | ||||
| class Lobby; | ||||
| } | ||||
| 
 | ||||
| namespace Core { | ||||
| class System; | ||||
| } | ||||
| 
 | ||||
| class LobbyModel; | ||||
| class LobbyFilterProxyModel; | ||||
| 
 | ||||
|  | @ -29,7 +33,7 @@ class Lobby : public QDialog { | |||
|     Q_OBJECT | ||||
| 
 | ||||
| public: | ||||
|     explicit Lobby(QWidget* parent, QStandardItemModel* list, | ||||
|     explicit Lobby(Core::System& system, QWidget* parent, QStandardItemModel* list, | ||||
|                    std::shared_ptr<Network::AnnounceMultiplayerSession> session); | ||||
|     ~Lobby() override; | ||||
| 
 | ||||
|  | @ -84,7 +88,9 @@ private: | |||
|      */ | ||||
|     QString PasswordPrompt(); | ||||
| 
 | ||||
| private: | ||||
|     std::unique_ptr<Ui::Lobby> ui; | ||||
|     Core::System& system; | ||||
| 
 | ||||
|     QStandardItemModel* model{}; | ||||
|     QStandardItemModel* game_list{}; | ||||
|  |  | |||
|  | @ -17,9 +17,10 @@ | |||
| #include "citra_qt/util/clickable_label.h" | ||||
| #include "common/logging/log.h" | ||||
| 
 | ||||
| MultiplayerState::MultiplayerState(QWidget* parent, QStandardItemModel* game_list_model, | ||||
|                                    QAction* leave_room, QAction* show_room) | ||||
|     : QWidget(parent), game_list_model(game_list_model), leave_room(leave_room), | ||||
| MultiplayerState::MultiplayerState(Core::System& system_, QWidget* parent, | ||||
|                                    QStandardItemModel* game_list_model, QAction* leave_room, | ||||
|                                    QAction* show_room) | ||||
|     : QWidget(parent), system{system_}, game_list_model(game_list_model), leave_room(leave_room), | ||||
|       show_room(show_room) { | ||||
|     if (auto member = Network::GetRoomMember().lock()) { | ||||
|         // register the network structs to use in slots and signals
 | ||||
|  | @ -203,14 +204,14 @@ static void BringWidgetToFront(QWidget* widget) { | |||
| 
 | ||||
| void MultiplayerState::OnViewLobby() { | ||||
|     if (lobby == nullptr) { | ||||
|         lobby = new Lobby(this, game_list_model, announce_multiplayer_session); | ||||
|         lobby = new Lobby(system, this, game_list_model, announce_multiplayer_session); | ||||
|     } | ||||
|     BringWidgetToFront(lobby); | ||||
| } | ||||
| 
 | ||||
| void MultiplayerState::OnCreateRoom() { | ||||
|     if (host_room == nullptr) { | ||||
|         host_room = new HostRoomWindow(this, game_list_model, announce_multiplayer_session); | ||||
|         host_room = new HostRoomWindow(system, this, game_list_model, announce_multiplayer_session); | ||||
|     } | ||||
|     BringWidgetToFront(host_room); | ||||
| } | ||||
|  | @ -274,7 +275,7 @@ void MultiplayerState::OnOpenNetworkRoom() { | |||
| 
 | ||||
| void MultiplayerState::OnDirectConnectToRoom() { | ||||
|     if (direct_connect == nullptr) { | ||||
|         direct_connect = new DirectConnectWindow(this); | ||||
|         direct_connect = new DirectConnectWindow(system, this); | ||||
|     } | ||||
|     BringWidgetToFront(direct_connect); | ||||
| } | ||||
|  |  | |||
|  | @ -15,12 +15,16 @@ class ClientRoomWindow; | |||
| class DirectConnectWindow; | ||||
| class ClickableLabel; | ||||
| 
 | ||||
| namespace Core { | ||||
| class System; | ||||
| } | ||||
| 
 | ||||
| class MultiplayerState : public QWidget { | ||||
|     Q_OBJECT; | ||||
| 
 | ||||
| public: | ||||
|     explicit MultiplayerState(QWidget* parent, QStandardItemModel* game_list, QAction* leave_room, | ||||
|                               QAction* show_room); | ||||
|     explicit MultiplayerState(Core::System& system, QWidget* parent, QStandardItemModel* game_list, | ||||
|                               QAction* leave_room, QAction* show_room); | ||||
|     ~MultiplayerState(); | ||||
| 
 | ||||
|     /**
 | ||||
|  | @ -71,6 +75,7 @@ signals: | |||
|     void AnnounceFailed(const Common::WebResult&); | ||||
| 
 | ||||
| private: | ||||
|     Core::System& system; | ||||
|     Lobby* lobby = nullptr; | ||||
|     HostRoomWindow* host_room = nullptr; | ||||
|     ClientRoomWindow* client_room = nullptr; | ||||
|  |  | |||
|  | @ -130,11 +130,9 @@ bool UpdaterPrivate::StartUpdateCheck() { | |||
|     main_process->setProgram(tool_info.absoluteFilePath()); | ||||
|     main_process->setArguments({QStringLiteral("--checkupdates"), QStringLiteral("-v")}); | ||||
| 
 | ||||
|     connect(main_process, | ||||
|             static_cast<void (QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished), this, | ||||
|     connect(main_process, qOverload<int, QProcess::ExitStatus>(&QProcess::finished), this, | ||||
|             &UpdaterPrivate::UpdaterReady, Qt::QueuedConnection); | ||||
|     connect(main_process, | ||||
|             static_cast<void (QProcess::*)(QProcess::ProcessError)>(&QProcess::errorOccurred), this, | ||||
|     connect(main_process, qOverload<QProcess::ProcessError>(&QProcess::errorOccurred), this, | ||||
|             &UpdaterPrivate::UpdaterError, Qt::QueuedConnection); | ||||
| 
 | ||||
|     main_process->start(QIODevice::ReadOnly); | ||||
|  | @ -156,7 +154,7 @@ void UpdaterPrivate::StopUpdateCheck(int delay, bool async) { | |||
|             QTimer* timer = new QTimer(this); | ||||
|             timer->setSingleShot(true); | ||||
| 
 | ||||
|             connect(timer, &QTimer::timeout, [this, timer]() { | ||||
|             connect(timer, &QTimer::timeout, this, [this, timer]() { | ||||
|                 StopUpdateCheck(0, false); | ||||
|                 timer->deleteLater(); | ||||
|             }); | ||||
|  |  | |||
|  | @ -86,7 +86,7 @@ System::ResultStatus System::RunLoop(bool tight_loop) { | |||
|         if (thread && running_core) { | ||||
|             running_core->SaveContext(thread->context); | ||||
|         } | ||||
|         GDBStub::HandlePacket(); | ||||
|         GDBStub::HandlePacket(*this); | ||||
| 
 | ||||
|         // If the loop is halted and we want to step, use a tiny (1) number of instructions to
 | ||||
|         // execute. Otherwise, get out of the loop function.
 | ||||
|  | @ -368,7 +368,7 @@ System::ResultStatus System::Init(Frontend::EmuWindow& emu_window, | |||
|                                   const Kernel::New3dsHwCapabilities& n3ds_hw_caps, u32 num_cores) { | ||||
|     LOG_DEBUG(HW_Memory, "initialized OK"); | ||||
| 
 | ||||
|     memory = std::make_unique<Memory::MemorySystem>(); | ||||
|     memory = std::make_unique<Memory::MemorySystem>(*this); | ||||
| 
 | ||||
|     timing = std::make_unique<Timing>(num_cores, Settings::values.cpu_clock_percentage.GetValue()); | ||||
| 
 | ||||
|  | @ -632,9 +632,9 @@ void System::ApplySettings() { | |||
| 
 | ||||
|     if (IsPoweredOn()) { | ||||
|         CoreTiming().UpdateClockSpeed(Settings::values.cpu_clock_percentage.GetValue()); | ||||
|         Core::DSP().SetSink(Settings::values.output_type.GetValue(), | ||||
|                             Settings::values.output_device.GetValue()); | ||||
|         Core::DSP().EnableStretching(Settings::values.enable_audio_stretching.GetValue()); | ||||
|         dsp_core->SetSink(Settings::values.output_type.GetValue(), | ||||
|                           Settings::values.output_device.GetValue()); | ||||
|         dsp_core->EnableStretching(Settings::values.enable_audio_stretching.GetValue()); | ||||
| 
 | ||||
|         auto hid = Service::HID::GetModule(*this); | ||||
|         if (hid) { | ||||
|  |  | |||
|  | @ -194,6 +194,10 @@ public: | |||
|         return *cpu_cores[core_id]; | ||||
|     }; | ||||
| 
 | ||||
|     [[nodiscard]] const ARM_Interface& GetCore(u32 core_id) const { | ||||
|         return *cpu_cores[core_id]; | ||||
|     }; | ||||
| 
 | ||||
|     [[nodiscard]] u32 GetNumCores() const { | ||||
|         return static_cast<u32>(cpu_cores.size()); | ||||
|     } | ||||
|  | @ -451,10 +455,6 @@ private: | |||
|     return System::GetInstance().GetNumCores(); | ||||
| } | ||||
| 
 | ||||
| [[nodiscard]] inline AudioCore::DspInterface& DSP() { | ||||
|     return System::GetInstance().DSP(); | ||||
| } | ||||
| 
 | ||||
| } // namespace Core
 | ||||
| 
 | ||||
| BOOST_CLASS_VERSION(Core::System, 1) | ||||
|  |  | |||
|  | @ -36,7 +36,6 @@ | |||
| #include "core/gdbstub/gdbstub.h" | ||||
| #include "core/gdbstub/hio.h" | ||||
| #include "core/hle/kernel/process.h" | ||||
| #include "core/loader/loader.h" | ||||
| #include "core/memory.h" | ||||
| 
 | ||||
| namespace GDBStub { | ||||
|  | @ -1035,7 +1034,7 @@ static void RemoveBreakpoint() { | |||
|     SendReply("OK"); | ||||
| } | ||||
| 
 | ||||
| void HandlePacket() { | ||||
| void HandlePacket(Core::System& system) { | ||||
|     if (!IsConnected()) { | ||||
|         if (defer_start) { | ||||
|             ToggleServer(true); | ||||
|  | @ -1076,7 +1075,7 @@ void HandlePacket() { | |||
|         Continue(); | ||||
|         return; | ||||
|     case 'F': | ||||
|         HandleHioReply(command_buffer, command_length); | ||||
|         HandleHioReply(system, command_buffer, command_length); | ||||
|         break; | ||||
|     case 'g': | ||||
|         ReadRegisters(); | ||||
|  |  | |||
|  | @ -10,6 +10,10 @@ | |||
| #include "common/common_types.h" | ||||
| #include "core/hle/kernel/thread.h" | ||||
| 
 | ||||
| namespace Core { | ||||
| class System; | ||||
| } | ||||
| 
 | ||||
| namespace GDBStub { | ||||
| 
 | ||||
| /// Breakpoint Method
 | ||||
|  | @ -70,7 +74,7 @@ void Break(bool is_memory_break = false); | |||
| bool IsMemoryBreak(); | ||||
| 
 | ||||
| /// Read and handle packet from gdb client.
 | ||||
| void HandlePacket(); | ||||
| void HandlePacket(Core::System& system); | ||||
| 
 | ||||
| /**
 | ||||
|  * Get the nearest breakpoint of the specified type at the given address. | ||||
|  |  | |||
|  | @ -54,7 +54,7 @@ static void SendErrorReply(int error_code, int retval = -1) { | |||
|     SendReply(packet.data()); | ||||
| } | ||||
| 
 | ||||
| void SetHioRequest(const VAddr addr) { | ||||
| void SetHioRequest(Core::System& system, const VAddr addr) { | ||||
|     if (!IsServerEnabled()) { | ||||
|         LOG_WARNING(Debug_GDBStub, "HIO requested but GDB stub is not running"); | ||||
|         return; | ||||
|  | @ -69,15 +69,15 @@ void SetHioRequest(const VAddr addr) { | |||
|         LOG_INFO(Debug_GDBStub, "overwriting existing HIO request that was not sent yet"); | ||||
|     } | ||||
| 
 | ||||
|     auto& memory = Core::System::GetInstance().Memory(); | ||||
|     const auto process = Core::System::GetInstance().Kernel().GetCurrentProcess(); | ||||
|     auto& memory = system.Memory(); | ||||
|     const auto process = system.Kernel().GetCurrentProcess(); | ||||
| 
 | ||||
|     if (!memory.IsValidVirtualAddress(*process, addr)) { | ||||
|         LOG_WARNING(Debug_GDBStub, "Invalid address for HIO request"); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     memory.ReadBlock(*process, addr, ¤t_hio_request, sizeof(PackedGdbHioRequest)); | ||||
|     memory.ReadBlock(addr, ¤t_hio_request, sizeof(PackedGdbHioRequest)); | ||||
| 
 | ||||
|     if (current_hio_request.magic != std::array{'G', 'D', 'B', '\0'}) { | ||||
|         std::string_view bad_magic{ | ||||
|  | @ -105,10 +105,11 @@ void SetHioRequest(const VAddr addr) { | |||
|     Break(); | ||||
|     SetCpuHaltFlag(true); | ||||
|     SetCpuStepFlag(false); | ||||
|     Core::GetRunningCore().ClearInstructionCache(); | ||||
|     system.GetRunningCore().ClearInstructionCache(); | ||||
| } | ||||
| 
 | ||||
| void HandleHioReply(const u8* const command_buffer, const u32 command_length) { | ||||
| void HandleHioReply(Core::System& system, const u8* const command_buffer, | ||||
|                     const u32 command_length) { | ||||
|     if (!IsWaitingForHioReply()) { | ||||
|         LOG_WARNING(Debug_GDBStub, "Got HIO reply but never sent a request"); | ||||
|         return; | ||||
|  | @ -176,8 +177,8 @@ void HandleHioReply(const u8* const command_buffer, const u32 command_length) { | |||
|               current_hio_request.retval, current_hio_request.gdb_errno, | ||||
|               current_hio_request.ctrl_c); | ||||
| 
 | ||||
|     const auto process = Core::System::GetInstance().Kernel().GetCurrentProcess(); | ||||
|     auto& memory = Core::System::GetInstance().Memory(); | ||||
|     const auto process = system.Kernel().GetCurrentProcess(); | ||||
|     auto& memory = system.Memory(); | ||||
| 
 | ||||
|     // should have been checked when we first initialized the request,
 | ||||
|     // but just double check again before we write to memory
 | ||||
|  | @ -187,8 +188,7 @@ void HandleHioReply(const u8* const command_buffer, const u32 command_length) { | |||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     memory.WriteBlock(*process, current_hio_request_addr, ¤t_hio_request, | ||||
|                       sizeof(PackedGdbHioRequest)); | ||||
|     memory.WriteBlock(current_hio_request_addr, ¤t_hio_request, sizeof(PackedGdbHioRequest)); | ||||
| 
 | ||||
|     current_hio_request = {}; | ||||
|     current_hio_request_addr = 0; | ||||
|  | @ -197,7 +197,7 @@ void HandleHioReply(const u8* const command_buffer, const u32 command_length) { | |||
|     // Restore state from before the request came in
 | ||||
|     SetCpuStepFlag(was_stepping); | ||||
|     SetCpuHaltFlag(was_halted); | ||||
|     Core::GetRunningCore().ClearInstructionCache(); | ||||
|     system.GetRunningCore().ClearInstructionCache(); | ||||
| } | ||||
| 
 | ||||
| bool HandlePendingHioRequestPacket() { | ||||
|  |  | |||
|  | @ -6,6 +6,10 @@ | |||
| 
 | ||||
| #include "common/common_types.h" | ||||
| 
 | ||||
| namespace Core { | ||||
| class System; | ||||
| } | ||||
| 
 | ||||
| namespace GDBStub { | ||||
| 
 | ||||
| /**
 | ||||
|  | @ -47,7 +51,7 @@ static_assert(sizeof(PackedGdbHioRequest) == 152, | |||
|  * | ||||
|  *  @param address The memory address of the \ref PackedGdbHioRequest. | ||||
|  */ | ||||
| void SetHioRequest(const VAddr address); | ||||
| void SetHioRequest(Core::System& system, const VAddr address); | ||||
| 
 | ||||
| /**
 | ||||
|  * If there is a pending HIO request, send it to the client. | ||||
|  | @ -59,6 +63,6 @@ bool HandlePendingHioRequestPacket(); | |||
| /**
 | ||||
|  * Process an HIO reply from the client. | ||||
|  */ | ||||
| void HandleHioReply(const u8* const command_buffer, const u32 command_length); | ||||
| void HandleHioReply(Core::System& system, const u8* const command_buffer, const u32 command_length); | ||||
| 
 | ||||
| } // namespace GDBStub
 | ||||
|  |  | |||
|  | @ -1128,7 +1128,7 @@ void SVC::OutputDebugString(VAddr address, s32 len) { | |||
|     } | ||||
| 
 | ||||
|     if (len == 0) { | ||||
|         GDBStub::SetHioRequest(address); | ||||
|         GDBStub::SetHioRequest(system, address); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|  | @ -1953,12 +1953,12 @@ ResultCode SVC::GetProcessList(s32* process_count, VAddr out_process_array, | |||
| } | ||||
| 
 | ||||
| ResultCode SVC::InvalidateInstructionCacheRange(u32 addr, u32 size) { | ||||
|     Core::GetRunningCore().InvalidateCacheRange(addr, size); | ||||
|     system.GetRunningCore().InvalidateCacheRange(addr, size); | ||||
|     return RESULT_SUCCESS; | ||||
| } | ||||
| 
 | ||||
| ResultCode SVC::InvalidateEntireInstructionCache() { | ||||
|     Core::GetRunningCore().ClearInstructionCache(); | ||||
|     system.GetRunningCore().ClearInstructionCache(); | ||||
|     return RESULT_SUCCESS; | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -17,9 +17,7 @@ | |||
| #include "core/arm/arm_interface.h" | ||||
| #include "core/core.h" | ||||
| #include "core/global.h" | ||||
| #include "core/hle/kernel/memory.h" | ||||
| #include "core/hle/kernel/process.h" | ||||
| #include "core/hle/lock.h" | ||||
| #include "core/hle/service/plgldr/plgldr.h" | ||||
| #include "core/hw/hw.h" | ||||
| #include "core/memory.h" | ||||
|  | @ -89,12 +87,13 @@ private: | |||
| 
 | ||||
| class MemorySystem::Impl { | ||||
| public: | ||||
|     // Visual Studio would try to allocate these on compile time if they are std::array, which would
 | ||||
|     // exceed the memory limit.
 | ||||
|     // Visual Studio would try to allocate these on compile time
 | ||||
|     // if they are std::array which would exceed the memory limit.
 | ||||
|     std::unique_ptr<u8[]> fcram = std::make_unique<u8[]>(Memory::FCRAM_N3DS_SIZE); | ||||
|     std::unique_ptr<u8[]> vram = std::make_unique<u8[]>(Memory::VRAM_SIZE); | ||||
|     std::unique_ptr<u8[]> n3ds_extra_ram = std::make_unique<u8[]>(Memory::N3DS_EXTRA_RAM_SIZE); | ||||
| 
 | ||||
|     Core::System& system; | ||||
|     std::shared_ptr<PageTable> current_page_table = nullptr; | ||||
|     RasterizerCacheMarker cache_marker; | ||||
|     std::vector<std::shared_ptr<PageTable>> page_table_list; | ||||
|  | @ -106,7 +105,7 @@ public: | |||
|     std::shared_ptr<BackingMem> n3ds_extra_ram_mem; | ||||
|     std::shared_ptr<BackingMem> dsp_mem; | ||||
| 
 | ||||
|     Impl(); | ||||
|     Impl(Core::System& system_); | ||||
| 
 | ||||
|     const u8* GetPtr(Region r) const { | ||||
|         switch (r) { | ||||
|  | @ -153,6 +152,10 @@ public: | |||
|         } | ||||
|     } | ||||
| 
 | ||||
|     u32 GetPC() const noexcept { | ||||
|         return system.GetRunningCore().GetPC(); | ||||
|     } | ||||
| 
 | ||||
|     /**
 | ||||
|      * This function should only be called for virtual addreses with attribute `PageType::Special`. | ||||
|      */ | ||||
|  | @ -187,7 +190,7 @@ public: | |||
|                     HW_Memory, | ||||
|                     "unmapped ReadBlock @ 0x{:08X} (start address = 0x{:08X}, size = {}) at PC " | ||||
|                     "0x{:08X}", | ||||
|                     current_vaddr, src_addr, size, Core::GetRunningCore().GetPC()); | ||||
|                     current_vaddr, src_addr, size, GetPC()); | ||||
|                 std::memset(dest_buffer, 0, copy_amount); | ||||
|                 break; | ||||
|             } | ||||
|  | @ -242,7 +245,7 @@ public: | |||
|                     HW_Memory, | ||||
|                     "unmapped WriteBlock @ 0x{:08X} (start address = 0x{:08X}, size = {}) at PC " | ||||
|                     "0x{:08X}", | ||||
|                     current_vaddr, dest_addr, size, Core::GetRunningCore().GetPC()); | ||||
|                     current_vaddr, dest_addr, size, GetPC()); | ||||
|                 break; | ||||
|             } | ||||
|             case PageType::Memory: { | ||||
|  | @ -345,13 +348,13 @@ private: | |||
|     friend class boost::serialization::access; | ||||
| }; | ||||
| 
 | ||||
| MemorySystem::Impl::Impl() | ||||
|     : fcram_mem(std::make_shared<BackingMemImpl<Region::FCRAM>>(*this)), | ||||
| MemorySystem::Impl::Impl(Core::System& system_) | ||||
|     : system{system_}, fcram_mem(std::make_shared<BackingMemImpl<Region::FCRAM>>(*this)), | ||||
|       vram_mem(std::make_shared<BackingMemImpl<Region::VRAM>>(*this)), | ||||
|       n3ds_extra_ram_mem(std::make_shared<BackingMemImpl<Region::N3DS>>(*this)), | ||||
|       dsp_mem(std::make_shared<BackingMemImpl<Region::DSP>>(*this)) {} | ||||
| 
 | ||||
| MemorySystem::MemorySystem() : impl(std::make_unique<Impl>()) {} | ||||
| MemorySystem::MemorySystem(Core::System& system) : impl(std::make_unique<Impl>(system)) {} | ||||
| MemorySystem::~MemorySystem() = default; | ||||
| 
 | ||||
| template <class Archive> | ||||
|  | @ -467,7 +470,7 @@ T MemorySystem::Read(const VAddr vaddr) { | |||
|     switch (type) { | ||||
|     case PageType::Unmapped: | ||||
|         LOG_ERROR(HW_Memory, "unmapped Read{} @ 0x{:08X} at PC 0x{:08X}", sizeof(T) * 8, vaddr, | ||||
|                   Core::GetRunningCore().GetPC()); | ||||
|                   impl->GetPC()); | ||||
|         return 0; | ||||
|     case PageType::Memory: | ||||
|         ASSERT_MSG(false, "Mapped memory page without a pointer @ {:08X}", vaddr); | ||||
|  | @ -518,7 +521,7 @@ void MemorySystem::Write(const VAddr vaddr, const T data) { | |||
|     switch (type) { | ||||
|     case PageType::Unmapped: | ||||
|         LOG_ERROR(HW_Memory, "unmapped Write{} 0x{:08X} @ 0x{:08X} at PC 0x{:08X}", | ||||
|                   sizeof(data) * 8, (u32)data, vaddr, Core::GetRunningCore().GetPC()); | ||||
|                   sizeof(data) * 8, (u32)data, vaddr, impl->GetPC()); | ||||
|         return; | ||||
|     case PageType::Memory: | ||||
|         ASSERT_MSG(false, "Mapped memory page without a pointer @ {:08X}", vaddr); | ||||
|  | @ -550,7 +553,7 @@ bool MemorySystem::WriteExclusive(const VAddr vaddr, const T data, const T expec | |||
|     switch (type) { | ||||
|     case PageType::Unmapped: | ||||
|         LOG_ERROR(HW_Memory, "unmapped Write{} 0x{:08X} @ 0x{:08X} at PC 0x{:08X}", | ||||
|                   sizeof(data) * 8, (u32)data, vaddr, Core::GetRunningCore().GetPC()); | ||||
|                   sizeof(data) * 8, static_cast<u32>(data), vaddr, impl->GetPC()); | ||||
|         return true; | ||||
|     case PageType::Memory: | ||||
|         ASSERT_MSG(false, "Mapped memory page without a pointer @ {:08X}", vaddr); | ||||
|  | @ -606,8 +609,7 @@ u8* MemorySystem::GetPointer(const VAddr vaddr) { | |||
|         return GetPointerForRasterizerCache(vaddr); | ||||
|     } | ||||
| 
 | ||||
|     LOG_ERROR(HW_Memory, "unknown GetPointer @ 0x{:08x} at PC 0x{:08X}", vaddr, | ||||
|               Core::GetRunningCore().GetPC()); | ||||
|     LOG_ERROR(HW_Memory, "unknown GetPointer @ 0x{:08x} at PC 0x{:08X}", vaddr, impl->GetPC()); | ||||
|     return nullptr; | ||||
| } | ||||
| 
 | ||||
|  | @ -663,7 +665,7 @@ MemoryRef MemorySystem::GetPhysicalRef(PAddr address) const { | |||
| 
 | ||||
|     if (area == memory_areas.end()) { | ||||
|         LOG_ERROR(HW_Memory, "Unknown GetPhysicalPointer @ {:#08X} at PC {:#08X}", address, | ||||
|                   Core::GetRunningCore().GetPC()); | ||||
|                   impl->GetPC()); | ||||
|         return nullptr; | ||||
|     } | ||||
| 
 | ||||
|  | @ -693,8 +695,7 @@ MemoryRef MemorySystem::GetPhysicalRef(PAddr address) const { | |||
|     return {target_mem, offset_into_region}; | ||||
| } | ||||
| 
 | ||||
| /// For a rasterizer-accessible PAddr, gets a list of all possible VAddr
 | ||||
| static std::vector<VAddr> PhysicalToVirtualAddressForRasterizer(PAddr addr) { | ||||
| std::vector<VAddr> MemorySystem::PhysicalToVirtualAddressForRasterizer(PAddr addr) { | ||||
|     if (addr >= VRAM_PADDR && addr < VRAM_PADDR_END) { | ||||
|         return {addr - VRAM_PADDR + VRAM_VADDR}; | ||||
|     } | ||||
|  | @ -714,7 +715,7 @@ static std::vector<VAddr> PhysicalToVirtualAddressForRasterizer(PAddr addr) { | |||
|     // parts of the texture.
 | ||||
|     LOG_ERROR(HW_Memory, | ||||
|               "Trying to use invalid physical address for rasterizer: {:08X} at PC 0x{:08X}", addr, | ||||
|               Core::GetRunningCore().GetPC()); | ||||
|               impl->GetPC()); | ||||
|     return {}; | ||||
| } | ||||
| 
 | ||||
|  | @ -729,7 +730,7 @@ void MemorySystem::RasterizerMarkRegionCached(PAddr start, u32 size, bool cached | |||
|     for (unsigned i = 0; i < num_pages; ++i, paddr += CITRA_PAGE_SIZE) { | ||||
|         for (VAddr vaddr : PhysicalToVirtualAddressForRasterizer(paddr)) { | ||||
|             impl->cache_marker.Mark(vaddr, cached); | ||||
|             for (auto page_table : impl->page_table_list) { | ||||
|             for (auto& page_table : impl->page_table_list) { | ||||
|                 PageType& page_type = page_table->attributes[vaddr >> CITRA_PAGE_BITS]; | ||||
| 
 | ||||
|                 if (cached) { | ||||
|  | @ -868,7 +869,7 @@ void MemorySystem::ReadBlock(const Kernel::Process& process, const VAddr src_add | |||
| } | ||||
| 
 | ||||
| void MemorySystem::ReadBlock(VAddr src_addr, void* dest_buffer, std::size_t size) { | ||||
|     const auto& process = *Core::System::GetInstance().Kernel().GetCurrentProcess(); | ||||
|     const auto& process = *impl->system.Kernel().GetCurrentProcess(); | ||||
|     return impl->ReadBlockImpl<false>(process, src_addr, dest_buffer, size); | ||||
| } | ||||
| 
 | ||||
|  | @ -911,7 +912,7 @@ void MemorySystem::WriteBlock(const Kernel::Process& process, const VAddr dest_a | |||
| 
 | ||||
| void MemorySystem::WriteBlock(const VAddr dest_addr, const void* src_buffer, | ||||
|                               const std::size_t size) { | ||||
|     auto& process = *Core::System::GetInstance().Kernel().GetCurrentProcess(); | ||||
|     auto& process = *impl->system.Kernel().GetCurrentProcess(); | ||||
|     return impl->WriteBlockImpl<false>(process, dest_addr, src_buffer, size); | ||||
| } | ||||
| 
 | ||||
|  | @ -934,7 +935,7 @@ void MemorySystem::ZeroBlock(const Kernel::Process& process, const VAddr dest_ad | |||
|             LOG_ERROR(HW_Memory, | ||||
|                       "unmapped ZeroBlock @ 0x{:08X} (start address = 0x{:08X}, size = {}) at PC " | ||||
|                       "0x{:08X}", | ||||
|                       current_vaddr, dest_addr, size, Core::GetRunningCore().GetPC()); | ||||
|                       current_vaddr, dest_addr, size, impl->GetPC()); | ||||
|             break; | ||||
|         } | ||||
|         case PageType::Memory: { | ||||
|  | @ -989,7 +990,7 @@ void MemorySystem::CopyBlock(const Kernel::Process& dest_process, | |||
|             LOG_ERROR(HW_Memory, | ||||
|                       "unmapped CopyBlock @ 0x{:08X} (start address = 0x{:08X}, size = {}) at PC " | ||||
|                       "0x{:08X}", | ||||
|                       current_vaddr, src_addr, size, Core::GetRunningCore().GetPC()); | ||||
|                       current_vaddr, src_addr, size, impl->GetPC()); | ||||
|             ZeroBlock(dest_process, dest_addr, copy_amount); | ||||
|             break; | ||||
|         } | ||||
|  |  | |||
|  | @ -18,6 +18,10 @@ namespace Kernel { | |||
| class Process; | ||||
| } | ||||
| 
 | ||||
| namespace Core { | ||||
| class System; | ||||
| } | ||||
| 
 | ||||
| namespace AudioCore { | ||||
| class DspInterface; | ||||
| } | ||||
|  | @ -287,7 +291,7 @@ void RasterizerFlushVirtualRegion(VAddr start, u32 size, FlushMode mode); | |||
| 
 | ||||
| class MemorySystem { | ||||
| public: | ||||
|     MemorySystem(); | ||||
|     explicit MemorySystem(Core::System& system); | ||||
|     ~MemorySystem(); | ||||
| 
 | ||||
|     /**
 | ||||
|  | @ -575,6 +579,9 @@ public: | |||
|      */ | ||||
|     void RasterizerMarkRegionCached(PAddr start, u32 size, bool cached); | ||||
| 
 | ||||
|     /// For a rasterizer-accessible PAddr, gets a list of all possible VAddr
 | ||||
|     std::vector<VAddr> PhysicalToVirtualAddressForRasterizer(PAddr addr); | ||||
| 
 | ||||
|     /// Gets a pointer to the memory region beginning at the specified physical address.
 | ||||
|     u8* GetPhysicalPointer(PAddr address) const; | ||||
| 
 | ||||
|  | @ -627,6 +634,7 @@ private: | |||
| 
 | ||||
|     void MapPages(PageTable& page_table, u32 base, u32 size, MemoryRef memory, PageType type); | ||||
| 
 | ||||
| private: | ||||
|     class Impl; | ||||
|     std::unique_ptr<Impl> impl; | ||||
| 
 | ||||
|  |  | |||
|  | @ -20,7 +20,8 @@ | |||
| #include "audio_fixures.h" | ||||
| 
 | ||||
| TEST_CASE("DSP HLE Audio Decoder", "[audio_core]") { | ||||
|     Memory::MemorySystem memory; | ||||
|     Core::System system; | ||||
|     Memory::MemorySystem memory{system}; | ||||
|     SECTION("decoder should produce correct samples") { | ||||
|         auto decoder = | ||||
| #ifdef HAVE_MF | ||||
|  |  | |||
|  | @ -8,14 +8,16 @@ | |||
| #include "audio_core/lle/lle.h" | ||||
| #include "common/common_paths.h" | ||||
| #include "common/file_util.h" | ||||
| #include "core/core.h" | ||||
| #include "core/core_timing.h" | ||||
| #include "core/memory.h" | ||||
| 
 | ||||
| TEST_CASE("DSP LLE vs HLE", "[audio_core][hle]") { | ||||
|     Memory::MemorySystem hle_memory; | ||||
|     Core::System system; | ||||
|     Memory::MemorySystem hle_memory{system}; | ||||
|     Core::Timing hle_core_timing(1, 100); | ||||
| 
 | ||||
|     Memory::MemorySystem lle_memory; | ||||
|     Memory::MemorySystem lle_memory{system}; | ||||
|     Core::Timing lle_core_timing(1, 100); | ||||
| 
 | ||||
|     AudioCore::DspHle hle(hle_memory, hle_core_timing); | ||||
|  |  | |||
|  | @ -7,11 +7,13 @@ | |||
| #include "audio_core/lle/lle.h" | ||||
| #include "common/common_paths.h" | ||||
| #include "common/file_util.h" | ||||
| #include "core/core.h" | ||||
| #include "core/core_timing.h" | ||||
| #include "core/memory.h" | ||||
| 
 | ||||
| TEST_CASE("DSP LLE Sanity", "[audio_core][lle]") { | ||||
|     Memory::MemorySystem memory; | ||||
|     Core::System system; | ||||
|     Memory::MemorySystem memory{system}; | ||||
|     Core::Timing core_timing(1, 100); | ||||
| 
 | ||||
|     AudioCore::DspLle lle(memory, core_timing, true); | ||||
|  |  | |||
|  | @ -16,7 +16,8 @@ TestEnvironment::TestEnvironment(bool mutable_memory_) | |||
|     : mutable_memory(mutable_memory_), test_memory(std::make_shared<TestMemory>(this)) { | ||||
| 
 | ||||
|     timing = std::make_unique<Core::Timing>(1, 100); | ||||
|     memory = std::make_unique<Memory::MemorySystem>(); | ||||
|     system = std::make_unique<Core::System>(); | ||||
|     memory = std::make_unique<Memory::MemorySystem>(*system); | ||||
|     kernel = std::make_unique<Kernel::KernelSystem>( | ||||
|         *memory, *timing, [] {}, Kernel::MemoryMode::Prod, 1, | ||||
|         Kernel::New3dsHwCapabilities{false, false, Kernel::New3dsMemoryMode::Legacy}); | ||||
|  |  | |||
|  | @ -85,6 +85,7 @@ private: | |||
|     std::vector<WriteRecord> write_records; | ||||
| 
 | ||||
|     std::unique_ptr<Core::Timing> timing; | ||||
|     std::unique_ptr<Core::System> system; | ||||
|     std::unique_ptr<Memory::MemorySystem> memory; | ||||
|     std::unique_ptr<Kernel::KernelSystem> kernel; | ||||
| }; | ||||
|  |  | |||
|  | @ -3,12 +3,10 @@ | |||
| // Refer to the license.txt file included.
 | ||||
| 
 | ||||
| #include <catch2/catch_test_macros.hpp> | ||||
| #include "common/archives.h" | ||||
| #include "core/core.h" | ||||
| #include "core/core_timing.h" | ||||
| #include "core/hle/ipc.h" | ||||
| #include "core/hle/kernel/client_port.h" | ||||
| #include "core/hle/kernel/client_session.h" | ||||
| #include "core/hle/kernel/event.h" | ||||
| #include "core/hle/kernel/handle_table.h" | ||||
| #include "core/hle/kernel/hle_ipc.h" | ||||
|  | @ -23,7 +21,8 @@ static std::shared_ptr<Object> MakeObject(Kernel::KernelSystem& kernel) { | |||
| 
 | ||||
| TEST_CASE("HLERequestContext::PopulateFromIncomingCommandBuffer", "[core][kernel]") { | ||||
|     Core::Timing timing(1, 100); | ||||
|     Memory::MemorySystem memory; | ||||
|     Core::System system; | ||||
|     Memory::MemorySystem memory{system}; | ||||
|     Kernel::KernelSystem kernel( | ||||
|         memory, timing, [] {}, Kernel::MemoryMode::Prod, 1, | ||||
|         Kernel::New3dsHwCapabilities{false, false, Kernel::New3dsMemoryMode::Legacy}); | ||||
|  | @ -247,7 +246,8 @@ TEST_CASE("HLERequestContext::PopulateFromIncomingCommandBuffer", "[core][kernel | |||
| 
 | ||||
| TEST_CASE("HLERequestContext::WriteToOutgoingCommandBuffer", "[core][kernel]") { | ||||
|     Core::Timing timing(1, 100); | ||||
|     Memory::MemorySystem memory; | ||||
|     Core::System system; | ||||
|     Memory::MemorySystem memory{system}; | ||||
|     Kernel::KernelSystem kernel( | ||||
|         memory, timing, [] {}, Kernel::MemoryMode::Prod, 1, | ||||
|         Kernel::New3dsHwCapabilities{false, false, Kernel::New3dsMemoryMode::Legacy}); | ||||
|  |  | |||
|  | @ -3,13 +3,15 @@ | |||
| // Refer to the license.txt file included.
 | ||||
| 
 | ||||
| #include <catch2/catch_test_macros.hpp> | ||||
| #include "core/core.h" | ||||
| #include "core/core_timing.h" | ||||
| #include "core/hle/kernel/process.h" | ||||
| #include "core/memory.h" | ||||
| 
 | ||||
| TEST_CASE("memory.IsValidVirtualAddress", "[core][memory]") { | ||||
|     Core::Timing timing(1, 100); | ||||
|     Memory::MemorySystem memory; | ||||
|     Core::System system; | ||||
|     Memory::MemorySystem memory{system}; | ||||
|     Kernel::KernelSystem kernel( | ||||
|         memory, timing, [] {}, Kernel::MemoryMode::Prod, 1, | ||||
|         Kernel::New3dsHwCapabilities{false, false, Kernel::New3dsMemoryMode::Legacy}); | ||||
|  |  | |||
|  | @ -4,9 +4,9 @@ | |||
| 
 | ||||
| #include <vector> | ||||
| #include <catch2/catch_test_macros.hpp> | ||||
| #include "core/core.h" | ||||
| #include "core/core_timing.h" | ||||
| #include "core/hle/kernel/errors.h" | ||||
| #include "core/hle/kernel/memory.h" | ||||
| #include "core/hle/kernel/process.h" | ||||
| #include "core/hle/kernel/vm_manager.h" | ||||
| #include "core/memory.h" | ||||
|  | @ -15,7 +15,8 @@ TEST_CASE("Memory Basics", "[kernel][memory]") { | |||
|     auto mem = std::make_shared<BufferMem>(Memory::CITRA_PAGE_SIZE); | ||||
|     MemoryRef block{mem}; | ||||
|     Core::Timing timing(1, 100); | ||||
|     Memory::MemorySystem memory; | ||||
|     Core::System system; | ||||
|     Memory::MemorySystem memory{system}; | ||||
|     Kernel::KernelSystem kernel( | ||||
|         memory, timing, [] {}, Kernel::MemoryMode::Prod, 1, | ||||
|         Kernel::New3dsHwCapabilities{false, false, Kernel::New3dsMemoryMode::Legacy}); | ||||
|  |  | |||
|  | @ -503,26 +503,27 @@ SurfaceId RasterizerCache<T>::GetTextureSurface(const Pica::Texture::TextureInfo | |||
|     const u32 min_width = info.width >> max_level; | ||||
|     const u32 min_height = info.height >> max_level; | ||||
|     if (min_width % 8 != 0 || min_height % 8 != 0) { | ||||
|         if (min_width % 4 == 0 && min_height % 4 == 0) { | ||||
|             const auto [src_surface_id, rect] = GetSurfaceSubRect(params, ScaleMatch::Ignore, true); | ||||
|             Surface& src_surface = slot_surfaces[src_surface_id]; | ||||
| 
 | ||||
|             params.res_scale = src_surface.res_scale; | ||||
|             SurfaceId tmp_surface_id = CreateSurface(params); | ||||
|             Surface& tmp_surface = slot_surfaces[tmp_surface_id]; | ||||
| 
 | ||||
|             const TextureBlit blit = { | ||||
|                 .src_level = src_surface.LevelOf(params.addr), | ||||
|                 .dst_level = 0, | ||||
|                 .src_rect = rect, | ||||
|                 .dst_rect = tmp_surface.GetScaledRect(), | ||||
|             }; | ||||
|             runtime.BlitTextures(src_surface, tmp_surface, blit); | ||||
|             return tmp_surface_id; | ||||
|         if (min_width % 4 != 0 || min_height % 4 != 0) { | ||||
|             LOG_CRITICAL(HW_GPU, "Texture size ({}x{}) is not multiple of 4", min_width, | ||||
|                          min_height); | ||||
|             return NULL_SURFACE_ID; | ||||
|         } | ||||
|         const auto [src_surface_id, rect] = GetSurfaceSubRect(params, ScaleMatch::Ignore, true); | ||||
|         Surface& src_surface = slot_surfaces[src_surface_id]; | ||||
| 
 | ||||
|         LOG_CRITICAL(HW_GPU, "Texture size ({}x{}) is not multiple of 4", min_width, min_height); | ||||
|         return NULL_SURFACE_ID; | ||||
|         params.res_scale = src_surface.res_scale; | ||||
|         SurfaceId tmp_surface_id = CreateSurface(params); | ||||
|         Surface& tmp_surface = slot_surfaces[tmp_surface_id]; | ||||
|         sentenced.emplace_back(tmp_surface_id, frame_tick); | ||||
| 
 | ||||
|         const TextureBlit blit = { | ||||
|             .src_level = src_surface.LevelOf(params.addr), | ||||
|             .dst_level = 0, | ||||
|             .src_rect = rect, | ||||
|             .dst_rect = tmp_surface.GetScaledRect(), | ||||
|         }; | ||||
|         runtime.BlitTextures(src_surface, tmp_surface, blit); | ||||
|         return tmp_surface_id; | ||||
|     } | ||||
|     if (info.width != (min_width << max_level) || info.height != (min_height << max_level)) { | ||||
|         LOG_CRITICAL(HW_GPU, "Texture size ({}x{}) does not support required mipmap level ({})", | ||||
|  | @ -1054,8 +1055,9 @@ bool RasterizerCache<T>::UploadCustomSurface(SurfaceId surface_id, SurfaceInterv | |||
|         ASSERT_MSG(True(surface.flags & SurfaceFlagBits::Custom), | ||||
|                    "Surface is not suitable for custom upload, aborting!"); | ||||
|         if (!surface.IsCustom()) { | ||||
|             const SurfaceBase old_surface{surface}; | ||||
|             const SurfaceId old_id = | ||||
|                 slot_surfaces.swap_and_insert(surface_id, runtime, surface, material); | ||||
|                 slot_surfaces.swap_and_insert(surface_id, runtime, old_surface, material); | ||||
|             sentenced.emplace_back(old_id, frame_tick); | ||||
|         } | ||||
|         surface.UploadCustom(material, level); | ||||
|  |  | |||
|  | @ -105,7 +105,7 @@ SurfaceInterval SurfaceBase::GetCopyableInterval(const SurfaceParams& params) co | |||
|     return result; | ||||
| } | ||||
| 
 | ||||
| Extent SurfaceBase::RealExtent(bool scaled) { | ||||
| Extent SurfaceBase::RealExtent(bool scaled) const { | ||||
|     const bool is_custom = IsCustom(); | ||||
|     u32 real_width = width; | ||||
|     u32 real_height = height; | ||||
|  |  | |||
|  | @ -41,7 +41,7 @@ public: | |||
|     ClearValue MakeClearValue(PAddr copy_addr, PixelFormat dst_format); | ||||
| 
 | ||||
|     /// Returns the internal surface extent.
 | ||||
|     Extent RealExtent(bool scaled = true); | ||||
|     Extent RealExtent(bool scaled = true) const; | ||||
| 
 | ||||
|     /// Returns true if the surface contains a custom material with a normal map.
 | ||||
|     bool HasNormalMap() const noexcept; | ||||
|  |  | |||
|  | @ -73,12 +73,12 @@ public: | |||
|         return height * res_scale; | ||||
|     } | ||||
| 
 | ||||
|     [[nodiscard]] Common::Rectangle<u32> GetRect() const noexcept { | ||||
|         return {0, height, width, 0}; | ||||
|     [[nodiscard]] Common::Rectangle<u32> GetRect(u32 level = 0) const noexcept { | ||||
|         return {0, height >> level, width >> level, 0}; | ||||
|     } | ||||
| 
 | ||||
|     [[nodiscard]] Common::Rectangle<u32> GetScaledRect() const noexcept { | ||||
|         return {0, GetScaledHeight(), GetScaledWidth(), 0}; | ||||
|     [[nodiscard]] Common::Rectangle<u32> GetScaledRect(u32 level = 0) const noexcept { | ||||
|         return {0, GetScaledHeight() >> level, GetScaledWidth() >> level, 0}; | ||||
|     } | ||||
| 
 | ||||
|     [[nodiscard]] u32 PixelsInBytes(u32 size) const noexcept { | ||||
|  |  | |||
|  | @ -9,10 +9,6 @@ | |||
| #include "common/common_types.h" | ||||
| #include "core/hw/gpu.h" | ||||
| 
 | ||||
| namespace OpenGL { | ||||
| struct ScreenInfo; | ||||
| } | ||||
| 
 | ||||
| namespace Pica::Shader { | ||||
| struct OutputVertex; | ||||
| } // namespace Pica::Shader
 | ||||
|  | @ -76,14 +72,6 @@ public: | |||
|         return false; | ||||
|     } | ||||
| 
 | ||||
|     /// Attempt to use a faster method to display the framebuffer to screen
 | ||||
|     virtual bool AccelerateDisplay([[maybe_unused]] const GPU::Regs::FramebufferConfig& config, | ||||
|                                    [[maybe_unused]] PAddr framebuffer_addr, | ||||
|                                    [[maybe_unused]] u32 pixel_stride, | ||||
|                                    [[maybe_unused]] OpenGL::ScreenInfo& screen_info) { | ||||
|         return false; | ||||
|     } | ||||
| 
 | ||||
|     /// Attempt to draw using hardware shaders
 | ||||
|     virtual bool AccelerateDrawBatch([[maybe_unused]] bool is_indexed) { | ||||
|         return false; | ||||
|  |  | |||
|  | @ -42,7 +42,7 @@ public: | |||
|     virtual ~RendererBase(); | ||||
| 
 | ||||
|     /// Returns the rasterizer owned by the renderer
 | ||||
|     virtual VideoCore::RasterizerInterface* Rasterizer() const = 0; | ||||
|     virtual VideoCore::RasterizerInterface* Rasterizer() = 0; | ||||
| 
 | ||||
|     /// Finalize rendering the guest frame and draw into the presentation texture
 | ||||
|     virtual void SwapBuffers() = 0; | ||||
|  | @ -72,9 +72,6 @@ public: | |||
|     /// Ends the current frame
 | ||||
|     void EndFrame(); | ||||
| 
 | ||||
|     // Getter/setter functions:
 | ||||
|     // ------------------------
 | ||||
| 
 | ||||
|     f32 GetCurrentFPS() const { | ||||
|         return current_fps; | ||||
|     } | ||||
|  |  | |||
|  | @ -12,9 +12,9 @@ | |||
| #include "video_core/regs_rasterizer.h" | ||||
| #include "video_core/renderer_opengl/gl_rasterizer.h" | ||||
| #include "video_core/renderer_opengl/gl_shader_gen.h" | ||||
| #include "video_core/renderer_opengl/gl_vars.h" | ||||
| #include "video_core/renderer_opengl/pica_to_gl.h" | ||||
| #include "video_core/renderer_opengl/renderer_opengl.h" | ||||
| #include "video_core/texture/texture_decode.h" | ||||
| #include "video_core/video_core.h" | ||||
| 
 | ||||
| namespace OpenGL { | ||||
|  | @ -76,8 +76,9 @@ GLenum MakeAttributeType(Pica::PipelineRegs::VertexAttributeFormat format) { | |||
| RasterizerOpenGL::RasterizerOpenGL(Memory::MemorySystem& memory, | ||||
|                                    VideoCore::CustomTexManager& custom_tex_manager, | ||||
|                                    VideoCore::RendererBase& renderer, Driver& driver_) | ||||
|     : VideoCore::RasterizerAccelerated{memory}, driver{driver_}, runtime{driver, renderer}, | ||||
|       res_cache{memory, custom_tex_manager, runtime, regs, renderer}, | ||||
|     : VideoCore::RasterizerAccelerated{memory}, driver{driver_}, | ||||
|       shader_manager{renderer.GetRenderWindow(), driver, !driver.IsOpenGLES()}, | ||||
|       runtime{driver, renderer}, res_cache{memory, custom_tex_manager, runtime, regs, renderer}, | ||||
|       texture_buffer_size{TextureBufferSize()}, vertex_buffer{driver, GL_ARRAY_BUFFER, | ||||
|                                                               VERTEX_BUFFER_SIZE}, | ||||
|       uniform_buffer{driver, GL_UNIFORM_BUFFER, UNIFORM_BUFFER_SIZE}, | ||||
|  | @ -89,14 +90,6 @@ RasterizerOpenGL::RasterizerOpenGL(Memory::MemorySystem& memory, | |||
|     // Clipping plane 0 is always enabled for PICA fixed clip plane z <= 0
 | ||||
|     state.clip_distance[0] = true; | ||||
| 
 | ||||
|     // Create a 1x1 clear texture to use in the NULL case,
 | ||||
|     // instead of OpenGL's default of solid black
 | ||||
|     glGenTextures(1, &default_texture); | ||||
|     glBindTexture(GL_TEXTURE_2D, default_texture); | ||||
|     // For some reason alpha 0 wraps around to 1.0, so use 1/255 instead
 | ||||
|     u8 framebuffer_data[4] = {0, 0, 0, 1}; | ||||
|     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, framebuffer_data); | ||||
| 
 | ||||
|     // Generate VAO
 | ||||
|     sw_vao.Create(); | ||||
|     hw_vao.Create(); | ||||
|  | @ -142,9 +135,6 @@ RasterizerOpenGL::RasterizerOpenGL(Memory::MemorySystem& memory, | |||
|                           (GLvoid*)offsetof(HardwareVertex, view)); | ||||
|     glEnableVertexAttribArray(ATTRIBUTE_VIEW); | ||||
| 
 | ||||
|     // Create render framebuffer
 | ||||
|     framebuffer.Create(); | ||||
| 
 | ||||
|     // Allocate and bind texture buffer lut textures
 | ||||
|     texture_buffer_lut_lf.Create(); | ||||
|     texture_buffer_lut_rg.Create(); | ||||
|  | @ -165,9 +155,6 @@ RasterizerOpenGL::RasterizerOpenGL(Memory::MemorySystem& memory, | |||
|     state.Apply(); | ||||
|     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer.GetHandle()); | ||||
| 
 | ||||
|     shader_program_manager = | ||||
|         std::make_unique<ShaderProgramManager>(renderer.GetRenderWindow(), driver, !GLES); | ||||
| 
 | ||||
|     glEnable(GL_BLEND); | ||||
| 
 | ||||
|     SyncEntireState(); | ||||
|  | @ -181,7 +168,7 @@ void RasterizerOpenGL::TickFrame() { | |||
| 
 | ||||
| void RasterizerOpenGL::LoadDiskResources(const std::atomic_bool& stop_loading, | ||||
|                                          const VideoCore::DiskResourceLoadCallback& callback) { | ||||
|     shader_program_manager->LoadDiskCache(stop_loading, callback); | ||||
|     shader_manager.LoadDiskCache(stop_loading, callback); | ||||
| } | ||||
| 
 | ||||
| void RasterizerOpenGL::SyncFixedState() { | ||||
|  | @ -277,7 +264,7 @@ void RasterizerOpenGL::SetupVertexArray(u8* array_ptr, GLintptr buffer_offset, | |||
| 
 | ||||
| bool RasterizerOpenGL::SetupVertexShader() { | ||||
|     MICROPROFILE_SCOPE(OpenGL_VS); | ||||
|     return shader_program_manager->UseProgrammableVertexShader(regs, Pica::g_state.vs); | ||||
|     return shader_manager.UseProgrammableVertexShader(regs, Pica::g_state.vs); | ||||
| } | ||||
| 
 | ||||
| bool RasterizerOpenGL::SetupGeometryShader() { | ||||
|  | @ -288,7 +275,7 @@ bool RasterizerOpenGL::SetupGeometryShader() { | |||
|         return false; | ||||
|     } | ||||
| 
 | ||||
|     shader_program_manager->UseFixedGeometryShader(regs); | ||||
|     shader_manager.UseFixedGeometryShader(regs); | ||||
|     return true; | ||||
| } | ||||
| 
 | ||||
|  | @ -302,11 +289,13 @@ bool RasterizerOpenGL::AccelerateDrawBatch(bool is_indexed) { | |||
|         } | ||||
|     } | ||||
| 
 | ||||
|     if (!SetupVertexShader()) | ||||
|     if (!SetupVertexShader()) { | ||||
|         return false; | ||||
|     } | ||||
| 
 | ||||
|     if (!SetupGeometryShader()) | ||||
|     if (!SetupGeometryShader()) { | ||||
|         return false; | ||||
|     } | ||||
| 
 | ||||
|     return Draw(true, is_indexed); | ||||
| } | ||||
|  | @ -329,7 +318,7 @@ bool RasterizerOpenGL::AccelerateDrawBatchInternal(bool is_indexed) { | |||
|     SetupVertexArray(buffer_ptr, buffer_offset, vs_input_index_min, vs_input_index_max); | ||||
|     vertex_buffer.Unmap(vs_input_size); | ||||
| 
 | ||||
|     shader_program_manager->ApplyTo(state); | ||||
|     shader_manager.ApplyTo(state); | ||||
|     state.Apply(); | ||||
| 
 | ||||
|     if (is_indexed) { | ||||
|  | @ -341,9 +330,9 @@ bool RasterizerOpenGL::AccelerateDrawBatchInternal(bool is_indexed) { | |||
|             return false; | ||||
|         } | ||||
| 
 | ||||
|         const u8* index_data = VideoCore::g_memory->GetPhysicalPointer( | ||||
|             regs.pipeline.vertex_attributes.GetPhysicalBaseAddress() + | ||||
|             regs.pipeline.index_array.offset); | ||||
|         const u8* index_data = | ||||
|             memory.GetPhysicalPointer(regs.pipeline.vertex_attributes.GetPhysicalBaseAddress() + | ||||
|                                       regs.pipeline.index_array.offset); | ||||
|         std::tie(buffer_ptr, buffer_offset, std::ignore) = index_buffer.Map(index_buffer_size, 4); | ||||
|         std::memcpy(buffer_ptr, index_data, index_buffer_size); | ||||
|         index_buffer.Unmap(index_buffer_size); | ||||
|  | @ -434,7 +423,7 @@ bool RasterizerOpenGL::Draw(bool accelerate, bool is_indexed) { | |||
| 
 | ||||
|     // Sync and bind the shader
 | ||||
|     if (shader_dirty) { | ||||
|         shader_program_manager->UseFragmentShader(regs, use_custom_normal); | ||||
|         shader_manager.UseFragmentShader(regs, use_custom_normal); | ||||
|         shader_dirty = false; | ||||
|     } | ||||
| 
 | ||||
|  | @ -452,9 +441,9 @@ bool RasterizerOpenGL::Draw(bool accelerate, bool is_indexed) { | |||
|     } else { | ||||
|         state.draw.vertex_array = sw_vao.handle; | ||||
|         state.draw.vertex_buffer = vertex_buffer.GetHandle(); | ||||
|         shader_program_manager->UseTrivialVertexShader(); | ||||
|         shader_program_manager->UseTrivialGeometryShader(); | ||||
|         shader_program_manager->ApplyTo(state); | ||||
|         shader_manager.UseTrivialVertexShader(); | ||||
|         shader_manager.UseTrivialGeometryShader(); | ||||
|         shader_manager.ApplyTo(state); | ||||
|         state.Apply(); | ||||
| 
 | ||||
|         std::size_t max_vertices = 3 * (VERTEX_BUFFER_SIZE / (3 * sizeof(HardwareVertex))); | ||||
|  | @ -820,7 +809,7 @@ void RasterizerOpenGL::SyncBlendColor() { | |||
| void RasterizerOpenGL::SyncLogicOp() { | ||||
|     state.logic_op = PicaToGL::LogicOp(regs.framebuffer.output_merger.logic_op); | ||||
| 
 | ||||
|     if (GLES) { | ||||
|     if (driver.IsOpenGLES()) { | ||||
|         if (!regs.framebuffer.output_merger.alphablend_enable) { | ||||
|             if (regs.framebuffer.output_merger.logic_op == Pica::FramebufferRegs::LogicOp::NoOp) { | ||||
|                 // Color output is disabled by logic operation. We use color write mask to skip
 | ||||
|  | @ -832,7 +821,7 @@ void RasterizerOpenGL::SyncLogicOp() { | |||
| } | ||||
| 
 | ||||
| void RasterizerOpenGL::SyncColorWriteMask() { | ||||
|     if (GLES) { | ||||
|     if (driver.IsOpenGLES()) { | ||||
|         if (!regs.framebuffer.output_merger.alphablend_enable) { | ||||
|             if (regs.framebuffer.output_merger.logic_op == Pica::FramebufferRegs::LogicOp::NoOp) { | ||||
|                 // Color output is disabled by logic operation. We use color write mask to skip
 | ||||
|  | @ -842,17 +831,19 @@ void RasterizerOpenGL::SyncColorWriteMask() { | |||
|         } | ||||
|     } | ||||
| 
 | ||||
|     auto IsColorWriteEnabled = [&](u32 value) { | ||||
|     auto is_color_write_enabled = [&](u32 value) { | ||||
|         return (regs.framebuffer.framebuffer.allow_color_write != 0 && value != 0) ? GL_TRUE | ||||
|                                                                                    : GL_FALSE; | ||||
|     }; | ||||
| 
 | ||||
|     state.color_mask.red_enabled = IsColorWriteEnabled(regs.framebuffer.output_merger.red_enable); | ||||
|     state.color_mask.red_enabled = | ||||
|         is_color_write_enabled(regs.framebuffer.output_merger.red_enable); | ||||
|     state.color_mask.green_enabled = | ||||
|         IsColorWriteEnabled(regs.framebuffer.output_merger.green_enable); | ||||
|     state.color_mask.blue_enabled = IsColorWriteEnabled(regs.framebuffer.output_merger.blue_enable); | ||||
|         is_color_write_enabled(regs.framebuffer.output_merger.green_enable); | ||||
|     state.color_mask.blue_enabled = | ||||
|         is_color_write_enabled(regs.framebuffer.output_merger.blue_enable); | ||||
|     state.color_mask.alpha_enabled = | ||||
|         IsColorWriteEnabled(regs.framebuffer.output_merger.alpha_enable); | ||||
|         is_color_write_enabled(regs.framebuffer.output_merger.alpha_enable); | ||||
| } | ||||
| 
 | ||||
| void RasterizerOpenGL::SyncStencilWriteMask() { | ||||
|  | @ -903,12 +894,10 @@ void RasterizerOpenGL::SyncAndUploadLUTsLF() { | |||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     u8* buffer; | ||||
|     GLintptr offset; | ||||
|     bool invalidate; | ||||
|     std::size_t bytes_used = 0; | ||||
|     glBindBuffer(GL_TEXTURE_BUFFER, texture_lf_buffer.GetHandle()); | ||||
|     std::tie(buffer, offset, invalidate) = texture_lf_buffer.Map(max_size, sizeof(Common::Vec4f)); | ||||
|     const auto [buffer, offset, invalidate] = | ||||
|         texture_lf_buffer.Map(max_size, sizeof(Common::Vec4f)); | ||||
| 
 | ||||
|     // Sync the lighting luts
 | ||||
|     if (uniform_block_data.lighting_lut_dirty_any || invalidate) { | ||||
|  | @ -973,50 +962,48 @@ void RasterizerOpenGL::SyncAndUploadLUTs() { | |||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     u8* buffer; | ||||
|     GLintptr offset; | ||||
|     bool invalidate; | ||||
|     std::size_t bytes_used = 0; | ||||
|     glBindBuffer(GL_TEXTURE_BUFFER, texture_buffer.GetHandle()); | ||||
|     std::tie(buffer, offset, invalidate) = texture_buffer.Map(max_size, sizeof(Common::Vec4f)); | ||||
|     const auto [buffer, offset, invalidate] = texture_buffer.Map(max_size, sizeof(Common::Vec4f)); | ||||
| 
 | ||||
|     // helper function for SyncProcTexNoiseLUT/ColorMap/AlphaMap
 | ||||
|     auto SyncProcTexValueLUT = [this, buffer, offset, invalidate, &bytes_used]( | ||||
|                                    const std::array<Pica::State::ProcTex::ValueEntry, 128>& lut, | ||||
|                                    std::array<Common::Vec2f, 128>& lut_data, GLint& lut_offset) { | ||||
|         std::array<Common::Vec2f, 128> new_data; | ||||
|         std::transform(lut.begin(), lut.end(), new_data.begin(), [](const auto& entry) { | ||||
|             return Common::Vec2f{entry.ToFloat(), entry.DiffToFloat()}; | ||||
|         }); | ||||
|     const auto sync_proc_tex_value_lut = | ||||
|         [this, buffer = buffer, offset = offset, invalidate = invalidate, | ||||
|          &bytes_used](const std::array<Pica::State::ProcTex::ValueEntry, 128>& lut, | ||||
|                       std::array<Common::Vec2f, 128>& lut_data, GLint& lut_offset) { | ||||
|             std::array<Common::Vec2f, 128> new_data; | ||||
|             std::transform(lut.begin(), lut.end(), new_data.begin(), [](const auto& entry) { | ||||
|                 return Common::Vec2f{entry.ToFloat(), entry.DiffToFloat()}; | ||||
|             }); | ||||
| 
 | ||||
|         if (new_data != lut_data || invalidate) { | ||||
|             lut_data = new_data; | ||||
|             std::memcpy(buffer + bytes_used, new_data.data(), | ||||
|                         new_data.size() * sizeof(Common::Vec2f)); | ||||
|             lut_offset = static_cast<GLint>((offset + bytes_used) / sizeof(Common::Vec2f)); | ||||
|             uniform_block_data.dirty = true; | ||||
|             bytes_used += new_data.size() * sizeof(Common::Vec2f); | ||||
|         } | ||||
|     }; | ||||
|             if (new_data != lut_data || invalidate) { | ||||
|                 lut_data = new_data; | ||||
|                 std::memcpy(buffer + bytes_used, new_data.data(), | ||||
|                             new_data.size() * sizeof(Common::Vec2f)); | ||||
|                 lut_offset = static_cast<GLint>((offset + bytes_used) / sizeof(Common::Vec2f)); | ||||
|                 uniform_block_data.dirty = true; | ||||
|                 bytes_used += new_data.size() * sizeof(Common::Vec2f); | ||||
|             } | ||||
|         }; | ||||
| 
 | ||||
|     // Sync the proctex noise lut
 | ||||
|     if (uniform_block_data.proctex_noise_lut_dirty || invalidate) { | ||||
|         SyncProcTexValueLUT(Pica::g_state.proctex.noise_table, proctex_noise_lut_data, | ||||
|                             uniform_block_data.data.proctex_noise_lut_offset); | ||||
|         sync_proc_tex_value_lut(Pica::g_state.proctex.noise_table, proctex_noise_lut_data, | ||||
|                                 uniform_block_data.data.proctex_noise_lut_offset); | ||||
|         uniform_block_data.proctex_noise_lut_dirty = false; | ||||
|     } | ||||
| 
 | ||||
|     // Sync the proctex color map
 | ||||
|     if (uniform_block_data.proctex_color_map_dirty || invalidate) { | ||||
|         SyncProcTexValueLUT(Pica::g_state.proctex.color_map_table, proctex_color_map_data, | ||||
|                             uniform_block_data.data.proctex_color_map_offset); | ||||
|         sync_proc_tex_value_lut(Pica::g_state.proctex.color_map_table, proctex_color_map_data, | ||||
|                                 uniform_block_data.data.proctex_color_map_offset); | ||||
|         uniform_block_data.proctex_color_map_dirty = false; | ||||
|     } | ||||
| 
 | ||||
|     // Sync the proctex alpha map
 | ||||
|     if (uniform_block_data.proctex_alpha_map_dirty || invalidate) { | ||||
|         SyncProcTexValueLUT(Pica::g_state.proctex.alpha_map_table, proctex_alpha_map_data, | ||||
|                             uniform_block_data.data.proctex_alpha_map_offset); | ||||
|         sync_proc_tex_value_lut(Pica::g_state.proctex.alpha_map_table, proctex_alpha_map_data, | ||||
|                                 uniform_block_data.data.proctex_alpha_map_offset); | ||||
|         uniform_block_data.proctex_alpha_map_dirty = false; | ||||
|     } | ||||
| 
 | ||||
|  | @ -1070,28 +1057,25 @@ void RasterizerOpenGL::SyncAndUploadLUTs() { | |||
| } | ||||
| 
 | ||||
| void RasterizerOpenGL::UploadUniforms(bool accelerate_draw) { | ||||
|     // glBindBufferRange below also changes the generic buffer binding point, so we sync the state
 | ||||
|     // first
 | ||||
|     // glBindBufferRange also changes the generic buffer binding point, so we sync the state first.
 | ||||
|     state.draw.uniform_buffer = uniform_buffer.GetHandle(); | ||||
|     state.Apply(); | ||||
| 
 | ||||
|     bool sync_vs = accelerate_draw; | ||||
|     bool sync_fs = uniform_block_data.dirty; | ||||
| 
 | ||||
|     if (!sync_vs && !sync_fs) | ||||
|     const bool sync_vs = accelerate_draw; | ||||
|     const bool sync_fs = uniform_block_data.dirty; | ||||
|     if (!sync_vs && !sync_fs) { | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     std::size_t uniform_size = uniform_size_aligned_vs + uniform_size_aligned_fs; | ||||
|     std::size_t used_bytes = 0; | ||||
|     u8* uniforms; | ||||
|     GLintptr offset; | ||||
|     bool invalidate; | ||||
|     std::tie(uniforms, offset, invalidate) = | ||||
| 
 | ||||
|     const auto [uniforms, offset, invalidate] = | ||||
|         uniform_buffer.Map(uniform_size, uniform_buffer_alignment); | ||||
| 
 | ||||
|     if (sync_vs) { | ||||
|         Pica::Shader::VSUniformData vs_uniforms; | ||||
|         vs_uniforms.uniforms.SetFromRegs(Pica::g_state.regs.vs, Pica::g_state.vs); | ||||
|         vs_uniforms.uniforms.SetFromRegs(regs.vs, Pica::g_state.vs); | ||||
|         std::memcpy(uniforms + used_bytes, &vs_uniforms, sizeof(vs_uniforms)); | ||||
|         glBindBufferRange(GL_UNIFORM_BUFFER, static_cast<GLuint>(Pica::Shader::UniformBindings::VS), | ||||
|                           uniform_buffer.GetHandle(), offset + used_bytes, | ||||
|  |  | |||
|  | @ -6,7 +6,6 @@ | |||
| 
 | ||||
| #include "core/hw/gpu.h" | ||||
| #include "video_core/rasterizer_accelerated.h" | ||||
| #include "video_core/rasterizer_cache/rasterizer_cache.h" | ||||
| #include "video_core/rasterizer_interface.h" | ||||
| #include "video_core/regs_texturing.h" | ||||
| #include "video_core/renderer_opengl/gl_shader_manager.h" | ||||
|  | @ -24,6 +23,8 @@ class CustomTexManager; | |||
| 
 | ||||
| namespace OpenGL { | ||||
| 
 | ||||
| struct ScreenInfo; | ||||
| 
 | ||||
| class Driver; | ||||
| class ShaderProgramManager; | ||||
| 
 | ||||
|  | @ -48,7 +49,7 @@ public: | |||
|     bool AccelerateTextureCopy(const GPU::Regs::DisplayTransferConfig& config) override; | ||||
|     bool AccelerateFill(const GPU::Regs::MemoryFillConfig& config) override; | ||||
|     bool AccelerateDisplay(const GPU::Regs::FramebufferConfig& config, PAddr framebuffer_addr, | ||||
|                            u32 pixel_stride, ScreenInfo& screen_info) override; | ||||
|                            u32 pixel_stride, ScreenInfo& screen_info); | ||||
|     bool AccelerateDrawBatch(bool is_indexed) override; | ||||
| 
 | ||||
| private: | ||||
|  | @ -132,10 +133,9 @@ private: | |||
| private: | ||||
|     Driver& driver; | ||||
|     OpenGLState state; | ||||
|     GLuint default_texture; | ||||
|     ShaderProgramManager shader_manager; | ||||
|     TextureRuntime runtime; | ||||
|     RasterizerCache res_cache; | ||||
|     std::unique_ptr<ShaderProgramManager> shader_program_manager; | ||||
| 
 | ||||
|     OGLVertexArray sw_vao; // VAO for software shader draw
 | ||||
|     OGLVertexArray hw_vao; // VAO for hardware shader / accelerate draw
 | ||||
|  | @ -147,7 +147,6 @@ private: | |||
|     OGLStreamBuffer index_buffer; | ||||
|     OGLStreamBuffer texture_buffer; | ||||
|     OGLStreamBuffer texture_lf_buffer; | ||||
|     OGLFramebuffer framebuffer; | ||||
|     GLint uniform_buffer_alignment; | ||||
|     std::size_t uniform_size_aligned_vs; | ||||
|     std::size_t uniform_size_aligned_fs; | ||||
|  |  | |||
|  | @ -8,7 +8,6 @@ | |||
| #include <thread> | ||||
| #include <unordered_map> | ||||
| #include <variant> | ||||
| #include "common/scope_exit.h" | ||||
| #include "core/frontend/emu_window.h" | ||||
| #include "video_core/renderer_opengl/gl_driver.h" | ||||
| #include "video_core/renderer_opengl/gl_resource_manager.h" | ||||
|  |  | |||
|  | @ -2,7 +2,7 @@ | |||
| // Licensed under GPLv2 or any later version
 | ||||
| // Refer to the license.txt file included.
 | ||||
| 
 | ||||
| #include <glad/glad.h> | ||||
| #include "common/common_types.h" | ||||
| #include "video_core/renderer_opengl/gl_state.h" | ||||
| #include "video_core/renderer_opengl/gl_vars.h" | ||||
| 
 | ||||
|  |  | |||
|  | @ -528,13 +528,13 @@ void Surface::ScaleUp(u32 new_scale) { | |||
|     textures[1] = MakeHandle(GL_TEXTURE_2D, GetScaledWidth(), GetScaledHeight(), levels, tuple, | ||||
|                              DebugName(true)); | ||||
| 
 | ||||
|     VideoCore::TextureBlit blit = { | ||||
|         .src_rect = GetRect(), | ||||
|         .dst_rect = GetScaledRect(), | ||||
|     }; | ||||
|     for (u32 level = 0; level < levels; level++) { | ||||
|         blit.src_level = level; | ||||
|         blit.dst_level = level; | ||||
|         const VideoCore::TextureBlit blit = { | ||||
|             .src_level = level, | ||||
|             .dst_level = level, | ||||
|             .src_rect = GetRect(level), | ||||
|             .dst_rect = GetScaledRect(level), | ||||
|         }; | ||||
|         BlitScale(blit, true); | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -78,7 +78,8 @@ static std::array<GLfloat, 3 * 2> MakeOrthographicMatrix(const float width, cons | |||
| RendererOpenGL::RendererOpenGL(Core::System& system, Frontend::EmuWindow& window, | ||||
|                                Frontend::EmuWindow* secondary_window) | ||||
|     : VideoCore::RendererBase{system, window, secondary_window}, driver{system.TelemetrySession()}, | ||||
|       frame_dumper{system, window} { | ||||
|       rasterizer{system.Memory(), system.CustomTexManager(), *this, driver}, frame_dumper{system, | ||||
|                                                                                           window} { | ||||
|     const bool has_debug_tool = driver.HasDebugTool(); | ||||
|     window.mailbox = std::make_unique<OGLTextureMailbox>(has_debug_tool); | ||||
|     if (secondary_window) { | ||||
|  | @ -86,8 +87,6 @@ RendererOpenGL::RendererOpenGL(Core::System& system, Frontend::EmuWindow& window | |||
|     } | ||||
|     frame_dumper.mailbox = std::make_unique<OGLVideoDumpingMailbox>(); | ||||
|     InitOpenGLObjects(); | ||||
|     rasterizer = std::make_unique<RasterizerOpenGL>(system.Memory(), system.CustomTexManager(), | ||||
|                                                     *this, driver); | ||||
| } | ||||
| 
 | ||||
| RendererOpenGL::~RendererOpenGL() = default; | ||||
|  | @ -121,8 +120,7 @@ void RendererOpenGL::SwapBuffers() { | |||
| 
 | ||||
|     EndFrame(); | ||||
|     prev_state.Apply(); | ||||
| 
 | ||||
|     rasterizer->TickFrame(); | ||||
|     rasterizer.TickFrame(); | ||||
| } | ||||
| 
 | ||||
| void RendererOpenGL::RenderScreenshot() { | ||||
|  | @ -273,8 +271,8 @@ void RendererOpenGL::LoadFBToScreenInfo(const GPU::Regs::FramebufferConfig& fram | |||
|     // only allows rows to have a memory alignement of 4.
 | ||||
|     ASSERT(pixel_stride % 4 == 0); | ||||
| 
 | ||||
|     if (!Rasterizer()->AccelerateDisplay(framebuffer, framebuffer_addr, | ||||
|                                          static_cast<u32>(pixel_stride), screen_info)) { | ||||
|     if (!rasterizer.AccelerateDisplay(framebuffer, framebuffer_addr, static_cast<u32>(pixel_stride), | ||||
|                                       screen_info)) { | ||||
|         // Reset the screen info's display texture to its own permanent texture
 | ||||
|         screen_info.display_texture = screen_info.texture.resource.handle; | ||||
|         screen_info.display_texcoords = Common::Rectangle<float>(0.f, 0.f, 1.f, 1.f); | ||||
|  | @ -903,7 +901,7 @@ void RendererOpenGL::CleanupVideoDumping() { | |||
| } | ||||
| 
 | ||||
| void RendererOpenGL::Sync() { | ||||
|     rasterizer->SyncEntireState(); | ||||
|     rasterizer.SyncEntireState(); | ||||
| } | ||||
| 
 | ||||
| } // namespace OpenGL
 | ||||
|  |  | |||
|  | @ -46,8 +46,8 @@ public: | |||
|                             Frontend::EmuWindow* secondary_window); | ||||
|     ~RendererOpenGL() override; | ||||
| 
 | ||||
|     [[nodiscard]] VideoCore::RasterizerInterface* Rasterizer() const override { | ||||
|         return rasterizer.get(); | ||||
|     [[nodiscard]] VideoCore::RasterizerInterface* Rasterizer() override { | ||||
|         return &rasterizer; | ||||
|     } | ||||
| 
 | ||||
|     void SwapBuffers() override; | ||||
|  | @ -86,8 +86,8 @@ private: | |||
| 
 | ||||
| private: | ||||
|     Driver driver; | ||||
|     RasterizerOpenGL rasterizer; | ||||
|     OpenGLState state; | ||||
|     std::unique_ptr<RasterizerOpenGL> rasterizer; | ||||
| 
 | ||||
|     // OpenGL object IDs
 | ||||
|     OGLVertexArray vertex_array; | ||||
|  |  | |||
|  | @ -13,7 +13,7 @@ namespace SwRenderer { | |||
| 
 | ||||
| RendererSoftware::RendererSoftware(Core::System& system, Frontend::EmuWindow& window) | ||||
|     : VideoCore::RendererBase{system, window, nullptr}, memory{system.Memory()}, | ||||
|       rasterizer{std::make_unique<RasterizerSoftware>(system.Memory())} {} | ||||
|       rasterizer{system.Memory()} {} | ||||
| 
 | ||||
| RendererSoftware::~RendererSoftware() = default; | ||||
| 
 | ||||
|  |  | |||
|  | @ -24,8 +24,8 @@ public: | |||
|     explicit RendererSoftware(Core::System& system, Frontend::EmuWindow& window); | ||||
|     ~RendererSoftware() override; | ||||
| 
 | ||||
|     [[nodiscard]] VideoCore::RasterizerInterface* Rasterizer() const override { | ||||
|         return rasterizer.get(); | ||||
|     [[nodiscard]] VideoCore::RasterizerInterface* Rasterizer() override { | ||||
|         return &rasterizer; | ||||
|     } | ||||
| 
 | ||||
|     [[nodiscard]] const ScreenInfo& Screen(VideoCore::ScreenId id) const noexcept { | ||||
|  | @ -42,7 +42,7 @@ private: | |||
| 
 | ||||
| private: | ||||
|     Memory::MemorySystem& memory; | ||||
|     std::unique_ptr<RasterizerSoftware> rasterizer; | ||||
|     RasterizerSoftware rasterizer; | ||||
|     std::array<ScreenInfo, 3> screen_infos{}; | ||||
| }; | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue