diff options
8 files changed, 307 insertions, 22 deletions
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java index 00d1570df799..b8b22e283175 100644 --- a/core/java/android/view/SurfaceControl.java +++ b/core/java/android/view/SurfaceControl.java @@ -3462,15 +3462,15 @@ public final class SurfaceControl implements Parcelable { * @return this This transaction for chaining * @hide */ - public @NonNull Transaction setCrop(@NonNull SurfaceControl sc, float top, float left, - float bottom, float right) { + public @NonNull Transaction setCrop(@NonNull SurfaceControl sc, float left, float top, + float right, float bottom) { checkPreconditions(sc); if (SurfaceControlRegistry.sCallStackDebuggingEnabled) { SurfaceControlRegistry.getProcessInstance().checkCallStackDebugging( "setCrop", this, sc, "crop={" + top + ", " + left + ", " + bottom + ", " + right + "}"); } - nativeSetCrop(mNativeObject, sc.mNativeObject, top, left, bottom, right); + nativeSetCrop(mNativeObject, sc.mNativeObject, left, top, right, bottom); return this; } diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java index 9cad3e58fa02..4df7649e1c9b 100644 --- a/core/java/android/view/SurfaceView.java +++ b/core/java/android/view/SurfaceView.java @@ -40,6 +40,7 @@ import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.PixelFormat; import android.graphics.Rect; +import android.graphics.RectF; import android.graphics.Region; import android.graphics.RenderNode; import android.hardware.input.InputManager; @@ -1666,7 +1667,7 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall } private final Rect mRTLastReportedPosition = new Rect(); - private final Rect mRTLastSetCrop = new Rect(); + private final RectF mRTLastSetCrop = new RectF(); private class SurfaceViewPositionUpdateListener implements RenderNode.PositionUpdateListener { private final int mRtSurfaceWidth; @@ -1711,16 +1712,18 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall @Override public void positionChanged(long frameNumber, int left, int top, int right, int bottom, - int clipLeft, int clipTop, int clipRight, int clipBottom) { + int clipLeft, int clipTop, int clipRight, int clipBottom, + int nodeWidth, int nodeHeight) { try { if (DEBUG_POSITION) { Log.d(TAG, String.format( "%d updateSurfacePosition RenderWorker, frameNr = %d, " + "position = [%d, %d, %d, %d] clip = [%d, %d, %d, %d] " - + "surfaceSize = %dx%d", + + "surfaceSize = %dx%d renderNodeSize = %d%d", System.identityHashCode(SurfaceView.this), frameNumber, left, top, right, bottom, clipLeft, clipTop, clipRight, clipBottom, - mRtSurfaceWidth, mRtSurfaceHeight)); + mRtSurfaceWidth, mRtSurfaceHeight, + nodeWidth, nodeHeight)); } synchronized (mSurfaceControlLock) { if (mSurfaceControl == null) return; @@ -1735,14 +1738,29 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall mRTLastReportedPosition.top /*positionTop*/, postScaleX, postScaleY); - mRTLastSetCrop.set(clipLeft, clipTop, clipRight, clipBottom); + // The computed crop is in view-relative dimensions, however we need it to be + // in buffer-relative dimensions. So scale the crop by the ratio between + // the view's unscaled width/height (nodeWidth/Height), and the surface's + // width/height + // That is, if the Surface has a fixed size of 50x50, the SurfaceView is laid + // out to a size of 100x100, and the SurfaceView is ultimately scaled to + // 1000x1000, then we need to scale the crop by just the 2x from surface + // domain to SV domain. + final float surfaceToNodeScaleX = (float) mRtSurfaceWidth / (float) nodeWidth; + final float surfaceToNodeScaleY = (float) mRtSurfaceHeight / (float) nodeHeight; + mRTLastSetCrop.set(clipLeft * surfaceToNodeScaleX, + clipTop * surfaceToNodeScaleY, + clipRight * surfaceToNodeScaleX, + clipBottom * surfaceToNodeScaleY); + if (DEBUG_POSITION) { - Log.d(TAG, String.format("Setting layer crop = [%d, %d, %d, %d] " + Log.d(TAG, String.format("Setting layer crop = [%f, %f, %f, %f] " + "from scale %f, %f", mRTLastSetCrop.left, mRTLastSetCrop.top, mRTLastSetCrop.right, mRTLastSetCrop.bottom, - postScaleX, postScaleY)); + surfaceToNodeScaleX, surfaceToNodeScaleY)); } - mPositionChangedTransaction.setCrop(mSurfaceControl, mRTLastSetCrop); + mPositionChangedTransaction.setCrop(mSurfaceControl, mRTLastSetCrop.left, + mRTLastSetCrop.top, mRTLastSetCrop.right, mRTLastSetCrop.bottom); if (mRTLastSetCrop.isEmpty()) { mPositionChangedTransaction.hide(mSurfaceControl); } else { diff --git a/graphics/java/android/graphics/RenderNode.java b/graphics/java/android/graphics/RenderNode.java index 211f74a47bdd..03a8b306f99d 100644 --- a/graphics/java/android/graphics/RenderNode.java +++ b/graphics/java/android/graphics/RenderNode.java @@ -279,7 +279,8 @@ public final class RenderNode { * @hide */ default void positionChanged(long frameNumber, int left, int top, int right, int bottom, - int clipLeft, int clipTop, int clipRight, int clipBottom) { + int clipLeft, int clipTop, int clipRight, int clipBottom, + int nodeWidth, int nodeHeight) { positionChanged(frameNumber, left, top, right, bottom); } @@ -304,11 +305,12 @@ public final class RenderNode { * @hide */ static boolean callPositionChanged2(WeakReference<PositionUpdateListener> weakListener, long frameNumber, int left, int top, int right, int bottom, - int clipLeft, int clipTop, int clipRight, int clipBottom) { + int clipLeft, int clipTop, int clipRight, int clipBottom, + int nodeWidth, int nodeHeight) { final PositionUpdateListener listener = weakListener.get(); if (listener != null) { listener.positionChanged(frameNumber, left, top, right, bottom, clipLeft, - clipTop, clipRight, clipBottom); + clipTop, clipRight, clipBottom, nodeWidth, nodeHeight); return true; } else { return false; @@ -401,10 +403,11 @@ public final class RenderNode { @Override public void positionChanged(long frameNumber, int left, int top, int right, int bottom, - int clipLeft, int clipTop, int clipRight, int clipBottom) { + int clipLeft, int clipTop, int clipRight, int clipBottom, + int nodeWidth, int nodeHeight) { for (PositionUpdateListener pul : mListeners) { pul.positionChanged(frameNumber, left, top, right, bottom, clipLeft, clipTop, - clipRight, clipBottom); + clipRight, clipBottom, nodeWidth, nodeHeight); } } diff --git a/libs/hwui/jni/android_graphics_RenderNode.cpp b/libs/hwui/jni/android_graphics_RenderNode.cpp index 6e03bbd0fa16..d9dc8eb8c1b1 100644 --- a/libs/hwui/jni/android_graphics_RenderNode.cpp +++ b/libs/hwui/jni/android_graphics_RenderNode.cpp @@ -593,9 +593,9 @@ static void android_view_RenderNode_requestPositionUpdates(JNIEnv* env, jobject, Matrix4 transform; SkIRect clipBounds; + uirenderer::Rect initialClipBounds; + const auto clipFlags = props.getClippingFlags(); if (enableClip) { - uirenderer::Rect initialClipBounds; - const auto clipFlags = props.getClippingFlags(); if (clipFlags) { props.getClippingRectForFlags(clipFlags, &initialClipBounds); } else { @@ -659,8 +659,8 @@ static void android_view_RenderNode_requestPositionUpdates(JNIEnv* env, jobject, static_cast<jint>(bounds.left), static_cast<jint>(bounds.top), static_cast<jint>(bounds.right), static_cast<jint>(bounds.bottom), static_cast<jint>(clipBounds.fLeft), static_cast<jint>(clipBounds.fTop), - static_cast<jint>(clipBounds.fRight), - static_cast<jint>(clipBounds.fBottom)); + static_cast<jint>(clipBounds.fRight), static_cast<jint>(clipBounds.fBottom), + static_cast<jint>(props.getWidth()), static_cast<jint>(props.getHeight())); } if (!keepListening) { env->DeleteGlobalRef(mListener); @@ -891,7 +891,7 @@ int register_android_view_RenderNode(JNIEnv* env) { gPositionListener.callPositionChanged = GetStaticMethodIDOrDie( env, clazz, "callPositionChanged", "(Ljava/lang/ref/WeakReference;JIIII)Z"); gPositionListener.callPositionChanged2 = GetStaticMethodIDOrDie( - env, clazz, "callPositionChanged2", "(Ljava/lang/ref/WeakReference;JIIIIIIII)Z"); + env, clazz, "callPositionChanged2", "(Ljava/lang/ref/WeakReference;JIIIIIIIIII)Z"); gPositionListener.callApplyStretch = GetStaticMethodIDOrDie( env, clazz, "callApplyStretch", "(Ljava/lang/ref/WeakReference;JFFFFFFFFFF)Z"); gPositionListener.callPositionLost = GetStaticMethodIDOrDie( diff --git a/tests/graphics/HwAccelerationTest/AndroidManifest.xml b/tests/graphics/HwAccelerationTest/AndroidManifest.xml index db3a992b9c7b..05b2f4c53b15 100644 --- a/tests/graphics/HwAccelerationTest/AndroidManifest.xml +++ b/tests/graphics/HwAccelerationTest/AndroidManifest.xml @@ -24,7 +24,7 @@ <uses-feature android:name="android.hardware.camera"/> <uses-feature android:name="android.hardware.camera.autofocus"/> - <uses-sdk android:minSdkVersion="21"/> + <uses-sdk android:minSdkVersion="21" /> <application android:label="HwUi" android:theme="@android:style/Theme.Material.Light"> @@ -409,6 +409,24 @@ </intent-filter> </activity> + <activity android:name="ScrollingZAboveSurfaceView" + android:label="SurfaceView/Z-Above scrolling" + android:exported="true"> + <intent-filter> + <action android:name="android.intent.action.MAIN"/> + <category android:name="com.android.test.hwui.TEST"/> + </intent-filter> + </activity> + + <activity android:name="ScrollingZAboveScaledSurfaceView" + android:label="SurfaceView/Z-Above scrolling, scaled surface" + android:exported="true"> + <intent-filter> + <action android:name="android.intent.action.MAIN"/> + <category android:name="com.android.test.hwui.TEST"/> + </intent-filter> + </activity> + <activity android:name="StretchySurfaceViewActivity" android:label="SurfaceView/Stretchy Movement" android:exported="true"> diff --git a/tests/graphics/HwAccelerationTest/res/layout/scrolling_zabove_surfaceview.xml b/tests/graphics/HwAccelerationTest/res/layout/scrolling_zabove_surfaceview.xml new file mode 100644 index 000000000000..31e5774dd1ad --- /dev/null +++ b/tests/graphics/HwAccelerationTest/res/layout/scrolling_zabove_surfaceview.xml @@ -0,0 +1,131 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2024 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. + --> + +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto" + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="vertical" + tools:context=".MainActivity"> + + <TextView + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="Above the ScrollView" + android:textColor="#FFFFFFFF" + android:background="#FF444444" + android:padding="32dp" /> + + <ScrollView + android:layout_width="match_parent" + android:layout_height="0dp" + android:layout_weight="1"> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical"> + + <TextView + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="Scrolling Header" + android:background="#FFCCCCCC" + android:padding="32dp" /> + + <SurfaceView + android:layout_width="match_parent" + android:layout_height="500dp" + android:id="@+id/surfaceview" /> + + <TextView + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="Scrolling Item" + android:background="#FFCCCCCC" + android:padding="32dp" /> + + <TextView + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="Scrolling Item" + android:background="#FFCCCCCC" + android:padding="32dp" /> + + <TextView + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="Scrolling Item" + android:background="#FFCCCCCC" + android:padding="32dp" /> + + <TextView + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="Scrolling Item" + android:background="#FFCCCCCC" + android:padding="32dp" /> + + <TextView + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="Scrolling Item" + android:background="#FFCCCCCC" + android:padding="32dp" /> + + <TextView + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="Scrolling Item" + android:background="#FFCCCCCC" + android:padding="32dp" /> + + <TextView + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="Scrolling Item" + android:background="#FFCCCCCC" + android:padding="32dp" /> + + <TextView + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="Scrolling Item" + android:background="#FFCCCCCC" + android:padding="32dp" /> + + <TextView + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="Scrolling Item" + android:background="#FFCCCCCC" + android:padding="32dp" /> + + </LinearLayout> + + </ScrollView> + + <TextView + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="Below the ScrollView" + android:textColor="#FFFFFFFF" + android:background="#FF444444" + android:padding="32dp" /> + +</LinearLayout>
\ No newline at end of file diff --git a/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/ScrollingZAboveScaledSurfaceView.kt b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/ScrollingZAboveScaledSurfaceView.kt new file mode 100644 index 000000000000..59ae885664db --- /dev/null +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/ScrollingZAboveScaledSurfaceView.kt @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2024 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.test.hwui + +import android.app.Activity +import android.graphics.Color +import android.graphics.Paint +import android.os.Bundle +import android.view.SurfaceHolder +import android.view.SurfaceView + +class ScrollingZAboveScaledSurfaceView : Activity() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.scrolling_zabove_surfaceview) + + findViewById<SurfaceView>(R.id.surfaceview).apply { + setZOrderOnTop(true) + holder.setFixedSize(1000, 2000) + holder.addCallback(object : SurfaceHolder.Callback { + override fun surfaceCreated(p0: SurfaceHolder) { + + } + + override fun surfaceChanged(holder: SurfaceHolder, format: Int, width: Int, height: Int) { + holder.unlockCanvasAndPost(holder.lockCanvas().apply { + drawColor(Color.BLUE) + val paint = Paint() + paint.textSize = 16 * resources.displayMetrics.density + paint.textAlign = Paint.Align.CENTER + paint.color = Color.WHITE + drawText("I'm a setZOrderOnTop(true) SurfaceView!", + (width / 2).toFloat(), (height / 2).toFloat(), paint) + }) + } + + override fun surfaceDestroyed(p0: SurfaceHolder) { + + } + + }) + } + } +}
\ No newline at end of file diff --git a/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/ScrollingZAboveSurfaceView.kt b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/ScrollingZAboveSurfaceView.kt new file mode 100644 index 000000000000..ccb71ec0ff2a --- /dev/null +++ b/tests/graphics/HwAccelerationTest/src/com/android/test/hwui/ScrollingZAboveSurfaceView.kt @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2024 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.test.hwui + +import android.app.Activity +import android.graphics.Color +import android.graphics.Paint +import android.os.Bundle +import android.view.SurfaceHolder +import android.view.SurfaceView + +class ScrollingZAboveSurfaceView : Activity() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.scrolling_zabove_surfaceview) + + findViewById<SurfaceView>(R.id.surfaceview).apply { + setZOrderOnTop(true) + holder.addCallback(object : SurfaceHolder.Callback { + override fun surfaceCreated(p0: SurfaceHolder) { + + } + + override fun surfaceChanged(holder: SurfaceHolder, format: Int, width: Int, height: Int) { + holder.unlockCanvasAndPost(holder.lockCanvas().apply { + drawColor(Color.BLUE) + val paint = Paint() + paint.textSize = 16 * resources.displayMetrics.density + paint.textAlign = Paint.Align.CENTER + paint.color = Color.WHITE + drawText("I'm a setZOrderOnTop(true) SurfaceView!", + (width / 2).toFloat(), (height / 2).toFloat(), paint) + }) + } + + override fun surfaceDestroyed(p0: SurfaceHolder) { + + } + + }) + } + } +}
\ No newline at end of file |