summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--hwc3/Android.mk2
-rw-r--r--libhwc2.1/Android.mk6
-rw-r--r--libhwc2.1/ExynosHWC.cpp29
-rw-r--r--libhwc2.1/histogram_mediator.cpp29
-rw-r--r--libhwc2.1/histogram_mediator.h6
-rw-r--r--libhwc2.1/libdevice/BrightnessController.cpp134
-rw-r--r--libhwc2.1/libdevice/BrightnessController.h49
-rw-r--r--libhwc2.1/libdevice/ExynosDisplay.cpp32
-rw-r--r--libhwc2.1/libdevice/ExynosDisplay.h6
-rw-r--r--libhwc2.1/libdevice/ExynosLayer.h12
-rw-r--r--libhwc2.1/libdisplayinterface/ExynosDisplayDrmInterface.cpp42
-rw-r--r--libhwc2.1/libdisplayinterface/ExynosDisplayDrmInterface.h2
-rw-r--r--libhwc2.1/libhwcService/ExynosHWCService.cpp13
-rw-r--r--libhwc2.1/libhwcService/ExynosHWCService.h2
-rw-r--r--libhwc2.1/libhwcService/IExynosHWC.cpp20
-rw-r--r--libhwc2.1/libhwcService/IExynosHWC.h1
-rw-r--r--libhwc2.1/libhwchelper/ExynosHWCHelper.cpp5
-rw-r--r--libhwc2.1/libmaindisplay/ExynosPrimaryDisplay.cpp111
-rw-r--r--libhwc2.1/libmaindisplay/ExynosPrimaryDisplay.h3
-rw-r--r--libhwc2.1/libresource/ExynosResourceManager.cpp2
-rw-r--r--libhwc2.1/pixel-display-default.xml2
-rw-r--r--libhwc2.1/pixel-display-secondary.xml2
-rw-r--r--libhwc2.1/pixel-display.cpp17
-rw-r--r--libhwc2.1/pixel-display.h2
24 files changed, 409 insertions, 120 deletions
diff --git a/hwc3/Android.mk b/hwc3/Android.mk
index f233aab..43538d3 100644
--- a/hwc3/Android.mk
+++ b/hwc3/Android.mk
@@ -35,7 +35,7 @@ LOCAL_SHARED_LIBRARIES := android.hardware.graphics.composer3-V1-ndk \
android.hardware.graphics.composer@2.1-resources \
android.hardware.graphics.composer@2.2-resources \
android.hardware.graphics.composer@2.4 \
- com.google.hardware.pixel.display-V6-ndk \
+ com.google.hardware.pixel.display-V7-ndk \
libbase \
libbinder \
libbinder_ndk \
diff --git a/libhwc2.1/Android.mk b/libhwc2.1/Android.mk
index 5b0d781..71391cd 100644
--- a/libhwc2.1/Android.mk
+++ b/libhwc2.1/Android.mk
@@ -68,7 +68,7 @@ LOCAL_SHARED_LIBRARIES := liblog libcutils libhardware \
android.hardware.power-V2-ndk pixel-power-ext-V1-ndk
LOCAL_SHARED_LIBRARIES += android.hardware.graphics.composer3-V1-ndk \
- com.google.hardware.pixel.display-V6-ndk \
+ com.google.hardware.pixel.display-V7-ndk \
libbinder_ndk \
libbase \
libpng \
@@ -160,7 +160,7 @@ LOCAL_SHARED_LIBRARIES := liblog libcutils libutils libbinder libexynosdisplay l
android.hardware.graphics.allocator@2.0 \
android.hardware.graphics.mapper@2.0
-LOCAL_SHARED_LIBRARIES += com.google.hardware.pixel.display-V6-ndk \
+LOCAL_SHARED_LIBRARIES += com.google.hardware.pixel.display-V7-ndk \
libbinder_ndk \
libbase
@@ -221,7 +221,7 @@ LOCAL_SHARED_LIBRARIES := liblog libcutils libutils libexynosdisplay libacryl \
libui
LOCAL_SHARED_LIBRARIES += android.hardware.graphics.composer3-V1-ndk \
- com.google.hardware.pixel.display-V6-ndk \
+ com.google.hardware.pixel.display-V7-ndk \
libbinder_ndk \
libbase
diff --git a/libhwc2.1/ExynosHWC.cpp b/libhwc2.1/ExynosHWC.cpp
index 8b3d9a4..fee44ed 100644
--- a/libhwc2.1/ExynosHWC.cpp
+++ b/libhwc2.1/ExynosHWC.cpp
@@ -1149,15 +1149,34 @@ int32_t exynos_SetActiveConfigWithConstraints(hwc2_device_t* dev, hwc2_display_t
{
HDEBUGLOGD(eDebugDisplayConfig, "%s, %d", __func__, config);
ExynosDevice *exynosDevice = checkDevice(dev);
+ if (!exynosDevice) {
+ return HWC2_ERROR_BAD_DISPLAY;
+ }
- if (exynosDevice) {
- ExynosDisplay *exynosDisplay = checkDisplay(exynosDevice, display);
- if (exynosDisplay) {
- return exynosDisplay->setActiveConfigWithConstraints(config, vsyncPeriodChangeConstraints, outTimeline);
+ ExynosDisplay *exynosDisplay = checkDisplay(exynosDevice, display);
+ if (!exynosDisplay) {
+ return HWC2_ERROR_BAD_DISPLAY;
+ }
+
+ const auto prevXres = exynosDisplay->mXres, prevYres = exynosDisplay->mYres;
+ auto ret = exynosDisplay->setActiveConfigWithConstraints(config,
+ vsyncPeriodChangeConstraints,
+ outTimeline);
+ if (ret != HWC2_ERROR_NONE) {
+ ALOGE("exynos_SetActiveConfigWithConstraints() failed config(%d)", config);
+ return ret;
+ }
+
+ // when resolution is changed, HWC2 updates the property
+ if (prevXres != exynosDisplay->mDisplayConfigs[config].width ||
+ prevYres != exynosDisplay->mDisplayConfigs[config].height) {
+ if ((ret = exynosDisplay->setBootDisplayConfig(config)) != HWC2_ERROR_NONE) {
+ ALOGE("setBootDisplayConfig() failed when setActiveConfigWithConstraints()");
+ return ret;
}
}
- return HWC2_ERROR_BAD_DISPLAY;
+ return HWC2_ERROR_NONE;
}
int32_t exynos_SetAutoLowLatencyMode(hwc2_device_t* dev, hwc2_display_t display, bool on)
diff --git a/libhwc2.1/histogram_mediator.cpp b/libhwc2.1/histogram_mediator.cpp
index c917783..991b972 100644
--- a/libhwc2.1/histogram_mediator.cpp
+++ b/libhwc2.1/histogram_mediator.cpp
@@ -19,8 +19,9 @@ histogram::HistogramMediator::HistogramMediator(ExynosDisplay *display) {
mDisplay = display;
ExynosDisplayDrmInterface *moduleDisplayInterface =
static_cast<ExynosDisplayDrmInterface *>(display->mDisplayInterface.get());
+ mIDLHistogram = std::make_shared<HistogramReceiver>();
- moduleDisplayInterface->registerHistogramInfo(static_cast<IDLHistogram *>(&mIDLHistogram));
+ moduleDisplayInterface->registerHistogramInfo(mIDLHistogram);
moduleDisplayInterface->getPanelResolution();
}
uint32_t histogram::HistogramMediator::getFrameCount() {
@@ -60,8 +61,8 @@ histogram::HistogramErrorCode histogram::HistogramMediator::requestHist() {
return histogram::HistogramErrorCode::ENABLE_HIST_ERROR;
}
{
- std::unique_lock<std::mutex> lk(mIDLHistogram.mDataCollectingMutex);
- mIDLHistogram.mHistReq_pending = true;
+ std::unique_lock<std::mutex> lk(mIDLHistogram->mDataCollectingMutex);
+ mIDLHistogram->mHistReq_pending = true;
}
return histogram::HistogramErrorCode::NONE;
}
@@ -94,25 +95,25 @@ int histogram::HistogramMediator::calculateThreshold(const RoiRect &roi) {
histogram::HistogramErrorCode histogram::HistogramMediator::setRoiWeightThreshold(
const RoiRect roi, const Weight weight, const HistogramPos pos) {
int threshold = calculateThreshold(roi);
- mIDLHistogram.setHistogramROI((uint16_t)roi.left, (uint16_t)roi.top,
- (uint16_t)(roi.right - roi.left),
- (uint16_t)(roi.bottom - roi.top));
- mIDLHistogram.setHistogramWeights(weight.weightR, weight.weightG, weight.weightB);
- mIDLHistogram.setHistogramThreshold(threshold);
- mIDLHistogram.setHistogramPos(pos);
+ mIDLHistogram->setHistogramROI((uint16_t)roi.left, (uint16_t)roi.top,
+ (uint16_t)(roi.right - roi.left),
+ (uint16_t)(roi.bottom - roi.top));
+ mIDLHistogram->setHistogramWeights(weight.weightR, weight.weightG, weight.weightB);
+ mIDLHistogram->setHistogramThreshold(threshold);
+ mIDLHistogram->setHistogramPos(pos);
return histogram::HistogramErrorCode::NONE;
}
histogram::HistogramErrorCode histogram::HistogramMediator::collectRoiLuma(
std::vector<char16_t> *buf) {
- std::unique_lock<std::mutex> lk(mIDLHistogram.mDataCollectingMutex);
+ std::unique_lock<std::mutex> lk(mIDLHistogram->mDataCollectingMutex);
- mIDLHistogram.mHistData_cv.wait_for(lk, std::chrono::milliseconds(50), [this]() {
- return (!isDisplayPowerOff() && !mIDLHistogram.mHistReq_pending);
+ mIDLHistogram->mHistData_cv.wait_for(lk, std::chrono::milliseconds(50), [this]() {
+ return (!isDisplayPowerOff() && !mIDLHistogram->mHistReq_pending);
});
- if (mIDLHistogram.mHistReq_pending == false) setSampleFrameCounter(getFrameCount());
- buf->assign(mIDLHistogram.mHistData, mIDLHistogram.mHistData + HISTOGRAM_BINS_SIZE);
+ if (mIDLHistogram->mHistReq_pending == false) setSampleFrameCounter(getFrameCount());
+ buf->assign(mIDLHistogram->mHistData, mIDLHistogram->mHistData + HISTOGRAM_BINS_SIZE);
return histogram::HistogramErrorCode::NONE;
}
diff --git a/libhwc2.1/histogram_mediator.h b/libhwc2.1/histogram_mediator.h
index 84f77a2..eac4c98 100644
--- a/libhwc2.1/histogram_mediator.h
+++ b/libhwc2.1/histogram_mediator.h
@@ -66,7 +66,7 @@ public:
const HistogramPos pos);
RoiRect calRoi(RoiRect roi);
struct HistogramReceiver : public IDLHistogram {
- HistogramReceiver() : mHistData() {}
+ HistogramReceiver() : mHistData(){};
void callbackHistogram(char16_t *bin) override;
uint16_t mHistData[HISTOGRAM_BINS_SIZE]; // luma buffer
std::condition_variable mHistData_cv; // for pullback data sync ctrl
@@ -76,11 +76,11 @@ public:
uint32_t getFrameCount();
void setSampleFrameCounter(int32_t id) { mSampledFrameCounter = id; }
uint32_t getSampleFrameCounter() { return mSampledFrameCounter; }
- bool histRequested() { return mIDLHistogram.mHistReq_pending; }
+ bool histRequested() { return mIDLHistogram->mHistReq_pending; }
private:
int calculateThreshold(const RoiRect &roi);
- HistogramReceiver mIDLHistogram;
+ std::shared_ptr<HistogramReceiver> mIDLHistogram;
ExynosDisplay *mDisplay = nullptr;
uint32_t mSampledFrameCounter = 0;
};
diff --git a/libhwc2.1/libdevice/BrightnessController.cpp b/libhwc2.1/libdevice/BrightnessController.cpp
index a18c499..1057629 100644
--- a/libhwc2.1/libdevice/BrightnessController.cpp
+++ b/libhwc2.1/libdevice/BrightnessController.cpp
@@ -34,6 +34,7 @@ BrightnessController::BrightnessController(int32_t panelIndex, std::function<voi
mLhbm(false),
mSdrDim(false),
mPrevSdrDim(false),
+ mDimBrightnessReq(false),
mFrameRefresh(refresh),
mHdrLayerState(HdrLayerState::kHdrNone),
mUpdateDcLhbm(updateDcLhbm) {
@@ -106,11 +107,15 @@ void BrightnessController::initBrightnessSysfs() {
}
void BrightnessController::initCabcSysfs() {
+ mCabcSupport = property_get_bool("vendor.display.cabc.supported", false);
+ if (!mCabcSupport) return;
+
String8 nodeName;
nodeName.appendFormat(kLocalCabcModeFileNode, mPanelIndex);
+
mCabcModeOfs.open(nodeName.string(), std::ofstream::out);
if (mCabcModeOfs.fail()) {
- ALOGW("%s %s fail to open", __func__, nodeName.string());
+ ALOGE("%s %s fail to open", __func__, nodeName.string());
mCabcModeOfs.close();
return;
}
@@ -153,6 +158,21 @@ void BrightnessController::initBrightnessTable(const DrmDevice& drmDevice,
mBrightnessIntfSupported = true;
drmModeFreePropertyBlob(blob);
+
+ String8 nodeName;
+ nodeName.appendFormat(kDimBrightnessFileNode, mPanelIndex);
+
+ std::ifstream ifsDimBrightness(nodeName.string());
+ if (ifsDimBrightness.fail()) {
+ ALOGW("%s fail to open %s", __func__, nodeName.string());
+ } else {
+ ifsDimBrightness >> mDimBrightness;
+ ifsDimBrightness.close();
+ if (mDimBrightness >= mBrightnessTable[toUnderlying(BrightnessRange::NORMAL)].mBklStart)
+ mDimBrightness = 0;
+ }
+ mDbmSupported = !!mDimBrightness;
+ ALOGI("%s mDimBrightness=%d, mDbmSupported=%d", __func__, mDimBrightness, mDbmSupported);
}
int BrightnessController::processEnhancedHbm(bool on) {
@@ -202,20 +222,14 @@ int BrightnessController::processDisplayBrightness(float brightness, const nsecs
// check if it will go drm path for below cases.
// case 1: hbm state will change
// case 2: for hwc3, brightness command could apply at next present if possible
- if (mGhbmSupported || waitPresent) {
+ if (queryBrightness(brightness, &ghbm, &level) == NO_ERROR) {
// ghbm on/off always go drm path
- if (mGhbmSupported) {
- if (queryBrightness(brightness, &ghbm, &level)) {
- ALOGE("%s failed to convert brightness %f", __func__, brightness);
- return -EINVAL;
- }
- // check if this will cause a hbm transition
- if ((mGhbm.get() != HbmMode::OFF) != ghbm) {
- // this brightness change will go drm path
- updateStates();
- mFrameRefresh(); // force next frame to update brightness
- return NO_ERROR;
- }
+ // check if this will cause a hbm transition
+ if (mGhbmSupported && (mGhbm.get() != HbmMode::OFF) != ghbm) {
+ // this brightness change will go drm path
+ updateStates();
+ mFrameRefresh(); // force next frame to update brightness
+ return NO_ERROR;
}
// there will be a Present to apply this brightness change
if (waitPresent) {
@@ -234,13 +248,13 @@ int BrightnessController::processDisplayBrightness(float brightness, const nsecs
if (mUncheckedGbhmRequest) {
ATRACE_NAME("check_ghbm_mode");
checkSysfsStatus(kGlobalHbmModeFileNode,
- std::to_string(toUnderlying(mPendingGhbmStatus.load())), vsyncNs * 5);
+ {std::to_string(toUnderlying(mPendingGhbmStatus.load()))}, vsyncNs * 5);
mUncheckedGbhmRequest = false;
}
if (mUncheckedLhbmRequest) {
ATRACE_NAME("check_lhbm_mode");
- checkSysfsStatus(kLocalHbmModeFileNode, std::to_string(mPendingLhbmStatus), vsyncNs * 5);
+ checkSysfsStatus(kLocalHbmModeFileNode, {std::to_string(mPendingLhbmStatus)}, vsyncNs * 5);
mUncheckedLhbmRequest = false;
}
@@ -279,7 +293,7 @@ int BrightnessController::applyPendingChangeViaSysfs(const nsecs_t vsyncNs) {
if (mUncheckedBlRequest) {
ATRACE_NAME("check_bl_value");
- checkSysfsStatus(BRIGHTNESS_SYSFS_NODE, std::to_string(mPendingBl), vsyncNs * 5);
+ checkSysfsStatus(BRIGHTNESS_SYSFS_NODE, {std::to_string(mPendingBl)}, vsyncNs * 5);
mUncheckedBlRequest = false;
}
@@ -327,6 +341,16 @@ int BrightnessController::processInstantHbm(bool on) {
return NO_ERROR;
}
+int BrightnessController::processDimBrightness(bool on) {
+ std::lock_guard<std::recursive_mutex> lock(mBrightnessMutex);
+ mDimBrightnessReq.store(on);
+ if (mDimBrightnessReq.is_dirty()) {
+ updateStates();
+ ALOGI("%s request = %d", __func__, mDimBrightnessReq.get());
+ }
+ return NO_ERROR;
+}
+
float BrightnessController::getSdrDimRatioForInstantHbm() {
if (!mBrightnessIntfSupported || !mGhbmSupported) {
return 1.0f;
@@ -358,9 +382,10 @@ float BrightnessController::getSdrDimRatioForInstantHbm() {
}
void BrightnessController::onClearDisplay() {
+ resetLhbmState();
+
std::lock_guard<std::recursive_mutex> lock(mBrightnessMutex);
mEnhanceHbmReq.reset(false);
- mLhbmReq.reset(false);
mBrightnessFloatReq.reset(-1);
mInstantHbmReq.reset(false);
@@ -373,9 +398,6 @@ void BrightnessController::onClearDisplay() {
if (mBrightnessDimmingUsage == BrightnessDimmingUsage::NORMAL) {
mDimming.store(true);
}
- mLhbm.reset(false);
-
- mLhbmBrightnessAdj = false;
std::lock_guard<std::recursive_mutex> lock1(mCabcModeMutex);
mCabcMode.reset(false);
@@ -594,11 +616,11 @@ int BrightnessController::updateStates() {
mInstantHbmReq.clear_dirty();
mSdrDim.clear_dirty();
mPrevSdrDim.clear_dirty();
+ mDimBrightnessReq.clear_dirty();
if (mBrightnessLevel.is_dirty() || mDimming.is_dirty() || mGhbm.is_dirty() ||
mLhbm.is_dirty()) {
- ALOGI("level=%d, DimmingOn=%d, Hbm=%d, LhbmOn=%d.", mBrightnessLevel.get(), mDimming.get(),
- mGhbm.get(), mLhbm.get());
+ printBrightnessStates("drm");
}
return NO_ERROR;
}
@@ -609,6 +631,15 @@ int BrightnessController::queryBrightness(float brightness, bool *ghbm, uint32_t
return HWC2_ERROR_UNSUPPORTED;
}
+ if (mBrightnessTable[toUnderlying(BrightnessRange::NORMAL)].mBklStart == 0 &&
+ mBrightnessTable[toUnderlying(BrightnessRange::NORMAL)].mBklEnd == 0 &&
+ mBrightnessTable[toUnderlying(BrightnessRange::NORMAL)].mBriStart == 0 &&
+ mBrightnessTable[toUnderlying(BrightnessRange::NORMAL)].mBriEnd == 0 &&
+ mBrightnessTable[toUnderlying(BrightnessRange::NORMAL)].mNitsStart == 0 &&
+ mBrightnessTable[toUnderlying(BrightnessRange::NORMAL)].mNitsEnd == 0) {
+ return HWC2_ERROR_UNSUPPORTED;
+ }
+
if (brightness < 0) {
// screen off
if (ghbm) {
@@ -644,7 +675,10 @@ int BrightnessController::queryBrightness(float brightness, bool *ghbm, uint32_t
*nits = norm * nSpan + mBrightnessTable[i].mNitsStart;
}
}
-
+ if ((i == toUnderlying(BrightnessRange::NORMAL)) && mDbmSupported &&
+ (mDimBrightnessReq.get() == true) && (*level == mBrightnessTable[i].mBklStart)) {
+ *level = mDimBrightness;
+ }
return NO_ERROR;
}
}
@@ -653,9 +687,13 @@ int BrightnessController::queryBrightness(float brightness, bool *ghbm, uint32_t
}
// Return immediately if it's already in the status. Otherwise poll the status
-int BrightnessController::checkSysfsStatus(const char* file, const std::string& expectedValue,
+int BrightnessController::checkSysfsStatus(const char* file,
+ const std::vector<std::string>& expectedValue,
const nsecs_t timeoutNs) {
ATRACE_CALL();
+
+ if (expectedValue.size() == 0) return false;
+
char buf[16];
String8 nodeName;
nodeName.appendFormat(file, mPanelIndex);
@@ -668,8 +706,11 @@ int BrightnessController::checkSysfsStatus(const char* file, const std::string&
}
// '- 1' to remove trailing '\n'
- if (std::string_view(buf, size - 1) == expectedValue) {
+ std::string val = std::string(buf, size - 1);
+ if (std::find(expectedValue.begin(), expectedValue.end(), val) != expectedValue.end()) {
return true;
+ } else if (timeoutNs == 0) {
+ return false;
}
struct pollfd pfd;
@@ -699,12 +740,20 @@ int BrightnessController::checkSysfsStatus(const char* file, const std::string&
lseek(fd.get(), 0, SEEK_SET);
size = read(fd.get(), buf, sizeof(buf));
if (size > 0) {
- if (std::string_view(buf, size - 1) == expectedValue) {
+ val = std::string(buf, size - 1);
+ if (std::find(expectedValue.begin(), expectedValue.end(), val) !=
+ expectedValue.end()) {
ret = 0;
} else {
- buf[size - 1] = 0;
- ALOGE("%s read %s expected %s after notified", __func__, buf,
- expectedValue.c_str());
+ std::string values;
+ for (auto& s : expectedValue) {
+ values += s + std::string(" ");
+ }
+ if (values.size() > 0) {
+ values.resize(values.size() - 1);
+ }
+ ALOGE("%s read %s expected %s after notified", __func__, val.c_str(),
+ values.c_str());
ret = EINVAL;
}
} else {
@@ -726,13 +775,20 @@ int BrightnessController::checkSysfsStatus(const char* file, const std::string&
return ret == NO_ERROR;
}
+void BrightnessController::resetLhbmState() {
+ std::lock_guard<std::recursive_mutex> lock(mBrightnessMutex);
+ mLhbmReq.reset(false);
+ mLhbm.reset(false);
+ mLhbmBrightnessAdj = false;
+}
+
void BrightnessController::setOutdoorVisibility(LbeState state) {
std::lock_guard<std::recursive_mutex> lock(mCabcModeMutex);
mOutdoorVisibility = (state != LbeState::OFF);
}
int BrightnessController::updateCabcMode() {
- if (mCabcModeOfs.fail()) return HWC2_ERROR_UNSUPPORTED;
+ if (!mCabcSupport || mCabcModeOfs.fail()) return HWC2_ERROR_UNSUPPORTED;
std::lock_guard<std::recursive_mutex> lock(mCabcModeMutex);
bool mode = (!(isHdrLayerOn() || mOutdoorVisibility));
@@ -763,8 +819,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());
+ printBrightnessStates("sysfs");
}
return NO_ERROR;
@@ -819,6 +874,15 @@ void BrightnessController::parseHbmModeEnums(const DrmProperty& property) {
}
}
+/*
+ * WARNING: This print is parsed by Battery Historian. Consult with the Battery
+ * Historian team before modifying (b/239640926).
+ */
+void BrightnessController::printBrightnessStates(const char* path) {
+ ALOGI("path=%s, id=%d, level=%d, DimmingOn=%d, Hbm=%d, LhbmOn=%d", path ?: "unknown",
+ mPanelIndex, mBrightnessLevel.get(), mDimming.get(), mGhbm.get(), mLhbm.get());
+}
+
void BrightnessController::dump(String8& result) {
std::lock_guard<std::recursive_mutex> lock(mBrightnessMutex);
@@ -827,9 +891,9 @@ void BrightnessController::dump(String8& result) {
"lhbm supported %d, ghbm supported %d\n", mBrightnessOfs.is_open(),
mMaxBrightness, mBrightnessIntfSupported, mLhbmSupported, mGhbmSupported);
result.appendFormat("\trequests: enhance hbm %d, lhbm %d, "
- "brightness %f, instant hbm %d\n",
+ "brightness %f, instant hbm %d, DimBrightness %d\n",
mEnhanceHbmReq.get(), mLhbmReq.get(), mBrightnessFloatReq.get(),
- mInstantHbmReq.get());
+ mInstantHbmReq.get(), mDimBrightnessReq.get());
result.appendFormat("\tstates: brighntess level %d, ghbm %d, dimming %d, lhbm %d",
mBrightnessLevel.get(), mGhbm.get(), mDimming.get(), mLhbm.get());
result.appendFormat("\thdr layer state %d, unchecked lhbm request %d(%d), "
diff --git a/libhwc2.1/libdevice/BrightnessController.h b/libhwc2.1/libdevice/BrightnessController.h
index e1662d4..1a19758 100644
--- a/libhwc2.1/libdevice/BrightnessController.h
+++ b/libhwc2.1/libdevice/BrightnessController.h
@@ -65,6 +65,8 @@ public:
int processEnhancedHbm(bool on);
int processDisplayBrightness(float bl, const nsecs_t vsyncNs, bool waitPresent = false);
int processLocalHbm(bool on);
+ int processDimBrightness(bool on);
+ bool isDbmSupported() { return mDbmSupported; }
int applyPendingChangeViaSysfs(const nsecs_t vsyncNs);
bool validateLayerBrightness(float brightness);
@@ -112,8 +114,9 @@ public:
std::lock_guard<std::recursive_mutex> lock(mBrightnessMutex);
return mLhbm.get();
}
- int checkSysfsStatus(const char *file, const std::string &expectedValue,
+ int checkSysfsStatus(const char *file, const std::vector<std::string>& expectedValue,
const nsecs_t timeoutNs);
+ void resetLhbmState();
uint32_t getBrightnessLevel() {
std::lock_guard<std::recursive_mutex> lock(mBrightnessMutex);
@@ -159,16 +162,39 @@ public:
const BrightnessTable *getBrightnessTable() { return mBrightnessTable; }
+ /*
+ * WARNING: This enum is parsed by Battery Historian. Add new values, but
+ * do not modify/remove existing ones. Alternatively, consult with the
+ * Battery Historian team (b/239640926).
+ */
enum class BrightnessRange : uint32_t {
NORMAL = 0,
- HBM,
+ HBM = 1,
MAX,
};
+ /*
+ * WARNING: This enum is parsed by Battery Historian. Add new values, but
+ * do not modify/remove existing ones. Alternatively, consult with the
+ * Battery Historian team (b/239640926).
+ */
enum class HbmMode {
OFF = 0,
- ON_IRC_ON,
- ON_IRC_OFF,
+ ON_IRC_ON = 1,
+ ON_IRC_OFF = 2,
+ };
+
+ /*
+ * LHBM command need take a couple of frames to become effective
+ * DISABLED - finish sending disabling command to panel
+ * ENABLED - panel finishes boosting brightness to the peak value
+ * ENABLING - finish sending enabling command to panel (panel begins boosting brightness)
+ * Note: the definition should be consistent with kernel driver
+ */
+ enum class LhbmMode {
+ DISABLED = 0,
+ ENABLED = 1,
+ ENABLING = 2,
};
/*
@@ -176,15 +202,22 @@ public:
* NORMAL- enable dimming
* HBM- enable dimming only for hbm transition
* NONE- disable dimming
+ *
+ * WARNING: This enum is parsed by Battery Historian. Add new values, but
+ * do not modify/remove existing ones. Alternatively, consult with the
+ * Battery Historian team (b/239640926).
*/
enum class BrightnessDimmingUsage {
NORMAL = 0,
- HBM,
+ HBM = 1,
NONE,
};
static constexpr const char *kLocalHbmModeFileNode =
"/sys/class/backlight/panel%d-backlight/local_hbm_mode";
+ static constexpr const char* kDimBrightnessFileNode =
+ "/sys/class/backlight/panel%d-backlight/dim_brightness";
+
private:
// sync brightness change for mixed composition when there is more than 50% luminance change.
// The percentage is calculated as:
@@ -216,8 +249,11 @@ private:
void parseHbmModeEnums(const DrmProperty& property);
+ void printBrightnessStates(const char* path) REQUIRES(mBrightnessMutex);
+
bool mLhbmSupported = false;
bool mGhbmSupported = false;
+ bool mDbmSupported = false;
bool mBrightnessIntfSupported = false;
BrightnessTable mBrightnessTable[toUnderlying(BrightnessRange::MAX)];
@@ -238,6 +274,7 @@ private:
CtrlValue<bool> mLhbm GUARDED_BY(mBrightnessMutex);
CtrlValue<bool> mSdrDim GUARDED_BY(mBrightnessMutex);
CtrlValue<bool> mPrevSdrDim GUARDED_BY(mBrightnessMutex);
+ CtrlValue<bool> mDimBrightnessReq GUARDED_BY(mBrightnessMutex);
// Indicating if the last LHBM on has changed the brightness level
bool mLhbmBrightnessAdj = false;
@@ -269,6 +306,8 @@ private:
std::ofstream mBrightnessOfs;
uint32_t mMaxBrightness = 0; // read from sysfs
std::ofstream mCabcModeOfs;
+ bool mCabcSupport = false;
+ uint32_t mDimBrightness = 0;
// Note IRC or dimming is not in consideration for now.
float mDisplayWhitePointNits = 0;
diff --git a/libhwc2.1/libdevice/ExynosDisplay.cpp b/libhwc2.1/libdevice/ExynosDisplay.cpp
index 987ec7c..354d75c 100644
--- a/libhwc2.1/libdevice/ExynosDisplay.cpp
+++ b/libhwc2.1/libdevice/ExynosDisplay.cpp
@@ -3214,7 +3214,7 @@ int32_t ExynosDisplay::getDisplayRequests(
for (int32_t i = mClientCompositionInfo.mFirstIndex; i < mClientCompositionInfo.mLastIndex; i++) {
ExynosLayer *layer = mLayers[i];
- if (layer->mOverlayPriority >= ePriorityHigh) {
+ if (layer->needClearClientTarget()) {
if ((outLayers != NULL) && (outLayerRequests != NULL)) {
if (requestNum >= *outNumElements)
return -1;
@@ -4902,8 +4902,10 @@ int32_t ExynosDisplay::addClientCompositionLayer(uint32_t layerIndex)
/* handle sandwiched layers */
for (uint32_t i = (uint32_t)mClientCompositionInfo.mFirstIndex + 1; i < (uint32_t)mClientCompositionInfo.mLastIndex; i++) {
ExynosLayer *layer = mLayers[i];
- if (layer->mOverlayPriority >= ePriorityHigh) {
- DISPLAY_LOGD(eDebugResourceManager, "\t[%d] layer has high or max priority (%d)", i, layer->mOverlayPriority);
+ if (layer->needClearClientTarget()) {
+ DISPLAY_LOGD(eDebugResourceManager,
+ "\t[%d] layer is opaque and has high or max priority (%d)", i,
+ layer->mOverlayPriority);
continue;
}
if (layer->mValidateCompositionType != HWC2_COMPOSITION_CLIENT)
@@ -6041,3 +6043,27 @@ bool ExynosDisplay::isMixedComposition() {
}
return false;
}
+
+int ExynosDisplay::lookupDisplayConfigs(const int32_t &width,
+ const int32_t &height,
+ const int32_t &fps,
+ int32_t *outConfig) {
+ if (!fps)
+ 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;
+
+ for (auto const& [config, mode] : mDisplayConfigs) {
+ long delta = abs(vsyncPeriod - mode.vsyncPeriod);
+ if ((width == mode.width) && (height == mode.height) && (delta < nsecsPerMs)) {
+ ALOGD("%s: found display config for mode: %dx%d@%d=%d",
+ __func__, width, height, fps, config);
+ *outConfig = config;
+ return HWC2_ERROR_NONE;
+ }
+ }
+ return HWC2_ERROR_BAD_CONFIG;
+}
diff --git a/libhwc2.1/libdevice/ExynosDisplay.h b/libhwc2.1/libdevice/ExynosDisplay.h
index 0132415..ad7977b 100644
--- a/libhwc2.1/libdevice/ExynosDisplay.h
+++ b/libhwc2.1/libdevice/ExynosDisplay.h
@@ -1209,6 +1209,8 @@ class ExynosDisplay {
virtual PanelCalibrationStatus getPanelCalibrationStatus() {
return PanelCalibrationStatus::UNCALIBRATED;
}
+ virtual bool isDbmSupported() { return false; }
+ virtual int32_t setDbmState(bool __unused enabled) { return NO_ERROR; }
/* getDisplayPreAssignBit support mIndex up to 1.
It supports only dual LCD and 2 external displays */
@@ -1260,6 +1262,10 @@ class ExynosDisplay {
// check if there are any dimmed layers
bool isMixedComposition();
bool isPriorFrameMixedCompostion() { return mPriorFrameMixedComposition; }
+ int lookupDisplayConfigs(const int32_t& width,
+ const int32_t& height,
+ const int32_t& fps,
+ int32_t* outConfig);
private:
bool skipStaticLayerChanged(ExynosCompositionInfo& compositionInfo);
diff --git a/libhwc2.1/libdevice/ExynosLayer.h b/libhwc2.1/libdevice/ExynosLayer.h
index ead41af..0838c0f 100644
--- a/libhwc2.1/libdevice/ExynosLayer.h
+++ b/libhwc2.1/libdevice/ExynosLayer.h
@@ -471,6 +471,18 @@ class ExynosLayer : public ExynosMPPSource {
return ((mLayerBuffer != NULL) &&
isFormatYUV(VendorGraphicBufferMeta::get_internal_format(mLayerBuffer)));
}
+ bool isLayerHasAlphaChannel() {
+ return ((mLayerBuffer != NULL) &&
+ formatHasAlphaChannel(
+ VendorGraphicBufferMeta::get_internal_format(mLayerBuffer)));
+ }
+ bool isLayerOpaque() {
+ return (!isLayerHasAlphaChannel() &&
+ std::fabs(mPlaneAlpha - 1.0f) <= std::numeric_limits<float>::epsilon());
+ }
+ bool needClearClientTarget() {
+ return (mOverlayPriority >= ePriorityHigh && isLayerOpaque());
+ }
size_t getDisplayFrameArea() { return HEIGHT(mDisplayFrame) * WIDTH(mDisplayFrame); }
void setGeometryChanged(uint64_t changedBit);
void clearGeometryChanged() {mGeometryChanged = 0;};
diff --git a/libhwc2.1/libdisplayinterface/ExynosDisplayDrmInterface.cpp b/libhwc2.1/libdisplayinterface/ExynosDisplayDrmInterface.cpp
index 1984d7b..994027a 100644
--- a/libhwc2.1/libdisplayinterface/ExynosDisplayDrmInterface.cpp
+++ b/libhwc2.1/libdisplayinterface/ExynosDisplayDrmInterface.cpp
@@ -832,23 +832,41 @@ int32_t ExynosDisplayDrmInterface::chosePreferredConfig()
if (err != HWC2_ERROR_NONE || !num_configs)
return err;
- hwc2_config_t config;
- int32_t bootConfig;
- err = mExynosDisplay->getPreferredDisplayConfigInternal(&bootConfig);
- if (err == HWC2_ERROR_NONE && property_get_bool("sys.boot_completed", false) == true) {
- config = static_cast<hwc2_config_t>(bootConfig);
+ int32_t config = -1;
+ char modeStr[PROPERTY_VALUE_MAX] = "\0";
+ int32_t width = 0, height = 0, fps = 0;
+ if (property_get("vendor.display.preferred_mode", modeStr, "") > 0 &&
+ sscanf(modeStr, "%dx%d@%d", &width, &height, &fps) == 3) {
+ err = mExynosDisplay->lookupDisplayConfigs(width, height, fps, &config);
} else {
- config = mDrmConnector->get_preferred_mode_id();
+ err = HWC2_ERROR_BAD_CONFIG;
}
- ALOGI("Preferred mode id: %d, state: %d", config, mDrmConnector->state());
- if ((err = setActiveConfig(config)) < 0) {
- ALOGE("failed to set default config, err %d", err);
- return err;
+ const int32_t drmPreferredConfig = mDrmConnector->get_preferred_mode_id();
+ if (err != HWC2_ERROR_NONE) {
+ config = drmPreferredConfig;
+ }
+ ALOGI("Preferred mode id: %d(%s), state: %d", config, modeStr, mDrmConnector->state());
+
+ auto &configs = mExynosDisplay->mDisplayConfigs;
+ if (config != drmPreferredConfig &&
+ (configs[config].width != configs[drmPreferredConfig].width ||
+ configs[config].height != configs[drmPreferredConfig].height)) {
+ // HWC cannot send a resolution change commit here until 1st frame update because of
+ // some panels requirement. Therefore, it calls setActiveConfigWithConstraints() help
+ // set mDesiredModeState correctly, and then trigger modeset in the 1s frame update.
+ if ((err = setActiveConfigWithConstraints(config)) < 0) {
+ ALOGE("failed to setActiveConfigWithConstraints(), err %d", err);
+ return err;
+ }
+ } else {
+ if ((err = setActiveConfig(config)) < 0) {
+ ALOGE("failed to set default config, err %d", err);
+ return err;
+ }
}
- mExynosDisplay->updateInternalDisplayConfigVariables(config);
- return err;
+ return mExynosDisplay->updateInternalDisplayConfigVariables(config);
}
int32_t ExynosDisplayDrmInterface::getDisplayConfigs(
diff --git a/libhwc2.1/libdisplayinterface/ExynosDisplayDrmInterface.h b/libhwc2.1/libdisplayinterface/ExynosDisplayDrmInterface.h
index d795b72..c391b9f 100644
--- a/libhwc2.1/libdisplayinterface/ExynosDisplayDrmInterface.h
+++ b/libhwc2.1/libdisplayinterface/ExynosDisplayDrmInterface.h
@@ -318,7 +318,7 @@ class ExynosDisplayDrmInterface :
return NO_ERROR;
}
int32_t getFrameCount() { return mFrameCounter; }
- virtual void registerHistogramInfo(IDLHistogram *info) { return; }
+ virtual void registerHistogramInfo(const std::shared_ptr<IDLHistogram> &info) { return; }
virtual int32_t setHistogramControl(hidl_histogram_control_t enabled) { return NO_ERROR; }
virtual int32_t setHistogramData(void *bin) { return NO_ERROR; }
int32_t getActiveModeHDisplay() { return mActiveModeState.mode.h_display(); }
diff --git a/libhwc2.1/libhwcService/ExynosHWCService.cpp b/libhwc2.1/libhwcService/ExynosHWCService.cpp
index 5413f41..aac4916 100644
--- a/libhwc2.1/libhwcService/ExynosHWCService.cpp
+++ b/libhwc2.1/libhwcService/ExynosHWCService.cpp
@@ -502,4 +502,17 @@ int32_t ExynosHWCService::triggerDisplayIdleEnter(uint32_t displayIndex,
return NO_ERROR;
}
+int32_t ExynosHWCService::setDisplayDbm(int32_t display_id, uint32_t on) {
+ if (on > 1) return -EINVAL;
+
+ auto display = mHWCCtx->device->getDisplay(display_id);
+
+ if (display == nullptr) return -EINVAL;
+
+ ALOGD("ExynosHWCService::%s() display(%u) on=%d", __func__, display_id, on);
+ display->setDbmState(!!on);
+ mHWCCtx->device->onRefresh();
+ return NO_ERROR;
+}
+
} //namespace android
diff --git a/libhwc2.1/libhwcService/ExynosHWCService.h b/libhwc2.1/libhwcService/ExynosHWCService.h
index f4224fb..586e335 100644
--- a/libhwc2.1/libhwcService/ExynosHWCService.h
+++ b/libhwc2.1/libhwcService/ExynosHWCService.h
@@ -78,6 +78,8 @@ public:
virtual int32_t setMinIdleRefreshRate(uint32_t display_id, int32_t fps);
virtual int32_t setRefreshRateThrottle(uint32_t display_id, int32_t delayMs);
+ virtual int32_t setDisplayDbm(int32_t display_id, uint32_t on);
+
int32_t setDisplayRCDLayerEnabled(uint32_t displayIndex, bool enable) override;
int32_t triggerDisplayIdleEnter(uint32_t displayIndex, uint32_t idleTeRefreshRate) override;
diff --git a/libhwc2.1/libhwcService/IExynosHWC.cpp b/libhwc2.1/libhwcService/IExynosHWC.cpp
index 181fdf2..9833e64 100644
--- a/libhwc2.1/libhwcService/IExynosHWC.cpp
+++ b/libhwc2.1/libhwcService/IExynosHWC.cpp
@@ -66,6 +66,7 @@ enum {
SET_REFRESH_RATE_THROTTLE = 1006,
SET_DISPLAY_RCDLAYER_ENABLED = 1007,
TRIGGER_DISPLAY_IDLE_ENTER = 1008,
+ SET_DISPLAY_DBM = 1009,
};
class BpExynosHWCService : public BpInterface<IExynosHWCService> {
@@ -459,6 +460,16 @@ public:
ALOGE_IF(result != NO_ERROR, "TRIGGER_DISPLAY_IDLE_ENTER transact error(%d)", result);
return result;
}
+
+ virtual int32_t setDisplayDbm(int32_t display_id, uint32_t on) {
+ Parcel data, reply;
+ data.writeInterfaceToken(IExynosHWCService::getInterfaceDescriptor());
+ data.writeInt32(display_id);
+ data.writeInt32(on);
+ int result = remote()->transact(SET_DISPLAY_DBM, data, &reply);
+ if (result) ALOGE("SET_DISPLAY_DBM transact error(%d)", result);
+ return result;
+ }
};
IMPLEMENT_META_INTERFACE(ExynosHWCService, "android.hal.ExynosHWCService");
@@ -741,6 +752,15 @@ status_t BnExynosHWCService::onTransact(
return triggerDisplayIdleEnter(displayIndex, idleTeRefreshRate);
} break;
+ case SET_DISPLAY_DBM: {
+ CHECK_INTERFACE(IExynosHWCService, data, reply);
+ int32_t display_id = data.readInt32();
+ uint32_t on = data.readInt32();
+ int32_t error = setDisplayDbm(display_id, on);
+ reply->writeInt32(error);
+ return NO_ERROR;
+ } break;
+
default:
return BBinder::onTransact(code, data, reply, flags);
}
diff --git a/libhwc2.1/libhwcService/IExynosHWC.h b/libhwc2.1/libhwcService/IExynosHWC.h
index debf6fb..640ca7d 100644
--- a/libhwc2.1/libhwcService/IExynosHWC.h
+++ b/libhwc2.1/libhwcService/IExynosHWC.h
@@ -76,6 +76,7 @@ public:
virtual int32_t setRefreshRateThrottle(uint32_t display_id, int32_t throttle) = 0;
virtual int32_t setDisplayRCDLayerEnabled(uint32_t displayIndex, bool enable) = 0;
virtual int32_t triggerDisplayIdleEnter(uint32_t displayIndex, uint32_t idleTeRefreshRate) = 0;
+ virtual int32_t setDisplayDbm(int32_t display_id, uint32_t on) = 0;
};
/* Native Interface */
diff --git a/libhwc2.1/libhwchelper/ExynosHWCHelper.cpp b/libhwc2.1/libhwchelper/ExynosHWCHelper.cpp
index d9d5b4b..1c10909 100644
--- a/libhwc2.1/libhwchelper/ExynosHWCHelper.cpp
+++ b/libhwc2.1/libhwchelper/ExynosHWCHelper.cpp
@@ -1157,8 +1157,9 @@ int32_t load_png_image(const char* filepath, buffer_handle_t buffer) {
return -EINVAL;
}
- uint32_t bufferHandleSize = gmeta.stride * gmeta.vstride * formatToBpp(gmeta.format) / 8;
- if (bufferHandleSize > gmeta.size) {
+ size_t bufferHandleSize = gmeta.stride * gmeta.vstride * formatToBpp(gmeta.format) / 8;
+ size_t png_size = png_get_rowbytes(png_ptr, info_ptr) * height;
+ if (bufferHandleSize > gmeta.size || (bufferHandleSize < png_size)) {
fclose(fp);
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
return -EINVAL;
diff --git a/libhwc2.1/libmaindisplay/ExynosPrimaryDisplay.cpp b/libhwc2.1/libmaindisplay/ExynosPrimaryDisplay.cpp
index 6fc7ee9..594495b 100644
--- a/libhwc2.1/libmaindisplay/ExynosPrimaryDisplay.cpp
+++ b/libhwc2.1/libmaindisplay/ExynosPrimaryDisplay.cpp
@@ -38,7 +38,6 @@ extern struct exynos_hwc_control exynosHWCControl;
using namespace SOC_VERSION;
constexpr auto nsecsPerSec = std::chrono::nanoseconds(1s).count();
-constexpr auto nsecsPerMs = std::chrono::nanoseconds(1ms).count();
static const std::map<const DisplayType, const std::string> panelSysfsPath =
{{DisplayType::DISPLAY_PRIMARY, "/sys/devices/platform/exynos-drm/primary-panel/"},
@@ -259,25 +258,16 @@ int32_t ExynosPrimaryDisplay::getPreferredDisplayConfigInternal(int32_t *outConf
return HWC2_ERROR_BAD_CONFIG;
}
- const auto vsyncPeriod = nsecsPerSec / fps;
-
- for (auto const& [config, mode] : mDisplayConfigs) {
- long delta = abs(vsyncPeriod - mode.vsyncPeriod);
- if ((width == mode.width) && (height == mode.height) &&
- (delta < nsecsPerMs)) {
- ALOGD("%s: found preferred display config for mode: %s=%d",
- __func__, modeStr, config);
- *outConfig = config;
- return HWC2_ERROR_NONE;
- }
- }
- return HWC2_ERROR_BAD_CONFIG;
+ return lookupDisplayConfigs(width, height, fps, outConfig);
}
int32_t ExynosPrimaryDisplay::setPowerOn() {
ATRACE_CALL();
updateAppliedActiveConfig(0, 0);
- int ret = applyPendingConfig();
+ int ret = NO_ERROR;
+ if (!mFirstPowerOn) {
+ ret = applyPendingConfig();
+ }
if (!mPowerModeState.has_value() || (*mPowerModeState == HWC2_POWER_MODE_OFF)) {
// check the dynamic recomposition thread by following display
@@ -353,6 +343,11 @@ int32_t ExynosPrimaryDisplay::setPowerDoze(hwc2_power_mode_t mode) {
mPowerModeState = mode;
}
+ // LHBM will be disabled in the kernel while entering AOD mode if it's
+ // already enabled. Reset the state to avoid the sync problem.
+ mBrightnessController->resetLhbmState();
+ mLhbmOn = false;
+
ExynosDisplay::updateRefreshRateHint();
return HWC2_ERROR_NONE;
@@ -564,13 +559,35 @@ int32_t ExynosPrimaryDisplay::setLhbmState(bool enabled) {
setLHBMRefreshRateThrottle(kLhbmRefreshRateThrottleMs);
}
+ bool wasDisabled =
+ mBrightnessController
+ ->checkSysfsStatus(BrightnessController::kLocalHbmModeFileNode,
+ {std::to_string(static_cast<int>(
+ BrightnessController::LhbmMode::DISABLED))},
+ 0);
+ if (!enabled && wasDisabled) {
+ ALOGW("lhbm is at DISABLED state, skip disabling");
+ return NO_ERROR;
+ } else if (enabled && !wasDisabled) {
+ requestLhbm(true);
+ ALOGI("lhbm is at ENABLING or ENABLED state, re-enable to reset timeout timer");
+ return NO_ERROR;
+ }
+
+ int64_t lhbmEnablingNanos;
+ std::vector<std::string> checkingValue = {
+ std::to_string(static_cast<int>(BrightnessController::LhbmMode::DISABLED))};
+ if (enabled) {
+ 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);
constexpr uint32_t kSysfsCheckTimeoutMs = 500;
ALOGI("setLhbmState =%d", enabled);
- bool succeed = mBrightnessController->checkSysfsStatus(
- BrightnessController::kLocalHbmModeFileNode,
- std::to_string(enabled ? 1 : 0),
- ms2ns(kSysfsCheckTimeoutMs));
+ bool succeed =
+ mBrightnessController->checkSysfsStatus(BrightnessController::kLocalHbmModeFileNode,
+ checkingValue, ms2ns(kSysfsCheckTimeoutMs));
if (!succeed) {
ALOGE("failed to update lhbm mode");
if (enabled) {
@@ -579,11 +596,40 @@ int32_t ExynosPrimaryDisplay::setLhbmState(bool enabled) {
return -ENODEV;
}
- if (!enabled) {
+ if (enabled) {
+ int64_t lhbmEnablingDoneNanos = systemTime(SYSTEM_TIME_MONOTONIC);
+ bool enablingStateSupported = !mFramesToReachLhbmPeakBrightness;
+ if (enablingStateSupported) {
+ ATRACE_NAME("lhbm_wait_peak_brightness");
+ if (!mBrightnessController
+ ->checkSysfsStatus(BrightnessController::kLocalHbmModeFileNode,
+ {std::to_string(static_cast<int>(
+ BrightnessController::LhbmMode::ENABLED))},
+ ms2ns(kSysfsCheckTimeoutMs))) {
+ ALOGE("failed to wait for lhbm becoming effective");
+ return -EIO;
+ }
+ } else {
+ // lhbm takes effect at next vblank
+ ATRACE_NAME("lhbm_wait_apply");
+ if (mDisplayInterface->waitVBlank()) {
+ ALOGE("%s failed to wait vblank for taking effect", __func__);
+ return -ENODEV;
+ }
+ ATRACE_NAME("lhbm_wait_peak_brightness");
+ for (int32_t i = mFramesToReachLhbmPeakBrightness; i > 0; i--) {
+ if (mDisplayInterface->waitVBlank()) {
+ ALOGE("%s failed to wait vblank for peak brightness, %d", __func__, i);
+ return -ENODEV;
+ }
+ }
+ }
+ ALOGI("lhbm delay mode: %s, latency(ms): total: %d cmd: %d\n",
+ enablingStateSupported ? "poll" : "fixed",
+ static_cast<int>((systemTime(SYSTEM_TIME_MONOTONIC) - lhbmEnablingNanos) / 1000000),
+ static_cast<int>((lhbmEnablingDoneNanos - lhbmEnablingNanos) / 1000000));
+ } else {
setLHBMRefreshRateThrottle(0);
- }
-
- {
// lhbm takes effect at next vblank
ATRACE_NAME("lhbm_wait_apply");
if (mDisplayInterface->waitVBlank()) {
@@ -592,16 +638,6 @@ int32_t ExynosPrimaryDisplay::setLhbmState(bool enabled) {
}
}
- if (enabled) {
- for (int32_t i = mFramesToReachLhbmPeakBrightness; i > 0; i--) {
- ATRACE_NAME("lhbm_wait_peak_brightness");
- if (mDisplayInterface->waitVBlank()) {
- ALOGE("%s failed to wait vblank for peak brightness, %d", __func__, i);
- return -ENODEV;
- }
- }
- }
-
mLhbmOn = enabled;
if (!mPowerModeState.has_value() || (*mPowerModeState == HWC2_POWER_MODE_OFF && mLhbmOn)) {
mLhbmOn = false;
@@ -968,3 +1004,12 @@ void ExynosPrimaryDisplay::checkBtsReassignResource(const uint32_t vsyncPeriod,
}
}
}
+
+bool ExynosPrimaryDisplay::isDbmSupported() {
+ return mBrightnessController->isDbmSupported();
+}
+
+int32_t ExynosPrimaryDisplay::setDbmState(bool enabled) {
+ mBrightnessController->processDimBrightness(enabled);
+ return NO_ERROR;
+}
diff --git a/libhwc2.1/libmaindisplay/ExynosPrimaryDisplay.h b/libhwc2.1/libmaindisplay/ExynosPrimaryDisplay.h
index bd9cda7..d9ec1ca 100644
--- a/libhwc2.1/libmaindisplay/ExynosPrimaryDisplay.h
+++ b/libhwc2.1/libmaindisplay/ExynosPrimaryDisplay.h
@@ -52,6 +52,9 @@ class ExynosPrimaryDisplay : public ExynosDisplay {
virtual int setMinIdleRefreshRate(const int fps) override;
virtual int setRefreshRateThrottleNanos(const int64_t delayNs,
const VrrThrottleRequester requester) override;
+ virtual bool isDbmSupported() override;
+ virtual int32_t setDbmState(bool enabled) override;
+
virtual void dump(String8& result) override;
virtual void updateAppliedActiveConfig(const hwc2_config_t newConfig,
const int64_t ts) override;
diff --git a/libhwc2.1/libresource/ExynosResourceManager.cpp b/libhwc2.1/libresource/ExynosResourceManager.cpp
index 85bcaa4..3c94c2f 100644
--- a/libhwc2.1/libresource/ExynosResourceManager.cpp
+++ b/libhwc2.1/libresource/ExynosResourceManager.cpp
@@ -2314,7 +2314,7 @@ void ExynosResourceManager::setScaleDownRatio(uint32_t physicalType,
}
}
-int32_t ExynosResourceManager::prepareResources()
+int32_t ExynosResourceManager::prepareResources()
{
int ret = NO_ERROR;
HDEBUGLOGD(eDebugResourceManager, "This is first validate");
diff --git a/libhwc2.1/pixel-display-default.xml b/libhwc2.1/pixel-display-default.xml
index fc10d6a..86c1b03 100644
--- a/libhwc2.1/pixel-display-default.xml
+++ b/libhwc2.1/pixel-display-default.xml
@@ -1,7 +1,7 @@
<manifest version="1.0" type="device">
<hal format="aidl">
<name>com.google.hardware.pixel.display</name>
- <version>6</version>
+ <version>7</version>
<fqname>IDisplay/default</fqname>
</hal>
</manifest>
diff --git a/libhwc2.1/pixel-display-secondary.xml b/libhwc2.1/pixel-display-secondary.xml
index f8bd77b..515bc21 100644
--- a/libhwc2.1/pixel-display-secondary.xml
+++ b/libhwc2.1/pixel-display-secondary.xml
@@ -1,7 +1,7 @@
<manifest version="1.0" type="device">
<hal format="aidl">
<name>com.google.hardware.pixel.display</name>
- <version>6</version>
+ <version>7</version>
<fqname>IDisplay/secondary</fqname>
</hal>
</manifest>
diff --git a/libhwc2.1/pixel-display.cpp b/libhwc2.1/pixel-display.cpp
index d12e328..c95c239 100644
--- a/libhwc2.1/pixel-display.cpp
+++ b/libhwc2.1/pixel-display.cpp
@@ -260,6 +260,23 @@ ndk::ScopedAStatus Display::getPanelCalibrationStatus(PanelCalibrationStatus *_a
}
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
}
+
+ndk::ScopedAStatus Display::isDbmSupported(bool *_aidl_return) {
+ if (!mDisplay) {
+ return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+ }
+ *_aidl_return = mDisplay->isDbmSupported();
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Display::setDbmState(bool enabled) {
+ if (!mDisplay) {
+ return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+ }
+ mDisplay->setDbmState(enabled);
+ return ndk::ScopedAStatus::ok();
+}
+
} // namespace display
} // namespace pixel
} // namespace hardware
diff --git a/libhwc2.1/pixel-display.h b/libhwc2.1/pixel-display.h
index 0fd0a5b..b1696d5 100644
--- a/libhwc2.1/pixel-display.h
+++ b/libhwc2.1/pixel-display.h
@@ -59,6 +59,8 @@ public:
Priority pri, std::vector<char16_t> *histogrambuffer,
HistogramErrorCode *_aidl_return) override;
ndk::ScopedAStatus getPanelCalibrationStatus(PanelCalibrationStatus *_aidl_return) override;
+ ndk::ScopedAStatus isDbmSupported(bool *_aidl_return) override;
+ ndk::ScopedAStatus setDbmState(bool enabled) override;
private:
bool runMediator(const RoiRect roi, const Weight weight, const HistogramPos pos,