mirror of
https://github.com/brl/mutter.git
synced 2025-02-02 14:53:03 +00:00
backend/native: Calculate refresh rate in double-precision
The old calculation was introduced to improve the precision with commit c16a5ec1cf14d67ee8100afd31a2e85e7003f9a8. Here, I call the calculation as "revision 2", and the calculation even older as "revision 1", and the new calculation introduced with this commit as "reivion 3". Revision 2 has two problems: 1. The calculation is mixed with fixed-point numbers and floating-point numbers. To overcome the precision loss of fixed-point numbers division, it first "calculates refresh rate in milliHz first for extra precision", but this requires converting the value back to Hz. An extra calculation has performance and precision costs. It is also hard to understand for programmers. 2. The calculation has a bias. In the process, it does: refresh += (drm_mode->vtotal / 2); It prevents the value from being rounded to a smaller value in a fixed-point integer arithmetics, but it only adds a small bias (0.0005) and consumes some fraction bits for floating point arithmetic. Revision 3, introduced with this commit always uses double-precision floating-point values for true precision and to ease understanding of this code. It also removes the bias. Another change is that it now has two internal values, numerator and denominator. Revision 1 also calculated those two values first, and later performed a division with them, which minimizes the precision loss caused by divisions. This method has risks of overflowing the two values and revision 1 caused problems due to that, but revision 3 won't thanks to double-precision. Therefore, revision 3 will theoretically have the result identical with the calculation with infinite-precision. Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1737>
This commit is contained in:
parent
504af40c69
commit
a41c30338f
@ -33,19 +33,18 @@
|
||||
float
|
||||
meta_calculate_drm_mode_refresh_rate (const drmModeModeInfo *drm_mode)
|
||||
{
|
||||
float refresh = 0.0;
|
||||
double numerator;
|
||||
double denominator;
|
||||
|
||||
if (drm_mode->htotal > 0 && drm_mode->vtotal > 0)
|
||||
{
|
||||
/* Calculate refresh rate in milliHz first for extra precision. */
|
||||
refresh = (drm_mode->clock * 1000000LL) / drm_mode->htotal;
|
||||
refresh += (drm_mode->vtotal / 2);
|
||||
refresh /= drm_mode->vtotal;
|
||||
if (drm_mode->vscan > 1)
|
||||
refresh /= drm_mode->vscan;
|
||||
refresh /= 1000.0;
|
||||
}
|
||||
return refresh;
|
||||
if (drm_mode->htotal <= 0 || drm_mode->vtotal <= 0)
|
||||
return 0.0;
|
||||
|
||||
numerator = drm_mode->clock * 1000.0;
|
||||
denominator = (double) drm_mode->vtotal * drm_mode->htotal;
|
||||
if (drm_mode->vscan > 1)
|
||||
denominator *= drm_mode->vscan;
|
||||
|
||||
return numerator / denominator;
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
x
Reference in New Issue
Block a user