diff options
author | Long Ling <longling@google.com> | 2022-05-16 09:58:40 -0700 |
---|---|---|
committer | Long Ling <longling@google.com> | 2022-06-09 09:15:26 -0700 |
commit | 7ae595591d74ef2bcb5240f3dafa570a0de32a1f (patch) | |
tree | 85f3992205dedb79c35235b899fbfe6603db4bed | |
parent | 10554b33eac4a1a6abaed1967a38e3e245e644b9 (diff) | |
download | common-7ae595591d74ef2bcb5240f3dafa570a0de32a1f.tar.gz |
libhwc2.1: sync ghbm/dbv and buffer for brightness jump
For mixed composition, if brightness mipi commands and frame are not
synchronized, there will be a dark or white flash when there is a
brightness jump. It happens when HDR become visible or gone and the
brightness animation is disabled.
Bug: 220962789
Change-Id: I2993562a2c69351f561f932305f88bfb4a2b3cf1
-rw-r--r-- | libhwc2.1/libdevice/BrightnessController.cpp | 23 | ||||
-rw-r--r-- | libhwc2.1/libdevice/BrightnessController.h | 8 | ||||
-rw-r--r-- | libhwc2.1/libdevice/ExynosDisplay.cpp | 12 | ||||
-rw-r--r-- | libhwc2.1/libdevice/ExynosDisplay.h | 8 | ||||
-rw-r--r-- | libhwc2.1/libdisplayinterface/ExynosDisplayDrmInterface.cpp | 5 |
5 files changed, 53 insertions, 3 deletions
diff --git a/libhwc2.1/libdevice/BrightnessController.cpp b/libhwc2.1/libdevice/BrightnessController.cpp index 40fb813..354de59 100644 --- a/libhwc2.1/libdevice/BrightnessController.cpp +++ b/libhwc2.1/libdevice/BrightnessController.cpp @@ -133,6 +133,7 @@ void BrightnessController::initBrightnessTable(const DrmDevice& drmDevice, // init to min before SF sets the brightness mDisplayWhitePointNits = cap->normal.nits.min; + mPrevDisplayWhitePointNits = mDisplayWhitePointNits; mBrightnessIntfSupported = true; drmModeFreePropertyBlob(blob); @@ -348,6 +349,8 @@ void BrightnessController::onClearDisplay() { mInstantHbmReq.reset(false); mBrightnessLevel.reset(0); + mDisplayWhitePointNits = 0; + mPrevDisplayWhitePointNits = 0; mGhbm.reset(HbmMode::OFF); mDimming.reset(false); mHbmDimming = false; @@ -362,6 +365,7 @@ void BrightnessController::onClearDisplay() { int BrightnessController::prepareFrameCommit(ExynosDisplay& display, const DrmConnector& connector, ExynosDisplayDrmInterface::DrmModeAtomicReq& drmReq, + const bool mixedComposition, bool& ghbmSync, bool& lhbmSync, bool& blSync) { int ret; @@ -372,6 +376,17 @@ int BrightnessController::prepareFrameCommit(ExynosDisplay& display, ATRACE_CALL(); std::lock_guard<std::recursive_mutex> lock(mBrightnessMutex); + bool sync = false; + if (mixedComposition && mPrevDisplayWhitePointNits > 0 && mDisplayWhitePointNits > 0) { + float diff = std::abs(mPrevDisplayWhitePointNits - mDisplayWhitePointNits); + float min = std::min(mPrevDisplayWhitePointNits, mDisplayWhitePointNits); + if (diff / min > kBrightnessSyncThreshold) { + sync = true; + ALOGD("%s: enable brightness sync for change from %f to %f", __func__, + mPrevDisplayWhitePointNits, mDisplayWhitePointNits); + } + } + if (mDimming.is_dirty()) { if ((ret = drmReq.atomicAddProperty(connector.id(), connector.dimming_on(), mDimming.get())) < 0) { @@ -437,9 +452,11 @@ int BrightnessController::prepareFrameCommit(ExynosDisplay& display, } else { mUncheckedBlRequest = true; mPendingBl = mBrightnessLevel.get(); + blSync = sync; } } mBrightnessLevel.clear_dirty(); + mPrevDisplayWhitePointNits = mDisplayWhitePointNits; } if (mGhbm.is_dirty() && mGhbmSupported) { @@ -455,7 +472,7 @@ int BrightnessController::prepareFrameCommit(ExynosDisplay& display, hbmEnum)) < 0) { ALOGE("%s: Fail to set hbm_mode property", __func__); } else { - ghbmSync = true; + ghbmSync = sync; } mGhbm.clear_dirty(); } @@ -705,6 +722,7 @@ int BrightnessController::applyBrightnessViaSysfs(uint32_t level) { { std::lock_guard<std::recursive_mutex> lock(mBrightnessMutex); mBrightnessLevel.reset(level); + mPrevDisplayWhitePointNits = mDisplayWhitePointNits; ALOGI("level=%d, DimmingOn=%d, Hbm=%d, LhbmOn=%d", level, mDimming.get(), mGhbm.get(), mLhbm.get()); } @@ -765,6 +783,7 @@ void BrightnessController::dump(String8& result) { mPendingGhbmStatus.load()); result.appendFormat("\tdimming usage %d, hbm dimming %d, time us %d\n", mBrightnessDimmingUsage, mHbmDimming, mHbmDimmingTimeUs); - result.appendFormat("\twhite point nits %f\n", mDisplayWhitePointNits); + result.appendFormat("\twhite point nits current %f, previous %f\n", mDisplayWhitePointNits, + mPrevDisplayWhitePointNits); result.appendFormat("\n"); } diff --git a/libhwc2.1/libdevice/BrightnessController.h b/libhwc2.1/libdevice/BrightnessController.h index 3a7fa85..254a576 100644 --- a/libhwc2.1/libdevice/BrightnessController.h +++ b/libhwc2.1/libdevice/BrightnessController.h @@ -97,6 +97,7 @@ public: int prepareFrameCommit(ExynosDisplay& display, const DrmConnector& connector, ExynosDisplayDrmInterface::DrmModeAtomicReq& drmReq, + const bool mixedComposition, bool& ghbmSync, bool& lhbmSync, bool& blSync); bool isGhbmSupported() { return mGhbmSupported; } @@ -177,6 +178,12 @@ public: }; private: + // sync brightness change for mixed composition when there is more than 50% luminance change. + // The percentage is calculated as: + // (big_lumi - small_lumi) / small_lumi + // For mixed composition, if remove brightness animations, the minimum brightness jump is + // between nbm peak and hbm peak. 50% will cover known panels + static constexpr float kBrightnessSyncThreshold = 0.5f; // Worst case for panel with brightness range 2 nits to 1000 nits. static constexpr float kGhbmMinDimRatio = 0.002; static constexpr int32_t kHbmDimmingTimeUs = 5000000; @@ -254,6 +261,7 @@ private: // Note IRC or dimming is not in consideration for now. float mDisplayWhitePointNits = 0; + float mPrevDisplayWhitePointNits = 0; std::function<void(void)> mUpdateDcLhbm; }; diff --git a/libhwc2.1/libdevice/ExynosDisplay.cpp b/libhwc2.1/libdevice/ExynosDisplay.cpp index 7d01650..d27a8a6 100644 --- a/libhwc2.1/libdevice/ExynosDisplay.cpp +++ b/libhwc2.1/libdevice/ExynosDisplay.cpp @@ -3369,6 +3369,7 @@ int32_t ExynosDisplay::presentDisplay(int32_t* outRetireFence) { ATRACE_CALL(); gettimeofday(&updateTimeInfo.lastPresentTime, NULL); + const bool mixedComposition = isMixedComposition(); // store this once here for the whole frame so it's consistent mUsePowerHints = usePowerHintSession(); if (mUsePowerHints) { @@ -3693,6 +3694,8 @@ int32_t ExynosDisplay::presentDisplay(int32_t* outRetireFence) { mPowerHalHint.signalActualWorkDuration(duration + mValidationDuration.value_or(0)); } + mPriorFrameMixedComposition = mixedComposition; + return ret; err: printDebugInfos(errString); @@ -6016,3 +6019,12 @@ int32_t ExynosDisplay::setDebugRCDLayerEnabled(bool enable) { int32_t ExynosDisplay::getDisplayIdleTimerSupport(bool &outSupport) { return mDisplayInterface->getDisplayIdleTimerSupport(outSupport); } + +bool ExynosDisplay::isMixedComposition() { + for (size_t i = 0; i < mLayers.size(); i++) { + if (mLayers[i]->mBrightness < 1.0) { + return true; + } + } + return false; +} diff --git a/libhwc2.1/libdevice/ExynosDisplay.h b/libhwc2.1/libdevice/ExynosDisplay.h index d784aa4..b75cc98 100644 --- a/libhwc2.1/libdevice/ExynosDisplay.h +++ b/libhwc2.1/libdevice/ExynosDisplay.h @@ -1250,6 +1250,10 @@ class ExynosDisplay { (mVsyncPeriod == mMinDisplayVsyncPeriod)); } + // check if there are any dimmed layers + bool isMixedComposition(); + bool isPriorFrameMixedCompostion() { return mPriorFrameMixedComposition; } + private: bool skipStaticLayerChanged(ExynosCompositionInfo& compositionInfo); @@ -1267,6 +1271,10 @@ class ExynosDisplay { // vsync period of peak refresh rate uint32_t mMinDisplayVsyncPeriod; + // track if the last frame is a mixed composition, to detect mixed + // composition to non-mixed composition transition. + bool mPriorFrameMixedComposition; + /* Display hint to notify power hal */ class PowerHalHintWorker : public Worker { public: diff --git a/libhwc2.1/libdisplayinterface/ExynosDisplayDrmInterface.cpp b/libhwc2.1/libdisplayinterface/ExynosDisplayDrmInterface.cpp index d03b5b7..51dddd7 100644 --- a/libhwc2.1/libdisplayinterface/ExynosDisplayDrmInterface.cpp +++ b/libhwc2.1/libdisplayinterface/ExynosDisplayDrmInterface.cpp @@ -1779,8 +1779,11 @@ int32_t ExynosDisplayDrmInterface::deliverWinConfigData() if (mExynosDisplay->mBrightnessController) { bool ghbmSync, lhbmSync, blSync; + bool mixedComposition = mExynosDisplay->isMixedComposition() + || mExynosDisplay->isPriorFrameMixedCompostion(); ret = mExynosDisplay->mBrightnessController->prepareFrameCommit(*mExynosDisplay, - *mDrmConnector, drmReq, ghbmSync, lhbmSync, blSync); + *mDrmConnector, drmReq, mixedComposition, + ghbmSync, lhbmSync, blSync); if (ret < 0) { HWC_LOGE(mExynosDisplay, "%s: Fail to config brightness", __func__); } else { |