summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdam Jackson <ajax@benzedrine.nwnk.net>2006-09-14 19:24:41 -0400
committerAdam Jackson <ajax@benzedrine.nwnk.net>2006-09-14 19:24:41 -0400
commita8f9936f55c5364bb02e8c3187507eb1f70e2ef2 (patch)
tree71470dde5b7272275d8d4416711523e43861b04e
parent81ef1b6d6063c20db4963abf7b7848e235aa4ebb (diff)
Prefer driver-provided modes when matching name strings to modelines.
Well, kinda. Strictly we prefer M_T_BUILTIN strongest since those are modes where the driver has said it absolutely can't do anything else (VBE). Then we look for user-defined modes, ie, modelines from the config file. Then we consider modes reported by the monitor via EDID. Finally if nothing has matched yet we consider the default mode pool. Within each of the above-mentioned classes, modes with the M_T_PREFERRED bit take priority over other modes in the same class. This logic ensures that the timings sent to the monitor exactly match the timings it reported as supported, which occasionally don't match the numbers you might get for that mode from CVT or GTF.
-rw-r--r--hw/xfree86/common/xf86Mode.c256
1 files changed, 133 insertions, 123 deletions
diff --git a/hw/xfree86/common/xf86Mode.c b/hw/xfree86/common/xf86Mode.c
index a3ef42071..ac3fb8c26 100644
--- a/hw/xfree86/common/xf86Mode.c
+++ b/hw/xfree86/common/xf86Mode.c
@@ -445,6 +445,17 @@ xf86LookupMode(ScrnInfoPtr scrp, DisplayModePtr modep,
ModeStatus status = MODE_NOMODE;
Bool allowDiv2 = (strategy & LOOKUP_CLKDIV2) != 0;
Bool haveBuiltin;
+ int n;
+ const int types[] = {
+ M_T_BUILTIN | M_T_PREFERRED,
+ M_T_BUILTIN,
+ M_T_USERDEF | M_T_PREFERRED,
+ M_T_USERDEF,
+ M_T_DRIVER | M_T_PREFERRED,
+ M_T_DRIVER,
+ 0
+ };
+ const int ntypes = sizeof(types) / sizeof(int);
strategy &= ~(LOOKUP_CLKDIV2 | LOOKUP_OPTIONAL_TOLERANCES);
@@ -464,143 +475,141 @@ xf86LookupMode(ScrnInfoPtr scrp, DisplayModePtr modep,
cp->ClockMulFactor = max(1, cp->ClockMulFactor);
}
- haveBuiltin = FALSE;
/* Scan the mode pool for matching names */
- for (p = scrp->modePool; p != NULL; p = p->next) {
- if (strcmp(p->name, modep->name) == 0) {
- /*
- * Requested mode is a built-in mode. Don't let the user
- * override it.
- * Since built-in modes always come before user specified
- * modes it will always be found first.
- */
- if (p->type & M_T_BUILTIN) {
- haveBuiltin = TRUE;
- }
+ for (n = 0; n < ntypes; n++) {
+ int type = types[n];
+ for (p = scrp->modePool; p != NULL; p = p->next) {
- if (haveBuiltin && !(p->type & M_T_BUILTIN))
+ /* scan through the modes in the sort order above */
+ if ((p->type & type) != type)
continue;
- /* Skip over previously rejected modes */
- if (p->status != MODE_OK) {
- if (!found)
- status = p->status;
- continue;
- }
-
- /* Skip over previously considered modes */
- if (p->prev)
- continue;
+ if (strcmp(p->name, modep->name) == 0) {
- if (p->type & M_T_BUILTIN) {
- return xf86HandleBuiltinMode(scrp, p,modep, clockRanges,
- allowDiv2);
- }
+ /* Skip over previously rejected modes */
+ if (p->status != MODE_OK) {
+ if (!found)
+ status = p->status;
+ continue;
+ }
- /* Check clock is in range */
- cp = xf86FindClockRangeForMode(clockRanges, p);
- if (cp == NULL) {
- /*
- * XXX Could do more here to provide a more detailed
- * reason for not finding a mode.
- */
- p->status = MODE_CLOCK_RANGE;
- if (!found)
- status = MODE_CLOCK_RANGE;
- continue;
- }
+ /* Skip over previously considered modes */
+ if (p->prev)
+ continue;
- /*
- * If programmable clock and strategy is not LOOKUP_BEST_REFRESH,
- * the required mode has been found, otherwise record the refresh
- * and continue looking.
- */
- if (scrp->progClock) {
- found = TRUE;
- if (strategy != LOOKUP_BEST_REFRESH) {
- bestMode = p;
- DivFactor = cp->ClockDivFactor;
- MulFactor = cp->ClockMulFactor;
- ModePrivFlags = cp->PrivFlags;
- break;
+ if (p->type & M_T_BUILTIN) {
+ return xf86HandleBuiltinMode(scrp, p,modep, clockRanges,
+ allowDiv2);
}
- refresh = ModeVRefresh(p);
- if (p->Flags & V_INTERLACE)
- refresh /= INTERLACE_REFRESH_WEIGHT;
- if (refresh > bestRefresh) {
- bestMode = p;
- DivFactor = cp->ClockDivFactor;
- MulFactor = cp->ClockMulFactor;
- ModePrivFlags = cp->PrivFlags;
- bestRefresh = refresh;
+
+ /* Check clock is in range */
+ cp = xf86FindClockRangeForMode(clockRanges, p);
+ if (cp == NULL) {
+ /*
+ * XXX Could do more here to provide a more detailed
+ * reason for not finding a mode.
+ */
+ p->status = MODE_CLOCK_RANGE;
+ if (!found)
+ status = MODE_CLOCK_RANGE;
+ continue;
}
- continue;
- }
- /*
- * Clock is in range, so if it is not a programmable clock, find
- * a matching clock.
- */
+ /*
+ * If programmable clock and strategy is not
+ * LOOKUP_BEST_REFRESH, the required mode has been found,
+ * otherwise record the refresh and continue looking.
+ */
+ if (scrp->progClock) {
+ found = TRUE;
+ if (strategy != LOOKUP_BEST_REFRESH) {
+ bestMode = p;
+ DivFactor = cp->ClockDivFactor;
+ MulFactor = cp->ClockMulFactor;
+ ModePrivFlags = cp->PrivFlags;
+ break;
+ }
+ refresh = ModeVRefresh(p);
+ if (p->Flags & V_INTERLACE)
+ refresh /= INTERLACE_REFRESH_WEIGHT;
+ if (refresh > bestRefresh) {
+ bestMode = p;
+ DivFactor = cp->ClockDivFactor;
+ MulFactor = cp->ClockMulFactor;
+ ModePrivFlags = cp->PrivFlags;
+ bestRefresh = refresh;
+ }
+ continue;
+ }
- i = xf86GetNearestClock(scrp, p->Clock, allowDiv2,
- cp->ClockDivFactor, cp->ClockMulFactor, &k);
- /*
- * If the clock is too far from the requested clock, this
- * mode is no good.
- */
- if (k & V_CLKDIV2)
- gap = abs((p->Clock * 2) -
- ((scrp->clock[i] * cp->ClockDivFactor) / cp->ClockMulFactor));
- else
- gap = abs(p->Clock -
- ((scrp->clock[i] * cp->ClockDivFactor) / cp->ClockMulFactor));
- if (gap > minimumGap) {
- p->status = MODE_NOCLOCK;
- if (!found)
- status = MODE_NOCLOCK;
- continue;
- }
- found = TRUE;
-
- if (strategy == LOOKUP_BEST_REFRESH) {
- refresh = ModeVRefresh(p);
- if (p->Flags & V_INTERLACE)
- refresh /= INTERLACE_REFRESH_WEIGHT;
- if (refresh > bestRefresh) {
- bestMode = p;
- DivFactor = cp->ClockDivFactor;
- MulFactor = cp->ClockMulFactor;
- ModePrivFlags = cp->PrivFlags;
- extraFlags = k;
- clockIndex = i;
- bestRefresh = refresh;
+ /*
+ * Clock is in range, so if it is not a programmable clock, find
+ * a matching clock.
+ */
+
+ i = xf86GetNearestClock(scrp, p->Clock, allowDiv2,
+ cp->ClockDivFactor, cp->ClockMulFactor, &k);
+ /*
+ * If the clock is too far from the requested clock, this
+ * mode is no good.
+ */
+ if (k & V_CLKDIV2)
+ gap = abs((p->Clock * 2) -
+ ((scrp->clock[i] * cp->ClockDivFactor) /
+ cp->ClockMulFactor));
+ else
+ gap = abs(p->Clock -
+ ((scrp->clock[i] * cp->ClockDivFactor) /
+ cp->ClockMulFactor));
+ if (gap > minimumGap) {
+ p->status = MODE_NOCLOCK;
+ if (!found)
+ status = MODE_NOCLOCK;
+ continue;
}
- continue;
- }
- if (strategy == LOOKUP_CLOSEST_CLOCK) {
- if (gap < minimumGap) {
- bestMode = p;
- DivFactor = cp->ClockDivFactor;
- MulFactor = cp->ClockMulFactor;
- ModePrivFlags = cp->PrivFlags;
- extraFlags = k;
- clockIndex = i;
- minimumGap = gap;
+ found = TRUE;
+
+ if (strategy == LOOKUP_BEST_REFRESH) {
+ refresh = ModeVRefresh(p);
+ if (p->Flags & V_INTERLACE)
+ refresh /= INTERLACE_REFRESH_WEIGHT;
+ if (refresh > bestRefresh) {
+ bestMode = p;
+ DivFactor = cp->ClockDivFactor;
+ MulFactor = cp->ClockMulFactor;
+ ModePrivFlags = cp->PrivFlags;
+ extraFlags = k;
+ clockIndex = i;
+ bestRefresh = refresh;
+ }
+ continue;
}
- continue;
+ if (strategy == LOOKUP_CLOSEST_CLOCK) {
+ if (gap < minimumGap) {
+ bestMode = p;
+ DivFactor = cp->ClockDivFactor;
+ MulFactor = cp->ClockMulFactor;
+ ModePrivFlags = cp->PrivFlags;
+ extraFlags = k;
+ clockIndex = i;
+ minimumGap = gap;
+ }
+ continue;
+ }
+ /*
+ * If strategy is neither LOOKUP_BEST_REFRESH or
+ * LOOKUP_CLOSEST_CLOCK the required mode has been found.
+ */
+ bestMode = p;
+ DivFactor = cp->ClockDivFactor;
+ MulFactor = cp->ClockMulFactor;
+ ModePrivFlags = cp->PrivFlags;
+ extraFlags = k;
+ clockIndex = i;
+ break;
}
- /*
- * If strategy is neither LOOKUP_BEST_REFRESH or
- * LOOKUP_CLOSEST_CLOCK the required mode has been found.
- */
- bestMode = p;
- DivFactor = cp->ClockDivFactor;
- MulFactor = cp->ClockMulFactor;
- ModePrivFlags = cp->PrivFlags;
- extraFlags = k;
- clockIndex = i;
- break;
}
+ if (found) break;
}
if (!found || bestMode == NULL)
return status;
@@ -611,7 +620,8 @@ xf86LookupMode(ScrnInfoPtr scrp, DisplayModePtr modep,
modep->ClockIndex = -1;
modep->SynthClock = (modep->Clock * MulFactor) / DivFactor;
} else {
- modep->Clock = (scrp->clock[clockIndex] * DivFactor) / MulFactor;
+ modep->Clock = (scrp->clock[clockIndex] * DivFactor) /
+ MulFactor;
modep->ClockIndex = clockIndex;
modep->SynthClock = scrp->clock[clockIndex];
if (extraFlags & V_CLKDIV2) {