diff --git a/android/app/src/main/res/values/strings.xml b/android/app/src/main/res/values/strings.xml index a6ef6a3ad..8bbb7e618 100644 --- a/android/app/src/main/res/values/strings.xml +++ b/android/app/src/main/res/values/strings.xml @@ -212,4 +212,6 @@ Quick Save Show Resolution Shows the resolution the game is rendering at in the top-right corner of the display. + Stretches the active display to fill the screen. + Stretch To Fill diff --git a/android/app/src/main/res/xml/display_preferences.xml b/android/app/src/main/res/xml/display_preferences.xml index aedd2a050..e2f87fc98 100644 --- a/android/app/src/main/res/xml/display_preferences.xml +++ b/android/app/src/main/res/xml/display_preferences.xml @@ -43,18 +43,28 @@ app:useSimpleSummaryProvider="true" app:iconSpaceReserved="false" /> + + + (window_width) / static_cast(window_height); + const float display_aspect_ratio = m_display_stretch ? window_ratio : m_display_aspect_ratio; const float x_scale = apply_aspect_ratio ? - (m_display_aspect_ratio / (static_cast(m_display_width) / static_cast(m_display_height))) : + (display_aspect_ratio / (static_cast(m_display_width) / static_cast(m_display_height))) : 1.0f; const float display_width = static_cast(m_display_width) * x_scale; const float display_height = static_cast(m_display_height); @@ -162,8 +164,6 @@ void HostDisplay::CalculateDrawRect(s32 window_width, s32 window_height, float* *out_x_scale = x_scale; // now fit it within the window - const float window_ratio = static_cast(window_width) / static_cast(window_height); - float scale; if ((display_width / display_height) >= window_ratio) { diff --git a/src/core/host_display.h b/src/core/host_display.h index 9f46246d4..03601c4d6 100644 --- a/src/core/host_display.h +++ b/src/core/host_display.h @@ -196,6 +196,7 @@ public: void SetDisplayTopMargin(s32 height) { m_display_top_margin = height; } void SetDisplayIntegerScaling(bool enabled) { m_display_integer_scaling = enabled; } void SetDisplayAlignment(Alignment alignment) { m_display_alignment = alignment; } + void SetDisplayStretch(bool stretch) { m_display_stretch = stretch; } /// Sets the software cursor to the specified texture. Ownership of the texture is transferred. void SetSoftwareCursor(std::unique_ptr texture, float scale = 1.0f); @@ -276,4 +277,5 @@ protected: bool m_display_linear_filtering = false; bool m_display_changed = false; bool m_display_integer_scaling = false; + bool m_display_stretch = false; }; diff --git a/src/core/host_interface.cpp b/src/core/host_interface.cpp index 750d3a185..88ec11d21 100644 --- a/src/core/host_interface.cpp +++ b/src/core/host_interface.cpp @@ -109,6 +109,7 @@ bool HostInterface::BootSystem(const SystemBootParameters& parameters) // set host display settings m_display->SetDisplayLinearFiltering(g_settings.display_linear_filtering); m_display->SetDisplayIntegerScaling(g_settings.display_integer_scaling); + m_display->SetDisplayStretch(g_settings.display_stretch); // create the audio stream. this will never fail, since we'll just fall back to null CreateAudioStream(); @@ -545,6 +546,7 @@ void HostInterface::SetDefaultSettings(SettingsInterface& si) si.SetBoolValue("Display", "Force4_3For24Bit", false); si.SetBoolValue("Display", "LinearFiltering", true); si.SetBoolValue("Display", "IntegerScaling", false); + si.SetBoolValue("Display", "Stretch", false); si.SetBoolValue("Display", "PostProcessing", false); si.SetBoolValue("Display", "ShowOSDMessages", true); si.SetBoolValue("Display", "ShowFPS", false); @@ -593,8 +595,7 @@ void HostInterface::SetDefaultSettings(SettingsInterface& si) si.SetStringValue("MemoryCards", "Card2Path", "memcards" FS_OSPATH_SEPARATOR_STR "shared_card_2.mcd"); si.SetBoolValue("MemoryCards", "UsePlaylistTitle", true); - si.SetStringValue("ControllerPorts", "MultitapMode", - Settings::GetMultitapModeName(Settings::DEFAULT_MULTITAP_MODE)); + si.SetStringValue("ControllerPorts", "MultitapMode", Settings::GetMultitapModeName(Settings::DEFAULT_MULTITAP_MODE)); si.SetStringValue("Logging", "LogLevel", Settings::GetLogLevelName(Settings::DEFAULT_LOG_LEVEL)); si.SetStringValue("Logging", "LogFilter", ""); @@ -655,6 +656,12 @@ void HostInterface::FixIncompatibleSettings(bool display_osd_messages) g_settings.display_linear_filtering = false; } + if (g_settings.display_stretch && g_settings.display_linear_filtering) + { + Log_WarningPrintf("Disabling stretch due to integer upscaling."); + g_settings.display_stretch = false; + } + if (g_settings.gpu_pgxp_enable) { if (g_settings.gpu_renderer == GPURenderer::Software) @@ -884,11 +891,17 @@ void HostInterface::CheckForSettingsChanges(const Settings& old_settings) if (g_settings.multitap_mode != old_settings.multitap_mode) System::UpdateMultitaps(); - if (m_display && g_settings.display_linear_filtering != old_settings.display_linear_filtering) - m_display->SetDisplayLinearFiltering(g_settings.display_linear_filtering); + if (m_display) + { + if (g_settings.display_linear_filtering != old_settings.display_linear_filtering) + m_display->SetDisplayLinearFiltering(g_settings.display_linear_filtering); - if (m_display && g_settings.display_integer_scaling != old_settings.display_integer_scaling) - m_display->SetDisplayIntegerScaling(g_settings.display_integer_scaling); + if (g_settings.display_integer_scaling != old_settings.display_integer_scaling) + m_display->SetDisplayIntegerScaling(g_settings.display_integer_scaling); + + if (g_settings.display_stretch != old_settings.display_stretch) + m_display->SetDisplayStretch(g_settings.display_stretch); + } } void HostInterface::SetUserDirectoryToProgramDirectory() diff --git a/src/core/settings.cpp b/src/core/settings.cpp index 937ca5992..c3816ec43 100644 --- a/src/core/settings.cpp +++ b/src/core/settings.cpp @@ -214,6 +214,7 @@ void Settings::Load(SettingsInterface& si) display_line_end_offset = static_cast(si.GetIntValue("Display", "LineEndOffset", 0)); display_linear_filtering = si.GetBoolValue("Display", "LinearFiltering", true); display_integer_scaling = si.GetBoolValue("Display", "IntegerScaling", false); + display_stretch = si.GetBoolValue("Display", "Stretch", false); display_post_processing = si.GetBoolValue("Display", "PostProcessing", false); display_show_osd_messages = si.GetBoolValue("Display", "ShowOSDMessages", true); display_show_fps = si.GetBoolValue("Display", "ShowFPS", false); @@ -382,6 +383,7 @@ void Settings::Save(SettingsInterface& si) const si.SetStringValue("Display", "AspectRatio", GetDisplayAspectRatioName(display_aspect_ratio)); si.SetBoolValue("Display", "LinearFiltering", display_linear_filtering); si.SetBoolValue("Display", "IntegerScaling", display_integer_scaling); + si.SetBoolValue("Display", "Stretch", display_stretch); si.SetBoolValue("Display", "PostProcessing", display_post_processing); si.SetBoolValue("Display", "ShowOSDMessages", display_show_osd_messages); si.SetBoolValue("Display", "ShowFPS", display_show_fps); diff --git a/src/core/settings.h b/src/core/settings.h index 21b2b8562..24f931439 100644 --- a/src/core/settings.h +++ b/src/core/settings.h @@ -134,6 +134,7 @@ struct Settings bool gpu_24bit_chroma_smoothing = false; bool display_linear_filtering = true; bool display_integer_scaling = false; + bool display_stretch = false; bool display_post_processing = false; bool display_show_osd_messages = false; bool display_show_fps = false; diff --git a/src/duckstation-qt/displaysettingswidget.cpp b/src/duckstation-qt/displaysettingswidget.cpp index 36d0028b2..e647a893a 100644 --- a/src/duckstation-qt/displaysettingswidget.cpp +++ b/src/duckstation-qt/displaysettingswidget.cpp @@ -35,6 +35,8 @@ DisplaySettingsWidget::DisplaySettingsWidget(QtHostInterface* host_interface, QW "LinearFiltering"); SettingWidgetBinder::BindWidgetToBoolSetting(m_host_interface, m_ui.displayIntegerScaling, "Display", "IntegerScaling"); + SettingWidgetBinder::BindWidgetToBoolSetting(m_host_interface, m_ui.displayStretch, "Display", + "Stretch"); SettingWidgetBinder::BindWidgetToBoolSetting(m_host_interface, m_ui.vsync, "Display", "VSync"); SettingWidgetBinder::BindWidgetToBoolSetting(m_host_interface, m_ui.displayAllFrames, "Display", "DisplayAllFrames", false); @@ -99,6 +101,9 @@ DisplaySettingsWidget::DisplaySettingsWidget(QtHostInterface* host_interface, QW m_ui.displayIntegerScaling, tr("Integer Upscaling"), tr("Unchecked"), tr("Adds padding to the display area to ensure that the ratio between pixels on the host to " "pixels in the console is an integer number.
May result in a sharper image in some 2D games.")); + dialog->registerWidgetHelp( + m_ui.displayIntegerScaling, tr("Stretch To Fill"), tr("Unchecked"), + tr("Fills the window with the active display area, regardless of the aspect ratio.")); dialog->registerWidgetHelp( m_ui.vsync, tr("VSync"), tr("Checked"), tr("Enable this option to match DuckStation's refresh rate with your current monitor or screen. " @@ -268,4 +273,5 @@ void DisplaySettingsWidget::onGPUFullscreenModeIndexChanged() void DisplaySettingsWidget::onIntegerFilteringChanged() { m_ui.displayLinearFiltering->setEnabled(!m_ui.displayIntegerScaling->isChecked()); -} \ No newline at end of file + m_ui.displayStretch->setEnabled(!m_ui.displayIntegerScaling->isChecked()); +} diff --git a/src/duckstation-qt/displaysettingswidget.ui b/src/duckstation-qt/displaysettingswidget.ui index 4ddc08a8a..5a5d315db 100644 --- a/src/duckstation-qt/displaysettingswidget.ui +++ b/src/duckstation-qt/displaysettingswidget.ui @@ -6,8 +6,8 @@ 0 0 - 448 - 430 + 485 + 525 @@ -134,18 +134,25 @@ - + - + - Linear Upscaling + Integer Upscaling - + - Integer Upscaling + Stretch To Fill + + + + + + + Linear Upscaling diff --git a/src/duckstation-qt/qthostinterface.cpp b/src/duckstation-qt/qthostinterface.cpp index 9e69505fb..960862a7f 100644 --- a/src/duckstation-qt/qthostinterface.cpp +++ b/src/duckstation-qt/qthostinterface.cpp @@ -447,11 +447,11 @@ void QtHostInterface::onDisplayWindowMouseWheelEvent(const QPoint& delta_angle) void QtHostInterface::onDisplayWindowResized(int width, int height) { - Log_WarningPrintf("resize %dx%d", width, height); // this can be null if it was destroyed and the main thread is late catching up if (!m_display) return; + Log_DevPrintf("Display window resized to %dx%d", width, height); m_display->ResizeRenderWindow(width, height); OnHostDisplayResized(width, height, m_display->GetWindowScale());