From e17d37b8bc6c1fd7fdb50b8ebbbe9a0cc4c15d6f Mon Sep 17 00:00:00 2001 From: Connor McLaughlin <stenzek@gmail.com> Date: Sat, 27 Feb 2021 13:53:03 +1000 Subject: [PATCH] HostDisplay: Add stretch option --- android/app/src/main/res/values/strings.xml | 2 ++ .../src/main/res/xml/display_preferences.xml | 17 ++++++++++--- src/core/host_display.cpp | 6 ++--- src/core/host_display.h | 2 ++ src/core/host_interface.cpp | 25 ++++++++++++++----- src/core/settings.cpp | 2 ++ src/core/settings.h | 1 + src/duckstation-qt/displaysettingswidget.cpp | 8 +++++- src/duckstation-qt/displaysettingswidget.ui | 21 ++++++++++------ src/duckstation-qt/qthostinterface.cpp | 2 +- 10 files changed, 65 insertions(+), 21 deletions(-) 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 @@ <string name="save_state_info_quick_save">Quick Save</string> <string name="settings_osd_show_show_resolution">Show Resolution</string> <string name="settings_summary_osd_show_resolution">Shows the resolution the game is rendering at in the top-right corner of the display.</string> + <string name="settings_summary_display_stretch">Stretches the active display to fill the screen.</string> + <string name="settings_display_stretch">Stretch To Fill</string> </resources> 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" /> + <SwitchPreferenceCompat + app:key="Display/IntegerScaling" + app:title="@string/settings_integer_upscaling" + app:defaultValue="false" + app:disableDependentsState="true" + app:summary="@string/settings_summary_integer_upscaling" + app:iconSpaceReserved="false" /> + <SwitchPreferenceCompat app:key="Display/LinearFiltering" app:title="@string/settings_linear_upscaling" app:defaultValue="true" + app:dependency="Display/IntegerScaling" app:summary="@string/settings_summary_linear_upscaling" app:iconSpaceReserved="false" /> <SwitchPreferenceCompat - app:key="Display/IntegerScaling" - app:title="@string/settings_integer_upscaling" + app:key="Display/Stretch" + app:title="@string/settings_display_stretch" app:defaultValue="false" - app:summary="@string/settings_summary_integer_upscaling" + app:dependency="Display/IntegerScaling" + app:summary="@string/settings_summary_display_stretch" app:iconSpaceReserved="false" /> <SwitchPreferenceCompat @@ -63,6 +73,7 @@ app:defaultValue="true" app:summary="@string/settings_summary_osd_show_messages" app:iconSpaceReserved="false" /> + <SwitchPreferenceCompat app:key="Display/ShowSpeed" app:title="@string/settings_osd_show_speed" diff --git a/src/core/host_display.cpp b/src/core/host_display.cpp index 9d8758bae..b7af94a29 100644 --- a/src/core/host_display.cpp +++ b/src/core/host_display.cpp @@ -148,9 +148,11 @@ void HostDisplay::CalculateDrawRect(s32 window_width, s32 window_height, float* float* out_top_padding, float* out_scale, float* out_x_scale, bool apply_aspect_ratio /* = true */) const { + const float window_ratio = static_cast<float>(window_width) / static_cast<float>(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<float>(m_display_width) / static_cast<float>(m_display_height))) : + (display_aspect_ratio / (static_cast<float>(m_display_width) / static_cast<float>(m_display_height))) : 1.0f; const float display_width = static_cast<float>(m_display_width) * x_scale; const float display_height = static_cast<float>(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<float>(window_width) / static_cast<float>(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<HostDisplayTexture> 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<s8>(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. <br>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 @@ <rect> <x>0</x> <y>0</y> - <width>448</width> - <height>430</height> + <width>485</width> + <height>525</height> </rect> </property> <property name="windowTitle"> @@ -134,18 +134,25 @@ <widget class="QComboBox" name="gpuDownsampleMode"/> </item> <item row="3" column="0" colspan="2"> - <layout class="QGridLayout" name="gridLayout_2"> + <layout class="QGridLayout" name="gridLayout"> <item row="0" column="0"> - <widget class="QCheckBox" name="displayLinearFiltering"> + <widget class="QCheckBox" name="displayIntegerScaling"> <property name="text"> - <string>Linear Upscaling</string> + <string>Integer Upscaling</string> </property> </widget> </item> <item row="0" column="1"> - <widget class="QCheckBox" name="displayIntegerScaling"> + <widget class="QCheckBox" name="displayStretch"> <property name="text"> - <string>Integer Upscaling</string> + <string>Stretch To Fill</string> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="QCheckBox" name="displayLinearFiltering"> + <property name="text"> + <string>Linear Upscaling</string> </property> </widget> </item> 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());