summaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
authorChet Haase <chet@google.com>2012-03-21 18:54:18 -0700
committerChet Haase <chet@google.com>2012-04-03 14:02:17 -0700
commitdb8c9a6a4d9bf8c39f834b25611926caf21380f6 (patch)
tree5a1ef2e49ea05c5a28477fcf8525ca66e8e31890 /core
parentb3fa3960a03ef553e58bf1add88029a6c072c6b6 (diff)
downloadframeworks_base-db8c9a6a4d9bf8c39f834b25611926caf21380f6.zip
frameworks_base-db8c9a6a4d9bf8c39f834b25611926caf21380f6.tar.gz
frameworks_base-db8c9a6a4d9bf8c39f834b25611926caf21380f6.tar.bz2
Optimization of alpha with DisplayList properties
Some views (such as ImageView and TextView) handle non-opaque alpha values directly. This was originally an optimization, but we can handle it faster in many cases without this optimization when DisplayList properties are enabled. Basically, if a view has non-overlapping rendering, we set the alpha value directly on the renderer (the equivalent of setting it on the Paint object) and draw each primitive with that alpha value. Doing it this way avoids re-creating DisplayLists while getting the same speedup that onSetAlpha() used to get pre-DisplayList properties. Change-Id: I0f7827f075d3b35093a882d4adbb300a1063c288
Diffstat (limited to 'core')
-rw-r--r--core/java/android/view/DisplayList.java9
-rw-r--r--core/java/android/view/GLES20DisplayList.java11
-rw-r--r--core/java/android/view/HardwareRenderer.java6
-rw-r--r--core/java/android/view/View.java44
-rw-r--r--core/java/android/view/ViewPropertyAnimator.java13
-rw-r--r--core/java/android/widget/ImageView.java11
-rw-r--r--core/java/android/widget/TextView.java12
-rw-r--r--core/jni/android_view_GLES20DisplayList.cpp7
8 files changed, 91 insertions, 22 deletions
diff --git a/core/java/android/view/DisplayList.java b/core/java/android/view/DisplayList.java
index 33631b7..fba73fbd 100644
--- a/core/java/android/view/DisplayList.java
+++ b/core/java/android/view/DisplayList.java
@@ -149,6 +149,15 @@ public abstract class DisplayList {
public abstract void setAlpha(float alpha);
/**
+ * Sets whether the DisplayList renders content which overlaps. Non-overlapping rendering
+ * can use a fast path for alpha that avoids rendering to an offscreen buffer.
+ *
+ * @param hasOverlappingRendering
+ * @see android.view.View#hasOverlappingRendering()
+ */
+ public abstract void setHasOverlappingRendering(boolean hasOverlappingRendering);
+
+ /**
* Sets the translationX value for the DisplayList
*
* @param translationX The translationX value of the DisplayList
diff --git a/core/java/android/view/GLES20DisplayList.java b/core/java/android/view/GLES20DisplayList.java
index bc3bce0..f3618eb 100644
--- a/core/java/android/view/GLES20DisplayList.java
+++ b/core/java/android/view/GLES20DisplayList.java
@@ -147,6 +147,15 @@ class GLES20DisplayList extends DisplayList {
}
@Override
+ public void setHasOverlappingRendering(boolean hasOverlappingRendering) {
+ try {
+ nSetHasOverlappingRendering(getNativeDisplayList(), hasOverlappingRendering);
+ } catch (IllegalStateException e) {
+ // invalid DisplayList okay: we'll set current values the next time we render to it
+ }
+ }
+
+ @Override
public void setTranslationX(float translationX) {
try {
nSetTranslationX(getNativeDisplayList(), translationX);
@@ -335,6 +344,8 @@ class GLES20DisplayList extends DisplayList {
private static native void nSetClipChildren(int displayList, boolean clipChildren);
private static native void nSetApplicationScale(int displayList, float scale);
private static native void nSetAlpha(int displayList, float alpha);
+ private static native void nSetHasOverlappingRendering(int displayList,
+ boolean hasOverlappingRendering);
private static native void nSetTranslationX(int displayList, float translationX);
private static native void nSetTranslationY(int displayList, float translationY);
private static native void nSetRotation(int displayList, float rotation);
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index b100a0c..9ef2621 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -134,7 +134,7 @@ public abstract class HardwareRenderer {
/**
* Number of frames to profile.
*/
- private static final int PROFILE_MAX_FRAMES = 64;
+ private static final int PROFILE_MAX_FRAMES = 120;
/**
* Number of floats per profiled frame.
@@ -1046,10 +1046,6 @@ public abstract class HardwareRenderer {
Log.d(ViewDebug.DEBUG_LATENCY_TAG, "- getDisplayList() took " +
total + "ms");
}
- if (View.USE_DISPLAY_LIST_PROPERTIES) {
- Log.d("DLProperties", "getDisplayList():\t" +
- mProfileData[mProfileCurrentFrame]);
- }
}
if (displayList != null) {
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 69d7655..cecb445 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -2830,19 +2830,6 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
private boolean mSendingHoverAccessibilityEvents;
/**
- * Delegate for injecting accessiblity functionality.
- */
- AccessibilityDelegate mAccessibilityDelegate;
-
- /**
- * Consistency verifier for debugging purposes.
- * @hide
- */
- protected final InputEventConsistencyVerifier mInputEventConsistencyVerifier =
- InputEventConsistencyVerifier.isInstrumentationEnabled() ?
- new InputEventConsistencyVerifier(this, 0) : null;
-
- /**
* Simple constructor to use when creating a view from code.
*
* @param context The Context the view is running in, through which it can
@@ -2863,6 +2850,19 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
}
/**
+ * Delegate for injecting accessiblity functionality.
+ */
+ AccessibilityDelegate mAccessibilityDelegate;
+
+ /**
+ * Consistency verifier for debugging purposes.
+ * @hide
+ */
+ protected final InputEventConsistencyVerifier mInputEventConsistencyVerifier =
+ InputEventConsistencyVerifier.isInstrumentationEnabled() ?
+ new InputEventConsistencyVerifier(this, 0) : null;
+
+ /**
* Constructor that is called when inflating a view from XML. This is called
* when a view is being constructed from an XML file, supplying attributes
* that were specified in the XML file. This version uses a default style of
@@ -7855,6 +7855,23 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
}
/**
+ * Returns whether this View has content which overlaps. This function, intended to be
+ * overridden by specific View types, is an optimization when alpha is set on a view. If
+ * rendering overlaps in a view with alpha < 1, that view is drawn to an offscreen buffer
+ * and then composited it into place, which can be expensive. If the view has no overlapping
+ * rendering, the view can draw each primitive with the appropriate alpha value directly.
+ * An example of overlapping rendering is a TextView with a background image, such as a
+ * Button. An example of non-overlapping rendering is a TextView with no background, or
+ * an ImageView with only the foreground image. The default implementation returns true;
+ * subclasses should override if they have cases which can be optimized.
+ *
+ * @return true if the content in this view might overlap, false otherwise.
+ */
+ public boolean hasOverlappingRendering() {
+ return true;
+ }
+
+ /**
* <p>Sets the opacity of the view. This is a value from 0 to 1, where 0 means the view is
* completely transparent and 1 means the view is completely opaque.</p>
*
@@ -11525,6 +11542,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
void setDisplayListProperties(DisplayList displayList) {
if (USE_DISPLAY_LIST_PROPERTIES && displayList != null) {
displayList.setLeftTopRightBottom(mLeft, mTop, mRight, mBottom);
+ displayList.setHasOverlappingRendering(hasOverlappingRendering());
if (mParent instanceof ViewGroup) {
displayList.setClipChildren(
(((ViewGroup)mParent).mGroupFlags & ViewGroup.FLAG_CLIP_CHILDREN) != 0);
diff --git a/core/java/android/view/ViewPropertyAnimator.java b/core/java/android/view/ViewPropertyAnimator.java
index 623b567..3626aba 100644
--- a/core/java/android/view/ViewPropertyAnimator.java
+++ b/core/java/android/view/ViewPropertyAnimator.java
@@ -834,40 +834,49 @@ public class ViewPropertyAnimator {
*/
private void setValue(int propertyConstant, float value) {
final View.TransformationInfo info = mView.mTransformationInfo;
+ DisplayList displayList = View.USE_DISPLAY_LIST_PROPERTIES ? mView.mDisplayList : null;
switch (propertyConstant) {
case TRANSLATION_X:
info.mTranslationX = value;
+ if (displayList != null) displayList.setTranslationX(value);
break;
case TRANSLATION_Y:
info.mTranslationY = value;
+ if (displayList != null) displayList.setTranslationY(value);
break;
case ROTATION:
info.mRotation = value;
+ if (displayList != null) displayList.setRotation(value);
break;
case ROTATION_X:
info.mRotationX = value;
+ if (displayList != null) displayList.setRotationX(value);
break;
case ROTATION_Y:
info.mRotationY = value;
+ if (displayList != null) displayList.setRotationY(value);
break;
case SCALE_X:
info.mScaleX = value;
+ if (displayList != null) displayList.setScaleX(value);
break;
case SCALE_Y:
info.mScaleY = value;
+ if (displayList != null) displayList.setScaleY(value);
break;
case X:
info.mTranslationX = value - mView.mLeft;
+ if (displayList != null) displayList.setTranslationX(value - mView.mLeft);
break;
case Y:
info.mTranslationY = value - mView.mTop;
+ if (displayList != null) displayList.setTranslationY(value - mView.mTop);
break;
case ALPHA:
info.mAlpha = value;
+ if (displayList != null) displayList.setAlpha(value);
break;
}
- // TODO: optimize to set only the properties that have changed
- mView.setDisplayListProperties();
}
/**
diff --git a/core/java/android/widget/ImageView.java b/core/java/android/widget/ImageView.java
index b1a75e1..91e2e49 100644
--- a/core/java/android/widget/ImageView.java
+++ b/core/java/android/widget/ImageView.java
@@ -201,7 +201,7 @@ public class ImageView extends View {
@Override
protected boolean onSetAlpha(int alpha) {
- if (getBackground() == null) {
+ if (!USE_DISPLAY_LIST_PROPERTIES && getBackground() == null) {
int scale = alpha + (alpha >> 7);
if (mViewAlphaScale != scale) {
mViewAlphaScale = scale;
@@ -214,6 +214,15 @@ public class ImageView extends View {
}
@Override
+ public boolean hasOverlappingRendering() {
+ if (!USE_DISPLAY_LIST_PROPERTIES) {
+ return super.hasOverlappingRendering();
+ } else {
+ return (getBackground() != null);
+ }
+ }
+
+ @Override
public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
super.onPopulateAccessibilityEvent(event);
CharSequence contentDescription = getContentDescription();
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 2a81f08..d2a1755 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -4268,7 +4268,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
protected boolean onSetAlpha(int alpha) {
// Alpha is supported if and only if the drawing can be done in one pass.
// TODO text with spans with a background color currently do not respect this alpha.
- if (getBackground() == null) {
+ if (!USE_DISPLAY_LIST_PROPERTIES &&
+ (getBackground() != null || mText instanceof Spannable || hasSelection())) {
if (mCurrentAlpha != alpha) {
mCurrentAlpha = alpha;
final Drawables dr = mDrawables;
@@ -4292,6 +4293,15 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
return false;
}
+ @Override
+ public boolean hasOverlappingRendering() {
+ if (!USE_DISPLAY_LIST_PROPERTIES) {
+ return super.hasOverlappingRendering();
+ } else {
+ return (getBackground() != null || mText instanceof Spannable || hasSelection());
+ }
+ }
+
/**
* When a TextView is used to display a useful piece of information to the user (such as a
* contact's address), it should be made selectable, so that the user can select and copy this
diff --git a/core/jni/android_view_GLES20DisplayList.cpp b/core/jni/android_view_GLES20DisplayList.cpp
index 60fb6d4..b307a2f 100644
--- a/core/jni/android_view_GLES20DisplayList.cpp
+++ b/core/jni/android_view_GLES20DisplayList.cpp
@@ -65,6 +65,11 @@ static void android_view_GLES20DisplayList_setAlpha(JNIEnv* env,
displayList->setAlpha(alpha);
}
+static void android_view_GLES20DisplayList_setHasOverlappingRendering(JNIEnv* env,
+ jobject clazz, DisplayList* displayList, bool hasOverlappingRendering) {
+ displayList->setHasOverlappingRendering(hasOverlappingRendering);
+}
+
static void android_view_GLES20DisplayList_setTranslationX(JNIEnv* env,
jobject clazz, DisplayList* displayList, float tx) {
displayList->setTranslationX(tx);
@@ -185,6 +190,8 @@ static JNINativeMethod gMethods[] = {
{ "nSetAnimationMatrix", "(II)V", (void*) android_view_GLES20DisplayList_setAnimationMatrix },
{ "nSetClipChildren", "(IZ)V", (void*) android_view_GLES20DisplayList_setClipChildren },
{ "nSetAlpha", "(IF)V", (void*) android_view_GLES20DisplayList_setAlpha },
+ { "nSetHasOverlappingRendering", "(IZ)V",
+ (void*) android_view_GLES20DisplayList_setHasOverlappingRendering },
{ "nSetTranslationX", "(IF)V", (void*) android_view_GLES20DisplayList_setTranslationX },
{ "nSetTranslationY", "(IF)V", (void*) android_view_GLES20DisplayList_setTranslationY },
{ "nSetRotation", "(IF)V", (void*) android_view_GLES20DisplayList_setRotation },