191 lines
5.8 KiB
Diff
191 lines
5.8 KiB
Diff
|
From 326f992a90dae7a747da45626e588fa3c1dfa5dc Mon Sep 17 00:00:00 2001
|
||
|
From: Ray Strode <rstrode@redhat.com>
|
||
|
Date: Fri, 21 Sep 2018 14:38:31 -0400
|
||
|
Subject: [PATCH xserver] xfree86: try harder to span on multihead
|
||
|
|
||
|
right now if one of the monitors can't give
|
||
|
it's native resolution because of bandwidth limitations,
|
||
|
X decides to avoid spanning and instead clone.
|
||
|
|
||
|
That's suboptimal, spanning is normally the right
|
||
|
thing to do (with the exception of some projector
|
||
|
use cases and other edge cases)
|
||
|
|
||
|
This commit tries harder to make spanning work.
|
||
|
---
|
||
|
hw/xfree86/modes/xf86Crtc.c | 33 +++++++++++++++++++++++++++++----
|
||
|
1 file changed, 29 insertions(+), 4 deletions(-)
|
||
|
|
||
|
diff --git a/hw/xfree86/modes/xf86Crtc.c b/hw/xfree86/modes/xf86Crtc.c
|
||
|
index 37a45bb3a..686cb51b8 100644
|
||
|
--- a/hw/xfree86/modes/xf86Crtc.c
|
||
|
+++ b/hw/xfree86/modes/xf86Crtc.c
|
||
|
@@ -2132,135 +2132,160 @@ bestModeForAspect(xf86CrtcConfigPtr config, Bool *enabled, float aspect)
|
||
|
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 int
|
||
|
numEnabledOutputs(xf86CrtcConfigPtr config, Bool *enabled)
|
||
|
{
|
||
|
int i = 0, p;
|
||
|
|
||
|
for (i = 0, p = -1; nextEnabledOutput(config, enabled, &p); i++) ;
|
||
|
|
||
|
return i;
|
||
|
}
|
||
|
|
||
|
+static DisplayModePtr
|
||
|
+findReasonableMode(xf86CrtcConfigPtr config, xf86OutputPtr output, Bool *enabled, int width, int height)
|
||
|
+{
|
||
|
+ DisplayModePtr mode =
|
||
|
+ xf86OutputHasPreferredMode(output, width, height);
|
||
|
+
|
||
|
+ /* if there's no preferred mode, just try to find a reasonable one */
|
||
|
+ if (!mode) {
|
||
|
+ float aspect = 0.0;
|
||
|
+ DisplayModePtr a = NULL, b = NULL;
|
||
|
+
|
||
|
+ if (output->mm_height)
|
||
|
+ aspect = (float) output->mm_width /
|
||
|
+ (float) output->mm_height;
|
||
|
+
|
||
|
+ a = bestModeForAspect(config, enabled, 4.0/3.0);
|
||
|
+ if (aspect)
|
||
|
+ b = bestModeForAspect(config, enabled, aspect);
|
||
|
+
|
||
|
+ mode = biggestMode(a, b);
|
||
|
+ }
|
||
|
+
|
||
|
+ return mode;
|
||
|
+}
|
||
|
+
|
||
|
static Bool
|
||
|
xf86TargetRightOf(ScrnInfoPtr scrn, xf86CrtcConfigPtr config,
|
||
|
DisplayModePtr *modes, Bool *enabled,
|
||
|
int width, int height)
|
||
|
{
|
||
|
int o;
|
||
|
int w = 0;
|
||
|
Bool has_tile = FALSE;
|
||
|
uint32_t configured_outputs;
|
||
|
|
||
|
xf86GetOptValBool(config->options, OPTION_PREFER_CLONEMODE,
|
||
|
&scrn->preferClone);
|
||
|
if (scrn->preferClone)
|
||
|
return FALSE;
|
||
|
|
||
|
if (numEnabledOutputs(config, enabled) < 2)
|
||
|
return FALSE;
|
||
|
|
||
|
for (o = -1; nextEnabledOutput(config, enabled, &o); ) {
|
||
|
DisplayModePtr mode =
|
||
|
- xf86OutputHasPreferredMode(config->output[o], width, height);
|
||
|
+ findReasonableMode(config, config->output[o], enabled, width, height);
|
||
|
|
||
|
if (!mode)
|
||
|
return FALSE;
|
||
|
|
||
|
w += mode->HDisplay;
|
||
|
}
|
||
|
|
||
|
if (w > width)
|
||
|
return FALSE;
|
||
|
|
||
|
w = 0;
|
||
|
configured_outputs = 0;
|
||
|
|
||
|
for (o = -1; nextEnabledOutput(config, enabled, &o); ) {
|
||
|
DisplayModePtr mode =
|
||
|
- xf86OutputHasPreferredMode(config->output[o], width, height);
|
||
|
+ findReasonableMode(config, config->output[o], enabled, width, height);
|
||
|
|
||
|
if (configured_outputs & (1 << o))
|
||
|
continue;
|
||
|
|
||
|
if (config->output[o]->tile_info.group_id) {
|
||
|
has_tile = TRUE;
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
config->output[o]->initial_x = w;
|
||
|
w += mode->HDisplay;
|
||
|
|
||
|
configured_outputs |= (1 << o);
|
||
|
modes[o] = mode;
|
||
|
}
|
||
|
|
||
|
if (has_tile) {
|
||
|
for (o = -1; nextEnabledOutput(config, enabled, &o); ) {
|
||
|
int ht, vt, ot;
|
||
|
int add_x, cur_x = w;
|
||
|
struct xf86CrtcTileInfo *tile_info = &config->output[o]->tile_info, *this_tile;
|
||
|
if (configured_outputs & (1 << o))
|
||
|
continue;
|
||
|
if (!tile_info->group_id)
|
||
|
continue;
|
||
|
|
||
|
if (tile_info->tile_h_loc != 0 && tile_info->tile_v_loc != 0)
|
||
|
continue;
|
||
|
|
||
|
for (ht = 0; ht < tile_info->num_h_tile; ht++) {
|
||
|
int cur_y = 0;
|
||
|
add_x = 0;
|
||
|
for (vt = 0; vt < tile_info->num_v_tile; vt++) {
|
||
|
|
||
|
for (ot = -1; nextEnabledOutput(config, enabled, &ot); ) {
|
||
|
-
|
||
|
DisplayModePtr mode =
|
||
|
- xf86OutputHasPreferredMode(config->output[ot], width, height);
|
||
|
+ findReasonableMode(config, config->output[ot], enabled, width, height);
|
||
|
+
|
||
|
if (!config->output[ot]->tile_info.group_id)
|
||
|
continue;
|
||
|
|
||
|
this_tile = &config->output[ot]->tile_info;
|
||
|
if (this_tile->group_id != tile_info->group_id)
|
||
|
continue;
|
||
|
|
||
|
if (this_tile->tile_h_loc != ht ||
|
||
|
this_tile->tile_v_loc != vt)
|
||
|
continue;
|
||
|
|
||
|
config->output[ot]->initial_x = cur_x;
|
||
|
config->output[ot]->initial_y = cur_y;
|
||
|
|
||
|
if (vt == 0)
|
||
|
add_x = this_tile->tile_h_size;
|
||
|
cur_y += this_tile->tile_v_size;
|
||
|
configured_outputs |= (1 << ot);
|
||
|
modes[ot] = mode;
|
||
|
}
|
||
|
}
|
||
|
cur_x += add_x;
|
||
|
}
|
||
|
w = cur_x;
|
||
|
}
|
||
|
}
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
static Bool
|
||
|
--
|
||
|
2.17.1
|
||
|
|