Skip to content

Commit

Permalink
GPU: Further simplify draw rect calculation
Browse files Browse the repository at this point in the history
Remove "Stretch Vertically" option, it was very confusing to users.

Integer scale will prefer whichever direction gets a larger draw
rectangle/preserves as much detail.
  • Loading branch information
stenzek committed Feb 2, 2025
1 parent 0c3d55a commit 64d3716
Show file tree
Hide file tree
Showing 10 changed files with 63 additions and 62 deletions.
11 changes: 2 additions & 9 deletions src/core/fullscreen_ui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5177,11 +5177,6 @@ void FullscreenUI::DrawGraphicsSettingsPage()
"particularly with the software renderer, and is safe to use."),
"GPU", "UseThread", true);

DrawToggleSetting(
bsi, FSUI_ICONSTR(ICON_FA_ARROWS_ALT_V, "Stretch Display Vertically"),
FSUI_CSTR("Stretches the display to match the aspect ratio by multiplying vertically instead of horizontally."),
"Display", "StretchVertically", false);

DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_FA_EXPAND_ARROWS_ALT, "Automatically Resize Window"),
FSUI_CSTR("Automatically resizes the window to match the internal resolution."), "Display",
"AutoResizeWindow", false);
Expand Down Expand Up @@ -9131,7 +9126,7 @@ TRANSLATE_NOOP("FullscreenUI", "PGXP (Precision Geometry Transform Pipeline)");
TRANSLATE_NOOP("FullscreenUI", "PGXP Depth Buffer");
TRANSLATE_NOOP("FullscreenUI", "PGXP Geometry Correction");
TRANSLATE_NOOP("FullscreenUI", "Parent Directory");
TRANSLATE_NOOP("FullscreenUI", "Password: ");
TRANSLATE_NOOP("FullscreenUI", "Password");
TRANSLATE_NOOP("FullscreenUI", "Patches");
TRANSLATE_NOOP("FullscreenUI", "Patches the BIOS to skip the boot animation. Safe to enable.");
TRANSLATE_NOOP("FullscreenUI", "Path");
Expand Down Expand Up @@ -9329,9 +9324,7 @@ TRANSLATE_NOOP("FullscreenUI", "Start Game");
TRANSLATE_NOOP("FullscreenUI", "Start a game from a disc in your PC's DVD drive.");
TRANSLATE_NOOP("FullscreenUI", "Start the console without any disc inserted.");
TRANSLATE_NOOP("FullscreenUI", "Stores the current settings to a controller preset.");
TRANSLATE_NOOP("FullscreenUI", "Stretch Display Vertically");
TRANSLATE_NOOP("FullscreenUI", "Stretch Mode");
TRANSLATE_NOOP("FullscreenUI", "Stretches the display to match the aspect ratio by multiplying vertically instead of horizontally.");
TRANSLATE_NOOP("FullscreenUI", "Summary");
TRANSLATE_NOOP("FullscreenUI", "Switches back to 4:3 display aspect ratio when displaying 24-bit content, usually FMVs.");
TRANSLATE_NOOP("FullscreenUI", "Switches between full screen and windowed when the window is double-clicked.");
Expand Down Expand Up @@ -9378,7 +9371,7 @@ TRANSLATE_NOOP("FullscreenUI", "Use Old MDEC Routines");
TRANSLATE_NOOP("FullscreenUI", "Use Separate Disc Settings");
TRANSLATE_NOOP("FullscreenUI", "Use Single Card For Multi-Disc Games");
TRANSLATE_NOOP("FullscreenUI", "Use Software Renderer For Readbacks");
TRANSLATE_NOOP("FullscreenUI", "User Name: ");
TRANSLATE_NOOP("FullscreenUI", "User Name");
TRANSLATE_NOOP("FullscreenUI", "Username: {}");
TRANSLATE_NOOP("FullscreenUI", "Uses PGXP for all instructions, not just memory operations.");
TRANSLATE_NOOP("FullscreenUI", "Uses a blit presentation model instead of flipping. This may be needed on some systems.");
Expand Down
69 changes: 47 additions & 22 deletions src/core/gpu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1331,7 +1331,7 @@ void GPU::ConvertScreenCoordinatesToDisplayCoordinates(float window_x, float win
CalculateDrawRect(wi.surface_width, wi.surface_height, m_crtc_state.display_width, m_crtc_state.display_height,
m_crtc_state.display_origin_left, m_crtc_state.display_origin_top, m_crtc_state.display_vram_width,
m_crtc_state.display_vram_height, g_settings.display_rotation, g_settings.display_alignment,
ComputePixelAspectRatio(), g_settings.display_stretch_vertically,
ComputePixelAspectRatio(),
(g_settings.display_scaling == DisplayScalingMode::NearestInteger ||
g_settings.display_scaling == DisplayScalingMode::BilinearInteger),
&display_rc, &draw_rc);
Expand Down Expand Up @@ -1761,31 +1761,54 @@ void GPU::SetTextureWindow(u32 value)
m_draw_mode.texture_window_value = value;
}

