Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 15e666c8 authored by John Reck's avatar John Reck
Browse files

Add automatic HDR transition animation

Test: enable flag && silkfx
Bug: 314810174

Change-Id: Ic69b633d6042145a537c7d39e713f804faff6600
parent cbf643b4
Loading
Loading
Loading
Loading
+121 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 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 android.view;

import android.os.SystemClock;

import com.android.graphics.hwui.flags.Flags;

import java.util.function.Consumer;

/** @hide */
class HdrRenderState implements Consumer<Display> {
    // Targeting an animation from 1x to 5x over 400ms means we need to increase by 0.01/ms
    private static final float TRANSITION_PER_MS = 0.01f;

    private static final boolean FLAG_ANIMATE_ENABLED = Flags.animateHdrTransitions();

    private final ViewRootImpl mViewRoot;

    private boolean mIsListenerRegistered = false;
    private boolean mUpdateHdrSdrRatioInfo = false;
    private float mDesiredHdrSdrRatio = 1f;
    private float mTargetHdrSdrRatio = 1f;
    private float mRenderHdrSdrRatio = 1f;
    private float mPreviousRenderRatio = 1f;
    private long mLastUpdateMillis = -1;

    HdrRenderState(ViewRootImpl viewRoot) {
        mViewRoot = viewRoot;
    }

    @Override
    public void accept(Display display) {
        forceUpdateHdrSdrRatio();
        mViewRoot.invalidate();
    }

    boolean isHdrEnabled() {
        return mDesiredHdrSdrRatio >= 1.01f;
    }

    void stopListening() {
        if (mIsListenerRegistered) {
            mViewRoot.mDisplay.unregisterHdrSdrRatioChangedListener(this);
            mIsListenerRegistered = false;
        }
    }

    void startListening() {
        if (isHdrEnabled() && !mIsListenerRegistered && mViewRoot.mDisplay != null) {
            mViewRoot.mDisplay.registerHdrSdrRatioChangedListener(mViewRoot.mExecutor, this);
        }
    }

    /** @return true if something changed, else false */
    boolean updateForFrame(long frameTimeMillis) {
        boolean hasUpdate = mUpdateHdrSdrRatioInfo;
        mUpdateHdrSdrRatioInfo = false;
        mRenderHdrSdrRatio = mTargetHdrSdrRatio;
        long timeDelta = Math.max(Math.min(32, frameTimeMillis - mLastUpdateMillis), 8);
        final float maxStep = timeDelta * TRANSITION_PER_MS;
        mLastUpdateMillis = frameTimeMillis;
        if (hasUpdate && FLAG_ANIMATE_ENABLED) {
            if (mTargetHdrSdrRatio == 1.0f) {
                mPreviousRenderRatio = mTargetHdrSdrRatio;
            } else {
                float delta = mTargetHdrSdrRatio - mPreviousRenderRatio;
                if (delta > maxStep) {
                    mRenderHdrSdrRatio = mPreviousRenderRatio + maxStep;
                    mUpdateHdrSdrRatioInfo = true;
                    mViewRoot.invalidate();
                }
                mPreviousRenderRatio = mRenderHdrSdrRatio;
            }
        }
        return hasUpdate;
    }

    float getDesiredHdrSdrRatio() {
        return mDesiredHdrSdrRatio;
    }

    float getRenderHdrSdrRatio() {
        return mRenderHdrSdrRatio;
    }

    void forceUpdateHdrSdrRatio() {
        mTargetHdrSdrRatio = Math.min(mDesiredHdrSdrRatio, mViewRoot.mDisplay.getHdrSdrRatio());
        mUpdateHdrSdrRatioInfo = true;
    }

