From 76d7c5af40fee6ef527467dff81d02cf8689a60c Mon Sep 17 00:00:00 2001 From: Alex Hong Date: Mon, 14 Mar 2022 14:57:43 +0800 Subject: Revert "Revert "[RESTRICT AUTOMERGE]DisplayManager: Switch RampAnimator to ramp in HLG space."" This reverts commit e828f33713a4a9103f10fdc1affe21e144635c16. Revert reason: Check if this causes AOC regression Bug: 223124178 Change-Id: If01ec6728c1723d4763dc32b7b206dd2ee73335f (cherry picked from commit 5fb150a5a1beaebb228eb6d01d69298b646eade2) Merged-In: If01ec6728c1723d4763dc32b7b206dd2ee73335f --- .../android/server/display/BrightnessUtils.java | 83 ++++++++++++++++++++++ .../com/android/server/display/RampAnimator.java | 20 ++++-- 2 files changed, 96 insertions(+), 7 deletions(-) create mode 100644 services/core/java/com/android/server/display/BrightnessUtils.java diff --git a/services/core/java/com/android/server/display/BrightnessUtils.java b/services/core/java/com/android/server/display/BrightnessUtils.java new file mode 100644 index 000000000000..84fa0cccbd10 --- /dev/null +++ b/services/core/java/com/android/server/display/BrightnessUtils.java @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.display; + +import android.util.MathUtils; + +/** + * Utility class providing functions to convert between linear and perceptual gamma space. + * + * Internally, this implements the Hybrid Log Gamma electro-optical transfer function, which is a + * slight improvement to the typical gamma transfer function for displays whose max brightness + * exceeds the 120 nit reference point, but doesn't set a specific reference brightness like the PQ + * function does. + * + * Note that this transfer function is only valid if the display's backlight value is a linear + * control. If it's calibrated to be something non-linear, then a different transfer function + * should be used. + * + * Note: This code is based on the same class in the com.android.settingslib.display package. + */ +public class BrightnessUtils { + + // Hybrid Log Gamma constant values + private static final float R = 0.5f; + private static final float A = 0.17883277f; + private static final float B = 0.28466892f; + private static final float C = 0.55991073f; + + /** + * A function for converting from the gamma space into the linear space. + * + * @param val The value in the gamma space [0 .. 1.0] + * @return The corresponding value in the linear space [0 .. 1.0]. + */ + public static final float convertGammaToLinear(float val) { + final float ret; + if (val <= R) { + ret = MathUtils.sq(val / R); + } else { + ret = MathUtils.exp((val - C) / A) + B; + } + + // HLG is normalized to the range [0, 12], ensure that value is within that range, + // it shouldn't be out of bounds. + final float normalizedRet = MathUtils.constrain(ret, 0, 12); + + // Re-normalize to the range [0, 1] + // in order to derive the correct setting value. + return normalizedRet / 12; + } + + /** + * A function for converting from the linear space into the gamma space. + * + * @param val The value in linear space [0 .. 1.0] + * @return The corresponding value in gamma space [0 .. 1.0] + */ + public static final float convertLinearToGamma(float val) { + // For some reason, HLG normalizes to the range [0, 12] rather than [0, 1] + final float normalizedVal = val * 12; + final float ret; + if (normalizedVal <= 1f) { + ret = MathUtils.sqrt(normalizedVal) * R; + } else { + ret = A * MathUtils.log(normalizedVal - B) + C; + } + return ret; + } +} diff --git a/services/core/java/com/android/server/display/RampAnimator.java b/services/core/java/com/android/server/display/RampAnimator.java index ed3b15fb2661..1ebd1f5a535c 100644 --- a/services/core/java/com/android/server/display/RampAnimator.java +++ b/services/core/java/com/android/server/display/RampAnimator.java @@ -23,6 +23,8 @@ import android.view.Choreographer; /** * A custom animator that progressively updates a property value at * a given variable rate until it reaches a particular target value. + * The ramping at the given rate is done in the perceptual space using + * the HLG transfer functions. */ class RampAnimator { private final T mObject; @@ -57,7 +59,9 @@ class RampAnimator { * @param rate The convergence rate in units per second, or 0 to set the value immediately. * @return True if the target differs from the previous target. */ - public boolean animateTo(float target, float rate) { + public boolean animateTo(float targetLinear, float rate) { + // Convert the target from the linear into the HLG space. + final float target = BrightnessUtils.convertLinearToGamma(targetLinear); // Immediately jump to the target the first time. if (mFirstTime || rate <= 0) { @@ -156,7 +160,9 @@ class RampAnimator { final float oldCurrentValue = mCurrentValue; mCurrentValue = mAnimatedValue; if (oldCurrentValue != mCurrentValue) { - mProperty.setValue(mObject, mCurrentValue); + // Convert value from HLG into linear space for the property. + final float linearCurrentVal = BrightnessUtils.convertGammaToLinear(mCurrentValue); + mProperty.setValue(mObject, linearCurrentVal); } if (mTargetValue != mCurrentValue) { postAnimationCallback(); @@ -201,14 +207,14 @@ class RampAnimator { * If this is the first time the property is being set or if the rate is 0, * the value jumps directly to the target. * - * @param firstTarget The first target value. - * @param secondTarget The second target value. + * @param linearFirstTarget The first target value in linear space. + * @param linearSecondTarget The second target value in linear space. * @param rate The convergence rate in units per second, or 0 to set the value immediately. * @return True if either target differs from the previous target. */ - public boolean animateTo(float firstTarget, float secondTarget, float rate) { - final boolean firstRetval = mFirst.animateTo(firstTarget, rate); - final boolean secondRetval = mSecond.animateTo(secondTarget, rate); + public boolean animateTo(float linearFirstTarget, float linearSecondTarget, float rate) { + final boolean firstRetval = mFirst.animateTo(linearFirstTarget, rate); + final boolean secondRetval = mSecond.animateTo(linearSecondTarget, rate); return firstRetval && secondRetval; } -- cgit v1.2.3