summaryrefslogtreecommitdiff
path: root/libhwc2.1/libmaindisplay/ExynosPrimaryDisplay.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libhwc2.1/libmaindisplay/ExynosPrimaryDisplay.cpp')
-rw-r--r--libhwc2.1/libmaindisplay/ExynosPrimaryDisplay.cpp317
1 files changed, 247 insertions, 70 deletions
diff --git a/libhwc2.1/libmaindisplay/ExynosPrimaryDisplay.cpp b/libhwc2.1/libmaindisplay/ExynosPrimaryDisplay.cpp
index ec1e8ba..d440ac2 100644
--- a/libhwc2.1/libmaindisplay/ExynosPrimaryDisplay.cpp
+++ b/libhwc2.1/libmaindisplay/ExynosPrimaryDisplay.cpp
@@ -38,11 +38,26 @@
extern struct exynos_hwc_control exynosHWCControl;
using namespace SOC_VERSION;
+
+namespace {
+
constexpr auto nsecsPerSec = std::chrono::nanoseconds(1s).count();
+inline constexpr int kDefaultNotifyExpectedPresentConfigHeadsUpNs =
+ std::chrono::nanoseconds(30ms).count();
+inline constexpr int kDefaultNotifyExpectedPresentConfigTimeoutNs =
+ std::chrono::nanoseconds(30ms).count();
+
+static constexpr int kMaximumPropertyIdentifierLength = 128;
+
static const std::map<const DisplayType, const std::string> panelSysfsPath =
{{DisplayType::DISPLAY_PRIMARY, "/sys/devices/platform/exynos-drm/primary-panel/"},
- {DisplayType::DISPLAY_SECONDARY, "/sys/devices/platform/exynos-drm/secondary-panel/"}};
+#ifdef USES_IDISPLAY_INTF_SEC
+ {DisplayType::DISPLAY_SECONDARY, "/sys/devices/platform/exynos-drm/secondary-panel/"}
+#endif
+
+};
+} // namespace
static String8 getPropertyBootModeStr(const int32_t dispId) {
String8 str;
@@ -87,8 +102,8 @@ ExynosPrimaryDisplay::ExynosPrimaryDisplay(uint32_t index, ExynosDevice *device,
: ExynosDisplay(HWC_DISPLAY_PRIMARY, index, device, displayName),
mUseBlockingZoneForMinIdleRefreshRate(false),
mMinIdleRefreshRate(0),
- mVrrThrottleFps{0},
- mVrrThrottleNanos{0},
+ mRrThrottleFps{0},
+ mRrThrottleNanos{0},
mRefreshRateDelayNanos(0),
mLastRefreshRateAppliedNanos(0),
mAppliedActiveConfig(0),
@@ -117,6 +132,36 @@ ExynosPrimaryDisplay::ExynosPrimaryDisplay(uint32_t index, ExynosDevice *device,
mDbvThresholdForBlockingZone);
}
+ DisplayType displayType = getDcDisplayType();
+ std::string displayTypeIdentifier;
+ if (displayType == DisplayType::DISPLAY_PRIMARY) {
+ displayTypeIdentifier = "primarydisplay";
+ } else if (displayType == DisplayType::DISPLAY_EXTERNAL) {
+ displayTypeIdentifier = "externaldisplay";
+ }
+#ifdef USES_IDISPLAY_INTF_SEC
+ else if (displayType == DisplayType::DISPLAY_SECONDARY) {
+ displayTypeIdentifier = "secondarydisplay";
+ }
+#endif
+ if (!displayTypeIdentifier.empty()) {
+ char pathBuffer[kMaximumPropertyIdentifierLength];
+ sprintf(pathBuffer, "ro.vendor.%s.vrr.enabled", displayTypeIdentifier.c_str());
+ mVrrSettings.enabled = property_get_bool(pathBuffer, false);
+ if (mVrrSettings.enabled) {
+ sprintf(pathBuffer, "ro.vendor.%s.vrr.expected_present.headsup_ns",
+ displayTypeIdentifier.c_str());
+ mVrrSettings.notifyExpectedPresentConfig.HeadsUpNs =
+ property_get_int32(pathBuffer, kDefaultNotifyExpectedPresentConfigHeadsUpNs);
+ sprintf(pathBuffer, "ro.vendor.%s.vrr.expected_present.timeout_ns",
+ displayTypeIdentifier.c_str());
+ mVrrSettings.notifyExpectedPresentConfig.TimeoutNs =
+ property_get_int32(pathBuffer, kDefaultNotifyExpectedPresentConfigTimeoutNs);
+ mVrrSettings.configChangeCallback =
+ std::bind(&ExynosPrimaryDisplay::onConfigChange, this, std::placeholders::_1);
+ }
+ }
+
// Allow to enable dynamic recomposition after every power on
// since it will always be disabled for every power off
// TODO(b/268474771): to enable DR by default if video mode panel is detected
@@ -146,7 +191,7 @@ ExynosPrimaryDisplay::ExynosPrimaryDisplay(uint32_t index, ExynosDevice *device,
char value[PROPERTY_VALUE_MAX];
const char *earlyWakeupNodeBase = early_wakeup_node_0_base;
- if (getDisplayTypeFromIndex(mIndex) == DisplayType::DISPLAY_SECONDARY &&
+ if (getDcDisplayType() == DisplayType::DISPLAY_SECONDARY &&
property_get("vendor.display.secondary_early_wakeup_node", value, "") > 0) {
earlyWakeupNodeBase = value;
}
@@ -234,10 +279,14 @@ int32_t ExynosPrimaryDisplay::setActiveConfigInternal(hwc2_config_t config, bool
}
int32_t ExynosPrimaryDisplay::applyPendingConfig() {
- if (!isConfigSettingEnabled()) return HWC2_ERROR_NONE;
+ if (!isConfigSettingEnabled()) {
+ ALOGI("%s:: config setting is disabled", __func__);
+ return HWC2_ERROR_NONE;
+ }
hwc2_config_t config;
if (mPendingConfig != UINT_MAX) {
+ ALOGI("%s:: mPendingConfig: %d", __func__, mPendingConfig);
config = mPendingConfig;
mPendingConfig = UINT_MAX;
} else {
@@ -260,15 +309,14 @@ int32_t ExynosPrimaryDisplay::setBootDisplayConfig(int32_t config) {
if (mode.vsyncPeriod == 0)
return HWC2_ERROR_BAD_CONFIG;
- int refreshRate = round(nsecsPerSec / mode.vsyncPeriod * 0.1f) * 10;
+ int vsyncRate = round(static_cast<float>(nsecsPerSec) / mode.vsyncPeriod);
char modeStr[PROPERTY_VALUE_MAX];
- int ret = snprintf(modeStr, sizeof(modeStr), "%dx%d@%d",
- mode.width, mode.height, refreshRate);
+ int ret = snprintf(modeStr, sizeof(modeStr), "%dx%d@%d:%d",
+ mode.width, mode.height, mode.refreshRate, vsyncRate);
if (ret <= 0)
return HWC2_ERROR_BAD_CONFIG;
- ALOGD("%s: mode=%s (%d) vsyncPeriod=%d", __func__, modeStr, config,
- mode.vsyncPeriod);
+ ALOGD("%s: mode=%s (%d)", __func__, modeStr, config);
ret = property_set(getPropertyBootModeStr(mDisplayId).c_str(), modeStr);
return !ret ? HWC2_ERROR_NONE : HWC2_ERROR_BAD_CONFIG;
@@ -290,15 +338,31 @@ int32_t ExynosPrimaryDisplay::getPreferredDisplayConfigInternal(int32_t *outConf
}
int width, height;
- int fps = 0;
-
- ret = sscanf(modeStr, "%dx%d@%d", &width, &height, &fps);
- if ((ret < 3) || !fps) {
- ALOGD("%s: unable to find boot config for mode: %s", __func__, modeStr);
+ int fps = 0, vsyncRate = 0;
+
+ ret = sscanf(modeStr, "%dx%d@%d:%d", &width, &height, &fps, &vsyncRate);
+ if (ret < 4) {
+ ret = sscanf(modeStr, "%dx%d@%d", &width, &height, &fps);
+ if ((ret < 3) || !fps) {
+ ALOGW("%s: unable to find boot config for mode: %s", __func__, modeStr);
+ return HWC2_ERROR_BAD_CONFIG;
+ }
+ if (lookupDisplayConfigs(width, height, fps, fps, outConfig) != HWC2_ERROR_NONE) {
+ ALOGE("%s: kernel doesn't support mode: %s", __func__, modeStr);
+ return HWC2_ERROR_BAD_CONFIG;
+ }
+ ret = setBootDisplayConfig(*outConfig);
+ if (ret == HWC2_ERROR_NONE)
+ ALOGI("%s: succeeded to replace %s with new format", __func__, modeStr);
+ else
+ ALOGE("%s: failed to replace %s with new format", __func__, modeStr);
+ return ret;
+ }
+ if (!fps || !vsyncRate || (fps > vsyncRate)) {
+ ALOGE("%s: bad boot config: %s", __func__, modeStr);
return HWC2_ERROR_BAD_CONFIG;
}
-
- return lookupDisplayConfigs(width, height, fps, outConfig);
+ return lookupDisplayConfigs(width, height, fps, vsyncRate, outConfig);
}
int32_t ExynosPrimaryDisplay::setPowerOn() {
@@ -430,27 +494,35 @@ int32_t ExynosPrimaryDisplay::setPowerMode(int32_t mode) {
mOperationRateManager->getTargetOperationRate());
}
+ int32_t res = HWC2_ERROR_BAD_PARAMETER;
switch (mode) {
case HWC2_POWER_MODE_DOZE:
- case HWC2_POWER_MODE_DOZE_SUSPEND:
+ case HWC2_POWER_MODE_DOZE_SUSPEND: {
if (mode == HWC2_POWER_MODE_DOZE && mDisplayInterface->needRefreshOnLP()) {
ALOGI("Refresh before setting power doze.");
mDevice->onRefresh(mDisplayId);
}
- return setPowerDoze(static_cast<hwc2_power_mode_t>(mode));
+ res = setPowerDoze(static_cast<hwc2_power_mode_t>(mode));
+ break;
+ }
case HWC2_POWER_MODE_OFF:
- setPowerOff();
+ res = setPowerOff();
break;
case HWC2_POWER_MODE_ON:
- setPowerOn();
+ res = setPowerOn();
break;
default:
- return HWC2_ERROR_BAD_PARAMETER;
+ return res;
+ }
+ if (res != HWC2_ERROR_NONE) {
+ return res;
}
ExynosDisplay::updateRefreshRateHint();
-
- return HWC2_ERROR_NONE;
+ if (mVariableRefreshRateController) {
+ mVariableRefreshRateController->setPowerMode(mode);
+ }
+ return res;
}
void ExynosPrimaryDisplay::firstPowerOn() {
@@ -474,19 +546,23 @@ void ExynosPrimaryDisplay::initDisplayInterface(uint32_t interfaceType)
__func__, interfaceType);
mDisplayInterface->init(this);
+ if (mVrrSettings.enabled) {
+ mDisplayInterface->setVrrSettings(mVrrSettings);
+ }
+
mDpuData.init(mMaxWindowNum, mDevice->getSpecialPlaneNum(mDisplayId));
mLastDpuData.init(mMaxWindowNum, mDevice->getSpecialPlaneNum(mDisplayId));
ALOGI("window configs size(%zu) rcd configs zie(%zu)", mDpuData.configs.size(),
mDpuData.rcdConfigs.size());
}
-std::string ExynosPrimaryDisplay::getPanelSysfsPath(const DisplayType &type) {
+std::string ExynosPrimaryDisplay::getPanelSysfsPath(const DisplayType& type) const {
if ((type < DisplayType::DISPLAY_PRIMARY) || (type >= DisplayType::DISPLAY_MAX)) {
ALOGE("Invalid display panel type %d", type);
return {};
}
- auto iter = panelSysfsPath.find(type);
+ const auto& iter = panelSysfsPath.find(type);
if (iter == panelSysfsPath.end()) {
return {};
}
@@ -578,7 +654,7 @@ bool ExynosPrimaryDisplay::isConfigSettingEnabled() {
void ExynosPrimaryDisplay::enableConfigSetting(bool en) {
DISPLAY_ATRACE_INT("ConfigSettingDisabled", !en);
-
+ ALOGI("%s:: mConfigSettingDisabled: %d", __func__, !en);
if (!en) {
mConfigSettingDisabled = true;
mConfigSettingDisabledTimestamp = systemTime(SYSTEM_TIME_MONOTONIC);
@@ -588,6 +664,57 @@ void ExynosPrimaryDisplay::enableConfigSetting(bool en) {
mConfigSettingDisabled = false;
}
+int32_t ExynosPrimaryDisplay::getDisplayConfigs(uint32_t* outNumConfigs,
+ hwc2_config_t* outConfigs) {
+ int32_t ret = ExynosDisplay::getDisplayConfigs(outNumConfigs, outConfigs);
+ if (ret == HWC2_ERROR_NONE) {
+ if (mVrrSettings.enabled && mDisplayConfigs.size()) {
+ if (!mVariableRefreshRateController) {
+ mVariableRefreshRateController =
+ VariableRefreshRateController::CreateInstance(this);
+ std::unordered_map<hwc2_config_t, VrrConfig_t> vrrConfigs;
+ for (const auto& it : mDisplayConfigs) {
+ if (!it.second.vrrConfig.has_value()) {
+ return HWC2_ERROR_BAD_CONFIG;
+ }
+ vrrConfigs[it.first] = it.second.vrrConfig.value();
+ }
+ mVariableRefreshRateController->setVrrConfigurations(std::move(vrrConfigs));
+ hwc2_config_t activeConfig;
+ if (ExynosDisplay::getActiveConfig(&activeConfig) == HWC2_ERROR_NONE) {
+ mVariableRefreshRateController->setActiveVrrConfiguration(activeConfig);
+ mVariableRefreshRateController->setEnable(true);
+ }
+ }
+ }
+ }
+ return ret;
+}
+
+int32_t ExynosPrimaryDisplay::presentDisplay(int32_t* outRetireFence) {
+ auto res = ExynosDisplay::presentDisplay(outRetireFence);
+ // Forward presentDisplay if there is a listener.
+ const auto presentListener = getPresentListener();
+ if (res == HWC2_ERROR_NONE && presentListener) {
+ presentListener->onPresent(*outRetireFence);
+ }
+ return res;
+}
+
+void ExynosPrimaryDisplay::onVsync(int64_t timestamp) {
+ const auto vsyncListener = getVsyncListener();
+ if (vsyncListener) {
+ vsyncListener->onVsync(timestamp, 0);
+ }
+}
+
+int32_t ExynosPrimaryDisplay::notifyExpectedPresent(int64_t timestamp, int32_t frameIntervalNs) {
+ if (mVariableRefreshRateController) {
+ mVariableRefreshRateController->notifyExpectedPresent(timestamp, frameIntervalNs);
+ }
+ return NO_ERROR;
+}
+
int32_t ExynosPrimaryDisplay::setLhbmDisplayConfigLocked(uint32_t peakRate) {
auto hwConfig = mDisplayInterface->getActiveModeId();
auto config = getConfigId(peakRate, mDisplayConfigs[hwConfig].width,
@@ -641,10 +768,11 @@ int32_t ExynosPrimaryDisplay::setLhbmState(bool enabled) {
{
ATRACE_NAME("wait_for_power_on");
std::unique_lock<std::mutex> lock(mPowerModeMutex);
- if (mPowerModeState != HWC2_POWER_MODE_ON) {
+ if (!mPowerModeState.has_value() || (*mPowerModeState != HWC2_POWER_MODE_ON)) {
mNotifyPowerOn = true;
if (!mPowerOnCondition.wait_for(lock, std::chrono::milliseconds(2000), [this]() {
- return (mPowerModeState == HWC2_POWER_MODE_ON);
+ return (mPowerModeState.has_value() &&
+ (*mPowerModeState == HWC2_POWER_MODE_ON));
})) {
DISPLAY_LOGW("%s: wait for power mode on timeout !", __func__);
return TIMED_OUT;
@@ -786,6 +914,18 @@ int32_t ExynosPrimaryDisplay::setLhbmState(bool enabled) {
}
return NO_ERROR;
enable_err:
+ {
+ // We may receive LHBM request during the power off sequence due to the
+ // race condition between display and sensor. If the failure happens
+ // after requestLhbm(), we will get a wrong LHBM state in the 1st commit
+ // after power on. We should reset the state in this case.
+ std::unique_lock<std::mutex> lock(mPowerModeMutex);
+ if (!mPowerModeState.has_value() || (*mPowerModeState == HWC2_POWER_MODE_OFF)) {
+ DISPLAY_LOGW("%s: request lhbm during power off sequence, reset the state", __func__);
+ mBrightnessController->resetLhbmState();
+ }
+ }
+
Mutex::Autolock lock(mDisplayMutex);
restoreLhbmDisplayConfigLocked();
return ret;
@@ -807,7 +947,7 @@ void ExynosPrimaryDisplay::setLHBMRefreshRateThrottle(const uint32_t delayMs) {
setRefreshRateThrottleNanos(std::chrono::duration_cast<std::chrono::nanoseconds>(
std::chrono::milliseconds(delayMs))
.count(),
- VrrThrottleRequester::LHBM);
+ RrThrottleRequester::LHBM);
}
void ExynosPrimaryDisplay::setEarlyWakeupDisplay() {
@@ -816,20 +956,33 @@ void ExynosPrimaryDisplay::setEarlyWakeupDisplay() {
}
}
-void ExynosPrimaryDisplay::setExpectedPresentTime(uint64_t timestamp) {
- mExpectedPresentTime.store(timestamp);
+void ExynosPrimaryDisplay::setExpectedPresentTime(uint64_t timestamp, int frameIntervalNs) {
+ mExpectedPresentTimeAndInterval.store(std::make_tuple(timestamp, frameIntervalNs));
+ // Forward presentDisplay if there is a listener.
+ const auto presentListener = getPresentListener();
+ if (presentListener) {
+ presentListener->setExpectedPresentTime(timestamp, frameIntervalNs);
+ }
}
uint64_t ExynosPrimaryDisplay::getPendingExpectedPresentTime() {
- if (mExpectedPresentTime.is_dirty()) {
- return mExpectedPresentTime.get();
+ if (mExpectedPresentTimeAndInterval.is_dirty()) {
+ return std::get<0>(mExpectedPresentTimeAndInterval.get());
+ }
+
+ return 0;
+}
+
+int ExynosPrimaryDisplay::getPendingFrameInterval() {
+ if (mExpectedPresentTimeAndInterval.is_dirty()) {
+ return std::get<1>(mExpectedPresentTimeAndInterval.get());
}
return 0;
}
void ExynosPrimaryDisplay::applyExpectedPresentTime() {
- mExpectedPresentTime.clear_dirty();
+ mExpectedPresentTimeAndInterval.clear_dirty();
}
int32_t ExynosPrimaryDisplay::setDisplayIdleTimer(const int32_t timeoutMs) {
@@ -865,7 +1018,7 @@ int32_t ExynosPrimaryDisplay::getDisplayIdleTimerEnabled(bool &enabled) {
return HWC2_ERROR_UNSUPPORTED;
}
- const std::string path = getPanelSysfsPath(getDisplayTypeFromIndex(mIndex)) + "panel_idle";
+ const std::string path = getPanelSysfsPath() + "panel_idle";
std::ifstream ifs(path);
if (!ifs.is_open()) {
ALOGW("%s() unable to open node '%s', error = %s", __func__, path.c_str(), strerror(errno));
@@ -881,7 +1034,7 @@ int32_t ExynosPrimaryDisplay::getDisplayIdleTimerEnabled(bool &enabled) {
}
int32_t ExynosPrimaryDisplay::setDisplayIdleTimerEnabled(const bool enabled) {
- const std::string path = getPanelSysfsPath(getDisplayTypeFromIndex(mIndex)) + "panel_idle";
+ const std::string path = getPanelSysfsPath() + "panel_idle";
std::ofstream ofs(path);
if (!ofs.is_open()) {
ALOGW("%s() unable to open node '%s', error = %s", __func__, path.c_str(), strerror(errno));
@@ -915,7 +1068,7 @@ int32_t ExynosPrimaryDisplay::setDisplayIdleDelayNanos(const int32_t delayNanos,
const int32_t displayIdleDelayMs = std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::nanoseconds(mDisplayIdleDelayNanos))
.count();
- const std::string path = getPanelSysfsPath(DisplayType::DISPLAY_PRIMARY) + "idle_delay_ms";
+ const std::string path = getPanelSysfsPath() + "idle_delay_ms";
std::ofstream ofs(path);
if (!ofs.is_open()) {
ALOGW("%s() unable to open node '%s', error = %s", __func__, path.c_str(), strerror(errno));
@@ -934,8 +1087,7 @@ void ExynosPrimaryDisplay::initDisplayHandleIdleExit() {
return;
}
- const std::string path =
- getPanelSysfsPath(getDisplayTypeFromIndex(mIndex)) + "panel_need_handle_idle_exit";
+ const std::string path = getPanelSysfsPath() + "panel_need_handle_idle_exit";
mDisplayNeedHandleIdleExitOfs.open(path, std::ofstream::out);
if (!mDisplayNeedHandleIdleExitOfs.is_open()) {
ALOGI("%s() '%s' doesn't exist(%s)", __func__, path.c_str(), strerror(errno));
@@ -972,18 +1124,23 @@ void ExynosPrimaryDisplay::setDisplayNeedHandleIdleExit(const bool needed, const
}
void ExynosPrimaryDisplay::handleDisplayIdleEnter(const uint32_t idleTeRefreshRate) {
- Mutex::Autolock lock(mDisplayMutex);
- uint32_t btsRefreshRate = getBtsRefreshRate();
- if (idleTeRefreshRate <= btsRefreshRate) {
- return;
+ {
+ Mutex::Autolock lock(mDisplayMutex);
+ uint32_t btsRefreshRate = getBtsRefreshRate();
+ if (idleTeRefreshRate <= btsRefreshRate) {
+ return;
+ }
}
bool needed = false;
- for (size_t i = 0; i < mLayers.size(); i++) {
- if (mLayers[i]->mOtfMPP && mLayers[i]->mM2mMPP == nullptr &&
- !mLayers[i]->checkBtsCap(idleTeRefreshRate)) {
- needed = true;
- break;
+ {
+ Mutex::Autolock lock(mDRMutex);
+ for (size_t i = 0; i < mLayers.size(); i++) {
+ if (mLayers[i]->mOtfMPP && mLayers[i]->mM2mMPP == nullptr &&
+ !mLayers[i]->checkBtsCap(idleTeRefreshRate)) {
+ needed = true;
+ break;
+ }
}
}
@@ -991,28 +1148,28 @@ void ExynosPrimaryDisplay::handleDisplayIdleEnter(const uint32_t idleTeRefreshRa
}
int ExynosPrimaryDisplay::setMinIdleRefreshRate(const int targetFps,
- const VrrThrottleRequester requester) {
+ const RrThrottleRequester requester) {
int fps = (targetFps <= 0) ? mDefaultMinIdleRefreshRate : targetFps;
- if (requester == VrrThrottleRequester::BRIGHTNESS && mUseBlockingZoneForMinIdleRefreshRate) {
+ if (requester == RrThrottleRequester::BRIGHTNESS && mUseBlockingZoneForMinIdleRefreshRate) {
uint32_t level = mBrightnessController->getBrightnessLevel();
fps = (level < mDbvThresholdForBlockingZone) ? mMinIdleRefreshRateForBlockingZone
: mDefaultMinIdleRefreshRate;
}
std::lock_guard<std::mutex> lock(mMinIdleRefreshRateMutex);
- if (fps == mVrrThrottleFps[toUnderlying(requester)]) return NO_ERROR;
+ if (fps == mRrThrottleFps[toUnderlying(requester)]) return NO_ERROR;
ALOGD("%s requester %u, fps %d", __func__, toUnderlying(requester), fps);
- mVrrThrottleFps[toUnderlying(requester)] = fps;
+ mRrThrottleFps[toUnderlying(requester)] = fps;
int maxMinIdleFps = 0;
- for (uint32_t i = 0; i < toUnderlying(VrrThrottleRequester::MAX); i++) {
- if (mVrrThrottleFps[i] > maxMinIdleFps) {
- maxMinIdleFps = mVrrThrottleFps[i];
+ for (uint32_t i = 0; i < toUnderlying(RrThrottleRequester::MAX); i++) {
+ if (mRrThrottleFps[i] > maxMinIdleFps) {
+ maxMinIdleFps = mRrThrottleFps[i];
}
}
if (maxMinIdleFps == mMinIdleRefreshRate) return NO_ERROR;
- const std::string path = getPanelSysfsPath(getDisplayTypeFromIndex(mIndex)) + "min_vrefresh";
+ const std::string path = getPanelSysfsPath() + "min_vrefresh";
std::ofstream ofs(path);
if (!ofs.is_open()) {
ALOGW("%s Unable to open node '%s', error = %s", __func__, path.c_str(), strerror(errno));
@@ -1028,7 +1185,7 @@ int ExynosPrimaryDisplay::setMinIdleRefreshRate(const int targetFps,
}
int ExynosPrimaryDisplay::setRefreshRateThrottleNanos(const int64_t delayNanos,
- const VrrThrottleRequester requester) {
+ const RrThrottleRequester requester) {
ATRACE_CALL();
if (delayNanos < 0) {
ALOGW("%s() set invalid delay(%" PRId64 ")", __func__, delayNanos);
@@ -1036,15 +1193,15 @@ int ExynosPrimaryDisplay::setRefreshRateThrottleNanos(const int64_t delayNanos,
}
std::lock_guard<std::mutex> lock(mIdleRefreshRateThrottleMutex);
- if (delayNanos == mVrrThrottleNanos[toUnderlying(requester)]) return NO_ERROR;
+ if (delayNanos == mRrThrottleNanos[toUnderlying(requester)]) return NO_ERROR;
ALOGI("%s() requester(%u) set delay to %" PRId64 "ns", __func__, toUnderlying(requester),
delayNanos);
- mVrrThrottleNanos[toUnderlying(requester)] = delayNanos;
+ mRrThrottleNanos[toUnderlying(requester)] = delayNanos;
int64_t maxDelayNanos = 0;
- for (uint32_t i = 0; i < toUnderlying(VrrThrottleRequester::MAX); i++) {
- if (mVrrThrottleNanos[i] > maxDelayNanos) {
- maxDelayNanos = mVrrThrottleNanos[i];
+ for (uint32_t i = 0; i < toUnderlying(RrThrottleRequester::MAX); i++) {
+ if (mRrThrottleNanos[i] > maxDelayNanos) {
+ maxDelayNanos = mRrThrottleNanos[i];
}
}
@@ -1054,7 +1211,7 @@ int ExynosPrimaryDisplay::setRefreshRateThrottleNanos(const int64_t delayNanos,
}
mRefreshRateDelayNanos = maxDelayNanos;
- return setDisplayIdleDelayNanos(mRefreshRateDelayNanos, DispIdleTimerRequester::VRR_THROTTLE);
+ return setDisplayIdleDelayNanos(mRefreshRateDelayNanos, DispIdleTimerRequester::RR_THROTTLE);
}
void ExynosPrimaryDisplay::dump(String8 &result) {
@@ -1074,13 +1231,13 @@ void ExynosPrimaryDisplay::dump(String8 &result) {
result.appendFormat("\n");
}
- for (uint32_t i = 0; i < toUnderlying(VrrThrottleRequester::MAX); i++) {
- result.appendFormat("\t[%u] vote to %d hz\n", i, mVrrThrottleFps[i]);
+ for (uint32_t i = 0; i < toUnderlying(RrThrottleRequester::MAX); i++) {
+ result.appendFormat("\t[%u] vote to %d hz\n", i, mRrThrottleFps[i]);
}
result.appendFormat("Refresh rate delay: %" PRId64 " ns\n", mRefreshRateDelayNanos);
- for (uint32_t i = 0; i < toUnderlying(VrrThrottleRequester::MAX); i++) {
- result.appendFormat("\t[%u] vote to %" PRId64 " ns\n", i, mVrrThrottleNanos[i]);
+ for (uint32_t i = 0; i < toUnderlying(RrThrottleRequester::MAX); i++) {
+ result.appendFormat("\t[%u] vote to %" PRId64 " ns\n", i, mRrThrottleNanos[i]);
}
result.appendFormat("\n");
}
@@ -1154,8 +1311,8 @@ void ExynosPrimaryDisplay::updateAppliedActiveConfig(const hwc2_config_t newConf
mAppliedActiveConfig = newConfig;
}
-void ExynosPrimaryDisplay::checkBtsReassignResource(const uint32_t vsyncPeriod,
- const uint32_t btsVsyncPeriod) {
+void ExynosPrimaryDisplay::checkBtsReassignResource(const int32_t vsyncPeriod,
+ const int32_t btsVsyncPeriod) {
ATRACE_CALL();
uint32_t refreshRate = static_cast<uint32_t>(round(nsecsPerSec / vsyncPeriod * 0.1f) * 10);
@@ -1195,3 +1352,23 @@ int32_t ExynosPrimaryDisplay::setDbmState(bool enabled) {
mBrightnessController->processDimBrightness(enabled);
return NO_ERROR;
}
+
+PresentListener* ExynosPrimaryDisplay::getPresentListener() {
+ if (mVariableRefreshRateController) {
+ return mVariableRefreshRateController.get();
+ }
+ return nullptr;
+}
+
+VsyncListener* ExynosPrimaryDisplay::getVsyncListener() {
+ if (mVariableRefreshRateController) {
+ return mVariableRefreshRateController.get();
+ }
+ return nullptr;
+}
+
+void ExynosPrimaryDisplay::onConfigChange(int configId) {
+ if (mVariableRefreshRateController) {
+ return mVariableRefreshRateController->setActiveVrrConfiguration(configId);
+ }
+}