    void setDesiredHdrSdrRatio(float desiredRatio) {
        mLastUpdateMillis = SystemClock.uptimeMillis();
        // TODO: When decreasing the desired ratio we need to animate it downwards
        if (desiredRatio != mDesiredHdrSdrRatio) {
            mDesiredHdrSdrRatio = desiredRatio;
            forceUpdateHdrSdrRatio();
            mViewRoot.invalidate();

            if (isHdrEnabled()) {
                startListening();
            } else {
                stopListening();
            }
        }
    }
}
+13 −40
Original line number Diff line number Diff line
@@ -729,10 +729,7 @@ public final class ViewRootImpl implements ViewParent,

    private BLASTBufferQueue mBlastBufferQueue;

    private boolean mUpdateHdrSdrRatioInfo = false;
    private float mDesiredHdrSdrRatio = 1f;
    private float mRenderHdrSdrRatio = 1f;
    private Consumer<Display> mHdrSdrRatioChangedListener = null;
    private final HdrRenderState mHdrRenderState = new HdrRenderState(this);

    /**
     * Child container layer of {@code mSurface} with the same bounds as its parent, and cropped to
@@ -1778,7 +1775,7 @@ public final class ViewRootImpl implements ViewParent,
                mAttachInfo.mThreadedRenderer = renderer;
                renderer.setSurfaceControl(mSurfaceControl, mBlastBufferQueue);
                updateColorModeIfNeeded(attrs.getColorMode(), attrs.getDesiredHdrHeadroom());
                updateRenderHdrSdrRatio();
                mHdrRenderState.forceUpdateHdrSdrRatio();
                updateForceDarkMode();
                mAttachInfo.mHardwareAccelerated = true;
                mAttachInfo.mHardwareAccelerationRequested = true;
@@ -2121,9 +2118,7 @@ public final class ViewRootImpl implements ViewParent,
    private void updateInternalDisplay(int displayId, Resources resources) {
        final Display preferredDisplay =
                ResourcesManager.getInstance().getAdjustedDisplay(displayId, resources);
        if (mHdrSdrRatioChangedListener != null && mDisplay != null) {
            mDisplay.unregisterHdrSdrRatioChangedListener(mHdrSdrRatioChangedListener);
        }
        mHdrRenderState.stopListening();
        if (preferredDisplay == null) {
            // Fallback to use default display.
            Slog.w(TAG, "Cannot get desired display with Id: " + displayId);
@@ -2132,9 +2127,7 @@ public final class ViewRootImpl implements ViewParent,
        } else {
            mDisplay = preferredDisplay;
        }
        if (mHdrSdrRatioChangedListener != null && mDisplay != null) {
            mDisplay.registerHdrSdrRatioChangedListener(mExecutor, mHdrSdrRatioChangedListener);
        }
        mHdrRenderState.startListening();
        mContext.updateDisplay(mDisplay.getDisplayId());
    }

@@ -5100,11 +5093,12 @@ public final class ViewRootImpl implements ViewParent,

                useAsyncReport = true;

                if (mUpdateHdrSdrRatioInfo) {
                    mUpdateHdrSdrRatioInfo = false;
                if (mHdrRenderState.updateForFrame(mAttachInfo.mDrawingTime)) {
                    final float renderRatio = mHdrRenderState.getRenderHdrSdrRatio();
                    applyTransactionOnDraw(mTransaction.setExtendedRangeBrightness(
                            getSurfaceControl(), mRenderHdrSdrRatio, mDesiredHdrSdrRatio));
                    mAttachInfo.mThreadedRenderer.setTargetHdrSdrRatio(mRenderHdrSdrRatio);
                            getSurfaceControl(), renderRatio,
                            mHdrRenderState.getDesiredHdrSdrRatio()));
                    mAttachInfo.mThreadedRenderer.setTargetHdrSdrRatio(renderRatio);
                }

                if (activeSyncGroup != null) {
@@ -5715,11 +5709,6 @@ public final class ViewRootImpl implements ViewParent,
        }
    }

    private void updateRenderHdrSdrRatio() {
        mRenderHdrSdrRatio = Math.min(mDesiredHdrSdrRatio, mDisplay.getHdrSdrRatio());
        mUpdateHdrSdrRatioInfo = true;
    }

    private void updateColorModeIfNeeded(@ActivityInfo.ColorMode int colorMode,
            float desiredRatio) {
        if (mAttachInfo.mThreadedRenderer == null) {
@@ -5739,22 +5728,8 @@ public final class ViewRootImpl implements ViewParent,
        if (desiredRatio == 0 || desiredRatio > automaticRatio) {
            desiredRatio = automaticRatio;
        }
        if (desiredRatio != mDesiredHdrSdrRatio) {
            mDesiredHdrSdrRatio = desiredRatio;
            updateRenderHdrSdrRatio();
            invalidate();

            if (mDesiredHdrSdrRatio < 1.01f) {
                mDisplay.unregisterHdrSdrRatioChangedListener(mHdrSdrRatioChangedListener);
                mHdrSdrRatioChangedListener = null;
            } else {
                mHdrSdrRatioChangedListener = display -> {
                    updateRenderHdrSdrRatio();
                    invalidate();
                };
                mDisplay.registerHdrSdrRatioChangedListener(mExecutor, mHdrSdrRatioChangedListener);
            }
        }
        mHdrRenderState.setDesiredHdrSdrRatio(desiredRatio);
    }

    @Override
@@ -6365,7 +6340,7 @@ public final class ViewRootImpl implements ViewParent,
    }

    final ViewRootHandler mHandler = new ViewRootHandler();
    private final Executor mExecutor = (Runnable r) -> {
    final Executor mExecutor = (Runnable r) -> {
        mHandler.post(r);
    };

@@ -8656,7 +8631,7 @@ public final class ViewRootImpl implements ViewParent,
            if (mAttachInfo.mThreadedRenderer != null) {
                mAttachInfo.mThreadedRenderer.setSurfaceControl(mSurfaceControl, mBlastBufferQueue);
            }
            updateRenderHdrSdrRatio();
            mHdrRenderState.forceUpdateHdrSdrRatio();
            if (mPreviousTransformHint != transformHint) {
                mPreviousTransformHint = transformHint;
                dispatchTransformHintChanged(transformHint);
@@ -9204,9 +9179,7 @@ public final class ViewRootImpl implements ViewParent,
    private void destroyHardwareRenderer() {
        ThreadedRenderer hardwareRenderer = mAttachInfo.mThreadedRenderer;

        if (mHdrSdrRatioChangedListener != null) {
            mDisplay.unregisterHdrSdrRatioChangedListener(mHdrSdrRatioChangedListener);
        }
        mHdrRenderState.stopListening();

        if (hardwareRenderer != null) {
            if (mHardwareRendererObserver != null) {
+7 −0
Original line number Diff line number Diff line
@@ -41,3 +41,10 @@ flag {
  description: "Enable r_8, r_16_uint, rg_1616_uint, and rgba_10101010 in the SDK"
  bug: "292545615"
}

flag {
  name: "animate_hdr_transitions"
  namespace: "core_graphics"
  description: "Automatically animate all changes in HDR headroom"
  bug: "314810174"
}