| Summary: | CalculateXRandRRefreshRate() returns incorrect refresh rate due to floating point truncation. | ||
|---|---|---|---|
| Product: | SDL | Reporter: | Michael <calledtolife> |
| Component: | video | Assignee: | Sam Lantinga <slouken> |
| Status: | RESOLVED FIXED | QA Contact: | Sam Lantinga <slouken> |
| Severity: | normal | ||
| Priority: | P2 | CC: | amaranth72, psilord, sezeroz |
| Version: | 2.0.3 | ||
| Hardware: | All | ||
| OS: | Linux | ||
I would actually say the bug is worse. I have an Asus PA248Q monitor and a Geforce GTX 660 video card with vsync turned on. I'm using Linux Mint 17 x86_64. It turns out that the refresh rate reported by my nvidia-settings is actually 59.95Hz for my monitor even though my monitor's firmware UI reports 60Hz AND xrandr reports 60Hz. This means my game which I'm writing with SDL 2.0.4, which has vsync enabled, which uses world state interpolation for smooth movement, and which error corrects the physics system in accordance to the detected monitor refresh rate, stutters because SDL thinks the refresh rate is 59Hz and it is really 59.95Hz. The stutter is maddening and impossible to fix, because SDL_GetCurrentDisplayMode() returns an SDL_DisplayMode structure with an _integral_ quantity for refresh rate. Are there any real workarounds for this problem? You should use the actual delta time between frames instead of the monitor's refresh rate, for logic calculations in your game. Even if SDL reported a completely accurate monitor refresh rate, your game's frame update rate will not match that all the time (even if it does on your particular computer). In SDL 2.1 I want to change refresh rate to be represented as floating point or numerator / denominator. This change seems reasonable for SDL 2.0, thanks! https://hg.libsdl.org/SDL/rev/d62c4978fffa |
In SDL_x11modes.c the CalculateXRandRRefreshRate() function performs integer math on values that may return fractional results. This causes a value that would be calculated as 59.99972... to be returned as 59. In Linux the xrandr command returns 60Hz for this particular display mode yet SDL returns 59Hz. I suggest this function be updated to correctly round the result of the calculation instead of truncating the result. SUGGESTED UPDATE: static int CalculateXRandRRefreshRate(const XRRModeInfo *info) { return (info->hTotal && info->vTotal) ? round(((double)info->dotClock / (double)(info->hTotal * info->vTotal))) : 0; } ORIGINAL CODE: static int CalculateXRandRRefreshRate(const XRRModeInfo *info) { return (info->hTotal && info->vTotal) ? (info->dotClock / (info->hTotal * info->vTotal)) : 0; }