summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2012-12-03 13:25:19 +0000
committerChris Wilson <chris@chris-wilson.co.uk>2013-02-25 12:12:53 +0000
commit06618a9b3d9585508b0debd18d5b981636f98c54 (patch)
tree387f07d84d65b4b0398ec12e18185182febd6eeb
parentacb90bc34ad99a7c4de8c69a26ff09a65cd0281d (diff)
Add missing GTF modes
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
-rw-r--r--src/drmmode_display.c75
1 files changed, 74 insertions, 1 deletions
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