diff --git a/port/fast3d/gfx_modes.h b/port/fast3d/gfx_modes.h deleted file mode 100644 index 1fe895c41..000000000 --- a/port/fast3d/gfx_modes.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef GFX_MODES_H -#define GFX_MODES_H - -struct GfxModes { - char mode[10]; -}; - -#endif diff --git a/port/fast3d/gfx_sdl2.cpp b/port/fast3d/gfx_sdl2.cpp index e69615953..5ddacd407 100644 --- a/port/fast3d/gfx_sdl2.cpp +++ b/port/fast3d/gfx_sdl2.cpp @@ -6,7 +6,6 @@ #include "platform.h" #include "system.h" -#include "gfx_modes.h" #include "gfx_window_manager_api.h" #include "gfx_screen_config.h" @@ -389,51 +388,39 @@ static bool gfx_sdl_set_swap_interval(int interval) { return success; } -static GfxModes *gfx_sdl_alloc_display_modes(GfxModes *modes, int *num_modes) { - static const char *alloc_failed_msg = "failed to allocate video display modes"; - const int disp_idx = SDL_GetWindowDisplayIndex(wnd); - const int display_modes = SDL_GetNumDisplayModes(disp_idx); - int modes_sz = sizeof *modes * 16; - - modes = (GfxModes *)malloc(modes_sz); - if (!modes) { - sysLogPrintf(LOG_ERROR, "malloc: %s", alloc_failed_msg); +int gfx_sdl_get_display_mode(int modenum, int *out_w, int *out_h) { + const int display_in_use = SDL_GetWindowDisplayIndex(wnd); + SDL_DisplayMode sdlmode; + if (SDL_GetDisplayMode(display_in_use, modenum, &sdlmode) == 0) { + *out_w = sdlmode.w; + *out_h = sdlmode.h; + return 1; } + return 0; +} - strncpy(modes[0].mode, "Custom", sizeof modes[0].mode); - modes[0].mode[sizeof modes[0].mode - 1] = '\0'; - - int j = 1; - for (int i = 0; i < display_modes; ++i) { - SDL_DisplayMode mode = {}; - if (SDL_GetDisplayMode(disp_idx, i, &mode) == 0) { - if (j == (int)(modes_sz / sizeof *modes)) { - modes = (GfxModes *)realloc(modes, modes_sz <<= 1); - if (!modes) { - sysLogPrintf(LOG_ERROR, "realloc: %s", alloc_failed_msg); - } - } - - snprintf(modes[j].mode, sizeof modes[0].mode, "%dx%d", mode.w, mode.h); - - if (j && strcmp(modes[j].mode, modes[j - 1].mode) != 0) { - ++j; - } - } +int gfx_sdl_get_current_display_mode(int *out_w, int *out_h) { + const int display_in_use = SDL_GetWindowDisplayIndex(wnd); + SDL_DisplayMode sdlmode; + if (SDL_GetCurrentDisplayMode(display_in_use, &sdlmode) == 0) { + *out_w = sdlmode.w; + *out_h = sdlmode.h; + return 1; } + return 0; +} - *num_modes = j; - modes_sz = *num_modes * sizeof *modes; - modes = (GfxModes *)realloc(modes, modes_sz); - if (!modes) { - sysLogPrintf(LOG_ERROR, "realloc: %s", alloc_failed_msg); - } - return modes; +int gfx_sdl_get_num_display_modes(void) { + const int display_in_use = SDL_GetWindowDisplayIndex(wnd); + return SDL_GetNumDisplayModes(display_in_use); } struct GfxWindowManagerAPI gfx_sdl = { gfx_sdl_init, gfx_sdl_close, + gfx_sdl_get_display_mode, + gfx_sdl_get_current_display_mode, + gfx_sdl_get_num_display_modes, gfx_sdl_get_fullscreen_state, gfx_sdl_set_fullscreen_changed_callback, gfx_sdl_set_fullscreen, @@ -458,5 +445,4 @@ struct GfxWindowManagerAPI gfx_sdl = { gfx_sdl_get_window_handle, gfx_sdl_set_window_title, gfx_sdl_set_swap_interval, - gfx_sdl_alloc_display_modes, }; diff --git a/port/fast3d/gfx_window_manager_api.h b/port/fast3d/gfx_window_manager_api.h index 0dc2ddd9a..4883a79cc 100644 --- a/port/fast3d/gfx_window_manager_api.h +++ b/port/fast3d/gfx_window_manager_api.h @@ -20,6 +20,9 @@ struct GfxWindowInitSettings { struct GfxWindowManagerAPI { void (*init)(const struct GfxWindowInitSettings *settings); void (*close)(void); + int (*get_display_mode)(int modenum, int *out_w, int *out_h); + int (*get_current_display_mode)(int *out_w, int *out_h); + int (*get_num_display_modes)(void); int32_t (*get_fullscreen_state)(void); void (*set_fullscreen_changed_callback)(void (*on_fullscreen_changed)(bool is_now_fullscreen)); void (*set_fullscreen)(bool enable); @@ -44,7 +47,6 @@ struct GfxWindowManagerAPI { void *(*get_window_handle)(void); void (*set_window_title)(const char *); bool (*set_swap_interval)(int); - struct GfxModes *(*alloc_display_modes)(struct GfxModes *, int *); }; #endif diff --git a/port/include/video.h b/port/include/video.h index 5c22f466e..97f9e4082 100644 --- a/port/include/video.h +++ b/port/include/video.h @@ -11,6 +11,11 @@ #define VIDEO_MAX_FPS 240 #endif +typedef struct { + s32 width; + s32 height; +} displaymode; + s32 videoInit(void); void videoStartFrame(void); void videoSubmitCommands(Gfx *cmds); @@ -36,18 +41,16 @@ u32 videoGetTextureFilter(void); s32 videoGetTextureFilter2D(void); s32 videoGetDetailTextures(void); s32 videoGetDisplayModeIndex(void); -struct GfxModes *videoGetDisplayModes(void); +s32 videoGetDisplayMode(displaymode *out, const s32 index); s32 videoGetNumDisplayModes(void); -void videoAllocDisplayModes(void); - void videoSetWindowOffset(s32 x, s32 y); void videoSetFullscreen(s32 fs); void videoSetFullscreenMode(s32 mode); void videoSetTextureFilter(u32 filter); void videoSetTextureFilter2D(s32 filter); void videoSetDetailTextures(s32 detail); -void videoSetDisplayMode(const s32 mode_idx); +void videoSetDisplayMode(const s32 index); s32 videoCreateFramebuffer(u32 w, u32 h, s32 upscale, s32 autoresize); void videoSetFramebuffer(s32 target); diff --git a/port/src/optionsmenu.c b/port/src/optionsmenu.c index 12e068ea1..b44355a75 100644 --- a/port/src/optionsmenu.c +++ b/port/src/optionsmenu.c @@ -9,7 +9,6 @@ #include "game/mainmenu.h" #include "game/menu.h" #include "game/gamefile.h" -#include "../fast3d/gfx_modes.h" #include "video.h" #include "input.h" #include "config.h" @@ -739,6 +738,10 @@ static MenuItemHandlerResult menuhandlerCenterWindow(s32 operation, struct menui static MenuItemHandlerResult menuhandlerResolution(s32 operation, struct menuitem *item, union handlerdata *data) { + static char resstring[32]; + static const char *rescustom = "Custom"; + displaymode mode; + switch (operation) { case MENUOP_CHECKDISABLED: if (videoGetFullscreen() && videoGetFullscreenMode() == 0) { @@ -749,7 +752,13 @@ static MenuItemHandlerResult menuhandlerResolution(s32 operation, struct menuite data->dropdown.value = videoGetNumDisplayModes(); break; case MENUOP_GETOPTIONTEXT: - return (intptr_t)videoGetDisplayModes()[data->dropdown.value].mode; + videoGetDisplayMode(&mode, data->dropdown.value); + if (mode.width == 0 && mode.height == 0) { + return (intptr_t)rescustom; + } else { + snprintf(resstring, sizeof(resstring), "%dx%d", mode.width, mode.height); + } + return (intptr_t)resstring; case MENUOP_SET: videoSetDisplayMode(data->dropdown.value); break; diff --git a/port/src/video.c b/port/src/video.c index 238fcc386..390ab662e 100644 --- a/port/src/video.c +++ b/port/src/video.c @@ -6,7 +6,7 @@ #include #include "platform.h" #include "config.h" -#include "../fast3d/gfx_modes.h" +#include "system.h" #include "video.h" #include "../fast3d/gfx_api.h" @@ -41,8 +41,9 @@ static s32 vidAllowHiDpi = false; static s32 vidVsync = 1; static s32 vidMSAA = 1; static s32 vidFramerateLimit = 0; -static struct GfxModes *vidModes = NULL; // Allocated in videoAllocDisplayModes(). Freed in videoShutdown(). -static s32 vidNumModes = 0; +static displaymode vidModeDefault; +static s32 vidNumModes = 1; +static displaymode *vidModes = &vidModeDefault; static s32 texFilter = FILTER_LINEAR; static s32 texFilter2D = true; @@ -53,6 +54,8 @@ static u32 frames = 0; static u32 framesPerSec = 0; static f64 startTime, endTime, fpsTime; +static s32 videoInitDisplayModes(void); + s32 videoInit(void) { wmAPI = &gfx_sdl; @@ -83,7 +86,7 @@ s32 videoInit(void) }; gfx_init(&set); - videoAllocDisplayModes(); + videoInitDisplayModes(); if (!wmAPI->set_swap_interval(vidVsync)) { vidVsync = 0; @@ -211,26 +214,72 @@ f32 videoGetAspect(void) s32 videoGetDisplayModeIndex(void) { - for (int i = 1; i < vidNumModes; ++i) { - char tmp[10] = {0}; - snprintf(tmp, sizeof tmp, "%dx%d", gfx_current_dimensions.width, gfx_current_dimensions.height); - if (strcmp(tmp, vidModes[i].mode) == 0) { + for (s32 i = 1; i < vidNumModes; ++i) { + if (vidModes[i].width == gfx_current_dimensions.width && + vidModes[i].height == gfx_current_dimensions.height) { return i; } } - // Current dimensions don't match any known mode, so return index 0, "Custom". return 0; } -void videoAllocDisplayModes(void) +static s32 videoInitDisplayModes(void) { - vidModes = wmAPI->alloc_display_modes(vidModes, &vidNumModes); + if (!wmAPI->get_current_display_mode(&vidModeDefault.width, &vidModeDefault.height)) { + vidModeDefault.width = 640; + vidModeDefault.height = 480; + return false; + } + + const s32 numBaseModes = wmAPI->get_num_display_modes(); + if (!numBaseModes) { + return false; + } + + const s32 numCustomModes = 1; + displaymode *modeList = sysMemZeroAlloc((numBaseModes + numCustomModes) * sizeof(displaymode)); + if (!modeList) { + return false; + } + + modeList[0].width = 0; + modeList[0].height = 0; + + s32 numModes = 1; + s32 w = -1, h = w, neww = w, newh = w; + + // SDL modes are guaranteed to be sorted high to low + for (s32 i = 0; i < numBaseModes; ++i) { + wmAPI->get_display_mode(i, &neww, &newh); + + if (neww != w || newh != h) { + w = neww; + h = newh; + modeList[numModes].width = w; + modeList[numModes].height = h; + ++numModes; + } + } + + modeList = sysMemRealloc(modeList, numModes * sizeof(displaymode)); + if (!modeList) { + return false; + } + + vidModes = modeList; + vidNumModes = numModes; + + return true; } -struct GfxModes *videoGetDisplayModes(void) +s32 videoGetDisplayMode(displaymode *out, const s32 index) { - return vidModes; + if (index >= 0 && index < vidNumModes) { + *out = vidModes[index]; + return true; + } + return false; } s32 videoGetNumDisplayModes(void) @@ -238,19 +287,17 @@ s32 videoGetNumDisplayModes(void) return vidNumModes; } -void videoSetDisplayMode(const s32 mode_idx) +void videoSetDisplayMode(const s32 index) { - const char *cur_mode = vidModes[mode_idx].mode; - char *x_pos = NULL; + const displaymode dm = vidModes[index]; - if (mode_idx == 0) { + if (index == 0) { // "Custom" video mode. return; } - vidWidth = strtol(cur_mode, &x_pos, 10); - cur_mode = x_pos + 1; - vidHeight = strtol(cur_mode, NULL, 10); + vidWidth = dm.width; + vidHeight = dm.height; s32 posX = 100; s32 posY = 100;