summaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
authorChet Haase <chet@google.com>2012-02-21 13:43:44 -0800
committerChet Haase <chet@google.com>2012-03-12 15:41:48 -0700
commita1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3 (patch)
tree01a809b1ae5a50b8721f05c540a76570794d828c /core
parentbdc5afeee57a943adac3896297fab74b96b307c1 (diff)
downloadframeworks_base-a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3.zip
frameworks_base-a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3.tar.gz
frameworks_base-a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3.tar.bz2
Handle view properties at the native level
Basic functionality of handling View properties (transforms, left/right/top/bottom, and alpha) at the native DisplayList level. This logic is disabled for now (via compile-time flags in View.java and DisplayListRenderer.h) as we continue work on it (there is no advantage to the new approach until we optimize invalidation and rendering paths to use the new code path). Change-Id: I370c8d21fbd291be415f55515ab8dced6f6d51a3
Diffstat (limited to 'core')
-rw-r--r--core/java/android/view/DisplayList.java200
-rw-r--r--core/java/android/view/GLES20DisplayList.java245
-rw-r--r--core/java/android/view/HardwareLayer.java19
-rw-r--r--core/java/android/view/View.java327
-rw-r--r--core/java/android/view/ViewGroup.java16
-rw-r--r--core/java/android/view/ViewPropertyAnimator.java2
-rw-r--r--core/java/android/widget/TextView.java5
-rw-r--r--core/jni/Android.mk1
-rw-r--r--core/jni/AndroidRuntime.cpp2
-rw-r--r--core/jni/android/graphics/Camera.cpp18
-rw-r--r--core/jni/android_view_GLES20DisplayList.cpp227
11 files changed, 999 insertions, 63 deletions
diff --git a/core/java/android/view/DisplayList.java b/core/java/android/view/DisplayList.java
index f60c8f0..a50f09f 100644
--- a/core/java/android/view/DisplayList.java
+++ b/core/java/android/view/DisplayList.java
@@ -70,4 +70,204 @@ public abstract class DisplayList {
* @return The size of this display list in bytes
*/
public abstract int getSize();
+
+ ///////////////////////////////////////////////////////////////////////////
+ // DisplayList Property Setters
+ ///////////////////////////////////////////////////////////////////////////
+
+ /**
+ * Set the caching property on the DisplayList, which indicates whether the DisplayList
+ * holds a layer. Layer DisplayLists should avoid creating an alpha layer, since alpha is
+ * handled in the drawLayer operation directly (and more efficiently).
+ *
+ * @param caching true if the DisplayList represents a hardware layer, false otherwise.
+ */
+ public abstract void setCaching(boolean caching);
+
+ /**
+ * Set whether the DisplayList should clip itself to its bounds. This property is controlled by
+ * the view's parent.
+ *
+ * @param clipChildren true if the DisplayList should clip to its bounds
+ */
+ public abstract void setClipChildren(boolean clipChildren);
+
+ /**
+ * Set the application scale on the DisplayList. This scale is incurred by applications that
+ * are auto-scaled for compatibility reasons. By default, the value is 1 (unscaled).
+ *
+ * @param scale The scaling factor
+ */
+ public abstract void setApplicationScale(float scale);
+
+ /**
+ * Sets the alpha value for the DisplayList
+ *
+ * @param alpha The translucency of the DisplayList
+ * @see View#setAlpha(float)
+ */
+ public abstract void setAlpha(float alpha);
+
+ /**
+ * Sets the translationX value for the DisplayList
+ *
+ * @param translationX The translationX value of the DisplayList
+ * @see View#setTranslationX(float)
+ */
+ public abstract void setTranslationX(float translationX);
+
+ /**
+ * Sets the translationY value for the DisplayList
+ *
+ * @param translationY The translationY value of the DisplayList
+ * @see View#setTranslationY(float)
+ */
+ public abstract void setTranslationY(float translationY);
+
+ /**
+ * Sets the rotation value for the DisplayList
+ *
+ * @param rotation The rotation value of the DisplayList
+ * @see View#setRotation(float)
+ */
+ public abstract void setRotation(float rotation);
+
+ /**
+ * Sets the rotationX value for the DisplayList
+ *
+ * @param rotationX The rotationX value of the DisplayList
+ * @see View#setRotationX(float)
+ */
+ public abstract void setRotationX(float rotationX);
+
+ /**
+ * Sets the rotationY value for the DisplayList
+ *
+ * @param rotationY The rotationY value of the DisplayList
+ * @see View#setRotationY(float)
+ */
+ public abstract void setRotationY(float rotationY);
+
+ /**
+ * Sets the scaleX value for the DisplayList
+ *
+ * @param scaleX The scaleX value of the DisplayList
+ * @see View#setScaleX(float)
+ */
+ public abstract void setScaleX(float scaleX);
+
+ /**
+ * Sets the scaleY value for the DisplayList
+ *
+ * @param scaleY The scaleY value of the DisplayList
+ * @see View#setScaleY(float)
+ */
+ public abstract void setScaleY(float scaleY);
+
+ /**
+ * Sets all of the transform-related values of the View onto the DisplayList
+ *
+ * @param alpha The alpha value of the DisplayList
+ * @param translationX The translationX value of the DisplayList
+ * @param translationY The translationY value of the DisplayList
+ * @param rotation The rotation value of the DisplayList
+ * @param rotationX The rotationX value of the DisplayList
+ * @param rotationY The rotationY value of the DisplayList
+ * @param scaleX The scaleX value of the DisplayList
+ * @param scaleY The scaleY value of the DisplayList
+ */
+ public abstract void setTransformationInfo(float alpha, float translationX, float translationY,
+ float rotation, float rotationX, float rotationY, float scaleX, float scaleY);
+
+ /**
+ * Sets the pivotX value for the DisplayList
+ *
+ * @param pivotX The pivotX value of the DisplayList
+ * @see View#setPivotX(float)
+ */
+ public abstract void setPivotX(float pivotX);
+
+ /**
+ * Sets the pivotY value for the DisplayList
+ *
+ * @param pivotY The pivotY value of the DisplayList
+ * @see View#setPivotY(float)
+ */
+ public abstract void setPivotY(float pivotY);
+
+ /**
+ * Sets the camera distance for the DisplayList
+ *
+ * @param distance The distance in z of the camera of the DisplayList
+ * @see View#setCameraDistance(float)
+ */
+ public abstract void setCameraDistance(float distance);
+
+ /**
+ * Sets the left value for the DisplayList
+ *
+ * @param left The left value of the DisplayList
+ * @see View#setLeft(int)
+ */
+ public abstract void setLeft(int left);
+
+ /**
+ * Sets the top value for the DisplayList
+ *
+ * @param top The top value of the DisplayList
+ * @see View#setTop(int)
+ */
+ public abstract void setTop(int top);
+
+ /**
+ * Sets the right value for the DisplayList
+ *
+ * @param right The right value of the DisplayList
+ * @see View#setRight(int)
+ */
+ public abstract void setRight(int right);
+
+ /**
+ * Sets the bottom value for the DisplayList
+ *
+ * @param bottom The bottom value of the DisplayList
+ * @see View#setBottom(int)
+ */
+ public abstract void setBottom(int bottom);
+
+ /**
+ * Sets the left and top values for the DisplayList
+ *
+ * @param left The left value of the DisplayList
+ * @param top The top value of the DisplayList
+ * @see View#setLeft(int)
+ * @see View#setTop(int)
+ */
+ public abstract void setLeftTop(int left, int top);
+
+ /**
+ * Sets the left and top values for the DisplayList
+ *
+ * @param left The left value of the DisplayList
+ * @param top The top value of the DisplayList
+ * @see View#setLeft(int)
+ * @see View#setTop(int)
+ */
+ public abstract void setLeftTopRightBottom(int left, int top, int right, int bottom);
+
+ /**
+ * Offsets the left and right values for the DisplayList
+ *
+ * @param offset The amount that the left and right values of the DisplayList are offset
+ * @see View#offsetLeftAndRight(int)
+ */
+ public abstract void offsetLeftRight(int offset);
+
+ /**
+ * Offsets the top and bottom values for the DisplayList
+ *
+ * @param offset The amount that the top and bottom values of the DisplayList are offset
+ * @see View#offsetTopAndBottom(int)
+ */
+ public abstract void offsetTopBottom(int offset);
}
diff --git a/core/java/android/view/GLES20DisplayList.java b/core/java/android/view/GLES20DisplayList.java
index 969c9ab..9b4cf21 100644
--- a/core/java/android/view/GLES20DisplayList.java
+++ b/core/java/android/view/GLES20DisplayList.java
@@ -96,6 +96,251 @@ class GLES20DisplayList extends DisplayList {
return GLES20Canvas.getDisplayListSize(mFinalizer.mNativeDisplayList);
}
+ ///////////////////////////////////////////////////////////////////////////
+ // Native View Properties
+ ///////////////////////////////////////////////////////////////////////////
+
+ @Override
+ public void setCaching(boolean caching) {
+ try {
+ nSetCaching(getNativeDisplayList(), caching);
+ } catch (IllegalStateException e) {
+ // invalid DisplayList okay: we'll set current values the next time we render to it
+ }
+ }
+
+ @Override
+ public void setClipChildren(boolean clipChildren) {
+ try {
+ nSetClipChildren(getNativeDisplayList(), clipChildren);
+ } catch (IllegalStateException e) {
+ // invalid DisplayList okay: we'll set current values the next time we render to it
+ }
+ }
+
+ @Override
+ public void setApplicationScale(float scale) {
+ try {
+ nSetApplicationScale(getNativeDisplayList(), scale);
+ } catch (IllegalStateException e) {
+ // invalid DisplayList okay: we'll set current values the next time we render to it
+ }
+ }
+
+ @Override
+ public void setAlpha(float alpha) {
+ try {
+ nSetAlpha(getNativeDisplayList(), alpha);
+ } 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);
+ } catch (IllegalStateException e) {
+ // invalid DisplayList okay: we'll set current values the next time we render to it
+ }
+ }
+
+ @Override
+ public void setTranslationY(float translationY) {
+ try {
+ nSetTranslationY(getNativeDisplayList(), translationY);
+ } catch (IllegalStateException e) {
+ // invalid DisplayList okay: we'll set current values the next time we render to it
+ }
+ }
+
+ @Override
+ public void setRotation(float rotation) {
+ try {
+ nSetRotation(getNativeDisplayList(), rotation);
+ } catch (IllegalStateException e) {
+ // invalid DisplayList okay: we'll set current values the next time we render to it
+ }
+ }
+
+ @Override
+ public void setRotationX(float rotationX) {
+ try {
+ nSetRotationX(getNativeDisplayList(), rotationX);
+ } catch (IllegalStateException e) {
+ // invalid DisplayList okay: we'll set current values the next time we render to it
+ }
+ }
+
+ @Override
+ public void setRotationY(float rotationY) {
+ try {
+ nSetRotationY(getNativeDisplayList(), rotationY);
+ } catch (IllegalStateException e) {
+ // invalid DisplayList okay: we'll set current values the next time we render to it
+ }
+ }
+
+ @Override
+ public void setScaleX(float scaleX) {
+ try {
+ nSetScaleX(getNativeDisplayList(), scaleX);
+ } catch (IllegalStateException e) {
+ // invalid DisplayList okay: we'll set current values the next time we render to it
+ }
+ }
+
+ @Override
+ public void setScaleY(float scaleY) {
+ try {
+ nSetScaleY(getNativeDisplayList(), scaleY);
+ } catch (IllegalStateException e) {
+ // invalid DisplayList okay: we'll set current values the next time we render to it
+ }
+ }
+
+ @Override
+ public void setTransformationInfo(float alpha, float translationX, float translationY,
+ float rotation, float rotationX, float rotationY, float scaleX, float scaleY) {
+ try {
+ nSetTransformationInfo(getNativeDisplayList(), alpha, translationX, translationY,
+ rotation, rotationX, rotationY, scaleX, scaleY);
+ } catch (IllegalStateException e) {
+ // invalid DisplayList okay: we'll set current values the next time we render to it
+ }
+ }
+
+ @Override
+ public void setPivotX(float pivotX) {
+ try {
+ nSetPivotX(getNativeDisplayList(), pivotX);
+ } catch (IllegalStateException e) {
+ // invalid DisplayList okay: we'll set current values the next time we render to it
+ }
+ }
+
+ @Override
+ public void setPivotY(float pivotY) {
+ try {
+ nSetPivotY(getNativeDisplayList(), pivotY);
+ } catch (IllegalStateException e) {
+ // invalid DisplayList okay: we'll set current values the next time we render to it
+ }
+ }
+
+ @Override
+ public void setCameraDistance(float distance) {
+ try {
+ nSetCameraDistance(getNativeDisplayList(), distance);
+ } catch (IllegalStateException e) {
+ // invalid DisplayList okay: we'll set current values the next time we render to it
+ }
+ }
+
+ @Override
+ public void setLeft(int left) {
+ try {
+ nSetLeft(getNativeDisplayList(), left);
+ } catch (IllegalStateException e) {
+ // invalid DisplayList okay: we'll set current values the next time we render to it
+ }
+ }
+
+ @Override
+ public void setTop(int top) {
+ try {
+ nSetTop(getNativeDisplayList(), top);
+ } catch (IllegalStateException e) {
+ // invalid DisplayList okay: we'll set current values the next time we render to it
+ }
+ }
+
+ @Override
+ public void setRight(int right) {
+ try {
+ nSetRight(getNativeDisplayList(), right);
+ } catch (IllegalStateException e) {
+ // invalid DisplayList okay: we'll set current values the next time we render to it
+ }
+ }
+
+ @Override
+ public void setBottom(int bottom) {
+ try {
+ nSetBottom(getNativeDisplayList(), bottom);
+ } catch (IllegalStateException e) {
+ // invalid DisplayList okay: we'll set current values the next time we render to it
+ }
+ }
+
+ @Override
+ public void setLeftTop(int left, int top) {
+ try {
+ nSetLeftTop(getNativeDisplayList(), left, top);
+ } catch (IllegalStateException e) {
+ // invalid DisplayList okay: we'll set current values the next time we render to it
+ }
+ }
+
+ @Override
+ public void setLeftTopRightBottom(int left, int top, int right, int bottom) {
+ try {
+ nSetLeftTopRightBottom(getNativeDisplayList(), left, top, right, bottom);
+ } catch (IllegalStateException e) {
+ // invalid DisplayList okay: we'll set current values the next time we render to it
+ }
+ }
+
+ @Override
+ public void offsetLeftRight(int offset) {
+ try {
+ nOffsetLeftRight(getNativeDisplayList(), offset);
+ } catch (IllegalStateException e) {
+ // invalid DisplayList okay: we'll set current values the next time we render to it
+ }
+ }
+
+ @Override
+ public void offsetTopBottom(int offset) {
+ try {
+ nOffsetTopBottom(getNativeDisplayList(), offset);
+ } catch (IllegalStateException e) {
+ // invalid DisplayList okay: we'll set current values the next time we render to it
+ }
+ }
+
+ private static native void nOffsetTopBottom(int displayList, int offset);
+ private static native void nOffsetLeftRight(int displayList, int offset);
+ private static native void nSetLeftTopRightBottom(int displayList, int left, int top,
+ int right, int bottom);
+ private static native void nSetLeftTop(int displayList, int left, int top);
+ private static native void nSetBottom(int displayList, int bottom);
+ private static native void nSetRight(int displayList, int right);
+ private static native void nSetTop(int displayList, int top);
+ private static native void nSetLeft(int displayList, int left);
+ private static native void nSetCameraDistance(int displayList, float distance);
+ private static native void nSetPivotY(int displayList, float pivotY);
+ private static native void nSetPivotX(int displayList, float pivotX);
+ private static native void nSetCaching(int displayList, boolean caching);
+ 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 nSetTranslationX(int displayList, float translationX);
+ private static native void nSetTranslationY(int displayList, float translationY);
+ private static native void nSetRotation(int displayList, float rotation);
+ private static native void nSetRotationX(int displayList, float rotationX);
+ private static native void nSetRotationY(int displayList, float rotationY);
+ private static native void nSetScaleX(int displayList, float scaleX);
+ private static native void nSetScaleY(int displayList, float scaleY);
+ private static native void nSetTransformationInfo(int displayList, float alpha,
+ float translationX, float translationY, float rotation, float rotationX,
+ float rotationY, float scaleX, float scaleY);
+
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Finalization
+ ///////////////////////////////////////////////////////////////////////////
+
private static class DisplayListFinalizer {
final int mNativeDisplayList;
diff --git a/core/java/android/view/HardwareLayer.java b/core/java/android/view/HardwareLayer.java
index a97167b..e73f7bf 100644
--- a/core/java/android/view/HardwareLayer.java
+++ b/core/java/android/view/HardwareLayer.java
@@ -36,6 +36,7 @@ abstract class HardwareLayer {
int mWidth;
int mHeight;
+ DisplayList mDisplayList;
boolean mOpaque;
@@ -79,6 +80,24 @@ abstract class HardwareLayer {
}
/**
+ * Returns the DisplayList for the layer.
+ *
+ * @return The DisplayList of the hardware layer
+ */
+ DisplayList getDisplayList() {
+ return mDisplayList;
+ }
+
+ /**
+ * Sets the DisplayList for the layer.
+ *
+ * @param displayList The new DisplayList for this layer
+ */
+ void setDisplayList(DisplayList displayList) {
+ mDisplayList = displayList;
+ }
+
+ /**
* Returns whether or not this layer is opaque.
*
* @return True if the layer is opaque, false otherwise
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 679a65a..bf48ff2 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -1498,6 +1498,14 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
static final ThreadLocal<Rect> sThreadLocal = new ThreadLocal<Rect>();
/**
+ * Temporary flag, used to enable processing of View properties in the native DisplayList
+ * object instead of during draw(). Soon to be enabled by default for hardware-accelerated
+ * apps.
+ * @hide
+ */
+ protected static final boolean USE_DISPLAY_LIST_PROPERTIES = false;
+
+ /**
* Map used to store views' tags.
*/
private SparseArray<Object> mKeyedTags;
@@ -7284,6 +7292,24 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
}
/**
+ * Gets the distance along the Z axis from the camera to this view.
+ *
+ * @see #setCameraDistance(float)
+ *
+ * @return The distance along the Z axis.
+ */
+ public float getCameraDistance() {
+ ensureTransformationInfo();
+ final float dpi = mResources.getDisplayMetrics().densityDpi;
+ final TransformationInfo info = mTransformationInfo;
+ if (info.mCamera == null) {
+ info.mCamera = new Camera();
+ info.matrix3D = new Matrix();
+ }
+ return -(info.mCamera.getLocationZ() * dpi);
+ }
+
+ /**
* <p>Sets the distance along the Z axis (orthogonal to the X/Y plane on which
* views are drawn) from the camera to this view. The camera's distance
* affects 3D transformations, for instance rotations around the X and Y
@@ -7338,6 +7364,9 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
info.mMatrixDirty = true;
invalidate(false);
+ if (USE_DISPLAY_LIST_PROPERTIES && mDisplayList != null) {
+ mDisplayList.setCameraDistance(distance);
+ }
}
/**
@@ -7379,6 +7408,9 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
info.mMatrixDirty = true;
mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
invalidate(false);
+ if (USE_DISPLAY_LIST_PROPERTIES && mDisplayList != null) {
+ mDisplayList.setRotation(rotation);
+ }
}
}
@@ -7426,6 +7458,9 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
info.mMatrixDirty = true;
mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
invalidate(false);
+ if (USE_DISPLAY_LIST_PROPERTIES && mDisplayList != null) {
+ mDisplayList.setRotationY(rotationY);
+ }
}
}
@@ -7473,6 +7508,9 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
info.mMatrixDirty = true;
mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
invalidate(false);
+ if (USE_DISPLAY_LIST_PROPERTIES && mDisplayList != null) {
+ mDisplayList.setRotationX(rotationX);
+ }
}
}
@@ -7512,6 +7550,9 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
info.mMatrixDirty = true;
mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
invalidate(false);
+ if (USE_DISPLAY_LIST_PROPERTIES && mDisplayList != null) {
+ mDisplayList.setScaleX(scaleX);
+ }
}
}
@@ -7551,6 +7592,9 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
info.mMatrixDirty = true;
mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
invalidate(false);
+ if (USE_DISPLAY_LIST_PROPERTIES && mDisplayList != null) {
+ mDisplayList.setScaleY(scaleY);
+ }
}
}
@@ -7596,6 +7640,9 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
info.mMatrixDirty = true;
mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
invalidate(false);
+ if (USE_DISPLAY_LIST_PROPERTIES && mDisplayList != null) {
+ mDisplayList.setPivotX(pivotX);
+ }
}
}
@@ -7640,6 +7687,9 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
info.mMatrixDirty = true;
mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
invalidate(false);
+ if (USE_DISPLAY_LIST_PROPERTIES && mDisplayList != null) {
+ mDisplayList.setPivotY(pivotY);
+ }
}
}
@@ -7686,6 +7736,9 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
} else {
mPrivateFlags &= ~ALPHA_SET;
invalidate(false);
+ if (USE_DISPLAY_LIST_PROPERTIES && mDisplayList != null) {
+ mDisplayList.setAlpha(alpha);
+ }
}
}
}
@@ -7710,6 +7763,9 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
return true;
} else {
mPrivateFlags &= ~ALPHA_SET;
+ if (USE_DISPLAY_LIST_PROPERTIES && mDisplayList != null) {
+ mDisplayList.setAlpha(alpha);
+ }
}
}
return false;
@@ -7759,6 +7815,9 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
int oldHeight = mBottom - mTop;
mTop = top;
+ if (USE_DISPLAY_LIST_PROPERTIES && mDisplayList != null) {
+ mDisplayList.setTop(mTop);
+ }
onSizeChanged(width, mBottom - mTop, width, oldHeight);
@@ -7825,6 +7884,9 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
int oldHeight = mBottom - mTop;
mBottom = bottom;
+ if (USE_DISPLAY_LIST_PROPERTIES && mDisplayList != null) {
+ mDisplayList.setBottom(mBottom);
+ }
onSizeChanged(width, mBottom - mTop, width, oldHeight);
@@ -7885,6 +7947,9 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
int height = mBottom - mTop;
mLeft = left;
+ if (USE_DISPLAY_LIST_PROPERTIES && mDisplayList != null) {
+ mDisplayList.setLeft(left);
+ }
onSizeChanged(mRight - mLeft, height, oldWidth, height);
@@ -7898,6 +7963,9 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
}
mBackgroundSizeChanged = true;
invalidateParentIfNeeded();
+ if (USE_DISPLAY_LIST_PROPERTIES) {
+
+ }
}
}
@@ -7942,6 +8010,9 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
int height = mBottom - mTop;
mRight = right;
+ if (USE_DISPLAY_LIST_PROPERTIES && mDisplayList != null) {
+ mDisplayList.setRight(mRight);
+ }
onSizeChanged(mRight - mLeft, height, oldWidth, height);
@@ -8038,6 +8109,9 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
info.mMatrixDirty = true;
mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
invalidate(false);
+ if (USE_DISPLAY_LIST_PROPERTIES && mDisplayList != null) {
+ mDisplayList.setTranslationX(translationX);
+ }
}
}
@@ -8075,6 +8149,9 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
info.mMatrixDirty = true;
mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
invalidate(false);
+ if (USE_DISPLAY_LIST_PROPERTIES && mDisplayList != null) {
+ mDisplayList.setTranslationY(translationY);
+ }
}
}
@@ -8207,6 +8284,9 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
mTop += offset;
mBottom += offset;
+ if (USE_DISPLAY_LIST_PROPERTIES && mDisplayList != null) {
+ mDisplayList.offsetTopBottom(offset);
+ }
if (!matrixIsIdentity) {
mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
@@ -8248,6 +8328,9 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
mLeft += offset;
mRight += offset;
+ if (USE_DISPLAY_LIST_PROPERTIES && mDisplayList != null) {
+ mDisplayList.offsetLeftRight(offset);
+ }
if (!matrixIsIdentity) {
mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
@@ -10384,7 +10467,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
return null;
}
- mHardwareLayer.redraw(getDisplayList(), mLocalDirtyRect);
+ mHardwareLayer.redraw(getHardwareLayerDisplayList(mHardwareLayer), mLocalDirtyRect);
mLocalDirtyRect.setEmpty();
}
@@ -10536,78 +10619,138 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
}
/**
- * <p>Returns a display list that can be used to draw this view again
- * without executing its draw method.</p>
+ * Returns a DisplayList. If the incoming displayList is null, one will be created.
+ * Otherwise, the same display list will be returned (after having been rendered into
+ * along the way, depending on the invalidation state of the view).
*
- * @return A DisplayList ready to replay, or null if caching is not enabled.
- *
- * @hide
+ * @param displayList The previous version of this displayList, could be null.
+ * @param isLayer Whether the requester of the display list is a layer. If so,
+ * the view will avoid creating a layer inside the resulting display list.
+ * @return A new or reused DisplayList object.
*/
- public DisplayList getDisplayList() {
+ private DisplayList getDisplayList(DisplayList displayList, boolean isLayer) {
if (!canHaveDisplayList()) {
return null;
}
if (((mPrivateFlags & DRAWING_CACHE_VALID) == 0 ||
- mDisplayList == null || !mDisplayList.isValid() ||
- mRecreateDisplayList)) {
+ displayList == null || !displayList.isValid() ||
+ (!isLayer && mRecreateDisplayList))) {
// Don't need to recreate the display list, just need to tell our
// children to restore/recreate theirs
- if (mDisplayList != null && mDisplayList.isValid() &&
- !mRecreateDisplayList) {
+ if (displayList != null && displayList.isValid() &&
+ !isLayer && !mRecreateDisplayList) {
mPrivateFlags |= DRAWN | DRAWING_CACHE_VALID;
mPrivateFlags &= ~DIRTY_MASK;
dispatchGetDisplayList();
- return mDisplayList;
+ return displayList;
}
- // If we got here, we're recreating it. Mark it as such to ensure that
- // we copy in child display lists into ours in drawChild()
- mRecreateDisplayList = true;
- if (mDisplayList == null) {
+ if (!isLayer) {
+ // If we got here, we're recreating it. Mark it as such to ensure that
+ // we copy in child display lists into ours in drawChild()
+ mRecreateDisplayList = true;
+ }
+ if (displayList == null) {
final String name = getClass().getSimpleName();
- mDisplayList = mAttachInfo.mHardwareRenderer.createDisplayList(name);
+ displayList = mAttachInfo.mHardwareRenderer.createDisplayList(name);
// If we're creating a new display list, make sure our parent gets invalidated
// since they will need to recreate their display list to account for this
// new child display list.
invalidateParentCaches();
}
- final HardwareCanvas canvas = mDisplayList.start();
+ boolean caching = false;
+ final HardwareCanvas canvas = displayList.start();
int restoreCount = 0;
- try {
- int width = mRight - mLeft;
- int height = mBottom - mTop;
+ int width = mRight - mLeft;
+ int height = mBottom - mTop;
+ try {
canvas.setViewport(width, height);
// The dirty rect should always be null for a display list
canvas.onPreDraw(null);
+ int layerType = (
+ !(mParent instanceof ViewGroup) || ((ViewGroup)mParent).mDrawLayers) ?
+ getLayerType() : LAYER_TYPE_NONE;
+ if (!isLayer && layerType == LAYER_TYPE_HARDWARE && USE_DISPLAY_LIST_PROPERTIES) {
+ final HardwareLayer layer = getHardwareLayer();
+ if (layer != null && layer.isValid()) {
+ canvas.drawHardwareLayer(layer, 0, 0, mLayerPaint);
+ } else {
+ canvas.saveLayer(0, 0,
+ mRight - mLeft, mBottom - mTop, mLayerPaint,
+ Canvas.HAS_ALPHA_LAYER_SAVE_FLAG | Canvas.CLIP_TO_LAYER_SAVE_FLAG);
+ }
+ caching = true;
+ } else {
- computeScroll();
+ computeScroll();
- restoreCount = canvas.save();
- canvas.translate(-mScrollX, -mScrollY);
- mPrivateFlags |= DRAWN | DRAWING_CACHE_VALID;
- mPrivateFlags &= ~DIRTY_MASK;
+ if (!USE_DISPLAY_LIST_PROPERTIES) {
+ restoreCount = canvas.save();
+ }
+ canvas.translate(-mScrollX, -mScrollY);
+ if (!isLayer) {
+ mPrivateFlags |= DRAWN | DRAWING_CACHE_VALID;
+ mPrivateFlags &= ~DIRTY_MASK;
+ }
- // Fast path for layouts with no backgrounds
- if ((mPrivateFlags & SKIP_DRAW) == SKIP_DRAW) {
- dispatchDraw(canvas);
- } else {
- draw(canvas);
+ // Fast path for layouts with no backgrounds
+ if ((mPrivateFlags & SKIP_DRAW) == SKIP_DRAW) {
+ dispatchDraw(canvas);
+ } else {
+ draw(canvas);
+ }
}
} finally {
- canvas.restoreToCount(restoreCount);
+ if (USE_DISPLAY_LIST_PROPERTIES) {
+ canvas.restoreToCount(restoreCount);
+ }
canvas.onPostDraw();
- mDisplayList.end();
+ displayList.end();
+ if (USE_DISPLAY_LIST_PROPERTIES) {
+ displayList.setCaching(caching);
+ }
+ if (isLayer && USE_DISPLAY_LIST_PROPERTIES) {
+ displayList.setLeftTopRightBottom(0, 0, width, height);
+ } else {
+ setDisplayListProperties(displayList);
+ }
}
- } else {
+ } else if (!isLayer) {
mPrivateFlags |= DRAWN | DRAWING_CACHE_VALID;
mPrivateFlags &= ~DIRTY_MASK;
}
+ return displayList;
+ }
+
+ /**
+ * Get the DisplayList for the HardwareLayer
+ *
+ * @param layer The HardwareLayer whose DisplayList we want
+ * @return A DisplayList fopr the specified HardwareLayer
+ */
+ private DisplayList getHardwareLayerDisplayList(HardwareLayer layer) {
+ DisplayList displayList = getDisplayList(layer.getDisplayList(), true);
+ layer.setDisplayList(displayList);
+ return displayList;
+ }
+
+
+ /**
+ * <p>Returns a display list that can be used to draw this view again
+ * without executing its draw method.</p>
+ *
+ * @return A DisplayList ready to replay, or null if caching is not enabled.
+ *
+ * @hide
+ */
+ public DisplayList getDisplayList() {
+ mDisplayList = getDisplayList(mDisplayList, false);
return mDisplayList;
}
@@ -11152,19 +11295,57 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
return more;
}
+ void setDisplayListProperties() {
+ setDisplayListProperties(mDisplayList);
+ }
+
+ /**
+ * This method is called by getDisplayList() when a display list is created or re-rendered.
+ * It sets or resets the current value of all properties on that display list (resetting is
+ * necessary when a display list is being re-created, because we need to make sure that
+ * previously-set transform values
+ */
+ void setDisplayListProperties(DisplayList displayList) {
+ if (USE_DISPLAY_LIST_PROPERTIES && displayList != null) {
+ displayList.setLeftTopRightBottom(mLeft, mTop, mRight, mBottom);
+ if (mParent instanceof ViewGroup) {
+ displayList.setClipChildren(
+ (((ViewGroup)mParent).mGroupFlags & ViewGroup.FLAG_CLIP_CHILDREN) != 0);
+ }
+ if (mAttachInfo != null && mAttachInfo.mScalingRequired &&
+ mAttachInfo.mApplicationScale != 1.0f) {
+ displayList.setApplicationScale(1f / mAttachInfo.mApplicationScale);
+ }
+ if (mTransformationInfo != null) {
+ displayList.setTransformationInfo(mTransformationInfo.mAlpha,
+ mTransformationInfo.mTranslationX, mTransformationInfo.mTranslationY,
+ mTransformationInfo.mRotation, mTransformationInfo.mRotationX,
+ mTransformationInfo.mRotationY, mTransformationInfo.mScaleX,
+ mTransformationInfo.mScaleY);
+ displayList.setCameraDistance(getCameraDistance());
+ if ((mPrivateFlags & PIVOT_EXPLICITLY_SET) == PIVOT_EXPLICITLY_SET) {
+ displayList.setPivotX(getPivotX());
+ displayList.setPivotY(getPivotY());
+ }
+ }
+ }
+ }
+
/**
* This method is called by ViewGroup.drawChild() to have each child view draw itself.
* This draw() method is an implementation detail and is not intended to be overridden or
* to be called from anywhere else other than ViewGroup.drawChild().
*/
boolean draw(Canvas canvas, ViewGroup parent, long drawingTime) {
+ boolean useDisplayListProperties = USE_DISPLAY_LIST_PROPERTIES && mAttachInfo != null &&
+ mAttachInfo.mHardwareAccelerated;
boolean more = false;
final boolean childHasIdentityMatrix = hasIdentityMatrix();
final int flags = parent.mGroupFlags;
- if ((flags & parent.FLAG_CLEAR_TRANSFORMATION) == parent.FLAG_CLEAR_TRANSFORMATION) {
+ if ((flags & ViewGroup.FLAG_CLEAR_TRANSFORMATION) == ViewGroup.FLAG_CLEAR_TRANSFORMATION) {
parent.mChildTransformation.clear();
- parent.mGroupFlags &= ~parent.FLAG_CLEAR_TRANSFORMATION;
+ parent.mGroupFlags &= ~ViewGroup.FLAG_CLEAR_TRANSFORMATION;
}
Transformation transformToApply = null;
@@ -11175,8 +11356,8 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
int layerType = parent.mDrawLayers ? getLayerType() : LAYER_TYPE_NONE;
final boolean hardwareAccelerated = canvas.isHardwareAccelerated();
- if ((flags & parent.FLAG_CHILDREN_DRAWN_WITH_CACHE) == parent.FLAG_CHILDREN_DRAWN_WITH_CACHE ||
- (flags & parent.FLAG_ALWAYS_DRAWN_WITH_CACHE) == parent.FLAG_ALWAYS_DRAWN_WITH_CACHE) {
+ if ((flags & ViewGroup.FLAG_CHILDREN_DRAWN_WITH_CACHE) != 0 ||
+ (flags & ViewGroup.FLAG_ALWAYS_DRAWN_WITH_CACHE) != 0) {
caching = true;
if (mAttachInfo != null) scalingRequired = mAttachInfo.mScalingRequired;
} else {
@@ -11188,8 +11369,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
more = drawAnimation(parent, drawingTime, a, scalingRequired);
concatMatrix = a.willChangeTransformationMatrix();
transformToApply = parent.mChildTransformation;
- } else if ((flags & parent.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) ==
- parent.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) {
+ } else if ((flags & ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
final boolean hasTransform =
parent.getChildStaticTransformation(this, parent.mChildTransformation);
if (hasTransform) {
@@ -11239,6 +11419,11 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
buildDrawingCache(true);
cache = getDrawingCache(true);
break;
+ case LAYER_TYPE_HARDWARE:
+ if (useDisplayListProperties) {
+ hasDisplayList = canHaveDisplayList();
+ }
+ break;
case LAYER_TYPE_NONE:
// Delay getting the display list until animation-driven alpha values are
// set up and possibly passed on to the view
@@ -11247,24 +11432,33 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
}
}
}
+ useDisplayListProperties &= hasDisplayList;
final boolean hasNoCache = cache == null || hasDisplayList;
final boolean offsetForScroll = cache == null && !hasDisplayList &&
layerType != LAYER_TYPE_HARDWARE;
- final int restoreTo = canvas.save();
+ int restoreTo = -1;
+ if (!useDisplayListProperties) {
+ restoreTo = canvas.save();
+ }
if (offsetForScroll) {
canvas.translate(mLeft - sx, mTop - sy);
} else {
- canvas.translate(mLeft, mTop);
+ if (!useDisplayListProperties) {
+ canvas.translate(mLeft, mTop);
+ }
if (scalingRequired) {
+ if (useDisplayListProperties) {
+ restoreTo = canvas.save();
+ }
// mAttachInfo cannot be null, otherwise scalingRequired == false
final float scale = 1.0f / mAttachInfo.mApplicationScale;
canvas.scale(scale, scale);
}
}
- float alpha = getAlpha();
+ float alpha = useDisplayListProperties ? 1 : getAlpha();
if (transformToApply != null || alpha < 1.0f || !hasIdentityMatrix()) {
if (transformToApply != null || !childHasIdentityMatrix) {
int transX = 0;
@@ -11279,20 +11473,22 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
if (concatMatrix) {
// Undo the scroll translation, apply the transformation matrix,
// then redo the scroll translate to get the correct result.
- canvas.translate(-transX, -transY);
- canvas.concat(transformToApply.getMatrix());
- canvas.translate(transX, transY);
- parent.mGroupFlags |= parent.FLAG_CLEAR_TRANSFORMATION;
+ if (!hasDisplayList) {
+ canvas.translate(-transX, -transY);
+ canvas.concat(transformToApply.getMatrix());
+ canvas.translate(transX, transY);
+ }
+ parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
}
float transformAlpha = transformToApply.getAlpha();
if (transformAlpha < 1.0f) {
alpha *= transformToApply.getAlpha();
- parent.mGroupFlags |= parent.FLAG_CLEAR_TRANSFORMATION;
+ parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
}
}
- if (!childHasIdentityMatrix) {
+ if (!childHasIdentityMatrix && !useDisplayListProperties) {
canvas.translate(-transX, -transY);
canvas.concat(getMatrix());
canvas.translate(transX, transY);
@@ -11300,20 +11496,22 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
}
if (alpha < 1.0f) {
- parent.mGroupFlags |= parent.FLAG_CLEAR_TRANSFORMATION;
+ parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
if (hasNoCache) {
final int multipliedAlpha = (int) (255 * alpha);
if (!onSetAlpha(multipliedAlpha)) {
int layerFlags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG;
- if ((flags & parent.FLAG_CLIP_CHILDREN) == parent.FLAG_CLIP_CHILDREN ||
+ if ((flags & ViewGroup.FLAG_CLIP_CHILDREN) != 0 ||
layerType != LAYER_TYPE_NONE) {
layerFlags |= Canvas.CLIP_TO_LAYER_SAVE_FLAG;
}
if (layerType == LAYER_TYPE_NONE) {
- final int scrollX = hasDisplayList ? 0 : sx;
- final int scrollY = hasDisplayList ? 0 : sy;
- canvas.saveLayerAlpha(scrollX, scrollY, scrollX + mRight - mLeft,
- scrollY + mBottom - mTop, multipliedAlpha, layerFlags);
+ if (!useDisplayListProperties) {
+ final int scrollX = hasDisplayList ? 0 : sx;
+ final int scrollY = hasDisplayList ? 0 : sy;
+ canvas.saveLayerAlpha(scrollX, scrollY, scrollX + mRight - mLeft,
+ scrollY + mBottom - mTop, multipliedAlpha, layerFlags);
+ }
}
} else {
// Alpha is handled by the child directly, clobber the layer's alpha
@@ -11326,7 +11524,8 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
mPrivateFlags &= ~ALPHA_SET;
}
- if ((flags & parent.FLAG_CLIP_CHILDREN) == parent.FLAG_CLIP_CHILDREN) {
+ if ((flags & ViewGroup.FLAG_CLIP_CHILDREN) == ViewGroup.FLAG_CLIP_CHILDREN &&
+ !useDisplayListProperties) {
if (offsetForScroll) {
canvas.clipRect(sx, sy, sx + (mRight - mLeft), sy + (mBottom - mTop));
} else {
@@ -11351,7 +11550,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
if (hasNoCache) {
boolean layerRendered = false;
- if (layerType == LAYER_TYPE_HARDWARE) {
+ if (layerType == LAYER_TYPE_HARDWARE && !useDisplayListProperties) {
final HardwareLayer layer = getHardwareLayer();
if (layer != null && layer.isValid()) {
mLayerPaint.setAlpha((int) (alpha * 255));
@@ -11397,11 +11596,10 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
}
if (alpha < 1.0f) {
cachePaint.setAlpha((int) (alpha * 255));
- parent.mGroupFlags |= parent.FLAG_ALPHA_LOWER_THAN_ONE;
- } else if ((flags & parent.FLAG_ALPHA_LOWER_THAN_ONE) ==
- parent.FLAG_ALPHA_LOWER_THAN_ONE) {
+ parent.mGroupFlags |= ViewGroup.FLAG_ALPHA_LOWER_THAN_ONE;
+ } else if ((flags & ViewGroup.FLAG_ALPHA_LOWER_THAN_ONE) != 0) {
cachePaint.setAlpha(255);
- parent.mGroupFlags &= ~parent.FLAG_ALPHA_LOWER_THAN_ONE;
+ parent.mGroupFlags &= ~ViewGroup.FLAG_ALPHA_LOWER_THAN_ONE;
}
} else {
cachePaint = mLayerPaint;
@@ -11410,7 +11608,9 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
canvas.drawBitmap(cache, 0.0f, 0.0f, cachePaint);
}
- canvas.restoreToCount(restoreTo);
+ if (restoreTo >= 0) {
+ canvas.restoreToCount(restoreTo);
+ }
if (a != null && !more) {
if (!hardwareAccelerated && !a.getFillAfter()) {
@@ -11868,6 +12068,9 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
mTop = top;
mRight = right;
mBottom = bottom;
+ if (USE_DISPLAY_LIST_PROPERTIES && mDisplayList != null) {
+ mDisplayList.setLeftTopRightBottom(mLeft, mTop, mRight, mBottom);
+ }
mPrivateFlags |= HAS_BOUNDS;
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index c9e0242..1993ce6 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -2736,7 +2736,18 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
* @attr ref android.R.styleable#ViewGroup_clipChildren
*/
public void setClipChildren(boolean clipChildren) {
- setBooleanFlag(FLAG_CLIP_CHILDREN, clipChildren);
+ boolean previousValue = (mGroupFlags & FLAG_CLIP_CHILDREN) == FLAG_CLIP_CHILDREN;
+ if (clipChildren != previousValue) {
+ setBooleanFlag(FLAG_CLIP_CHILDREN, clipChildren);
+ if (USE_DISPLAY_LIST_PROPERTIES) {
+ for (int i = 0; i < mChildrenCount; ++i) {
+ View child = getChildAt(i);
+ if (child.mDisplayList != null) {
+ child.mDisplayList.setClipChildren(clipChildren);
+ }
+ }
+ }
+ }
}
/**
@@ -3973,6 +3984,9 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
final View v = children[i];
v.mTop += offset;
v.mBottom += offset;
+ if (USE_DISPLAY_LIST_PROPERTIES && v.mDisplayList != null) {
+ v.mDisplayList.offsetTopBottom(offset);
+ }
}
}
diff --git a/core/java/android/view/ViewPropertyAnimator.java b/core/java/android/view/ViewPropertyAnimator.java
index 0fdcd0f..fe0e659 100644
--- a/core/java/android/view/ViewPropertyAnimator.java
+++ b/core/java/android/view/ViewPropertyAnimator.java
@@ -866,6 +866,8 @@ public class ViewPropertyAnimator {
info.mAlpha = value;
break;
}
+ // TODO: optimize to set only the properties that have changed
+ mView.setDisplayListProperties();
}
/**
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index b8db848..e535170 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -11703,8 +11703,10 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
firstLine, lastLine);
if (mTextDisplayList == null || !mTextDisplayList.isValid()) {
+ boolean displayListCreated = false;
if (mTextDisplayList == null) {
mTextDisplayList = getHardwareRenderer().createDisplayList("Text");
+ displayListCreated = true;
}
final HardwareCanvas hardwareCanvas = mTextDisplayList.start();
@@ -11719,6 +11721,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
} finally {
hardwareCanvas.onPostDraw();
mTextDisplayList.end();
+ if (displayListCreated && USE_DISPLAY_LIST_PROPERTIES) {
+ mTextDisplayList.setLeftTopRightBottom(mLeft, mTop, mRight, mBottom);
+ }
}
}
canvas.translate(mScrollX, mScrollY);
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index 543e32d..92b07b3 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -53,6 +53,7 @@ LOCAL_SRC_FILES:= \
android_view_KeyEvent.cpp \
android_view_KeyCharacterMap.cpp \
android_view_HardwareRenderer.cpp \
+ android_view_GLES20DisplayList.cpp \
android_view_GLES20Canvas.cpp \
android_view_MotionEvent.cpp \
android_view_PointerIcon.cpp \
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index a512679..92ff8da 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -117,6 +117,7 @@ extern int register_android_graphics_Xfermode(JNIEnv* env);
extern int register_android_graphics_PixelFormat(JNIEnv* env);
extern int register_android_view_Display(JNIEnv* env);
extern int register_android_view_DisplayEventReceiver(JNIEnv* env);
+extern int register_android_view_GLES20DisplayList(JNIEnv* env);
extern int register_android_view_GLES20Canvas(JNIEnv* env);
extern int register_android_view_HardwareRenderer(JNIEnv* env);
extern int register_android_view_Surface(JNIEnv* env);
@@ -1102,6 +1103,7 @@ static const RegJNIRec gRegJNI[] = {
REG_JNI(register_android_nio_utils),
REG_JNI(register_android_graphics_PixelFormat),
REG_JNI(register_android_graphics_Graphics),
+ REG_JNI(register_android_view_GLES20DisplayList),
REG_JNI(register_android_view_GLES20Canvas),
REG_JNI(register_android_view_HardwareRenderer),
REG_JNI(register_android_view_Surface),
diff --git a/core/jni/android/graphics/Camera.cpp b/core/jni/android/graphics/Camera.cpp
index 76d415a..5176d9a 100644
--- a/core/jni/android/graphics/Camera.cpp
+++ b/core/jni/android/graphics/Camera.cpp
@@ -57,6 +57,21 @@ static void Camera_setLocation(JNIEnv* env, jobject obj, jfloat x, jfloat y, jfl
v->setCameraLocation(SkFloatToScalar(x), SkFloatToScalar(y), SkFloatToScalar(z));
}
+static jfloat Camera_getLocationX(JNIEnv* env, jobject obj) {
+ Sk3DView* v = (Sk3DView*)env->GetIntField(obj, gNativeInstanceFieldID);
+ return SkScalarToFloat(v->getCameraLocationX());
+}
+
+static jfloat Camera_getLocationY(JNIEnv* env, jobject obj) {
+ Sk3DView* v = (Sk3DView*)env->GetIntField(obj, gNativeInstanceFieldID);
+ return SkScalarToFloat(v->getCameraLocationY());
+}
+
+static jfloat Camera_getLocationZ(JNIEnv* env, jobject obj) {
+ Sk3DView* v = (Sk3DView*)env->GetIntField(obj, gNativeInstanceFieldID);
+ return SkScalarToFloat(v->getCameraLocationZ());
+}
+
static void Camera_getMatrix(JNIEnv* env, jobject obj, int native_matrix) {
Sk3DView* v = (Sk3DView*)env->GetIntField(obj, gNativeInstanceFieldID);
v->getMatrix((SkMatrix*)native_matrix);
@@ -93,6 +108,9 @@ static JNINativeMethod gCameraMethods[] = {
{ "rotateZ", "(F)V", (void*)Camera_rotateZ },
{ "rotate", "(FFF)V", (void*)Camera_rotate },
{ "setLocation", "(FFF)V", (void*)Camera_setLocation },
+ { "getLocationX", "()F", (void*)Camera_getLocationX },
+ { "getLocationY", "()F", (void*)Camera_getLocationY },
+ { "getLocationZ", "()F", (void*)Camera_getLocationZ },
{ "nativeGetMatrix", "(I)V", (void*)Camera_getMatrix },
{ "nativeApplyToCanvas", "(I)V", (void*)Camera_applyToCanvas },
{ "dotWithNormal", "(FFF)F", (void*)Camera_dotWithNormal }
diff --git a/core/jni/android_view_GLES20DisplayList.cpp b/core/jni/android_view_GLES20DisplayList.cpp
new file mode 100644
index 0000000..407c196
--- /dev/null
+++ b/core/jni/android_view_GLES20DisplayList.cpp
@@ -0,0 +1,227 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "OpenGLRenderer"
+
+#include <EGL/egl.h>
+
+#include "jni.h"
+#include "GraphicsJNI.h"
+#include <nativehelper/JNIHelp.h>
+#include <android_runtime/AndroidRuntime.h>
+
+#include <DisplayListRenderer.h>
+
+namespace android {
+
+using namespace uirenderer;
+
+/**
+ * Note: OpenGLRenderer JNI layer is generated and compiled only on supported
+ * devices. This means all the logic must be compiled only when the
+ * preprocessor variable USE_OPENGL_RENDERER is defined.
+ */
+#ifdef USE_OPENGL_RENDERER
+
+// ----------------------------------------------------------------------------
+// DisplayList view properties
+// ----------------------------------------------------------------------------
+
+static void android_view_GLES20DisplayList_setCaching(JNIEnv* env,
+ jobject clazz, DisplayList* displayList, jboolean caching) {
+ displayList->setCaching(caching);
+}
+
+static void android_view_GLES20DisplayList_setApplicationScale(JNIEnv* env,
+ jobject clazz, DisplayList* displayList, float scale) {
+ displayList->setApplicationScale(scale);
+}
+
+static void android_view_GLES20DisplayList_setClipChildren(JNIEnv* env,
+ jobject clazz, DisplayList* displayList, jboolean clipChildren) {
+ displayList->setClipChildren(clipChildren);
+}
+
+static void android_view_GLES20DisplayList_setAlpha(JNIEnv* env,
+ jobject clazz, DisplayList* displayList, float alpha) {
+ displayList->setAlpha(alpha);
+}
+
+static void android_view_GLES20DisplayList_setTranslationX(JNIEnv* env,
+ jobject clazz, DisplayList* displayList, float tx) {
+ displayList->setTranslationX(tx);
+}
+
+static void android_view_GLES20DisplayList_setTranslationY(JNIEnv* env,
+ jobject clazz, DisplayList* displayList, float ty) {
+ displayList->setTranslationY(ty);
+}
+
+static void android_view_GLES20DisplayList_setRotation(JNIEnv* env,
+ jobject clazz, DisplayList* displayList, float rotation) {
+ displayList->setRotation(rotation);
+}
+
+static void android_view_GLES20DisplayList_setRotationX(JNIEnv* env,
+ jobject clazz, DisplayList* displayList, float rx) {
+ displayList->setRotationX(rx);
+}
+
+static void android_view_GLES20DisplayList_setRotationY(JNIEnv* env,
+ jobject clazz, DisplayList* displayList, float ry) {
+ displayList->setRotationY(ry);
+}
+
+static void android_view_GLES20DisplayList_setScaleX(JNIEnv* env,
+ jobject clazz, DisplayList* displayList, float sx) {
+ displayList->setScaleX(sx);
+}
+
+static void android_view_GLES20DisplayList_setScaleY(JNIEnv* env,
+ jobject clazz, DisplayList* displayList, float sy) {
+ displayList->setScaleY(sy);
+}
+
+static void android_view_GLES20DisplayList_setTransformationInfo(JNIEnv* env,
+ jobject clazz, DisplayList* displayList, float alpha,
+ float translationX, float translationY, float rotation, float rotationX, float rotationY,
+ float scaleX, float scaleY) {
+ displayList->setAlpha(alpha);
+ displayList->setTranslationX(translationX);
+ displayList->setTranslationY(translationY);
+ displayList->setRotation(rotation);
+ displayList->setRotationX(rotationX);
+ displayList->setRotationY(rotationY);
+ displayList->setScaleX(scaleX);
+ displayList->setScaleY(scaleY);
+}
+
+static void android_view_GLES20DisplayList_setPivotX(JNIEnv* env,
+ jobject clazz, DisplayList* displayList, float px) {
+ displayList->setPivotX(px);
+}
+
+static void android_view_GLES20DisplayList_setPivotY(JNIEnv* env,
+ jobject clazz, DisplayList* displayList, float py) {
+ displayList->setPivotY(py);
+}
+
+static void android_view_GLES20DisplayList_setCameraDistance(JNIEnv* env,
+ jobject clazz, DisplayList* displayList, float distance) {
+ displayList->setCameraDistance(distance);
+}
+
+static void android_view_GLES20DisplayList_setLeft(JNIEnv* env,
+ jobject clazz, DisplayList* displayList, int left) {
+ displayList->setLeft(left);
+}
+
+static void android_view_GLES20DisplayList_setTop(JNIEnv* env,
+ jobject clazz, DisplayList* displayList, int top) {
+ displayList->setTop(top);
+}
+
+static void android_view_GLES20DisplayList_setRight(JNIEnv* env,
+ jobject clazz, DisplayList* displayList, int right) {
+ displayList->setRight(right);
+}
+
+static void android_view_GLES20DisplayList_setBottom(JNIEnv* env,
+ jobject clazz, DisplayList* displayList, int bottom) {
+ displayList->setBottom(bottom);
+}
+
+static void android_view_GLES20DisplayList_setLeftTop(JNIEnv* env,
+ jobject clazz, DisplayList* displayList, int left, int top) {
+ displayList->setLeftTop(left, top);
+}
+
+static void android_view_GLES20DisplayList_setLeftTopRightBottom(JNIEnv* env,
+ jobject clazz, DisplayList* displayList, int left, int top,
+ int right, int bottom) {
+ displayList->setLeftTopRightBottom(left, top, right, bottom);
+}
+
+static void android_view_GLES20DisplayList_offsetLeftRight(JNIEnv* env,
+ jobject clazz, DisplayList* displayList, int offset) {
+ displayList->offsetLeftRight(offset);
+}
+
+static void android_view_GLES20DisplayList_offsetTopBottom(JNIEnv* env,
+ jobject clazz, DisplayList* displayList, int offset) {
+ displayList->offsetTopBottom(offset);
+}
+
+#endif // USE_OPENGL_RENDERER
+
+// ----------------------------------------------------------------------------
+// JNI Glue
+// ----------------------------------------------------------------------------
+
+const char* const kClassPathName = "android/view/GLES20DisplayList";
+
+static JNINativeMethod gMethods[] = {
+#ifdef USE_OPENGL_RENDERER
+ { "nSetCaching", "(IZ)V", (void*) android_view_GLES20DisplayList_setCaching },
+ { "nSetApplicationScale", "(IF)V",
+ (void*) android_view_GLES20DisplayList_setApplicationScale },
+ { "nSetClipChildren", "(IZ)V", (void*) android_view_GLES20DisplayList_setClipChildren },
+ { "nSetAlpha", "(IF)V", (void*) android_view_GLES20DisplayList_setAlpha },
+ { "nSetTranslationX", "(IF)V", (void*) android_view_GLES20DisplayList_setTranslationX },
+ { "nSetTranslationY", "(IF)V", (void*) android_view_GLES20DisplayList_setTranslationY },
+ { "nSetRotation", "(IF)V", (void*) android_view_GLES20DisplayList_setRotation },
+ { "nSetRotationX", "(IF)V", (void*) android_view_GLES20DisplayList_setRotationX },
+ { "nSetRotationY", "(IF)V", (void*) android_view_GLES20DisplayList_setRotationY },
+ { "nSetScaleX", "(IF)V", (void*) android_view_GLES20DisplayList_setScaleX },
+ { "nSetScaleY", "(IF)V", (void*) android_view_GLES20DisplayList_setScaleY },
+ { "nSetTransformationInfo", "(IFFFFFFFF)V",
+ (void*) android_view_GLES20DisplayList_setTransformationInfo },
+ { "nSetPivotX", "(IF)V", (void*) android_view_GLES20DisplayList_setPivotX },
+ { "nSetPivotY", "(IF)V", (void*) android_view_GLES20DisplayList_setPivotY },
+ { "nSetCameraDistance", "(IF)V",
+ (void*) android_view_GLES20DisplayList_setCameraDistance },
+ { "nSetLeft", "(II)V", (void*) android_view_GLES20DisplayList_setLeft },
+ { "nSetTop", "(II)V", (void*) android_view_GLES20DisplayList_setTop },
+ { "nSetRight", "(II)V", (void*) android_view_GLES20DisplayList_setRight },
+ { "nSetBottom", "(II)V", (void*) android_view_GLES20DisplayList_setBottom },
+ { "nSetLeftTop", "(III)V", (void*) android_view_GLES20DisplayList_setLeftTop },
+ { "nSetLeftTopRightBottom", "(IIIII)V",
+ (void*) android_view_GLES20DisplayList_setLeftTopRightBottom },
+ { "nOffsetLeftRight", "(II)V", (void*) android_view_GLES20DisplayList_offsetLeftRight },
+ { "nOffsetTopBottom", "(II)V", (void*) android_view_GLES20DisplayList_offsetTopBottom },
+
+#endif
+};
+
+#ifdef USE_OPENGL_RENDERER
+ #define FIND_CLASS(var, className) \
+ var = env->FindClass(className); \
+ LOG_FATAL_IF(! var, "Unable to find class " className);
+
+ #define GET_METHOD_ID(var, clazz, methodName, methodDescriptor) \
+ var = env->GetMethodID(clazz, methodName, methodDescriptor); \
+ LOG_FATAL_IF(! var, "Unable to find method " methodName);
+#else
+ #define FIND_CLASS(var, className)
+ #define GET_METHOD_ID(var, clazz, methodName, methodDescriptor)
+#endif
+
+int register_android_view_GLES20DisplayList(JNIEnv* env) {
+ return AndroidRuntime::registerNativeMethods(env, kClassPathName, gMethods, NELEM(gMethods));
+}
+
+};
+