xserver: Branch 'server-1.3-branch'
Keith Packard
keithp at kemper.freedesktop.org
Tue Mar 6 06:17:36 EET 2007
hw/xfree86/modes/xf86Crtc.c | 126 ++++++++++++++++++++++++++++++++++++++++++++
hw/xfree86/modes/xf86Crtc.h | 6 ++
2 files changed, 132 insertions(+)
New commits:
diff-tree 5a595c1f767a8d666348b845d18934aee0cfe38f (from 73904d953f2f9cbe941a215ba240b46bc7a61357)
Author: Keith Packard <keithp at neko.keithp.com>
Date: Sat Mar 3 23:10:31 2007 -0800
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.
diff --git a/hw/xfree86/modes/xf86Crtc.c b/hw/xfree86/modes/xf86Crtc.c
index 2ffa956..3d28293 100644
--- a/hw/xfree86/modes/xf86Crtc.c
+++ b/hw/xfree86/modes/xf86Crtc.c
@@ -1543,6 +1543,132 @@ xf86InitialConfiguration (ScrnInfoPtr sc
}
/**
+ * 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.
*
* If the new mode is off, it will turn off outputs and then CRTCs.
diff --git a/hw/xfree86/modes/xf86Crtc.h b/hw/xfree86/modes/xf86Crtc.h
index 537df3a..56c7769 100644
--- a/hw/xfree86/modes/xf86Crtc.h
+++ b/hw/xfree86/modes/xf86Crtc.h
@@ -594,6 +594,12 @@ xf86SaveScreen(ScreenPtr pScreen, int mo
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
*/
More information about the xorg-commit
mailing list