Allow controlling the SDR white point

Test: this
Change-Id: I9ee059afd73ca0850e41072c068c9effe8362382
diff --git a/graphics/java/android/graphics/HardwareRenderer.java b/graphics/java/android/graphics/HardwareRenderer.java
index b3103fd5..0452933 100644
--- a/graphics/java/android/graphics/HardwareRenderer.java
+++ b/graphics/java/android/graphics/HardwareRenderer.java
@@ -634,6 +634,19 @@
     }
 
     /**
+     * Sets the colormode with the desired SDR white point.
+     *
+     * The white point only applies if the color mode is an HDR mode
+     *
+     * @hide
+     */
+    public void setColorMode(@ActivityInfo.ColorMode int colorMode, float whitePoint) {
+        nSetSdrWhitePoint(mNativeProxy, whitePoint);
+        mColorMode = colorMode;
+        nSetColorMode(mNativeProxy, colorMode);
+    }
+
+    /**
      * Blocks until all previously queued work has completed.
      *
      * TODO: Only used for draw finished listeners, but the FrameCompleteCallback does that
@@ -1227,6 +1240,8 @@
 
     private static native void nSetColorMode(long nativeProxy, int colorMode);
 
+    private static native void nSetSdrWhitePoint(long nativeProxy, float whitePoint);
+
     private static native int nSyncAndDrawFrame(long nativeProxy, long[] frameInfo, int size);
 
     private static native void nDestroy(long nativeProxy, long rootRenderNode);
diff --git a/libs/hwui/Properties.cpp b/libs/hwui/Properties.cpp
index 446e81e..ba44d05 100644
--- a/libs/hwui/Properties.cpp
+++ b/libs/hwui/Properties.cpp
@@ -78,6 +78,7 @@
 
 int Properties::contextPriority = 0;
 int Properties::defaultRenderAhead = -1;
+float Properties::defaultSdrWhitePoint = 200.f;
 
 bool Properties::load() {
     bool prevDebugLayersUpdates = debugLayersUpdates;
diff --git a/libs/hwui/Properties.h b/libs/hwui/Properties.h
index c8f6b3b..85a0f4a 100644
--- a/libs/hwui/Properties.h
+++ b/libs/hwui/Properties.h
@@ -249,6 +249,8 @@
 
     static int defaultRenderAhead;
 
+    static float defaultSdrWhitePoint;
+
 private:
     static ProfileType sProfileType;
     static bool sDisableProfileBars;
diff --git a/libs/hwui/jni/android_graphics_HardwareRenderer.cpp b/libs/hwui/jni/android_graphics_HardwareRenderer.cpp
index 7d6875f..fc594da 100644
--- a/libs/hwui/jni/android_graphics_HardwareRenderer.cpp
+++ b/libs/hwui/jni/android_graphics_HardwareRenderer.cpp
@@ -223,6 +223,11 @@
     proxy->setColorMode(static_cast<ColorMode>(colorMode));
 }
 
+static void android_view_ThreadedRenderer_setSdrWhitePoint(JNIEnv* env, jobject clazz,
+        jlong proxyPtr, jfloat sdrWhitePoint) {
+    Properties::defaultSdrWhitePoint = sdrWhitePoint;
+}
+
 static int android_view_ThreadedRenderer_syncAndDrawFrame(JNIEnv* env, jobject clazz,
         jlong proxyPtr, jlongArray frameInfo, jint frameInfoSize) {
     LOG_ALWAYS_FATAL_IF(frameInfoSize != UI_THREAD_FRAME_INFO_SIZE,
@@ -671,6 +676,7 @@
         {"nSetLightGeometry", "(JFFFF)V", (void*)android_view_ThreadedRenderer_setLightGeometry},
         {"nSetOpaque", "(JZ)V", (void*)android_view_ThreadedRenderer_setOpaque},
         {"nSetColorMode", "(JI)V", (void*)android_view_ThreadedRenderer_setColorMode},
+        {"nSetSdrWhitePoint", "(JF)V", (void*)android_view_ThreadedRenderer_setSdrWhitePoint},
         {"nSyncAndDrawFrame", "(J[JI)I", (void*)android_view_ThreadedRenderer_syncAndDrawFrame},
         {"nDestroy", "(JJ)V", (void*)android_view_ThreadedRenderer_destroy},
         {"nRegisterAnimatingRenderNode", "(JJ)V",
diff --git a/libs/hwui/utils/Color.cpp b/libs/hwui/utils/Color.cpp
index eff34a8..87512f0 100644
--- a/libs/hwui/utils/Color.cpp
+++ b/libs/hwui/utils/Color.cpp
@@ -26,6 +26,7 @@
 
 #include <algorithm>
 #include <cmath>
+#include <Properties.h>
 
 namespace android {
 namespace uirenderer {
@@ -344,13 +345,9 @@
             static_cast<uint8_t>(rgb.b * 255));
 }
 
-// Note that SkColorSpace doesn't have the notion of an unspecified SDR white
-// level.
-static constexpr float kDefaultSDRWhiteLevel = 150.f;
-
 skcms_TransferFunction GetPQSkTransferFunction(float sdr_white_level) {
     if (sdr_white_level <= 0.f) {
-        sdr_white_level = kDefaultSDRWhiteLevel;
+        sdr_white_level = Properties::defaultSdrWhitePoint;
     }
     // The generic PQ transfer function produces normalized luminance values i.e.
     // the range 0-1 represents 0-10000 nits for the reference display, but we
diff --git a/tests/SilkFX/src/com/android/test/silkfx/common/ColorModeControls.kt b/tests/SilkFX/src/com/android/test/silkfx/common/ColorModeControls.kt
index c3d689c..9b15b04 100644
--- a/tests/SilkFX/src/com/android/test/silkfx/common/ColorModeControls.kt
+++ b/tests/SilkFX/src/com/android/test/silkfx/common/ColorModeControls.kt
@@ -26,10 +26,10 @@
 import android.widget.TextView
 import com.android.test.silkfx.R
 import com.android.test.silkfx.app.WindowObserver
-import java.lang.Exception
 
 class ColorModeControls : LinearLayout, WindowObserver {
     private val COLOR_MODE_HDR10 = 3
+    private val SDR_WHITE_POINTS = floatArrayOf(200f, 250f, 300f, 350f, 400f, 100f, 150f)
 
     constructor(context: Context) : this(context, null)
     constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) {
@@ -37,14 +37,17 @@
     }
 
     private var window: Window? = null
-    private var currentMode: TextView? = null
+    private var currentModeDisplay: TextView? = null
     private val displayManager: DisplayManager
+    private var targetSdrWhitePointIndex = 0
+
+    private val whitePoint get() = SDR_WHITE_POINTS[targetSdrWhitePointIndex]
 
     override fun onFinishInflate() {
         super.onFinishInflate()
         val window = window ?: throw IllegalStateException("Failed to attach window")
 
-        currentMode = findViewById(R.id.current_mode)!!
+        currentModeDisplay = findViewById(R.id.current_mode)!!
         setColorMode(window.colorMode)
 
         findViewById<Button>(R.id.mode_default)!!.setOnClickListener {
@@ -63,21 +66,30 @@
 
     private fun setColorMode(newMode: Int) {
         val window = window!!
+        var sdrWhitepointChanged = false
         // Need to do this before setting the colorMode, as setting the colorMode will
         // trigger the attribute change listener
         if (newMode == ActivityInfo.COLOR_MODE_HDR ||
                 newMode == COLOR_MODE_HDR10) {
+            if (window.colorMode == newMode) {
+                targetSdrWhitePointIndex = (targetSdrWhitePointIndex + 1) % SDR_WHITE_POINTS.size
+                sdrWhitepointChanged = true
+            }
             setBrightness(1.0f)
         } else {
             setBrightness(.4f)
         }
         window.colorMode = newMode
-        currentMode?.run {
+        if (sdrWhitepointChanged) {
+            threadedRenderer?.setColorMode(newMode, whitePoint)
+        }
+        val whitePoint = whitePoint.toInt()
+        currentModeDisplay?.run {
             text = "Current Mode: " + when (newMode) {
                 ActivityInfo.COLOR_MODE_DEFAULT -> "Default/SRGB"
                 ActivityInfo.COLOR_MODE_WIDE_COLOR_GAMUT -> "Wide Gamut"
-                ActivityInfo.COLOR_MODE_HDR -> "HDR (sdr white point 150)"
-                COLOR_MODE_HDR10 -> "HDR10 (sdr white point 150)"
+                ActivityInfo.COLOR_MODE_HDR -> "HDR (sdr white point $whitePoint)"
+                COLOR_MODE_HDR10 -> "HDR10 (sdr white point $whitePoint)"
                 else -> "Unknown"
             }
         }
@@ -101,4 +113,10 @@
             }
         }
     }
+
+    override fun onAttachedToWindow() {
+        super.onAttachedToWindow()
+
+        threadedRenderer?.setColorMode(window!!.colorMode, whitePoint)
+    }
 }
\ No newline at end of file
diff --git a/tests/SilkFX/src/com/android/test/silkfx/hdr/BlingyNotification.kt b/tests/SilkFX/src/com/android/test/silkfx/hdr/BlingyNotification.kt
index e517c3c..4ad21fa 100644
--- a/tests/SilkFX/src/com/android/test/silkfx/hdr/BlingyNotification.kt
+++ b/tests/SilkFX/src/com/android/test/silkfx/hdr/BlingyNotification.kt
@@ -71,9 +71,9 @@
         paint.shader = LinearGradient(0f, 0f, w.toFloat(), 0f,
                 longArrayOf(
                         color(1f, 1f, 1f, 0f),
-                        color(1f, 1f, 1f, .4f),
-                        color(2f, 2f, 2f, .8f),
-                        color(1f, 1f, 1f, .4f),
+                        color(1f, 1f, 1f, .1f),
+                        color(2f, 2f, 2f, .3f),
+                        color(1f, 1f, 1f, .2f),
                         color(1f, 1f, 1f, 0f)
                         ),
                 floatArrayOf(.2f, .4f, .5f, .6f, .8f),