From patchwork Wed Jun 1 10:06:38 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Florian Mickler X-Patchwork-Id: 838462 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by demeter1.kernel.org (8.14.4/8.14.3) with ESMTP id p51A7Yvp029999 for ; Wed, 1 Jun 2011 10:07:55 GMT Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 7F2419E9D3 for ; Wed, 1 Jun 2011 03:07:33 -0700 (PDT) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from mx01.d-labs.de (ist.d-labs.de [213.239.218.44]) by gabe.freedesktop.org (Postfix) with ESMTP id 2F5B99E774 for ; Wed, 1 Jun 2011 03:07:13 -0700 (PDT) Received: from schatten.dmk.lab (f053222245.adsl.alicedsl.de [78.53.222.245]) by mx01.d-labs.de (Postfix) with ESMTPSA id 215CC7F84C; Wed, 1 Jun 2011 12:07:11 +0200 (CEST) Received: by schatten.dmk.lab (Postfix, from userid 1000) id 998DBE5C00A; Wed, 1 Jun 2011 12:06:41 +0200 (CEST) From: Florian Mickler To: xorg-devel@lists.x.org, ajax@redhat.com Date: Wed, 1 Jun 2011 12:06:38 +0200 Message-Id: <1306922798-29344-1-git-send-email-florian@mickler.org> X-Mailer: git-send-email 1.7.4.1 In-Reply-To: <20110518190320.51800988@schatten.dmk.lab> References: <20110518190320.51800988@schatten.dmk.lab> Cc: intel-gfx@lists.freedesktop.org Subject: [Intel-gfx] [PATCH] change initial modesetting if outputs are aligned in 1 dimension X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.11 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: intel-gfx-bounces+patchwork-intel-gfx=patchwork.kernel.org@lists.freedesktop.org Errors-To: intel-gfx-bounces+patchwork-intel-gfx=patchwork.kernel.org@lists.freedesktop.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.6 (demeter1.kernel.org [140.211.167.41]); Wed, 01 Jun 2011 10:07:55 +0000 (UTC) Recently the kernel started reporting my outputs in a different ordering due to commit cb0953d734 (drm/i915: Initialize LVDS and eDP outputs before anything else) Which made X choose a "wrong" resolution for my VGA display. Since they are aligned horizontally, I wish them to be aligned in vertical Resolution only. Before this patch, the sum of squared distances would force my VGA display (1680x1050 native resolution) to 1280x1024 (non-native) due to my internal display beeing considered first and 1400x1050 as native resolution. This was not an issue the other way around (VGA beeing first) because 1400x1050 is nearest to 1680x1050 anyway. This patch changes the heuristic to only align resolution vertically if the displays are horizontally aligned, or vice versa. Signed-off-by: Florian Mickler --- Ok, Adam... seems I lost the staring contest... :) What about something like this? hw/xfree86/modes/xf86Crtc.c | 115 ++++++++++++++++++++++++++++++++++++------- 1 files changed, 96 insertions(+), 19 deletions(-) diff --git a/hw/xfree86/modes/xf86Crtc.c b/hw/xfree86/modes/xf86Crtc.c index 4e3f6bf..96c6c62 100644 --- a/hw/xfree86/modes/xf86Crtc.c +++ b/hw/xfree86/modes/xf86Crtc.c @@ -872,15 +872,92 @@ xf86DefaultMode (xf86OutputPtr output, int width, int height) return target_mode; } +static Bool +xf86GetOptRelation(xf86OutputPtr output, OutputOpts *relation, char **relative_name) +{ + int r; + static const OutputOpts relations[] = { + OPTION_BELOW, OPTION_RIGHT_OF, OPTION_ABOVE, OPTION_LEFT_OF + }; + + *relation = 0; + *relative_name = NULL; + + for (r = 0; r < 4; r++) + { + *relation = relations[r]; + *relative_name = xf86GetOptValString (output->options, + *relation); + if (*relative_name) + break; + } + return (*relative_name != NULL); +} + +static Bool +xf86OutputsRelatedHorizontal(xf86OutputPtr out1, xf86OutputPtr out2) +{ + OutputOpts relation; + char *other_name; + Bool ret = FALSE; + + if (xf86GetOptRelation(out1, &relation, &other_name) && + strcmp(other_name, out2->name) == 0) { + /* + * out1 related to out2 + */ + ret = (relation == OPTION_RIGHT_OF || + relation == OPTION_LEFT_OF); + } + if (!ret && xf86GetOptRelation(out2, &relation, &other_name) && + strcmp(other_name, out1->name) == 0) { + /* + * out2 related to out1 + */ + ret = (relation == OPTION_RIGHT_OF || + relation == OPTION_LEFT_OF); + } + + return ret; + +} + +static Bool +xf86OutputsRelatedVertical(xf86OutputPtr out1, xf86OutputPtr out2) +{ + OutputOpts relation; + char *other_name; + Bool ret = FALSE; + + if (xf86GetOptRelation(out1, &relation, &other_name) && + strcmp(other_name, out2->name) == 0) { + /* + * out1 related to out2 + */ + ret = (relation == OPTION_ABOVE || + relation == OPTION_BELOW); + } + if (!ret && xf86GetOptRelation(out2, &relation, &other_name) && + strcmp(other_name, out1->name) == 0) { + /* + * out2 related to out1 + */ + ret = (relation == OPTION_ABOVE || + relation == OPTION_BELOW); + } + + return ret; +} + static DisplayModePtr -xf86ClosestMode (xf86OutputPtr output, +xf86ClosestMode (xf86OutputPtr output, xf86OutputPtr match_output, DisplayModePtr match, Rotation match_rotation, int width, int height) { DisplayModePtr target_mode = NULL; DisplayModePtr mode; int target_diff = 0; - + /* * Pick a mode closest to the specified mode */ @@ -892,15 +969,26 @@ xf86ClosestMode (xf86OutputPtr output, if (xf86ModeWidth (mode, output->initial_rotation) > width || xf86ModeHeight (mode, output->initial_rotation) > height) continue; - + /* exact matches are preferred */ if (output->initial_rotation == match_rotation && xf86ModesEqual (mode, match)) return mode; - + dx = xf86ModeWidth (match, match_rotation) - xf86ModeWidth (mode, output->initial_rotation); dy = xf86ModeHeight (match, match_rotation) - xf86ModeHeight (mode, output->initial_rotation); - diff = dx * dx + dy * dy; + + /* + * If we are aligning screens horizontally or vertically use + * only one dimension for matching + */ + if (xf86OutputsRelatedHorizontal(output, match_output)) + diff = dy * dy; + else if (xf86OutputsRelatedVertical(output, match_output)) + diff = dx * dx; + else + diff = dx * dx + dy * dy; + xf86DrvMsg (0, X_INFO, "XF86ClosestMode: Output %s, Mode %s [ dx = %i, dy = %i, diff = %i ]\n", output->name, mode->name, dx, dy, diff); @@ -1122,10 +1210,6 @@ xf86UserConfiguredOutputs(ScrnInfoPtr scrn, DisplayModePtr *modes) char *position; char *relative_name; OutputOpts relation; - int r; - static const OutputOpts relations[] = { - OPTION_BELOW, OPTION_RIGHT_OF, OPTION_ABOVE, OPTION_LEFT_OF - }; position = xf86GetOptValString (output->options, OPTION_POSITION); @@ -1137,15 +1221,7 @@ xf86UserConfiguredOutputs(ScrnInfoPtr scrn, DisplayModePtr *modes) } relation = 0; relative_name = NULL; - for (r = 0; r < 4; r++) - { - relation = relations[r]; - relative_name = xf86GetOptValString (output->options, - relation); - if (relative_name) - break; - } - if (relative_name) { + if (xf86GetOptRelation(output, &relation, &relative_name)) { user_conf = TRUE; xf86DrvMsg (scrn->scrnIndex, X_INFO, "Output %s has user_conf due to relation: %s\n", @@ -2245,7 +2321,8 @@ xf86TargetFallback(ScrnInfoPtr scrn, xf86CrtcConfigPtr config, /* Fill in other output modes */ for (o = -1; nextEnabledOutput(config, enabled, &o); ) { if (!modes[o]) - modes[o] = xf86ClosestMode(config->output[o], target_mode, + modes[o] = xf86ClosestMode(config->output[o], + config->output[config->compat_output], target_mode, target_rotation, width, height); }