From fe968e3e54235cd75b739aab311a1b9c074d7ad1 Mon Sep 17 00:00:00 2001 From: Julien Masson Date: Tue, 7 Feb 2023 10:47:19 +0100 Subject: [PATCH] backlight: convert linear to gamma float brightness The brightness controller in Android frameworks convert initial value from the slider to a new value not linear [1]. The value is modified by convertGammaToLinearFloat. The current implementation in light HAL doesn't take account the none linearity of this incoming value, these values are logarithmic [2]. Thus the brightness of the panel is very low most of the time. In order to get back a linear value, one solution is to re-convert the incoming value to a linear form: convertLinearToGammaFloat. The implementation convertLinearToGammaFloat has been highly inspired by the one in BrightnessUtils [3]. [1] https://android.googlesource.com/platform/frameworks/base/+/refs/tags/android-12.0.0_r34/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessController.java#354 [2] https://tunjid.medium.com/reverse-engineering-android-pies-logarithmic-brightness-curve-ecd41739d7a2 [3] https://android.googlesource.com/platform/frameworks/base/+/refs/tags/android-12.0.0_r34/packages/SettingsLib/src/com/android/settingslib/display/BrightnessUtils.java#129 Signed-off-by: Julien Masson --- Lights.cpp | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/Lights.cpp b/Lights.cpp index 28316ef..6b519df 100644 --- a/Lights.cpp +++ b/Lights.cpp @@ -19,6 +19,7 @@ #include #include #include +#include static const std::string BACKLIGHT_DIR = "/sys/class/backlight"; static const std::string LEDS_DIR = "/sys/class/leds"; @@ -59,11 +60,26 @@ static int32_t rgbToBrightness(int32_t color) return (77 * r + 150 * g + 29 * b) >> 8; } +static float convertLinearToGammaFloat(float val) +{ + const float r = 0.5; + const float a = 0.17883277; + const float b = 0.28466892; + const float c = 0.55991073; + // HLG normalizes to the range [0, 12] rather than [0, 1] + float normalizedVal = val * 12; + + if (normalizedVal <= 1.0) + return sqrt(normalizedVal) * r; + else + return a * log(normalizedVal - b) + c; +} + ndk::ScopedAStatus Backlight::setLightState(const HwLightState &state) const { auto brightness = rgbToBrightness(state.color); - // Adding half of the max (255/2=127) provides proper rounding while staying in integer mode: - brightness = (brightness * maxBrightness + 127) / 255; + brightness = convertLinearToGammaFloat((float)brightness / 255) * maxBrightness; + if (state.brightnessMode == BrightnessMode::LOW_PERSISTENCE) LOG(ERROR) << "TODO: Implement Low Persistence brightness mode"; LOG(DEBUG) << "Changing backlight to level " << brightness << "/" << maxBrightness;