1 /* 2 * Copyright (C) 2023 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.view; 18 19 import android.os.SystemClock; 20 21 import com.android.graphics.hwui.flags.Flags; 22 23 import java.util.function.Consumer; 24 25 /** @hide */ 26 class HdrRenderState implements Consumer<Display> { 27 // Targeting an animation from 1x to 5x over 400ms means we need to increase by 0.01/ms 28 private static final float TRANSITION_PER_MS = 0.01f; 29 30 private static final boolean FLAG_ANIMATE_ENABLED = Flags.animateHdrTransitions(); 31 32 private final ViewRootImpl mViewRoot; 33 34 private boolean mIsHdrEnabled = false; 35 private boolean mIsListenerRegistered = false; 36 private boolean mUpdateHdrSdrRatioInfo = false; 37 private float mDesiredHdrSdrRatio = 1f; 38 private float mTargetDesiredHdrSdrRatio = 1f; 39 private float mTargetHdrSdrRatio = 1f; 40 private float mRenderHdrSdrRatio = 1f; 41 private float mPreviousRenderRatio = 1f; 42 private long mLastUpdateMillis = -1; 43 HdrRenderState(ViewRootImpl viewRoot)44 HdrRenderState(ViewRootImpl viewRoot) { 45 mViewRoot = viewRoot; 46 } 47 48 @Override accept(Display display)49 public void accept(Display display) { 50 forceUpdateHdrSdrRatio(); 51 mViewRoot.invalidate(); 52 } 53 isHdrEnabled()54 boolean isHdrEnabled() { 55 return mIsHdrEnabled; 56 } 57 stopListening()58 void stopListening() { 59 if (mIsListenerRegistered) { 60 mViewRoot.mDisplay.unregisterHdrSdrRatioChangedListener(this); 61 mIsListenerRegistered = false; 62 } 63 } 64 startListening()65 void startListening() { 66 if (isHdrEnabled() && !mIsListenerRegistered && mViewRoot.mDisplay != null) { 67 mViewRoot.mDisplay.registerHdrSdrRatioChangedListener(mViewRoot.mExecutor, this); 68 mIsListenerRegistered = true; 69 } 70 } 71 72 /** @return true if something changed, else false */ updateForFrame(long frameTimeMillis)73 boolean updateForFrame(long frameTimeMillis) { 74 boolean hasUpdate = mUpdateHdrSdrRatioInfo; 75 mUpdateHdrSdrRatioInfo = false; 76 mRenderHdrSdrRatio = mTargetHdrSdrRatio; 77 long timeDelta = Math.max(Math.min(32, frameTimeMillis - mLastUpdateMillis), 8); 78 final float maxStep = timeDelta * TRANSITION_PER_MS; 79 mLastUpdateMillis = frameTimeMillis; 80 if (hasUpdate && FLAG_ANIMATE_ENABLED) { 81 if (isHdrEnabled()) { 82 float delta = mTargetHdrSdrRatio - mPreviousRenderRatio; 83 if (delta > maxStep) { 84 mRenderHdrSdrRatio = mPreviousRenderRatio + maxStep; 85 mUpdateHdrSdrRatioInfo = true; 86 mViewRoot.invalidate(); 87 } 88 mPreviousRenderRatio = mRenderHdrSdrRatio; 89 90 if (mTargetDesiredHdrSdrRatio < mDesiredHdrSdrRatio) { 91 mDesiredHdrSdrRatio = Math.max(mTargetDesiredHdrSdrRatio, 92 mDesiredHdrSdrRatio - maxStep); 93 if (mDesiredHdrSdrRatio != mTargetDesiredHdrSdrRatio) { 94 mUpdateHdrSdrRatioInfo = true; 95 mViewRoot.invalidate(); 96 } 97 } 98 99 } else { 100 mPreviousRenderRatio = mTargetHdrSdrRatio; 101 mDesiredHdrSdrRatio = mTargetDesiredHdrSdrRatio; 102 } 103 } 104 return hasUpdate; 105 } 106 getDesiredHdrSdrRatio()107 float getDesiredHdrSdrRatio() { 108 return mDesiredHdrSdrRatio; 109 } 110 getRenderHdrSdrRatio()111 float getRenderHdrSdrRatio() { 112 return mRenderHdrSdrRatio; 113 } 114 forceUpdateHdrSdrRatio()115 void forceUpdateHdrSdrRatio() { 116 if (isHdrEnabled()) { 117 mTargetHdrSdrRatio = Math.min(mDesiredHdrSdrRatio, 118 mViewRoot.mDisplay.getHdrSdrRatio()); 119 } else { 120 mTargetHdrSdrRatio = 1.0f; 121 } 122 mUpdateHdrSdrRatioInfo = true; 123 } 124 setDesiredHdrSdrRatio(boolean isHdrEnabled, float desiredRatio)125 void setDesiredHdrSdrRatio(boolean isHdrEnabled, float desiredRatio) { 126 mIsHdrEnabled = isHdrEnabled; 127 mLastUpdateMillis = SystemClock.uptimeMillis(); 128 if (desiredRatio != mTargetDesiredHdrSdrRatio) { 129 mTargetDesiredHdrSdrRatio = desiredRatio; 130 if (mTargetDesiredHdrSdrRatio > mDesiredHdrSdrRatio || !FLAG_ANIMATE_ENABLED) { 131 mDesiredHdrSdrRatio = mTargetDesiredHdrSdrRatio; 132 } 133 forceUpdateHdrSdrRatio(); 134 mViewRoot.invalidate(); 135 136 if (isHdrEnabled()) { 137 startListening(); 138 } else { 139 stopListening(); 140 } 141 } 142 } 143 } 144