summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLong Ling <longling@google.com>2022-05-16 09:58:40 -0700
committerLong Ling <longling@google.com>2022-06-09 09:15:26 -0700
commit7ae595591d74ef2bcb5240f3dafa570a0de32a1f (patch)
tree85f3992205dedb79c35235b899fbfe6603db4bed
parent10554b33eac4a1a6abaed1967a38e3e245e644b9 (diff)
downloadcommon-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.cpp23
-rw-r--r--libhwc2.1/libdevice/BrightnessController.h8
-rw-r--r--libhwc2.1/libdevice/ExynosDisplay.cpp12
-rw-r--r--libhwc2.1/libdevice/ExynosDisplay.h8
-rw-r--r--libhwc2.1/libdisplayinterface/ExynosDisplayDrmInterface.cpp5
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 {