xserver: Branch 'server-1.5-branch' - 2 commits

Adam Jackson ajax at kemper.freedesktop.org
Tue Mar 4 10:01:18 PST 2008


 hw/xfree86/common/xf86AutoConfig.c |    3 
 hw/xfree86/common/xf86Config.c     |    2 
 hw/xfree86/modes/xf86Crtc.c        |  376 +++++++++++++++++++++++++++++--------
 3 files changed, 300 insertions(+), 81 deletions(-)

New commits:
commit e4d92a13e83b4327067c97d8c9fe151a1c0b35af
Author: Adam Jackson <ajax at redhat.com>
Date:   Tue Mar 4 11:38:34 2008 -0500

    Make xf86InitialConfiguration slightly smarter.
    
    Old heuristic was to find the first monitor that expressed a preference,
    then attempt to get all other monitors to agree.  This doesn't work
    particularly well when the two sets of modes don't precisely intersect,
    you get overlapping-but-not-identical output geometry and things go wrong.
    
    New heuristic is:
    - Exact user preference, if given
    - Exact output preference, if the same for all outputs
    - Best (largest) mode of modes common to all outputs:
      - with the same aspect ratio as all outputs (may be NULL)
      - with 4:3 aspect ratio
    - Then the old heuristic to try to get something lit
    
    Note that it is simply not doable to have a reliable initial output guess if
    you insist on trying to clone all outputs together.  It's far too easy to
    end up with displays that simply don't have modes in common.  We need to
    switch to right-of placement someday, once we're not limited to CRTC size
    limits and we have working multi-GPU in RANDR.
    (cherry picked from commit 27e7dacbf7ef17712be31ff90f98ee3a5c5cf909)

