diff options
author | John Stultz <john.stultz@linaro.org> | 2019-06-21 20:30:57 +0000 |
---|---|---|
committer | John Stultz <john.stultz@linaro.org> | 2019-06-21 20:30:57 +0000 |
commit | f13a30b95ab986492e9208feb3de446b3d669cc1 (patch) | |
tree | 456febec556b9c21f956e3e7e69a86f9d45dc9b2 | |
parent | 05a93307bd3c7164724fdf8d1665b5311ca57cb2 (diff) | |
parent | b67d049c870c2b82c2883b0c10a07bc29c4cd598 (diff) | |
download | drm_hwcomposer-f13a30b95ab986492e9208feb3de446b3d669cc1.tar.gz |
Merge remote-tracking branch 'aosp/upstream-master' into HEAD
Includes change from Neil that addresses db845c regression
caused by SF mode-selection (combined with a db845c specific mode
issue still to be fixed)
* aosp/upstream-master:
drm_hwcomposer: pre-filter modes provided to HWC2
Change-Id: I9eb36c50ea6ad50edb9971fdf93ea0f2757b87ac
Signed-off-by: John Stultz <john.stultz@linaro.org>
-rw-r--r-- | drmhwctwo.cpp | 76 |
1 files changed, 59 insertions, 17 deletions
diff --git a/drmhwctwo.cpp b/drmhwctwo.cpp index b96eb31..9268cdc 100644 --- a/drmhwctwo.cpp +++ b/drmhwctwo.cpp @@ -399,17 +399,37 @@ HWC2::Error DrmHwcTwo::HwcDisplay::GetDisplayConfigs(uint32_t *num_configs, } } - uint32_t idx = 0; + // Since the upper layers only look at vactive/hactive/refresh, height and + // width, it doesn't differentiate interlaced from progressive and other + // similar modes. Depending on the order of modes we return to SF, it could + // end up choosing a suboptimal configuration and dropping the preferred + // mode. To workaround this, don't offer interlaced modes to SF if there is + // at least one non-interlaced alternative and only offer a single WxH@R + // mode with at least the prefered mode from in DrmConnector::UpdateModes() + + // TODO: Remove the following block of code until AOSP handles all modes + std::vector<DrmMode> sel_modes; + + // Add the preferred mode first to be sure it's not dropped + auto mode = std::find_if(connector_->modes().begin(), + connector_->modes().end(), [&](DrmMode const &m) { + return m.id() == + connector_->get_preferred_mode_id(); + }); + if (mode != connector_->modes().end()) + sel_modes.push_back(*mode); + + // Add the active mode if different from preferred mode + if (connector_->active_mode().id() != connector_->get_preferred_mode_id()) + sel_modes.push_back(connector_->active_mode()); + + // Cycle over the modes and filter out "similar" modes, keeping only the + // first ones in the order given by DRM (from CEA ids and timings order) for (const DrmMode &mode : connector_->modes()) { - if (configs && idx >= *num_configs) - break; - // Since the upper layers only look at vactive/hactive/refresh, it doesn't - // differentiate interlaced from progressive modes. Depending on the order - // of modes we return to SF, it could end up choosing a suboptimal - // configuration. - // To workaround this, don't offer interlaced modes to SF if there is at - // least one non-interlaced alternative. - // + // TODO: Remove this when 3D Attributes are in AOSP + if (mode.flags() & DRM_MODE_FLAG_3D_MASK) + continue; + // TODO: Remove this when the Interlaced attribute is in AOSP if (mode.flags() & DRM_MODE_FLAG_INTERLACE) { auto m = std::find_if(connector_->modes().begin(), @@ -419,14 +439,36 @@ HWC2::Error DrmHwcTwo::HwcDisplay::GetDisplayConfigs(uint32_t *num_configs, m.h_display() == mode.h_display() && m.v_display() == mode.v_display(); }); - if (m != connector_->modes().end()) - continue; - } - if (configs) { - configs[idx++] = mode.id(); - } else { - idx++; + if (m == connector_->modes().end()) + sel_modes.push_back(mode); + + continue; } + + // Search for a similar WxH@R mode in the filtered list and drop it if + // another mode with the same WxH@R has already been selected + // TODO: Remove this when AOSP handles duplicates modes + auto m = std::find_if(sel_modes.begin(), sel_modes.end(), + [&mode](DrmMode const &m) { + return m.h_display() == mode.h_display() && + m.v_display() == mode.v_display() && + m.v_refresh() == mode.v_refresh(); + }); + if (m == sel_modes.end()) + sel_modes.push_back(mode); + } + + auto num_modes = static_cast<uint32_t>(sel_modes.size()); + if (!configs) { + *num_configs = num_modes; + return HWC2::Error::None; + } + + uint32_t idx = 0; + for (const DrmMode &mode : sel_modes) { + if (idx >= *num_configs) + break; + configs[idx++] = mode.id(); } *num_configs = idx; return HWC2::Error::None; |