diff options
Diffstat (limited to 'src')
32 files changed, 334 insertions, 98 deletions
diff --git a/src/audio_core/audio_core.cpp b/src/audio_core/audio_core.cpp index d42249ebd..8e19ec0c4 100644 --- a/src/audio_core/audio_core.cpp +++ b/src/audio_core/audio_core.cpp @@ -71,6 +71,10 @@ void SelectSink(std::string sink_id) { DSP::HLE::SetSink(iter->factory()); } +void EnableStretching(bool enable) { + DSP::HLE::EnableStretching(enable); +} + void Shutdown() { CoreTiming::UnscheduleEvent(tick_event, 0); DSP::HLE::Shutdown(); diff --git a/src/audio_core/audio_core.h b/src/audio_core/audio_core.h index f618361f3..7e678aba5 100644 --- a/src/audio_core/audio_core.h +++ b/src/audio_core/audio_core.h @@ -23,6 +23,9 @@ void AddAddressSpace(Kernel::VMManager& vm_manager); /// Select the sink to use based on sink id. void SelectSink(std::string sink_id); +/// Enable/Disable stretching. +void EnableStretching(bool enable); + /// Shutdown Audio Core void Shutdown(); diff --git a/src/audio_core/hle/dsp.cpp b/src/audio_core/hle/dsp.cpp index 0640e1eff..0cddeb82a 100644 --- a/src/audio_core/hle/dsp.cpp +++ b/src/audio_core/hle/dsp.cpp @@ -85,12 +85,45 @@ static StereoFrame16 GenerateCurrentFrame() { // Audio output +static bool perform_time_stretching = true; static std::unique_ptr<AudioCore::Sink> sink; static AudioCore::TimeStretcher time_stretcher; +static void FlushResidualStretcherAudio() { + time_stretcher.Flush(); + while (true) { + std::vector<s16> residual_audio = time_stretcher.Process(sink->SamplesInQueue()); + if (residual_audio.empty()) + break; + sink->EnqueueSamples(residual_audio.data(), residual_audio.size() / 2); + } +} + static void OutputCurrentFrame(const StereoFrame16& frame) { - time_stretcher.AddSamples(&frame[0][0], frame.size()); - sink->EnqueueSamples(time_stretcher.Process(sink->SamplesInQueue())); + if (perform_time_stretching) { + time_stretcher.AddSamples(&frame[0][0], frame.size()); + std::vector<s16> stretched_samples = time_stretcher.Process(sink->SamplesInQueue()); + sink->EnqueueSamples(stretched_samples.data(), stretched_samples.size() / 2); + } else { + constexpr size_t maximum_sample_latency = 1024; // about 32 miliseconds + if (sink->SamplesInQueue() > maximum_sample_latency) { + // This can occur if we're running too fast and samples are starting to back up. + // Just drop the samples. + return; + } + + sink->EnqueueSamples(&frame[0][0], frame.size()); + } +} + +void EnableStretching(bool enable) { + if (perform_time_stretching == enable) + return; + + if (!enable) { + FlushResidualStretcherAudio(); + } + perform_time_stretching = enable; } // Public Interface @@ -111,12 +144,8 @@ void Init() { } void Shutdown() { - time_stretcher.Flush(); - while (true) { - std::vector<s16> residual_audio = time_stretcher.Process(sink->SamplesInQueue()); - if (residual_audio.empty()) - break; - sink->EnqueueSamples(residual_audio); + if (perform_time_stretching) { + FlushResidualStretcherAudio(); } } diff --git a/src/audio_core/hle/dsp.h b/src/audio_core/hle/dsp.h index 9275cd7de..565f20b6f 100644 --- a/src/audio_core/hle/dsp.h +++ b/src/audio_core/hle/dsp.h @@ -544,5 +544,13 @@ bool Tick(); */ void SetSink(std::unique_ptr<AudioCore::Sink> sink); +/** + * Enables/Disables audio-stretching. + * Audio stretching is an enhancement that stretches audio to match emulation + * speed to prevent stuttering at the cost of some audio latency. + * @param enable true to enable, false to disable. + */ +void EnableStretching(bool enable); + } // namespace HLE } // namespace DSP diff --git a/src/audio_core/null_sink.h b/src/audio_core/null_sink.h index faf0ee4e1..9931c4778 100644 --- a/src/audio_core/null_sink.h +++ b/src/audio_core/null_sink.h @@ -19,7 +19,7 @@ public: return native_sample_rate; } - void EnqueueSamples(const std::vector<s16>&) override {} + void EnqueueSamples(const s16*, size_t) override {} size_t SamplesInQueue() const override { return 0; diff --git a/src/audio_core/sdl2_sink.cpp b/src/audio_core/sdl2_sink.cpp index dc75c04ee..311dd5b59 100644 --- a/src/audio_core/sdl2_sink.cpp +++ b/src/audio_core/sdl2_sink.cpp @@ -71,14 +71,12 @@ unsigned int SDL2Sink::GetNativeSampleRate() const { return impl->sample_rate; } -void SDL2Sink::EnqueueSamples(const std::vector<s16>& samples) { +void SDL2Sink::EnqueueSamples(const s16* samples, size_t sample_count) { if (impl->audio_device_id <= 0) return; - ASSERT_MSG(samples.size() % 2 == 0, "Samples must be in interleaved stereo PCM16 format (size must be a multiple of two)"); - SDL_LockAudioDevice(impl->audio_device_id); - impl->queue.emplace_back(samples); + impl->queue.emplace_back(samples, samples + sample_count * 2); SDL_UnlockAudioDevice(impl->audio_device_id); } diff --git a/src/audio_core/sdl2_sink.h b/src/audio_core/sdl2_sink.h index 0f296b673..b13827214 100644 --- a/src/audio_core/sdl2_sink.h +++ b/src/audio_core/sdl2_sink.h @@ -18,7 +18,7 @@ public: unsigned int GetNativeSampleRate() const override; - void EnqueueSamples(const std::vector<s16>& samples) override; + void EnqueueSamples(const s16* samples, size_t sample_count) override; size_t SamplesInQueue() const override; diff --git a/src/audio_core/sink.h b/src/audio_core/sink.h index 1c881c3d2..a06fc3dcc 100644 --- a/src/audio_core/sink.h +++ b/src/audio_core/sink.h @@ -23,9 +23,10 @@ public: /** * Feed stereo samples to sink. - * @param samples Samples in interleaved stereo PCM16 format. Size of vector must be multiple of two. + * @param samples Samples in interleaved stereo PCM16 format. + * @param sample_count Number of samples. */ - virtual void EnqueueSamples(const std::vector<s16>& samples) = 0; + virtual void EnqueueSamples(const s16* samples, size_t sample_count) = 0; /// Samples enqueued that have not been played yet. virtual std::size_t SamplesInQueue() const = 0; diff --git a/src/citra/config.cpp b/src/citra/config.cpp index e832ec58d..110b883fb 100644 --- a/src/citra/config.cpp +++ b/src/citra/config.cpp @@ -71,6 +71,7 @@ void Config::ReadValues() { Settings::values.use_hw_renderer = sdl2_config->GetBoolean("Renderer", "use_hw_renderer", true); Settings::values.use_shader_jit = sdl2_config->GetBoolean("Renderer", "use_shader_jit", true); Settings::values.use_scaled_resolution = sdl2_config->GetBoolean("Renderer", "use_scaled_resolution", false); + Settings::values.use_vsync = sdl2_config->GetBoolean("Renderer", "use_vsync", false); Settings::values.bg_red = (float)sdl2_config->GetReal("Renderer", "bg_red", 1.0); Settings::values.bg_green = (float)sdl2_config->GetReal("Renderer", "bg_green", 1.0); @@ -78,6 +79,7 @@ void Config::ReadValues() { // Audio Settings::values.sink_id = sdl2_config->Get("Audio", "output_engine", "auto"); + Settings::values.enable_audio_stretching = sdl2_config->GetBoolean("Audio", "enable_audio_stretching", true); // Data Storage Settings::values.use_virtual_sd = sdl2_config->GetBoolean("Data Storage", "use_virtual_sd", true); diff --git a/src/citra/default_ini.h b/src/citra/default_ini.h index 6249ef9e2..2031620a5 100644 --- a/src/citra/default_ini.h +++ b/src/citra/default_ini.h @@ -55,6 +55,10 @@ use_shader_jit = # 0 (default): Native, 1: Scaled use_scaled_resolution = +# Whether to enable V-Sync (caps the framerate at 60FPS) or not. +# 0 (default): Off, 1: On +use_vsync = + # The clear color for the renderer. What shows up on the sides of the bottom screen. # Must be in range of 0.0-1.0. Defaults to 1.0 for all. bg_red = @@ -66,6 +70,12 @@ bg_green = # auto (default): Auto-select, null: No audio output, sdl2: SDL2 (if available) output_engine = +# Whether or not to enable the audio-stretching post-processing effect. +# This effect adjusts audio speed to match emulation speed and helps prevent audio stutter, +# at the cost of increasing audio latency. +# 0: No, 1 (default): Yes +enable_audio_stretching = + [Data Storage] # Whether to create a virtual SD card. # 1 (default): Yes, 0: No diff --git a/src/citra/emu_window/emu_window_sdl2.cpp b/src/citra/emu_window/emu_window_sdl2.cpp index 591f68aa4..da12307b7 100644 --- a/src/citra/emu_window/emu_window_sdl2.cpp +++ b/src/citra/emu_window/emu_window_sdl2.cpp @@ -108,6 +108,7 @@ EmuWindow_SDL2::EmuWindow_SDL2() { OnResize(); OnMinimalClientAreaChangeRequest(GetActiveConfig().min_client_area_size); SDL_PumpEvents(); + SDL_GL_SetSwapInterval(Settings::values.use_vsync); DoneCurrent(); } diff --git a/src/citra_qt/CMakeLists.txt b/src/citra_qt/CMakeLists.txt index 4402ad995..e97d33da4 100644 --- a/src/citra_qt/CMakeLists.txt +++ b/src/citra_qt/CMakeLists.txt @@ -22,6 +22,7 @@ set(SRCS configure_debug.cpp configure_dialog.cpp configure_general.cpp + configure_graphics.cpp configure_system.cpp configure_input.cpp game_list.cpp @@ -54,6 +55,7 @@ set(HEADERS configure_debug.h configure_dialog.h configure_general.h + configure_graphics.h configure_system.h configure_input.h game_list.h @@ -73,6 +75,7 @@ set(UIS configure_audio.ui configure_debug.ui configure_general.ui + configure_graphics.ui configure_system.ui configure_input.ui hotkeys.ui diff --git a/src/citra_qt/bootmanager.cpp b/src/citra_qt/bootmanager.cpp index 414b2f8af..6dddde9ba 100644 --- a/src/citra_qt/bootmanager.cpp +++ b/src/citra_qt/bootmanager.cpp @@ -107,36 +107,13 @@ private: }; GRenderWindow::GRenderWindow(QWidget* parent, EmuThread* emu_thread) : - QWidget(parent), keyboard_id(0), emu_thread(emu_thread) { + QWidget(parent), keyboard_id(0), emu_thread(emu_thread), child(nullptr) { std::string window_title = Common::StringFromFormat("Citra | %s-%s", Common::g_scm_branch, Common::g_scm_desc); setWindowTitle(QString::fromStdString(window_title)); keyboard_id = KeyMap::NewDeviceId(); ReloadSetKeymaps(); - - // TODO: One of these flags might be interesting: WA_OpaquePaintEvent, WA_NoBackground, WA_DontShowOnScreen, WA_DeleteOnClose - QGLFormat fmt; - fmt.setVersion(3,3); - fmt.setProfile(QGLFormat::CoreProfile); - // Requests a forward-compatible context, which is required to get a 3.2+ context on OS X - fmt.setOption(QGL::NoDeprecatedFunctions); - - child = new GGLWidgetInternal(fmt, this); - QBoxLayout* layout = new QHBoxLayout(this); - - resize(VideoCore::kScreenTopWidth, VideoCore::kScreenTopHeight + VideoCore::kScreenBottomHeight); - layout->addWidget(child); - layout->setMargin(0); - setLayout(layout); - - OnMinimalClientAreaChangeRequest(GetActiveConfig().min_client_area_size); - - OnFramebufferSizeChanged(); - NotifyClientAreaSizeChanged(std::pair<unsigned,unsigned>(child->width(), child->height())); - - BackupGeometry(); - } void GRenderWindow::moveContext() @@ -281,6 +258,40 @@ void GRenderWindow::OnClientAreaResized(unsigned width, unsigned height) NotifyClientAreaSizeChanged(std::make_pair(width, height)); } +void GRenderWindow::InitRenderTarget() { + if (child) { + delete child; + } + + if (layout()) { + delete layout(); + } + + // TODO: One of these flags might be interesting: WA_OpaquePaintEvent, WA_NoBackground, WA_DontShowOnScreen, WA_DeleteOnClose + QGLFormat fmt; + fmt.setVersion(3, 3); + fmt.setProfile(QGLFormat::CoreProfile); + fmt.setSwapInterval(Settings::values.use_vsync); + + // Requests a forward-compatible context, which is required to get a 3.2+ context on OS X + fmt.setOption(QGL::NoDeprecatedFunctions); + + child = new GGLWidgetInternal(fmt, this); + QBoxLayout* layout = new QHBoxLayout(this); + + resize(VideoCore::kScreenTopWidth, VideoCore::kScreenTopHeight + VideoCore::kScreenBottomHeight); + layout->addWidget(child); + layout->setMargin(0); + setLayout(layout); + + OnMinimalClientAreaChangeRequest(GetActiveConfig().min_client_area_size); + + OnFramebufferSizeChanged(); + NotifyClientAreaSizeChanged(std::pair<unsigned, unsigned>(child->width(), child->height())); + + BackupGeometry(); +} + void GRenderWindow::OnMinimalClientAreaChangeRequest(const std::pair<unsigned,unsigned>& minimal_size) { setMinimumSize(minimal_size.first, minimal_size.second); } diff --git a/src/citra_qt/bootmanager.h b/src/citra_qt/bootmanager.h index 0dcf3e5eb..c1da2bc5f 100644 --- a/src/citra_qt/bootmanager.h +++ b/src/citra_qt/bootmanager.h @@ -126,6 +126,8 @@ public: void OnClientAreaResized(unsigned width, unsigned height); + void InitRenderTarget(); + public slots: void moveContext(); // overridden diff --git a/src/citra_qt/config.cpp b/src/citra_qt/config.cpp index 93c6a6e41..fa3fa210c 100644 --- a/src/citra_qt/config.cpp +++ b/src/citra_qt/config.cpp @@ -48,6 +48,7 @@ void Config::ReadValues() { Settings::values.use_hw_renderer = qt_config->value("use_hw_renderer", true).toBool(); Settings::values.use_shader_jit = qt_config->value("use_shader_jit", true).toBool(); Settings::values.use_scaled_resolution = qt_config->value("use_scaled_resolution", false).toBool(); + Settings::values.use_vsync = qt_config->value("use_vsync", false).toBool(); Settings::values.bg_red = qt_config->value("bg_red", 1.0).toFloat(); Settings::values.bg_green = qt_config->value("bg_green", 1.0).toFloat(); @@ -56,6 +57,7 @@ void Config::ReadValues() { qt_config->beginGroup("Audio"); Settings::values.sink_id = qt_config->value("output_engine", "auto").toString().toStdString(); + Settings::values.enable_audio_stretching = qt_config->value("enable_audio_stretching", true).toBool(); qt_config->endGroup(); qt_config->beginGroup("Data Storage"); @@ -139,6 +141,7 @@ void Config::SaveValues() { qt_config->setValue("use_hw_renderer", Settings::values.use_hw_renderer); qt_config->setValue("use_shader_jit", Settings::values.use_shader_jit); qt_config->setValue("use_scaled_resolution", Settings::values.use_scaled_resolution); + qt_config->setValue("use_vsync", Settings::values.use_vsync); // Cast to double because Qt's written float values are not human-readable qt_config->setValue("bg_red", (double)Settings::values.bg_red); @@ -148,6 +151,7 @@ void Config::SaveValues() { qt_config->beginGroup("Audio"); qt_config->setValue("output_engine", QString::fromStdString(Settings::values.sink_id)); + qt_config->setValue("enable_audio_stretching", Settings::values.enable_audio_stretching); qt_config->endGroup(); qt_config->beginGroup("Data Storage"); diff --git a/src/citra_qt/configure.ui b/src/citra_qt/configure.ui index 15fe17323..28b4a3b90 100644 --- a/src/citra_qt/configure.ui +++ b/src/citra_qt/configure.ui @@ -34,11 +34,16 @@ <string>Input</string> </attribute> </widget> - <widget class="ConfigureAudio" name="audioTab"> + <widget class="ConfigureGraphics" name="graphicsTab"> <attribute name="title"> - <string>Audio</string> + <string>Graphics</string> </attribute> </widget> + <widget class="ConfigureAudio" name="audioTab"> + <attribute name="title"> + <string>Audio</string> + </attribute> + </widget> <widget class="ConfigureDebug" name="debugTab"> <attribute name="title"> <string>Debug</string> @@ -80,12 +85,18 @@ <header>configure_debug.h</header> <container>1</container> </customwidget> - <customwidget> - <class>ConfigureInput</class> - <extends>QWidget</extends> - <header>configure_input.h</header> - <container>1</container> - </customwidget> + <customwidget> + <class>ConfigureInput</class> + <extends>QWidget</extends> + <header>configure_input.h</header> + <container>1</container> + </customwidget> + <customwidget> + <class>ConfigureGraphics</class> + <extends>QWidget</extends> + <header>configure_graphics.h</header> + <container>1</container> + </customwidget> </customwidgets> <resources/> <connections> diff --git a/src/citra_qt/configure_audio.cpp b/src/citra_qt/configure_audio.cpp index cedfa2f2a..7100be158 100644 --- a/src/citra_qt/configure_audio.cpp +++ b/src/citra_qt/configure_audio.cpp @@ -36,9 +36,12 @@ void ConfigureAudio::setConfiguration() { } } ui->output_sink_combo_box->setCurrentIndex(new_sink_index); + + ui->toggle_audio_stretching->setChecked(Settings::values.enable_audio_stretching); } void ConfigureAudio::applyConfiguration() { Settings::values.sink_id = ui->output_sink_combo_box->itemText(ui->output_sink_combo_box->currentIndex()).toStdString(); + Settings::values.enable_audio_stretching = ui->toggle_audio_stretching->isChecked(); Settings::Apply(); } diff --git a/src/citra_qt/configure_audio.ui b/src/citra_qt/configure_audio.ui index d7f6946ca..3e2b4635f 100644 --- a/src/citra_qt/configure_audio.ui +++ b/src/citra_qt/configure_audio.ui @@ -25,6 +25,16 @@ </item> </layout> </item> + <item> + <widget class="QCheckBox" name="toggle_audio_stretching"> + <property name="text"> + <string>Enable audio stretching</string> + </property> + <property name="toolTip"> + <string>This post-processing effect adjusts audio speed to match emulation speed and helps prevent audio stutter. This however increases audio latency.</string> + </property> + </widget> + </item> </layout> </widget> </item> diff --git a/src/citra_qt/configure_debug.cpp b/src/citra_qt/configure_debug.cpp index dc3d7b906..fa57a7f72 100644 --- a/src/citra_qt/configure_debug.cpp +++ b/src/citra_qt/configure_debug.cpp @@ -19,13 +19,13 @@ ConfigureDebug::~ConfigureDebug() { } void ConfigureDebug::setConfiguration() { - ui->toogle_gdbstub->setChecked(Settings::values.use_gdbstub); + ui->toggle_gdbstub->setChecked(Settings::values.use_gdbstub); ui->gdbport_spinbox->setEnabled(Settings::values.use_gdbstub); ui->gdbport_spinbox->setValue(Settings::values.gdbstub_port); } void ConfigureDebug::applyConfiguration() { - Settings::values.use_gdbstub = ui->toogle_gdbstub->isChecked(); + Settings::values.use_gdbstub = ui->toggle_gdbstub->isChecked(); Settings::values.gdbstub_port = ui->gdbport_spinbox->value(); Settings::Apply(); } diff --git a/src/citra_qt/configure_debug.ui b/src/citra_qt/configure_debug.ui index 3ba7f44da..bbbb0e3f4 100644 --- a/src/citra_qt/configure_debug.ui +++ b/src/citra_qt/configure_debug.ui @@ -25,7 +25,7 @@ <item> <layout class="QHBoxLayout" name="horizontalLayout_3"> <item> - <widget class="QCheckBox" name="toogle_gdbstub"> + <widget class="QCheckBox" name="toggle_gdbstub"> <property name="text"> <string>Enable GDB Stub</string> </property> @@ -83,7 +83,7 @@ <resources/> <connections> <connection> - <sender>toogle_gdbstub</sender> + <sender>toggle_gdbstub</sender> <signal>toggled(bool)</signal> <receiver>gdbport_spinbox</receiver> <slot>setEnabled(bool)</slot> diff --git a/src/citra_qt/configure_dialog.cpp b/src/citra_qt/configure_dialog.cpp index 459fac4bb..7da8ad067 100644 --- a/src/citra_qt/configure_dialog.cpp +++ b/src/citra_qt/configure_dialog.cpp @@ -31,6 +31,7 @@ void ConfigureDialog::applyConfiguration() { ui->generalTab->applyConfiguration(); ui->systemTab->applyConfiguration(); ui->inputTab->applyConfiguration(); + ui->graphicsTab->applyConfiguration(); ui->audioTab->applyConfiguration(); ui->debugTab->applyConfiguration(); } diff --git a/src/citra_qt/configure_general.cpp b/src/citra_qt/configure_general.cpp index 62648e665..95aab9f2e 100644 --- a/src/citra_qt/configure_general.cpp +++ b/src/citra_qt/configure_general.cpp @@ -20,20 +20,14 @@ ConfigureGeneral::~ConfigureGeneral() { } void ConfigureGeneral::setConfiguration() { - ui->toogle_deepscan->setChecked(UISettings::values.gamedir_deepscan); - ui->toogle_check_exit->setChecked(UISettings::values.confirm_before_closing); + ui->toggle_deepscan->setChecked(UISettings::values.gamedir_deepscan); + ui->toggle_check_exit->setChecked(UISettings::values.confirm_before_closing); ui->region_combobox->setCurrentIndex(Settings::values.region_value); - ui->toogle_hw_renderer->setChecked(Settings::values.use_hw_renderer); - ui->toogle_shader_jit->setChecked(Settings::values.use_shader_jit); - ui->toogle_scaled_resolution->setChecked(Settings::values.use_scaled_resolution); } void ConfigureGeneral::applyConfiguration() { - UISettings::values.gamedir_deepscan = ui->toogle_deepscan->isChecked(); - UISettings::values.confirm_before_closing = ui->toogle_check_exit->isChecked(); + UISettings::values.gamedir_deepscan = ui->toggle_deepscan->isChecked(); + UISettings::values.confirm_before_closing = ui->toggle_check_exit->isChecked(); Settings::values.region_value = ui->region_combobox->currentIndex(); - Settings::values.use_hw_renderer = ui->toogle_hw_renderer->isChecked(); - Settings::values.use_shader_jit = ui->toogle_shader_jit->isChecked(); - Settings::values.use_scaled_resolution = ui->toogle_scaled_resolution->isChecked(); Settings::Apply(); } diff --git a/src/citra_qt/configure_general.ui b/src/citra_qt/configure_general.ui index 5eb309793..343f804c0 100644 --- a/src/citra_qt/configure_general.ui +++ b/src/citra_qt/configure_general.ui @@ -25,14 +25,14 @@ <item> <layout class="QVBoxLayout" name="verticalLayout_2"> <item> - <widget class="QCheckBox" name="toogle_deepscan"> + <widget class="QCheckBox" name="toggle_deepscan"> <property name="text"> <string>Recursive scan for game folder</string> </property> </widget> </item> <item> - <widget class="QCheckBox" name="toogle_check_exit"> + <widget class="QCheckBox" name="toggle_check_exit"> <property name="text"> <string>Confirm exit while emulation is running</string> </property> @@ -107,40 +107,6 @@ </widget> </item> <item> - <widget class="QGroupBox" name="groupBox_2"> - <property name="title"> - <string>Performance</string> - </property> - <layout class="QHBoxLayout" name="horizontalLayout_2"> - <item> - <layout class="QVBoxLayout" name="verticalLayout_3"> - <item> - <widget class="QCheckBox" name="toogle_hw_renderer"> - <property name="text"> - <string>Enable hardware renderer</string> - </property> - </widget> - </item> - <item> - <widget class="QCheckBox" name="toogle_shader_jit"> - <property name="text"> - <string>Enable shader JIT</string> - </property> - </widget> - </item> - <item> - <widget class="QCheckBox" name="toogle_scaled_resolution"> - <property name="text"> - <string>Enable scaled resolution</string> - </property> - </widget> - </item> - </layout> - </item> - </layout> - </widget> - </item> - <item> <widget class="QGroupBox" name="groupBox_3"> <property name="title"> <string>Hotkeys</string> diff --git a/src/citra_qt/configure_graphics.cpp b/src/citra_qt/configure_graphics.cpp new file mode 100644 index 000000000..5a8101795 --- /dev/null +++ b/src/citra_qt/configure_graphics.cpp @@ -0,0 +1,37 @@ +// Copyright 2016 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "citra_qt/configure_graphics.h" +#include "ui_configure_graphics.h" + +#include "core/settings.h" +#include "core/system.h" + +ConfigureGraphics::ConfigureGraphics(QWidget *parent) : + QWidget(parent), + ui(new Ui::ConfigureGraphics) +{ + ui->setupUi(this); + this->setConfiguration(); + + ui->toggle_vsync->setEnabled(!System::IsPoweredOn()); +} + +ConfigureGraphics::~ConfigureGraphics() { +} + +void ConfigureGraphics::setConfiguration() { + ui->toggle_hw_renderer->setChecked(Settings::values.use_hw_renderer); + ui->toggle_shader_jit->setChecked(Settings::values.use_shader_jit); + ui->toggle_scaled_resolution->setChecked(Settings::values.use_scaled_resolution); + ui->toggle_vsync->setChecked(Settings::values.use_vsync); +} + +void ConfigureGraphics::applyConfiguration() { + Settings::values.use_hw_renderer = ui->toggle_hw_renderer->isChecked(); + Settings::values.use_shader_jit = ui->toggle_shader_jit->isChecked(); + Settings::values.use_scaled_resolution = ui->toggle_scaled_resolution->isChecked(); + Settings::values.use_vsync = ui->toggle_vsync->isChecked(); + Settings::Apply(); +} diff --git a/src/citra_qt/configure_graphics.h b/src/citra_qt/configure_graphics.h new file mode 100644 index 000000000..dfb0c0461 --- /dev/null +++ b/src/citra_qt/configure_graphics.h @@ -0,0 +1,29 @@ +// Copyright 2016 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include <memory> +#include <QWidget> + +namespace Ui { +class ConfigureGraphics; +} + +class ConfigureGraphics : public QWidget +{ + Q_OBJECT + +public: + explicit ConfigureGraphics(QWidget *parent = nullptr); + ~ConfigureGraphics(); + + void applyConfiguration(); + +private: + void setConfiguration(); + +private: + std::unique_ptr<Ui::ConfigureGraphics> ui; +}; diff --git a/src/citra_qt/configure_graphics.ui b/src/citra_qt/configure_graphics.ui new file mode 100644 index 000000000..da6e19ce1 --- /dev/null +++ b/src/citra_qt/configure_graphics.ui @@ -0,0 +1,92 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>ConfigureGraphics</class> + <widget class="QWidget" name="ConfigureGraphics"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>400</width> + <height>300</height> + </rect> + </property> + <property name="windowTitle"> + <string>Form</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <layout class="QVBoxLayout" name="verticalLayout_3"> + <item> + <widget class="QGroupBox" name="groupBox"> + <property name="title"> + <string>Graphics</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout_2"> + <item> + <widget class="QCheckBox" name="toggle_hw_renderer"> + <property name="text"> + <string>Enable hardware renderer</string> + </property> + </widget> + </item> + <item> + <widget class="QCheckBox" name="toggle_shader_jit"> + <property name="text"> + <string>Enable shader JIT</string> + </property> + </widget> + </item> + <item> + <widget class="QCheckBox" name="toggle_scaled_resolution"> + <property name="text"> + <string>Enable scaled resolution</string> + </property> + </widget> + </item> + <item> + <widget class="QCheckBox" name="toggle_vsync"> + <property name="text"> + <string>Enable V-Sync</string> + </property> + </widget> + </item> + </layout> + </widget> + </item> + </layout> + </item> + <item> + <spacer name="verticalSpacer"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </item> + </layout> + </widget> + <resources/> + <connections> + <connection> + <sender>toggle_gdbstub</sender> + <signal>toggled(bool)</signal> + <receiver>gdbport_spinbox</receiver> + <slot>setEnabled(bool)</slot> + <hints> + <hint type="sourcelabel"> + <x>84</x> + <y>157</y> + </hint> + <hint type="destinationlabel"> + <x>342</x> + <y>158</y> + </hint> + </hints> + </connection> + </connections> +</ui> diff --git a/src/citra_qt/main.cpp b/src/citra_qt/main.cpp index 68a936087..9fd4482f6 100644 --- a/src/citra_qt/main.cpp +++ b/src/citra_qt/main.cpp @@ -243,7 +243,9 @@ bool GMainWindow::InitializeSystem() { if (emu_thread != nullptr) ShutdownGame(); + render_window->InitRenderTarget(); render_window->MakeCurrent(); + if (!gladLoadGL()) { QMessageBox::critical(this, tr("Error while starting Citra!"), tr("Failed to initialize the video core!\n\n" diff --git a/src/core/settings.cpp b/src/core/settings.cpp index 77261eafe..1b6733a79 100644 --- a/src/core/settings.cpp +++ b/src/core/settings.cpp @@ -24,6 +24,7 @@ void Apply() { VideoCore::g_scaled_resolution_enabled = values.use_scaled_resolution; AudioCore::SelectSink(values.sink_id); + AudioCore::EnableStretching(values.enable_audio_stretching); } diff --git a/src/core/settings.h b/src/core/settings.h index f95e62390..fb3fbe391 100644 --- a/src/core/settings.h +++ b/src/core/settings.h @@ -72,6 +72,7 @@ struct Values { bool use_hw_renderer; bool use_shader_jit; bool use_scaled_resolution; + bool use_vsync; float bg_red; float bg_green; @@ -81,6 +82,7 @@ struct Values { // Audio std::string sink_id; + bool enable_audio_stretching; // Debugging bool use_gdbstub; diff --git a/src/core/system.cpp b/src/core/system.cpp index 4a4757af3..4fc266cb0 100644 --- a/src/core/system.cpp +++ b/src/core/system.cpp @@ -17,6 +17,8 @@ namespace System { +static bool is_powered_on{ false }; + Result Init(EmuWindow* emu_window) { Core::Init(); CoreTiming::Init(); @@ -30,9 +32,15 @@ Result Init(EmuWindow* emu_window) { AudioCore::Init(); GDBStub::Init(); + is_powered_on = true; + return Result::Success; } +bool IsPoweredOn() { + return is_powered_on; +} + void Shutdown() { GDBStub::Shutdown(); AudioCore::Shutdown(); @@ -42,6 +50,8 @@ void Shutdown() { HW::Shutdown(); CoreTiming::Shutdown(); Core::Shutdown(); + + is_powered_on = false; } } // namespace diff --git a/src/core/system.h b/src/core/system.h index a4a627ea9..fb0ca4e1b 100644 --- a/src/core/system.h +++ b/src/core/system.h @@ -16,6 +16,7 @@ enum class Result { }; Result Init(EmuWindow* emu_window); +bool IsPoweredOn(); void Shutdown(); } diff --git a/src/video_core/video_core.cpp b/src/video_core/video_core.cpp index c9975876d..bd6e5eb6b 100644 --- a/src/video_core/video_core.cpp +++ b/src/video_core/video_core.cpp @@ -22,6 +22,7 @@ std::unique_ptr<RendererBase> g_renderer; ///< Renderer plugin std::atomic<bool> g_hw_renderer_enabled; std::atomic<bool> g_shader_jit_enabled; std::atomic<bool> g_scaled_resolution_enabled; +std::atomic<bool> g_vsync_enabled; /// Initialize the video core bool Init(EmuWindow* emu_window) { |