game: ensure the default game-size is also valid when initializing the pc-settings.gc file (#3624)

Also saves out the default `pc-settings.gc` file so it's less confusing
_and_ so we can request it from users to actually see what it's doing.

The fix in the last release was only to fix bad `game-size` values when
_loading_ the file. But if you don't have a file, it picks a default.

Right now it picks that default by:
1. Your largest reported resolution
2. If that fails, the one that is currently set

In reality this scenario can never really happen (if you have a set
resolution, it will be one of the reported ones). However what can
happen is for SDL to be misinformed by bad display/monitor drivers/the
OS and be given "supported" resolutions that aren't actually supported.
For example some users have a 4K resolution as their highest, despite
them using a 1080p monitor.

The solution is to not blindly assume the largest resolution is valid,
instead use the one the user already has set.

I'm also now filtering out resolutions by refresh rate, as perhaps this
also caused a problem. ie. the monitor supports a resolution if the
refresh rate is lowered, but it's currently set high (at 144hz for
example).
This commit is contained in:
Tyler Wilding 2024-08-03 14:57:07 -04:00 committed by GitHub
parent a13b0dce45
commit 8b7e0bde53
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 46 additions and 19 deletions

View File

@ -322,3 +322,6 @@ endif()
add_executable(gk main.cpp)
target_link_libraries(gk runtime)
if(WIN32)
set_target_properties(gk PROPERTIES VS_DPI_AWARE "PerMonitor")
endif()

View File

@ -187,7 +187,7 @@ Resolution DisplayManager::get_resolution(int id) {
}
bool DisplayManager::is_supported_resolution(int width, int height) {
for (const auto resolution : m_available_resolutions) {
for (const auto& resolution : m_available_resolutions) {
if (resolution.width == width && resolution.height == height) {
return true;
}
@ -358,6 +358,10 @@ void DisplayManager::update_video_modes() {
DisplayMode new_mode = {display_name_str, curr_mode.format, curr_mode.w,
curr_mode.h, curr_mode.refresh_rate, orient};
m_current_display_modes[display_id] = new_mode;
lg::info(
"[DISPLAY]: Found monitor {}, currently set to {}x{}@{}hz. Format: {}, Orientation: {}",
new_mode.display_name, new_mode.screen_width, new_mode.screen_height, new_mode.refresh_rate,
new_mode.sdl_pixel_format, static_cast<int>(new_mode.orientation));
}
update_resolutions();
}
@ -365,17 +369,29 @@ void DisplayManager::update_video_modes() {
void DisplayManager::update_resolutions() {
lg::info("[DISPLAY] Enumerating resolutions");
// Enumerate display's display modes to get the resolutions
auto num_display_modes = SDL_GetNumDisplayModes(get_active_display_id());
const auto active_display_id = get_active_display_id();
const auto active_refresh_rate = m_current_display_modes[active_display_id].refresh_rate;
auto num_display_modes = SDL_GetNumDisplayModes(active_display_id);
SDL_DisplayMode curr_mode;
for (int i = 0; i < num_display_modes; i++) {
auto ok = SDL_GetDisplayMode(get_active_display_id(), i, &curr_mode);
auto ok = SDL_GetDisplayMode(active_display_id, i, &curr_mode);
if (ok != 0) {
sdl_util::log_error(fmt::format("unable to get display mode for display {}, index {}",
get_active_display_id(), i));
sdl_util::log_error(
fmt::format("unable to get display mode for display {}, index {}", active_display_id, i));
continue;
}
// Skip resolutions that aren't using the current refresh rate, they won't work.
// For example if your monitor is currently set to `60hz` and the monitor _could_ support
// resolution X but only at `30hz`...then there's no reason for us to consider it as an option.
if (curr_mode.refresh_rate != active_refresh_rate) {
lg::debug(
"[DISPLAY]: Skipping {}x{} as it requires {}hz but the monitor is currently set to {}hz",
curr_mode.w, curr_mode.h, curr_mode.refresh_rate, active_refresh_rate);
continue;
}
Resolution new_res = {curr_mode.w, curr_mode.h,
static_cast<float>(curr_mode.w) / static_cast<float>(curr_mode.h)};
lg::info("[DISPLAY]: {}x{} is supported", new_res.width, new_res.height);
m_available_resolutions.push_back(new_res);
}

View File

@ -34,13 +34,14 @@
(defmethod set-window-size! ((obj pc-settings) (width int) (height int))
"sets the size of the display window"
(let ((display-mode (pc-get-display-mode)))
(format 0 "Setting ~A size to ~D x ~D~%" display-mode width height)
(cond
((= display-mode 'windowed)
(set! (-> obj window-width) width)
(set! (-> obj window-height) height)
(format 0 "Setting window size to ~D x ~D~%" width height)
(pc-set-window-size! (max PC_MIN_WIDTH (-> obj window-width)) (max PC_MIN_HEIGHT (-> obj window-height))))
(else
(format 0 "Setting borderless/fullscreen size to ~D x ~D~%" width height)
(set! (-> obj width) width)
(set! (-> obj height) height))))
(none))
@ -642,7 +643,11 @@
(unless (read-from-file obj *pc-temp-string-1*)
(format 0 "[PC] PC Settings found at '~S' but could not be loaded, using defaults!~%" *pc-temp-string-1*)
(reset obj #t)))
(else (format 0 "[PC] PC Settings not found at '~S'...initializing with defaults!~%" *pc-temp-string-1*) (reset obj #t)))
(else
(format 0 "[PC] PC Settings not found at '~S'...initializing with defaults!~%" *pc-temp-string-1*)
(reset obj #t)
;; save the file so users aren't confused, and so we can debug what the game is producing for them
(commit-to-file obj)))
0)
(defmethod initialize ((obj pc-settings))

View File

@ -318,18 +318,21 @@
(set! (-> obj aspect-ratio-auto?) #t)
(set! (-> obj vsync?) #t)
(set! (-> obj letterbox?) #t)
;; get screen size and set to borderless at screen res (if retail)
(cond
((> (pc-get-num-resolutions) 0)
;; pick first available resolution by default
(pc-get-resolution 0 (&-> obj width) (&-> obj height)))
(else
;; somehow didn't get a single resolution. this is pretty bad.
(pc-get-active-display-size (&-> obj width) (&-> obj height))
(max! (-> obj width) PC_MIN_WIDTH)
(max! (-> obj height) PC_MIN_HEIGHT)
(format 0 "!!!! failed to get any screen resolutions !!!!")))
(format 0 "fullscreen resolution defaulted to ~D x ~D~%" (-> obj width) (-> obj height))
;; default to the displays currently chosen resolution
(pc-get-active-display-size (&-> obj width) (&-> obj height))
(max! (-> obj width) PC_MIN_WIDTH)
(max! (-> obj height) PC_MIN_HEIGHT)
;; ensure the default resolution was a valid choice
(let* ((saved-width (-> obj width))
(saved-height (-> obj height))
(supported-resolution? (pc-is-supported-resolution? saved-width saved-height)))
(cond
(supported-resolution?
(format 0 "[PC Settings]: Valid default game-size resolution set ~D x ~D~%" saved-width saved-height))
(else
(pc-get-active-display-size (&-> obj width) (&-> obj height))
(format 0 "[PC Settings]: Invalid game-size resolution ~D x ~D, defaulting to ~D x ~D~%" saved-width saved-height (-> obj width) (-> obj height)))))
(format 0 "[PC Settings]: fullscreen resolution defaulted to ~D x ~D~%" (-> obj width) (-> obj height))
(set! (-> obj gfx-msaa) PC_DEFAULT_MSAA) ;; default msaa
0)