Loading core/java/android/view/HardwareRenderer.java +5 −0 Original line number Diff line number Diff line Loading @@ -960,6 +960,11 @@ 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) { Loading core/java/android/view/View.java +130 −92 Original line number Diff line number Diff line Loading @@ -1503,7 +1503,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal * apps. * @hide */ protected static final boolean USE_DISPLAY_LIST_PROPERTIES = false; public static final boolean USE_DISPLAY_LIST_PROPERTIES = false; /** * Map used to store views' tags. Loading Loading @@ -7349,8 +7349,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal * @see #setRotationY(float) */ public void setCameraDistance(float distance) { invalidateParentCaches(); invalidate(false); invalidateViewProperty(true, false); ensureTransformationInfo(); final float dpi = mResources.getDisplayMetrics().densityDpi; Loading @@ -7363,7 +7362,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal info.mCamera.setLocation(0.0f, 0.0f, -Math.abs(distance) / dpi); info.mMatrixDirty = true; invalidate(false); invalidateViewProperty(false, false); if (USE_DISPLAY_LIST_PROPERTIES && mDisplayList != null) { mDisplayList.setCameraDistance(distance); } Loading Loading @@ -7401,13 +7400,11 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal ensureTransformationInfo(); final TransformationInfo info = mTransformationInfo; if (info.mRotation != rotation) { invalidateParentCaches(); // Double-invalidation is necessary to capture view's old and new areas invalidate(false); invalidateViewProperty(true, false); info.mRotation = rotation; info.mMatrixDirty = true; mPrivateFlags |= DRAWN; // force another invalidation with the new orientation invalidate(false); invalidateViewProperty(false, true); if (USE_DISPLAY_LIST_PROPERTIES && mDisplayList != null) { mDisplayList.setRotation(rotation); } Loading Loading @@ -7451,13 +7448,10 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal ensureTransformationInfo(); final TransformationInfo info = mTransformationInfo; if (info.mRotationY != rotationY) { invalidateParentCaches(); // Double-invalidation is necessary to capture view's old and new areas invalidate(false); invalidateViewProperty(true, false); info.mRotationY = rotationY; info.mMatrixDirty = true; mPrivateFlags |= DRAWN; // force another invalidation with the new orientation invalidate(false); invalidateViewProperty(false, true); if (USE_DISPLAY_LIST_PROPERTIES && mDisplayList != null) { mDisplayList.setRotationY(rotationY); } Loading Loading @@ -7501,13 +7495,10 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal ensureTransformationInfo(); final TransformationInfo info = mTransformationInfo; if (info.mRotationX != rotationX) { invalidateParentCaches(); // Double-invalidation is necessary to capture view's old and new areas invalidate(false); invalidateViewProperty(true, false); info.mRotationX = rotationX; info.mMatrixDirty = true; mPrivateFlags |= DRAWN; // force another invalidation with the new orientation invalidate(false); invalidateViewProperty(false, true); if (USE_DISPLAY_LIST_PROPERTIES && mDisplayList != null) { mDisplayList.setRotationX(rotationX); } Loading Loading @@ -7543,13 +7534,10 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal ensureTransformationInfo(); final TransformationInfo info = mTransformationInfo; if (info.mScaleX != scaleX) { invalidateParentCaches(); // Double-invalidation is necessary to capture view's old and new areas invalidate(false); invalidateViewProperty(true, false); info.mScaleX = scaleX; info.mMatrixDirty = true; mPrivateFlags |= DRAWN; // force another invalidation with the new orientation invalidate(false); invalidateViewProperty(false, true); if (USE_DISPLAY_LIST_PROPERTIES && mDisplayList != null) { mDisplayList.setScaleX(scaleX); } Loading Loading @@ -7585,13 +7573,10 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal ensureTransformationInfo(); final TransformationInfo info = mTransformationInfo; if (info.mScaleY != scaleY) { invalidateParentCaches(); // Double-invalidation is necessary to capture view's old and new areas invalidate(false); invalidateViewProperty(true, false); info.mScaleY = scaleY; info.mMatrixDirty = true; mPrivateFlags |= DRAWN; // force another invalidation with the new orientation invalidate(false); invalidateViewProperty(false, true); if (USE_DISPLAY_LIST_PROPERTIES && mDisplayList != null) { mDisplayList.setScaleY(scaleY); } Loading Loading @@ -7633,13 +7618,10 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal mPrivateFlags |= PIVOT_EXPLICITLY_SET; final TransformationInfo info = mTransformationInfo; if (info.mPivotX != pivotX) { invalidateParentCaches(); // Double-invalidation is necessary to capture view's old and new areas invalidate(false); invalidateViewProperty(true, false); info.mPivotX = pivotX; info.mMatrixDirty = true; mPrivateFlags |= DRAWN; // force another invalidation with the new orientation invalidate(false); invalidateViewProperty(false, true); if (USE_DISPLAY_LIST_PROPERTIES && mDisplayList != null) { mDisplayList.setPivotX(pivotX); } Loading Loading @@ -7680,13 +7662,10 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal mPrivateFlags |= PIVOT_EXPLICITLY_SET; final TransformationInfo info = mTransformationInfo; if (info.mPivotY != pivotY) { invalidateParentCaches(); // Double-invalidation is necessary to capture view's old and new areas invalidate(false); invalidateViewProperty(true, false); info.mPivotY = pivotY; info.mMatrixDirty = true; mPrivateFlags |= DRAWN; // force another invalidation with the new orientation invalidate(false); invalidateViewProperty(false, true); if (USE_DISPLAY_LIST_PROPERTIES && mDisplayList != null) { mDisplayList.setPivotY(pivotY); } Loading Loading @@ -7728,14 +7707,14 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal ensureTransformationInfo(); if (mTransformationInfo.mAlpha != alpha) { mTransformationInfo.mAlpha = alpha; invalidateParentCaches(); if (onSetAlpha((int) (alpha * 255))) { mPrivateFlags |= ALPHA_SET; // subclass is handling alpha - don't optimize rendering cache invalidation invalidateParentCaches(); invalidate(true); } else { mPrivateFlags &= ~ALPHA_SET; invalidate(false); invalidateViewProperty(true, false); if (USE_DISPLAY_LIST_PROPERTIES && mDisplayList != null) { mDisplayList.setAlpha(alpha); } Loading Loading @@ -8102,13 +8081,11 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal ensureTransformationInfo(); final TransformationInfo info = mTransformationInfo; if (info.mTranslationX != translationX) { invalidateParentCaches(); // Double-invalidation is necessary to capture view's old and new areas invalidate(false); invalidateViewProperty(true, false); info.mTranslationX = translationX; info.mMatrixDirty = true; mPrivateFlags |= DRAWN; // force another invalidation with the new orientation invalidate(false); invalidateViewProperty(false, true); if (USE_DISPLAY_LIST_PROPERTIES && mDisplayList != null) { mDisplayList.setTranslationX(translationX); } Loading Loading @@ -8142,13 +8119,10 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal ensureTransformationInfo(); final TransformationInfo info = mTransformationInfo; if (info.mTranslationY != translationY) { invalidateParentCaches(); // Double-invalidation is necessary to capture view's old and new areas invalidate(false); invalidateViewProperty(true, false); info.mTranslationY = translationY; info.mMatrixDirty = true; mPrivateFlags |= DRAWN; // force another invalidation with the new orientation invalidate(false); invalidateViewProperty(false, true); if (USE_DISPLAY_LIST_PROPERTIES && mDisplayList != null) { mDisplayList.setTranslationY(translationY); } Loading Loading @@ -8260,6 +8234,9 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal final boolean matrixIsIdentity = mTransformationInfo == null || mTransformationInfo.mMatrixIsIdentity; if (matrixIsIdentity) { if (USE_DISPLAY_LIST_PROPERTIES && mDisplayList != null) { invalidateViewProperty(false, false); } else { final ViewParent p = mParent; if (p != null && mAttachInfo != null) { final Rect r = mAttachInfo.mTmpInvalRect; Loading @@ -8278,23 +8255,24 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal r.set(0, yLoc, mRight - mLeft, maxBottom - minTop); p.invalidateChild(this, r); } } } else { invalidate(false); invalidateViewProperty(false, false); } mTop += offset; mBottom += offset; if (USE_DISPLAY_LIST_PROPERTIES && mDisplayList != null) { mDisplayList.offsetTopBottom(offset); } invalidateViewProperty(false, false); } else { if (!matrixIsIdentity) { mPrivateFlags |= DRAWN; // force another invalidation with the new orientation invalidate(false); invalidateViewProperty(false, true); } invalidateParentIfNeeded(); } } } /** * Offset this view's horizontal location by the specified amount of pixels. Loading @@ -8307,6 +8285,9 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal final boolean matrixIsIdentity = mTransformationInfo == null || mTransformationInfo.mMatrixIsIdentity; if (matrixIsIdentity) { if (USE_DISPLAY_LIST_PROPERTIES && mDisplayList != null) { invalidateViewProperty(false, false); } else { final ViewParent p = mParent; if (p != null && mAttachInfo != null) { final Rect r = mAttachInfo.mTmpInvalRect; Loading @@ -8322,23 +8303,24 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal r.set(0, 0, maxRight - minLeft, mBottom - mTop); p.invalidateChild(this, r); } } } else { invalidate(false); invalidateViewProperty(false, false); } mLeft += offset; mRight += offset; if (USE_DISPLAY_LIST_PROPERTIES && mDisplayList != null) { mDisplayList.offsetLeftRight(offset); } invalidateViewProperty(false, false); } else { if (!matrixIsIdentity) { mPrivateFlags |= DRAWN; // force another invalidation with the new orientation invalidate(false); invalidateViewProperty(false, true); } invalidateParentIfNeeded(); } } } /** * Get the LayoutParams associated with this view. All views should have Loading Loading @@ -8740,6 +8722,62 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal } } /** * Quick invalidation for View property changes (alpha, translationXY, etc.). We don't want to * set any flags or handle all of the cases handled by the default invalidation methods. * Instead, we just want to schedule a traversal in ViewRootImpl with the appropriate * dirty rect. This method calls into fast invalidation methods in ViewGroup that * walk up the hierarchy, transforming the dirty rect as necessary. * * The method also handles normal invalidation logic if display list properties are not * being used in this view. The invalidateParent and forceRedraw flags are used by that * backup approach, to handle these cases used in the various property-setting methods. * * @param invalidateParent Force a call to invalidateParentCaches() if display list properties * are not being used in this view * @param forceRedraw Mark the view as DRAWN to force the invalidation to propagate, if display * list properties are not being used in this view */ void invalidateViewProperty(boolean invalidateParent, boolean forceRedraw) { if (!USE_DISPLAY_LIST_PROPERTIES || mDisplayList == null || (mPrivateFlags & DRAW_ANIMATION) == DRAW_ANIMATION) { if (invalidateParent) { invalidateParentCaches(); } if (forceRedraw) { mPrivateFlags |= DRAWN; // force another invalidation with the new orientation } invalidate(false); } else { final AttachInfo ai = mAttachInfo; final ViewParent p = mParent; if (p != null && ai != null) { final Rect r = ai.mTmpInvalRect; r.set(0, 0, mRight - mLeft, mBottom - mTop); if (mParent instanceof ViewGroup) { ((ViewGroup) mParent).invalidateChildFast(this, r); } else { mParent.invalidateChild(this, r); } } } } /** * Utility method to transform a given Rect by the current matrix of this view. */ void transformRect(final Rect rect) { if (!getMatrix().isIdentity()) { RectF boundingRect = mAttachInfo.mTmpTransformRect; boundingRect.set(rect); getMatrix().mapRect(boundingRect); rect.set((int) (boundingRect.left - 0.5f), (int) (boundingRect.top - 0.5f), (int) (boundingRect.right + 0.5f), (int) (boundingRect.bottom + 0.5f)); } } /** * Used to indicate that the parent of this view should clear its caches. This functionality * is used to force the parent to rebuild its display list (when hardware-accelerated), Loading core/java/android/view/ViewGroup.java +67 −0 Original line number Diff line number Diff line Loading @@ -3895,6 +3895,72 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager return null; } /** * Quick invalidation method called by View.invalidateViewProperty. This doesn't set the * DRAWN flags and doesn't handle the Animation logic that the default invalidation methods * do; all we want to do here is schedule a traversal with the appropriate dirty rect. * * @hide */ public void invalidateChildFast(View child, final Rect dirty) { ViewParent parent = this; final AttachInfo attachInfo = mAttachInfo; if (attachInfo != null) { if (child.mLayerType != LAYER_TYPE_NONE) { child.mLocalDirtyRect.union(dirty); } int left = child.mLeft; int top = child.mTop; if (!child.getMatrix().isIdentity()) { child.transformRect(dirty); } do { if (parent instanceof ViewGroup) { ViewGroup parentVG = (ViewGroup) parent; parent = parentVG.invalidateChildInParentFast(left, top, dirty); left = parentVG.mLeft; top = parentVG.mTop; } else { // Reached the top; this calls into the usual invalidate method in // ViewRootImpl, which schedules a traversal final int[] location = attachInfo.mInvalidateChildLocation; location[0] = left; location[1] = top; parent = parent.invalidateChildInParent(location, dirty); } } while (parent != null); } } /** * Quick invalidation method that simply transforms the dirty rect into the parent's * coordinate system, pruning the invalidation if the parent has already been invalidated. */ private ViewParent invalidateChildInParentFast(int left, int top, final Rect dirty) { if ((mPrivateFlags & DRAWN) == DRAWN || (mPrivateFlags & DRAWING_CACHE_VALID) == DRAWING_CACHE_VALID) { dirty.offset(left - mScrollX, top - mScrollY); if ((mGroupFlags & FLAG_CLIP_CHILDREN) == 0 || dirty.intersect(0, 0, mRight - mLeft, mBottom - mTop)) { if (mLayerType != LAYER_TYPE_NONE) { mLocalDirtyRect.union(dirty); } if (!getMatrix().isIdentity()) { transformRect(dirty); } return mParent; } } return null; } /** * Offset a rectangle that is in a descendant's coordinate * space into our coordinate space. Loading Loading @@ -3986,6 +4052,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager v.mBottom += offset; if (USE_DISPLAY_LIST_PROPERTIES && v.mDisplayList != null) { v.mDisplayList.offsetTopBottom(offset); invalidateViewProperty(false, false); } } } Loading core/java/android/view/ViewPropertyAnimator.java +15 −4 Original line number Diff line number Diff line Loading @@ -986,17 +986,22 @@ public class ViewPropertyAnimator { // Shouldn't happen, but just to play it safe return; } boolean useDisplayListProperties = View.USE_DISPLAY_LIST_PROPERTIES && mView.mDisplayList != null; // alpha requires slightly different treatment than the other (transform) properties. // The logic in setAlpha() is not simply setting mAlpha, plus the invalidation // logic is dependent on how the view handles an internal call to onSetAlpha(). // We track what kinds of properties are set, and how alpha is handled when it is // set, and perform the invalidation steps appropriately. boolean alphaHandled = false; if (!useDisplayListProperties) { mView.invalidateParentCaches(); } float fraction = animation.getAnimatedFraction(); int propertyMask = propertyBundle.mPropertyMask; if ((propertyMask & TRANSFORM_MASK) != 0) { mView.invalidate(false); mView.invalidateViewProperty(false, false); } ArrayList<NameValuesHolder> valueList = propertyBundle.mNameValuesHolder; if (valueList != null) { Loading @@ -1013,11 +1018,17 @@ public class ViewPropertyAnimator { } if ((propertyMask & TRANSFORM_MASK) != 0) { mView.mTransformationInfo.mMatrixDirty = true; if (!useDisplayListProperties) { mView.mPrivateFlags |= View.DRAWN; // force another invalidation } } // invalidate(false) in all cases except if alphaHandled gets set to true // via the call to setAlphaNoInvalidation(), above mView.invalidate(alphaHandled); if (alphaHandled) { mView.invalidate(true); } else { mView.invalidateViewProperty(false, false); } } } } libs/hwui/DisplayListRenderer.cpp +26 −26 Original line number Diff line number Diff line Loading @@ -671,18 +671,6 @@ void DisplayList::outputViewProperties(OpenGLRenderer& renderer, char* indent) { if (mLeft != 0 || mTop != 0) { ALOGD("%s%s %d, %d", indent, "Translate", mLeft, mTop); } if (mAlpha < 1) { // TODO: should be able to store the size of a DL at record time and not // have to pass it into this call. In fact, this information might be in the // location/size info that we store with the new native transform data. int flags = SkCanvas::kHasAlphaLayer_SaveFlag; if (mClipChildren) { flags |= SkCanvas::kClipToLayer_SaveFlag; } ALOGD("%s%s %.2f, %.2f, %.2f, %.2f, %d, 0x%x", indent, "SaveLayerAlpha", (float) 0, (float) 0, (float) mRight - mLeft, (float) mBottom - mTop, mMultipliedAlpha, flags); } if (mMatrixFlags != 0) { if (mMatrixFlags == TRANSLATION) { ALOGD("%s%s %f, %f", indent, "Translate", mTranslationX, mTranslationY); Loading @@ -696,6 +684,18 @@ void DisplayList::outputViewProperties(OpenGLRenderer& renderer, char* indent) { mTransformMatrix->get(8)); } } if (mAlpha < 1) { // TODO: should be able to store the size of a DL at record time and not // have to pass it into this call. In fact, this information might be in the // location/size info that we store with the new native transform data. int flags = SkCanvas::kHasAlphaLayer_SaveFlag; if (mClipChildren) { flags |= SkCanvas::kClipToLayer_SaveFlag; } ALOGD("%s%s %.2f, %.2f, %.2f, %.2f, %d, 0x%x", indent, "SaveLayerAlpha", (float) 0, (float) 0, (float) mRight - mLeft, (float) mBottom - mTop, mMultipliedAlpha, flags); } if (mClipChildren) { ALOGD("%s%s %.2f, %.2f, %.2f, %.2f", indent, "ClipRect", 0.0f, 0.0f, (float) mRight - mLeft, (float) mBottom - mTop); Loading Loading @@ -724,20 +724,6 @@ void DisplayList::setViewProperties(OpenGLRenderer& renderer, uint32_t width, ui mApplicationScale, mApplicationScale); renderer.scale(mApplicationScale, mApplicationScale); } if (mAlpha < 1 && !mCaching) { // TODO: should be able to store the size of a DL at record time and not // have to pass it into this call. In fact, this information might be in the // location/size info that we store with the new native transform data. int flags = SkCanvas::kHasAlphaLayer_SaveFlag; if (mClipChildren) { flags |= SkCanvas::kClipToLayer_SaveFlag; } DISPLAY_LIST_LOGD("%s%s %.2f, %.2f, %.2f, %.2f, %d, 0x%x", indent, "SaveLayerAlpha", (float) 0, (float) 0, (float) mRight - mLeft, (float) mBottom - mTop, mMultipliedAlpha, flags); renderer.saveLayerAlpha(0, 0, mRight - mLeft, mBottom - mTop, mMultipliedAlpha, flags); } if (mMatrixFlags != 0) { if (mMatrixFlags == TRANSLATION) { DISPLAY_LIST_LOGD("%s%s %f, %f", indent, "Translate", mTranslationX, mTranslationY); Loading @@ -754,6 +740,20 @@ void DisplayList::setViewProperties(OpenGLRenderer& renderer, uint32_t width, ui renderer.concatMatrix(mTransformMatrix); } } if (mAlpha < 1 && !mCaching) { // TODO: should be able to store the size of a DL at record time and not // have to pass it into this call. In fact, this information might be in the // location/size info that we store with the new native transform data. int flags = SkCanvas::kHasAlphaLayer_SaveFlag; if (mClipChildren) { flags |= SkCanvas::kClipToLayer_SaveFlag; } DISPLAY_LIST_LOGD("%s%s %.2f, %.2f, %.2f, %.2f, %d, 0x%x", indent, "SaveLayerAlpha", (float) 0, (float) 0, (float) mRight - mLeft, (float) mBottom - mTop, mMultipliedAlpha, flags); renderer.saveLayerAlpha(0, 0, mRight - mLeft, mBottom - mTop, mMultipliedAlpha, flags); } if (mClipChildren) { DISPLAY_LIST_LOGD("%s%s %.2f, %.2f, %.2f, %.2f", indent, "ClipRect", 0.0f, 0.0f, (float) mRight - mLeft, (float) mBottom - mTop); Loading Loading
core/java/android/view/HardwareRenderer.java +5 −0 Original line number Diff line number Diff line Loading @@ -960,6 +960,11 @@ 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) { Loading
core/java/android/view/View.java +130 −92 Original line number Diff line number Diff line Loading @@ -1503,7 +1503,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal * apps. * @hide */ protected static final boolean USE_DISPLAY_LIST_PROPERTIES = false; public static final boolean USE_DISPLAY_LIST_PROPERTIES = false; /** * Map used to store views' tags. Loading Loading @@ -7349,8 +7349,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal * @see #setRotationY(float) */ public void setCameraDistance(float distance) { invalidateParentCaches(); invalidate(false); invalidateViewProperty(true, false); ensureTransformationInfo(); final float dpi = mResources.getDisplayMetrics().densityDpi; Loading @@ -7363,7 +7362,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal info.mCamera.setLocation(0.0f, 0.0f, -Math.abs(distance) / dpi); info.mMatrixDirty = true; invalidate(false); invalidateViewProperty(false, false); if (USE_DISPLAY_LIST_PROPERTIES && mDisplayList != null) { mDisplayList.setCameraDistance(distance); } Loading Loading @@ -7401,13 +7400,11 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal ensureTransformationInfo(); final TransformationInfo info = mTransformationInfo; if (info.mRotation != rotation) { invalidateParentCaches(); // Double-invalidation is necessary to capture view's old and new areas invalidate(false); invalidateViewProperty(true, false); info.mRotation = rotation; info.mMatrixDirty = true; mPrivateFlags |= DRAWN; // force another invalidation with the new orientation invalidate(false); invalidateViewProperty(false, true); if (USE_DISPLAY_LIST_PROPERTIES && mDisplayList != null) { mDisplayList.setRotation(rotation); } Loading Loading @@ -7451,13 +7448,10 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal ensureTransformationInfo(); final TransformationInfo info = mTransformationInfo; if (info.mRotationY != rotationY) { invalidateParentCaches(); // Double-invalidation is necessary to capture view's old and new areas invalidate(false); invalidateViewProperty(true, false); info.mRotationY = rotationY; info.mMatrixDirty = true; mPrivateFlags |= DRAWN; // force another invalidation with the new orientation invalidate(false); invalidateViewProperty(false, true); if (USE_DISPLAY_LIST_PROPERTIES && mDisplayList != null) { mDisplayList.setRotationY(rotationY); } Loading Loading @@ -7501,13 +7495,10 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal ensureTransformationInfo(); final TransformationInfo info = mTransformationInfo; if (info.mRotationX != rotationX) { invalidateParentCaches(); // Double-invalidation is necessary to capture view's old and new areas invalidate(false); invalidateViewProperty(true, false); info.mRotationX = rotationX; info.mMatrixDirty = true; mPrivateFlags |= DRAWN; // force another invalidation with the new orientation invalidate(false); invalidateViewProperty(false, true); if (USE_DISPLAY_LIST_PROPERTIES && mDisplayList != null) { mDisplayList.setRotationX(rotationX); } Loading Loading @@ -7543,13 +7534,10 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal ensureTransformationInfo(); final TransformationInfo info = mTransformationInfo; if (info.mScaleX != scaleX) { invalidateParentCaches(); // Double-invalidation is necessary to capture view's old and new areas invalidate(false); invalidateViewProperty(true, false); info.mScaleX = scaleX; info.mMatrixDirty = true; mPrivateFlags |= DRAWN; // force another invalidation with the new orientation invalidate(false); invalidateViewProperty(false, true); if (USE_DISPLAY_LIST_PROPERTIES && mDisplayList != null) { mDisplayList.setScaleX(scaleX); } Loading Loading @@ -7585,13 +7573,10 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal ensureTransformationInfo(); final TransformationInfo info = mTransformationInfo; if (info.mScaleY != scaleY) { invalidateParentCaches(); // Double-invalidation is necessary to capture view's old and new areas invalidate(false); invalidateViewProperty(true, false); info.mScaleY = scaleY; info.mMatrixDirty = true; mPrivateFlags |= DRAWN; // force another invalidation with the new orientation invalidate(false); invalidateViewProperty(false, true); if (USE_DISPLAY_LIST_PROPERTIES && mDisplayList != null) { mDisplayList.setScaleY(scaleY); } Loading Loading @@ -7633,13 +7618,10 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal mPrivateFlags |= PIVOT_EXPLICITLY_SET; final TransformationInfo info = mTransformationInfo; if (info.mPivotX != pivotX) { invalidateParentCaches(); // Double-invalidation is necessary to capture view's old and new areas invalidate(false); invalidateViewProperty(true, false); info.mPivotX = pivotX; info.mMatrixDirty = true; mPrivateFlags |= DRAWN; // force another invalidation with the new orientation invalidate(false); invalidateViewProperty(false, true); if (USE_DISPLAY_LIST_PROPERTIES && mDisplayList != null) { mDisplayList.setPivotX(pivotX); } Loading Loading @@ -7680,13 +7662,10 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal mPrivateFlags |= PIVOT_EXPLICITLY_SET; final TransformationInfo info = mTransformationInfo; if (info.mPivotY != pivotY) { invalidateParentCaches(); // Double-invalidation is necessary to capture view's old and new areas invalidate(false); invalidateViewProperty(true, false); info.mPivotY = pivotY; info.mMatrixDirty = true; mPrivateFlags |= DRAWN; // force another invalidation with the new orientation invalidate(false); invalidateViewProperty(false, true); if (USE_DISPLAY_LIST_PROPERTIES && mDisplayList != null) { mDisplayList.setPivotY(pivotY); } Loading Loading @@ -7728,14 +7707,14 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal ensureTransformationInfo(); if (mTransformationInfo.mAlpha != alpha) { mTransformationInfo.mAlpha = alpha; invalidateParentCaches(); if (onSetAlpha((int) (alpha * 255))) { mPrivateFlags |= ALPHA_SET; // subclass is handling alpha - don't optimize rendering cache invalidation invalidateParentCaches(); invalidate(true); } else { mPrivateFlags &= ~ALPHA_SET; invalidate(false); invalidateViewProperty(true, false); if (USE_DISPLAY_LIST_PROPERTIES && mDisplayList != null) { mDisplayList.setAlpha(alpha); } Loading Loading @@ -8102,13 +8081,11 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal ensureTransformationInfo(); final TransformationInfo info = mTransformationInfo; if (info.mTranslationX != translationX) { invalidateParentCaches(); // Double-invalidation is necessary to capture view's old and new areas invalidate(false); invalidateViewProperty(true, false); info.mTranslationX = translationX; info.mMatrixDirty = true; mPrivateFlags |= DRAWN; // force another invalidation with the new orientation invalidate(false); invalidateViewProperty(false, true); if (USE_DISPLAY_LIST_PROPERTIES && mDisplayList != null) { mDisplayList.setTranslationX(translationX); } Loading Loading @@ -8142,13 +8119,10 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal ensureTransformationInfo(); final TransformationInfo info = mTransformationInfo; if (info.mTranslationY != translationY) { invalidateParentCaches(); // Double-invalidation is necessary to capture view's old and new areas invalidate(false); invalidateViewProperty(true, false); info.mTranslationY = translationY; info.mMatrixDirty = true; mPrivateFlags |= DRAWN; // force another invalidation with the new orientation invalidate(false); invalidateViewProperty(false, true); if (USE_DISPLAY_LIST_PROPERTIES && mDisplayList != null) { mDisplayList.setTranslationY(translationY); } Loading Loading @@ -8260,6 +8234,9 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal final boolean matrixIsIdentity = mTransformationInfo == null || mTransformationInfo.mMatrixIsIdentity; if (matrixIsIdentity) { if (USE_DISPLAY_LIST_PROPERTIES && mDisplayList != null) { invalidateViewProperty(false, false); } else { final ViewParent p = mParent; if (p != null && mAttachInfo != null) { final Rect r = mAttachInfo.mTmpInvalRect; Loading @@ -8278,23 +8255,24 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal r.set(0, yLoc, mRight - mLeft, maxBottom - minTop); p.invalidateChild(this, r); } } } else { invalidate(false); invalidateViewProperty(false, false); } mTop += offset; mBottom += offset; if (USE_DISPLAY_LIST_PROPERTIES && mDisplayList != null) { mDisplayList.offsetTopBottom(offset); } invalidateViewProperty(false, false); } else { if (!matrixIsIdentity) { mPrivateFlags |= DRAWN; // force another invalidation with the new orientation invalidate(false); invalidateViewProperty(false, true); } invalidateParentIfNeeded(); } } } /** * Offset this view's horizontal location by the specified amount of pixels. Loading @@ -8307,6 +8285,9 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal final boolean matrixIsIdentity = mTransformationInfo == null || mTransformationInfo.mMatrixIsIdentity; if (matrixIsIdentity) { if (USE_DISPLAY_LIST_PROPERTIES && mDisplayList != null) { invalidateViewProperty(false, false); } else { final ViewParent p = mParent; if (p != null && mAttachInfo != null) { final Rect r = mAttachInfo.mTmpInvalRect; Loading @@ -8322,23 +8303,24 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal r.set(0, 0, maxRight - minLeft, mBottom - mTop); p.invalidateChild(this, r); } } } else { invalidate(false); invalidateViewProperty(false, false); } mLeft += offset; mRight += offset; if (USE_DISPLAY_LIST_PROPERTIES && mDisplayList != null) { mDisplayList.offsetLeftRight(offset); } invalidateViewProperty(false, false); } else { if (!matrixIsIdentity) { mPrivateFlags |= DRAWN; // force another invalidation with the new orientation invalidate(false); invalidateViewProperty(false, true); } invalidateParentIfNeeded(); } } } /** * Get the LayoutParams associated with this view. All views should have Loading Loading @@ -8740,6 +8722,62 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal } } /** * Quick invalidation for View property changes (alpha, translationXY, etc.). We don't want to * set any flags or handle all of the cases handled by the default invalidation methods. * Instead, we just want to schedule a traversal in ViewRootImpl with the appropriate * dirty rect. This method calls into fast invalidation methods in ViewGroup that * walk up the hierarchy, transforming the dirty rect as necessary. * * The method also handles normal invalidation logic if display list properties are not * being used in this view. The invalidateParent and forceRedraw flags are used by that * backup approach, to handle these cases used in the various property-setting methods. * * @param invalidateParent Force a call to invalidateParentCaches() if display list properties * are not being used in this view * @param forceRedraw Mark the view as DRAWN to force the invalidation to propagate, if display * list properties are not being used in this view */ void invalidateViewProperty(boolean invalidateParent, boolean forceRedraw) { if (!USE_DISPLAY_LIST_PROPERTIES || mDisplayList == null || (mPrivateFlags & DRAW_ANIMATION) == DRAW_ANIMATION) { if (invalidateParent) { invalidateParentCaches(); } if (forceRedraw) { mPrivateFlags |= DRAWN; // force another invalidation with the new orientation } invalidate(false); } else { final AttachInfo ai = mAttachInfo; final ViewParent p = mParent; if (p != null && ai != null) { final Rect r = ai.mTmpInvalRect; r.set(0, 0, mRight - mLeft, mBottom - mTop); if (mParent instanceof ViewGroup) { ((ViewGroup) mParent).invalidateChildFast(this, r); } else { mParent.invalidateChild(this, r); } } } } /** * Utility method to transform a given Rect by the current matrix of this view. */ void transformRect(final Rect rect) { if (!getMatrix().isIdentity()) { RectF boundingRect = mAttachInfo.mTmpTransformRect; boundingRect.set(rect); getMatrix().mapRect(boundingRect); rect.set((int) (boundingRect.left - 0.5f), (int) (boundingRect.top - 0.5f), (int) (boundingRect.right + 0.5f), (int) (boundingRect.bottom + 0.5f)); } } /** * Used to indicate that the parent of this view should clear its caches. This functionality * is used to force the parent to rebuild its display list (when hardware-accelerated), Loading
core/java/android/view/ViewGroup.java +67 −0 Original line number Diff line number Diff line Loading @@ -3895,6 +3895,72 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager return null; } /** * Quick invalidation method called by View.invalidateViewProperty. This doesn't set the * DRAWN flags and doesn't handle the Animation logic that the default invalidation methods * do; all we want to do here is schedule a traversal with the appropriate dirty rect. * * @hide */ public void invalidateChildFast(View child, final Rect dirty) { ViewParent parent = this; final AttachInfo attachInfo = mAttachInfo; if (attachInfo != null) { if (child.mLayerType != LAYER_TYPE_NONE) { child.mLocalDirtyRect.union(dirty); } int left = child.mLeft; int top = child.mTop; if (!child.getMatrix().isIdentity()) { child.transformRect(dirty); } do { if (parent instanceof ViewGroup) { ViewGroup parentVG = (ViewGroup) parent; parent = parentVG.invalidateChildInParentFast(left, top, dirty); left = parentVG.mLeft; top = parentVG.mTop; } else { // Reached the top; this calls into the usual invalidate method in // ViewRootImpl, which schedules a traversal final int[] location = attachInfo.mInvalidateChildLocation; location[0] = left; location[1] = top; parent = parent.invalidateChildInParent(location, dirty); } } while (parent != null); } } /** * Quick invalidation method that simply transforms the dirty rect into the parent's * coordinate system, pruning the invalidation if the parent has already been invalidated. */ private ViewParent invalidateChildInParentFast(int left, int top, final Rect dirty) { if ((mPrivateFlags & DRAWN) == DRAWN || (mPrivateFlags & DRAWING_CACHE_VALID) == DRAWING_CACHE_VALID) { dirty.offset(left - mScrollX, top - mScrollY); if ((mGroupFlags & FLAG_CLIP_CHILDREN) == 0 || dirty.intersect(0, 0, mRight - mLeft, mBottom - mTop)) { if (mLayerType != LAYER_TYPE_NONE) { mLocalDirtyRect.union(dirty); } if (!getMatrix().isIdentity()) { transformRect(dirty); } return mParent; } } return null; } /** * Offset a rectangle that is in a descendant's coordinate * space into our coordinate space. Loading Loading @@ -3986,6 +4052,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager v.mBottom += offset; if (USE_DISPLAY_LIST_PROPERTIES && v.mDisplayList != null) { v.mDisplayList.offsetTopBottom(offset); invalidateViewProperty(false, false); } } } Loading
core/java/android/view/ViewPropertyAnimator.java +15 −4 Original line number Diff line number Diff line Loading @@ -986,17 +986,22 @@ public class ViewPropertyAnimator { // Shouldn't happen, but just to play it safe return; } boolean useDisplayListProperties = View.USE_DISPLAY_LIST_PROPERTIES && mView.mDisplayList != null; // alpha requires slightly different treatment than the other (transform) properties. // The logic in setAlpha() is not simply setting mAlpha, plus the invalidation // logic is dependent on how the view handles an internal call to onSetAlpha(). // We track what kinds of properties are set, and how alpha is handled when it is // set, and perform the invalidation steps appropriately. boolean alphaHandled = false; if (!useDisplayListProperties) { mView.invalidateParentCaches(); } float fraction = animation.getAnimatedFraction(); int propertyMask = propertyBundle.mPropertyMask; if ((propertyMask & TRANSFORM_MASK) != 0) { mView.invalidate(false); mView.invalidateViewProperty(false, false); } ArrayList<NameValuesHolder> valueList = propertyBundle.mNameValuesHolder; if (valueList != null) { Loading @@ -1013,11 +1018,17 @@ public class ViewPropertyAnimator { } if ((propertyMask & TRANSFORM_MASK) != 0) { mView.mTransformationInfo.mMatrixDirty = true; if (!useDisplayListProperties) { mView.mPrivateFlags |= View.DRAWN; // force another invalidation } } // invalidate(false) in all cases except if alphaHandled gets set to true // via the call to setAlphaNoInvalidation(), above mView.invalidate(alphaHandled); if (alphaHandled) { mView.invalidate(true); } else { mView.invalidateViewProperty(false, false); } } } }
libs/hwui/DisplayListRenderer.cpp +26 −26 Original line number Diff line number Diff line Loading @@ -671,18 +671,6 @@ void DisplayList::outputViewProperties(OpenGLRenderer& renderer, char* indent) { if (mLeft != 0 || mTop != 0) { ALOGD("%s%s %d, %d", indent, "Translate", mLeft, mTop); } if (mAlpha < 1) { // TODO: should be able to store the size of a DL at record time and not // have to pass it into this call. In fact, this information might be in the // location/size info that we store with the new native transform data. int flags = SkCanvas::kHasAlphaLayer_SaveFlag; if (mClipChildren) { flags |= SkCanvas::kClipToLayer_SaveFlag; } ALOGD("%s%s %.2f, %.2f, %.2f, %.2f, %d, 0x%x", indent, "SaveLayerAlpha", (float) 0, (float) 0, (float) mRight - mLeft, (float) mBottom - mTop, mMultipliedAlpha, flags); } if (mMatrixFlags != 0) { if (mMatrixFlags == TRANSLATION) { ALOGD("%s%s %f, %f", indent, "Translate", mTranslationX, mTranslationY); Loading @@ -696,6 +684,18 @@ void DisplayList::outputViewProperties(OpenGLRenderer& renderer, char* indent) { mTransformMatrix->get(8)); } } if (mAlpha < 1) { // TODO: should be able to store the size of a DL at record time and not // have to pass it into this call. In fact, this information might be in the // location/size info that we store with the new native transform data. int flags = SkCanvas::kHasAlphaLayer_SaveFlag; if (mClipChildren) { flags |= SkCanvas::kClipToLayer_SaveFlag; } ALOGD("%s%s %.2f, %.2f, %.2f, %.2f, %d, 0x%x", indent, "SaveLayerAlpha", (float) 0, (float) 0, (float) mRight - mLeft, (float) mBottom - mTop, mMultipliedAlpha, flags); } if (mClipChildren) { ALOGD("%s%s %.2f, %.2f, %.2f, %.2f", indent, "ClipRect", 0.0f, 0.0f, (float) mRight - mLeft, (float) mBottom - mTop); Loading Loading @@ -724,20 +724,6 @@ void DisplayList::setViewProperties(OpenGLRenderer& renderer, uint32_t width, ui mApplicationScale, mApplicationScale); renderer.scale(mApplicationScale, mApplicationScale); } if (mAlpha < 1 && !mCaching) { // TODO: should be able to store the size of a DL at record time and not // have to pass it into this call. In fact, this information might be in the // location/size info that we store with the new native transform data. int flags = SkCanvas::kHasAlphaLayer_SaveFlag; if (mClipChildren) { flags |= SkCanvas::kClipToLayer_SaveFlag; } DISPLAY_LIST_LOGD("%s%s %.2f, %.2f, %.2f, %.2f, %d, 0x%x", indent, "SaveLayerAlpha", (float) 0, (float) 0, (float) mRight - mLeft, (float) mBottom - mTop, mMultipliedAlpha, flags); renderer.saveLayerAlpha(0, 0, mRight - mLeft, mBottom - mTop, mMultipliedAlpha, flags); } if (mMatrixFlags != 0) { if (mMatrixFlags == TRANSLATION) { DISPLAY_LIST_LOGD("%s%s %f, %f", indent, "Translate", mTranslationX, mTranslationY); Loading @@ -754,6 +740,20 @@ void DisplayList::setViewProperties(OpenGLRenderer& renderer, uint32_t width, ui renderer.concatMatrix(mTransformMatrix); } } if (mAlpha < 1 && !mCaching) { // TODO: should be able to store the size of a DL at record time and not // have to pass it into this call. In fact, this information might be in the // location/size info that we store with the new native transform data. int flags = SkCanvas::kHasAlphaLayer_SaveFlag; if (mClipChildren) { flags |= SkCanvas::kClipToLayer_SaveFlag; } DISPLAY_LIST_LOGD("%s%s %.2f, %.2f, %.2f, %.2f, %d, 0x%x", indent, "SaveLayerAlpha", (float) 0, (float) 0, (float) mRight - mLeft, (float) mBottom - mTop, mMultipliedAlpha, flags); renderer.saveLayerAlpha(0, 0, mRight - mLeft, mBottom - mTop, mMultipliedAlpha, flags); } if (mClipChildren) { DISPLAY_LIST_LOGD("%s%s %.2f, %.2f, %.2f, %.2f", indent, "ClipRect", 0.0f, 0.0f, (float) mRight - mLeft, (float) mBottom - mTop); Loading