summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdam Jackson <ajax@nwnk.net>2008-11-13 14:58:21 -0500
committerAlex Deucher <alexdeucher@gmail.com>2008-11-13 14:58:21 -0500
commitc232f3d673fb00d7fceb8e82741349d64e5ac0ad (patch)
tree467a270f128c5ab3d161906a6d1711175edb897a
parent6b501d7cc55f1d06966cdf3caf36bcfc6cf18939 (diff)
xf86TargetExact should try harder if there's only one monitor attached.
If there's no preferred mode, but only one monitor, pick the biggest mode for its aspect ratio, assuming one exists.
-rw-r--r--hw/xfree86/modes/xf86Crtc.c148
1 files changed, 88 insertions, 60 deletions
diff --git a/hw/xfree86/modes/xf86Crtc.c b/hw/xfree86/modes/xf86Crtc.c
index f072109de..74ffce372 100644
--- a/hw/xfree86/modes/xf86Crtc.c
+++ b/hw/xfree86/modes/xf86Crtc.c
@@ -1820,6 +1820,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)
@@ -1871,75 +1931,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