[PATCH] Add missing GTF modes

Chris Wilson chris at chris-wilson.co.uk
Mon Feb 25 04:13:14 PST 2013


A fixed-mode output device like a panel will often only inform of its
preferred mode through its EDID. However, the driver will adjust user
specified modes for display through use of a panel-fitter allowing
greater flexibility in upscaling. This is often used by games to set a
low resolution for performance and use the panel fitter to fill the
screen.

v2: Use the presence of the 'scaling mode' connector property as an
indication that a panel fitter is attached to that pipe.

Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=55564
---
 src/drmmode_display.c |   75 ++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 74 insertions(+), 1 deletion(-)

diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index 63cecc3..e8ebef1 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -626,6 +626,78 @@ drmmode_output_mode_valid(xf86OutputPtr output, DisplayModePtr pModes)
 	return MODE_OK;
 }
 
+static Bool
+has_panel_fitter(xf86OutputPtr output)
+{
+	drmmode_output_private_ptr drmmode_output = output->driver_private;
+	drmModeConnectorPtr koutput = drmmode_output->mode_output;
+	drmmode_ptr drmmode = drmmode_output->drmmode;
+	int i;
+
+	/* Presume that if the output supports scaling, then we have a
+	 * panel fitter capable of adjust any mode to suit.
+	 */
+	for (i = 0; i < koutput->count_props; i++) {
+		drmModePropertyPtr props;
+		Bool found = FALSE;
+
+		props = drmModeGetProperty(drmmode->fd, koutput->props[i]);
+		if (props) {
+			found = strcmp(props->name, "scaling mode") == 0;
+			drmModeFreeProperty(props);
+		}
+
+		if (found)
+			return TRUE;
+	}
+
+	return FALSE;
+}
+
+static DisplayModePtr
+drmmode_output_add_gtf_modes(xf86OutputPtr output,
+			     DisplayModePtr Modes)
+{
+	xf86MonPtr mon = output->MonInfo;
+	DisplayModePtr i, m, preferred = NULL;
+	int max_x = 0, max_y = 0;
+	float max_vrefresh = 0.0;
+
+	if (mon && GTF_SUPPORTED(mon->features.msc))
+		return Modes;
+
+	if (!has_panel_fitter(output))
+		return Modes;
+
+	for (m = Modes; m; m = m->next) {
+		if (m->type & M_T_PREFERRED)
+			preferred = m;
+		max_x = max(max_x, m->HDisplay);
+		max_y = max(max_y, m->VDisplay);
+		max_vrefresh = max(max_vrefresh, xf86ModeVRefresh(m));
+	}
+
+	max_vrefresh = max(max_vrefresh, 60.0);
+	max_vrefresh *= (1 + SYNC_TOLERANCE);
+
+	m = xf86GetDefaultModes();
+	xf86ValidateModesSize(output->scrn, m, max_x, max_y, 0);
+
+	for (i = m; i; i = i->next) {
+		if (xf86ModeVRefresh(i) > max_vrefresh)
+			i->status = MODE_VSYNC;
+		if (preferred &&
+		    i->HDisplay >= preferred->HDisplay &&
+		    i->VDisplay >= preferred->VDisplay &&
+		    xf86ModeVRefresh(i) >= xf86ModeVRefresh(preferred))
+			i->status = MODE_VSYNC;
+	}
+
+	xf86PruneInvalidModes(output->scrn, &m, FALSE);
+
+	return xf86ModesAdd(Modes, m);
+}
+
 static DisplayModePtr
 drmmode_output_get_modes(xf86OutputPtr output)
 {
@@ -666,7 +738,8 @@ drmmode_output_get_modes(xf86OutputPtr output)
 		Modes = xf86ModesAdd(Modes, Mode);
 
 	}
-	return Modes;
+
+	return drmmode_output_add_gtf_modes(output, Modes);
 }
 
 static void
-- 
1.7.10.4



More information about the xorg-devel mailing list