summaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
authorChet Haase <chet@google.com>2012-03-29 16:28:32 -0700
committerChet Haase <chet@google.com>2012-04-02 15:31:24 -0700
commit9420abd56a2af7ddbeb70562b79d61b2dca8c5a1 (patch)
tree8625a64e2d9ffd1520d890c2eb7989ccbef28adc /core
parent1d6013357847983180a317e2acaf807bde8b7ea7 (diff)
downloadframeworks_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.java24
-rw-r--r--core/java/android/view/GLES20DisplayList.java16
-rw-r--r--core/java/android/view/View.java76
-rw-r--r--core/jni/android_view_GLES20DisplayList.cpp60
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
};