From 51d1587b2117365e44cb947da4527430fb56d7de Mon Sep 17 00:00:00 2001 From: Superstarxalien Date: Sat, 21 Jan 2023 14:51:55 -0400 Subject: [PATCH] Improve Integer Scaling behavior ...so it always upscales the display from the framebuffer to fit the aspect ratio by stretching either horizontally or vertically instead of always stretching horizontally, which sometimes (actually most of the time) downscales the image --- src/core/host_display.cpp | 67 ++++++++++++++++--- src/core/settings.cpp | 2 + src/core/settings.h | 1 + src/duckstation-qt/advancedsettingswidget.cpp | 4 ++ src/frontend-common/fullscreen_ui.cpp | 3 + 5 files changed, 68 insertions(+), 9 deletions(-) diff --git a/src/core/host_display.cpp b/src/core/host_display.cpp index b765e27c5..eb9983cfb 100644 --- a/src/core/host_display.cpp +++ b/src/core/host_display.cpp @@ -227,12 +227,39 @@ void HostDisplay::CalculateDrawRect(s32 window_width, s32 window_height, float* apply_aspect_ratio ? (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); - const float active_left = static_cast(m_display_active_left) * x_scale; - const float active_top = static_cast(m_display_active_top); - const float active_width = static_cast(m_display_active_width) * x_scale; - const float active_height = static_cast(m_display_active_height); + const float display_width_stretched = static_cast(m_display_width) * x_scale; + const float display_width_pre = + (display_width_stretched > static_cast(m_display_width)) ? + display_width_stretched : static_cast(m_display_width); + const float display_width = g_settings.display_always_stretch_horizontally ? display_width_stretched : + display_width_pre; + const float active_left_stretched = static_cast(m_display_active_left) * x_scale; + const float active_left_pre = + (display_width_stretched > static_cast(m_display_width)) ? + active_left_stretched : static_cast(m_display_active_left); + const float active_left = g_settings.display_always_stretch_horizontally ? active_left_stretched : + active_left_pre; + const float active_width_stretched = static_cast(m_display_active_width) * x_scale; + const float active_width_pre = + (display_width_stretched > static_cast(m_display_width)) ? + active_width_stretched : static_cast(m_display_active_width); + const float active_width = g_settings.display_always_stretch_horizontally ? active_width_stretched : + active_width_pre; + const float display_height_pre = + (display_width_stretched < static_cast(m_display_width)) ? + static_cast(m_display_height) / x_scale : static_cast(m_display_height); + const float display_height = g_settings.display_always_stretch_horizontally ? + static_cast(m_display_height) : display_height_pre; + const float active_top_pre = + (display_width_stretched < static_cast(m_display_width)) ? + static_cast(m_display_active_top) / x_scale : static_cast(m_display_active_top); + const float active_top = g_settings.display_always_stretch_horizontally ? + static_cast(m_display_active_top) : active_top_pre; + const float active_height_pre = + (display_width_stretched < static_cast(m_display_width)) ? + static_cast(m_display_active_height) / x_scale : static_cast(m_display_active_height); + const float active_height = g_settings.display_always_stretch_horizontally ? + static_cast(m_display_active_height) : active_height_pre; if (out_x_scale) *out_x_scale = x_scale; @@ -360,8 +387,17 @@ std::tuple HostDisplay::ConvertWindowCoordinatesToDisplayCoordinat const float scaled_display_y = static_cast(window_y) - top_padding; // scale back to internal resolution - const float display_x = scaled_display_x / scale / x_scale; - const float display_y = scaled_display_y / scale; + const float display_x_stretched = scaled_display_x / scale / x_scale; + const float display_x_pre = + (display_x_stretched > (scaled_display_x / scale)) ? + display_x_stretched : (scaled_display_x / scale); + const float display_x = g_settings.display_always_stretch_horizontally ? + display_x_stretched : display_x_pre; + const float display_y_pre = + (display_x_stretched < (scaled_display_x / scale)) ? + scaled_display_y / scale * x_scale : scaled_display_y / scale; + const float display_y = g_settings.display_always_stretch_horizontally ? + scaled_display_y / scale : display_y_pre; return std::make_tuple(display_x, display_y); } @@ -488,7 +524,20 @@ bool HostDisplay::WriteDisplayTextureToFile(std::string filename, bool full_reso const float ss_width_scale = static_cast(m_display_active_width) / static_cast(m_display_width); const float ss_height_scale = static_cast(m_display_active_height) / static_cast(m_display_height); const float ss_aspect_ratio = m_display_aspect_ratio * ss_width_scale / ss_height_scale; - resize_width = static_cast(static_cast(resize_height) * ss_aspect_ratio); + const float resize_width_stretched = static_cast(resize_height) * ss_aspect_ratio; + const float resize_width_pre = + (static_cast(resize_width_stretched) > m_display_texture_view_width) ? + resize_width_stretched : static_cast(m_display_texture_view_width); + resize_width = g_settings.display_always_stretch_horizontally ? + static_cast(resize_width_stretched) : static_cast(resize_width_pre); + if (!g_settings.display_always_stretch_horizontally) + { + resize_height = + (static_cast(resize_width_stretched) < m_display_texture_view_width) ? + static_cast(static_cast(resize_height) / + (m_display_aspect_ratio / (static_cast(m_display_width) / static_cast(m_display_height)))) : + resize_height; + } } else { diff --git a/src/core/settings.cpp b/src/core/settings.cpp index 89b50e158..460c70d2b 100644 --- a/src/core/settings.cpp +++ b/src/core/settings.cpp @@ -270,6 +270,7 @@ void Settings::Load(SettingsInterface& si) display_show_enhancements = si.GetBoolValue("Display", "ShowEnhancements", false); display_all_frames = si.GetBoolValue("Display", "DisplayAllFrames", false); display_internal_resolution_screenshots = si.GetBoolValue("Display", "InternalResolutionScreenshots", false); + display_always_stretch_horizontally = si.GetBoolValue("Display", "AlwaysStretchHorizontally", false); video_sync_enabled = si.GetBoolValue("Display", "VSync", DEFAULT_VSYNC_VALUE); display_post_process_chain = si.GetStringValue("Display", "PostProcessChain", ""); display_max_fps = si.GetFloatValue("Display", "MaxFPS", DEFAULT_DISPLAY_MAX_FPS); @@ -487,6 +488,7 @@ void Settings::Save(SettingsInterface& si) const si.SetBoolValue("Display", "ShowEnhancements", display_show_enhancements); si.SetBoolValue("Display", "DisplayAllFrames", display_all_frames); si.SetBoolValue("Display", "InternalResolutionScreenshots", display_internal_resolution_screenshots); + si.SetBoolValue("Display", "AlwaysStretchHorizontally", display_always_stretch_horizontally); si.SetBoolValue("Display", "VSync", video_sync_enabled); if (display_post_process_chain.empty()) si.DeleteValue("Display", "PostProcessChain"); diff --git a/src/core/settings.h b/src/core/settings.h index 1461a9870..27bfbba86 100644 --- a/src/core/settings.h +++ b/src/core/settings.h @@ -143,6 +143,7 @@ struct Settings bool display_show_enhancements = false; bool display_all_frames = false; bool display_internal_resolution_screenshots = false; + bool display_always_stretch_horizontally = false; bool video_sync_enabled = DEFAULT_VSYNC_VALUE; float display_osd_scale = 100.0f; float display_max_fps = DEFAULT_DISPLAY_MAX_FPS; diff --git a/src/duckstation-qt/advancedsettingswidget.cpp b/src/duckstation-qt/advancedsettingswidget.cpp index a21fc5465..5a3f84d62 100644 --- a/src/duckstation-qt/advancedsettingswidget.cpp +++ b/src/duckstation-qt/advancedsettingswidget.cpp @@ -288,6 +288,9 @@ void AdvancedSettingsWidget::addTweakOptions() addBooleanTweakOption(m_dialog, m_ui.tweakOptionTable, tr("Use Debug Host GPU Device"), "GPU", "UseDebugDevice", false); + addBooleanTweakOption(m_dialog, m_ui.tweakOptionTable, tr("Always Stretch Display Horizontally"), "Display", + "AlwaysStretchHorizontally", false); + addBooleanTweakOption(m_dialog, m_ui.tweakOptionTable, tr("Increase Timer Resolution"), "Main", "IncreaseTimerResolution", true); @@ -354,6 +357,7 @@ void AdvancedSettingsWidget::onResetToDefaultClicked() sif->DeleteValue("Display", "ActiveEndOffset"); sif->DeleteValue("Display", "LineStartOffset"); sif->DeleteValue("Display", "LineEndOffset"); + sif->DeleteValue("Display", "AlwaysStretchHorizontally"); sif->DeleteValue("GPU", "Multisamples"); sif->DeleteValue("GPU", "PerSampleShading"); sif->DeleteValue("GPU", "PGXPVertexCache"); diff --git a/src/frontend-common/fullscreen_ui.cpp b/src/frontend-common/fullscreen_ui.cpp index 3ec2dec5d..d308d0f32 100644 --- a/src/frontend-common/fullscreen_ui.cpp +++ b/src/frontend-common/fullscreen_ui.cpp @@ -4506,6 +4506,9 @@ void FullscreenUI::DrawAdvancedSettingsPage() DrawFloatRangeSetting(bsi, "Display FPS Limit", "Limits how many frames are displayed to the screen. These frames are still rendered.", "Display", "MaxFPS", Settings::DEFAULT_DISPLAY_MAX_FPS, 0.0f, 500.0f, "%.2f FPS"); + DrawToggleSetting(bsi, "Always Stretch Display Horizontally", + "Enables old DuckStation behavior for Integer Scaling, where the display is always stretched horizontally.", + "Display", "AlwaysStretchHorizontally", false); MenuHeading("PGXP Settings");