aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Stultz <john.stultz@linaro.org>2019-06-21 20:30:57 +0000
committerJohn Stultz <john.stultz@linaro.org>2019-06-21 20:30:57 +0000
commitf13a30b95ab986492e9208feb3de446b3d669cc1 (patch)
tree456febec556b9c21f956e3e7e69a86f9d45dc9b2
parent05a93307bd3c7164724fdf8d1665b5311ca57cb2 (diff)
parentb67d049c870c2b82c2883b0c10a07bc29c4cd598 (diff)
downloaddrm_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.cpp76
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;