06bf710
From 64a83ee98d0cde089857d92bdbc080f95a623543 Mon Sep 17 00:00:00 2001
06bf710
From: Adam Jackson <ajax@redhat.com>
06bf710
Date: Mon, 22 Dec 2008 12:17:32 -0500
06bf710
Subject: [PATCH] randr: try harder to do aspect match if there's only one head
06bf710
06bf710
---
06bf710
 hw/xfree86/modes/xf86Crtc.c |  148 +++++++++++++++++++++++++-----------------
06bf710
 1 files changed, 88 insertions(+), 60 deletions(-)
06bf710
06bf710
diff --git a/hw/xfree86/modes/xf86Crtc.c b/hw/xfree86/modes/xf86Crtc.c
06bf710
index a6afd91..4d38955 100644
06bf710
--- a/hw/xfree86/modes/xf86Crtc.c
06bf710
+++ b/hw/xfree86/modes/xf86Crtc.c
06bf710
@@ -1818,6 +1818,66 @@ nextEnabledOutput(xf86CrtcConfigPtr config, Bool *enabled, int *index)
06bf710
 }
06bf710
 
06bf710
 static Bool
06bf710
+aspectMatch(float a, float b)
06bf710
+{
06bf710
+    return fabs(1 - (a / b)) < 0.05;
06bf710
+}
06bf710
+
06bf710
+static DisplayModePtr
06bf710
+nextAspectMode(xf86OutputPtr o, DisplayModePtr last, float aspect)
06bf710
+{
06bf710
+    DisplayModePtr m = NULL;
06bf710
+
06bf710
+    if (!o)
06bf710
+	return NULL;
06bf710
+
06bf710
+    if (!last)
06bf710
+	m = o->probed_modes;
06bf710
+    else
06bf710
+	m = last->next;
06bf710
+
06bf710
+    for (; m; m = m->next)
06bf710
+	if (aspectMatch(aspect, (float)m->HDisplay / (float)m->VDisplay))
06bf710
+	    return m;
06bf710
+
06bf710
+    return NULL;
06bf710
+}
06bf710
+
06bf710
+static DisplayModePtr
06bf710
+bestModeForAspect(xf86CrtcConfigPtr config, Bool *enabled, float aspect)
06bf710
+{
06bf710
+    int o = -1, p;
06bf710
+    DisplayModePtr mode = NULL, test = NULL, match = NULL;
06bf710
+
06bf710
+    if (!nextEnabledOutput(config, enabled, &o))
06bf710
+	return NULL;
06bf710
+    while ((mode = nextAspectMode(config->output[o], mode, aspect))) {
06bf710
+	test = mode;
06bf710
+	for (p = o; nextEnabledOutput(config, enabled, &p); ) {
06bf710
+	    test = xf86OutputFindClosestMode(config->output[p], mode);
06bf710
+	    if (!test)
06bf710
+		break;
06bf710
+	    if (test->HDisplay != mode->HDisplay ||
06bf710
+		    test->VDisplay != mode->VDisplay) {
06bf710
+		test = NULL;
06bf710
+		break;
06bf710
+	    }
06bf710
+	}
06bf710
+
06bf710
+	/* if we didn't match it on all outputs, try the next one */
06bf710
+	if (!test)
06bf710
+	    continue;
06bf710
+
06bf710
+	/* if it's bigger than the last one, save it */
06bf710
+	if (!match || (test->HDisplay > match->HDisplay))
06bf710
+	    match = test;
06bf710
+    }
06bf710
+
06bf710
+    /* return the biggest one found */
06bf710
+    return match;
06bf710
+}
06bf710
+
06bf710
+static Bool
06bf710
 xf86TargetPreferred(ScrnInfoPtr scrn, xf86CrtcConfigPtr config,
06bf710
 		    DisplayModePtr *modes, Bool *enabled,
06bf710
 		    int width, int height)
06bf710
@@ -1869,75 +1929,43 @@ xf86TargetPreferred(ScrnInfoPtr scrn, xf86CrtcConfigPtr config,
06bf710
 	}
06bf710
     }
06bf710
 
