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
This commit is contained in:
Chris Wilson 2012-12-03 13:25:19 +00:00
parent ac34281b8a
commit 75815dbb37

View File

@ -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