[mutter] backend/native: Calculate refresh rate in double-precision



commit a41c30338f8c632fa0e67128ad4fcac92216c29a
Author: Akihiko Odaki <akihiko odaki gmail com>
Date:   Thu Feb 18 11:27:06 2021 +0900

    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>

 src/backends/native/meta-kms-utils.c | 23 +++++++++++------------
 1 file changed, 11 insertions(+), 12 deletions(-)
---
diff --git a/src/backends/native/meta-kms-utils.c b/src/backends/native/meta-kms-utils.c
index 11df09be88..1c58db83d5 100644
--- a/src/backends/native/meta-kms-utils.c
+++ b/src/backends/native/meta-kms-utils.c
@@ -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;
 }
 
 /**


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]