diff --git a/hw/xfree86/modes/xf86Crtc.c b/hw/xfree86/modes/xf86Crtc.c
index 14b6049..4d5d7b8 100644
--- a/hw/xfree86/modes/xf86Crtc.c
+++ b/hw/xfree86/modes/xf86Crtc.c
@@ -1,5 +1,6 @@
 /*
  * Copyright © 2006 Keith Packard
+ * Copyright © 2008 Red Hat, Inc.
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
  * documentation for any purpose is hereby granted without fee, provided that
@@ -808,7 +809,7 @@ xf86ClosestMode (xf86OutputPtr output,
     return target_mode;
 }
 
-static Bool
+static DisplayModePtr
 xf86OutputHasPreferredMode (xf86OutputPtr output, int width, int height)
 {
     DisplayModePtr  mode;
@@ -820,9 +821,21 @@ xf86OutputHasPreferredMode (xf86OutputPtr output, int width, int height)
 	    continue;
 
 	if (mode->type & M_T_PREFERRED)
-	    return TRUE;
+	    return mode;
     }
-    return FALSE;
+    return NULL;
+}
+
+static DisplayModePtr
+xf86OutputHasUserPreferredMode (xf86OutputPtr output)
+{
+    DisplayModePtr mode, first = output->probed_modes;
+
+    for (mode = first; mode && mode->next != first; mode = mode->next)
+	if (mode->type & M_T_USERPREF)
+	    return mode;
+
+    return NULL;
 }
 
 static int
@@ -1577,6 +1590,265 @@ xf86SetScrnInfoModes (ScrnInfoPtr scrn)
     scrn->currentMode = scrn->modes;
 }
 
+static void
+xf86EnableOutputs(ScrnInfoPtr scrn, xf86CrtcConfigPtr config, Bool *enabled)
+{
+    Bool any_enabled = FALSE;
+    int o;
+
+    for (o = 0; o < config->num_output; o++)
+	any_enabled |= enabled[o] = xf86OutputEnabled(config->output[o], TRUE);
+    
+    if (!any_enabled) {
+	xf86DrvMsg(scrn->scrnIndex, X_WARNING,
+		   "No outputs definitely connected, trying again...\n");
+
+	for (o = 0; o < config->num_output; o++)
+	    enabled[o] = xf86OutputEnabled(config->output[o], FALSE);
+    }
+}
+
+static Bool
+nextEnabledOutput(xf86CrtcConfigPtr config, Bool *enabled, int *index)
+{
+    int o = *index;
+
+    for (o++; o < config->num_output; o++) {
+	if (enabled[o]) {
+	    *index = o;
+	    return TRUE;
+	}
+    }
+    
+    return FALSE;
+}
+
+static Bool
+xf86TargetExact(ScrnInfoPtr scrn, xf86CrtcConfigPtr config,
+		DisplayModePtr *modes, Bool *enabled,
+		int width, int height)
+{
+    int o;
+    int pref_width = 0, pref_height = 0;
+    DisplayModePtr *preferred;
+    Bool ret = FALSE;
+
+    preferred = xnfcalloc(config->num_output, sizeof(DisplayModePtr));
+
+    /* Find all the preferred modes; fail if any outputs lack them */
+    for (o = -1; nextEnabledOutput(config, enabled, &o); ) {
+	preferred[o] =
+	    xf86OutputHasPreferredMode(config->output[o], width, height);
+
+	if (!preferred[o])
+	    goto out;
+    }
+
+    /* check that they're all the same size */
+    for (o = -1; nextEnabledOutput(config, enabled, &o); ) {
+	Rotation r = config->output[o]->initial_rotation;
+	if (!pref_width) {
+	    pref_width = xf86ModeWidth(preferred[o], r);
+	    pref_height = xf86ModeHeight(preferred[o], r);
+	} else {
+	    if (pref_width != xf86ModeWidth(preferred[o], r))
+		goto out;
+	    if (pref_height != xf86ModeHeight(preferred[o], r))
+		goto out;
+	}
+    }
+
+    /* oh good, they match.  stash the selected modes and return. */
+    memcpy(modes, preferred, config->num_output * sizeof(DisplayModePtr));
+    ret = TRUE;
+
+out:
+    xfree(preferred);
+    return ret;
+}
+
+static Bool
+aspectMatch(float a, float b)
+{
+    return fabs(1 - (a / b)) < 0.05;
+}
+
+static DisplayModePtr
+nextAspectMode(DisplayModePtr start, float aspect)
+{
+    DisplayModePtr m = start;
+
+    for (m = m->next; 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, p;
+    DisplayModePtr mode, test = NULL, match = NULL;
+
+    for (o = -1; nextEnabledOutput(config, enabled, &o); ) {
+	mode = config->output[o]->probed_modes;
+	while ((mode = nextAspectMode(mode, aspect))) {
+	    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 DisplayModePtr
+biggestMode(DisplayModePtr a, DisplayModePtr b)
+{
+    int A, B;
+
+    if (!a)
+	return b;
+    if (!b)
+	return a;
+
+    A = a->HDisplay * a->VDisplay;
+    B = b->HDisplay * b->VDisplay;
+
+    if (A > B)
+	return a;
+
+    return b;
+}
+
+static Bool
+xf86TargetAspect(ScrnInfoPtr scrn, xf86CrtcConfigPtr config,
+		 DisplayModePtr *modes, Bool *enabled,
+		 int width, int height)
+{
+    int o;
+    float aspect = 0.0, *aspects;
+    xf86OutputPtr output;
+    Bool ret = FALSE;
+    DisplayModePtr guess = NULL, aspect_guess = NULL, base_guess = NULL;
+
+    aspects = xnfcalloc(config->num_output, sizeof(float));
+
+    /* collect the aspect ratios */
+    for (o = -1; nextEnabledOutput(config, enabled, &o); ) {
+	output = config->output[o];
+	if (output->mm_height)
+	    aspects[o] = (float)output->mm_width / (float)output->mm_height;
+	else
+	    aspects[o] = 4.0 / 3.0;
+    }
+
+    /* check that they're all the same */
+    for (o = -1; nextEnabledOutput(config, enabled, &o); ) {
+	output = config->output[o];
+	if (!aspect) {
+	    aspect = aspects[o];
+	} else if (!aspectMatch(aspect, aspects[o])) {
+	    goto no_aspect_match;
+	}
+    }
+
+    /* if they're all 4:3, just skip ahead and save effort */
+    if (!aspectMatch(aspect, 4.0/3.0))
+	aspect_guess = bestModeForAspect(config, enabled, aspect);
+
+no_aspect_match:
+    base_guess = bestModeForAspect(config, enabled, 4.0/3.0);
+
+    guess = biggestMode(base_guess, aspect_guess);
+
+    if (!guess)
+	goto out;
+
+    /* found a mode that works everywhere, now apply it */
+    for (o = -1; nextEnabledOutput(config, enabled, &o); ) {
+	modes[o] = xf86OutputFindClosestMode(config->output[o], guess);
+    }
+    ret = TRUE;
+
+out:
+    xfree(aspects);
+    return ret;
+}
+
+static Bool
+xf86TargetFallback(ScrnInfoPtr scrn, xf86CrtcConfigPtr config,
+		   DisplayModePtr *modes, Bool *enabled,
+		   int width, int height)
+{
+    DisplayModePtr target_mode = NULL;
+    Rotation target_rotation = RR_Rotate_0;
+    DisplayModePtr default_mode;
+    int default_preferred, target_preferred = 0, o;
+
+    /* User preferred > preferred > other modes */
+    for (o = -1; nextEnabledOutput(config, enabled, &o); ) {
+	default_mode = xf86DefaultMode (config->output[o], width, height);
+	if (!default_mode)
+	    continue;
+
+	default_preferred = (((default_mode->type & M_T_PREFERRED) != 0) +
+		((default_mode->type & M_T_USERPREF) != 0));
+
+	if (default_preferred > target_preferred || !target_mode) {
+	    target_mode = default_mode;
+	    target_preferred = default_preferred;
+	    target_rotation = config->output[o]->initial_rotation;
+	    config->compat_output = o;
+	}
+    }
+
+    if (target_mode)
+	modes[config->compat_output] = target_mode;
+
+    /* Fill in other output modes */
+    for (o = -1; nextEnabledOutput(config, enabled, &o); ) {
+	if (!modes[o])
+	    modes[o] = xf86ClosestMode(config->output[o], target_mode,
+				       target_rotation, width, height);
+    }
+
+    return (target_mode != NULL);
+}
+
+static Bool
+xf86TargetUserpref(ScrnInfoPtr scrn, xf86CrtcConfigPtr config,
+		   DisplayModePtr *modes, Bool *enabled,
+		   int width, int height)
+{
+    int o;
+
+    for (o = -1; nextEnabledOutput(config, enabled, &o); )
+	if (xf86OutputHasUserPreferredMode(config->output[o]))
+	    return 
+		xf86TargetFallback(scrn, config, modes, enabled, width, height);
+
+    return FALSE;
+}
+
+
 /**
  * Construct default screen configuration
  *
@@ -1596,14 +1868,11 @@ xf86InitialConfiguration (ScrnInfoPtr scrn, Bool canGrow)
 {
     xf86CrtcConfigPtr	config = XF86_CRTC_CONFIG_PTR(scrn);
     int			o, c;
-    DisplayModePtr	target_mode = NULL;
-    int			target_preferred = 0;
-    Rotation		target_rotation = RR_Rotate_0;
     xf86CrtcPtr		*crtcs;
     DisplayModePtr	*modes;
-    Bool		*enabled, any_enabled = FALSE;
-    int			width;
-    int			height;
+    Bool		*enabled;
+    int			width, height;
+    int			i = scrn->scrnIndex;
 
     /* Set up the device options */
     config->options = xnfalloc (sizeof (xf86DeviceOptions));
@@ -1629,75 +1898,28 @@ xf86InitialConfiguration (ScrnInfoPtr scrn, Bool canGrow)
     modes = xnfcalloc (config->num_output, sizeof (DisplayModePtr));
     enabled = xnfcalloc (config->num_output, sizeof (Bool));
     
-    for (o = 0; o < config->num_output; o++)
-    {
-	xf86OutputPtr output = config->output[o];
-	
-	modes[o] = NULL;
-	any_enabled |= (enabled[o] = xf86OutputEnabled (output, TRUE));
-    }
-    
-    if (!any_enabled)
-    {
-	xf86DrvMsg (scrn->scrnIndex, X_WARNING,
-		    "No outputs definitely connected, trying again...\n");
-
-	for (o = 0; o < config->num_output; o++)
-	{
-	    xf86OutputPtr output = config->output[o];
-	
-	    modes[o] = NULL;
-	    enabled[o] = xf86OutputEnabled (output, FALSE);
-	}
-    }
-
-    /*
-     * User preferred > preferred > other modes
-     */
-    for (o = 0; o < config->num_output; o++)
-    {
-	xf86OutputPtr	output = config->output[o];
-	DisplayModePtr	default_mode;
-	int		default_preferred;
+    xf86EnableOutputs(scrn, config, enabled);
+
+    if (xf86TargetUserpref(scrn, config, modes, enabled, width, height))
+	xf86DrvMsg(i, X_INFO, "Using user preference for initial modes\n");
+    else if (xf86TargetExact(scrn, config, modes, enabled, width, height))
+	xf86DrvMsg(i, X_INFO, "Using exact sizes for initial modes\n");
+    else if (xf86TargetAspect(scrn, config, modes, enabled, width, height))
+	xf86DrvMsg(i, X_INFO, "Using fuzzy aspect match for initial modes\n");
+    else if (xf86TargetFallback(scrn, config, modes, enabled, width, height))
+	xf86DrvMsg(i, X_INFO, "Using sloppy heuristic for initial modes\n");
+    else
+	xf86DrvMsg(i, X_WARNING, "Unable to find initial modes\n");
 
-	if (!enabled[o])
-	    continue;
-	default_mode = xf86DefaultMode (output, width, height);
-	if (!default_mode)
-	    continue;
-	default_preferred = (((default_mode->type & M_T_PREFERRED) != 0) +
-			     ((default_mode->type & M_T_USERPREF) != 0));
-	if (default_preferred > target_preferred || !target_mode)
-	{
-	    target_mode = default_mode;
-	    target_preferred = default_preferred;
-	    target_rotation = output->initial_rotation;
-	    config->compat_output = o;
-	}
-    }
-    if (target_mode)
-	modes[config->compat_output] = target_mode;
-    /*
-     * Fill in other output modes
-     */
-    for (o = 0; o < config->num_output; o++)
-    {
-	xf86OutputPtr output = config->output[o];
-	
-	if (enabled[o])
-	{
-	    if (!modes[o])
-		modes[o] = xf86ClosestMode (output, target_mode,
-					    target_rotation, width, height);
-	    if (!modes[o])
-		xf86DrvMsg (scrn->scrnIndex, X_ERROR,
-			    "Output %s enabled but has no modes\n",
-			    output->name);
-	    else
-		xf86DrvMsg (scrn->scrnIndex, X_INFO,
-			    "Output %s using initial mode %s\n",
-			    output->name, modes[o]->name);
-	}
+    for (o = -1; nextEnabledOutput(config, enabled, &o); ) {
+	if (!modes[o])
+	    xf86DrvMsg (scrn->scrnIndex, X_ERROR,
+			"Output %s enabled but has no modes\n",
+			config->output[o]->name);
+	else
+	    xf86DrvMsg (scrn->scrnIndex, X_INFO,
+			"Output %s using initial mode %s\n",
+			config->output[o]->name, modes[o]->name);
     }
 
     /*
commit 5afdba241e59b1dbcec962fea809f445739590f3
Author: Adam Jackson <ajax at redhat.com>
Date:   Tue Mar 4 10:59:24 2008 -0500

    Remove all mention of the vga driver from the config logic.
    (cherry picked from commit 95df04b744c6a3498a9a9e2ea9bb03ee780e60f8)

diff --git a/hw/xfree86/common/xf86AutoConfig.c b/hw/xfree86/common/xf86AutoConfig.c
index da6c3f3..e3e0bb3 100644
--- a/hw/xfree86/common/xf86AutoConfig.c
+++ b/hw/xfree86/common/xf86AutoConfig.c
@@ -82,7 +82,6 @@ static int builtinLines = 0;
 static const char *deviceList[] = {
 	"fbdev",
 	"vesa",
-	"vga",
 	NULL
 };
 
@@ -450,8 +449,6 @@ chooseVideoDriver(void)
 	if (chosen_driver == NULL) {
 #if defined  __i386__ || defined __amd64__ || defined __hurd__
 	    chosen_driver = "vesa";
-#elif defined __alpha__
-	    chosen_driver = "vga";
 #elif defined __sparc__
 	    chosen_driver = "sunffb";
 #else
diff --git a/hw/xfree86/common/xf86Config.c b/hw/xfree86/common/xf86Config.c
index de3edf6..635a88c 100644
--- a/hw/xfree86/common/xf86Config.c
+++ b/hw/xfree86/common/xf86Config.c
@@ -494,7 +494,7 @@ xf86InputDriverlistFromConfig()
 static void
 fixup_video_driver_list(char **drivers)
 {
-    static const char *fallback[5] = { "vga", "vesa", "fbdev", "wsfb", NULL };
+    static const char *fallback[4] = { "vesa", "fbdev", "wsfb", NULL };
     char **end, **drv;
     char *x;
     char **ati, **atimisc;


More information about the xorg-commit mailing list