Browse Source

SDL2: Improve best display mode selection (#8166)

pull/8168/head
Gleb Mazovetskiy 7 months ago committed by GitHub
parent
commit
ea8a348371
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 66
      Source/utils/display.cpp

66
Source/utils/display.cpp

@ -260,10 +260,43 @@ void ResizeWindowAndUpdateResolutionOptions()
const auto OptionChangeHandlerFitToScreen = (GetOptions().Graphics.fitToScreen.SetValueChangedCallback(ResizeWindowAndUpdateResolutionOptions), true);
#endif
#ifndef USE_SDL1
#if SDL_VERSION_ATLEAST(2, 0, 0)
const auto OptionChangeHandlerScaleQuality = (GetOptions().Graphics.scaleQuality.SetValueChangedCallback(ReinitializeTexture), true);
const auto OptionChangeHandlerIntegerScaling = (GetOptions().Graphics.integerScaling.SetValueChangedCallback(ReinitializeIntegerScale), true);
const auto OptionChangeHandlerVSync = (GetOptions().Graphics.frameRateControl.SetValueChangedCallback(ReinitializeRenderer), true);
struct DisplayModeComparator {
Size size;
SDL_PixelFormatEnum pixelFormat;
// Is `a` better than `b`?
[[nodiscard]] bool operator()(const SDL_DisplayMode &a, const SDL_DisplayMode &b)
{
const int dwa = a.w - size.width;
const int dha = a.h - size.height;
const int dwb = b.w - size.width;
const int dhb = b.h - size.height;
// A mode that fits the target is always better than one that doesn't:
if (dha >= 0 && dwa >= 0 && (dhb < 0 || dwb < 0)) return true;
if (dhb >= 0 && dwb >= 0 && (dha < 0 || dwa < 0)) return false;
// Either both modes fit or they both don't.
// If they're the same size, prefer one with matching pixel format.
if (pixelFormat != SDL_PIXELFORMAT_UNKNOWN && a.h == b.h && a.w == b.w) {
if (a.format != b.format) {
if (a.format == pixelFormat) return true;
if (b.format == pixelFormat) return false;
}
}
// Prefer smallest height difference, or width difference if heights are the same.
return a.h != b.h ? std::abs(dha) < std::abs(dhb)
: std::abs(dwa) < std::abs(dwb);
}
};
#endif
} // namespace
@ -279,36 +312,17 @@ SDL_DisplayMode GetNearestDisplayMode(Size preferredSize, SDL_PixelFormatEnum pr
const int modeCount = SDL_GetNumDisplayModes(displayIndex);
// First, find the best mode among the modes with the requested pixel format.
SDL_PixelFormatEnum bestPixelFormat = SDL_PIXELFORMAT_UNKNOWN;
std::vector<SDL_DisplayMode> modes;
modes.reserve(modeCount);
for (int modeIndex = 0; modeIndex < modeCount; modeIndex++) {
SDL_DisplayMode displayMode;
if (SDL_GetDisplayMode(displayIndex, modeIndex, &displayMode) != 0)
continue;
const int diffHeight = std::abs(nearestDisplayMode.h - preferredSize.height) - std::abs(displayMode.h - preferredSize.height);
const int diffWidth = std::abs(nearestDisplayMode.w - preferredSize.width) - std::abs(displayMode.w - preferredSize.width);
if (diffHeight < 0)
continue;
if (diffHeight == 0 && diffWidth < 0)
continue;
if (preferredPixelFormat == SDL_PIXELFORMAT_UNKNOWN
|| displayMode.format == preferredPixelFormat) {
nearestDisplayMode = displayMode;
}
modes.push_back(displayMode);
}
if (preferredPixelFormat != SDL_PIXELFORMAT_UNKNOWN && bestPixelFormat == SDL_PIXELFORMAT_UNKNOWN) {
// If no mode with the preferred pixel format was found, allow any pixel format:
for (int modeIndex = 0; modeIndex < modeCount; modeIndex++) {
SDL_DisplayMode displayMode;
if (SDL_GetDisplayMode(displayIndex, modeIndex, &displayMode) != 0)
continue;
const int diffHeight = std::abs(nearestDisplayMode.h - preferredSize.height) - std::abs(displayMode.h - preferredSize.height);
const int diffWidth = std::abs(nearestDisplayMode.w - preferredSize.width) - std::abs(displayMode.w - preferredSize.width);
if (diffHeight < 0)
continue;
if (diffHeight == 0 && diffWidth < 0)
continue;
nearestDisplayMode = displayMode;
}
if (!modes.empty()) {
nearestDisplayMode = *std::min_element(
modes.begin(), modes.end(), DisplayModeComparator { preferredSize, preferredPixelFormat });
}
LogVerbose("Nearest display mode to {}x{} is {}x{} {}bpp {}Hz",

Loading…
Cancel
Save