[mutter] monitor: Dynamically calculate supported scales per resolution



commit 3e8d0204bdb37507f06c51bb91ddd3cc0a511a2b
Author: Marco Trevisan (Treviño) <mail 3v1n0 net>
Date:   Tue Jun 6 11:27:58 2017 +0800

    monitor: Dynamically calculate supported scales per resolution
    
    When using logical sized monitors we are allowed to use fractional scaling
    but only if the resulting scaled logical monitor size is in integer form.
    So, in order to get this, we allow to scale the monitor to up to
    8 fractional values per integer, doing some computation in order to
    fetch the nearest values which are closer to the scaling factors we can
    permit.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=765011

 src/backends/meta-monitor.c |  117 ++++++++++++++++++++++++++++++++++++-------
 1 files changed, 98 insertions(+), 19 deletions(-)
---
diff --git a/src/backends/meta-monitor.c b/src/backends/meta-monitor.c
index c01daef..d86cea1 100644
--- a/src/backends/meta-monitor.c
+++ b/src/backends/meta-monitor.c
@@ -27,6 +27,10 @@
 #include "backends/meta-monitor-manager-private.h"
 #include "backends/meta-settings-private.h"
 
+#define SCALE_FACTORS_PER_INTEGER 8
+#define MINIMUM_SCALE_FACTOR 0.5f
+#define MAXIMUM_SCALE_FACTOR 4.0f
+
 typedef struct _MetaMonitorMode
 {
   MetaMonitorModeSpec spec;
@@ -1336,37 +1340,112 @@ meta_monitor_calculate_mode_scale (MetaMonitor     *monitor,
   return calculate_scale (monitor, monitor_mode);
 }
 
+static float
+get_closest_scale_factor_for_resolution (float width,
+                                         float height,
+                                         float scale,
+                                         float scale_step)
+{
+  unsigned int i, j;
+  float scaled_h;
+  float scaled_w;
+  float best_scale;
+  int base_scaled_w;
+  gboolean limit_exceeded;
+  gboolean found_one;
+
+  best_scale = 0;
+  scaled_w = width / scale;
+  scaled_h = height / scale;
+
+  if (scale < MINIMUM_SCALE_FACTOR || scale > MAXIMUM_SCALE_FACTOR)
+    goto out;
+
+  if (floorf (scaled_w) == scaled_w && floorf (scaled_h) == scaled_h)
+    return scale;
+
+  i = 0;
+  found_one = FALSE;
+  limit_exceeded = FALSE;
+  base_scaled_w = floorf (scaled_w);
+
+  do
+    {
+
+      for (j = 0; j < 2; j++)
+        {
+          float current_scale;
+          int offset = i * (j ? 1 : -1);
+
+          scaled_w = base_scaled_w + offset;
+          current_scale = width / scaled_w;
+          scaled_h = height / current_scale;
+
+          if (current_scale >= scale + scale_step ||
+              current_scale <= scale - scale_step ||
+              current_scale < MINIMUM_SCALE_FACTOR ||
+              current_scale > MAXIMUM_SCALE_FACTOR)
+            {
+              limit_exceeded = TRUE;
+              continue;
+            }
+
+          if (floorf (scaled_h) == scaled_h)
+            {
+              found_one = TRUE;
+
+              if (fabsf (current_scale - scale) < fabsf (best_scale - scale))
+                best_scale = current_scale;
+            }
+        }
+
+      i++;
+    }
+  while (!found_one && !limit_exceeded);
+
+out:
+  return best_scale;
+}
+
 float *
 meta_monitor_calculate_supported_scales (MetaMonitor                *monitor,
                                          MetaMonitorMode            *monitor_mode,
                                          MetaMonitorScalesConstraint constraints,
                                          int                        *n_supported_scales)
 {
-  unsigned int i;
+  unsigned int i, j;
   int width, height;
+  float scale_steps;
   GArray *supported_scales;
-  static const float all_scales[] = {
-    1.0,
-    1.5,
-    2.0
-  };
-
-  meta_monitor_mode_get_resolution (monitor_mode, &width, &height);
 
+  scale_steps = 1.0 / (float) SCALE_FACTORS_PER_INTEGER;
   supported_scales = g_array_new (FALSE, FALSE, sizeof (float));
 
-  for (i = 0; i < G_N_ELEMENTS (all_scales); i++)
-    {
-      float scale = all_scales[i];
-
-      if ((constraints & META_MONITOR_SCALES_CONSTRAINT_NO_FRAC) &&
-          fmodf (scale, 1.0) != 0.0)
-        continue;
-
-      if (fmodf (width, scale) != 0.0 || fmodf (height, scale) != 0.0)
-        continue;
+  meta_monitor_mode_get_resolution (monitor_mode, &width, &height);
 
-      g_array_append_val (supported_scales, scale);
+  for (i = floorf (MINIMUM_SCALE_FACTOR);
+       i <= ceilf (MAXIMUM_SCALE_FACTOR);
+       i++)
+    {
+      for (j = 0; j < SCALE_FACTORS_PER_INTEGER; j++)
+        {
+          float scale;
+          float scale_value = i + j * scale_steps;
+
+          if ((constraints & META_MONITOR_SCALES_CONSTRAINT_NO_FRAC) &&
+              fmodf (scale_value, 1.0) != 0.0)
+            {
+              continue;
+            }
+
+          scale = get_closest_scale_factor_for_resolution (width,
+                                                           height,
+                                                           scale_value,
+                                                           scale_steps);
+
+          if (scale > 0.0f)
+            g_array_append_val (supported_scales, scale);
+        }
     }
 
   *n_supported_scales = supported_scales->len;


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