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:
parent
689d52b624
commit
33d2cf93fb
|
@ -1542,6 +1542,132 @@ xf86InitialConfiguration (ScrnInfoPtr scrn, Bool canGrow)
|
||||||
return TRUE;
|
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.
|
* Set the DPMS power mode of all outputs and CRTCs.
|
||||||
*
|
*
|
||||||
|
|
|
@ -594,6 +594,12 @@ xf86SaveScreen(ScreenPtr pScreen, int mode);
|
||||||
void
|
void
|
||||||
xf86DisableUnusedFunctions(ScrnInfoPtr pScrn);
|
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
|
* Set the EDID information for the specified output
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Reference in New Issue
Block a user