diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2012-12-03 13:25:19 +0000 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2013-02-25 12:12:53 +0000 |
commit | 06618a9b3d9585508b0debd18d5b981636f98c54 (patch) | |
tree | 387f07d84d65b4b0398ec12e18185182febd6eeb | |
parent | acb90bc34ad99a7c4de8c69a26ff09a65cd0281d (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.c | 75 |
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 |