drm_hwcomposer: Move HwcDisplayConfigs out of HwcDisplay class
To reduce complexity of HwcDisplay class.
Signed-off-by: Roman Stratiienko <roman.o.stratiienko@globallogic.com>
diff --git a/Android.bp b/Android.bp
index 59aa05f..8e99056 100644
--- a/Android.bp
+++ b/Android.bp
@@ -110,6 +110,7 @@
"hwc2_device/DrmHwcTwo.cpp",
"hwc2_device/HwcDisplay.cpp",
+ "hwc2_device/HwcDisplayConfigs.cpp",
"hwc2_device/HwcLayer.cpp",
"hwc2_device/hwc2_device.cpp",
],
diff --git a/hwc2_device/HwcDisplay.cpp b/hwc2_device/HwcDisplay.cpp
index e0a5823..b2cdfa3 100644
--- a/hwc2_device/HwcDisplay.cpp
+++ b/hwc2_device/HwcDisplay.cpp
@@ -190,13 +190,11 @@
}
HWC2::Error HwcDisplay::ChosePreferredConfig() {
- // Fetch the number of modes from the display
- uint32_t num_configs = 0;
- HWC2::Error err = GetDisplayConfigs(&num_configs, nullptr);
- if (err != HWC2::Error::None || !num_configs)
+ HWC2::Error err = configs_.Update(*connector_);
+ if (err != HWC2::Error::None)
return HWC2::Error::BadDisplay;
- return SetActiveConfig(preferred_config_id_);
+ return SetActiveConfig(configs_.preferred_config_id);
}
HWC2::Error HwcDisplay::AcceptDisplayChanges() {
@@ -221,10 +219,10 @@
}
HWC2::Error HwcDisplay::GetActiveConfig(hwc2_config_t *config) const {
- if (hwc_configs_.count(active_config_id_) == 0)
+ if (configs_.hwc_configs.count(configs_.active_config_id) == 0)
return HWC2::Error::BadConfig;
- *config = active_config_id_;
+ *config = configs_.active_config_id;
return HWC2::Error::None;
}
@@ -280,12 +278,12 @@
int32_t *value) {
int conf = static_cast<int>(config);
- if (hwc_configs_.count(conf) == 0) {
+ if (configs_.hwc_configs.count(conf) == 0) {
ALOGE("Could not find active mode for %d", conf);
return HWC2::Error::BadConfig;
}
- auto &hwc_config = hwc_configs_[conf];
+ auto &hwc_config = configs_.hwc_configs[conf];
static const int32_t kUmPerInch = 25400;
uint32_t mm_width = connector_->mm_width();
@@ -328,7 +326,6 @@
return HWC2::Error::None;
}
-// NOLINTNEXTLINE (readability-function-cognitive-complexity): Fixme
HWC2::Error HwcDisplay::GetDisplayConfigs(uint32_t *num_configs,
hwc2_config_t *configs) {
// Since this callback is normally invoked twice (once to get the count, and
@@ -337,142 +334,11 @@
// it's possible this will result in stale modes, it'll all come out in the
// wash when we try to set the active config later.
if (!configs) {
- int ret = connector_->UpdateModes();
- if (ret) {
- ALOGE("Failed to update display modes %d", ret);
- return HWC2::Error::BadDisplay;
- }
-
- hwc_configs_.clear();
- preferred_config_id_ = 0;
- int preferred_config_group_id_ = 0;
-
- if (connector_->modes().empty()) {
- ALOGE("No modes reported by KMS");
- return HWC2::Error::BadDisplay;
- }
-
- int last_config_id = 1;
- int last_group_id = 1;
-
- /* Group modes */
- for (const auto &mode : connector_->modes()) {
- /* Find group for the new mode or create new group */
- int group_found = 0;
- for (auto &hwc_config : hwc_configs_) {
- if (mode.h_display() == hwc_config.second.mode.h_display() &&
- mode.v_display() == hwc_config.second.mode.v_display()) {
- group_found = hwc_config.second.group_id;
- }
- }
- if (group_found == 0) {
- group_found = last_group_id++;
- }
-
- bool disabled = false;
- if (mode.flags() & DRM_MODE_FLAG_3D_MASK) {
- ALOGI("Disabling display mode %s (Modes with 3D flag aren't supported)",
- mode.name().c_str());
- disabled = true;
- }
-
- /* Add config */
- hwc_configs_[last_config_id] = {
- .id = last_config_id,
- .group_id = group_found,
- .mode = mode,
- .disabled = disabled,
- };
-
- /* Chwck if the mode is preferred */
- if ((mode.type() & DRM_MODE_TYPE_PREFERRED) != 0 &&
- preferred_config_id_ == 0) {
- preferred_config_id_ = last_config_id;
- preferred_config_group_id_ = group_found;
- }
-
- last_config_id++;
- }
-
- /* We must have preferred mode. Set first mode as preferred
- * in case KMS haven't reported anything. */
- if (preferred_config_id_ == 0) {
- preferred_config_id_ = 1;
- preferred_config_group_id_ = 1;
- }
-
- for (int group = 1; group < last_group_id; group++) {
- bool has_interlaced = false;
- bool has_progressive = false;
- for (auto &hwc_config : hwc_configs_) {
- if (hwc_config.second.group_id != group || hwc_config.second.disabled) {
- continue;
- }
-
- if (hwc_config.second.IsInterlaced()) {
- has_interlaced = true;
- } else {
- has_progressive = true;
- }
- }
-
- bool has_both = has_interlaced && has_progressive;
- if (!has_both) {
- continue;
- }
-
- bool group_contains_preferred_interlaced = false;
- if (group == preferred_config_group_id_ &&
- hwc_configs_[preferred_config_id_].IsInterlaced()) {
- group_contains_preferred_interlaced = true;
- }
-
- for (auto &hwc_config : hwc_configs_) {
- if (hwc_config.second.group_id != group || hwc_config.second.disabled) {
- continue;
- }
-
- bool disable = group_contains_preferred_interlaced
- ? !hwc_config.second.IsInterlaced()
- : hwc_config.second.IsInterlaced();
-
- if (disable) {
- ALOGI(
- "Group %i: Disabling display mode %s (This group should consist "
- "of %s modes)",
- group, hwc_config.second.mode.name().c_str(),
- group_contains_preferred_interlaced ? "interlaced"
- : "progressive");
-
- hwc_config.second.disabled = true;
- }
- }
- }
-
- /* Group should not contain 2 modes with FPS delta less than ~1HZ
- * otherwise android.graphics.cts.SetFrameRateTest CTS will fail
- */
- for (int m1 = 1; m1 < last_config_id; m1++) {
- for (int m2 = 1; m2 < last_config_id; m2++) {
- if (m1 != m2 &&
- hwc_configs_[m1].group_id == hwc_configs_[m2].group_id &&
- !hwc_configs_[m1].disabled && !hwc_configs_[m2].disabled &&
- fabsf(hwc_configs_[m1].mode.v_refresh() -
- hwc_configs_[m2].mode.v_refresh()) < 1.0) {
- ALOGI(
- "Group %i: Disabling display mode %s (Refresh rate value is "
- "too close to existing mode %s)",
- hwc_configs_[m2].group_id, hwc_configs_[m2].mode.name().c_str(),
- hwc_configs_[m1].mode.name().c_str());
-
- hwc_configs_[m2].disabled = true;
- }
- }
- }
+ configs_.Update(*connector_);
}
uint32_t idx = 0;
- for (auto &hwc_config : hwc_configs_) {
+ for (auto &hwc_config : configs_.hwc_configs) {
if (hwc_config.second.disabled) {
continue;
}
@@ -666,16 +532,16 @@
HWC2::Error HwcDisplay::SetActiveConfig(hwc2_config_t config) {
int conf = static_cast<int>(config);
- if (hwc_configs_.count(conf) == 0) {
+ if (configs_.hwc_configs.count(conf) == 0) {
ALOGE("Could not find active mode for %d", conf);
return HWC2::Error::BadConfig;
}
- auto &mode = hwc_configs_[conf].mode;
+ auto &mode = configs_.hwc_configs[conf].mode;
staged_mode = mode;
- active_config_id_ = conf;
+ configs_.active_config_id = conf;
// Setup the client layer's dimensions
hwc_rect_t display_frame = {.left = 0,
@@ -825,7 +691,8 @@
HWC2::Error HwcDisplay::GetDisplayVsyncPeriod(
hwc2_vsync_period_t *outVsyncPeriod /* ns */) {
- return GetDisplayAttribute(active_config_id_, HWC2_ATTRIBUTE_VSYNC_PERIOD,
+ return GetDisplayAttribute(configs_.active_config_id,
+ HWC2_ATTRIBUTE_VSYNC_PERIOD,
(int32_t *)(outVsyncPeriod));
}
diff --git a/hwc2_device/HwcDisplay.h b/hwc2_device/HwcDisplay.h
index f69ff18..6f46f5d 100644
--- a/hwc2_device/HwcDisplay.h
+++ b/hwc2_device/HwcDisplay.h
@@ -21,6 +21,7 @@
#include <optional>
+#include "HwcDisplayConfigs.h"
#include "compositor/DrmDisplayCompositor.h"
#include "drm/ResourceManager.h"
#include "drm/VSyncWorker.h"
@@ -138,22 +139,6 @@
uint32_t frames_flattened_ = 0;
};
- struct HwcDisplayConfig {
- int id{};
- int group_id{};
- DrmMode mode;
- bool disabled{};
-
- bool IsInterlaced() const {
- return (mode.flags() & DRM_MODE_FLAG_INTERLACE) != 0;
- }
- };
-
- std::map<int /*config_id*/, struct HwcDisplayConfig> hwc_configs_;
-
- int active_config_id_ = 0;
- int preferred_config_id_ = 0;
-
const Backend *backend() const;
void set_backend(std::unique_ptr<Backend> backend);
@@ -229,6 +214,8 @@
constexpr static size_t MATRIX_SIZE = 16;
+ HwcDisplayConfigs configs_;
+
DrmHwcTwo *hwc2_;
std::optional<DrmMode> staged_mode;
diff --git a/hwc2_device/HwcDisplayConfigs.cpp b/hwc2_device/HwcDisplayConfigs.cpp
new file mode 100644
index 0000000..d1a8d4c
--- /dev/null
+++ b/hwc2_device/HwcDisplayConfigs.cpp
@@ -0,0 +1,165 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "hwc-display-configs"
+
+#include "HwcDisplayConfigs.h"
+
+#include <cmath>
+
+#include "drm/DrmConnector.h"
+#include "utils/log.h"
+
+namespace android {
+
+// NOLINTNEXTLINE (readability-function-cognitive-complexity): Fixme
+HWC2::Error HwcDisplayConfigs::Update(DrmConnector &connector) {
+ int ret = connector.UpdateModes();
+ if (ret != 0) {
+ ALOGE("Failed to update display modes %d", ret);
+ return HWC2::Error::BadDisplay;
+ }
+
+ hwc_configs.clear();
+ preferred_config_id = 0;
+ int preferred_config_group_id = 0;
+
+ if (connector.modes().empty()) {
+ ALOGE("No modes reported by KMS");
+ return HWC2::Error::BadDisplay;
+ }
+
+ int last_config_id = 1;
+ int last_group_id = 1;
+
+ /* Group modes */
+ for (const auto &mode : connector.modes()) {
+ /* Find group for the new mode or create new group */
+ int group_found = 0;
+ for (auto &hwc_config : hwc_configs) {
+ if (mode.h_display() == hwc_config.second.mode.h_display() &&
+ mode.v_display() == hwc_config.second.mode.v_display()) {
+ group_found = hwc_config.second.group_id;
+ }
+ }
+ if (group_found == 0) {
+ group_found = last_group_id++;
+ }
+
+ bool disabled = false;
+ if ((mode.flags() & DRM_MODE_FLAG_3D_MASK) != 0) {
+ ALOGI("Disabling display mode %s (Modes with 3D flag aren't supported)",
+ mode.name().c_str());
+ disabled = true;
+ }
+
+ /* Add config */
+ hwc_configs[last_config_id] = {
+ .id = last_config_id,
+ .group_id = group_found,
+ .mode = mode,
+ .disabled = disabled,
+ };
+
+ /* Chwck if the mode is preferred */
+ if ((mode.type() & DRM_MODE_TYPE_PREFERRED) != 0 &&
+ preferred_config_id == 0) {
+ preferred_config_id = last_config_id;
+ preferred_config_group_id = group_found;
+ }
+
+ last_config_id++;
+ }
+
+ /* We must have preferred mode. Set first mode as preferred
+ * in case KMS haven't reported anything. */
+ if (preferred_config_id == 0) {
+ preferred_config_id = 1;
+ preferred_config_group_id = 1;
+ }
+
+ for (int group = 1; group < last_group_id; group++) {
+ bool has_interlaced = false;
+ bool has_progressive = false;
+ for (auto &hwc_config : hwc_configs) {
+ if (hwc_config.second.group_id != group || hwc_config.second.disabled) {
+ continue;
+ }
+
+ if (hwc_config.second.IsInterlaced()) {
+ has_interlaced = true;
+ } else {
+ has_progressive = true;
+ }
+ }
+
+ bool has_both = has_interlaced && has_progressive;
+ if (!has_both) {
+ continue;
+ }
+
+ bool group_contains_preferred_interlaced = false;
+ if (group == preferred_config_group_id &&
+ hwc_configs[preferred_config_id].IsInterlaced()) {
+ group_contains_preferred_interlaced = true;
+ }
+
+ for (auto &hwc_config : hwc_configs) {
+ if (hwc_config.second.group_id != group || hwc_config.second.disabled) {
+ continue;
+ }
+
+ bool disable = group_contains_preferred_interlaced
+ ? !hwc_config.second.IsInterlaced()
+ : hwc_config.second.IsInterlaced();
+
+ if (disable) {
+ ALOGI(
+ "Group %i: Disabling display mode %s (This group should consist "
+ "of %s modes)",
+ group, hwc_config.second.mode.name().c_str(),
+ group_contains_preferred_interlaced ? "interlaced" : "progressive");
+
+ hwc_config.second.disabled = true;
+ }
+ }
+ }
+
+ /* Group should not contain 2 modes with FPS delta less than ~1HZ
+ * otherwise android.graphics.cts.SetFrameRateTest CTS will fail
+ */
+ constexpr float kMinFpsDelta = 1.0; // FPS
+ for (int m1 = 1; m1 < last_config_id; m1++) {
+ for (int m2 = 1; m2 < last_config_id; m2++) {
+ if (m1 != m2 && hwc_configs[m1].group_id == hwc_configs[m2].group_id &&
+ !hwc_configs[m1].disabled && !hwc_configs[m2].disabled &&
+ fabsf(hwc_configs[m1].mode.v_refresh() -
+ hwc_configs[m2].mode.v_refresh()) < kMinFpsDelta) {
+ ALOGI(
+ "Group %i: Disabling display mode %s (Refresh rate value is "
+ "too close to existing mode %s)",
+ hwc_configs[m2].group_id, hwc_configs[m2].mode.name().c_str(),
+ hwc_configs[m1].mode.name().c_str());
+
+ hwc_configs[m2].disabled = true;
+ }
+ }
+ }
+
+ return HWC2::Error::None;
+}
+
+} // namespace android
diff --git a/hwc2_device/HwcDisplayConfigs.h b/hwc2_device/HwcDisplayConfigs.h
new file mode 100644
index 0000000..cb38625
--- /dev/null
+++ b/hwc2_device/HwcDisplayConfigs.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HWC2_DEVICE_HWC_DISPLAY_CONFIGS_H
+#define ANDROID_HWC2_DEVICE_HWC_DISPLAY_CONFIGS_H
+
+#include <hardware/hwcomposer2.h>
+
+#include <map>
+
+#include "drm/DrmMode.h"
+
+namespace android {
+
+class DrmConnector;
+
+struct HwcDisplayConfig {
+ int id{};
+ int group_id{};
+ DrmMode mode;
+ bool disabled{};
+
+ bool IsInterlaced() const {
+ return (mode.flags() & DRM_MODE_FLAG_INTERLACE) != 0;
+ }
+};
+
+struct HwcDisplayConfigs {
+ HWC2::Error Update(DrmConnector &conn);
+
+ std::map<int /*config_id*/, struct HwcDisplayConfig> hwc_configs;
+
+ int active_config_id = 0;
+ int preferred_config_id = 0;
+};
+
+} // namespace android
+
+#endif