diff options
author | Chet Haase <chet@google.com> | 2012-03-29 16:28:32 -0700 |
---|---|---|
committer | Chet Haase <chet@google.com> | 2012-04-02 15:31:24 -0700 |
commit | 9420abd56a2af7ddbeb70562b79d61b2dca8c5a1 (patch) | |
tree | 8625a64e2d9ffd1520d890c2eb7989ccbef28adc /core | |
parent | 1d6013357847983180a317e2acaf807bde8b7ea7 (diff) | |
download | frameworks_base-9420abd56a2af7ddbeb70562b79d61b2dca8c5a1.zip frameworks_base-9420abd56a2af7ddbeb70562b79d61b2dca8c5a1.tar.gz frameworks_base-9420abd56a2af7ddbeb70562b79d61b2dca8c5a1.tar.bz2 |
Re-enable DisplayList properties.
Re-enabling DisplayList properties last week caused some app
errors due to the way that some transforms were being handled (specifically,
those coming from the old Animations and ViewGroup's childStaticTransformation
field). This change pushes *all* transform/alpha data from View.draw() into
the view's DisplayList, making DisplayLists more encapsulated (and correct).
Change-Id: Ia702c6aae050784bb3ed505aa87553113f8a1938
Diffstat (limited to 'core')
-rw-r--r-- | core/java/android/view/DisplayList.java | 24 | ||||
-rw-r--r-- | core/java/android/view/GLES20DisplayList.java | 16 | ||||
-rw-r--r-- | core/java/android/view/View.java | 76 | ||||
-rw-r--r-- | core/jni/android_view_GLES20DisplayList.cpp | 60 |
4 files changed, 126 insertions, 50 deletions
diff --git a/core/java/android/view/DisplayList.java b/core/java/android/view/DisplayList.java index e2aafa9..33631b7 100644 --- a/core/java/android/view/DisplayList.java +++ b/core/java/android/view/DisplayList.java @@ -16,6 +16,8 @@ package android.view; +import android.graphics.Matrix; + /** * A display lists records a series of graphics related operation and can replay * them later. Display lists are usually built by recording operations on a @@ -117,12 +119,26 @@ public abstract class DisplayList { public abstract void setClipChildren(boolean clipChildren); /** - * Set the application scale on the DisplayList. This scale is incurred by applications that - * are auto-scaled for compatibility reasons. By default, the value is 1 (unscaled). + * Set the static matrix on the DisplayList. This matrix exists if a custom ViewGroup + * overrides + * {@link ViewGroup#getChildStaticTransformation(View, android.view.animation.Transformation)} + * and also has {@link ViewGroup#setStaticTransformationsEnabled(boolean)} set to true. + * This matrix will be concatenated with any other matrices in the DisplayList to position + * the view appropriately. + * + * @param matrix The matrix + */ + public abstract void setStaticMatrix(Matrix matrix); + + /** + * Set the Animation matrix on the DisplayList. This matrix exists if an Animation is + * currently playing on a View, and is set on the DisplayList during at draw() time. When + * the Animation finishes, the matrix should be cleared by sending <code>null</code> + * for the matrix parameter. * - * @param scale The scaling factor + * @param matrix The matrix, null indicates that the matrix should be cleared. */ - public abstract void setApplicationScale(float scale); + public abstract void setAnimationMatrix(Matrix matrix); /** * Sets the alpha value for the DisplayList diff --git a/core/java/android/view/GLES20DisplayList.java b/core/java/android/view/GLES20DisplayList.java index 9b4cf21..bc3bce0 100644 --- a/core/java/android/view/GLES20DisplayList.java +++ b/core/java/android/view/GLES20DisplayList.java @@ -17,6 +17,7 @@ package android.view; import android.graphics.Bitmap; +import android.graphics.Matrix; import java.util.ArrayList; @@ -119,9 +120,18 @@ class GLES20DisplayList extends DisplayList { } @Override - public void setApplicationScale(float scale) { + public void setStaticMatrix(Matrix matrix) { try { - nSetApplicationScale(getNativeDisplayList(), scale); + nSetStaticMatrix(getNativeDisplayList(), matrix.native_instance); + } catch (IllegalStateException e) { + // invalid DisplayList okay: we'll set current values the next time we render to it + } + } + + @Override + public void setAnimationMatrix(Matrix matrix) { + try { + nSetAnimationMatrix(getNativeDisplayList(), matrix.native_instance); } catch (IllegalStateException e) { // invalid DisplayList okay: we'll set current values the next time we render to it } @@ -335,6 +345,8 @@ class GLES20DisplayList extends DisplayList { private static native void nSetTransformationInfo(int displayList, float alpha, float translationX, float translationY, float rotation, float rotationX, float rotationY, float scaleX, float scaleY); + private static native void nSetStaticMatrix(int displayList, int nativeMatrix); + private static native void nSetAnimationMatrix(int displayList, int animationMatrix); /////////////////////////////////////////////////////////////////////////// diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 99743e4..d72253b 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -11529,12 +11529,34 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal displayList.setClipChildren( (((ViewGroup)mParent).mGroupFlags & ViewGroup.FLAG_CLIP_CHILDREN) != 0); } - if (mAttachInfo != null && mAttachInfo.mScalingRequired && - mAttachInfo.mApplicationScale != 1.0f) { - displayList.setApplicationScale(1f / mAttachInfo.mApplicationScale); + float alpha = 1; + if (mParent instanceof ViewGroup && (((ViewGroup) mParent).mGroupFlags & + ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) { + ViewGroup parentVG = (ViewGroup) mParent; + final boolean hasTransform = + parentVG.getChildStaticTransformation(this, parentVG.mChildTransformation); + if (hasTransform) { + Transformation transform = parentVG.mChildTransformation; + final int transformType = parentVG.mChildTransformation.getTransformationType(); + if (transformType != Transformation.TYPE_IDENTITY) { + if ((transformType & Transformation.TYPE_ALPHA) != 0) { + alpha = transform.getAlpha(); + } + if ((transformType & Transformation.TYPE_MATRIX) != 0) { + displayList.setStaticMatrix(transform.getMatrix()); + } + } + } } if (mTransformationInfo != null) { - displayList.setTransformationInfo(mTransformationInfo.mAlpha, + alpha *= mTransformationInfo.mAlpha; + if (alpha < 1) { + final int multipliedAlpha = (int) (255 * alpha); + if (onSetAlpha(multipliedAlpha)) { + alpha = 1; + } + } + displayList.setTransformationInfo(alpha, mTransformationInfo.mTranslationX, mTransformationInfo.mTranslationY, mTransformationInfo.mRotation, mTransformationInfo.mRotationX, mTransformationInfo.mRotationY, mTransformationInfo.mScaleX, @@ -11548,6 +11570,8 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal displayList.setPivotX(getPivotX()); displayList.setPivotY(getPivotY()); } + } else if (alpha < 1) { + displayList.setAlpha(alpha); } } } @@ -11580,6 +11604,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal if ((flags & ViewGroup.FLAG_CHILDREN_DRAWN_WITH_CACHE) != 0 || (flags & ViewGroup.FLAG_ALWAYS_DRAWN_WITH_CACHE) != 0) { caching = true; + // Auto-scaled apps are not hw-accelerated, no need to set scaling flag on DisplayList if (mAttachInfo != null) scalingRequired = mAttachInfo.mScalingRequired; } else { caching = (layerType != LAYER_TYPE_NONE) || hardwareAccelerated; @@ -11590,7 +11615,8 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal more = drawAnimation(parent, drawingTime, a, scalingRequired); concatMatrix = a.willChangeTransformationMatrix(); transformToApply = parent.mChildTransformation; - } else if ((flags & ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) { + } else if (!useDisplayListProperties && + (flags & ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) { final boolean hasTransform = parent.getChildStaticTransformation(this, parent.mChildTransformation); if (hasTransform) { @@ -11658,6 +11684,17 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal } } useDisplayListProperties &= hasDisplayList; + if (useDisplayListProperties) { + displayList = getDisplayList(); + if (!displayList.isValid()) { + // Uncommon, but possible. If a view is removed from the hierarchy during the call + // to getDisplayList(), the display list will be marked invalid and we should not + // try to use it again. + displayList = null; + hasDisplayList = false; + useDisplayListProperties = false; + } + } final boolean hasNoCache = cache == null || hasDisplayList; final boolean offsetForScroll = cache == null && !hasDisplayList && @@ -11675,6 +11712,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal } if (scalingRequired) { if (useDisplayListProperties) { + // TODO: Might not need this if we put everything inside the DL restoreTo = canvas.save(); } // mAttachInfo cannot be null, otherwise scalingRequired == false @@ -11684,7 +11722,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal } float alpha = useDisplayListProperties ? 1 : getAlpha(); - if (transformToApply != null || alpha < 1.0f || !hasIdentityMatrix()) { + if (transformToApply != null || alpha < 1 || !hasIdentityMatrix()) { if (transformToApply != null || !childHasIdentityMatrix) { int transX = 0; int transY = 0; @@ -11696,16 +11734,20 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal if (transformToApply != null) { if (concatMatrix) { - // Undo the scroll translation, apply the transformation matrix, - // then redo the scroll translate to get the correct result. - canvas.translate(-transX, -transY); - canvas.concat(transformToApply.getMatrix()); - canvas.translate(transX, transY); + if (useDisplayListProperties) { + displayList.setAnimationMatrix(transformToApply.getMatrix()); + } else { + // Undo the scroll translation, apply the transformation matrix, + // then redo the scroll translate to get the correct result. + canvas.translate(-transX, -transY); + canvas.concat(transformToApply.getMatrix()); + canvas.translate(transX, transY); + } parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION; } float transformAlpha = transformToApply.getAlpha(); - if (transformAlpha < 1.0f) { + if (transformAlpha < 1) { alpha *= transformToApply.getAlpha(); parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION; } @@ -11718,7 +11760,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal } } - if (alpha < 1.0f) { + if (alpha < 1) { parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION; if (hasNoCache) { final int multipliedAlpha = (int) (255 * alpha); @@ -11728,7 +11770,9 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal layerType != LAYER_TYPE_NONE) { layerFlags |= Canvas.CLIP_TO_LAYER_SAVE_FLAG; } - if (layerType == LAYER_TYPE_NONE) { + if (useDisplayListProperties) { + displayList.setAlpha(alpha * getAlpha()); + } else if (layerType == LAYER_TYPE_NONE) { final int scrollX = hasDisplayList ? 0 : sx; final int scrollY = hasDisplayList ? 0 : sy; canvas.saveLayerAlpha(scrollX, scrollY, scrollX + mRight - mLeft, @@ -11758,7 +11802,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal } } - if (hasDisplayList) { + if (!useDisplayListProperties && hasDisplayList) { displayList = getDisplayList(); if (!displayList.isValid()) { // Uncommon, but possible. If a view is removed from the hierarchy during the call @@ -11815,7 +11859,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal cachePaint.setDither(false); parent.mCachePaint = cachePaint; } - if (alpha < 1.0f) { + if (alpha < 1) { cachePaint.setAlpha((int) (alpha * 255)); parent.mGroupFlags |= ViewGroup.FLAG_ALPHA_LOWER_THAN_ONE; } else if ((flags & ViewGroup.FLAG_ALPHA_LOWER_THAN_ONE) != 0) { diff --git a/core/jni/android_view_GLES20DisplayList.cpp b/core/jni/android_view_GLES20DisplayList.cpp index 407c196..60fb6d4 100644 --- a/core/jni/android_view_GLES20DisplayList.cpp +++ b/core/jni/android_view_GLES20DisplayList.cpp @@ -45,9 +45,14 @@ static void android_view_GLES20DisplayList_setCaching(JNIEnv* env, displayList->setCaching(caching); } -static void android_view_GLES20DisplayList_setApplicationScale(JNIEnv* env, - jobject clazz, DisplayList* displayList, float scale) { - displayList->setApplicationScale(scale); +static void android_view_GLES20DisplayList_setStaticMatrix(JNIEnv* env, + jobject clazz, DisplayList* displayList, SkMatrix* matrix) { + displayList->setStaticMatrix(matrix); +} + +static void android_view_GLES20DisplayList_setAnimationMatrix(JNIEnv* env, + jobject clazz, DisplayList* displayList, SkMatrix* matrix) { + displayList->setAnimationMatrix(matrix); } static void android_view_GLES20DisplayList_setClipChildren(JNIEnv* env, @@ -175,33 +180,32 @@ const char* const kClassPathName = "android/view/GLES20DisplayList"; static JNINativeMethod gMethods[] = { #ifdef USE_OPENGL_RENDERER - { "nSetCaching", "(IZ)V", (void*) android_view_GLES20DisplayList_setCaching }, - { "nSetApplicationScale", "(IF)V", - (void*) android_view_GLES20DisplayList_setApplicationScale }, - { "nSetClipChildren", "(IZ)V", (void*) android_view_GLES20DisplayList_setClipChildren }, - { "nSetAlpha", "(IF)V", (void*) android_view_GLES20DisplayList_setAlpha }, - { "nSetTranslationX", "(IF)V", (void*) android_view_GLES20DisplayList_setTranslationX }, - { "nSetTranslationY", "(IF)V", (void*) android_view_GLES20DisplayList_setTranslationY }, - { "nSetRotation", "(IF)V", (void*) android_view_GLES20DisplayList_setRotation }, - { "nSetRotationX", "(IF)V", (void*) android_view_GLES20DisplayList_setRotationX }, - { "nSetRotationY", "(IF)V", (void*) android_view_GLES20DisplayList_setRotationY }, - { "nSetScaleX", "(IF)V", (void*) android_view_GLES20DisplayList_setScaleX }, - { "nSetScaleY", "(IF)V", (void*) android_view_GLES20DisplayList_setScaleY }, - { "nSetTransformationInfo", "(IFFFFFFFF)V", + { "nSetCaching", "(IZ)V", (void*) android_view_GLES20DisplayList_setCaching }, + { "nSetStaticMatrix", "(II)V", (void*) android_view_GLES20DisplayList_setStaticMatrix }, + { "nSetAnimationMatrix", "(II)V", (void*) android_view_GLES20DisplayList_setAnimationMatrix }, + { "nSetClipChildren", "(IZ)V", (void*) android_view_GLES20DisplayList_setClipChildren }, + { "nSetAlpha", "(IF)V", (void*) android_view_GLES20DisplayList_setAlpha }, + { "nSetTranslationX", "(IF)V", (void*) android_view_GLES20DisplayList_setTranslationX }, + { "nSetTranslationY", "(IF)V", (void*) android_view_GLES20DisplayList_setTranslationY }, + { "nSetRotation", "(IF)V", (void*) android_view_GLES20DisplayList_setRotation }, + { "nSetRotationX", "(IF)V", (void*) android_view_GLES20DisplayList_setRotationX }, + { "nSetRotationY", "(IF)V", (void*) android_view_GLES20DisplayList_setRotationY }, + { "nSetScaleX", "(IF)V", (void*) android_view_GLES20DisplayList_setScaleX }, + { "nSetScaleY", "(IF)V", (void*) android_view_GLES20DisplayList_setScaleY }, + { "nSetTransformationInfo","(IFFFFFFFF)V", (void*) android_view_GLES20DisplayList_setTransformationInfo }, - { "nSetPivotX", "(IF)V", (void*) android_view_GLES20DisplayList_setPivotX }, - { "nSetPivotY", "(IF)V", (void*) android_view_GLES20DisplayList_setPivotY }, - { "nSetCameraDistance", "(IF)V", - (void*) android_view_GLES20DisplayList_setCameraDistance }, - { "nSetLeft", "(II)V", (void*) android_view_GLES20DisplayList_setLeft }, - { "nSetTop", "(II)V", (void*) android_view_GLES20DisplayList_setTop }, - { "nSetRight", "(II)V", (void*) android_view_GLES20DisplayList_setRight }, - { "nSetBottom", "(II)V", (void*) android_view_GLES20DisplayList_setBottom }, - { "nSetLeftTop", "(III)V", (void*) android_view_GLES20DisplayList_setLeftTop }, - { "nSetLeftTopRightBottom", "(IIIII)V", + { "nSetPivotX", "(IF)V", (void*) android_view_GLES20DisplayList_setPivotX }, + { "nSetPivotY", "(IF)V", (void*) android_view_GLES20DisplayList_setPivotY }, + { "nSetCameraDistance", "(IF)V", (void*) android_view_GLES20DisplayList_setCameraDistance }, + { "nSetLeft", "(II)V", (void*) android_view_GLES20DisplayList_setLeft }, + { "nSetTop", "(II)V", (void*) android_view_GLES20DisplayList_setTop }, + { "nSetRight", "(II)V", (void*) android_view_GLES20DisplayList_setRight }, + { "nSetBottom", "(II)V", (void*) android_view_GLES20DisplayList_setBottom }, + { "nSetLeftTop", "(III)V", (void*) android_view_GLES20DisplayList_setLeftTop }, + { "nSetLeftTopRightBottom","(IIIII)V", (void*) android_view_GLES20DisplayList_setLeftTopRightBottom }, - { "nOffsetLeftRight", "(II)V", (void*) android_view_GLES20DisplayList_offsetLeftRight }, - { "nOffsetTopBottom", "(II)V", (void*) android_view_GLES20DisplayList_offsetTopBottom }, + { "nOffsetLeftRight", "(II)V", (void*) android_view_GLES20DisplayList_offsetLeftRight }, + { "nOffsetTopBottom", "(II)V", (void*) android_view_GLES20DisplayList_offsetTopBottom }, #endif }; |