06bf710
-    if (ret) {
06bf710
-	/* oh good, there is a match.  stash the selected modes and return. */
06bf710
-	memcpy(modes, preferred_match,
06bf710
-		config->num_output * sizeof(DisplayModePtr));
06bf710
-    }
06bf710
-
06bf710
-    xfree(preferred);
06bf710
-    xfree(preferred_match);
06bf710
-    return ret;
06bf710
-}
06bf710
+    /*
06bf710
+     * If there's no preferred mode, but only one monitor, pick the
06bf710
+     * biggest mode for its aspect ratio, assuming one exists.
06bf710
+     */
06bf710
+    if (!ret) do {
06bf710
+	int i = 0;
06bf710
+	float aspect = 0.0;
06bf710
 
06bf710
-static Bool
06bf710
-aspectMatch(float a, float b)
06bf710
-{
06bf710
-    return fabs(1 - (a / b)) < 0.05;
06bf710
-}
06bf710
+	/* count the number of enabled outputs */
06bf710
+	for (i = 0, p = -1; nextEnabledOutput(config, enabled, &p); i++) ;
06bf710
 
06bf710
-static DisplayModePtr
06bf710
-nextAspectMode(xf86OutputPtr o, DisplayModePtr last, float aspect)
06bf710
-{
06bf710
-    DisplayModePtr m = NULL;
06bf710
+	if (i != 1)
06bf710
+	    break;
06bf710
 
06bf710
-    if (!o)
06bf710
-	return NULL;
06bf710
+	p = -1;
06bf710
+	nextEnabledOutput(config, enabled, &p);
06bf710
+	if (config->output[p]->mm_height)
06bf710
+	    aspect = (float)config->output[p]->mm_width /
06bf710
+		     (float)config->output[p]->mm_height;
06bf710
 
06bf710
-    if (!last)
06bf710
-	m = o->probed_modes;
06bf710
-    else
06bf710
-	m = last->next;
06bf710
+	if (aspect)
06bf710
+	    preferred_match[0] = bestModeForAspect(config, enabled, aspect);
06bf710
 
06bf710
-    for (; m; m = m->next)
06bf710
-	if (aspectMatch(aspect, (float)m->HDisplay / (float)m->VDisplay))
06bf710
-	    return m;
06bf710
+	if (preferred_match[0])
06bf710
+	    ret = TRUE;
06bf710
 
06bf710
-    return NULL;
06bf710
-}
06bf710
+    } while (0);
06bf710
 
06bf710
-static DisplayModePtr
06bf710
-bestModeForAspect(xf86CrtcConfigPtr config, Bool *enabled, float aspect)
06bf710
-{
06bf710
-    int o = -1, p;
06bf710
-    DisplayModePtr mode = NULL, test = NULL, match = NULL;
06bf710
-
06bf710
-    if (!nextEnabledOutput(config, enabled, &o))
06bf710
-	return NULL;
06bf710
-    while ((mode = nextAspectMode(config->output[o], mode, aspect))) {
06bf710
-	test = mode;
06bf710
-	for (p = o; nextEnabledOutput(config, enabled, &p); ) {
06bf710
-	    test = xf86OutputFindClosestMode(config->output[p], mode);
06bf710
-	    if (!test)
06bf710
-		break;
06bf710
-	    if (test->HDisplay != mode->HDisplay ||
06bf710
-		    test->VDisplay != mode->VDisplay) {
06bf710
-		test = NULL;
06bf710
-		break;
06bf710
-	    }
06bf710
-	}
06bf710
-
06bf710
-	/* if we didn't match it on all outputs, try the next one */
06bf710
-	if (!test)
06bf710
-	    continue;
06bf710
-
06bf710
-	/* if it's bigger than the last one, save it */
06bf710
-	if (!match || (test->HDisplay > match->HDisplay))
06bf710
-	    match = test;
06bf710
+    if (ret) {
06bf710
+	/* oh good, there is a match.  stash the selected modes and return. */
06bf710
+	memcpy(modes, preferred_match,
06bf710
+		config->num_output * sizeof(DisplayModePtr));
06bf710
     }
06bf710
 
06bf710
-    /* return the biggest one found */
06bf710
-    return match;
06bf710
+    xfree(preferred);
06bf710
+    xfree(preferred_match);
06bf710
+    return ret;
06bf710
 }
06bf710
 
06bf710
 static Bool
06bf710
-- 
06bf710
1.6.0.6
06bf710