Blob Blame History Raw
From 64a83ee98d0cde089857d92bdbc080f95a623543 Mon Sep 17 00:00:00 2001
From: Adam Jackson <ajax@redhat.com>
Date: Mon, 22 Dec 2008 12:17:32 -0500
Subject: [PATCH] randr: try harder to do aspect match if there's only one head

---
 hw/xfree86/modes/xf86Crtc.c |  148 +++++++++++++++++++++++++-----------------
 1 files changed, 88 insertions(+), 60 deletions(-)

diff --git a/hw/xfree86/modes/xf86Crtc.c b/hw/xfree86/modes/xf86Crtc.c
index a6afd91..4d38955 100644
--- a/hw/xfree86/modes/xf86Crtc.c
+++ b/hw/xfree86/modes/xf86Crtc.c
@@ -1818,6 +1818,66 @@ nextEnabledOutput(xf86CrtcConfigPtr config, Bool *enabled, int *index)
 }
 
 static Bool
+aspectMatch(float a, float b)
+{
+    return fabs(1 - (a / b)) < 0.05;
+}
+
+static DisplayModePtr
+nextAspectMode(xf86OutputPtr o, DisplayModePtr last, float aspect)
+{
+    DisplayModePtr m = NULL;
+
+    if (!o)
+	return NULL;
+
+    if (!last)
+	m = o->probed_modes;
+    else
+	m = last->next;
+
+    for (; m; m = m->next)
+	if (aspectMatch(aspect, (float)m->HDisplay / (float)m->VDisplay))
+	    return m;
+
+    return NULL;
+}
+
+static DisplayModePtr
+bestModeForAspect(xf86CrtcConfigPtr config, Bool *enabled, float aspect)
+{
+    int o = -1, p;
+    DisplayModePtr mode = NULL, test = NULL, match = NULL;
+
+    if (!nextEnabledOutput(config, enabled, &o))
+	return NULL;
+    while ((mode = nextAspectMode(config->output[o], mode, aspect))) {
+	test = mode;
+	for (p = o; nextEnabledOutput(config, enabled, &p); ) {
+	    test = xf86OutputFindClosestMode(config->output[p], mode);
+	    if (!test)
+		break;
+	    if (test->HDisplay != mode->HDisplay ||
+		    test->VDisplay != mode->VDisplay) {
+		test = NULL;
+		break;
+	    }
+	}
+
+	/* if we didn't match it on all outputs, try the next one */
+	if (!test)
+	    continue;
+
+	/* if it's bigger than the last one, save it */
+	if (!match || (test->HDisplay > match->HDisplay))
+	    match = test;
+    }
+
+    /* return the biggest one found */
+    return match;
+}
+
+static Bool
 xf86TargetPreferred(ScrnInfoPtr scrn, xf86CrtcConfigPtr config,
 		    DisplayModePtr *modes, Bool *enabled,
 		    int width, int height)
@@ -1869,75 +1929,43 @@ xf86TargetPreferred(ScrnInfoPtr scrn, xf86CrtcConfigPtr config,
 	}
     }
 
-    if (ret) {
-	/* oh good, there is a match.  stash the selected modes and return. */
-	memcpy(modes, preferred_match,
-		config->num_output * sizeof(DisplayModePtr));
-    }
-
-    xfree(preferred);
-    xfree(preferred_match);
-    return ret;
-}
+    /*
+     * If there's no preferred mode, but only one monitor, pick the
+     * biggest mode for its aspect ratio, assuming one exists.
+     */
+    if (!ret) do {
+	int i = 0;
+	float aspect = 0.0;
 
-static Bool
-aspectMatch(float a, float b)
-{
-    return fabs(1 - (a / b)) < 0.05;
-}
+	/* count the number of enabled outputs */
+	for (i = 0, p = -1; nextEnabledOutput(config, enabled, &p); i++) ;
 
-static DisplayModePtr
-nextAspectMode(xf86OutputPtr o, DisplayModePtr last, float aspect)
-{
-    DisplayModePtr m = NULL;
+	if (i != 1)
+	    break;
 
-    if (!o)
-	return NULL;
+	p = -1;
+	nextEnabledOutput(config, enabled, &p);
+	if (config->output[p]->mm_height)
+	    aspect = (float)config->output[p]->mm_width /
+		     (float)config->output[p]->mm_height;
 
-    if (!last)
-	m = o->probed_modes;
-    else
-	m = last->next;
+	if (aspect)
+	    preferred_match[0] = bestModeForAspect(config, enabled, aspect);
 
-    for (; m; m = m->next)
-	if (aspectMatch(aspect, (float)m->HDisplay / (float)m->VDisplay))
-	    return m;
+	if (preferred_match[0])
+	    ret = TRUE;
 
-    return NULL;
-}
+    } while (0);
 
-static DisplayModePtr
-bestModeForAspect(xf86CrtcConfigPtr config, Bool *enabled, float aspect)
-{
-    int o = -1, p;
-    DisplayModePtr mode = NULL, test = NULL, match = NULL;
-
-    if (!nextEnabledOutput(config, enabled, &o))
-	return NULL;
-    while ((mode = nextAspectMode(config->output[o], mode, aspect))) {
-	test = mode;
-	for (p = o; nextEnabledOutput(config, enabled, &p); ) {
-	    test = xf86OutputFindClosestMode(config->output[p], mode);
-	    if (!test)
-		break;
-	    if (test->HDisplay != mode->HDisplay ||
-		    test->VDisplay != mode->VDisplay) {
-		test = NULL;
-		break;
-	    }
-	}
-
-	/* if we didn't match it on all outputs, try the next one */
-	if (!test)
-	    continue;
-
-	/* if it's bigger than the last one, save it */
-	if (!match || (test->HDisplay > match->HDisplay))
-	    match = test;
+    if (ret) {
+	/* oh good, there is a match.  stash the selected modes and return. */
+	memcpy(modes, preferred_match,
+		config->num_output * sizeof(DisplayModePtr));
     }
 
-    /* return the biggest one found */
-    return match;
+    xfree(preferred);
+    xfree(preferred_match);
+    return ret;
 }
 
 static Bool
-- 
1.6.0.6