From 6b5fbd189d5f7c24da01daa1bf2eff6222551102 Mon Sep 17 00:00:00 2001 From: Ludwig Nussel Date: Sat, 8 Dec 2007 10:08:05 +0000 Subject: [PATCH] detect available resolutions and offer them in the menu Store the resolutions detected by SDL in a cvar. The mod code can then optionally use the cvar to offer a better choice in the menu. Signed-off-by: Ludwig Nussel --- code/q3_ui/ui_video.c | 147 ++++++++++++++++++++++++++++++++++++------ code/sdl/sdl_glimp.c | 44 +++++++++++++ 2 files changed, 172 insertions(+), 19 deletions(-) diff --git a/code/q3_ui/ui_video.c b/code/q3_ui/ui_video.c index 1a7e7f70..813b3e8e 100644 --- a/code/q3_ui/ui_video.c +++ b/code/q3_ui/ui_video.c @@ -24,6 +24,66 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA void GraphicsOptions_MenuInit( void ); +static const char *builtin_resolutions[] = +{ + "320x240", + "400x300", + "512x384", + "640x480", + "800x600", + "960x720", + "1024x768", + "1152x864", + "1280x1024", + "1600x1200", + "2048x1536", + "856x480 wide screen", + NULL +}; + +static char resbuf[MAX_STRING_CHARS]; +static const char* detected_resolutions[32]; + +static const char** reslist = builtin_resolutions; +static int use_builtin_resolutions = qtrue; + +static int det2builtinres(int mode) +{ + int i; + + if(use_builtin_resolutions) + return mode; + + if(mode < 0) + return -1; + + for(i = 0; builtin_resolutions[i]; ++i) + { + if(!strcmp(builtin_resolutions[i], detected_resolutions[mode])) + return i; + } + return -1; +} + +static int builtin2detres(int mode) +{ + int i; + + if(use_builtin_resolutions) + return mode; + + if(mode < 0) + return -1; + + for(i = 0; detected_resolutions[i]; ++i) + { + if(!strcmp(builtin_resolutions[mode], detected_resolutions[i])) + return i; + } + return -1; +} + + /* ======================================================================= @@ -480,7 +540,28 @@ static void GraphicsOptions_ApplyChanges( void *unused, int notification ) } trap_Cvar_SetValue( "r_picmip", 3 - s_graphicsoptions.tq.curvalue ); trap_Cvar_SetValue( "r_allowExtensions", s_graphicsoptions.allow_extensions.curvalue ); - trap_Cvar_SetValue( "r_mode", s_graphicsoptions.mode.curvalue ); + + if(!use_builtin_resolutions) + { + // search for builtin mode that matches the detected mode + int i; + int mode = s_graphicsoptions.mode.curvalue; + i = det2builtinres(mode); + if(i == -1) + { + char w[16], h[16]; + Q_strncpyz(w, detected_resolutions[mode], sizeof(w)); + *strchr(w, 'x') = 0; + Q_strncpyz(h, strchr(detected_resolutions[mode], 'x')+1, sizeof(h)); + trap_Cvar_Set( "r_customwidth", w); + trap_Cvar_Set( "r_customheight", h); + } + + trap_Cvar_SetValue( "r_mode", i ); + } + else + trap_Cvar_SetValue( "r_mode", s_graphicsoptions.mode.curvalue ); + trap_Cvar_SetValue( "r_fullscreen", s_graphicsoptions.fs.curvalue ); trap_Cvar_SetValue( "r_colorbits", 0 ); trap_Cvar_SetValue( "r_depthbits", 0 ); @@ -615,9 +696,33 @@ GraphicsOptions_SetMenuItems static void GraphicsOptions_SetMenuItems( void ) { s_graphicsoptions.mode.curvalue = trap_Cvar_VariableValue( "r_mode" ); + s_graphicsoptions.mode.curvalue = builtin2detres(s_graphicsoptions.mode.curvalue); if ( s_graphicsoptions.mode.curvalue < 0 ) { - s_graphicsoptions.mode.curvalue = 3; + if(use_builtin_resolutions) + { + s_graphicsoptions.mode.curvalue = 3; + } + else + { + int i; + char buf[MAX_STRING_CHARS]; + trap_Cvar_VariableStringBuffer("r_customwidth", buf, sizeof(buf)-2); + buf[strlen(buf)+1] = 0; + buf[strlen(buf)] = 'x'; + trap_Cvar_VariableStringBuffer("r_customheight", buf+strlen(buf), sizeof(buf)-strlen(buf)); + + for(i = 0; detected_resolutions[i]; ++i) + { + if(!strcmp(buf, detected_resolutions[i])) + { + s_graphicsoptions.mode.curvalue = i; + break; + } + } + if ( s_graphicsoptions.mode.curvalue < 0 ) + s_graphicsoptions.mode.curvalue = 0; + } } s_graphicsoptions.fs.curvalue = trap_Cvar_VariableValue("r_fullscreen"); s_graphicsoptions.allow_extensions.curvalue = trap_Cvar_VariableValue("r_allowExtensions"); @@ -743,22 +848,6 @@ void GraphicsOptions_MenuInit( void ) NULL }; - static const char *resolutions[] = - { - "320x240", - "400x300", - "512x384", - "640x480", - "800x600", - "960x720", - "1024x768", - "1152x864", - "1280x1024", - "1600x1200", - "2048x1536", - "856x480 wide screen", - NULL - }; static const char *filter_names[] = { "Bilinear", @@ -784,6 +873,26 @@ void GraphicsOptions_MenuInit( void ) // zero set all our globals memset( &s_graphicsoptions, 0 ,sizeof(graphicsoptions_t) ); + + Q_strncpyz(resbuf, UI_Cvar_VariableString("r_availableModes"), sizeof(resbuf)); + if(*resbuf) + { + char* s = resbuf; + unsigned i = 0; + while( s && i < sizeof(detected_resolutions)/sizeof(detected_resolutions[0])-1) + { + detected_resolutions[i++] = s; + s = strchr(s, ' '); + if(s) *s++ = '\0'; + } + detected_resolutions[i] = NULL; + if(i) + { + reslist = detected_resolutions; + use_builtin_resolutions = 0; + } + } + GraphicsOptions_Cache(); s_graphicsoptions.menu.wrapAround = qtrue; @@ -888,7 +997,7 @@ void GraphicsOptions_MenuInit( void ) s_graphicsoptions.mode.generic.flags = QMF_PULSEIFFOCUS|QMF_SMALLFONT; s_graphicsoptions.mode.generic.x = 400; s_graphicsoptions.mode.generic.y = y; - s_graphicsoptions.mode.itemnames = resolutions; + s_graphicsoptions.mode.itemnames = reslist; s_graphicsoptions.mode.generic.callback = GraphicsOptions_Event; s_graphicsoptions.mode.generic.id = ID_MODE; y += BIGCHAR_HEIGHT+2; diff --git a/code/sdl/sdl_glimp.c b/code/sdl/sdl_glimp.c index a1e1a27a..be2ab180 100644 --- a/code/sdl/sdl_glimp.c +++ b/code/sdl/sdl_glimp.c @@ -110,6 +110,46 @@ void GLimp_LogComment( char *comment ) { } +static void set_available_modes(void) +{ + char buf[MAX_STRING_CHARS]; + SDL_Rect **modes; + size_t len = 0; + int i; + + modes = SDL_ListModes(NULL, SDL_OPENGL | SDL_FULLSCREEN); + + if (!modes) + { + ri.Printf( PRINT_WARNING, "Can't get list of available modes\n"); + return; + } + + if (modes == (SDL_Rect **)-1) + { + ri.Printf( PRINT_ALL, "Display supports any resolution\n"); + return; // can set any resolution + } + + for (i = 0; modes[i]; ++i) + { + if(snprintf(NULL, 0, "%ux%u ", modes[i]->w, modes[i]->h) < (int)sizeof(buf)-len) + { + len += sprintf(buf+len, "%ux%u ", modes[i]->w, modes[i]->h); + } + else + { + ri.Printf( PRINT_WARNING, "Skipping mode %ux%x, buffer too small\n", modes[i]->w, modes[i]->h); + } + } + if(len) + { + buf[strlen(buf)-1] = 0; + ri.Printf( PRINT_ALL, "Available modes: '%s'\n", buf); + ri.Cvar_Set( "r_availableModes", buf ); + } +} + /* =============== GLimp_SetMode @@ -275,6 +315,8 @@ static int GLimp_SetMode( int mode, qboolean fullscreen ) break; } + set_available_modes(); + if (!vidscreen) { ri.Printf( PRINT_ALL, "Couldn't get a visual\n" ); @@ -526,6 +568,8 @@ void GLimp_Init( void ) // initialize extensions GLimp_InitExtensions( ); + ri.Cvar_Get( "r_availableModes", "", CVAR_ROM ); + // This depends on SDL_INIT_VIDEO, hence having it here IN_Init( );