Merge "Optimization of alpha with DisplayList properties"

This commit is contained in:
Chet Haase
2012-04-03 15:40:54 -07:00
committed by Android (Google) Code Review
18 changed files with 368 additions and 35 deletions

View File

@@ -148,6 +148,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
*

View File

@@ -146,6 +146,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 {
@@ -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);

View File

@@ -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) {

View File

@@ -2829,19 +2829,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.
*
@@ -2862,6 +2849,19 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
mUserPaddingRelative = false;
}
/**
* 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
@@ -7854,6 +7854,23 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
return mTransformationInfo != null ? mTransformationInfo.mAlpha : 1;
}
/**
* 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>
@@ -11534,6 +11551,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);

View File

@@ -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();
}
/**

View File

@@ -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;
@@ -213,6 +213,15 @@ public class ImageView extends View {
return false;
}
@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);

View File

@@ -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