From eb53e523957de8967b0c391166b63fa7835c9833 Mon Sep 17 00:00:00 2001 From: Vishnu Nair Date: Fri, 8 May 2020 18:03:12 -0700 Subject: [PATCH] Provide a fixed transform hint if the layer is in a fixed orientation 2/2 The transform hint is used to prevent allocating a buffer of a different size when a layer is rotated. The producer can choose to consume the hint and allocate the buffer with the same size. Provide the graphic producer a transform hint if the layer and its children are in an orientation different from the display's orientation. The caller is responsible for clearing this transform hint if the layer is no longer in a fixed orientation. Bug: 152919661 Test: atest VulkanPreTransformTest Test: confirm with winscope trace, buffers are allocated taking into account the transform hint in fixed orientation scenarios Test: go/wm-smoke Change-Id: I2ccc21ed8af015716e6cdfde1e3cec67c99f3339 --- core/java/android/view/SurfaceControl.java | 35 +++++++++++++++++++ core/jni/android_view_SurfaceControl.cpp | 9 +++++ .../android/server/wm/SeamlessRotator.java | 21 +++++++++-- .../com/android/server/wm/WindowState.java | 3 +- .../com/android/server/wm/WindowToken.java | 2 +- .../android/server/wm/StubTransaction.java | 12 +++++++ 6 files changed, 78 insertions(+), 4 deletions(-) diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java index c0c29eba41d1f..9109f50247e0a 100644 --- a/core/java/android/view/SurfaceControl.java +++ b/core/java/android/view/SurfaceControl.java @@ -220,6 +220,8 @@ public final class SurfaceControl implements Parcelable { private static native long nativeAcquireFrameRateFlexibilityToken(); private static native void nativeReleaseFrameRateFlexibilityToken(long token); + private static native void nativeSetFixedTransformHint(long transactionObj, long nativeObject, + int transformHint); private final CloseGuard mCloseGuard = CloseGuard.get(); private String mName; @@ -2306,6 +2308,39 @@ public final class SurfaceControl implements Parcelable { return this; } + /** + * Provide the graphic producer a transform hint if the layer and its children are + * in an orientation different from the display's orientation. The caller is responsible + * for clearing this transform hint if the layer is no longer in a fixed orientation. + * + * The transform hint is used to prevent allocating a buffer of different size when a + * layer is rotated. The producer can choose to consume the hint and allocate the buffer + * with the same size. + * + * @return This Transaction. + * @hide + */ + @NonNull + public Transaction setFixedTransformHint(@NonNull SurfaceControl sc, + @Surface.Rotation int transformHint) { + checkPreconditions(sc); + nativeSetFixedTransformHint(mNativeObject, sc.mNativeObject, transformHint); + return this; + } + + /** + * Clearing any transform hint if set on this layer. + * + * @return This Transaction. + * @hide + */ + @NonNull + public Transaction unsetFixedTransformHint(@NonNull SurfaceControl sc) { + checkPreconditions(sc); + nativeSetFixedTransformHint(mNativeObject, sc.mNativeObject, -1/* INVALID_ROTATION */); + return this; + } + /** * Set the Z-order for a given SurfaceControl, relative to it's siblings. * If two siblings share the same Z order the ordering is undefined. Surfaces diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp index 36b4b6aad4b46..e553a786da96b 100644 --- a/core/jni/android_view_SurfaceControl.cpp +++ b/core/jni/android_view_SurfaceControl.cpp @@ -645,6 +645,14 @@ static void nativeReleaseFrameRateFlexibilityToken(JNIEnv* env, jclass clazz, jl token->decStrong((void*)nativeAcquireFrameRateFlexibilityToken); } +static void nativeSetFixedTransformHint(JNIEnv* env, jclass clazz, jlong transactionObj, + jlong nativeObject, jint transformHint) { + auto transaction = reinterpret_cast(transactionObj); + + SurfaceControl* const ctrl = reinterpret_cast(nativeObject); + transaction->setFixedTransformHint(ctrl, transformHint); +} + static jlongArray nativeGetPhysicalDisplayIds(JNIEnv* env, jclass clazz) { const auto displayIds = SurfaceComposerClient::getPhysicalDisplayIds(); jlongArray array = env->NewLongArray(displayIds.size()); @@ -1644,6 +1652,7 @@ static const JNINativeMethod sSurfaceControlMethods[] = { (void*)nativeSetGlobalShadowSettings }, {"nativeGetHandle", "(J)J", (void*)nativeGetHandle }, + {"nativeSetFixedTransformHint", "(JJI)V", (void*)nativeSetFixedTransformHint}, }; int register_android_view_SurfaceControl(JNIEnv* env) diff --git a/services/core/java/com/android/server/wm/SeamlessRotator.java b/services/core/java/com/android/server/wm/SeamlessRotator.java index c79cb04a824f6..3d305e4d852d3 100644 --- a/services/core/java/com/android/server/wm/SeamlessRotator.java +++ b/services/core/java/com/android/server/wm/SeamlessRotator.java @@ -45,11 +45,22 @@ public class SeamlessRotator { private final float[] mFloat9 = new float[9]; private final int mOldRotation; private final int mNewRotation; + /* If the seamless rotator is used to rotate part of the hierarchy, then provide a transform + * hint based on the display orientation if the entire display was rotated. When the display + * orientation matches the hierarchy orientation, the fixed transform hint will be removed. + * This will prevent allocating different buffer sizes by the graphic producers when the + * orientation of a layer changes. + */ + private final boolean mApplyFixedTransformHint; + private final int mFixedTransformHint; - public SeamlessRotator(@Rotation int oldRotation, @Rotation int newRotation, DisplayInfo info) { + + public SeamlessRotator(@Rotation int oldRotation, @Rotation int newRotation, DisplayInfo info, + boolean applyFixedTransformationHint) { mOldRotation = oldRotation; mNewRotation = newRotation; - + mApplyFixedTransformHint = applyFixedTransformationHint; + mFixedTransformHint = oldRotation; final boolean flipped = info.rotation == ROTATION_90 || info.rotation == ROTATION_270; final int pH = flipped ? info.logicalWidth : info.logicalHeight; final int pW = flipped ? info.logicalHeight : info.logicalWidth; @@ -70,6 +81,9 @@ public class SeamlessRotator { final float[] winSurfacePos = {win.mLastSurfacePosition.x, win.mLastSurfacePosition.y}; mTransform.mapPoints(winSurfacePos); transaction.setPosition(win.getSurfaceControl(), winSurfacePos[0], winSurfacePos[1]); + if (mApplyFixedTransformHint) { + transaction.setFixedTransformHint(win.mSurfaceControl, mFixedTransformHint); + } } /** @@ -109,6 +123,9 @@ public class SeamlessRotator { mTransform.reset(); t.setMatrix(win.mSurfaceControl, mTransform, mFloat9); t.setPosition(win.mSurfaceControl, win.mLastSurfacePosition.x, win.mLastSurfacePosition.y); + if (mApplyFixedTransformHint) { + t.unsetFixedTransformHint(win.mSurfaceControl); + } } public void dump(PrintWriter pw) { diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index f6473fd8acd14..49d6889b95f93 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -741,7 +741,8 @@ class WindowState extends WindowContainer implements WindowManagerP if (mControllableInsetProvider != null) { mControllableInsetProvider.startSeamlessRotation(); } - mPendingSeamlessRotate = new SeamlessRotator(oldRotation, rotation, getDisplayInfo()); + mPendingSeamlessRotate = new SeamlessRotator(oldRotation, rotation, getDisplayInfo(), + false /* applyFixedTransformationHint */); mPendingSeamlessRotate.unrotate(transaction, this); getDisplayContent().getDisplayRotation().markForSeamlessRotation(this, true /* seamlesslyRotated */); diff --git a/services/core/java/com/android/server/wm/WindowToken.java b/services/core/java/com/android/server/wm/WindowToken.java index 472773e1bb1a2..96d8124e27937 100644 --- a/services/core/java/com/android/server/wm/WindowToken.java +++ b/services/core/java/com/android/server/wm/WindowToken.java @@ -141,7 +141,7 @@ class WindowToken extends WindowContainer { mRotatedOverrideConfiguration = rotatedConfig; // This will use unrotate as rotate, so the new and old rotation are inverted. mRotator = new SeamlessRotator(rotatedDisplayInfo.rotation, currentRotation, - rotatedDisplayInfo); + rotatedDisplayInfo, true /* applyFixedTransformationHint */); } /** diff --git a/services/tests/wmtests/src/com/android/server/wm/StubTransaction.java b/services/tests/wmtests/src/com/android/server/wm/StubTransaction.java index 851b0523b058a..d7eedd990f040 100644 --- a/services/tests/wmtests/src/com/android/server/wm/StubTransaction.java +++ b/services/tests/wmtests/src/com/android/server/wm/StubTransaction.java @@ -16,6 +16,7 @@ package com.android.server.wm; +import android.annotation.NonNull; import android.graphics.Matrix; import android.graphics.Rect; import android.graphics.Region; @@ -265,4 +266,15 @@ public class StubTransaction extends SurfaceControl.Transaction { public SurfaceControl.Transaction setShadowRadius(SurfaceControl sc, float shadowRadius) { return this; } + + @Override + public SurfaceControl.Transaction setFixedTransformHint(SurfaceControl sc, + @Surface.Rotation int transformHint) { + return this; + } + + @Override + public SurfaceControl.Transaction unsetFixedTransformHint(@NonNull SurfaceControl sc) { + return this; + } }