static bool IntegerScalePreferWidth(float display_width, float display_height, float pixel_aspect_ratio,
float fwindow_width, float fwindow_height)
{
static constexpr auto get_integer_scale = [](float dwidth, float dheight, float wwidth, float wheight) {
if ((dwidth / dheight) >= (wwidth / wheight))
return std::floor(wwidth / dwidth);
else
return std::floor(wheight / dheight);
};

const float scale_width =
get_integer_scale(display_width * pixel_aspect_ratio, display_height, fwindow_width, fwindow_height);
const float scale_height =
get_integer_scale(display_width, display_height / pixel_aspect_ratio, fwindow_width, fwindow_height);

return (scale_width >= scale_height);
}

void GPU::CalculateDrawRect(u32 window_width, u32 window_height, u32 crtc_display_width, u32 crtc_display_height,
s32 display_origin_left, s32 display_origin_top, u32 display_vram_width,
u32 display_vram_height, DisplayRotation rotation, DisplayAlignment alignment,
float pixel_aspect_ratio, bool stretch_vertically, bool integer_scale,
GSVector4i* display_rect, GSVector4i* draw_rect)
float pixel_aspect_ratio, bool integer_scale, GSVector4i* display_rect,
GSVector4i* draw_rect)
{
const float window_ratio = static_cast<float>(window_width) / static_cast<float>(window_height);
const float x_scale = pixel_aspect_ratio;
const float fwindow_width = static_cast<float>(window_width);
const float fwindow_height = static_cast<float>(window_height);
float display_width = static_cast<float>(crtc_display_width);
float display_height = static_cast<float>(crtc_display_height);
float active_left = static_cast<float>(display_origin_left);
float active_top = static_cast<float>(display_origin_top);
float active_width = static_cast<float>(display_vram_width);
float active_height = static_cast<float>(display_vram_height);
if (!stretch_vertically)

// for integer scale, use whichever gets us a greater effective display size
// this is needed for games like crash where the framebuffer is wide to not lose detail
if (integer_scale ?
IntegerScalePreferWidth(display_width, display_height, pixel_aspect_ratio, fwindow_width, fwindow_height) :
(pixel_aspect_ratio >= 1.0f))
{
display_width *= x_scale;
active_left *= x_scale;
active_width *= x_scale;
display_width *= pixel_aspect_ratio;
active_left *= pixel_aspect_ratio;
active_width *= pixel_aspect_ratio;
}
else
{
display_height /= x_scale;
active_top /= x_scale;
active_height /= x_scale;
display_height /= pixel_aspect_ratio;
active_top /= pixel_aspect_ratio;
active_height /= pixel_aspect_ratio;
}

// swap width/height when rotated, the flipping of padding is taken care of in the shader with the rotation matrix
Expand All @@ -1799,14 +1822,15 @@ void GPU::CalculateDrawRect(u32 window_width, u32 window_height, u32 crtc_displa
// now fit it within the window
float scale;
float left_padding, top_padding;
if ((display_width / display_height) >= window_ratio)
if ((display_width / display_height) >= (fwindow_width / fwindow_height))
{
// align in middle vertically
scale = static_cast<float>(window_width) / display_width;
scale = fwindow_width / display_width;
if (integer_scale)
{
scale = std::max(std::floor(scale), 1.0f);
left_padding = std::max<float>((static_cast<float>(window_width) - display_width * scale) / 2.0f, 0.0f);
// skip integer scaling if we cannot fit in the window at all
scale = (scale >= 1.0f) ? std::floor(scale) : scale;
left_padding = std::max<float>((fwindow_width - display_width * scale) / 2.0f, 0.0f);
}
else
{
Expand All @@ -1816,11 +1840,11 @@ void GPU::CalculateDrawRect(u32 window_width, u32 window_height, u32 crtc_displa
switch (alignment)
{
case DisplayAlignment::RightOrBottom:
top_padding = std::max<float>(static_cast<float>(window_height) - (display_height * scale), 0.0f);
top_padding = std::max<float>(fwindow_height - (display_height * scale), 0.0f);
break;

case DisplayAlignment::Center:
top_padding = std::max<float>((static_cast<float>(window_height) - (display_height * scale)) / 2.0f, 0.0f);
top_padding = std::max<float>((fwindow_height - (display_height * scale)) / 2.0f, 0.0f);
break;

case DisplayAlignment::LeftOrTop:
Expand All @@ -1835,8 +1859,9 @@ void GPU::CalculateDrawRect(u32 window_width, u32 window_height, u32 crtc_displa
scale = static_cast<float>(window_height) / display_height;
if (integer_scale)
{
scale = std::max(std::floor(scale), 1.0f);
top_padding = std::max<float>((static_cast<float>(window_height) - (display_height * scale)) / 2.0f, 0.0f);
// skip integer scaling if we cannot fit in the window at all
scale = (scale >= 1.0f) ? std::floor(scale) : scale;
top_padding = std::max<float>((fwindow_height - (display_height * scale)) / 2.0f, 0.0f);
}
else
{
Expand All @@ -1846,11 +1871,11 @@ void GPU::CalculateDrawRect(u32 window_width, u32 window_height, u32 crtc_displa
switch (alignment)
{
case DisplayAlignment::RightOrBottom:
left_padding = std::max<float>(static_cast<float>(window_width) - (display_width * scale), 0.0f);
left_padding = std::max<float>(fwindow_width - (display_width * scale), 0.0f);
break;

case DisplayAlignment::Center:
left_padding = std::max<float>((static_cast<float>(window_width) - (display_width * scale)) / 2.0f, 0.0f);
left_padding = std::max<float>((fwindow_width - (display_width * scale)) / 2.0f, 0.0f);
break;

case DisplayAlignment::LeftOrTop:
Expand Down
4 changes: 2 additions & 2 deletions src/core/gpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -234,8 +234,8 @@ class GPU final
static void CalculateDrawRect(u32 window_width, u32 window_height, u32 crtc_display_width, u32 crtc_display_height,
s32 display_origin_left, s32 display_origin_top, u32 display_vram_width,
u32 display_vram_height, DisplayRotation rotation, DisplayAlignment alignment,
float pixel_aspect_ratio, bool stretch_vertically, bool integer_scale,
GSVector4i* display_rect, GSVector4i* draw_rect);
float pixel_aspect_ratio, bool integer_scale, GSVector4i* display_rect,
GSVector4i* draw_rect);

private:
TickCount CRTCTicksToSystemTicks(TickCount crtc_ticks, TickCount fractional_ticks) const;
Expand Down
3 changes: 1 addition & 2 deletions src/core/gpu_presenter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1006,8 +1006,7 @@ void GPUPresenter::CalculateDrawRect(s32 window_width, s32 window_height, bool a
apply_alignment ? g_gpu_settings.display_alignment : DisplayAlignment::Center;
GPU::CalculateDrawRect(window_width, window_height, display_width, display_height, display_origin_left,
display_origin_top, display_vram_width, display_vram_height, display_rotation,
display_alignment, display_pixel_aspect_ratio, g_gpu_settings.display_stretch_vertically,
integer_scale, display_rect, draw_rect);
display_alignment, display_pixel_aspect_ratio, integer_scale, display_rect, draw_rect);
}

bool GPUPresenter::PresentFrame(GPUPresenter* presenter, GPUBackend* backend, bool allow_skip_present, u64 present_time)
Expand Down
2 changes: 0 additions & 2 deletions src/core/settings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -333,7 +333,6 @@ void Settings::Load(const SettingsInterface& si, const SettingsInterface& contro
display_show_status_indicators = si.GetBoolValue("Display", "ShowStatusIndicators", true);
display_show_inputs = si.GetBoolValue("Display", "ShowInputs", false);
display_show_enhancements = si.GetBoolValue("Display", "ShowEnhancements", false);
display_stretch_vertically = si.GetBoolValue("Display", "StretchVertically", false);
display_auto_resize_window = si.GetBoolValue("Display", "AutoResizeWindow", false);
display_osd_scale = si.GetFloatValue("Display", "OSDScale", DEFAULT_OSD_SCALE);
display_osd_margin = si.GetFloatValue("Display", "OSDMargin", ImGuiManager::DEFAULT_SCREEN_MARGIN);
Expand Down Expand Up @@ -644,7 +643,6 @@ void Settings::Save(SettingsInterface& si, bool ignore_base) const
si.SetFloatValue("Display", "OSDMargin", display_osd_margin);
}

si.SetBoolValue("Display", "StretchVertically", display_stretch_vertically);
si.SetBoolValue("Display", "AutoResizeWindow", display_auto_resize_window);

si.SetIntValue("CDROM", "ReadaheadSectors", cdrom_readahead_sectors);
Expand Down
1 change: 0 additions & 1 deletion src/core/settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,6 @@ struct GPUSettings
bool display_show_status_indicators : 1 = true;
bool display_show_inputs : 1 = false;
bool display_show_enhancements : 1 = false;
bool display_stretch_vertically : 1 = false;
bool display_auto_resize_window : 1 = false;
float display_pre_frame_sleep_buffer = DEFAULT_DISPLAY_PRE_FRAME_SLEEP_BUFFER;
float display_osd_scale = DEFAULT_OSD_SCALE;
Expand Down
1 change: 0 additions & 1 deletion src/core/system.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4481,7 +4481,6 @@ void System::CheckForSettingsChanges(const Settings& old_settings)
g_settings.display_scaling != old_settings.display_scaling ||
g_settings.display_alignment != old_settings.display_alignment ||
g_settings.display_rotation != old_settings.display_rotation ||
g_settings.display_stretch_vertically != old_settings.display_stretch_vertically ||
g_settings.display_deinterlacing_mode != old_settings.display_deinterlacing_mode ||
g_settings.display_osd_scale != old_settings.display_osd_scale ||
g_settings.display_osd_margin != old_settings.display_osd_margin ||
Expand Down
5 changes: 0 additions & 5 deletions src/duckstation-qt/graphicssettingswidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -131,8 +131,6 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsWindow* dialog, QWidget*
Settings::DEFAULT_DISPLAY_ROTATION);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.disableMailboxPresentation, "Display",
"DisableMailboxPresentation", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.stretchDisplayVertically, "Display", "StretchVertically",
false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.automaticallyResizeWindow, "Display", "AutoResizeWindow",
false);
#ifdef _WIN32
Expand Down Expand Up @@ -435,9 +433,6 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsWindow* dialog, QWidget*
m_ui.disableMailboxPresentation, tr("Disable Mailbox Presentation"), tr("Unchecked"),
tr("Forces the use of FIFO over Mailbox presentation, i.e. double buffering instead of triple buffering. "
"Usually results in worse frame pacing."));
dialog->registerWidgetHelp(
m_ui.stretchDisplayVertically, tr("Stretch Vertically"), tr("Unchecked"),
tr("Prefers stretching the display vertically instead of horizontally, when applying the display aspect ratio."));
dialog->registerWidgetHelp(m_ui.automaticallyResizeWindow, tr("Automatically Resize Window"), tr("Unchecked"),
tr("Automatically resizes the window to match the internal resolution. <strong>For high "
"internal resolutions, this will create very large windows.</strong>"));
Expand Down
27 changes: 10 additions & 17 deletions src/duckstation-qt/graphicssettingswidget.ui
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@
<item>
<widget class="QTabWidget" name="tabs">
<property name="currentIndex">
<number>0</number>
<number>1</number>
</property>
<property name="documentMode">
<bool>true</bool>
Expand Down Expand Up @@ -340,20 +340,6 @@
</item>
<item row="2" column="0" colspan="2">
<layout class="QGridLayout" name="advancedDisplayOptionsLayout">
<item row="1" column="0">
<widget class="QCheckBox" name="disableMailboxPresentation">
<property name="text">
<string>Disable Mailbox Presentation</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QCheckBox" name="blitSwapChain">
<property name="text">
<string>Use Blit Swap Chain</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QCheckBox" name="automaticallyResizeWindow">
<property name="text">
Expand All @@ -362,9 +348,16 @@
</widget>
</item>
<item row="0" column="1">
<widget class="QCheckBox" name="stretchDisplayVertically">
<widget class="QCheckBox" name="disableMailboxPresentation">
<property name="text">
<string>Stretch Vertically</string>
<string>Disable Mailbox Presentation</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="blitSwapChain">
<property name="text">
<string>Use Blit Swap Chain</string>
</property>
</widget>
</item>
Expand Down
Loading

0 comments on commit 64d3716

Please sign in to comment.