Hi Doug,
thanks for your reply!
In the meanwhile, I found a strategy that works well for me:
- Among modes of the same width, only keep the one whose aspect ratio best matches the aspect ratio of the physical screen. (The resulting list may still have modes with arbitrary a-r.)
- Optionally prune the result further by only keeping the modes with an a-r that is close to the physical a-r.
Not entirely pure GLFW code, but almost:
std::string glfwMonitorT::getUserChoiceList() const
{
unsigned int phys_width;
unsigned int phys_height;
getPhysicalSize(phys_width, phys_height);
const float phys_ar = float(phys_width) / float(phys_height);
int num_modes;
const GLFWvidmode* modes = glfwGetVideoModes(m_monitor, &num_modes);
std::vector<GLFWvidmode> ModeList;
ModeList.reserve(num_modes);
for (int i = 0; i < num_modes; i++)
ModeList.push_back(modes[i]);
std::sort(ModeList.begin(), ModeList.end(), CompareByWidth());
printModes("All modes, sorted by width", ModeList, phys_ar);
// Among modes that are of (almost) the same width, keep the one that best matches
// the aspect-ratio of the physical screen.
// This also removes duplicates from ignoring the bits per pixel and refresh rate.
for (size_t i = 0; i < ModeList.size(); i++)
{
float mi_ar = float(ModeList[i].width) / float(ModeList[i].height);
float mi_df = fabs(phys_ar - mi_ar);
for (size_t j = i + 1; j < ModeList.size(); j++)
{
if (abs(ModeList[i].width - ModeList[j].width) < 80)
{
const float mj_ar = float(ModeList[j].width) / float(ModeList[j].height);
const float mj_df = fabs(phys_ar - mj_ar);
if (mj_df < mi_df)
{
ModeList[i] = ModeList[j];
mi_ar = mj_ar;
mi_df = mj_df;
}
ModeList.erase(ModeList.begin() + j);
j--;
}
}
}
printModes("Kept the best match for each width", ModeList, phys_ar);
// Remove modes with mismatching aspect ratios.
for (size_t i = 0; i < ModeList.size() && ModeList.size() > 3; i++)
{
const float mi_ar = float(ModeList[i].width) / float(ModeList[i].height);
const float mi_df = fabs(phys_ar - mi_ar);
if (mi_df >= 0.1f)
{
ModeList.erase(ModeList.begin() + i);
i--;
}
}
printModes("Mismatching aspect ratios removed", ModeList, phys_ar);
// Assemble result.
std::string s;
for (size_t i = 0; i < ModeList.size(); i++)
s += std::to_string(ModeList[i].width) + " x " + std::to_string(ModeList[i].height) + "\n";
return s;
}
On my 16:10 screen, this yields:
All modes, sorted by width: (physical monitor a-r is 1.602)
320 * 200, 16:10.0 (1.600 0.002), 8 8 8, 59Hz
320 * 200, 16:10.0 (1.600 0.002), 8 8 8, 60Hz
320 * 240, 16:12.0 (1.333 0.269), 8 8 8, 59Hz
320 * 240, 16:12.0 (1.333 0.269), 8 8 8, 60Hz
400 * 300, 16:12.0 (1.333 0.269), 8 8 8, 59Hz
400 * 300, 16:12.0 (1.333 0.269), 8 8 8, 60Hz
512 * 384, 16:12.0 (1.333 0.269), 8 8 8, 59Hz
512 * 384, 16:12.0 (1.333 0.269), 8 8 8, 60Hz
640 * 400, 16:10.0 (1.600 0.002), 8 8 8, 59Hz
640 * 400, 16:10.0 (1.600 0.002), 8 8 8, 60Hz
640 * 480, 16:12.0 (1.333 0.269), 8 8 8, 59Hz
640 * 480, 16:12.0 (1.333 0.269), 8 8 8, 60Hz
720 * 480, 16:10.7 (1.500 0.102), 8 8 8, 59Hz
720 * 480, 16:10.7 (1.500 0.102), 8 8 8, 60Hz
800 * 600, 16:12.0 (1.333 0.269), 8 8 8, 59Hz
800 * 600, 16:12.0 (1.333 0.269), 8 8 8, 60Hz
1024 * 768, 16:12.0 (1.333 0.269), 8 8 8, 59Hz
1024 * 768, 16:12.0 (1.333 0.269), 8 8 8, 60Hz
1152 * 864, 16:12.0 (1.333 0.269), 8 8 8, 59Hz
1152 * 864, 16:12.0 (1.333 0.269), 8 8 8, 60Hz
1280 * 600, 16: 7.5 (2.133 -0.531), 8 8 8, 59Hz
1280 * 600, 16: 7.5 (2.133 -0.531), 8 8 8, 60Hz
1280 * 720, 16: 9.0 (1.778 -0.176), 8 8 8, 59Hz
1280 * 720, 16: 9.0 (1.778 -0.176), 8 8 8, 60Hz
1280 * 768, 16: 9.6 (1.667 -0.065), 8 8 8, 59Hz
1280 * 768, 16: 9.6 (1.667 -0.065), 8 8 8, 60Hz
1280 * 800, 16:10.0 (1.600 0.002), 8 8 8, 59Hz
1280 * 800, 16:10.0 (1.600 0.002), 8 8 8, 60Hz
1280 * 960, 16:12.0 (1.333 0.269), 8 8 8, 59Hz
1280 * 960, 16:12.0 (1.333 0.269), 8 8 8, 60Hz
1280 * 1024, 16:12.8 (1.250 0.352), 8 8 8, 59Hz
1280 * 1024, 16:12.8 (1.250 0.352), 8 8 8, 60Hz
1360 * 768, 16: 9.0 (1.771 -0.169), 8 8 8, 59Hz
1360 * 768, 16: 9.0 (1.771 -0.169), 8 8 8, 60Hz
1366 * 768, 16: 9.0 (1.779 -0.177), 8 8 8, 59Hz
1366 * 768, 16: 9.0 (1.779 -0.177), 8 8 8, 60Hz
1400 * 1050, 16:12.0 (1.333 0.269), 8 8 8, 59Hz
1400 * 1050, 16:12.0 (1.333 0.269), 8 8 8, 60Hz
1440 * 900, 16:10.0 (1.600 0.002), 8 8 8, 59Hz
1440 * 900, 16:10.0 (1.600 0.002), 8 8 8, 60Hz
1600 * 900, 16: 9.0 (1.778 -0.176), 8 8 8, 59Hz
1600 * 900, 16: 9.0 (1.778 -0.176), 8 8 8, 60Hz
1600 * 1200, 16:12.0 (1.333 0.269), 8 8 8, 59Hz
1600 * 1200, 16:12.0 (1.333 0.269), 8 8 8, 60Hz
1680 * 1050, 16:10.0 (1.600 0.002), 8 8 8, 59Hz
1680 * 1050, 16:10.0 (1.600 0.002), 8 8 8, 60Hz
1920 * 1080, 16: 9.0 (1.778 -0.176), 8 8 8, 59Hz
1920 * 1080, 16: 9.0 (1.778 -0.176), 8 8 8, 60Hz
1920 * 1200, 16:10.0 (1.600 0.002), 8 8 8, 59Hz
1920 * 1200, 16:10.0 (1.600 0.002), 8 8 8, 60Hz
Kept the best match for each width: (physical monitor a-r is 1.602)
320 * 200, 16:10.0 (1.600 0.002), 8 8 8, 59Hz
400 * 300, 16:12.0 (1.333 0.269), 8 8 8, 59Hz
512 * 384, 16:12.0 (1.333 0.269), 8 8 8, 59Hz
640 * 400, 16:10.0 (1.600 0.002), 8 8 8, 59Hz
720 * 480, 16:10.7 (1.500 0.102), 8 8 8, 59Hz
800 * 600, 16:12.0 (1.333 0.269), 8 8 8, 59Hz
1024 * 768, 16:12.0 (1.333 0.269), 8 8 8, 59Hz
1152 * 864, 16:12.0 (1.333 0.269), 8 8 8, 59Hz
1280 * 800, 16:10.0 (1.600 0.002), 8 8 8, 59Hz
1360 * 768, 16: 9.0 (1.771 -0.169), 8 8 8, 59Hz
1440 * 900, 16:10.0 (1.600 0.002), 8 8 8, 59Hz
1600 * 900, 16: 9.0 (1.778 -0.176), 8 8 8, 59Hz
1680 * 1050, 16:10.0 (1.600 0.002), 8 8 8, 59Hz
1920 * 1200, 16:10.0 (1.600 0.002), 8 8 8, 59Hz
Mismatching aspect ratios removed: (physical monitor a-r is 1.602)
320 * 200, 16:10.0 (1.600 0.002), 8 8 8, 59Hz
640 * 400, 16:10.0 (1.600 0.002), 8 8 8, 59Hz
1280 * 800, 16:10.0 (1.600 0.002), 8 8 8, 59Hz
1440 * 900, 16:10.0 (1.600 0.002), 8 8 8, 59Hz
1680 * 1050, 16:10.0 (1.600 0.002), 8 8 8, 59Hz
1920 * 1200, 16:10.0 (1.600 0.002), 8 8 8, 59Hz