forked from Ports/perfect_dark
Allow changing vsync and framerate limit at runtime
Also implements a new menu item flag: MENUITEMFLAG_SLIDER_DEFERRED, which only calls the MENUOP_GETSLIDER callback on entering dimmed mode, storing its value for later ticks, and only calls the MENUOP_SET callback on leaving dimmed mode. This was necessary to prevent the framerate limit slider from immediately affecting the framerate, leading to an annoying slow down as the value was decremented to 0.
This commit is contained in:
7 files changed
+155
-19
No files matched your search
@@ -363,6 +363,10 @@ static double gfx_sdl_get_time(void) {
|
||||
return SDL_GetPerformanceCounter() / (double)qpc_freq;
|
||||
}
|
||||
|
||||
static int32_t gfx_sdl_get_target_fps(void) {
|
||||
return target_fps;
|
||||
}
|
||||
|
||||
static void gfx_sdl_set_target_fps(int fps) {
|
||||
target_fps = fps;
|
||||
}
|
||||
@@ -379,6 +383,10 @@ static void gfx_sdl_set_window_title(const char *title) {
|
||||
SDL_SetWindowTitle(wnd, title);
|
||||
}
|
||||
|
||||
static int gfx_sdl_get_swap_interval(void) {
|
||||
return SDL_GL_GetSwapInterval();
|
||||
}
|
||||
|
||||
static bool gfx_sdl_set_swap_interval(int interval) {
|
||||
const bool success = SDL_GL_SetSwapInterval(interval) >= 0;
|
||||
vsync_enabled = success && (interval != 0);
|
||||
@@ -440,9 +448,11 @@ struct GfxWindowManagerAPI gfx_sdl = {
|
||||
gfx_sdl_swap_buffers_begin,
|
||||
gfx_sdl_swap_buffers_end,
|
||||
gfx_sdl_get_time,
|
||||
gfx_sdl_get_target_fps,
|
||||
gfx_sdl_set_target_fps,
|
||||
gfx_sdl_can_disable_vsync,
|
||||
gfx_sdl_get_window_handle,
|
||||
gfx_sdl_set_window_title,
|
||||
gfx_sdl_get_swap_interval,
|
||||
gfx_sdl_set_swap_interval,
|
||||
};
|
||||
@@ -42,10 +42,12 @@ struct GfxWindowManagerAPI {
|
||||
void (*swap_buffers_begin)(void);
|
||||
void (*swap_buffers_end)(void);
|
||||
double (*get_time)(void); // For debug
|
||||
int32_t (*get_target_fps)(void);
|
||||
void (*set_target_fps)(int fps);
|
||||
bool (*can_disable_vsync)(void);
|
||||
void *(*get_window_handle)(void);
|
||||
void (*set_window_title)(const char *);
|
||||
int (*get_swap_interval)(void);
|
||||
bool (*set_swap_interval)(int);
|
||||
};
|
||||
|
||||
|
||||
@@ -43,6 +43,8 @@ s32 videoGetDetailTextures(void);
|
||||
s32 videoGetDisplayModeIndex(void);
|
||||
s32 videoGetDisplayMode(displaymode *out, const s32 index);
|
||||
s32 videoGetNumDisplayModes(void);
|
||||
s32 videoGetVsync(void);
|
||||
s32 videoGetFramerateLimit(void);
|
||||
|
||||
void videoSetWindowOffset(s32 x, s32 y);
|
||||
void videoSetFullscreen(s32 fs);
|
||||
@@ -51,6 +53,8 @@ void videoSetTextureFilter(u32 filter);
|
||||
void videoSetTextureFilter2D(s32 filter);
|
||||
void videoSetDetailTextures(s32 detail);
|
||||
void videoSetDisplayMode(const s32 index);
|
||||
void videoSetVsync(const s32 vsync);
|
||||
void videoSetFramerateLimit(const s32 limit);
|
||||
|
||||
s32 videoCreateFramebuffer(u32 w, u32 h, s32 upscale, s32 autoresize);
|
||||
void videoSetFramebuffer(s32 target);
|
||||
|
||||
@@ -736,6 +736,60 @@ static MenuItemHandlerResult menuhandlerCenterWindow(s32 operation, struct menui
|
||||
return 0;
|
||||
}
|
||||
|
||||
static MenuItemHandlerResult menuhandlerVsync(s32 operation, struct menuitem *item, union handlerdata *data)
|
||||
{
|
||||
static const char *opts[] = {
|
||||
"Adaptive",
|
||||
"Off",
|
||||
"On (Sync Every Frame)",
|
||||
"On (Sync Every 2 Frames)",
|
||||
"On (Sync Every 3 Frames)",
|
||||
"On (Sync Every 4 Frames)",
|
||||
"On (Sync Every 5 Frames)",
|
||||
"On (Sync Every 6 Frames)",
|
||||
"On (Sync Every 7 Frames)",
|
||||
"On (Sync Every 8 Frames)",
|
||||
"On (Sync Every 9 Frames)",
|
||||
"On (Sync Every 10 Frames)"
|
||||
};
|
||||
|
||||
switch (operation) {
|
||||
case MENUOP_GETOPTIONCOUNT:
|
||||
data->dropdown.value = ARRAYCOUNT(opts);
|
||||
break;
|
||||
case MENUOP_GETOPTIONTEXT:
|
||||
return (intptr_t)opts[data->dropdown.value];
|
||||
case MENUOP_SET:
|
||||
videoSetVsync(data->dropdown.value - 1);
|
||||
case MENUOP_GETSELECTEDINDEX:
|
||||
data->dropdown.value = videoGetVsync() + 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static MenuItemHandlerResult menuhandlerFramerateLimit(s32 operation, struct menuitem *item, union handlerdata *data)
|
||||
{
|
||||
switch (operation) {
|
||||
case MENUOP_GETSLIDER:
|
||||
data->slider.value = videoGetFramerateLimit();
|
||||
break;
|
||||
case MENUOP_SET:
|
||||
if (g_TickRateDiv < 2) {
|
||||
g_TickRateDiv = (data->slider.value == 0 || data->slider.value > 60) ? 0 : 1;
|
||||
}
|
||||
videoSetFramerateLimit(data->slider.value);
|
||||
break;
|
||||
case MENUOP_GETSLIDERLABEL:
|
||||
if (data->slider.value == 0) {
|
||||
sprintf(data->slider.label, "Off");
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static MenuItemHandlerResult menuhandlerResolution(s32 operation, struct menuitem *item, union handlerdata *data)
|
||||
{
|
||||
static char resstring[32];
|
||||
@@ -929,6 +983,22 @@ struct menuitem g_ExtendedVideoMenuItems[] = {
|
||||
0,
|
||||
menuhandlerCenterWindow,
|
||||
},
|
||||
{
|
||||
MENUITEMTYPE_DROPDOWN,
|
||||
0,
|
||||
MENUITEMFLAG_LITERAL_TEXT,
|
||||
(uintptr_t)"Vsync",
|
||||
0,
|
||||
menuhandlerVsync,
|
||||
},
|
||||
{
|
||||
MENUITEMTYPE_SLIDER,
|
||||
0,
|
||||
MENUITEMFLAG_LITERAL_TEXT | MENUITEMFLAG_SLIDER_WIDE | MENUITEMFLAG_SLIDER_DEFERRED,
|
||||
(uintptr_t)"Framerate Limit",
|
||||
VIDEO_MAX_FPS,
|
||||
menuhandlerFramerateLimit,
|
||||
},
|
||||
{
|
||||
MENUITEMTYPE_CHECKBOX,
|
||||
0,
|
||||
|
||||
+31
-10
@@ -86,18 +86,11 @@ s32 videoInit(void)
|
||||
};
|
||||
|
||||
gfx_init(&set);
|
||||
|
||||
videoInitDisplayModes();
|
||||
videoSetVsync(vidVsync);
|
||||
videoSetFramerateLimit(vidFramerateLimit);
|
||||
|
||||
if (!wmAPI->set_swap_interval(vidVsync)) {
|
||||
vidVsync = 0;
|
||||
}
|
||||
|
||||
if (vidVsync == 0 && vidFramerateLimit == 0) {
|
||||
// cap FPS if there's no vsync to prevent the game from exploding
|
||||
vidFramerateLimit = VIDEO_MAX_FPS;
|
||||
}
|
||||
|
||||
wmAPI->set_target_fps(vidFramerateLimit); // disabled because vsync is on
|
||||
gfx_set_texture_filter((enum FilteringMode)texFilter);
|
||||
|
||||
initDone = true;
|
||||
@@ -224,6 +217,18 @@ s32 videoGetDisplayModeIndex(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
s32 videoGetVsync(void)
|
||||
{
|
||||
vidVsync = wmAPI->get_swap_interval();
|
||||
return vidVsync;
|
||||
}
|
||||
|
||||
s32 videoGetFramerateLimit(void)
|
||||
{
|
||||
vidFramerateLimit = wmAPI->get_target_fps();
|
||||
return vidFramerateLimit;
|
||||
}
|
||||
|
||||
static s32 videoInitDisplayModes(void)
|
||||
{
|
||||
if (!wmAPI->get_current_display_mode(&vidModeDefault.width, &vidModeDefault.height)) {
|
||||
@@ -409,6 +414,22 @@ s32 videoCreateFramebuffer(u32 w, u32 h, s32 upscale, s32 autoresize)
|
||||
return gfx_create_framebuffer(w, h, upscale, autoresize);
|
||||
}
|
||||
|
||||
void videoSetVsync(const s32 vsync)
|
||||
{
|
||||
vidVsync = wmAPI->set_swap_interval(vsync) ? vsync : 0;
|
||||
|
||||
if (vidVsync == 0 && vidFramerateLimit == 0) {
|
||||
// cap FPS if there's no vsync to prevent the game from exploding
|
||||
videoSetFramerateLimit(VIDEO_MAX_FPS);
|
||||
}
|
||||
}
|
||||
|
||||
void videoSetFramerateLimit(const s32 limit)
|
||||
{
|
||||
vidFramerateLimit = (vidVsync == 0 && limit == 0) ? VIDEO_MAX_FPS : limit;
|
||||
wmAPI->set_target_fps(vidFramerateLimit);
|
||||
}
|
||||
|
||||
void videoSetFramebuffer(s32 target)
|
||||
{
|
||||
return gfx_set_framebuffer(target, 1.f);
|
||||
|
||||
+36
-8
@@ -44,6 +44,8 @@ u8 g_KeyboardKeys[5][10] = {
|
||||
{ '1','2','1','2','1','2','3','1','2','3' },
|
||||
};
|
||||
|
||||
static s32 deferredindex = -1;
|
||||
|
||||
s32 func0f0e5ce0(s32 value)
|
||||
{
|
||||
if (value < var800711a4) {
|
||||
@@ -2171,7 +2173,7 @@ Gfx* menuitemColorBoxRender(Gfx *gdl, struct menurendercontext *context)
|
||||
return gdl;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
Gfx *menuitemSelectableRender(Gfx *gdl, struct menurendercontext *context)
|
||||
{
|
||||
@@ -2332,8 +2334,15 @@ Gfx *menuitemSliderRender(Gfx *gdl, struct menurendercontext *context)
|
||||
extray = 0;
|
||||
|
||||
if (context->item->handler != NULL) {
|
||||
context->item->handler(MENUOP_GETSLIDER, context->item, &data);
|
||||
slidervalue = (s16) data.slider.value;
|
||||
if ((context->item->flags & MENUITEMFLAG_SLIDER_DEFERRED) &&
|
||||
deferredindex != -1 &&
|
||||
context->dialog->dimmed &&
|
||||
context->focused) {
|
||||
slidervalue = (s16) deferredindex;
|
||||
} else {
|
||||
context->item->handler(MENUOP_GETSLIDER, context->item, &data);
|
||||
slidervalue = (s16) data.slider.value;
|
||||
}
|
||||
} else {
|
||||
slidervalue = 0;
|
||||
}
|
||||
@@ -2484,8 +2493,17 @@ bool menuitemSliderTick(struct menuitem *item, struct menudialog *dialog, struct
|
||||
|
||||
if (tickflags & MENUTICKFLAG_DIALOGISDIMMED) {
|
||||
if (item->handler) {
|
||||
item->handler(MENUOP_GETSLIDER, item, &handlerdata);
|
||||
index = (s16) handlerdata.slider.value;
|
||||
if (item->flags & MENUITEMFLAG_SLIDER_DEFERRED) {
|
||||
if (deferredindex == -1) {
|
||||
item->handler(MENUOP_GETSLIDER, item, &handlerdata);
|
||||
deferredindex = (s16) handlerdata.slider.value;
|
||||
}
|
||||
index = deferredindex;
|
||||
} else {
|
||||
item->handler(MENUOP_GETSLIDER, item, &handlerdata);
|
||||
index = (s16) handlerdata.slider.value;
|
||||
}
|
||||
|
||||
} else {
|
||||
index = 0;
|
||||
}
|
||||
@@ -2565,11 +2583,21 @@ bool menuitemSliderTick(struct menuitem *item, struct menudialog *dialog, struct
|
||||
inputs->leftright = 0;
|
||||
handlerdata.slider.value = index;
|
||||
|
||||
if (item->handler) {
|
||||
item->handler(MENUOP_SET, item, &handlerdata);
|
||||
if (item->flags & MENUITEMFLAG_SLIDER_DEFERRED) {
|
||||
deferredindex = index;
|
||||
} else {
|
||||
if (item->handler) {
|
||||
item->handler(MENUOP_SET, item, &handlerdata);
|
||||
}
|
||||
}
|
||||
|
||||
if (inputs->select) {
|
||||
if (item->flags & MENUITEMFLAG_SLIDER_DEFERRED) {
|
||||
deferredindex = -1;
|
||||
if (item->handler) {
|
||||
item->handler(MENUOP_SET, item, &handlerdata);
|
||||
}
|
||||
}
|
||||
dialog->dimmed = false;
|
||||
}
|
||||
} else {
|
||||
@@ -2609,7 +2637,7 @@ Gfx *menuitemCarouselRender(Gfx *gdl, struct menurendercontext *context)
|
||||
|
||||
#ifdef PLATFORM_N64
|
||||
s16 chevronOffset = 0;
|
||||
#else
|
||||
#else
|
||||
s16 chevronOffset = 3;
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1666,6 +1666,7 @@
|
||||
#define MENUITEMFLAG_CAROUSEL_04000000 0x04000000
|
||||
#define MENUITEMFLAG_LITERAL_TEXT 0x08000000
|
||||
#define MENUITEMFLAG_SLIDER_WIDE 0x10000000
|
||||
#define MENUITEMFLAG_SLIDER_DEFERRED 0x20000000
|
||||
|
||||
#define MENUITEMTYPE_LABEL 0x01
|
||||
#define MENUITEMTYPE_LIST 0x02
|
||||
@@ -1696,7 +1697,7 @@
|
||||
|
||||
#ifndef PLATFORM_N64
|
||||
#define MENUITEMTYPE_COLORBOX 0x1b
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define MENUMODELFLAG_HASSCALE 0x01
|
||||
#define MENUMODELFLAG_HASPOSITION 0x02
|
||||
|
||||
Reference in new issue
Block a user