diff options
-rw-r--r-- | api/current.txt | 7 | ||||
-rw-r--r-- | core/java/android/view/RenderNode.java | 10 | ||||
-rw-r--r-- | core/java/android/view/View.java | 58 | ||||
-rw-r--r-- | core/java/android/view/ViewPropertyAnimator.java | 36 | ||||
-rw-r--r-- | core/jni/android_view_RenderNode.cpp | 14 | ||||
-rw-r--r-- | core/res/res/values/attrs.xml | 5 | ||||
-rw-r--r-- | core/res/res/values/public.xml | 1 | ||||
-rw-r--r-- | libs/hwui/RenderNode.cpp | 16 | ||||
-rw-r--r-- | libs/hwui/RenderProperties.cpp | 3 | ||||
-rw-r--r-- | libs/hwui/RenderProperties.h | 21 | ||||
-rw-r--r-- | libs/hwui/utils/MathUtils.h | 4 | ||||
-rw-r--r-- | tests/HwAccelerationTest/res/layout/projection_clipping.xml | 2 |
12 files changed, 159 insertions, 18 deletions
diff --git a/api/current.txt b/api/current.txt index 8466443..ff67634 100644 --- a/api/current.txt +++ b/api/current.txt @@ -491,6 +491,7 @@ package android { field public static final int editTextStyle = 16842862; // 0x101006e field public static final deprecated int editable = 16843115; // 0x101016b field public static final int editorExtras = 16843300; // 0x1010224 + field public static final int elevation = 16843851; // 0x101044b field public static final int ellipsize = 16842923; // 0x10100ab field public static final int ems = 16843096; // 0x1010158 field public static final int enabled = 16842766; // 0x101000e @@ -30121,6 +30122,7 @@ package android.view { method public int getDrawingCacheQuality(); method public void getDrawingRect(android.graphics.Rect); method public long getDrawingTime(); + method public float getElevation(); method public boolean getFilterTouchesWhenObscured(); method public boolean getFitsSystemWindows(); method public java.util.ArrayList<android.view.View> getFocusables(int); @@ -30219,6 +30221,7 @@ package android.view { method public void getWindowVisibleDisplayFrame(android.graphics.Rect); method public float getX(); method public float getY(); + method public float getZ(); method public boolean hasFocus(); method public boolean hasFocusable(); method public boolean hasNestedScrollingParent(); @@ -30385,6 +30388,7 @@ package android.view { method public void setDrawingCacheEnabled(boolean); method public void setDrawingCacheQuality(int); method public void setDuplicateParentStateEnabled(boolean); + method public void setElevation(float); method public void setEnabled(boolean); method public void setFadingEdgeLength(int); method public void setFilterTouchesWhenObscured(boolean); @@ -30470,6 +30474,7 @@ package android.view { method public void setWillNotDraw(boolean); method public void setX(float); method public void setY(float); + method public void setZ(float); method public boolean showContextMenu(); method public android.view.ActionMode startActionMode(android.view.ActionMode.Callback); method public void startAnimation(android.view.animation.Animation); @@ -31049,6 +31054,8 @@ package android.view { method public android.view.ViewPropertyAnimator xBy(float); method public android.view.ViewPropertyAnimator y(float); method public android.view.ViewPropertyAnimator yBy(float); + method public android.view.ViewPropertyAnimator z(float); + method public android.view.ViewPropertyAnimator zBy(float); } public final class ViewStub extends android.view.View { diff --git a/core/java/android/view/RenderNode.java b/core/java/android/view/RenderNode.java index 30e4281..3dc09c4 100644 --- a/core/java/android/view/RenderNode.java +++ b/core/java/android/view/RenderNode.java @@ -443,6 +443,14 @@ public class RenderNode { return nHasOverlappingRendering(mNativeRenderNode); } + public void setElevation(float lift) { + nSetElevation(mNativeRenderNode, lift); + } + + public float getElevation() { + return nGetElevation(mNativeRenderNode); + } + /** * Sets the translation value for the display list on the X axis. * @@ -854,6 +862,7 @@ public class RenderNode { private static native void nSetAlpha(long renderNode, float alpha); private static native void nSetHasOverlappingRendering(long renderNode, boolean hasOverlappingRendering); + private static native void nSetElevation(long renderNode, float lift); private static native void nSetTranslationX(long renderNode, float translationX); private static native void nSetTranslationY(long renderNode, float translationY); private static native void nSetTranslationZ(long renderNode, float translationZ); @@ -874,6 +883,7 @@ public class RenderNode { private static native float nGetCameraDistance(long renderNode); private static native float nGetScaleX(long renderNode); private static native float nGetScaleY(long renderNode); + private static native float nGetElevation(long renderNode); private static native float nGetTranslationX(long renderNode); private static native float nGetTranslationY(long renderNode); private static native float nGetTranslationZ(long renderNode); diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index fdf31fa..463a2f7 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -3649,6 +3649,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, float tx = 0; float ty = 0; float tz = 0; + float elevation = 0; float rotation = 0; float rotationX = 0; float rotationY = 0; @@ -3732,6 +3733,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback, tz = a.getDimensionPixelOffset(attr, 0); transformSet = true; break; + case com.android.internal.R.styleable.View_elevation: + elevation = a.getDimensionPixelOffset(attr, 0); + transformSet = true; + break; case com.android.internal.R.styleable.View_rotation: rotation = a.getFloat(attr, 0); transformSet = true; @@ -4080,6 +4085,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, setTranslationX(tx); setTranslationY(ty); setTranslationZ(tz); + setElevation(elevation); setRotation(rotation); setRotationX(rotationX); setRotationY(rotationY); @@ -10435,6 +10441,48 @@ public class View implements Drawable.Callback, KeyEvent.Callback, setTranslationY(y - mTop); } + /** + * The visual z position of this view, in pixels. This is equivalent to the + * {@link #setTranslationZ(float) translationZ} property plus the current + * {@link #getElevation() elevation} property. + * + * @return The visual z position of this view, in pixels. + */ + @ViewDebug.ExportedProperty(category = "drawing") + public float getZ() { + return getElevation() + getTranslationZ(); + } + + /** + * Sets the visual z position of this view, in pixels. This is equivalent to setting the + * {@link #setTranslationZ(float) translationZ} property to be the difference between + * the x value passed in and the current {@link #getElevation() elevation} property. + * + * @param z The visual z position of this view, in pixels. + */ + public void setZ(float z) { + setTranslationZ(z - getElevation()); + } + + @ViewDebug.ExportedProperty(category = "drawing") + public float getElevation() { + return mRenderNode.getElevation(); + } + + /** + * Sets the base depth location of this view. + * + * @attr ref android.R.styleable#View_elevation + */ + public void setElevation(float elevation) { + if (elevation != getElevation()) { + invalidateViewProperty(true, false); + mRenderNode.setElevation(elevation); + invalidateViewProperty(false, true); + + invalidateParentIfNeededAndWasQuickRejected(); + } + } /** * The horizontal location of this view relative to its {@link #getLeft() left} position. @@ -10502,9 +10550,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } /** - * The depth location of this view relative to its parent. + * The depth location of this view relative to its {@link #getElevation() elevation}. * - * @return The depth of this view relative to its parent. + * @return The depth of this view relative to its elevation. */ @ViewDebug.ExportedProperty(category = "drawing") public float getTranslationZ() { @@ -10512,7 +10560,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } /** - * Sets the depth location of this view relative to its parent. + * Sets the depth location of this view relative to its {@link #getElevation() elevation}. * * @attr ref android.R.styleable#View_translationZ */ @@ -11184,7 +11232,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } // Damage the entire IsolatedZVolume recieving this view's shadow. - if (isHardwareAccelerated() && getTranslationZ() != 0) { + if (isHardwareAccelerated() && getZ() != 0) { damageShadowReceiver(); } } @@ -11260,7 +11308,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } else { damageInParent(); } - if (isHardwareAccelerated() && invalidateParent && getTranslationZ() != 0) { + if (isHardwareAccelerated() && invalidateParent && getZ() != 0) { damageShadowReceiver(); } } diff --git a/core/java/android/view/ViewPropertyAnimator.java b/core/java/android/view/ViewPropertyAnimator.java index 6b21451..b1aa7b2 100644 --- a/core/java/android/view/ViewPropertyAnimator.java +++ b/core/java/android/view/ViewPropertyAnimator.java @@ -144,10 +144,11 @@ public class ViewPropertyAnimator { private static final int ROTATION_Y = 0x0080; private static final int X = 0x0100; private static final int Y = 0x0200; - private static final int ALPHA = 0x0400; + private static final int Z = 0x0400; + private static final int ALPHA = 0x0800; private static final int TRANSFORM_MASK = TRANSLATION_X | TRANSLATION_Y | TRANSLATION_Z | - SCALE_X | SCALE_Y | ROTATION | ROTATION_X | ROTATION_Y | X | Y; + SCALE_X | SCALE_Y | ROTATION | ROTATION_X | ROTATION_Y | X | Y | Z; /** * The mechanism by which the user can request several properties that are then animated @@ -470,6 +471,32 @@ public class ViewPropertyAnimator { } /** + * This method will cause the View's <code>z</code> property to be animated to the + * specified value. Animations already running on the property will be canceled. + * + * @param value The value to be animated to. + * @see View#setZ(float) + * @return This object, allowing calls to methods in this class to be chained. + */ + public ViewPropertyAnimator z(float value) { + animateProperty(Z, value); + return this; + } + + /** + * This method will cause the View's <code>z</code> property to be animated by the + * specified value. Animations already running on the property will be canceled. + * + * @param value The amount to be animated by, as an offset from the current value. + * @see View#setZ(float) + * @return This object, allowing calls to methods in this class to be chained. + */ + public ViewPropertyAnimator zBy(float value) { + animatePropertyBy(Z, value); + return this; + } + + /** * This method will cause the View's <code>rotation</code> property to be animated to the * specified value. Animations already running on the property will be canceled. * @@ -957,6 +984,9 @@ public class ViewPropertyAnimator { case Y: renderNode.setTranslationY(value - mView.mTop); break; + case Z: + renderNode.setTranslationZ(value - renderNode.getElevation()); + break; case ALPHA: info.mAlpha = value; renderNode.setAlpha(value); @@ -993,6 +1023,8 @@ public class ViewPropertyAnimator { return mView.mLeft + node.getTranslationX(); case Y: return mView.mTop + node.getTranslationY(); + case Z: + return node.getElevation() + node.getTranslationZ(); case ALPHA: return mView.mTransformationInfo.mAlpha; } diff --git a/core/jni/android_view_RenderNode.cpp b/core/jni/android_view_RenderNode.cpp index 8dacfeb..3ad2ae5 100644 --- a/core/jni/android_view_RenderNode.cpp +++ b/core/jni/android_view_RenderNode.cpp @@ -164,6 +164,12 @@ static void android_view_RenderNode_setHasOverlappingRendering(JNIEnv* env, renderNode->mutateStagingProperties().setHasOverlappingRendering(hasOverlappingRendering); } +static void android_view_RenderNode_setElevation(JNIEnv* env, + jobject clazz, jlong renderNodePtr, float elevation) { + RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr); + renderNode->mutateStagingProperties().setElevation(elevation); +} + static void android_view_RenderNode_setTranslationX(JNIEnv* env, jobject clazz, jlong renderNodePtr, float tx) { RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr); @@ -331,6 +337,12 @@ static jfloat android_view_RenderNode_getScaleY(JNIEnv* env, return renderNode->stagingProperties().getScaleY(); } +static jfloat android_view_RenderNode_getElevation(JNIEnv* env, + jobject clazz, jlong renderNodePtr) { + RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr); + return renderNode->stagingProperties().getElevation(); +} + static jfloat android_view_RenderNode_getTranslationX(JNIEnv* env, jobject clazz, jlong renderNodePtr) { RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr); @@ -457,6 +469,7 @@ static JNINativeMethod gMethods[] = { { "nSetAlpha", "(JF)V", (void*) android_view_RenderNode_setAlpha }, { "nSetHasOverlappingRendering", "(JZ)V", (void*) android_view_RenderNode_setHasOverlappingRendering }, + { "nSetElevation", "(JF)V", (void*) android_view_RenderNode_setElevation }, { "nSetTranslationX", "(JF)V", (void*) android_view_RenderNode_setTranslationX }, { "nSetTranslationY", "(JF)V", (void*) android_view_RenderNode_setTranslationY }, { "nSetTranslationZ", "(JF)V", (void*) android_view_RenderNode_setTranslationZ }, @@ -485,6 +498,7 @@ static JNINativeMethod gMethods[] = { { "nGetCameraDistance", "(J)F", (void*) android_view_RenderNode_getCameraDistance }, { "nGetScaleX", "(J)F", (void*) android_view_RenderNode_getScaleX }, { "nGetScaleY", "(J)F", (void*) android_view_RenderNode_getScaleY }, + { "nGetElevation", "(J)F", (void*) android_view_RenderNode_getElevation }, { "nGetTranslationX", "(J)F", (void*) android_view_RenderNode_getTranslationX }, { "nGetTranslationY", "(J)F", (void*) android_view_RenderNode_getTranslationY }, { "nGetTranslationZ", "(J)F", (void*) android_view_RenderNode_getTranslationZ }, diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml index 69440be..abac60e 100644 --- a/core/res/res/values/attrs.xml +++ b/core/res/res/values/attrs.xml @@ -2191,6 +2191,9 @@ (completely opaque). --> <attr name="alpha" format="float" /> + <!-- base z depth of the view --> + <attr name="elevation" format="dimension" /> + <!-- translation in x of the view. This value is added post-layout to the left property of the view, which is set by its layout. --> <attr name="translationX" format="dimension" /> @@ -2199,7 +2202,7 @@ property of the view, which is set by its layout. --> <attr name="translationY" format="dimension" /> - <!-- translation in z of the view. This value is added post-layout to its position. --> + <!-- translation in z of the view. This value is added to its elevation. --> <attr name="translationZ" format="dimension" /> <!-- x location of the pivot point around which the view will rotate and scale. diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml index f68f759..85ef004 100644 --- a/core/res/res/values/public.xml +++ b/core/res/res/values/public.xml @@ -2163,6 +2163,7 @@ <public type="attr" name="windowAllowEnterTransitionOverlap" /> <public type="attr" name="sessionService" /> <public type="attr" name="switchStyle" /> + <public type="attr" name="elevation" /> <public-padding type="dimen" name="l_resource_pad" end="0x01050010" /> diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp index 2008f02..838e5ac 100644 --- a/libs/hwui/RenderNode.cpp +++ b/libs/hwui/RenderNode.cpp @@ -219,11 +219,11 @@ void RenderNode::applyViewPropertyTransforms(mat4& matrix, bool true3dTransform) matrix.multiply(anim); } - bool applyTranslationZ = true3dTransform && !MathUtils::isZero(properties().getTranslationZ()); + bool applyTranslationZ = true3dTransform && !MathUtils::isZero(properties().getZ()); if (properties().hasTransformMatrix() || applyTranslationZ) { if (properties().isTransformTranslateOnly()) { matrix.translate(properties().getTranslationX(), properties().getTranslationY(), - true3dTransform ? properties().getTranslationZ() : 0.0f); + true3dTransform ? properties().getZ() : 0.0f); } else { if (!true3dTransform) { matrix.multiply(*properties().getTransformMatrix()); @@ -232,7 +232,7 @@ void RenderNode::applyViewPropertyTransforms(mat4& matrix, bool true3dTransform) true3dMat.loadTranslate( properties().getPivotX() + properties().getTranslationX(), properties().getPivotY() + properties().getTranslationY(), - properties().getTranslationZ()); + properties().getZ()); true3dMat.rotate(properties().getRotationX(), 1, 0, 0); true3dMat.rotate(properties().getRotationY(), 0, 1, 0); true3dMat.rotate(properties().getRotation(), 0, 0, 1); @@ -344,7 +344,9 @@ private: void RenderNode::deferNodeTree(DeferStateStruct& deferStruct) { DeferOperationHandler handler(deferStruct, 0); - if (properties().getTranslationZ() > 0.0f) issueDrawShadowOperation(Matrix4::identity(), handler); + if (MathUtils::isPositive(properties().getZ())) { + issueDrawShadowOperation(Matrix4::identity(), handler); + } issueOperations<DeferOperationHandler>(deferStruct.mRenderer, handler); } @@ -380,7 +382,9 @@ private: void RenderNode::replayNodeTree(ReplayStateStruct& replayStruct) { ReplayOperationHandler handler(replayStruct, 0); - if (properties().getTranslationZ() > 0.0f) issueDrawShadowOperation(Matrix4::identity(), handler); + if (MathUtils::isPositive(properties().getZ())) { + issueDrawShadowOperation(Matrix4::identity(), handler); + } issueOperations<ReplayOperationHandler>(replayStruct.mRenderer, handler); } @@ -395,7 +399,7 @@ void RenderNode::buildZSortedChildList(Vector<ZDrawDisplayListOpPair>& zTranslat for (unsigned int i = 0; i < mDisplayListData->children().size(); i++) { DrawDisplayListOp* childOp = mDisplayListData->children()[i]; RenderNode* child = childOp->mDisplayList; - float childZ = child->properties().getTranslationZ(); + float childZ = child->properties().getZ(); if (!MathUtils::isZero(childZ)) { zTranslatedNodes.add(ZDrawDisplayListOpPair(childZ, childOp)); diff --git a/libs/hwui/RenderProperties.cpp b/libs/hwui/RenderProperties.cpp index a922db8..9ec7297 100644 --- a/libs/hwui/RenderProperties.cpp +++ b/libs/hwui/RenderProperties.cpp @@ -37,6 +37,7 @@ RenderProperties::PrimitiveFields::PrimitiveFields() , mProjectionReceiver(false) , mAlpha(1) , mHasOverlappingRendering(true) + , mElevation(0) , mTranslationX(0), mTranslationY(0), mTranslationZ(0) , mRotation(0), mRotationX(0), mRotationY(0) , mScaleX(1), mScaleY(1) @@ -100,7 +101,7 @@ void RenderProperties::debugOutputProperties(const int level) const { if (hasTransformMatrix()) { if (isTransformTranslateOnly()) { ALOGD("%*sTranslate %.2f, %.2f, %.2f", - level * 2, "", mPrimitiveFields.mTranslationX, mPrimitiveFields.mTranslationY, mPrimitiveFields.mTranslationZ); + level * 2, "", getTranslationX(), getTranslationY(), getZ()); } else { ALOGD("%*sConcatMatrix %p: " SK_MATRIX_STRING, level * 2, "", mComputedFields.mTransformMatrix, SK_MATRIX_ARGS(mComputedFields.mTransformMatrix)); diff --git a/libs/hwui/RenderProperties.h b/libs/hwui/RenderProperties.h index 4270da2..8fc2dd0 100644 --- a/libs/hwui/RenderProperties.h +++ b/libs/hwui/RenderProperties.h @@ -105,6 +105,17 @@ public: return mPrimitiveFields.mHasOverlappingRendering; } + void setElevation(float elevation) { + if (elevation != mPrimitiveFields.mElevation) { + mPrimitiveFields.mElevation = elevation; + // mMatrixOrPivotDirty not set, since matrix doesn't respect Z + } + } + + float getElevation() const { + return mPrimitiveFields.mElevation; + } + void setTranslationX(float translationX) { if (translationX != mPrimitiveFields.mTranslationX) { mPrimitiveFields.mTranslationX = translationX; @@ -130,7 +141,7 @@ public: void setTranslationZ(float translationZ) { if (translationZ != mPrimitiveFields.mTranslationZ) { mPrimitiveFields.mTranslationZ = translationZ; - mPrimitiveFields.mMatrixOrPivotDirty = true; + // mMatrixOrPivotDirty not set, since matrix doesn't respect Z } } @@ -138,6 +149,10 @@ public: return mPrimitiveFields.mTranslationZ; } + float getZ() const { + return getElevation() + getTranslationZ(); + } + void setRotation(float rotation) { if (rotation != mPrimitiveFields.mRotation) { mPrimitiveFields.mRotation = rotation; @@ -302,7 +317,8 @@ public: } void setLeftTopRightBottom(int left, int top, int right, int bottom) { - if (left != mPrimitiveFields.mLeft || top != mPrimitiveFields.mTop || right != mPrimitiveFields.mRight || bottom != mPrimitiveFields.mBottom) { + if (left != mPrimitiveFields.mLeft || top != mPrimitiveFields.mTop + || right != mPrimitiveFields.mRight || bottom != mPrimitiveFields.mBottom) { mPrimitiveFields.mLeft = left; mPrimitiveFields.mTop = top; mPrimitiveFields.mRight = right; @@ -429,6 +445,7 @@ private: bool mProjectionReceiver; float mAlpha; bool mHasOverlappingRendering; + float mElevation; float mTranslationX, mTranslationY, mTranslationZ; float mRotation, mRotationX, mRotationY; float mScaleX, mScaleY; diff --git a/libs/hwui/utils/MathUtils.h b/libs/hwui/utils/MathUtils.h index 57ba8fa..7deabe9 100644 --- a/libs/hwui/utils/MathUtils.h +++ b/libs/hwui/utils/MathUtils.h @@ -29,6 +29,10 @@ public: inline static bool isZero(float value) { return (value >= -gNonZeroEpsilon) && (value <= gNonZeroEpsilon); } + + inline static bool isPositive(float value) { + return value >= gNonZeroEpsilon; + } }; // class MathUtils } /* namespace uirenderer */ diff --git a/tests/HwAccelerationTest/res/layout/projection_clipping.xml b/tests/HwAccelerationTest/res/layout/projection_clipping.xml index 7caf90a..7177fc8f 100644 --- a/tests/HwAccelerationTest/res/layout/projection_clipping.xml +++ b/tests/HwAccelerationTest/res/layout/projection_clipping.xml @@ -6,7 +6,7 @@ <FrameLayout android:translationX="50dp" android:translationY="50dp" - android:translationZ="30dp" + android:elevation="30dp" android:layout_width="200dp" android:layout_height="200dp" android:background="@drawable/round_rect_background"> |