summaryrefslogtreecommitdiff
path: root/libhwc2.1/libdevice/ExynosDisplay.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libhwc2.1/libdevice/ExynosDisplay.cpp')
-rw-r--r--libhwc2.1/libdevice/ExynosDisplay.cpp329
1 files changed, 233 insertions, 96 deletions
diff --git a/libhwc2.1/libdevice/ExynosDisplay.cpp b/libhwc2.1/libdevice/ExynosDisplay.cpp
index 3688207..2f77bb9 100644
--- a/libhwc2.1/libdevice/ExynosDisplay.cpp
+++ b/libhwc2.1/libdevice/ExynosDisplay.cpp
@@ -63,7 +63,7 @@ constexpr float nsecsPerSec = std::chrono::nanoseconds(1s).count();
constexpr int64_t nsecsIdleHintTimeout = std::chrono::nanoseconds(100ms).count();
ExynosDisplay::PowerHalHintWorker::PowerHalHintWorker(uint32_t displayId,
- const String8 &displayTraceName)
+ const String8& displayTraceName)
: Worker("DisplayHints", HAL_PRIORITY_URGENT_DISPLAY),
mNeedUpdateRefreshRateHint(false),
mLastRefreshRateHint(0),
@@ -74,7 +74,7 @@ ExynosDisplay::PowerHalHintWorker::PowerHalHintWorker(uint32_t displayId,
mIdleHintIsSupported(false),
mDisplayTraceName(displayTraceName),
mPowerModeState(HWC2_POWER_MODE_OFF),
- mVsyncPeriod(16666666),
+ mRefreshRate(kDefaultRefreshRateFrequency),
mConnectRetryCount(0),
mDeathRecipient(AIBinder_DeathRecipient_new(BinderDiedCallback)),
mPowerHalExtAidl(nullptr),
@@ -196,7 +196,7 @@ int32_t ExynosDisplay::PowerHalHintWorker::sendPowerHalExtHint(const std::string
return NO_ERROR;
}
-int32_t ExynosDisplay::PowerHalHintWorker::checkRefreshRateHintSupport(int refreshRate) {
+int32_t ExynosDisplay::PowerHalHintWorker::checkRefreshRateHintSupport(const int32_t refreshRate) {
int32_t ret = NO_ERROR;
if (!isPowerHalExist()) {
@@ -223,7 +223,8 @@ int32_t ExynosDisplay::PowerHalHintWorker::checkRefreshRateHintSupport(int refre
return ret;
}
-int32_t ExynosDisplay::PowerHalHintWorker::sendRefreshRateHint(int refreshRate, bool enabled) {
+int32_t ExynosDisplay::PowerHalHintWorker::sendRefreshRateHint(const int32_t refreshRate,
+ bool enabled) {
std::string hintStr = mRefreshRateHintPrefixStr + std::to_string(refreshRate) + "FPS";
int32_t ret = sendPowerHalExtHint(hintStr, enabled);
if (ret == -ENOTCONN) {
@@ -234,11 +235,10 @@ int32_t ExynosDisplay::PowerHalHintWorker::sendRefreshRateHint(int refreshRate,
}
int32_t ExynosDisplay::PowerHalHintWorker::updateRefreshRateHintInternal(
- hwc2_power_mode_t powerMode, uint32_t vsyncPeriod) {
+ const hwc2_power_mode_t powerMode, const int32_t refreshRate) {
int32_t ret = NO_ERROR;
/* TODO: add refresh rate buckets, tracked in b/181100731 */
- int refreshRate = round(nsecsPerSec / vsyncPeriod * 0.1f) * 10;
// skip sending unnecessary hint if it's still the same.
if (mLastRefreshRateHint == refreshRate && powerMode == HWC2_POWER_MODE_ON) {
return NO_ERROR;
@@ -340,7 +340,8 @@ int32_t ExynosDisplay::PowerHalHintWorker::checkPowerHintSessionSupport() {
return out;
}
-int32_t ExynosDisplay::PowerHalHintWorker::updateIdleHint(int64_t deadlineTime, bool forceUpdate) {
+int32_t ExynosDisplay::PowerHalHintWorker::updateIdleHint(const int64_t deadlineTime,
+ const bool forceUpdate) {
int32_t ret = checkIdleHintSupport();
if (ret != NO_ERROR) {
return ret;
@@ -461,7 +462,7 @@ void ExynosDisplay::PowerHalHintWorker::signalActualWorkDuration(nsecs_t actualD
}
mActualWorkDuration = reportedDurationNs;
- WorkDuration duration = {.durationNanos = reportedDurationNs, .timeStampNanos = systemTime()};
+ WorkDuration duration = {.timeStampNanos = systemTime(), .durationNanos = reportedDurationNs};
if (sTraceHintSessionData) {
DISPLAY_ATRACE_INT64("Measured duration", actualDurationNanos);
@@ -509,17 +510,17 @@ void ExynosDisplay::PowerHalHintWorker::signalTargetWorkDuration(nsecs_t targetD
}
void ExynosDisplay::PowerHalHintWorker::signalRefreshRate(hwc2_power_mode_t powerMode,
- uint32_t vsyncPeriod) {
+ int32_t refreshRate) {
Lock();
mPowerModeState = powerMode;
- mVsyncPeriod = vsyncPeriod;
+ mRefreshRate = refreshRate;
mNeedUpdateRefreshRateHint = true;
Unlock();
Signal();
}
-void ExynosDisplay::PowerHalHintWorker::signalIdle() {
+void ExynosDisplay::PowerHalHintWorker::signalNonIdle() {
ATRACE_CALL();
Lock();
@@ -579,7 +580,6 @@ void ExynosDisplay::PowerHalHintWorker::Routine() {
bool needUpdateRefreshRateHint = mNeedUpdateRefreshRateHint;
int64_t deadlineTime = mIdleHintDeadlineTime;
hwc2_power_mode_t powerMode = mPowerModeState;
- uint32_t vsyncPeriod = mVsyncPeriod;
/*
* Clear the flags here instead of clearing them after calling the hint
@@ -602,7 +602,7 @@ void ExynosDisplay::PowerHalHintWorker::Routine() {
updateIdleHint(deadlineTime, forceUpdateIdleHint);
if (needUpdateRefreshRateHint) {
- int32_t rc = updateRefreshRateHintInternal(powerMode, vsyncPeriod);
+ int32_t rc = updateRefreshRateHintInternal(powerMode, mRefreshRate);
if (rc != NO_ERROR && rc != -EOPNOTSUPP) {
Lock();
if (mPowerModeState == HWC2_POWER_MODE_ON) {
@@ -980,8 +980,8 @@ String8 ExynosCompositionInfo::getTypeStr()
}
}
-ExynosDisplay::ExynosDisplay(uint32_t type, uint32_t index, ExynosDevice *device,
- const std::string &displayName)
+ExynosDisplay::ExynosDisplay(uint32_t type, uint32_t index, ExynosDevice* device,
+ const std::string& displayName)
: mDisplayId(getDisplayId(type, index)),
mType(type),
mIndex(index),
@@ -990,8 +990,9 @@ ExynosDisplay::ExynosDisplay(uint32_t type, uint32_t index, ExynosDevice *device
mYres(2960),
mXdpi(25400),
mYdpi(25400),
- mVsyncPeriod(16666666),
- mBtsVsyncPeriod(16666666),
+ mVsyncPeriod(kDefaultVsyncPeriodNanoSecond),
+ mBtsFrameScanoutPeriod(kDefaultVsyncPeriodNanoSecond),
+ mBtsPendingOperationRatePeriod(0),
mDevice(device),
mDisplayName(displayName.c_str()),
mDisplayTraceName(String8::format("%s(%d)", displayName.c_str(), mDisplayId)),
@@ -1403,15 +1404,21 @@ int ExynosDisplay::checkDynamicReCompMode() {
}
unsigned int incomingPixels = 0;
+ hwc_rect_t dispRect = {INT_MAX, INT_MAX, 0, 0};
for (size_t i = 0; i < mLayers.size(); i++) {
- auto w = WIDTH(mLayers[i]->mPreprocessedInfo.displayFrame);
- auto h = HEIGHT(mLayers[i]->mPreprocessedInfo.displayFrame);
+ auto& r = mLayers[i]->mPreprocessedInfo.displayFrame;
+ if (r.top < dispRect.top) dispRect.top = r.top;
+ if (r.left < dispRect.left) dispRect.left = r.left;
+ if (r.bottom > dispRect.bottom) dispRect.bottom = r.bottom;
+ if (r.right > dispRect.right) dispRect.right = r.right;
+ auto w = WIDTH(r);
+ auto h = HEIGHT(r);
incomingPixels += w * h;
}
/* Mode Switch is not required if total pixels are not more than the threshold */
- unsigned int lcdSize = mXres * mYres;
- if (incomingPixels <= lcdSize) {
+ unsigned int mergedDisplayFrameSize = WIDTH(dispRect) * HEIGHT(dispRect);
+ if (incomingPixels <= mergedDisplayFrameSize) {
auto ret = switchDynamicReCompMode(CLIENT_2_DEVICE);
if (ret) {
mUpdateCallCnt = 0;
@@ -1719,18 +1726,26 @@ int ExynosDisplay::skipStaticLayers(ExynosCompositionInfo& compositionInfo)
return NO_ERROR;
}
-bool ExynosDisplay::skipSignalIdle(void) {
+bool ExynosDisplay::shouldSignalNonIdle(void) {
+ // Some cases such that we can skip calling mPowerHalHint.signalNonIdle():
+ // 1. Updating source crop or buffer for video layer
+ // 2. Updating refresh rate indicator layer
+ uint64_t exclude = GEOMETRY_LAYER_SOURCECROP_CHANGED;
+ if ((mGeometryChanged & ~exclude) != 0) {
+ return true;
+ }
for (size_t i = 0; i < mLayers.size(); i++) {
// Frame update for refresh rate overlay indicator layer can be ignored
if (mLayers[i]->mRequestedCompositionType == HWC2_COMPOSITION_REFRESH_RATE_INDICATOR)
continue;
// Frame update for video layer can be ignored
if (mLayers[i]->isLayerFormatYuv()) continue;
- if (mLayers[i]->mLastLayerBuffer != mLayers[i]->mLayerBuffer) {
- return false;
+ if (mLayers[i]->mLastLayerBuffer != mLayers[i]->mLayerBuffer ||
+ mLayers[i]->mGeometryChanged != 0) {
+ return true;
}
}
- return true;
+ return false;
}
/**
@@ -1823,8 +1838,8 @@ int ExynosDisplay::doExynosComposition() {
return -EINVAL;
}
- if ((ret = mExynosCompositionInfo.mM2mMPP->doPostProcessing(mExynosCompositionInfo.mSrcImg,
- mExynosCompositionInfo.mDstImg)) != NO_ERROR) {
+ if ((ret = mExynosCompositionInfo.mM2mMPP->doPostProcessing(
+ mExynosCompositionInfo.mDstImg)) != NO_ERROR) {
DISPLAY_LOGE("exynosComposition doPostProcessing fail ret(%d)", ret);
return ret;
}
@@ -3489,6 +3504,8 @@ int32_t ExynosDisplay::presentDisplay(int32_t* outRetireFence) {
return ret;
}
+ tryUpdateBtsFromOperationRate(true);
+
if (mRenderingState != RENDERING_STATE_ACCEPTED_CHANGE) {
/*
* presentDisplay() can be called before validateDisplay()
@@ -3596,11 +3613,10 @@ int32_t ExynosDisplay::presentDisplay(int32_t* outRetireFence) {
if ((mDisplayControl.earlyStartMPP == false) &&
(mLayers[i]->mExynosCompositionType == HWC2_COMPOSITION_DEVICE) &&
(mLayers[i]->mM2mMPP != NULL)) {
- ExynosMPP *m2mMpp = mLayers[i]->mM2mMPP;
- srcImg = mLayers[i]->mSrcImg;
+ ExynosMPP* m2mMpp = mLayers[i]->mM2mMPP;
midImg = mLayers[i]->mMidImg;
m2mMpp->requestHWStateChange(MPP_HW_STATE_RUNNING);
- if ((ret = m2mMpp->doPostProcessing(srcImg, midImg)) != NO_ERROR) {
+ if ((ret = m2mMpp->doPostProcessing(midImg)) != NO_ERROR) {
HWC_LOGE(this, "%s:: doPostProcessing() failed, layer(%zu), ret(%d)",
__func__, i, ret);
errString.appendFormat("%s:: doPostProcessing() failed, layer(%zu), ret(%d)\n",
@@ -3625,12 +3641,12 @@ int32_t ExynosDisplay::presentDisplay(int32_t* outRetireFence) {
goto err;
}
- if (mGeometryChanged != 0 || !skipSignalIdle()) {
- mPowerHalHint.signalIdle();
+ if (shouldSignalNonIdle()) {
+ mPowerHalHint.signalNonIdle();
}
- if (needUpdateRRIndicator()) {
- updateRefreshRateIndicator();
+ if (mRefreshRateIndicatorHandler && needUpdateRRIndicator()) {
+ mRefreshRateIndicatorHandler->checkOnPresentDisplay();
}
handleWindowUpdate();
@@ -3733,6 +3749,8 @@ int32_t ExynosDisplay::presentDisplay(int32_t* outRetireFence) {
mPriorFrameMixedComposition = mixedComposition;
+ tryUpdateBtsFromOperationRate(false);
+
return ret;
err:
printDebugInfos(errString);
@@ -4022,7 +4040,7 @@ int32_t ExynosDisplay::setDisplayBrightness(float brightness, bool waitPresent)
ret = mBrightnessController->processDisplayBrightness(brightness, mVsyncPeriod,
waitPresent);
if (ret == NO_ERROR) {
- setMinIdleRefreshRate(0, VrrThrottleRequester::BRIGHTNESS);
+ setMinIdleRefreshRate(0, RrThrottleRequester::BRIGHTNESS);
if (mOperationRateManager) {
mOperationRateManager->onBrightness(mBrightnessController->getBrightnessLevel());
handleTargetOperationRate();
@@ -4047,7 +4065,7 @@ int32_t ExynosDisplay::setBrightnessNits(const float nits)
int32_t ret = mBrightnessController->setBrightnessNits(nits, mVsyncPeriod);
if (ret == NO_ERROR) {
- setMinIdleRefreshRate(0, VrrThrottleRequester::BRIGHTNESS);
+ setMinIdleRefreshRate(0, RrThrottleRequester::BRIGHTNESS);
if (mOperationRateManager)
mOperationRateManager->onBrightness(mBrightnessController->getBrightnessLevel());
}
@@ -4063,7 +4081,7 @@ int32_t ExynosDisplay::setBrightnessDbv(const uint32_t dbv) {
int32_t ret = mBrightnessController->setBrightnessDbv(dbv, mVsyncPeriod);
if (ret == NO_ERROR) {
- setMinIdleRefreshRate(0, VrrThrottleRequester::BRIGHTNESS);
+ setMinIdleRefreshRate(0, RrThrottleRequester::BRIGHTNESS);
if (mOperationRateManager) {
mOperationRateManager->onBrightness(mBrightnessController->getBrightnessLevel());
}
@@ -4207,13 +4225,15 @@ int32_t ExynosDisplay::setActiveConfigWithConstraints(hwc2_config_t config,
/* mActiveConfig should be changed immediately for internal status */
mActiveConfig = config;
mVsyncAppliedTimeLine = *outTimeline;
- uint32_t vsync_period = getDisplayVsyncPeriodFromConfig(config);
- updateBtsVsyncPeriod(vsync_period);
+ updateBtsFrameScanoutPeriod(getDisplayFrameScanoutPeriodFromConfig(config));
bool earlyWakeupNeeded = checkRrCompensationEnabled();
if (earlyWakeupNeeded) {
setEarlyWakeupDisplay();
}
+ if (mRefreshRateIndicatorHandler) {
+ mRefreshRateIndicatorHandler->checkOnSetActiveConfig(mDisplayConfigs[config].refreshRate);
+ }
return HWC2_ERROR_NONE;
}
@@ -4304,25 +4324,88 @@ int32_t ExynosDisplay::updateInternalDisplayConfigVariables(
if (updateVsync) {
resetConfigRequestStateLocked(config);
}
+ if (mRefreshRateIndicatorHandler) {
+ mRefreshRateIndicatorHandler->checkOnSetActiveConfig(mDisplayConfigs[config].refreshRate);
+ }
return NO_ERROR;
}
-void ExynosDisplay::updateBtsVsyncPeriod(uint32_t vsyncPeriod, bool configApplied) {
- if (configApplied || vsyncPeriod < mBtsVsyncPeriod) {
- checkBtsReassignResource(vsyncPeriod, mBtsVsyncPeriod);
- mBtsVsyncPeriod = vsyncPeriod;
+void ExynosDisplay::updateBtsFrameScanoutPeriod(int32_t frameScanoutPeriod, bool configApplied) {
+ if (mBtsFrameScanoutPeriod == frameScanoutPeriod) {
+ return;
+ }
+
+ if (configApplied || frameScanoutPeriod < mBtsFrameScanoutPeriod) {
+ checkBtsReassignResource(frameScanoutPeriod, mBtsFrameScanoutPeriod);
+ mBtsFrameScanoutPeriod = frameScanoutPeriod;
+ ATRACE_INT("btsFrameScanoutPeriod", mBtsFrameScanoutPeriod);
+ }
+}
+
+void ExynosDisplay::tryUpdateBtsFromOperationRate(bool beforeValidateDisplay) {
+ if (mOperationRateManager == nullptr || mBrightnessController == nullptr ||
+ mActiveConfig == UINT_MAX) {
+ return;
+ }
+
+ if (!mDisplayConfigs[mActiveConfig].isOperationRateToBts) {
+ return;
+ }
+
+ if (beforeValidateDisplay && mBrightnessController->isOperationRatePending()) {
+ uint32_t opRate = mBrightnessController->getOperationRate();
+ if (opRate) {
+ int32_t operationRatePeriod = nsecsPerSec / opRate;
+ if (operationRatePeriod < mBtsFrameScanoutPeriod) {
+ updateBtsFrameScanoutPeriod(opRate);
+ mBtsPendingOperationRatePeriod = 0;
+ } else if (operationRatePeriod != mBtsFrameScanoutPeriod) {
+ mBtsPendingOperationRatePeriod = operationRatePeriod;
+ }
+ }
+ }
+
+ if (!beforeValidateDisplay && mBtsPendingOperationRatePeriod &&
+ !mBrightnessController->isOperationRatePending()) {
+ /* Do not update during rr transition, it will be updated after setting config done */
+ if (mConfigRequestState != hwc_request_state_t::SET_CONFIG_STATE_REQUESTED) {
+ updateBtsFrameScanoutPeriod(mBtsPendingOperationRatePeriod, true);
+ }
+ mBtsPendingOperationRatePeriod = 0;
+ }
+}
+
+inline int32_t ExynosDisplay::getDisplayFrameScanoutPeriodFromConfig(hwc2_config_t config) {
+ int32_t frameScanoutPeriodNs;
+ std::optional<VrrConfig_t> vrrConfig = getVrrConfigs(config);
+ if (vrrConfig.has_value()) {
+ frameScanoutPeriodNs = vrrConfig->minFrameIntervalNs;
+ } else {
+ getDisplayAttribute(config, HWC2_ATTRIBUTE_VSYNC_PERIOD, &frameScanoutPeriodNs);
+ if (mOperationRateManager && mBrightnessController &&
+ mDisplayConfigs[config].isOperationRateToBts) {
+ uint32_t opRate = mBrightnessController->getOperationRate();
+ if (opRate) {
+ uint32_t opPeriodNs = nsecsPerSec / opRate;
+ frameScanoutPeriodNs =
+ (frameScanoutPeriodNs <= opPeriodNs) ? frameScanoutPeriodNs : opPeriodNs;
+ }
+ }
}
+
+ assert(frameScanoutPeriodNs > 0);
+ return frameScanoutPeriodNs;
}
uint32_t ExynosDisplay::getBtsRefreshRate() const {
- return static_cast<uint32_t>(round(nsecsPerSec / mBtsVsyncPeriod * 0.1f) * 10);
+ return static_cast<uint32_t>(round(nsecsPerSec / mBtsFrameScanoutPeriod * 0.1f) * 10);
}
void ExynosDisplay::updateRefreshRateHint() {
- if (mVsyncPeriod) {
+ if (mRefreshRate) {
mPowerHalHint.signalRefreshRate(mPowerModeState.value_or(HWC2_POWER_MODE_OFF),
- mVsyncPeriod);
+ mRefreshRate);
}
}
@@ -4330,8 +4413,11 @@ void ExynosDisplay::updateRefreshRateHint() {
int32_t ExynosDisplay::resetConfigRequestStateLocked(hwc2_config_t config) {
ATRACE_CALL();
+ assert(isBadConfig(config) == false);
+
+ mRefreshRate = mDisplayConfigs[config].refreshRate;
mVsyncPeriod = getDisplayVsyncPeriodFromConfig(config);
- updateBtsVsyncPeriod(mVsyncPeriod, true);
+ updateBtsFrameScanoutPeriod(getDisplayFrameScanoutPeriodFromConfig(config), true);
DISPLAY_LOGD(eDebugDisplayConfig, "Update mVsyncPeriod %d by config(%d)", mVsyncPeriod, config);
updateRefreshRateHint();
@@ -4598,15 +4684,14 @@ int32_t ExynosDisplay::validateDisplay(
for (size_t i = 0; i < mLayers.size(); i++) mLayers[i]->setSrcAcquireFence();
+ tryUpdateBtsFromOperationRate(true);
doPreProcessing();
checkLayerFps();
- if (exynosHWCControl.useDynamicRecomp == true && mDREnable)
+ if (exynosHWCControl.useDynamicRecomp == true && mDREnable) {
checkDynamicReCompMode();
-
- if (exynosHWCControl.useDynamicRecomp == true &&
- mDevice->isDynamicRecompositionThreadAlive() == false &&
- mDevice->mDRLoopStatus == false) {
- mDevice->dynamicRecompositionThreadCreate();
+ if (mDevice->isDynamicRecompositionThreadAlive() == false &&
+ mDevice->mDRLoopStatus == false)
+ mDevice->dynamicRecompositionThreadCreate();
}
if ((ret = mResourceManager->assignResource(this)) != NO_ERROR) {
@@ -4722,11 +4807,10 @@ int32_t ExynosDisplay::startPostProcessing()
mLayers[i]->setSrcExynosImage(&srcImg);
mLayers[i]->setDstExynosImage(&dstImg);
mLayers[i]->setExynosImage(srcImg, dstImg);
- ExynosMPP *m2mMpp = mLayers[i]->mM2mMPP;
- srcImg = mLayers[i]->mSrcImg;
+ ExynosMPP* m2mMpp = mLayers[i]->mM2mMPP;
midImg = mLayers[i]->mMidImg;
m2mMpp->requestHWStateChange(MPP_HW_STATE_RUNNING);
- if ((ret = m2mMpp->doPostProcessing(srcImg, midImg)) != NO_ERROR) {
+ if ((ret = m2mMpp->doPostProcessing(midImg)) != NO_ERROR) {
DISPLAY_LOGE("%s:: doPostProcessing() failed, layer(%zu), ret(%d)",
__func__, i, ret);
errString.appendFormat("%s:: doPostProcessing() failed, layer(%zu), ret(%d)\n",
@@ -5805,6 +5889,13 @@ int32_t ExynosDisplay::getMountOrientation(HwcMountOrientation *orientation)
return HWC2_ERROR_NONE;
}
+std::optional<VrrConfig_t> ExynosDisplay::getVrrConfigs(hwc2_config_t config) {
+ if (isBadConfig(config)) {
+ return std::nullopt;
+ }
+ return mDisplayConfigs[config].vrrConfig;
+}
+
// Support DDI scalser
void ExynosDisplay::setDDIScalerEnable(int __unused width, int __unused height) {
}
@@ -6035,7 +6126,7 @@ void ExynosDisplay::cleanupAfterClientDeath() {
int32_t ExynosDisplay::flushDisplayBrightnessChange() {
if (mBrightnessController) {
- setMinIdleRefreshRate(0, VrrThrottleRequester::BRIGHTNESS);
+ setMinIdleRefreshRate(0, RrThrottleRequester::BRIGHTNESS);
if (mOperationRateManager) {
mOperationRateManager->onBrightness(mBrightnessController->getBrightnessLevel());
handleTargetOperationRate();
@@ -6174,21 +6265,22 @@ bool ExynosDisplay::isMixedComposition() {
int ExynosDisplay::lookupDisplayConfigs(const int32_t &width,
const int32_t &height,
const int32_t &fps,
+ const int32_t &vsyncRate,
int32_t *outConfig) {
- if (!fps)
+ if (!fps || !vsyncRate)
return HWC2_ERROR_BAD_CONFIG;
constexpr auto nsecsPerSec = std::chrono::nanoseconds(1s).count();
constexpr auto nsecsPerMs = std::chrono::nanoseconds(1ms).count();
- const auto vsyncPeriod = nsecsPerSec / fps;
+ const auto vsyncPeriod = nsecsPerSec / vsyncRate;
for (auto const& [config, mode] : mDisplayConfigs) {
long delta = abs(vsyncPeriod - mode.vsyncPeriod);
if ((width == 0 || width == mode.width) && (height == 0 || height == mode.height) &&
- (delta < nsecsPerMs)) {
- ALOGD("%s: found display config for mode: %dx%d@%d=%d",
- __func__, width, height, fps, config);
+ (delta < nsecsPerMs) && (fps == mode.refreshRate)) {
+ ALOGD("%s: found display config for mode: %dx%d@%d:%d config=%d",
+ __func__, width, height, fps, vsyncRate, config);
*outConfig = config;
return HWC2_ERROR_NONE;
}
@@ -6281,10 +6373,13 @@ bool ExynosDisplay::checkHotplugEventUpdated(bool &hpdStatus) {
hpdStatus = mDisplayInterface->readHotplugStatus();
- DISPLAY_LOGI("[%s] mDisplayId(%d), mIndex(%d), HPD Status(previous :%d, current : %d)",
- __func__, mDisplayId, mIndex, mHpdStatus, hpdStatus);
+ int hotplugErrorCode = mDisplayInterface->readHotplugErrorCode();
- return (mHpdStatus != hpdStatus);
+ DISPLAY_LOGI("[%s] mDisplayId(%d), mIndex(%d), HPD Status(previous :%d, current : %d), "
+ "hotplugErrorCode=%d",
+ __func__, mDisplayId, mIndex, mHpdStatus, hpdStatus, hotplugErrorCode);
+
+ return (mHpdStatus != hpdStatus) || (hotplugErrorCode != 0);
}
void ExynosDisplay::handleHotplugEvent(bool hpdStatus) {
@@ -6292,19 +6387,21 @@ void ExynosDisplay::handleHotplugEvent(bool hpdStatus) {
}
void ExynosDisplay::hotplug() {
- mDevice->onHotPlug(mDisplayId, mHpdStatus);
- ALOGI("HPD callback(%s, mDisplayId %d) was called",
- mHpdStatus ? "connection" : "disconnection", mDisplayId);
+ int hotplugErrorCode = mDisplayInterface->readHotplugErrorCode();
+ mDisplayInterface->resetHotplugErrorCode();
+ mDevice->onHotPlug(mDisplayId, mHpdStatus, hotplugErrorCode);
+ ALOGI("HPD callback(%s, mDisplayId %d, hotplugErrorCode=%d) was called",
+ mHpdStatus ? "connection" : "disconnection", mDisplayId, hotplugErrorCode);
}
-ExynosDisplay::RefreshRateIndicatorHandler::RefreshRateIndicatorHandler(ExynosDisplay *display)
+ExynosDisplay::SysfsBasedRRIHandler::SysfsBasedRRIHandler(ExynosDisplay* display)
: mDisplay(display),
mLastRefreshRate(0),
mLastCallbackTime(0),
mIgnoringLastUpdate(false),
mCanIgnoreIncreaseUpdate(false) {}
-int32_t ExynosDisplay::RefreshRateIndicatorHandler::init() {
+int32_t ExynosDisplay::SysfsBasedRRIHandler::init() {
auto path = String8::format(kRefreshRateStatePathFormat, mDisplay->mIndex);
mFd.Set(open(path.c_str(), O_RDONLY));
if (mFd.get() < 0) {
@@ -6312,11 +6409,21 @@ int32_t ExynosDisplay::RefreshRateIndicatorHandler::init() {
strerror(errno));
return -errno;
}
-
+ auto ret = mDisplay->mDevice->mDeviceInterface->registerSysfsEventHandler(shared_from_this());
+ if (ret != NO_ERROR) {
+ ALOGE("%s: Failed to register sysfs event handler: %d", __func__, ret);
+ return ret;
+ }
+ // Call the callback immediately
+ handleSysfsEvent();
return NO_ERROR;
}
-void ExynosDisplay::RefreshRateIndicatorHandler::updateRefreshRateLocked(int refreshRate) {
+int32_t ExynosDisplay::SysfsBasedRRIHandler::disable() {
+ return mDisplay->mDevice->mDeviceInterface->unregisterSysfsEventHandler(getFd());
+}
+
+void ExynosDisplay::SysfsBasedRRIHandler::updateRefreshRateLocked(int refreshRate) {
ATRACE_CALL();
ATRACE_INT("Refresh rate indicator event", refreshRate);
// Ignore refresh rate increase that is caused by refresh rate indicator update but there's
@@ -6338,7 +6445,7 @@ void ExynosDisplay::RefreshRateIndicatorHandler::updateRefreshRateLocked(int ref
mCanIgnoreIncreaseUpdate = true;
}
-void ExynosDisplay::RefreshRateIndicatorHandler::handleSysfsEvent() {
+void ExynosDisplay::SysfsBasedRRIHandler::handleSysfsEvent() {
ATRACE_CALL();
std::scoped_lock lock(mMutex);
@@ -6362,7 +6469,7 @@ void ExynosDisplay::RefreshRateIndicatorHandler::handleSysfsEvent() {
updateRefreshRateLocked(refreshRate);
}
-void ExynosDisplay::RefreshRateIndicatorHandler::updateRefreshRate(int refreshRate) {
+void ExynosDisplay::SysfsBasedRRIHandler::updateRefreshRate(int refreshRate) {
std::scoped_lock lock(mMutex);
updateRefreshRateLocked(refreshRate);
}
@@ -6375,7 +6482,11 @@ int32_t ExynosDisplay::setRefreshRateChangedCallbackDebugEnabled(bool enabled) {
}
int32_t ret = NO_ERROR;
if (enabled) {
- mRefreshRateIndicatorHandler = std::make_shared<RefreshRateIndicatorHandler>(this);
+ if (mType == HWC_DISPLAY_PRIMARY) {
+ mRefreshRateIndicatorHandler = std::make_shared<SysfsBasedRRIHandler>(this);
+ } else {
+ mRefreshRateIndicatorHandler = std::make_shared<ActiveConfigBasedRRIHandler>(this);
+ }
if (!mRefreshRateIndicatorHandler) {
ALOGE("%s: Failed to create refresh rate debug handler", __func__);
return -ENOMEM;
@@ -6386,17 +6497,8 @@ int32_t ExynosDisplay::setRefreshRateChangedCallbackDebugEnabled(bool enabled) {
mRefreshRateIndicatorHandler.reset();
return ret;
}
- ret = mDevice->mDeviceInterface->registerSysfsEventHandler(mRefreshRateIndicatorHandler);
- if (ret != NO_ERROR) {
- ALOGE("%s: Failed to register sysfs event handler: %d", __func__, ret);
- mRefreshRateIndicatorHandler.reset();
- return ret;
- }
- // Call the callback immediately
- mRefreshRateIndicatorHandler->handleSysfsEvent();
} else {
- ret = mDevice->mDeviceInterface->unregisterSysfsEventHandler(
- mRefreshRateIndicatorHandler->getFd());
+ ret = mRefreshRateIndicatorHandler->disable();
mRefreshRateIndicatorHandler.reset();
}
return ret;
@@ -6414,13 +6516,34 @@ nsecs_t ExynosDisplay::getLastLayerUpdateTime() {
return time;
}
-void ExynosDisplay::updateRefreshRateIndicator() {
+void ExynosDisplay::SysfsBasedRRIHandler::checkOnPresentDisplay() {
// Update refresh rate indicator if the last update event is ignored to make sure that
// the refresh rate caused by the current frame update will be applied immediately since
// we may not receive the sysfs event if the refresh rate is the same as the last ignored one.
- if (!mRefreshRateIndicatorHandler || !mRefreshRateIndicatorHandler->isIgnoringLastUpdate())
+ if (!mIgnoringLastUpdate) {
return;
- mRefreshRateIndicatorHandler->handleSysfsEvent();
+ }
+ handleSysfsEvent();
+}
+
+ExynosDisplay::ActiveConfigBasedRRIHandler::ActiveConfigBasedRRIHandler(ExynosDisplay* display)
+ : mDisplay(display), mLastRefreshRate(0) {}
+
+int32_t ExynosDisplay::ActiveConfigBasedRRIHandler::init() {
+ updateRefreshRate(mDisplay->mRefreshRate);
+ return NO_ERROR;
+}
+
+void ExynosDisplay::ActiveConfigBasedRRIHandler::updateRefreshRate(int refreshRate) {
+ if (mLastRefreshRate == refreshRate) {
+ return;
+ }
+ mLastRefreshRate = refreshRate;
+ mDisplay->mDevice->onRefreshRateChangedDebug(mDisplay->mDisplayId, s2ns(1) / refreshRate);
+}
+
+void ExynosDisplay::ActiveConfigBasedRRIHandler::checkOnSetActiveConfig(int refreshRate) {
+ updateRefreshRate(refreshRate);
}
bool ExynosDisplay::needUpdateRRIndicator() {
@@ -6429,21 +6552,20 @@ bool ExynosDisplay::needUpdateRRIndicator() {
}
uint32_t ExynosDisplay::getPeakRefreshRate() {
- float opRate = mBrightnessController->getOperationRate();
- return static_cast<uint32_t>(std::round(opRate ?: mPeakRefreshRate));
+ uint32_t opRate = mBrightnessController->getOperationRate();
+ return opRate ?: mPeakRefreshRate;
}
VsyncPeriodNanos ExynosDisplay::getVsyncPeriod(const int32_t config) {
- const auto &it = mDisplayConfigs.find(config);
+ const auto& it = mDisplayConfigs.find(config);
if (it == mDisplayConfigs.end()) return 0;
- return mDisplayConfigs[config].vsyncPeriod;
+ return it->second.vsyncPeriod;
}
uint32_t ExynosDisplay::getRefreshRate(const int32_t config) {
- VsyncPeriodNanos period = getVsyncPeriod(config);
- if (!period) return 0;
- constexpr float nsecsPerSec = std::chrono::nanoseconds(1s).count();
- return round(nsecsPerSec / period * 0.1f) * 10;
+ const auto& it = mDisplayConfigs.find(config);
+ if (it == mDisplayConfigs.end()) return 0;
+ return it->second.refreshRate;
}
uint32_t ExynosDisplay::getConfigId(const int32_t refreshRate, const int32_t width,
@@ -6494,3 +6616,18 @@ void ExynosDisplay::storePrevValidateCompositionType() {
}
mClientCompositionInfo.mPrevHasCompositionLayer = mClientCompositionInfo.mHasCompositionLayer;
}
+
+displaycolor::DisplayType ExynosDisplay::getDcDisplayType() const {
+ switch (mType) {
+ case HWC_DISPLAY_PRIMARY:
+ return mIndex == 0 ? displaycolor::DisplayType::DISPLAY_PRIMARY
+ : displaycolor::DisplayType::DISPLAY_SECONDARY;
+ case HWC_DISPLAY_EXTERNAL:
+ return displaycolor::DisplayType::DISPLAY_EXTERNAL;
+ case HWC_DISPLAY_VIRTUAL:
+ default:
+ DISPLAY_LOGE("%s: Unsupported display type(%d)", __func__, mType);
+ assert(false);
+ return displaycolor::DisplayType::DISPLAY_PRIMARY;
+ }
+}