Skip to content

Commit 21aec19

Browse files
chethaaseAndroid (Google) Code Review
authored andcommitted
Merge "Optimization of alpha with DisplayList properties"
2 parents 66ac902 + db8c9a6 commit 21aec19

18 files changed

+368
-35
lines changed

api/current.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23373,6 +23373,7 @@ package android.view {
2337323373
method public boolean hasFocus();
2337423374
method public boolean hasFocusable();
2337523375
method public boolean hasOnClickListeners();
23376+
method public boolean hasOverlappingRendering();
2337623377
method public boolean hasTransientState();
2337723378
method public boolean hasWindowFocus();
2337823379
method public static android.view.View inflate(android.content.Context, int, android.view.ViewGroup);

core/java/android/view/DisplayList.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,15 @@ public abstract class DisplayList {
148148
*/
149149
public abstract void setAlpha(float alpha);
150150

151+
/**
152+
* Sets whether the DisplayList renders content which overlaps. Non-overlapping rendering
153+
* can use a fast path for alpha that avoids rendering to an offscreen buffer.
154+
*
155+
* @param hasOverlappingRendering
156+
* @see android.view.View#hasOverlappingRendering()
157+
*/
158+
public abstract void setHasOverlappingRendering(boolean hasOverlappingRendering);
159+
151160
/**
152161
* Sets the translationX value for the DisplayList
153162
*

core/java/android/view/GLES20DisplayList.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,15 @@ public void setAlpha(float alpha) {
146146
}
147147
}
148148

149+
@Override
150+
public void setHasOverlappingRendering(boolean hasOverlappingRendering) {
151+
try {
152+
nSetHasOverlappingRendering(getNativeDisplayList(), hasOverlappingRendering);
153+
} catch (IllegalStateException e) {
154+
// invalid DisplayList okay: we'll set current values the next time we render to it
155+
}
156+
}
157+
149158
@Override
150159
public void setTranslationX(float translationX) {
151160
try {
@@ -335,6 +344,8 @@ private static native void nSetLeftTopRightBottom(int displayList, int left, int
335344
private static native void nSetClipChildren(int displayList, boolean clipChildren);
336345
private static native void nSetApplicationScale(int displayList, float scale);
337346
private static native void nSetAlpha(int displayList, float alpha);
347+
private static native void nSetHasOverlappingRendering(int displayList,
348+
boolean hasOverlappingRendering);
338349
private static native void nSetTranslationX(int displayList, float translationX);
339350
private static native void nSetTranslationY(int displayList, float translationY);
340351
private static native void nSetRotation(int displayList, float rotation);

core/java/android/view/HardwareRenderer.java

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ public abstract class HardwareRenderer {
134134
/**
135135
* Number of frames to profile.
136136
*/
137-
private static final int PROFILE_MAX_FRAMES = 64;
137+
private static final int PROFILE_MAX_FRAMES = 120;
138138

139139
/**
140140
* Number of floats per profiled frame.
@@ -1046,10 +1046,6 @@ boolean draw(View view, View.AttachInfo attachInfo, HardwareDrawCallbacks callba
10461046
Log.d(ViewDebug.DEBUG_LATENCY_TAG, "- getDisplayList() took " +
10471047
total + "ms");
10481048
}
1049-
if (View.USE_DISPLAY_LIST_PROPERTIES) {
1050-
Log.d("DLProperties", "getDisplayList():\t" +
1051-
mProfileData[mProfileCurrentFrame]);
1052-
}
10531049
}
10541050

10551051
if (displayList != null) {

core/java/android/view/View.java

Lines changed: 31 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2829,19 +2829,6 @@ static class ListenerInfo {
28292829
*/
28302830
private boolean mSendingHoverAccessibilityEvents;
28312831

2832-
/**
2833-
* Delegate for injecting accessiblity functionality.
2834-
*/
2835-
AccessibilityDelegate mAccessibilityDelegate;
2836-
2837-
/**
2838-
* Consistency verifier for debugging purposes.
2839-
* @hide
2840-
*/
2841-
protected final InputEventConsistencyVerifier mInputEventConsistencyVerifier =
2842-
InputEventConsistencyVerifier.isInstrumentationEnabled() ?
2843-
new InputEventConsistencyVerifier(this, 0) : null;
2844-
28452832
/**
28462833
* Simple constructor to use when creating a view from code.
28472834
*
@@ -2862,6 +2849,19 @@ public View(Context context) {
28622849
mUserPaddingRelative = false;
28632850
}
28642851

2852+
/**
2853+
* Delegate for injecting accessiblity functionality.
2854+
*/
2855+
AccessibilityDelegate mAccessibilityDelegate;
2856+
2857+
/**
2858+
* Consistency verifier for debugging purposes.
2859+
* @hide
2860+
*/
2861+
protected final InputEventConsistencyVerifier mInputEventConsistencyVerifier =
2862+
InputEventConsistencyVerifier.isInstrumentationEnabled() ?
2863+
new InputEventConsistencyVerifier(this, 0) : null;
2864+
28652865
/**
28662866
* Constructor that is called when inflating a view from XML. This is called
28672867
* when a view is being constructed from an XML file, supplying attributes
@@ -7854,6 +7854,23 @@ public float getAlpha() {
78547854
return mTransformationInfo != null ? mTransformationInfo.mAlpha : 1;
78557855
}
78567856

7857+
/**
7858+
* Returns whether this View has content which overlaps. This function, intended to be
7859+
* overridden by specific View types, is an optimization when alpha is set on a view. If
7860+
* rendering overlaps in a view with alpha < 1, that view is drawn to an offscreen buffer
7861+
* and then composited it into place, which can be expensive. If the view has no overlapping
7862+
* rendering, the view can draw each primitive with the appropriate alpha value directly.
7863+
* An example of overlapping rendering is a TextView with a background image, such as a
7864+
* Button. An example of non-overlapping rendering is a TextView with no background, or
7865+
* an ImageView with only the foreground image. The default implementation returns true;
7866+
* subclasses should override if they have cases which can be optimized.
7867+
*
7868+
* @return true if the content in this view might overlap, false otherwise.
7869+
*/
7870+
public boolean hasOverlappingRendering() {
7871+
return true;
7872+
}
7873+
78577874
/**
78587875
* <p>Sets the opacity of the view. This is a value from 0 to 1, where 0 means the view is
78597876
* completely transparent and 1 means the view is completely opaque.</p>
@@ -11534,6 +11551,7 @@ void setDisplayListProperties() {
1153411551
void setDisplayListProperties(DisplayList displayList) {
1153511552
if (USE_DISPLAY_LIST_PROPERTIES && displayList != null) {
1153611553
displayList.setLeftTopRightBottom(mLeft, mTop, mRight, mBottom);
11554+
displayList.setHasOverlappingRendering(hasOverlappingRendering());
1153711555
if (mParent instanceof ViewGroup) {
1153811556
displayList.setClipChildren(
1153911557
(((ViewGroup)mParent).mGroupFlags & ViewGroup.FLAG_CLIP_CHILDREN) != 0);

core/java/android/view/ViewPropertyAnimator.java

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -834,40 +834,49 @@ private void animatePropertyBy(int constantName, float startValue, float byValue
834834
*/
835835
private void setValue(int propertyConstant, float value) {
836836
final View.TransformationInfo info = mView.mTransformationInfo;
837+
DisplayList displayList = View.USE_DISPLAY_LIST_PROPERTIES ? mView.mDisplayList : null;
837838
switch (propertyConstant) {
838839
case TRANSLATION_X:
839840
info.mTranslationX = value;
841+
if (displayList != null) displayList.setTranslationX(value);
840842
break;
841843
case TRANSLATION_Y:
842844
info.mTranslationY = value;
845+
if (displayList != null) displayList.setTranslationY(value);
843846
break;
844847
case ROTATION:
845848
info.mRotation = value;
849+
if (displayList != null) displayList.setRotation(value);
846850
break;
847851
case ROTATION_X:
848852
info.mRotationX = value;
853+
if (displayList != null) displayList.setRotationX(value);
849854
break;
850855
case ROTATION_Y:
851856
info.mRotationY = value;
857+
if (displayList != null) displayList.setRotationY(value);
852858
break;
853859
case SCALE_X:
854860
info.mScaleX = value;
861+
if (displayList != null) displayList.setScaleX(value);
855862
break;
856863
case SCALE_Y:
857864
info.mScaleY = value;
865+
if (displayList != null) displayList.setScaleY(value);
858866
break;
859867
case X:
860868
info.mTranslationX = value - mView.mLeft;
869+
if (displayList != null) displayList.setTranslationX(value - mView.mLeft);
861870
break;
862871
case Y:
863872
info.mTranslationY = value - mView.mTop;
873+
if (displayList != null) displayList.setTranslationY(value - mView.mTop);
864874
break;
865875
case ALPHA:
866876
info.mAlpha = value;
877+
if (displayList != null) displayList.setAlpha(value);
867878
break;
868879
}
869-
// TODO: optimize to set only the properties that have changed
870-
mView.setDisplayListProperties();
871880
}
872881

873882
/**

core/java/android/widget/ImageView.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,7 @@ public int getResolvedLayoutDirection(Drawable dr) {
201201

202202
@Override
203203
protected boolean onSetAlpha(int alpha) {
204-
if (getBackground() == null) {
204+
if (!USE_DISPLAY_LIST_PROPERTIES && getBackground() == null) {
205205
int scale = alpha + (alpha >> 7);
206206
if (mViewAlphaScale != scale) {
207207
mViewAlphaScale = scale;
@@ -213,6 +213,15 @@ protected boolean onSetAlpha(int alpha) {
213213
return false;
214214
}
215215

216+
@Override
217+
public boolean hasOverlappingRendering() {
218+
if (!USE_DISPLAY_LIST_PROPERTIES) {
219+
return super.hasOverlappingRendering();
220+
} else {
221+
return (getBackground() != null);
222+
}
223+
}
224+
216225
@Override
217226
public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
218227
super.onPopulateAccessibilityEvent(event);

core/java/android/widget/TextView.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4268,7 +4268,8 @@ public int getResolvedLayoutDirection(Drawable who) {
42684268
protected boolean onSetAlpha(int alpha) {
42694269
// Alpha is supported if and only if the drawing can be done in one pass.
42704270
// TODO text with spans with a background color currently do not respect this alpha.
4271-
if (getBackground() == null) {
4271+
if (!USE_DISPLAY_LIST_PROPERTIES &&
4272+
(getBackground() != null || mText instanceof Spannable || hasSelection())) {
42724273
if (mCurrentAlpha != alpha) {
42734274
mCurrentAlpha = alpha;
42744275
final Drawables dr = mDrawables;
@@ -4292,6 +4293,15 @@ protected boolean onSetAlpha(int alpha) {
42924293
return false;
42934294
}
42944295

4296+
@Override
4297+
public boolean hasOverlappingRendering() {
4298+
if (!USE_DISPLAY_LIST_PROPERTIES) {
4299+
return super.hasOverlappingRendering();
4300+
} else {
4301+
return (getBackground() != null || mText instanceof Spannable || hasSelection());
4302+
}
4303+
}
4304+
42954305
/**
42964306
* When a TextView is used to display a useful piece of information to the user (such as a
42974307
* contact's address), it should be made selectable, so that the user can select and copy this

core/jni/android_view_GLES20DisplayList.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,11 @@ static void android_view_GLES20DisplayList_setAlpha(JNIEnv* env,
6565
displayList->setAlpha(alpha);
6666
}
6767

68+
static void android_view_GLES20DisplayList_setHasOverlappingRendering(JNIEnv* env,
69+
jobject clazz, DisplayList* displayList, bool hasOverlappingRendering) {
70+
displayList->setHasOverlappingRendering(hasOverlappingRendering);
71+
}
72+
6873
static void android_view_GLES20DisplayList_setTranslationX(JNIEnv* env,
6974
jobject clazz, DisplayList* displayList, float tx) {
7075
displayList->setTranslationX(tx);
@@ -185,6 +190,8 @@ static JNINativeMethod gMethods[] = {
185190
{ "nSetAnimationMatrix", "(II)V", (void*) android_view_GLES20DisplayList_setAnimationMatrix },
186191
{ "nSetClipChildren", "(IZ)V", (void*) android_view_GLES20DisplayList_setClipChildren },
187192
{ "nSetAlpha", "(IF)V", (void*) android_view_GLES20DisplayList_setAlpha },
193+
{ "nSetHasOverlappingRendering", "(IZ)V",
194+
(void*) android_view_GLES20DisplayList_setHasOverlappingRendering },
188195
{ "nSetTranslationX", "(IF)V", (void*) android_view_GLES20DisplayList_setTranslationX },
189196
{ "nSetTranslationY", "(IF)V", (void*) android_view_GLES20DisplayList_setTranslationY },
190197
{ "nSetRotation", "(IF)V", (void*) android_view_GLES20DisplayList_setRotation },

libs/hwui/DisplayListRenderer.cpp

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ void DisplayList::initProperties() {
112112
mClipChildren = true;
113113
mAlpha = 1;
114114
mMultipliedAlpha = 255;
115+
mHasOverlappingRendering = true;
115116
mTranslationX = 0;
116117
mTranslationY = 0;
117118
mRotation = 0;
@@ -772,18 +773,23 @@ void DisplayList::setViewProperties(OpenGLRenderer& renderer, uint32_t width, ui
772773
}
773774
}
774775
if (mAlpha < 1 && !mCaching) {
775-
// TODO: should be able to store the size of a DL at record time and not
776-
// have to pass it into this call. In fact, this information might be in the
777-
// location/size info that we store with the new native transform data.
778-
int flags = SkCanvas::kHasAlphaLayer_SaveFlag;
779-
if (mClipChildren) {
780-
flags |= SkCanvas::kClipToLayer_SaveFlag;
776+
if (!mHasOverlappingRendering) {
777+
DISPLAY_LIST_LOGD("%s%s %.2f", indent, "SetAlpha", mAlpha);
778+
renderer.setAlpha(mAlpha);
779+
} else {
780+
// TODO: should be able to store the size of a DL at record time and not
781+
// have to pass it into this call. In fact, this information might be in the
782+
// location/size info that we store with the new native transform data.
783+
int flags = SkCanvas::kHasAlphaLayer_SaveFlag;
784+
if (mClipChildren) {
785+
flags |= SkCanvas::kClipToLayer_SaveFlag;
786+
}
787+
DISPLAY_LIST_LOGD("%s%s %.2f, %.2f, %.2f, %.2f, %d, 0x%x", indent, "SaveLayerAlpha",
788+
(float) 0, (float) 0, (float) mRight - mLeft, (float) mBottom - mTop,
789+
mMultipliedAlpha, flags);
790+
renderer.saveLayerAlpha(0, 0, mRight - mLeft, mBottom - mTop,
791+
mMultipliedAlpha, flags);
781792
}
782-
DISPLAY_LIST_LOGD("%s%s %.2f, %.2f, %.2f, %.2f, %d, 0x%x", indent, "SaveLayerAlpha",
783-
(float) 0, (float) 0, (float) mRight - mLeft, (float) mBottom - mTop,
784-
mMultipliedAlpha, flags);
785-
renderer.saveLayerAlpha(0, 0, mRight - mLeft, mBottom - mTop,
786-
mMultipliedAlpha, flags);
787793
}
788794
if (mClipChildren) {
789795
DISPLAY_LIST_LOGD("%s%s %.2f, %.2f, %.2f, %.2f", indent, "ClipRect", 0.0f, 0.0f,

0 commit comments

Comments
 (0)