diff options
author | Shiyong Li <shiyongli@google.com> | 2023-04-26 00:18:37 +0000 |
---|---|---|
committer | Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com> | 2023-04-26 00:18:37 +0000 |
commit | 0419717936f4c9a889c6c54b53de6531de2f1a9e (patch) | |
tree | d498590e90af5f42ae961147c4366400fd2cdb2a | |
parent | 3263620f7877fe3515d7a49d6443f1b2768c7794 (diff) | |
parent | 88780476976e4194bbaa581a5713b69d8d963a1e (diff) | |
download | common-0419717936f4c9a889c6c54b53de6531de2f1a9e.tar.gz |
libhwc2.1: actively set lhbm desired refresh rate during lhbm period am: 8878047697
Original change: https://googleplex-android-review.googlesource.com/c/platform/hardware/google/graphics/common/+/22540744
Change-Id: I028089ab9215114169ff440bbc22f154e4a814d7
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
-rw-r--r-- | libhwc2.1/ExynosHWCDebug.h | 7 | ||||
-rw-r--r-- | libhwc2.1/libdevice/ExynosDisplay.cpp | 24 | ||||
-rw-r--r-- | libhwc2.1/libdevice/ExynosDisplay.h | 11 | ||||
-rw-r--r-- | libhwc2.1/libdisplayinterface/ExynosDisplayDrmInterface.cpp | 29 | ||||
-rw-r--r-- | libhwc2.1/libmaindisplay/ExynosPrimaryDisplay.cpp | 126 | ||||
-rw-r--r-- | libhwc2.1/libmaindisplay/ExynosPrimaryDisplay.h | 10 |
6 files changed, 151 insertions, 56 deletions
diff --git a/libhwc2.1/ExynosHWCDebug.h b/libhwc2.1/ExynosHWCDebug.h index 25178d1..37d96fd 100644 --- a/libhwc2.1/ExynosHWCDebug.h +++ b/libhwc2.1/ExynosHWCDebug.h @@ -114,6 +114,13 @@ int32_t saveFenceTrace(ExynosDisplay *display); saveErrorLog(saveString, this); \ } +#define DISPLAY_DRM_LOGI(msg, ...) \ + ALOGI("[%s] " msg, mExynosDisplay->mDisplayName.string(), ##__VA_ARGS__) +#define DISPLAY_DRM_LOGW(msg, ...) \ + ALOGW("[%s] " msg, mExynosDisplay->mDisplayName.string(), ##__VA_ARGS__) +#define DISPLAY_DRM_LOGE(msg, ...) \ + ALOGE("[%s] " msg, mExynosDisplay->mDisplayName.string(), ##__VA_ARGS__) + #define MPP_LOGV(msg, ...) ALOGV("[%s][%d] " msg, mName.string(), mLogicalIndex, ##__VA_ARGS__) #define MPP_LOGI(msg, ...) ALOGI("[%s][%d] " msg, mName.string(), mLogicalIndex, ##__VA_ARGS__) #define MPP_LOGW(msg, ...) ALOGW("[%s][%d] " msg, mName.string(), mLogicalIndex, ##__VA_ARGS__) diff --git a/libhwc2.1/libdevice/ExynosDisplay.cpp b/libhwc2.1/libdevice/ExynosDisplay.cpp index 7d23696..a29927d 100644 --- a/libhwc2.1/libdevice/ExynosDisplay.cpp +++ b/libhwc2.1/libdevice/ExynosDisplay.cpp @@ -4086,6 +4086,12 @@ int32_t ExynosDisplay::setActiveConfigWithConstraints(hwc2_config_t config, if (isBadConfig(config)) return HWC2_ERROR_BAD_CONFIG; + if (!isConfigSettingEnabled()) { + mPendingConfig = config; + DISPLAY_LOGI("%s: config setting disabled, set pending config=%d", __func__, config); + return HWC2_ERROR_NONE; + } + if (mDisplayConfigs[mActiveConfig].groupId != mDisplayConfigs[config].groupId) { if (vsyncPeriodChangeConstraints->seamlessRequired) { DISPLAY_LOGD(eDebugDisplayConfig, "Case : Seamless is not allowed"); @@ -6285,6 +6291,11 @@ void ExynosDisplay::updateRefreshRateIndicator() { mRefreshRateIndicatorHandler->handleSysfsEvent(); } +uint32_t ExynosDisplay::getPeakRefreshRate() { + float opRate = mOperationRateManager ? mOperationRateManager->getOperationRate() : 0; + return static_cast<uint32_t>(std::round(opRate ?: mPeakRefreshRate)); +} + VsyncPeriodNanos ExynosDisplay::getVsyncPeriod(const int32_t config) { const auto &it = mDisplayConfigs.find(config); if (it == mDisplayConfigs.end()) return 0; @@ -6297,3 +6308,16 @@ uint32_t ExynosDisplay::getRefreshRate(const int32_t config) { constexpr float nsecsPerSec = std::chrono::nanoseconds(1s).count(); return round(nsecsPerSec / period * 0.1f) * 10; } + +uint32_t ExynosDisplay::getConfigId(const int32_t refreshRate, const int32_t width, + const int32_t height) { + for (auto entry : mDisplayConfigs) { + auto config = entry.first; + auto displayCfg = entry.second; + if (getRefreshRate(config) == refreshRate && displayCfg.width == width && + displayCfg.height == height) { + return config; + } + } + return UINT_MAX; +} diff --git a/libhwc2.1/libdevice/ExynosDisplay.h b/libhwc2.1/libdevice/ExynosDisplay.h index 41c6a93..8a12393 100644 --- a/libhwc2.1/libdevice/ExynosDisplay.h +++ b/libhwc2.1/libdevice/ExynosDisplay.h @@ -562,6 +562,8 @@ class ExynosDisplay { hwc2_config_t mDesiredConfig; hwc2_config_t mActiveConfig = UINT_MAX; + hwc2_config_t mPendingConfig = UINT_MAX; + int64_t mLastVsyncTimestamp = 0; void initDisplay(); @@ -1282,16 +1284,17 @@ class ExynosDisplay { virtual void updateAppliedActiveConfig(const hwc2_config_t /*newConfig*/, const int64_t /*ts*/) {} + virtual bool isConfigSettingEnabled() { return true; } + virtual void enableConfigSetting(bool /*en*/) {} + // is the hint session both enabled and supported bool usePowerHintSession(); void setPeakRefreshRate(float rr) { mPeakRefreshRate = rr; } - uint32_t getPeakRefreshRate() { - float opRate = mOperationRateManager ? mOperationRateManager->getOperationRate() : 0; - return static_cast<uint32_t>(std::round(opRate ?: mPeakRefreshRate)); - } + uint32_t getPeakRefreshRate(); VsyncPeriodNanos getVsyncPeriod(const int32_t config); uint32_t getRefreshRate(const int32_t config); + uint32_t getConfigId(const int32_t refreshRate, const int32_t width, const int32_t height); // check if there are any dimmed layers bool isMixedComposition(); diff --git a/libhwc2.1/libdisplayinterface/ExynosDisplayDrmInterface.cpp b/libhwc2.1/libdisplayinterface/ExynosDisplayDrmInterface.cpp index 6a2be7d..375153b 100644 --- a/libhwc2.1/libdisplayinterface/ExynosDisplayDrmInterface.cpp +++ b/libhwc2.1/libdisplayinterface/ExynosDisplayDrmInterface.cpp @@ -747,6 +747,30 @@ void ExynosDisplayDrmInterface::Callback( if (!mExynosDisplay->mPlugState || !mVsyncCallback.getVSyncEnabled()) { return; } + + // Refresh rate during enabling LHBM might be different from the one SF expects. + // HWC just reports the SF expected Vsync to make UI smoothness consistent even if + // HWC runs at different refresh rate temporarily. + if (!mExynosDisplay->isConfigSettingEnabled()) { + int64_t pendingPeriodNs = + mExynosDisplay->getVsyncPeriod(mExynosDisplay->mPendingConfig); + int64_t activePeriodNs = mExynosDisplay->getVsyncPeriod(mExynosDisplay->mActiveConfig); + if (pendingPeriodNs && mExynosDisplay->mLastVsyncTimestamp) { + if (activePeriodNs > pendingPeriodNs) { + DISPLAY_DRM_LOGW("wrong vsync period: %" PRId64 "us (active), %" PRId64 + "us (pending)", + activePeriodNs / 1000, pendingPeriodNs / 1000); + } else if (activePeriodNs != pendingPeriodNs) { + int64_t deltaNs = timestamp - mExynosDisplay->mLastVsyncTimestamp; + if (deltaNs < (pendingPeriodNs - ms2ns(2))) { + DISPLAY_DRM_LOGI("skip mismatching Vsync callback, delta=%" PRId64 "us", + deltaNs / 1000); + return; + } + } + } + } + mExynosDisplay->mLastVsyncTimestamp = timestamp; } ExynosDevice *exynosDevice = mExynosDisplay->mDevice; @@ -1152,6 +1176,7 @@ int32_t ExynosDisplayDrmInterface::setActiveConfigWithConstraints( if (mExynosDisplay->mOperationRateManager) { mExynosDisplay->mOperationRateManager->onConfig(config); } + DISPLAY_DRM_LOGI("%s: config(%d)", __func__, config); } else { ALOGD("%s:: same desired mode %d", __func__, config); } @@ -1243,9 +1268,9 @@ int32_t ExynosDisplayDrmInterface::setActiveConfig(hwc2_config_t config) { mExynosDisplay->updateAppliedActiveConfig(config, systemTime(SYSTEM_TIME_MONOTONIC)); if (!setActiveDrmMode(*mode)) { - ALOGI("%s:: %s config(%d)", __func__, mExynosDisplay->mDisplayName.string(), config); + DISPLAY_DRM_LOGI("%s: config(%d)", __func__, config); } else { - ALOGE("%s:: %s config(%d) failed", __func__, mExynosDisplay->mDisplayName.string(), config); + DISPLAY_DRM_LOGE("%s: config(%d) failed", __func__, config); } return 0; diff --git a/libhwc2.1/libmaindisplay/ExynosPrimaryDisplay.cpp b/libhwc2.1/libmaindisplay/ExynosPrimaryDisplay.cpp index a6b5582..379fbdd 100644 --- a/libhwc2.1/libmaindisplay/ExynosPrimaryDisplay.cpp +++ b/libhwc2.1/libmaindisplay/ExynosPrimaryDisplay.cpp @@ -172,7 +172,7 @@ int ExynosPrimaryDisplay::getDDIScalerMode(int width, int height) { int32_t ExynosPrimaryDisplay::doDisplayConfigInternal(hwc2_config_t config) { if (!mPowerModeState.has_value() || (*mPowerModeState != HWC2_POWER_MODE_ON) || !isConfigSettingEnabled()) { - mPendActiveConfig = config; + mPendingConfig = config; mConfigRequestState = hwc_request_state_t::SET_CONFIG_STATE_DONE; DISPLAY_LOGI("%s:: Pending desired Config: %d", __func__, config); return NO_ERROR; @@ -181,8 +181,8 @@ int32_t ExynosPrimaryDisplay::doDisplayConfigInternal(hwc2_config_t config) { } int32_t ExynosPrimaryDisplay::getActiveConfigInternal(hwc2_config_t *outConfig) { - if (outConfig && mPendActiveConfig != UINT_MAX) { - *outConfig = mPendActiveConfig; + if (outConfig && mPendingConfig != UINT_MAX) { + *outConfig = mPendingConfig; return HWC2_ERROR_NONE; } return ExynosDisplay::getActiveConfigInternal(outConfig); @@ -198,18 +198,19 @@ int32_t ExynosPrimaryDisplay::setActiveConfigInternal(hwc2_config_t config, bool } if (!mPowerModeState.has_value() || (*mPowerModeState != HWC2_POWER_MODE_ON) || !isConfigSettingEnabled()) { - mPendActiveConfig = config; + mPendingConfig = config; return HWC2_ERROR_NONE; } return ExynosDisplay::setActiveConfigInternal(config, force); } int32_t ExynosPrimaryDisplay::applyPendingConfig() { - hwc2_config_t config; + if (!isConfigSettingEnabled()) return HWC2_ERROR_NONE; - if (mPendActiveConfig != UINT_MAX) { - config = mPendActiveConfig; - mPendActiveConfig = UINT_MAX; + hwc2_config_t config; + if (mPendingConfig != UINT_MAX) { + config = mPendingConfig; + mPendingConfig = UINT_MAX; } else { getActiveConfigInternal(&config); } @@ -530,7 +531,7 @@ bool ExynosPrimaryDisplay::isLhbmSupported() { bool ExynosPrimaryDisplay::isConfigSettingEnabled() { int64_t msSinceDisabled = (systemTime(SYSTEM_TIME_MONOTONIC) - mConfigSettingDisabledTimestamp) / 1000000; - return !mConfigSettingDisabled || msSinceDisabled > kLhbmMaxEnablingDurationMs; + return !mConfigSettingDisabled || msSinceDisabled > kConfigDisablingMaxDurationMs; } void ExynosPrimaryDisplay::enableConfigSetting(bool en) { @@ -541,13 +542,41 @@ void ExynosPrimaryDisplay::enableConfigSetting(bool en) { } mConfigSettingDisabled = false; - if (mPendActiveConfig != UINT_MAX) { - hwc2_config_t config = mPendActiveConfig; - if (applyPendingConfig() != HWC2_ERROR_NONE) { - DISPLAY_LOGW("%s: failed to set mPendActiveConfig=%d", __func__, config); +} + +void ExynosPrimaryDisplay::setLhbmDisplayConfig(uint32_t refreshRate) { + auto config = getConfigId(refreshRate, mDisplayConfigs[mActiveConfig].width, + mDisplayConfigs[mActiveConfig].height); + + if (config == UINT_MAX) { + DISPLAY_LOGE("%s: failed to get config for rate=%d", __func__, refreshRate); + return; + } + if (mPendingConfig == UINT_MAX) mPendingConfig = mActiveConfig; + + if (ExynosDisplay::setActiveConfigInternal(config, true) == HWC2_ERROR_NONE) { + DISPLAY_LOGI("%s: succeeded to set config=%d rate=%d", __func__, config, refreshRate); + } else { + DISPLAY_LOGW("%s: failed to set config=%d rate=%d", __func__, config, refreshRate); + } +} + +void ExynosPrimaryDisplay::restoreLhbmDisplayConfig() { + if (mPendingConfig == UINT_MAX) return; + + hwc2_config_t pendingCfg = mPendingConfig; + if (mPendingConfig != mActiveConfig) { + if (applyPendingConfig() == HWC2_ERROR_NONE) { + DISPLAY_LOGI("%s: succeeded to set config=%d rate=%d", __func__, pendingCfg, + getRefreshRate(pendingCfg)); } else { - DISPLAY_LOGI("%s: succeed to set mPendActiveConfig=%d", __func__, config); + DISPLAY_LOGE("%s: failed to set config=%d rate=%d", __func__, pendingCfg, + getRefreshRate(pendingCfg)); } + } else { + mPendingConfig = UINT_MAX; + DISPLAY_LOGI("%s: keep config=%d rate=%d", __func__, pendingCfg, + getRefreshRate(pendingCfg)); } } @@ -594,19 +623,24 @@ int32_t ExynosPrimaryDisplay::setLhbmState(bool enabled) { std::vector<std::string> checkingValue; if (!enabled) { ATRACE_NAME("disable_lhbm"); - checkingValue = { - std::to_string(static_cast<int>(BrightnessController::LhbmMode::DISABLED))}; + { + ATRACE_NAME("apply_pending_rate"); + Mutex::Autolock lock(mDisplayMutex); + enableConfigSetting(true); + restoreLhbmDisplayConfig(); + } requestLhbm(false); - ret = mBrightnessController->checkSysfsStatus(lhbmSysfs, checkingValue, - ms2ns(kSysfsCheckTimeoutMs)); - if (ret != OK) { - DISPLAY_LOGW("%s: failed to send lhbm-off cmd", __func__); - } else if (mDisplayInterface->waitVBlank()) { - DISPLAY_LOGE("%s: failed to wait vblank of making lhbm-off cmd effective", __func__); + { + ATRACE_NAME("wait_for_lhbm_off_cmd"); + checkingValue = { + std::to_string(static_cast<int>(BrightnessController::LhbmMode::DISABLED))}; + ret = mBrightnessController->checkSysfsStatus(lhbmSysfs, checkingValue, + ms2ns(kSysfsCheckTimeoutMs)); + if (ret != OK) { + DISPLAY_LOGW("%s: failed to send lhbm-off cmd", __func__); + } } setLHBMRefreshRateThrottle(0); - Mutex::Autolock lock(mDisplayMutex); - enableConfigSetting(true); mLhbmOn = false; return NO_ERROR; } @@ -617,21 +651,23 @@ int32_t ExynosPrimaryDisplay::setLhbmState(bool enabled) { uint32_t peakRate; auto rrSysfs = mBrightnessController->GetPanelRefreshRateSysfile(); lhbmWaitForRrNanos = systemTime(SYSTEM_TIME_MONOTONIC); - hwc2_config_t curConfig; { Mutex::Autolock lock(mDisplayMutex); peakRate = getPeakRefreshRate(); - getActiveConfigInternal(&curConfig); - if (curConfig == peakRate) { - enableConfigSetting(false); + if (peakRate < 60) { + DISPLAY_LOGE("%s: invalid peak rate=%d", __func__, peakRate); + return -EINVAL; } + if (getRefreshRate(mActiveConfig) != peakRate) { + ATRACE_NAME("request_peak_rate"); + setLhbmDisplayConfig(peakRate); + } + enableConfigSetting(false); } if (mBrightnessController->fileExists(rrSysfs)) { - ATRACE_NAME("wait_for_peak_rate_sent"); - if (peakRate) { - ret = mBrightnessController->checkSysfsStatus(rrSysfs, {std::to_string(peakRate)}, - ms2ns(kLhbmWaitForPeakRefreshRateMs)); - } + ATRACE_NAME("wait_for_peak_rate_cmd"); + ret = mBrightnessController->checkSysfsStatus(rrSysfs, {std::to_string(peakRate)}, + ms2ns(kLhbmWaitForPeakRefreshRateMs)); if (ret != OK) { DISPLAY_LOGW("%s: failed to poll peak refresh rate=%d, ret=%d", __func__, peakRate, ret); @@ -650,24 +686,21 @@ int32_t ExynosPrimaryDisplay::setLhbmState(bool enabled) { } } } - { - Mutex::Autolock lock(mDisplayMutex); - if (isConfigSettingEnabled()) { - enableConfigSetting(false); - } - } setLHBMRefreshRateThrottle(kLhbmRefreshRateThrottleMs); checkingValue = {std::to_string(static_cast<int>(BrightnessController::LhbmMode::ENABLING)), std::to_string(static_cast<int>(BrightnessController::LhbmMode::ENABLED))}; lhbmEnablingNanos = systemTime(SYSTEM_TIME_MONOTONIC); - requestLhbm(enabled); - ret = mBrightnessController->checkSysfsStatus(lhbmSysfs, checkingValue, - ms2ns(kSysfsCheckTimeoutMs)); - if (ret != OK) { - DISPLAY_LOGE("%s: failed to enable lhbm", __func__); - setLHBMRefreshRateThrottle(0); - goto enable_err; + requestLhbm(true); + { + ATRACE_NAME("wait_for_lhbm_on_cmd"); + ret = mBrightnessController->checkSysfsStatus(lhbmSysfs, checkingValue, + ms2ns(kSysfsCheckTimeoutMs)); + if (ret != OK) { + DISPLAY_LOGE("%s: failed to enable lhbm", __func__); + setLHBMRefreshRateThrottle(0); + goto enable_err; + } } lhbmEnablingDoneNanos = systemTime(SYSTEM_TIME_MONOTONIC); @@ -710,6 +743,7 @@ int32_t ExynosPrimaryDisplay::setLhbmState(bool enabled) { enable_err: Mutex::Autolock lock(mDisplayMutex); enableConfigSetting(true); + restoreLhbmDisplayConfig(); return ret; } diff --git a/libhwc2.1/libmaindisplay/ExynosPrimaryDisplay.h b/libhwc2.1/libmaindisplay/ExynosPrimaryDisplay.h index e111907..796f6ef 100644 --- a/libhwc2.1/libmaindisplay/ExynosPrimaryDisplay.h +++ b/libhwc2.1/libmaindisplay/ExynosPrimaryDisplay.h @@ -64,6 +64,8 @@ class ExynosPrimaryDisplay : public ExynosDisplay { virtual int32_t setBootDisplayConfig(int32_t config) override; virtual int32_t clearBootDisplayConfig() override; virtual int32_t getPreferredDisplayConfigInternal(int32_t* outConfig) override; + virtual bool isConfigSettingEnabled() override; + virtual void enableConfigSetting(bool en) override; protected: /* setPowerMode(int32_t mode) @@ -87,7 +89,6 @@ class ExynosPrimaryDisplay : public ExynosDisplay { // Prepare multi resolution ResolutionInfo mResolutionInfo; std::string getPanelSysfsPath(const displaycolor::DisplayType& type); - bool isConfigSettingEnabled(); uint32_t mRcdId = -1; @@ -99,7 +100,6 @@ class ExynosPrimaryDisplay : public ExynosDisplay { bool checkLhbmMode(bool status, nsecs_t timoutNs); void setLHBMRefreshRateThrottle(const uint32_t delayMs); - hwc2_config_t mPendActiveConfig = UINT_MAX; bool mFirstPowerOn = true; bool mNotifyPowerOn = false; std::mutex mPowerModeMutex; @@ -116,6 +116,8 @@ class ExynosPrimaryDisplay : public ExynosDisplay { int32_t setDisplayIdleDelayNanos(int32_t delayNanos, const DispIdleTimerRequester requester); void initDisplayHandleIdleExit(); + void setLhbmDisplayConfig(uint32_t refreshRate); + void restoreLhbmDisplayConfig(); // LHBM FILE* mLhbmFd; @@ -126,9 +128,9 @@ class ExynosPrimaryDisplay : public ExynosDisplay { // timeout value of waiting for peak refresh rate static constexpr uint32_t kLhbmWaitForPeakRefreshRateMs = 100U; static constexpr uint32_t kLhbmRefreshRateThrottleMs = 1000U; - static constexpr uint32_t kLhbmMaxEnablingDurationMs = 1000U; + static constexpr uint32_t kConfigDisablingMaxDurationMs = 1000U; static constexpr uint32_t kSysfsCheckTimeoutMs = 500U; - void enableConfigSetting(bool en); + int32_t getTimestampDeltaMs(int64_t endNs, int64_t beginNs) { if (endNs == 0) endNs = systemTime(SYSTEM_TIME_MONOTONIC); return (endNs - beginNs) / 1000000; |