summaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
authorAlan Viverette <alanv@google.com>2014-02-04 22:05:26 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2014-02-04 22:05:26 +0000
commit9f244efbfac8d592a0af0321f7985761ed17ec6c (patch)
tree79fa9a35e6b4ee5f9c99ec65e8aa0cd3ac106c44 /core
parent40675bdd3857a9e29b2e61b5bc1660e9bb2e82a2 (diff)
parent4085aac5833e6d88c3f77b6c86cc7520a2550bfc (diff)
downloadframeworks_base-9f244efbfac8d592a0af0321f7985761ed17ec6c.zip
frameworks_base-9f244efbfac8d592a0af0321f7985761ed17ec6c.tar.gz
frameworks_base-9f244efbfac8d592a0af0321f7985761ed17ec6c.tar.bz2
Merge "Make background projection a property of View"
Diffstat (limited to 'core')
-rw-r--r--core/java/android/view/View.java165
1 files changed, 140 insertions, 25 deletions
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 15ede96..12dc044 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -2325,7 +2325,18 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
/* End of masks for mPrivateFlags2 */
- /* Masks for mPrivateFlags3 */
+ /**
+ * Masks for mPrivateFlags3, as generated by dumpFlags():
+ *
+ * |-------|-------|-------|-------|
+ * 1 PFLAG3_VIEW_IS_ANIMATING_TRANSFORM
+ * 1 PFLAG3_VIEW_IS_ANIMATING_ALPHA
+ * 1 PFLAG3_IS_LAID_OUT
+ * 1 PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT
+ * 1 PFLAG3_CALLED_SUPER
+ * 1 PFLAG3_PROJECT_BACKGROUND
+ * |-------|-------|-------|-------|
+ */
/**
* Flag indicating that view has a transform animation set on it. This is used to track whether
@@ -2359,6 +2370,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
*/
static final int PFLAG3_CALLED_SUPER = 0x10;
+ /**
+ * Flag indicating that the background of this view will be drawn into a
+ * display list and projected onto the closest parent projection surface.
+ */
+ static final int PFLAG3_PROJECT_BACKGROUND = 0x20;
/* End of masks for mPrivateFlags3 */
@@ -3225,6 +3241,15 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
@ViewDebug.ExportedProperty(deepExport = true, prefix = "bg_")
private Drawable mBackground;
+ /**
+ * Display list used for backgrounds.
+ * <p>
+ * When non-null and valid, this is expected to contain an up-to-date copy
+ * of the background drawable. It is cleared on temporary detach and reset
+ * on cleanup.
+ */
+ private DisplayList mBackgroundDisplayList;
+
private int mBackgroundResource;
private boolean mBackgroundSizeChanged;
@@ -3503,6 +3528,13 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
private Bitmap mDrawingCache;
private Bitmap mUnscaledDrawingCache;
+ /**
+ * Display list used for the View content.
+ * <p>
+ * When non-null and valid, this is expected to contain an up-to-date copy
+ * of the View content. It is cleared on temporary detach and reset on
+ * cleanup.
+ */
DisplayList mDisplayList;
/**
@@ -13688,12 +13720,20 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
if (mDisplayList != null) {
mDisplayList.clear();
}
+
+ if (mBackgroundDisplayList != null) {
+ mBackgroundDisplayList.clear();
+ }
}
private void resetDisplayList() {
if (mDisplayList != null) {
mDisplayList.reset();
}
+
+ if (mBackgroundDisplayList != null) {
+ mBackgroundDisplayList.reset();
+ }
}
/**
@@ -14721,24 +14761,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
int saveCount;
if (!dirtyOpaque) {
- final Drawable background = mBackground;
- if (background != null) {
- final int scrollX = mScrollX;
- final int scrollY = mScrollY;
-
- if (mBackgroundSizeChanged) {
- background.setBounds(0, 0, mRight - mLeft, mBottom - mTop);
- mBackgroundSizeChanged = false;
- }
-
- if ((scrollX | scrollY) == 0) {
- background.draw(canvas);
- } else {
- canvas.translate(scrollX, scrollY);
- background.draw(canvas);
- canvas.translate(-scrollX, -scrollY);
- }
- }
+ drawBackground(canvas);
}
// skip step 2 & 5 if possible (common case)
@@ -14905,6 +14928,90 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
}
/**
+ * Draws the background onto the specified canvas.
+ *
+ * @param canvas Canvas on which to draw the background
+ */
+ private void drawBackground(Canvas canvas) {
+ final Drawable background = mBackground;
+ if (background == null) {
+ return;
+ }
+
+ if (mBackgroundSizeChanged) {
+ // We should see the background invalidate itself, but just to be
+ // careful we're going to clear the display list and force redraw.
+ mBackgroundDisplayList.clear();
+ background.setBounds(0, 0, mRight - mLeft, mBottom - mTop);
+ mBackgroundSizeChanged = false;
+ }
+
+
+ // Attempt to use a display list if requested.
+ if (canvas != null && canvas.isHardwareAccelerated()) {
+ mBackgroundDisplayList = getDrawableDisplayList(background, mBackgroundDisplayList);
+
+ final DisplayList displayList = mBackgroundDisplayList;
+ if (displayList != null && displayList.isValid()) {
+ setBackgroundDisplayListProperties(displayList);
+ ((HardwareCanvas) canvas).drawDisplayList(displayList);
+ return;
+ }
+ }
+
+ final int scrollX = mScrollX;
+ final int scrollY = mScrollY;
+ if ((scrollX | scrollY) == 0) {
+ background.draw(canvas);
+ } else {
+ canvas.translate(scrollX, scrollY);
+ background.draw(canvas);
+ canvas.translate(-scrollX, -scrollY);
+ }
+ }
+
+ /**
+ * Set up background drawable display list properties.
+ *
+ * @param displayList Valid display list for the background drawable
+ */
+ private void setBackgroundDisplayListProperties(DisplayList displayList) {
+ displayList.setProjectBackwards((mPrivateFlags3 & PFLAG3_PROJECT_BACKGROUND) != 0);
+ displayList.setTranslationX(mScrollX);
+ displayList.setTranslationY(mScrollY);
+ }
+
+ /**
+ * Creates a new display list or updates the existing display list for the
+ * specified Drawable.
+ *
+ * @param drawable Drawable for which to create a display list
+ * @param displayList Existing display list, or {@code null}
+ * @return A valid display list for the specified drawable
+ */
+ private static DisplayList getDrawableDisplayList(Drawable drawable, DisplayList displayList) {
+ if (displayList != null && displayList.isValid()) {
+ return displayList;
+ }
+
+ if (displayList == null) {
+ displayList = DisplayList.create(drawable.getClass().getName());
+ }
+
+ final Rect bounds = drawable.getBounds();
+ final int width = bounds.width();
+ final int height = bounds.height();
+ final HardwareCanvas canvas = displayList.start(width, height);
+ drawable.draw(canvas);
+ displayList.end();
+
+ // Set up drawable properties that are view-independent.
+ displayList.setLeftTopRightBottom(bounds.left, bounds.top, bounds.right, bounds.bottom);
+ displayList.setClipToBounds(false);
+ return displayList;
+ }
+
+ /**
* Returns the overlay for this view, creating it if it does not yet exist.
* Adding drawables to the overlay will cause them to be displayed whenever
* the view itself is redrawn. Objects in the overlay should be actively
@@ -15245,14 +15352,22 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
*
* @param drawable the drawable to invalidate
*/
+ @Override
public void invalidateDrawable(Drawable drawable) {
if (verifyDrawable(drawable)) {
- final Rect dirty = drawable.getBounds();
- final int scrollX = mScrollX;
- final int scrollY = mScrollY;
+ if (drawable == mBackground && mBackgroundDisplayList != null) {
+ // If we're using a background display list, we only need to
+ // invalidate the display list and notify the parent to redraw.
+ mBackgroundDisplayList.clear();
+ invalidateViewProperty(true, false);
+ } else {
+ final Rect dirty = drawable.getBounds();
+ final int scrollX = mScrollX;
+ final int scrollY = mScrollY;
- invalidate(dirty.left + scrollX, dirty.top + scrollY,
- dirty.right + scrollX, dirty.bottom + scrollY);
+ invalidate(dirty.left + scrollX, dirty.top + scrollY,
+ dirty.right + scrollX, dirty.bottom + scrollY);
+ }
}
}
@@ -15399,7 +15514,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* @see Drawable#setState(int[])
*/
protected void drawableStateChanged() {
- Drawable d = mBackground;
+ final Drawable d = mBackground;
if (d != null && d.isStateful()) {
d.setState(getDrawableState());
}