In attempting to document how displays are expected to work in F12 [1], I realized we still don't have a decent heuristic for some cases.
Broadly, displays are either fixed-format or variable-format. FF means you have some set number of pixels, like an LCD. VF means you don't, like a CRT. (Projectors are often somewhere in between, we'll pretend they don't exist for a moment.) We get FF displays pretty much right, since they tend to describe themselves well enough in EDID to figure out what their native size is. Some VF displays are polite enough to define a preferred mode, and for that case we'll default to that.
But, many VF displays don't define a preferred mode. How are we to choose? What's currently implemented will pick something along the lines of "the largest available mode that matches our guess at the physical aspect ratio and that fits in the card's DAC and memory bandwidth limits". Which is awful. So I'm thinking something like (in wretched pseudopython):
def mode_dpi_cmp(x, y): return cmp(abs(x.dpi - 96), abs(y.dpi - 96))
def mode_size_cmp(x, y): return cmp(x.width * x.height, y.width * y.height)
def best_mode(modes, dpi_known = True): l = filter(lambda x: x.refresh >= 72, modes) if l == []: l = modes if dpi_known: l.sort(cmp=mode_dpi_cmp) else: l.sort(cmp=mode_size_cmp) return l[0]
Which is _pretty_ good, except you'd kinda like to match aspect ratio if you happen to know AR but not DPI. Which is trivial to add, but starts to be hard to read.
If anyone has ideas I'm all ears, but I'd like to get this implemented sometime this week, so speak up.
[1] https://fedoraproject.org/wiki/Desktop/Whiteboards/HardwareHandling
- ajax
On Tue, 2009-09-15 at 12:06 -0400, Adam Jackson wrote:
In attempting to document how displays are expected to work in F12 [1], I realized we still don't have a decent heuristic for some cases.
Broadly, displays are either fixed-format or variable-format. FF means you have some set number of pixels, like an LCD. VF means you don't, like a CRT. (Projectors are often somewhere in between, we'll pretend they don't exist for a moment.) We get FF displays pretty much right, since they tend to describe themselves well enough in EDID to figure out what their native size is. Some VF displays are polite enough to define a preferred mode, and for that case we'll default to that.
But, many VF displays don't define a preferred mode. How are we to choose? What's currently implemented will pick something along the lines of "the largest available mode that matches our guess at the physical aspect ratio and that fits in the card's DAC and memory bandwidth limits". Which is awful. So I'm thinking something like (in wretched pseudopython):
def mode_dpi_cmp(x, y): return cmp(abs(x.dpi - 96), abs(y.dpi - 96))
def mode_size_cmp(x, y): return cmp(x.width * x.height, y.width * y.height)
def best_mode(modes, dpi_known = True): l = filter(lambda x: x.refresh >= 72, modes) if l == []: l = modes if dpi_known: l.sort(cmp=mode_dpi_cmp) else: l.sort(cmp=mode_size_cmp) return l[0]
Which is _pretty_ good, except you'd kinda like to match aspect ratio if you happen to know AR but not DPI. Which is trivial to add, but starts to be hard to read.
If anyone has ideas I'm all ears, but I'd like to get this implemented sometime this week, so speak up.
I know that, in the dinosaur days of CRT, I could 'see' flicker (and get flicker-generated headaches) at anything under 80Hz, and I know there are even more sensitive people than that. So 72Hz may be a bit of a low 'safe refresh rate' cutoff. I'd like it to be 80 at least. 72/75 were better than 65 for me, but definitely not acceptable for long-term work.
(/me remembers the days when you could gain any office worker's everlasting friendship by changing their refresh rate from 60Hz to 85Hz...ahhh, good times.)
On Tue, 2009-09-15 at 10:48 -0700, Adam Williamson wrote:
I know that, in the dinosaur days of CRT, I could 'see' flicker (and get flicker-generated headaches) at anything under 80Hz, and I know there are even more sensitive people than that. So 72Hz may be a bit of a low 'safe refresh rate' cutoff. I'd like it to be 80 at least. 72/75 were better than 65 for me, but definitely not acceptable for long-term work.
The struggle here is that you may not actually have any modes in the pool with refresh rates that high. I'm remembering 72Hz as some OSHA recommendation but I'm not able to find a reference to it quickly. Both the EU and EnergyStar seem to indicate that CRTs should be measured for power at the largest resolution supported at 75Hz, but that's a power recommendation, not an ergonomic one.
There's also a (rather small) power usage argument here. Higher refresh rates require more memory bandwidth, which means more memory cycles, which means more power draw. It's linear on number of pixels, but the coefficient is pretty low, so maybe it's not worth worrying about.
I suppose you could successively run the filter() step in the given algorithm until you get a non-empty list. Nggh though.
- ajax
We get FF [fixed format] displays pretty much right,
What is holding up https://bugzilla.redhat.com/show_bug.cgi?id=493441 where a 1024x768 LCD panel is recognized only as 800x600, and with no option to choose 1024x768, except via explicit /etc/X11/xorg.conf ?
That box does not have EDID, but Xorg.0.log shows (II) R128(0): Panel size: 1024x768 so the driver does know the truth. It looks like a lazy driver if EDID is the only way to success.
On Tue, 2009-09-15 at 11:13 -0700, John Reiser wrote:
We get FF [fixed format] displays pretty much right,
What is holding up https://bugzilla.redhat.com/show_bug.cgi?id=493441
Primarily that it's rage128 hardware, which no one likes working on.
where a 1024x768 LCD panel is recognized only as 800x600, and with no option to choose 1024x768, except via explicit /etc/X11/xorg.conf ?
That box does not have EDID, but Xorg.0.log shows (II) R128(0): Panel size: 1024x768 so the driver does know the truth. It looks like a lazy driver if EDID is the only way to success.
Pretty sure I've seen other cases where r128 gets the panel size wrong.
We do something similar in the vesa driver though, where we'll call out to the VBE panel ID method if there's no EDID. I'd be interested to see what vesa does on that hardware. The panel size dump in r128 is scraping out of some scratch registers that happen to be the right size sometimes, where the VBE call might actually be reliable.
- ajax
On 09-09-15 12:06:54, Adam Jackson wrote: ...
def mode_dpi_cmp(x, y): return cmp(abs(x.dpi - 96), abs(y.dpi - 96))
...
The names x and y suggest coordinates to me. I'd have read the code right the first time if the names had been a and b.
def best_mode(modes, dpi_known = True): l = filter(lambda x: x.refresh >= 72, modes)
If the sort is stable, how about sorting by highest refresh rate first? That way an 85 Hz refresh (if available) would be preferred over a 75 Hz refresh rate. (I expect the 72 Hz is to separate out LCDs which usually have a fixed rate of about 60 Hz.)
l = filter(lambda a: a.refresh >= 72, modes).sorted( key=lambda a: -a.refresh )
(BTW, use key instead of cmp in the other cases as well.)
if l == []: l = modes if dpi_known: l.sort(cmp=mode_dpi_cmp) else: l.sort(cmp=mode_size_cmp) return l[0]
...
In any case, thank you for working on it (my bz is 522155 "RFE choose sensible resolution during boot").
Here's my suggestion...
def mode_megapixels(mode): return mode.width * mode.height
# Sort by best refresh rate. modes.sort(key=lambda mode: -mode['refresh'])
# Prefer to balance refresh rate vs. pixels. if dpi_known: acceptable = filter(lambda mode: mode.dpi >= 90, modes) if len(acceptable) > 0: # Anything above 90 DPI is good enough # for a default. # Pick the one with the best refresh. return acceptable[0]
# DPI not known or too low, balance refresh vs. pixels. best_megapixels = max(modes, mode_megapixels) acceptable = filter(lambda mode: megapixels(mode) >= best_megapixels / 2) # Pick the mode with the highest refresh rate and at least # half the max possible number of pixels. acceptable[0]
/abo
On 09-09-21 11:46:41, Alexander Boström wrote:
Here's my suggestion...
def mode_megapixels(mode): return mode.width * mode.height
# Sort by best refresh rate. modes.sort(key=lambda mode: -mode['refresh'])
# Prefer to balance refresh rate vs. pixels. if dpi_known: acceptable = filter(lambda mode: mode.dpi >= 90, modes) if len(acceptable) > 0: # Anything above 90 DPI is good enough # for a default.
This is wrong, as it will produce more or less random resolutions up to the maximum supported by the monitor, which is in fact the motivation for doing better. The modes close to 90 DPI should be preferred.
# Pick the one with the best refresh. return acceptable[0]
# DPI not known or too low, balance refresh vs. pixels. best_megapixels = max(modes, mode_megapixels) acceptable = filter(lambda mode: megapixels(mode) >= best_megapixels / 2) # Pick the mode with the highest refresh rate and at least # half the max possible number of pixels. acceptable[0]