Move xf86SetSingleMode into X server from intel driver.

This function applies a single mode to the screen (as from RandR 1.1,
XFree86-VidModeExtension or XFree86-DGA) using a policy that selects one
output to reconfigure to the requested mode and then makes all other outputs
fit within that size.
(cherry picked from commit 5a595c1f76)
This commit is contained in:
Keith Packard 2007-03-03 23:10:31 -08:00
parent 689d52b624
commit 33d2cf93fb
2 changed files with 132 additions and 0 deletions

View File

@ -1542,6 +1542,132 @@ xf86InitialConfiguration (ScrnInfoPtr scrn, Bool canGrow)
return TRUE;
}
/**
* In the current world order, there are lists of modes per output, which may
* or may not include the mode that was asked to be set by XFree86's mode
* selection. Find the closest one, in the following preference order:
*
* - Equality
* - Closer in size to the requested mode, but no larger
* - Closer in refresh rate to the requested mode.
*/
DisplayModePtr
xf86OutputFindClosestMode (xf86OutputPtr output, DisplayModePtr desired)
{
DisplayModePtr best = NULL, scan = NULL;
for (scan = output->probed_modes; scan != NULL; scan = scan->next)
{
/* If there's an exact match, we're done. */
if (xf86ModesEqual(scan, desired)) {
best = desired;
break;
}
/* Reject if it's larger than the desired mode. */
if (scan->HDisplay > desired->HDisplay ||
scan->VDisplay > desired->VDisplay)
{
continue;
}
/*
* If we haven't picked a best mode yet, use the first
* one in the size range
*/
if (best == NULL)
{
best = scan;
continue;
}
/* Find if it's closer to the right size than the current best
* option.
*/
if ((scan->HDisplay > best->HDisplay &&
scan->VDisplay >= best->VDisplay) ||
(scan->HDisplay >= best->HDisplay &&
scan->VDisplay > best->VDisplay))
{
best = scan;
continue;
}
/* Find if it's still closer to the right refresh than the current
* best resolution.
*/
if (scan->HDisplay == best->HDisplay &&
scan->VDisplay == best->VDisplay &&
(fabs(scan->VRefresh - desired->VRefresh) <
fabs(best->VRefresh - desired->VRefresh))) {
best = scan;
}
}
return best;
}
/**
* When setting a mode through XFree86-VidModeExtension or XFree86-DGA,
* take the specified mode and apply it to the crtc connected to the compat
* output. Then, find similar modes for the other outputs, as with the
* InitialConfiguration code above. The goal is to clone the desired
* mode across all outputs that are currently active.
*/
Bool
xf86SetSingleMode (ScrnInfoPtr pScrn, DisplayModePtr desired, Rotation rotation)
{
xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
Bool ok = TRUE;
xf86OutputPtr compat_output = config->output[config->compat_output];
DisplayModePtr compat_mode;
int c;
/*
* Let the compat output drive the final mode selection
*/
compat_mode = xf86OutputFindClosestMode (compat_output, desired);
if (compat_mode)
desired = compat_mode;
for (c = 0; c < config->num_crtc; c++)
{
xf86CrtcPtr crtc = config->crtc[c];
DisplayModePtr crtc_mode = NULL;
int o;
if (!crtc->enabled)
continue;
for (o = 0; o < config->num_output; o++)
{
xf86OutputPtr output = config->output[o];
DisplayModePtr output_mode;
/* skip outputs not on this crtc */
if (output->crtc != crtc)
continue;
if (crtc_mode)
{
output_mode = xf86OutputFindClosestMode (output, crtc_mode);
if (output_mode != crtc_mode)
output->crtc = NULL;
}
else
crtc_mode = xf86OutputFindClosestMode (output, desired);
}
if (!xf86CrtcSetMode (crtc, crtc_mode, rotation, 0, 0))
ok = FALSE;
else
crtc->desiredMode = *crtc_mode;
}
xf86DisableUnusedFunctions(pScrn);
return ok;
}
/**
* Set the DPMS power mode of all outputs and CRTCs.
*

View File

@ -594,6 +594,12 @@ xf86SaveScreen(ScreenPtr pScreen, int mode);
void
xf86DisableUnusedFunctions(ScrnInfoPtr pScrn);
DisplayModePtr
xf86OutputFindClosestMode (xf86OutputPtr output, DisplayModePtr desired);
Bool
xf86SetSingleMode (ScrnInfoPtr pScrn, DisplayModePtr desired, Rotation rotation);
/**
* Set the EDID information for the specified output
*/