From 7b123e9d3ab4b05b2e9f4dca59ad4af0cb9cc253 Mon Sep 17 00:00:00 2001 From: Louis Gombert Date: Tue, 25 Feb 2025 22:58:15 +0100 Subject: [PATCH] Default resolution choices: use display resolutions if possible --- Descent3/config.cpp | 118 +++++++++++++++++++++++++++++++----- Descent3/config.h | 36 ++++++++--- Descent3/descent.cpp | 2 + Descent3/game.cpp | 40 ++---------- Descent3/init.cpp | 21 +------ Descent3/pilot_class.cpp | 4 +- renderer/HardwareOpenGL.cpp | 28 ++------- 7 files changed, 148 insertions(+), 101 deletions(-) diff --git a/Descent3/config.cpp b/Descent3/config.cpp index 16a025c6..bcdbedb5 100644 --- a/Descent3/config.cpp +++ b/Descent3/config.cpp @@ -304,14 +304,18 @@ #include "ctlconfig.h" #include "d3music.h" #include "gameloop.h" +#include "args.h" + +#include #include #include +#include #define STAT_SCORE STAT_TIMER -std::vector Video_res_list = {{0,0}, - {512, 384}, +// This list is only used if `ConfigureDisplayResolutions` fails +std::vector Video_res_list = {{512, 384}, {640, 480}, {800, 600}, {960, 720}, @@ -336,9 +340,95 @@ std::vector Video_res_list = {{0,0}, {3440, 1440}, {3840, 1600}}; -const int DEFAULT_RESOLUTION = 0; // Screen resolution -int Game_video_resolution = DEFAULT_RESOLUTION; +int Default_resolution_id = 7; // 1280x720 in the default list +int Current_video_resolution_id = Default_resolution_id; float Render_FOV_setting = 72.0f; +int Display_id = 0; + +void ConfigureDisplayResolutions() { + int display_count = 0; + SDL_DisplayID *displays = SDL_GetDisplays(&display_count); + if (!displays) { + return; + } + + std::set resolutions; + for (int d = 0; d < display_count; d++) { + SDL_DisplayID display_id = displays[d]; + + int modes_count = 0; + SDL_DisplayMode **modes = SDL_GetFullscreenDisplayModes(display_id, &modes_count); + if (!modes) { + return; + } + for (int modes_id = 0; modes_id < modes_count; modes_id++) { + SDL_DisplayMode *mode = modes[modes_id]; + resolutions.emplace(tVideoResolution{static_cast(mode->w), static_cast(mode->h)}); + } + + SDL_free(modes); + } + + // Take width and height argument into account + int widtharg = FindArg("-Width"); + int heightarg = FindArg("-Height"); + + if (widtharg && !heightarg) { + LOG_ERROR << "Specify '-Height' argument when setting '-Width'"; + } + if (heightarg && !widtharg) { + LOG_ERROR << "Specify '-Width' argument when setting '-Height'"; + } + + // Use the first display by default, or the one specified by "-display" + int display_arg = FindArg("-display"); + int display_num = 0; + if (display_arg != 0) { + if (const char *arg_index_str = GetArg(display_arg + 1); arg_index_str == nullptr) { + LOG_WARNING << "No parameter for -display given"; + } else { + int arg_index = atoi(arg_index_str); + if ((arg_index < 0) || (arg_index >= display_count)) { + LOG_WARNING.printf("Parameter for -display must be in the range 0..%i", display_count - 1); + } else { + display_num = arg_index; + } + } + } + + Display_id = displays[display_num]; + + // Use either the CLI-provided resolution or the current display resolution as default + tVideoResolution current_resolution; + if (widtharg && heightarg) { + current_resolution.width = static_cast(atoi(GameArgs[widtharg + 1])); + current_resolution.height = static_cast(atoi(GameArgs[heightarg + 1])); + resolutions.emplace(current_resolution); + } else { + const SDL_DisplayMode *current_mode = SDL_GetCurrentDisplayMode(Display_id); + current_resolution.width = static_cast(current_mode->w); + current_resolution.height = static_cast(current_mode->h); + } + + // Fill in Video_res_list from the set of unique resolutions + std::vector resolutions_vec; + std::copy(resolutions.begin(), resolutions.end(), std::back_inserter(resolutions_vec)); + if (resolutions_vec.empty()) { + return; + } + std::swap(resolutions_vec, Video_res_list); + SDL_free(displays); + + // Find the index of the current screen resolution in the list + auto current_res_id = std::find(Video_res_list.begin(), Video_res_list.end(), current_resolution); + if (current_res_id != Video_res_list.end()) { + Default_resolution_id = static_cast(current_res_id - Video_res_list.begin()); + } else { + Default_resolution_id = 0; // default to the highest supported resolution + } + + Current_video_resolution_id = Default_resolution_id; +} tDetailSettings Detail_settings; int Default_detail_level = DETAIL_LEVEL_MED; @@ -660,7 +750,6 @@ static void config_gamma() { } } - ////////////////////////////////////////////////////////////////// // VIDEO MENU // @@ -678,14 +767,13 @@ struct video_menu { // sets the menu up. newuiSheet *setup(newuiMenu *menu) { - int iTemp = 0; sheet = menu->AddOption(IDV_VCONFIG, TXT_OPTVIDEO, NEWUIMENU_MEDIUM); // video resolution sheet->NewGroup(TXT_RESOLUTION, 0, 0); constexpr int RES_BUFFER_SIZE = 15; resolution_string = sheet->AddChangeableText(RES_BUFFER_SIZE); - std::string res = Video_res_list[Game_video_resolution].getName(); + std::string res = Video_res_list[Current_video_resolution_id].getName(); snprintf(resolution_string, res.size() + 1, res.c_str()); sheet->AddLongButton("Change", IDV_CHANGE_RES_WINDOW); @@ -694,10 +782,11 @@ struct video_menu { settings.min_val.f = D3_DEFAULT_FOV; settings.max_val.f = 90.f; settings.type = SLIDER_UNITS_FLOAT; - fov = sheet->AddSlider("FOV", static_cast(settings.max_val.f - settings.min_val.f), static_cast(Render_FOV_setting - D3_DEFAULT_FOV), - &settings); + fov = sheet->AddSlider("FOV", static_cast(settings.max_val.f - settings.min_val.f), + static_cast(Render_FOV_setting - D3_DEFAULT_FOV), &settings); #if !defined(POSIX) + int iTemp = 0; // renderer bit depth switch (Render_preferred_bitdepth) { case 16: @@ -751,10 +840,9 @@ struct video_menu { SetScreenMode(GetScreenMode(), true); - int temp_w = Video_res_list[Game_video_resolution].width; - int temp_h = Video_res_list[Game_video_resolution].height; + int temp_w = Video_res_list[Current_video_resolution_id].width; + int temp_h = Video_res_list[Current_video_resolution_id].height; Current_pilot.set_hud_data(NULL, NULL, NULL, &temp_w, &temp_h); - } Render_FOV_setting = static_cast(fov[0]) + D3_DEFAULT_FOV; @@ -788,7 +876,7 @@ struct video_menu { menu.Open(); - resolution_list->SetCurrentIndex(Game_video_resolution); + resolution_list->SetCurrentIndex(Current_video_resolution_id); int res; do { @@ -798,8 +886,8 @@ struct video_menu { if (res == UID_OK) { int newindex = resolution_list->GetCurrentIndex(); if (static_cast(newindex) < Video_res_list.size()) { - Game_video_resolution = newindex; - std::string res = Video_res_list[Game_video_resolution].getName(); + Current_video_resolution_id = newindex; + std::string res = Video_res_list[Current_video_resolution_id].getName(); snprintf(resolution_string, res.size() + 1, res.c_str()); } } diff --git a/Descent3/config.h b/Descent3/config.h index 4a7c750e..8086a3b2 100644 --- a/Descent3/config.h +++ b/Descent3/config.h @@ -132,24 +132,46 @@ struct tGameToggles { extern tGameToggles Game_toggles; -// this list should match the list in config.cpp to work. -#define N_SUPPORTED_VIDRES 8 - // stored resolution list and desired game resolution -struct tVideoResolution { +struct tVideoResolution +{ uint16_t width; uint16_t height; - std::string getName() const { + std::string getName() const + { std::stringstream ss; ss << this->width << "x" << this->height; return ss.str(); } + + bool operator==(const tVideoResolution& other) { + return other.width == this->width && other.height == this->height; + } + + struct tVideoResolutionCompare + { + bool operator()(const tVideoResolution &lres, const tVideoResolution &rres) const + { + if (lres.width != rres.width) + { + return lres.width < rres.width; + } + return lres.height < rres.height; + } + }; }; extern std::vector Video_res_list; -extern const int DEFAULT_RESOLUTION; -extern int Game_video_resolution; +extern int Default_resolution_id; +extern int Current_video_resolution_id; +extern int Display_id; + +/** + * List all unique resolutions for the detected displays, + * and set variables Video_res_list, Game_video_resolution and Display_id + */ +void ConfigureDisplayResolutions(); //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! // KEEP THESE MEMBERS IN THE SAME ORDER, IF YOU ADD,REMOVE, OR CHANGE ANYTHING IN THIS STRUCT, MAKE SURE YOU diff --git a/Descent3/descent.cpp b/Descent3/descent.cpp index f09cb4f9..0bf0c64e 100644 --- a/Descent3/descent.cpp +++ b/Descent3/descent.cpp @@ -407,6 +407,7 @@ #include "args.h" #include "multi_dll_mgr.h" #include "localization.h" +#include "config.h" #include "uisys.h" // --------------------------------------------------------------------------- @@ -475,6 +476,7 @@ void Descent3() { } // Show intro & loading screens if not dedicated server if (!Dedicated_server) { + ConfigureDisplayResolutions(); SetScreenMode(SM_CINEMATIC); // Show the intro movie diff --git a/Descent3/game.cpp b/Descent3/game.cpp index 358da032..787796f2 100644 --- a/Descent3/game.cpp +++ b/Descent3/game.cpp @@ -910,32 +910,6 @@ int GetScreenMode() { return Screen_mode; } int rend_initted = 0; int Low_vidmem = 0; -int GetSDLDisplayId() { - int display_num = 0; - int display_arg = FindArg("-display"); - int display_count = 0; - - SDL_DisplayID *displays = SDL_GetDisplays(&display_count); - - if (display_arg != 0) { - if (const char *arg_index_str = GetArg(display_arg + 1); arg_index_str == nullptr) { - LOG_WARNING << "No parameter for -display given"; - } else { - int arg_index = atoi(arg_index_str); - if ((arg_index < 0) || (arg_index >= display_count)) { - LOG_WARNING.printf("Parameter for -display must be in the range 0..%i", display_count - 1); - } else { - display_num = arg_index; - } - } - } - - int display_id = displays[display_num]; - SDL_free(displays); - - return display_id; -} - void SetScreenMode(int sm, bool force_res_change) { static int old_sm = SM_NULL; static int rend_width = 0, rend_height = 0; @@ -966,17 +940,11 @@ void SetScreenMode(int sm, bool force_res_change) { rend_initted = 0; } } else { - // Default resolution: use current display mode - int display_id = GetSDLDisplayId(); - const SDL_DisplayMode *mode = SDL_GetCurrentDisplayMode(display_id); - Video_res_list[0].width = mode->w; - Video_res_list[0].height = mode->h; - int scr_width, scr_height, scr_bitdepth; if (sm == SM_GAME) { - scr_width = Video_res_list[Game_video_resolution].width; - scr_height = Video_res_list[Game_video_resolution].height; + scr_width = Video_res_list[Current_video_resolution_id].width; + scr_height = Video_res_list[Current_video_resolution_id].height; scr_bitdepth = Render_preferred_bitdepth; } else { scr_width = FIXED_SCREEN_WIDTH; @@ -1013,7 +981,7 @@ void SetScreenMode(int sm, bool force_res_change) { // We're using the default, so change some values for the menus rend_initted = 1; LOG_INFO << "Changing menu settings to default!"; - Game_video_resolution = DEFAULT_RESOLUTION; + Current_video_resolution_id = Default_resolution_id; Render_preferred_state.bit_depth = 32; scr_width = 640; scr_height = 480; @@ -1031,7 +999,7 @@ void SetScreenMode(int sm, bool force_res_change) { // We're using the default, so change some values for the menus rend_initted = 1; LOG_INFO << "Changing menu settings to default!"; - Game_video_resolution = DEFAULT_RESOLUTION; + Current_video_resolution_id = Default_resolution_id; Render_preferred_state.bit_depth = 32; scr_width = 640; scr_height = 480; diff --git a/Descent3/init.cpp b/Descent3/init.cpp index 32b41cc4..a54d2417 100644 --- a/Descent3/init.cpp +++ b/Descent3/init.cpp @@ -1157,7 +1157,7 @@ void SaveGameSettings() { Database->write("DetailObjectComp", Detail_settings.Object_complexity); Database->write("DetailPowerupHalos", Detail_settings.Powerup_halos); - Database->write("RS_resolution", Game_video_resolution); + Database->write("RS_resolution", Current_video_resolution_id); Database->write("RS_fov", static_cast(Render_FOV_setting)); Database->write("RS_bitdepth", Render_preferred_bitdepth); @@ -1234,7 +1234,7 @@ void LoadGameSettings() { D3Use_force_feedback = true; D3Force_gain = 1.0f; D3Force_auto_center = true; - Game_video_resolution = DEFAULT_RESOLUTION; + Current_video_resolution_id = Default_resolution_id; PlayPowerupVoice = true; PlayVoices = true; Sound_mixer = SOUND_MIXER_SOFTWARE_16; @@ -1290,7 +1290,7 @@ void LoadGameSettings() { Database->read_int("RoomLeveling", &Default_player_room_leveling); Database->read("Specmapping", &Detail_settings.Specular_lighting); Database->read("RS_bitdepth", &Render_preferred_bitdepth, sizeof(Render_preferred_bitdepth)); - Database->read_int("RS_resolution", &Game_video_resolution); + Database->read_int("RS_resolution", &Current_video_resolution_id); int tempfov = 0; Database->read_int("RS_fov", &tempfov); @@ -1369,21 +1369,6 @@ void LoadGameSettings() { Database->read_int("PredefDetailSetting", &level); ConfigSetDetailLevel(level); - int widtharg = FindArg("-Width"); - int heightarg = FindArg("-Height"); - - if (widtharg && !heightarg) { - LOG_ERROR << "Specify '-Height' argument when setting '-Width'"; - } - if (heightarg && !widtharg) { - LOG_ERROR << "Specify '-Width' argument when setting '-Height'"; - } - - if (widtharg && heightarg) { - Video_res_list.emplace_back(tVideoResolution{static_cast(atoi(GameArgs[widtharg + 1])), - static_cast(atoi(GameArgs[heightarg + 1]))}); - Game_video_resolution = Video_res_list.size() - 1; - } // Motion blur Use_motion_blur = 0; diff --git a/Descent3/pilot_class.cpp b/Descent3/pilot_class.cpp index d459fff1..59f101a3 100644 --- a/Descent3/pilot_class.cpp +++ b/Descent3/pilot_class.cpp @@ -205,8 +205,8 @@ void pilot::initialize(void) { hud_mode = (uint8_t)HUD_COCKPIT; hud_stat = 0; hud_graphical_stat = STAT_STANDARD; - game_window_w = Video_res_list[Game_video_resolution].width; - game_window_h = Video_res_list[Game_video_resolution].height; + game_window_w = Video_res_list[Current_video_resolution_id].width; + game_window_h = Video_res_list[Current_video_resolution_id].height; num_missions_flown = 0; mission_data = NULL; mouselook_control = false; diff --git a/renderer/HardwareOpenGL.cpp b/renderer/HardwareOpenGL.cpp index 1ef1893d..55459c47 100644 --- a/renderer/HardwareOpenGL.cpp +++ b/renderer/HardwareOpenGL.cpp @@ -353,8 +353,8 @@ void opengl_SetDefaults() { extern renderer_preferred_state Render_preferred_state; int opengl_Setup(oeApplication *app, const int *width, const int *height) { - int winw = Video_res_list[Game_video_resolution].width; - int winh = Video_res_list[Game_video_resolution].height; + int winw = Video_res_list[Current_video_resolution_id].width; + int winh = Video_res_list[Current_video_resolution_id].height; SDL_ClearError(); if (!SDL_WasInit(SDL_INIT_VIDEO)) { @@ -424,27 +424,9 @@ int opengl_Setup(oeApplication *app, const int *width, const int *height) { int display_arg = FindArg("-display"); int display_count = 0; - SDL_DisplayID* displays = SDL_GetDisplays(&display_count); - - if (display_arg != 0) { - if (const char * arg_index_str = GetArg (display_arg + 1); arg_index_str == nullptr) { - LOG_WARNING << "No parameter for -display given"; - } else { - int arg_index = atoi(arg_index_str); - if ((arg_index < 0) || (arg_index >= display_count)) { - LOG_WARNING.printf( "Parameter for -display must be in the range 0..%i", display_count-1 ); - } else { - display_num = arg_index; - } - } - } - - int display_id = displays[display_num]; - SDL_free(displays); - //High-DPI support { - float scale = SDL_GetDisplayContentScale(display_id); + float scale = SDL_GetDisplayContentScale(Display_id); LOG_WARNING.printf("Using content scale %f", scale); winw = std::floor(static_cast(winw)*scale); winh = std::floor(static_cast(winh)*scale); @@ -453,8 +435,8 @@ int opengl_Setup(oeApplication *app, const int *width, const int *height) { SDL_PropertiesID props = SDL_CreateProperties(); SDL_SetStringProperty(props, SDL_PROP_WINDOW_CREATE_TITLE_STRING, "Descent 3"); - SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_X_NUMBER, SDL_WINDOWPOS_UNDEFINED_DISPLAY(display_id)); - SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_Y_NUMBER, SDL_WINDOWPOS_UNDEFINED_DISPLAY(display_id)); + SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_X_NUMBER, SDL_WINDOWPOS_UNDEFINED_DISPLAY(Display_id)); + SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_Y_NUMBER, SDL_WINDOWPOS_UNDEFINED_DISPLAY(Display_id)); SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_WIDTH_NUMBER, winw); SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_HEIGHT_NUMBER, winh); SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_FLAGS_NUMBER, SDL_WINDOW_OPENGL);