You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
190 lines
5.8 KiB
190 lines
5.8 KiB
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 |
|
|
|
|