We are currently migrating Bugzilla to GitHub issues.
Any changes made to the bug tracker now will be lost, so please do not post new bugs or make changes to them.
When we're done, all bug URLs will redirect to their equivalent location on the new bug tracker.

Bug 3134 - CalculateXRandRRefreshRate() returns incorrect refresh rate due to floating point truncation.
Summary: CalculateXRandRRefreshRate() returns incorrect refresh rate due to floating p...
Status: RESOLVED FIXED
Alias: None
Product: SDL
Classification: Unclassified
Component: video (show other bugs)
Version: 2.0.3
Hardware: All Linux
: P2 normal
Assignee: Sam Lantinga
QA Contact: Sam Lantinga
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2015-09-29 14:25 UTC by Michael
Modified: 2016-10-01 21:17 UTC (History)
3 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Michael 2015-09-29 14:25:23 UTC
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;
}
Comment 1 psilord 2016-08-11 01:27:08 UTC
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?
Comment 2 Alex Szpakowski 2016-08-12 16:57:42 UTC
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).
Comment 3 Sam Lantinga 2016-10-01 21:17:01 UTC
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