1
0
Fork 0

Dedupe near-identical EDID modes by resolution and refresh rate

This commit is contained in:
Brendan Szymanski 2026-07-13 14:36:44 -04:00
parent 22ba81cf61
commit fbaba3b2b4

View file

@ -21,9 +21,11 @@
#include <drm/drm_mode.h> #include <drm/drm_mode.h>
#include <xf86drmMode.h> #include <xf86drmMode.h>
#include <algorithm>
#include <array> #include <array>
#include <cerrno> #include <cerrno>
#include <cinttypes> #include <cinttypes>
#include <cmath>
#include <cstdint> #include <cstdint>
#include <sstream> #include <sstream>
@ -265,6 +267,26 @@ std::string DrmConnector::GetName() const {
return "None"; return "None";
} }
namespace {
// Some EDIDs describe the same effective resolution/refresh-rate as two
// distinct raw mode entries -- e.g. a detailed-timing "preferred" mode plus a
// CEA-861 mode for the same nominal timing, differing only in blanking or in
// the DRM_MODE_TYPE_PREFERRED bit. A byte-for-byte comparison (DrmMode::
// operator==) treats these as separate modes, so both survive into the mode
// list. That leaves which mode is "preferred" ambiguous between the kernel's
// initial modeset and drm_hwcomposer's own selection, which is the suspected
// cause of a mid-boot mode switch (visible as overscan until HDMI is
// replugged) and of framework APIs like Display.getSystemPreferredDisplayMode()
// intermittently returning null (TvSettings NPE on the Resolution screen).
constexpr float kDuplicateModeRateEpsilonHz = 0.05F;
bool IsSameEffectiveMode(const DrmMode &existing, const DrmMode &candidate) {
return existing.SameSize(candidate) &&
std::abs(existing.GetVRefresh() - candidate.GetVRefresh()) <
kDuplicateModeRateEpsilonHz;
}
} // namespace
int DrmConnector::UpdateModes() { int DrmConnector::UpdateModes() {
std::string force_mode = Properties::GetForceMode(); std::string force_mode = Properties::GetForceMode();
uint32_t xres = 0, yres = 0, rate = 0; uint32_t xres = 0, yres = 0, rate = 0;
@ -287,19 +309,28 @@ int DrmConnector::UpdateModes() {
modes_.clear(); modes_.clear();
for (int i = 0; i < connector_->count_modes; ++i) { for (int i = 0; i < connector_->count_modes; ++i) {
bool exists = false;
for (const DrmMode &mode : modes_) {
if (mode == connector_->modes[i]) {
exists = true;
break;
}
}
if (!exists) {
DrmMode m(&connector_->modes[i]); DrmMode m(&connector_->modes[i]);
ALOGV("Supported mode %dx%d@%fHz for display in connector %s", ALOGV("Supported mode %dx%d@%fHz for display in connector %s",
m.GetRawMode().hdisplay, m.GetRawMode().vdisplay, m.GetRawMode().hdisplay, m.GetRawMode().vdisplay,
m.GetVRefresh(), GetName().c_str()); m.GetVRefresh(), GetName().c_str());
auto existing = std::find_if(modes_.begin(), modes_.end(),
[&m](const DrmMode &other) {
return IsSameEffectiveMode(other, m);
});
if (existing != modes_.end()) {
// Keep whichever duplicate carries the EDID's PREFERRED flag.
if ((m.GetRawMode().type & DRM_MODE_TYPE_PREFERRED) != 0 &&
(existing->GetRawMode().type & DRM_MODE_TYPE_PREFERRED) == 0) {
ALOGD("Mode %dx%d@%fHz for display in connector %s duplicated; "
"keeping the PREFERRED entry",
m.GetRawMode().hdisplay, m.GetRawMode().vdisplay,
m.GetVRefresh(), GetName().c_str());
*existing = m;
}
continue;
}
if (xres && yres) { if (xres && yres) {
if (!rate && m.GetRawMode().hdisplay == xres if (!rate && m.GetRawMode().hdisplay == xres
&& m.GetRawMode().vdisplay == yres) { && m.GetRawMode().vdisplay == yres) {
@ -316,7 +347,6 @@ int DrmConnector::UpdateModes() {
m.GetVRefresh(), GetName().c_str()); m.GetVRefresh(), GetName().c_str());
modes_.emplace_back(m); modes_.emplace_back(m);
} }
}
return 0; return 0;
} }