summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdam Jackson <ajax@redhat.com>2009-10-28 15:44:37 -0400
committerPeter Hutterer <peter.hutterer@who-t.net>2009-11-03 13:26:44 +1000
commit9c87ede1d621bd7d69be81bdfdd2b18d47c68983 (patch)
treeaa3573ddd8ad1bf480d9c31097315c061b715c40
parentf61376b1365b558cf4d05e370cbea807ae168b27 (diff)
modes: Fix duplicate detection, and do it more consistently
Signed-off-by: Adam Jackson <ajax@redhat.com> (cherry picked from commit 7c0803f555782dbf451b7c79112d7deae02e5c9f)
-rw-r--r--hw/xfree86/modes/xf86Crtc.c31
-rw-r--r--hw/xfree86/modes/xf86EdidModes.c2
-rw-r--r--hw/xfree86/modes/xf86Modes.c34
-rw-r--r--hw/xfree86/modes/xf86Modes.h3
4 files changed, 39 insertions, 31 deletions
diff --git a/hw/xfree86/modes/xf86Crtc.c b/hw/xfree86/modes/xf86Crtc.c
index 506fbb9cb..937064003 100644
--- a/hw/xfree86/modes/xf86Crtc.c
+++ b/hw/xfree86/modes/xf86Crtc.c
@@ -1377,34 +1377,6 @@ xf86InitialPanning (ScrnInfoPtr scrn)
}
}
-/*
- * XXX walk the monitor mode list and prune out duplicates that
- * are inserted by xf86DDCMonitorSet. In an ideal world, that
- * function would do this work by itself.
- */
-
-static void
-xf86PruneDuplicateMonitorModes (MonPtr Monitor)
-{
- DisplayModePtr master, clone, next;
-
- for (master = Monitor->Modes;
- master && master != Monitor->Last;
- master = master->next)
- {
- for (clone = master->next; clone && clone != Monitor->Modes; clone = next)
- {
- next = clone->next;
- if (xf86ModesEqual (master, clone))
- {
- if (Monitor->Last == clone)
- Monitor->Last = clone->prev;
- xf86DeleteMode (&Monitor->Modes, clone);
- }
- }
- }
-}
-
/** Return - 0 + if a should be earlier, same or later than b in list
*/
static int
@@ -1539,9 +1511,6 @@ xf86ProbeOutputModes (ScrnInfoPtr scrn, int maxX, int maxY)
maxY = config->maxHeight;
}
- /* Elide duplicate modes before defaulting code uses them */
- xf86PruneDuplicateMonitorModes (scrn->monitor);
-
/* Probe the list of modes for each output. */
for (o = 0; o < config->num_output; o++)
{
diff --git a/hw/xfree86/modes/xf86EdidModes.c b/hw/xfree86/modes/xf86EdidModes.c
index 5992d95da..93d9f664a 100644
--- a/hw/xfree86/modes/xf86EdidModes.c
+++ b/hw/xfree86/modes/xf86EdidModes.c
@@ -975,6 +975,8 @@ xf86DDCGetModes(int scrnIndex, xf86MonPtr DDC)
if (quirks & DDC_QUIRK_PREFER_LARGE_75)
xf86DDCSetPreferredRefresh(scrnIndex, Modes, 75);
+ Modes = xf86PruneDuplicateModes(Modes);
+
return Modes;
}
diff --git a/hw/xfree86/modes/xf86Modes.c b/hw/xfree86/modes/xf86Modes.c
index d105b48ab..862a4734b 100644
--- a/hw/xfree86/modes/xf86Modes.c
+++ b/hw/xfree86/modes/xf86Modes.c
@@ -689,3 +689,37 @@ xf86GetDefaultModes (void)
}
return head;
}
+
+/*
+ * Walk a mode list and prune out duplicates. Will preserve the preferred
+ * mode of an otherwise-duplicate pair.
+ *
+ * Probably best to call this on lists that are all of a single class
+ * (driver, default, user, etc.), otherwise, which mode gets deleted is
+ * not especially well defined.
+ *
+ * Returns the new list.
+ */
+
+DisplayModePtr
+xf86PruneDuplicateModes(DisplayModePtr modes)
+{
+ DisplayModePtr m, n, o;
+
+top:
+ for (m = modes; m; m = m->next) {
+ for (n = m->next; n; n = o) {
+ o = n->next;
+ if (xf86ModesEqual(m, n)) {
+ if (n->type & M_T_PREFERRED) {
+ xf86DeleteMode(&modes, m);
+ goto top;
+ }
+ else
+ xf86DeleteMode(&modes, n);
+ }
+ }
+ }
+
+ return modes;
+}
diff --git a/hw/xfree86/modes/xf86Modes.h b/hw/xfree86/modes/xf86Modes.h
index 908f59b48..38927b128 100644
--- a/hw/xfree86/modes/xf86Modes.h
+++ b/hw/xfree86/modes/xf86Modes.h
@@ -95,6 +95,9 @@ extern _X_EXPORT void
xf86PruneInvalidModes(ScrnInfoPtr pScrn, DisplayModePtr *modeList,
Bool verbose);
+extern _X_EXPORT DisplayModePtr
+xf86PruneDuplicateModes(DisplayModePtr modes);
+
extern _X_EXPORT void
xf86ValidateModesFlags(ScrnInfoPtr pScrn, DisplayModePtr modeList,
int flags);