diff --git a/src/pc/configfile.c b/src/pc/configfile.c index 500172dc..63525b84 100644 --- a/src/pc/configfile.c +++ b/src/pc/configfile.c @@ -66,7 +66,8 @@ ConfigWindow configWindow = { .reset = false, .fullscreen = false, .exiting_fullscreen = false, - .settings_changed = false + .settings_changed = false, + .msaa = 0, }; unsigned int configFiltering = 2; // 0=force nearest, 1=linear, 2=three-point unsigned int configMasterVolume = 80; // 0 - MAX_VOLUME @@ -176,6 +177,7 @@ static const struct ConfigOption options[] = { {.name = "window_h", .type = CONFIG_TYPE_UINT, .uintValue = &configWindow.h}, {.name = "vsync", .type = CONFIG_TYPE_BOOL, .boolValue = &configWindow.vsync}, {.name = "texture_filtering", .type = CONFIG_TYPE_UINT, .uintValue = &configFiltering}, + {.name = "msaa", .type = CONFIG_TYPE_UINT, .uintValue = &configWindow.msaa}, {.name = "master_volume", .type = CONFIG_TYPE_UINT, .uintValue = &configMasterVolume}, {.name = "music_volume", .type = CONFIG_TYPE_UINT, .uintValue = &configMusicVolume}, {.name = "sfx_volume", .type = CONFIG_TYPE_UINT, .uintValue = &configSfxVolume}, diff --git a/src/pc/configfile.h b/src/pc/configfile.h index 3b496124..00aff835 100644 --- a/src/pc/configfile.h +++ b/src/pc/configfile.h @@ -25,6 +25,7 @@ typedef struct { bool fullscreen; bool exiting_fullscreen; bool settings_changed; + unsigned int msaa; } ConfigWindow; extern ConfigWindow configWindow; diff --git a/src/pc/djui/djui_panel_display.c b/src/pc/djui/djui_panel_display.c index 2717cb78..5061b3e6 100644 --- a/src/pc/djui/djui_panel_display.c +++ b/src/pc/djui/djui_panel_display.c @@ -6,8 +6,13 @@ #include "pc/utils/misc.h" #include "pc/configfile.h" +#define MSAA_ORIGINAL_UNSET ((u32)-1) + static struct DjuiInputbox* sFrameLimitInput = NULL; static struct DjuiSelectionbox* sInterpolationSelectionBox = NULL; +static struct DjuiText* sRestartText = NULL; +static u32 sMsaaSelection = 0; +static u32 sMsaaOriginal = MSAA_ORIGINAL_UNSET; static void djui_panel_display_apply(UNUSED struct DjuiBase* caller) { configWindow.settings_changed = true; @@ -30,9 +35,29 @@ static void djui_panel_display_frame_limit_text_change(struct DjuiBase* caller) djui_base_set_enabled(&sInterpolationSelectionBox->base, (configFrameLimit > 30 || (configFrameLimit <= 30 && configUncappedFramerate))); } +static void djui_panel_display_msaa_change(UNUSED struct DjuiBase* caller) { + switch (sMsaaSelection) { + case 1: configWindow.msaa = 2; break; + case 2: configWindow.msaa = 4; break; + case 3: configWindow.msaa = 8; break; + case 4: configWindow.msaa = 16; break; + default: configWindow.msaa = 0; break; + } + + if (sMsaaOriginal != configWindow.msaa) { + djui_text_set_text(sRestartText, DLANG(DISPLAY, MUST_RESTART)); + } else { + djui_text_set_text(sRestartText, ""); + } +} + void djui_panel_display_create(struct DjuiBase* caller) { struct DjuiThreePanel* panel = djui_panel_menu_create(DLANG(DISPLAY, DISPLAY)); struct DjuiBase* body = djui_three_panel_get_body(panel); + struct DjuiSelectionbox* msaa = NULL; + + // save original msaa value + if (sMsaaOriginal == MSAA_ORIGINAL_UNSET) { sMsaaOriginal = configWindow.msaa; } { djui_checkbox_create(body, DLANG(DISPLAY, FULLSCREEN), &configWindow.fullscreen, djui_panel_display_apply); @@ -74,10 +99,38 @@ void djui_panel_display_create(struct DjuiBase* caller) { char* filterChoices[3] = { DLANG(DISPLAY, NEAREST), DLANG(DISPLAY, LINEAR), DLANG(DISPLAY, TRIPOINT) }; djui_selectionbox_create(body, DLANG(DISPLAY, FILTERING), filterChoices, 3, &configFiltering, NULL); + int maxMsaa = wm_api->get_max_msaa(); + if (maxMsaa >= 2) { + if (configWindow.msaa >= 16) { sMsaaSelection = 4; } + else if (configWindow.msaa >= 8) { sMsaaSelection = 3; } + else if (configWindow.msaa >= 4) { sMsaaSelection = 2; } + else if (configWindow.msaa >= 2) { sMsaaSelection = 1; } + else { sMsaaSelection = 0; } + + int choiceCount = 2; + if (maxMsaa >= 16) { choiceCount = 5; } + else if (maxMsaa >= 8) { choiceCount = 4; } + else if (maxMsaa >= 4) { choiceCount = 3; } + + char* msaaChoices[5] = { DLANG(DISPLAY, OFF), "2x", "4x", "8x", "16x" }; + msaa = djui_selectionbox_create(body, DLANG(DISPLAY, ANTIALIASING), msaaChoices, choiceCount, &sMsaaSelection, djui_panel_display_msaa_change); + } + char* drawDistanceChoices[6] = { DLANG(DISPLAY, D0P5X), DLANG(DISPLAY, D1X), DLANG(DISPLAY, D1P5X), DLANG(DISPLAY, D3X), DLANG(DISPLAY, D10X), DLANG(DISPLAY, D100X) }; djui_selectionbox_create(body, DLANG(DISPLAY, DRAW_DISTANCE), drawDistanceChoices, 6, &configDrawDistance, NULL); djui_button_create(body, DLANG(MENU, BACK), DJUI_BUTTON_STYLE_BACK, djui_panel_menu_back); + + sRestartText = djui_text_create(body, ""); + djui_text_set_alignment(sRestartText, DJUI_HALIGN_CENTER, DJUI_VALIGN_TOP); + djui_base_set_color(&sRestartText->base, 255, 100, 100, 255); + djui_base_set_size_type(&sRestartText->base, DJUI_SVT_RELATIVE, DJUI_SVT_ABSOLUTE); + djui_base_set_size(&sRestartText->base, 1.0f, 64); + } + + // force the restart text to update + if (msaa) { + djui_panel_display_msaa_change(&msaa->base); } djui_panel_add(caller, panel, NULL); diff --git a/src/pc/gfx/gfx_dummy.c b/src/pc/gfx/gfx_dummy.c index 5ae1d353..aed6594b 100644 --- a/src/pc/gfx/gfx_dummy.c +++ b/src/pc/gfx/gfx_dummy.c @@ -80,6 +80,10 @@ static void gfx_dummy_wm_delay(u32 ms) { sleep_ms(ms); } +static int gfx_dummy_get_max_msaa(void) { + return 0; +} + static void gfx_dummy_set_window_title(UNUSED const char* title) { } @@ -208,6 +212,7 @@ struct GfxWindowManagerAPI gfx_dummy_wm_api = { gfx_dummy_wm_set_clipboard_text, gfx_dummy_wm_set_cursor_visible, gfx_dummy_wm_delay, + gfx_dummy_get_max_msaa, gfx_dummy_set_window_title, gfx_dummy_reset_window_title }; diff --git a/src/pc/gfx/gfx_dxgi.cpp b/src/pc/gfx/gfx_dxgi.cpp index 602b792f..0aa56897 100644 --- a/src/pc/gfx/gfx_dxgi.cpp +++ b/src/pc/gfx/gfx_dxgi.cpp @@ -665,6 +665,10 @@ void gfx_dxgi_delay(u32 ms) { Sleep(ms); } +static int gfx_dxgi_get_max_msaa(void) { + return 0; +} + static void gfx_dxgi_set_window_title(const char* title) { SetWindowTextA(dxgi.h_wnd, title); } @@ -742,6 +746,7 @@ struct GfxWindowManagerAPI gfx_dxgi = { gfx_dxgi_set_clipboard_text, gfx_dxgi_set_cursor_visible, gfx_dxgi_delay, + gfx_dxgi_get_max_msaa, gfx_dxgi_set_window_title, gfx_dxgi_reset_window_title }; diff --git a/src/pc/gfx/gfx_sdl1.c b/src/pc/gfx/gfx_sdl1.c index e0073355..49398979 100644 --- a/src/pc/gfx/gfx_sdl1.c +++ b/src/pc/gfx/gfx_sdl1.c @@ -188,6 +188,10 @@ static void gfx_sdl_delay(u32 ms) { SDL_Delay(ms); } +static int gfx_sdl_get_max_msaa(void) { + return 0; +} + static void gfx_sdl_set_window_title(const char* title) { SDL_WM_SetCaption(title, NULL); } @@ -224,6 +228,7 @@ struct GfxWindowManagerAPI gfx_sdl = { gfx_sdl_set_clipboard_text, gfx_sdl_set_cursor_visible, gfx_sdl_delay, + gfx_sdl_get_max_msaa, gfx_sdl_set_window_title, gfx_sdl_reset_window_title }; diff --git a/src/pc/gfx/gfx_sdl2.c b/src/pc/gfx/gfx_sdl2.c index 36f3b4e2..547308be 100644 --- a/src/pc/gfx/gfx_sdl2.c +++ b/src/pc/gfx/gfx_sdl2.c @@ -120,6 +120,13 @@ static void gfx_sdl_init(const char *window_title) { SDL_Init(SDL_INIT_VIDEO); SDL_StartTextInput(); + if (configWindow.msaa > 0) { + SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1); + SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, configWindow.msaa); + } else { + SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 0); + } + SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); @@ -259,6 +266,13 @@ static void gfx_sdl_delay(u32 ms) { SDL_Delay(ms); } +static int gfx_sdl_get_max_msaa(void) { + int maxSamples = 0; + glGetIntegerv(GL_MAX_SAMPLES, &maxSamples); + if (maxSamples > 16) { maxSamples = 16; } + return maxSamples; +} + static void gfx_sdl_set_window_title(const char* title) { SDL_SetWindowTitle(wnd, title); } @@ -298,6 +312,7 @@ struct GfxWindowManagerAPI gfx_sdl = { gfx_sdl_set_clipboard_text, gfx_sdl_set_cursor_visible, gfx_sdl_delay, + gfx_sdl_get_max_msaa, gfx_sdl_set_window_title, gfx_sdl_reset_window_title }; diff --git a/src/pc/gfx/gfx_window_manager_api.h b/src/pc/gfx/gfx_window_manager_api.h index cb613c30..ebb5eefb 100644 --- a/src/pc/gfx/gfx_window_manager_api.h +++ b/src/pc/gfx/gfx_window_manager_api.h @@ -26,6 +26,7 @@ struct GfxWindowManagerAPI { void (*set_clipboard_text)(char*); void (*set_cursor_visible)(bool); void (*delay)(unsigned int ms); + int (*get_max_msaa)(void); void (*set_window_title)(const char* title); void (*reset_window_title)(void); }; diff --git a/src/pc/pc_main.c b/src/pc/pc_main.c index 493784c4..3c2e9447 100644 --- a/src/pc/pc_main.c +++ b/src/pc/pc_main.c @@ -306,12 +306,7 @@ void game_exit(void) { void* main_game_init(void* isThreaded) { gIsThreaded = isThreaded != NULL; - const char *userpath = gCLIOpts.savePath[0] ? gCLIOpts.savePath : sys_user_path(); - fs_init(sys_ropaths, FS_BASEDIR, userpath); - - // load config - configfile_load(); - configWindow.settings_changed = true; + // load language if (!djui_language_init(configLanguage)) { snprintf(configLanguage, MAX_CONFIG_STRING, "%s", ""); } if (gIsThreaded) { REFRESH_MUTEX(loading_screen_set_segment_text("Loading")); } @@ -374,6 +369,10 @@ int main(int argc, char *argv[]) { #endif + const char *userpath = gCLIOpts.savePath[0] ? gCLIOpts.savePath : sys_user_path(); + fs_init(sys_ropaths, FS_BASEDIR, userpath); + configfile_load(); + // Create the window straight away if (!gGfxInited) { gfx_init(&WAPI, &RAPI, TITLE);