Dedupe near-identical EDID modes by resolution and refresh rate
This commit is contained in:
parent
22ba81cf61
commit
fbaba3b2b4
1 changed files with 54 additions and 24 deletions
|
|
@ -21,9 +21,11 @@
|
|||
#include <drm/drm_mode.h>
|
||||
#include <xf86drmMode.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <cerrno>
|
||||
#include <cinttypes>
|
||||
#include <cmath>
|
||||
#include <cstdint>
|
||||
#include <sstream>
|
||||
|
||||
|
|
@ -265,6 +267,26 @@ std::string DrmConnector::GetName() const {
|
|||
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() {
|
||||
std::string force_mode = Properties::GetForceMode();
|
||||
uint32_t xres = 0, yres = 0, rate = 0;
|
||||
|
|
@ -287,35 +309,43 @@ int DrmConnector::UpdateModes() {
|
|||
|
||||
modes_.clear();
|
||||
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;
|
||||
DrmMode m(&connector_->modes[i]);
|
||||
ALOGV("Supported mode %dx%d@%fHz for display in connector %s",
|
||||
m.GetRawMode().hdisplay, m.GetRawMode().vdisplay,
|
||||
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 (!exists) {
|
||||
DrmMode m(&connector_->modes[i]);
|
||||
ALOGV("Supported mode %dx%d@%fHz for display in connector %s",
|
||||
m.GetRawMode().hdisplay, m.GetRawMode().vdisplay,
|
||||
m.GetVRefresh(), GetName().c_str());
|
||||
if (xres && yres) {
|
||||
if (!rate && m.GetRawMode().hdisplay == xres
|
||||
&& m.GetRawMode().vdisplay == yres) {
|
||||
rate = m.GetVRefresh();
|
||||
}
|
||||
if (m.GetRawMode().hdisplay != xres
|
||||
|| m.GetRawMode().vdisplay != yres
|
||||
|| m.GetVRefresh() != rate) {
|
||||
continue;
|
||||
}
|
||||
if (xres && yres) {
|
||||
if (!rate && m.GetRawMode().hdisplay == xres
|
||||
&& m.GetRawMode().vdisplay == yres) {
|
||||
rate = m.GetVRefresh();
|
||||
}
|
||||
if (m.GetRawMode().hdisplay != xres
|
||||
|| m.GetRawMode().vdisplay != yres
|
||||
|| m.GetVRefresh() != rate) {
|
||||
continue;
|
||||
}
|
||||
ALOGD("Add mode %dx%d@%fHz for display in connector %s",
|
||||
m.GetRawMode().hdisplay, m.GetRawMode().vdisplay,
|
||||
m.GetVRefresh(), GetName().c_str());
|
||||
modes_.emplace_back(m);
|
||||
}
|
||||
ALOGD("Add mode %dx%d@%fHz for display in connector %s",
|
||||
m.GetRawMode().hdisplay, m.GetRawMode().vdisplay,
|
||||
m.GetVRefresh(), GetName().c_str());
|
||||
modes_.emplace_back(m);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue