summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChet Haase <chet@google.com>2012-03-12 15:48:32 -0700
committerAndroid (Google) Code Review <android-gerrit@google.com>2012-03-12 15:48:32 -0700
commit81a0647c302edb4ed74d6d80d8f85c85a6c3fec4 (patch)
treeda6a3f7ce1cebe1c613f110d2f0421ca0d780ee3
parent035c20f5b4f31a2a4b592ff5004fe67fef0106d2 (diff)
parenta1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3 (diff)
downloadframeworks_base-81a0647c302edb4ed74d6d80d8f85c85a6c3fec4.zip
frameworks_base-81a0647c302edb4ed74d6d80d8f85c85a6c3fec4.tar.gz
frameworks_base-81a0647c302edb4ed74d6d80d8f85c85a6c3fec4.tar.bz2
Merge "Handle view properties at the native level"
-rw-r--r--api/current.txt4
-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
-rw-r--r--graphics/java/android/graphics/Camera.java21
-rw-r--r--libs/hwui/DisplayListRenderer.cpp345
-rw-r--r--libs/hwui/DisplayListRenderer.h272
-rw-r--r--libs/hwui/OpenGLRenderer.cpp20
16 files changed, 1606 insertions, 118 deletions
diff --git a/api/current.txt b/api/current.txt
index 1b04830..92c309c 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -8035,6 +8035,9 @@ package android.graphics {
ctor public Camera();
method public void applyToCanvas(android.graphics.Canvas);
method public float dotWithNormal(float, float, float);
+ method public float getLocationX();
+ method public float getLocationY();
+ method public float getLocationZ();
method public void getMatrix(android.graphics.Matrix);
method public void restore();
method public void rotate(float, float, float);
@@ -23196,6 +23199,7 @@ package android.view {
method public final int getBottom();
method protected float getBottomFadingEdgeStrength();
method protected int getBottomPaddingOffset();
+ method public float getCameraDistance();
method public java.lang.CharSequence getContentDescription();
method public final android.content.Context getContext();
method protected android.view.ContextMenu.ContextMenuInfo getContextMenuInfo();
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));
+}
+
+};
+
diff --git a/graphics/java/android/graphics/Camera.java b/graphics/java/android/graphics/Camera.java
index 7ef35a9..6f71a2b 100644
--- a/graphics/java/android/graphics/Camera.java
+++ b/graphics/java/android/graphics/Camera.java
@@ -100,6 +100,27 @@ public class Camera {
public native void rotate(float x, float y, float z);
/**
+ * Gets the x location of the camera.
+ *
+ * @see #setLocation(float, float, float)
+ */
+ public native float getLocationX();
+
+ /**
+ * Gets the y location of the camera.
+ *
+ * @see #setLocation(float, float, float)
+ */
+ public native float getLocationY();
+
+ /**
+ * Gets the z location of the camera.
+ *
+ * @see #setLocation(float, float, float)
+ */
+ public native float getLocationZ();
+
+ /**
* Sets the location of the camera. The default location is set at
* 0, 0, -8.
*
diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp
index 18d0a70..24f4f1c 100644
--- a/libs/hwui/DisplayListRenderer.cpp
+++ b/libs/hwui/DisplayListRenderer.cpp
@@ -20,13 +20,11 @@
#include "DisplayListLogBuffer.h"
#include "DisplayListRenderer.h"
#include "Caches.h"
-
-#include <utils/String8.h>
+#include "SkCamera.h"
namespace android {
namespace uirenderer {
-
///////////////////////////////////////////////////////////////////////////////
// Display list
///////////////////////////////////////////////////////////////////////////////
@@ -101,6 +99,37 @@ DisplayList::~DisplayList() {
clearResources();
}
+void DisplayList::initProperties() {
+ mLeft = 0;
+ mTop = 0;
+ mTop = 0;
+ mBottom = 0;
+ mApplicationScale = -1;
+ mClipChildren = true;
+ mAlpha = 1;
+ mMultipliedAlpha = 255;
+ mTranslationX = 0;
+ mTranslationY = 0;
+ mRotation = 0;
+ mRotationX = 0;
+ mRotationY= 0;
+ mScaleX = 1;
+ mScaleY = 1;
+ mPivotX = 0;
+ mPivotY = 0;
+ mMatrixDirty = false;
+ mMatrixFlags = 0;
+ mPrevWidth = -1;
+ mPrevHeight = -1;
+ mWidth = 0;
+ mHeight = 0;
+ mPivotExplicitlySet = false;
+ mTransformMatrix = NULL;
+ mTransformCamera = NULL;
+ mTransformMatrix3D = NULL;
+ mCaching = false;
+}
+
void DisplayList::destroyDisplayListDeferred(DisplayList* displayList) {
if (displayList) {
DISPLAY_LIST_LOGD("Deferring display list destruction");
@@ -111,6 +140,19 @@ void DisplayList::destroyDisplayListDeferred(DisplayList* displayList) {
void DisplayList::clearResources() {
sk_free((void*) mReader.base());
+ if (mTransformMatrix) {
+ delete mTransformMatrix;
+ mTransformMatrix = NULL;
+ }
+ if (mTransformCamera) {
+ delete mTransformCamera;
+ mTransformCamera = NULL;
+ }
+ if (mTransformMatrix3D) {
+ delete mTransformMatrix3D;
+ mTransformMatrix3D = NULL;
+ }
+
Caches& caches = Caches::getInstance();
for (size_t i = 0; i < mBitmapResources.size(); i++) {
@@ -159,6 +201,7 @@ void DisplayList::initFromDisplayListRenderer(const DisplayListRenderer& recorde
// re-using display list - clear out previous allocations
clearResources();
}
+ initProperties();
mSize = writer.size();
void* buffer = sk_malloc_throw(mSize);
@@ -230,6 +273,7 @@ void DisplayList::output(OpenGLRenderer& renderer, uint32_t level) {
int saveCount = renderer.getSaveCount() - 1;
+ outputViewProperties(renderer, (char*) indent);
mReader.rewind();
while (!mReader.eof()) {
@@ -238,7 +282,7 @@ void DisplayList::output(OpenGLRenderer& renderer, uint32_t level) {
int skip = mReader.readInt();
ALOGD("%sSkip %d", (char*) indent, skip);
op &= ~OP_MAY_BE_SKIPPED_MASK;
- }
+ }
switch (op) {
case DrawGLFunction: {
@@ -268,7 +312,7 @@ void DisplayList::output(OpenGLRenderer& renderer, uint32_t level) {
SkPaint* paint = getPaint(renderer);
int flags = getInt();
ALOGD("%s%s %.2f, %.2f, %.2f, %.2f, %p, 0x%x", (char*) indent,
- OP_NAMES[op], f1, f2, f3, f4, paint, flags);
+ OP_NAMES[op], f1, f2, f3, f4, paint, flags);
}
break;
case SaveLayerAlpha: {
@@ -279,7 +323,7 @@ void DisplayList::output(OpenGLRenderer& renderer, uint32_t level) {
int alpha = getInt();
int flags = getInt();
ALOGD("%s%s %.2f, %.2f, %.2f, %.2f, %d, 0x%x", (char*) indent,
- OP_NAMES[op], f1, f2, f3, f4, alpha, flags);
+ OP_NAMES[op], f1, f2, f3, f4, alpha, flags);
}
break;
case Translate: {
@@ -312,7 +356,10 @@ void DisplayList::output(OpenGLRenderer& renderer, uint32_t level) {
break;
case ConcatMatrix: {
SkMatrix* matrix = getMatrix();
- ALOGD("%s%s %p", (char*) indent, OP_NAMES[op], matrix);
+ ALOGD("%s%s new concat %p: [%f, %f, %f] [%f, %f, %f] [%f, %f, %f]",
+ (char*) indent, OP_NAMES[op], matrix, matrix->get(0), matrix->get(1),
+ matrix->get(2), matrix->get(3), matrix->get(4), matrix->get(5),
+ matrix->get(6), matrix->get(7), matrix->get(8));
}
break;
case ClipRect: {
@@ -322,7 +369,7 @@ void DisplayList::output(OpenGLRenderer& renderer, uint32_t level) {
float f4 = getFloat();
int regionOp = getInt();
ALOGD("%s%s %.2f, %.2f, %.2f, %.2f, %d", (char*) indent, OP_NAMES[op],
- f1, f2, f3, f4, regionOp);
+ f1, f2, f3, f4, regionOp);
}
break;
case DrawDisplayList: {
@@ -331,7 +378,7 @@ void DisplayList::output(OpenGLRenderer& renderer, uint32_t level) {
uint32_t height = getUInt();
int32_t flags = getInt();
ALOGD("%s%s %p, %dx%d, 0x%x %d", (char*) indent, OP_NAMES[op],
- displayList, width, height, flags, level + 1);
+ displayList, width, height, flags, level + 1);
renderer.outputDisplayList(displayList, level + 1);
}
break;
@@ -341,7 +388,7 @@ void DisplayList::output(OpenGLRenderer& renderer, uint32_t level) {
float y = getFloat();
SkPaint* paint = getPaint(renderer);
ALOGD("%s%s %p, %.2f, %.2f, %p", (char*) indent, OP_NAMES[op],
- layer, x, y, paint);
+ layer, x, y, paint);
}
break;
case DrawBitmap: {
@@ -350,7 +397,7 @@ void DisplayList::output(OpenGLRenderer& renderer, uint32_t level) {
float y = getFloat();
SkPaint* paint = getPaint(renderer);
ALOGD("%s%s %p, %.2f, %.2f, %p", (char*) indent, OP_NAMES[op],
- bitmap, x, y, paint);
+ bitmap, x, y, paint);
}
break;
case DrawBitmapMatrix: {
@@ -358,7 +405,7 @@ void DisplayList::output(OpenGLRenderer& renderer, uint32_t level) {
SkMatrix* matrix = getMatrix();
SkPaint* paint = getPaint(renderer);
ALOGD("%s%s %p, %p, %p", (char*) indent, OP_NAMES[op],
- bitmap, matrix, paint);
+ bitmap, matrix, paint);
}
break;
case DrawBitmapRect: {
@@ -373,7 +420,7 @@ void DisplayList::output(OpenGLRenderer& renderer, uint32_t level) {
float f8 = getFloat();
SkPaint* paint = getPaint(renderer);
ALOGD("%s%s %p, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %p",
- (char*) indent, OP_NAMES[op], bitmap, f1, f2, f3, f4, f5, f6, f7, f8, paint);
+ (char*) indent, OP_NAMES[op], bitmap, f1, f2, f3, f4, f5, f6, f7, f8, paint);
}
break;
case DrawBitmapMesh: {
@@ -422,7 +469,7 @@ void DisplayList::output(OpenGLRenderer& renderer, uint32_t level) {
float f4 = getFloat();
SkPaint* paint = getPaint(renderer);
ALOGD("%s%s %.2f, %.2f, %.2f, %.2f, %p", (char*) indent, OP_NAMES[op],
- f1, f2, f3, f4, paint);
+ f1, f2, f3, f4, paint);
}
break;
case DrawRoundRect: {
@@ -434,7 +481,7 @@ void DisplayList::output(OpenGLRenderer& renderer, uint32_t level) {
float f6 = getFloat();
SkPaint* paint = getPaint(renderer);
ALOGD("%s%s %.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %p",
- (char*) indent, OP_NAMES[op], f1, f2, f3, f4, f5, f6, paint);
+ (char*) indent, OP_NAMES[op], f1, f2, f3, f4, f5, f6, paint);
}
break;
case DrawCircle: {
@@ -443,7 +490,7 @@ void DisplayList::output(OpenGLRenderer& renderer, uint32_t level) {
float f3 = getFloat();
SkPaint* paint = getPaint(renderer);
ALOGD("%s%s %.2f, %.2f, %.2f, %p",
- (char*) indent, OP_NAMES[op], f1, f2, f3, paint);
+ (char*) indent, OP_NAMES[op], f1, f2, f3, paint);
}
break;
case DrawOval: {
@@ -453,7 +500,7 @@ void DisplayList::output(OpenGLRenderer& renderer, uint32_t level) {
float f4 = getFloat();
SkPaint* paint = getPaint(renderer);
ALOGD("%s%s %.2f, %.2f, %.2f, %.2f, %p",
- (char*) indent, OP_NAMES[op], f1, f2, f3, f4, paint);
+ (char*) indent, OP_NAMES[op], f1, f2, f3, f4, paint);
}
break;
case DrawArc: {
@@ -466,7 +513,7 @@ void DisplayList::output(OpenGLRenderer& renderer, uint32_t level) {
int i1 = getInt();
SkPaint* paint = getPaint(renderer);
ALOGD("%s%s %.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %d, %p",
- (char*) indent, OP_NAMES[op], f1, f2, f3, f4, f5, f6, i1, paint);
+ (char*) indent, OP_NAMES[op], f1, f2, f3, f4, f5, f6, i1, paint);
}
break;
case DrawPath: {
@@ -497,7 +544,7 @@ void DisplayList::output(OpenGLRenderer& renderer, uint32_t level) {
SkPaint* paint = getPaint(renderer);
float length = getFloat();
ALOGD("%s%s %s, %d, %d, %.2f, %.2f, %p, %.2f", (char*) indent, OP_NAMES[op],
- text.text(), text.length(), count, x, y, paint, length);
+ text.text(), text.length(), count, x, y, paint, length);
}
break;
case DrawTextOnPath: {
@@ -518,7 +565,7 @@ void DisplayList::output(OpenGLRenderer& renderer, uint32_t level) {
float* positions = getFloats(positionsCount);
SkPaint* paint = getPaint(renderer);
ALOGD("%s%s %s, %d, %d, %p", (char*) indent, OP_NAMES[op],
- text.text(), text.length(), count, paint);
+ text.text(), text.length(), count, paint);
}
case ResetShader: {
ALOGD("%s%s", (char*) indent, OP_NAMES[op]);
@@ -548,7 +595,7 @@ void DisplayList::output(OpenGLRenderer& renderer, uint32_t level) {
float dy = getFloat();
int color = getInt();
ALOGD("%s%s %.2f, %.2f, %.2f, 0x%x", (char*) indent, OP_NAMES[op],
- radius, dx, dy, color);
+ radius, dx, dy, color);
}
break;
case ResetPaintFilter: {
@@ -563,20 +610,193 @@ void DisplayList::output(OpenGLRenderer& renderer, uint32_t level) {
break;
default:
ALOGD("Display List error: op not handled: %s%s",
- (char*) indent, OP_NAMES[op]);
+ (char*) indent, OP_NAMES[op]);
break;
}
}
+ ALOGD("%sDone (%p, %s)", (char*) indent + 2, this, mName.string());
+}
+
+void DisplayList::updateMatrix() {
+ if (mMatrixDirty) {
+ if (!mTransformMatrix) {
+ mTransformMatrix = new SkMatrix();
+ }
+ if (mMatrixFlags == 0 || mMatrixFlags == TRANSLATION) {
+ mTransformMatrix->reset();
+ } else {
+ if (!mPivotExplicitlySet) {
+ if (mWidth != mPrevWidth || mHeight != mPrevHeight) {
+ mPrevWidth = mWidth;
+ mPrevHeight = mHeight;
+ mPivotX = mPrevWidth / 2;
+ mPivotY = mPrevHeight / 2;
+ }
+ }
+ if ((mMatrixFlags & ROTATION_3D) == 0) {
+ mTransformMatrix->setTranslate(mTranslationX, mTranslationY);
+ mTransformMatrix->preRotate(mRotation, mPivotX, mPivotY);
+ mTransformMatrix->preScale(mScaleX, mScaleY, mPivotX, mPivotY);
+ } else {
+ if (!mTransformCamera) {
+ mTransformCamera = new Sk3DView();
+ mTransformMatrix3D = new SkMatrix();
+ }
+ mTransformMatrix->reset();
+ mTransformCamera->save();
+ mTransformMatrix->preScale(mScaleX, mScaleY, mPivotX, mPivotY);
+ mTransformCamera->rotateX(mRotationX);
+ mTransformCamera->rotateY(mRotationY);
+ mTransformCamera->rotateZ(-mRotation);
+ mTransformCamera->getMatrix(mTransformMatrix3D);
+ mTransformMatrix3D->preTranslate(-mPivotX, -mPivotY);
+ mTransformMatrix3D->postTranslate(mPivotX + mTranslationX,
+ mPivotY + mTranslationY);
+ mTransformMatrix->postConcat(*mTransformMatrix3D);
+ mTransformCamera->restore();
+ }
+ }
+ mMatrixDirty = false;
+ }
+}
+
+void DisplayList::outputViewProperties(OpenGLRenderer& renderer, char* indent) {
+ if (USE_DISPLAY_LIST_PROPERTIES) {
+ updateMatrix();
+ if (mApplicationScale >= 0) {
+ ALOGD("%s%s %.2f, %.2f", (char*) indent, "Scale",
+ mApplicationScale, mApplicationScale);
+ }
+ 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);
+ } else {
+ ALOGD("%s%s %p: [%.2f, %.2f, %.2f] [%.2f, %.2f, %.2f] [%.2f, %.2f, %.2f]",
+ indent, "ConcatMatrix", mTransformMatrix,
+ mTransformMatrix->get(0), mTransformMatrix->get(1),
+ mTransformMatrix->get(2), mTransformMatrix->get(3),
+ mTransformMatrix->get(4), mTransformMatrix->get(5),
+ mTransformMatrix->get(6), mTransformMatrix->get(7),
+ mTransformMatrix->get(8));
+ }
+ }
+ if (mClipChildren) {
+ ALOGD("%s%s %.2f, %.2f, %.2f, %.2f", indent, "ClipRect", 0.0f, 0.0f,
+ (float) mRight - mLeft, (float) mBottom - mTop);
+ }
+ }
+}
- ALOGD("%sDone", (char*) indent + 2);
+void DisplayList::setViewProperties(OpenGLRenderer& renderer, uint32_t width, uint32_t height,
+ uint32_t level) {
+ if (USE_DISPLAY_LIST_PROPERTIES) {
+#if DEBUG_DISPLAY_LIST
+ uint32_t count = (level + 1) * 2;
+ char indent[count + 1];
+ for (uint32_t i = 0; i < count; i++) {
+ indent[i] = ' ';
+ }
+ indent[count] = '\0';
+#endif
+ updateMatrix();
+ if (mLeft != 0 || mTop != 0) {
+ DISPLAY_LIST_LOGD("%s%s %d, %d", indent, "Translate", mLeft, mTop);
+ renderer.translate(mLeft, mTop);
+ }
+ if (mApplicationScale >= 0) {
+ DISPLAY_LIST_LOGD("%s%s %.2f, %.2f", (char*) indent, "Scale",
+ 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);
+ renderer.translate(mTranslationX, mTranslationY);
+ } else {
+ DISPLAY_LIST_LOGD(
+ "%s%s %p: [%.2f, %.2f, %.2f] [%.2f, %.2f, %.2f] [%.2f, %.2f, %.2f]",
+ indent, "ConcatMatrix", mTransformMatrix,
+ mTransformMatrix->get(0), mTransformMatrix->get(1),
+ mTransformMatrix->get(2), mTransformMatrix->get(3),
+ mTransformMatrix->get(4), mTransformMatrix->get(5),
+ mTransformMatrix->get(6), mTransformMatrix->get(7),
+ mTransformMatrix->get(8));
+ renderer.concatMatrix(mTransformMatrix);
+ }
+ }
+ if (mClipChildren) {
+ DISPLAY_LIST_LOGD("%s%s %.2f, %.2f, %.2f, %.2f", indent, "ClipRect", 0.0f, 0.0f,
+ (float) mRight - mLeft, (float) mBottom - mTop);
+ renderer.clipRect(0, 0, mRight - mLeft, mBottom - mTop,
+ SkRegion::kIntersect_Op);
+ }
+ }
+}
+
+void DisplayList::transformRect(float left, float top, float right, float bottom, Rect& result) {
+ result.left = left + mLeft;
+ result.top = top + mTop;
+ result.right = right + mLeft;
+ result.bottom = bottom + mTop;
+ if (mMatrixFlags != 0) {
+ if (mMatrixFlags == TRANSLATION) {
+ result.left += mTranslationX;
+ result.top += mTranslationY;
+ result.right += mTranslationX;
+ result.bottom += mTranslationY;
+ } else {
+ updateMatrix();
+ SkRect r;
+ r.fLeft = result.left;
+ r.fTop = result.top;
+ r.fRight = result.right;
+ r.fBottom = result.bottom;
+ mTransformMatrix->mapRect(&r);
+ result.left = r.fLeft;
+ result.top = r.fTop;
+ result.right = r.fRight;
+ result.bottom = r.fBottom;
+ }
+ }
}
+
/**
* Changes to replay(), specifically those involving opcode or parameter changes, should be mimicked
* in the output() function, since that function processes the same list of opcodes for the
* purposes of logging display list info for a given view.
*/
-bool DisplayList::replay(OpenGLRenderer& renderer, Rect& dirty, int32_t flags, uint32_t level) {
+bool DisplayList::replay(OpenGLRenderer& renderer, uint32_t width,
+ uint32_t height, Rect& dirty, int32_t flags, uint32_t level) {
bool needsInvalidate = false;
TextContainer text;
mReader.rewind();
@@ -592,6 +812,13 @@ bool DisplayList::replay(OpenGLRenderer& renderer, Rect& dirty, int32_t flags, u
#endif
renderer.startMark(mName.string());
+ int restoreTo = 0;
+ if (USE_DISPLAY_LIST_PROPERTIES) {
+ DISPLAY_LIST_LOGD("%s%s %d", indent, "Save",
+ SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag);
+ restoreTo = renderer.save(SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag);
+ }
+ setViewProperties(renderer, width, height, level);
DisplayListLogBuffer& logBuffer = DisplayListLogBuffer::getInstance();
int saveCount = renderer.getSaveCount() - 1;
@@ -644,7 +871,7 @@ bool DisplayList::replay(OpenGLRenderer& renderer, Rect& dirty, int32_t flags, u
SkPaint* paint = getPaint(renderer);
int32_t flags = getInt();
DISPLAY_LIST_LOGD("%s%s %.2f, %.2f, %.2f, %.2f, %p, 0x%x", (char*) indent,
- OP_NAMES[op], f1, f2, f3, f4, paint, flags);
+ OP_NAMES[op], f1, f2, f3, f4, paint, flags);
renderer.saveLayer(f1, f2, f3, f4, paint, flags);
}
break;
@@ -656,7 +883,7 @@ bool DisplayList::replay(OpenGLRenderer& renderer, Rect& dirty, int32_t flags, u
int32_t alpha = getInt();
int32_t flags = getInt();
DISPLAY_LIST_LOGD("%s%s %.2f, %.2f, %.2f, %.2f, %d, 0x%x", (char*) indent,
- OP_NAMES[op], f1, f2, f3, f4, alpha, flags);
+ OP_NAMES[op], f1, f2, f3, f4, alpha, flags);
renderer.saveLayerAlpha(f1, f2, f3, f4, alpha, flags);
}
break;
@@ -695,7 +922,12 @@ bool DisplayList::replay(OpenGLRenderer& renderer, Rect& dirty, int32_t flags, u
break;
case ConcatMatrix: {
SkMatrix* matrix = getMatrix();
- DISPLAY_LIST_LOGD("%s%s %p", (char*) indent, OP_NAMES[op], matrix);
+ DISPLAY_LIST_LOGD(
+ "%s%s %p: [%.2f, %.2f, %.2f] [%.2f, %.2f, %.2f] [%.2f, %.2f, %.2f]",
+ (char*) indent, OP_NAMES[op], matrix,
+ matrix->get(0), matrix->get(1), matrix->get(2),
+ matrix->get(3), matrix->get(4), matrix->get(5),
+ matrix->get(6), matrix->get(7), matrix->get(8));
renderer.concatMatrix(matrix);
}
break;
@@ -706,7 +938,7 @@ bool DisplayList::replay(OpenGLRenderer& renderer, Rect& dirty, int32_t flags, u
float f4 = getFloat();
int32_t regionOp = getInt();
DISPLAY_LIST_LOGD("%s%s %.2f, %.2f, %.2f, %.2f, %d", (char*) indent, OP_NAMES[op],
- f1, f2, f3, f4, regionOp);
+ f1, f2, f3, f4, regionOp);
renderer.clipRect(f1, f2, f3, f4, (SkRegion::Op) regionOp);
}
break;
@@ -716,9 +948,9 @@ bool DisplayList::replay(OpenGLRenderer& renderer, Rect& dirty, int32_t flags, u
uint32_t height = getUInt();
int32_t flags = getInt();
DISPLAY_LIST_LOGD("%s%s %p, %dx%d, 0x%x %d", (char*) indent, OP_NAMES[op],
- displayList, width, height, flags, level + 1);
- needsInvalidate |= renderer.drawDisplayList(displayList, width, height,
- dirty, flags, level + 1);
+ displayList, width, height, flags, level + 1);
+ needsInvalidate |= renderer.drawDisplayList(displayList, width,
+ height, dirty, flags, level + 1);
}
break;
case DrawLayer: {
@@ -726,8 +958,11 @@ bool DisplayList::replay(OpenGLRenderer& renderer, Rect& dirty, int32_t flags, u
float x = getFloat();
float y = getFloat();
SkPaint* paint = getPaint(renderer);
+ if (mCaching && mMultipliedAlpha < 255) {
+ paint->setAlpha(mMultipliedAlpha);
+ }
DISPLAY_LIST_LOGD("%s%s %p, %.2f, %.2f, %p", (char*) indent, OP_NAMES[op],
- layer, x, y, paint);
+ layer, x, y, paint);
renderer.drawLayer(layer, x, y, paint);
}
break;
@@ -737,7 +972,7 @@ bool DisplayList::replay(OpenGLRenderer& renderer, Rect& dirty, int32_t flags, u
float y = getFloat();
SkPaint* paint = getPaint(renderer);
DISPLAY_LIST_LOGD("%s%s %p, %.2f, %.2f, %p", (char*) indent, OP_NAMES[op],
- bitmap, x, y, paint);
+ bitmap, x, y, paint);
renderer.drawBitmap(bitmap, x, y, paint);
}
break;
@@ -746,7 +981,7 @@ bool DisplayList::replay(OpenGLRenderer& renderer, Rect& dirty, int32_t flags, u
SkMatrix* matrix = getMatrix();
SkPaint* paint = getPaint(renderer);
DISPLAY_LIST_LOGD("%s%s %p, %p, %p", (char*) indent, OP_NAMES[op],
- bitmap, matrix, paint);
+ bitmap, matrix, paint);
renderer.drawBitmap(bitmap, matrix, paint);
}
break;
@@ -762,7 +997,8 @@ bool DisplayList::replay(OpenGLRenderer& renderer, Rect& dirty, int32_t flags, u
float f8 = getFloat();
SkPaint* paint = getPaint(renderer);
DISPLAY_LIST_LOGD("%s%s %p, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %p",
- (char*) indent, OP_NAMES[op], bitmap, f1, f2, f3, f4, f5, f6, f7, f8, paint);
+ (char*) indent, OP_NAMES[op], bitmap,
+ f1, f2, f3, f4, f5, f6, f7, f8,paint);
renderer.drawBitmap(bitmap, f1, f2, f3, f4, f5, f6, f7, f8, paint);
}
break;
@@ -821,7 +1057,7 @@ bool DisplayList::replay(OpenGLRenderer& renderer, Rect& dirty, int32_t flags, u
float f4 = getFloat();
SkPaint* paint = getPaint(renderer);
DISPLAY_LIST_LOGD("%s%s %.2f, %.2f, %.2f, %.2f, %p", (char*) indent, OP_NAMES[op],
- f1, f2, f3, f4, paint);
+ f1, f2, f3, f4, paint);
renderer.drawRect(f1, f2, f3, f4, paint);
}
break;
@@ -834,7 +1070,7 @@ bool DisplayList::replay(OpenGLRenderer& renderer, Rect& dirty, int32_t flags, u
float f6 = getFloat();
SkPaint* paint = getPaint(renderer);
DISPLAY_LIST_LOGD("%s%s %.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %p",
- (char*) indent, OP_NAMES[op], f1, f2, f3, f4, f5, f6, paint);
+ (char*) indent, OP_NAMES[op], f1, f2, f3, f4, f5, f6, paint);
renderer.drawRoundRect(f1, f2, f3, f4, f5, f6, paint);
}
break;
@@ -844,7 +1080,7 @@ bool DisplayList::replay(OpenGLRenderer& renderer, Rect& dirty, int32_t flags, u
float f3 = getFloat();
SkPaint* paint = getPaint(renderer);
DISPLAY_LIST_LOGD("%s%s %.2f, %.2f, %.2f, %p",
- (char*) indent, OP_NAMES[op], f1, f2, f3, paint);
+ (char*) indent, OP_NAMES[op], f1, f2, f3, paint);
renderer.drawCircle(f1, f2, f3, paint);
}
break;
@@ -855,7 +1091,7 @@ bool DisplayList::replay(OpenGLRenderer& renderer, Rect& dirty, int32_t flags, u
float f4 = getFloat();
SkPaint* paint = getPaint(renderer);
DISPLAY_LIST_LOGD("%s%s %.2f, %.2f, %.2f, %.2f, %p",
- (char*) indent, OP_NAMES[op], f1, f2, f3, f4, paint);
+ (char*) indent, OP_NAMES[op], f1, f2, f3, f4, paint);
renderer.drawOval(f1, f2, f3, f4, paint);
}
break;
@@ -869,7 +1105,7 @@ bool DisplayList::replay(OpenGLRenderer& renderer, Rect& dirty, int32_t flags, u
int32_t i1 = getInt();
SkPaint* paint = getPaint(renderer);
DISPLAY_LIST_LOGD("%s%s %.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %d, %p",
- (char*) indent, OP_NAMES[op], f1, f2, f3, f4, f5, f6, i1, paint);
+ (char*) indent, OP_NAMES[op], f1, f2, f3, f4, f5, f6, i1, paint);
renderer.drawArc(f1, f2, f3, f4, f5, f6, i1 == 1, paint);
}
break;
@@ -965,7 +1201,7 @@ bool DisplayList::replay(OpenGLRenderer& renderer, Rect& dirty, int32_t flags, u
float dy = getFloat();
int32_t color = getInt();
DISPLAY_LIST_LOGD("%s%s %.2f, %.2f, %.2f, 0x%x", (char*) indent, OP_NAMES[op],
- radius, dx, dy, color);
+ radius, dx, dy, color);
renderer.setupShadow(radius, dx, dy, color);
}
break;
@@ -984,14 +1220,19 @@ bool DisplayList::replay(OpenGLRenderer& renderer, Rect& dirty, int32_t flags, u
break;
default:
DISPLAY_LIST_LOGD("Display List error: op not handled: %s%s",
- (char*) indent, OP_NAMES[op]);
+ (char*) indent, OP_NAMES[op]);
break;
}
}
+ if (USE_DISPLAY_LIST_PROPERTIES) {
+ DISPLAY_LIST_LOGD("%s%s %d", (char*) indent, "RestoreToCount", restoreTo);
+ renderer.restoreToCount(restoreTo);
+ }
renderer.endMark();
- DISPLAY_LIST_LOGD("%sDone, returning %d", (char*) indent + 2, needsInvalidate);
+ DISPLAY_LIST_LOGD("%sDone (%p, %s), returning %d", (char*) indent + 2, this, mName.string(),
+ needsInvalidate);
return needsInvalidate;
}
@@ -999,7 +1240,7 @@ bool DisplayList::replay(OpenGLRenderer& renderer, Rect& dirty, int32_t flags, u
// Base structure
///////////////////////////////////////////////////////////////////////////////
-DisplayListRenderer::DisplayListRenderer(): mWriter(MIN_WRITER_SIZE),
+DisplayListRenderer::DisplayListRenderer() : mWriter(MIN_WRITER_SIZE),
mTranslateX(0.0f), mTranslateY(0.0f), mHasTranslate(false), mHasDrawOps(false) {
}
@@ -1177,7 +1418,19 @@ bool DisplayListRenderer::drawDisplayList(DisplayList* displayList,
uint32_t width, uint32_t height, Rect& dirty, int32_t flags, uint32_t level) {
// dirty is an out parameter and should not be recorded,
// it matters only when replaying the display list
- const bool reject = quickReject(0.0f, 0.0f, width, height);
+ float top = 0;
+ float left = 0;
+ float right = width;
+ float bottom = height;
+ if (USE_DISPLAY_LIST_PROPERTIES) {
+ Rect transformedRect;
+ displayList->transformRect(left, top, right, bottom, transformedRect);
+ left = transformedRect.left;
+ top = transformedRect.top;
+ right = transformedRect.right;
+ bottom = transformedRect.bottom;
+ }
+ const bool reject = quickReject(left, top, right, bottom);
uint32_t* location = addOp(DisplayList::DrawDisplayList, reject);
addDisplayList(displayList);
addSize(width, height);
@@ -1274,7 +1527,7 @@ void DisplayListRenderer::drawRect(float left, float top, float right, float bot
}
void DisplayListRenderer::drawRoundRect(float left, float top, float right, float bottom,
- float rx, float ry, SkPaint* paint) {
+ float rx, float ry, SkPaint* paint) {
const bool reject = paint->getStyle() == SkPaint::kFill_Style &&
quickReject(left, top, right, bottom);
uint32_t* location = addOp(DisplayList::DrawRoundRect, reject);
diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h
index 02f8438..abe8b82 100644
--- a/libs/hwui/DisplayListRenderer.h
+++ b/libs/hwui/DisplayListRenderer.h
@@ -20,6 +20,7 @@
#include <SkChunkAlloc.h>
#include <SkFlattenable.h>
#include <SkMatrix.h>
+#include <SkCamera.h>
#include <SkPaint.h>
#include <SkPath.h>
#include <SkRefCnt.h>
@@ -28,11 +29,8 @@
#include <cutils/compiler.h>
-#include <utils/String8.h>
-
#include "DisplayListLogBuffer.h"
#include "OpenGLRenderer.h"
-#include "utils/Functor.h"
namespace android {
namespace uirenderer {
@@ -51,6 +49,16 @@ namespace uirenderer {
#define DISPLAY_LIST_LOGD(...)
#endif
+// Set to 1 to enable native processing of View properties. 0 by default. Eventually this
+// will go away and we will always use this approach for accelerated apps.
+#define USE_DISPLAY_LIST_PROPERTIES 0
+
+#define TRANSLATION 0x0001
+#define ROTATION 0x0002
+#define ROTATION_3D 0x0004
+#define SCALE 0x0008
+#define PIVOT 0x0010
+
///////////////////////////////////////////////////////////////////////////////
// Display list
///////////////////////////////////////////////////////////////////////////////
@@ -119,13 +127,18 @@ public:
static const char* OP_NAMES[];
+ void setViewProperties(OpenGLRenderer& renderer, uint32_t width, uint32_t height,
+ uint32_t level);
+ void outputViewProperties(OpenGLRenderer& renderer, char* indent);
+
ANDROID_API size_t getSize();
ANDROID_API static void destroyDisplayListDeferred(DisplayList* displayList);
ANDROID_API static void outputLogBuffer(int fd);
void initFromDisplayListRenderer(const DisplayListRenderer& recorder, bool reusing = false);
- bool replay(OpenGLRenderer& renderer, Rect& dirty, int32_t flags, uint32_t level = 0);
+ bool replay(OpenGLRenderer& renderer, uint32_t width, uint32_t height,
+ Rect& dirty, int32_t flags, uint32_t level = 0);
void output(OpenGLRenderer& renderer, uint32_t level = 0);
@@ -143,11 +156,240 @@ public:
}
}
+ void setApplicationScale(float scale) {
+ mApplicationScale = scale;
+ }
+
+ void setClipChildren(bool clipChildren) {
+ mClipChildren = clipChildren;
+ }
+
+ void setAlpha(float alpha) {
+ if (alpha != mAlpha) {
+ mAlpha = alpha;
+ mMultipliedAlpha = (int)(255 * alpha);
+ }
+ }
+
+ void setTranslationX(float translationX) {
+ if (translationX != mTranslationX) {
+ mTranslationX = translationX;
+ mMatrixDirty = true;
+ if (ALMOST_EQUAL(mTranslationX, 0) && ALMOST_EQUAL(mTranslationY, 0)) {
+ mMatrixFlags &= ~TRANSLATION;
+ } else {
+ mMatrixFlags |= TRANSLATION;
+ }
+ }
+ }
+
+ void setTranslationY(float translationY) {
+ if (translationY != mTranslationY) {
+ mTranslationY = translationY;
+ mMatrixDirty = true;
+ if (ALMOST_EQUAL(mTranslationX, 0) && ALMOST_EQUAL(mTranslationY, 0)) {
+ mMatrixFlags &= ~TRANSLATION;
+ } else {
+ mMatrixFlags |= TRANSLATION;
+ }
+ }
+ }
+
+ void setRotation(float rotation) {
+ if (rotation != mRotation) {
+ mRotation = rotation;
+ mMatrixDirty = true;
+ if (ALMOST_EQUAL(mRotation, 0)) {
+ mMatrixFlags &= ~ROTATION;
+ } else {
+ mMatrixFlags |= ROTATION;
+ }
+ }
+ }
+
+ void setRotationX(float rotationX) {
+ if (rotationX != mRotationX) {
+ mRotationX = rotationX;
+ mMatrixDirty = true;
+ if (ALMOST_EQUAL(mRotationX, 0) && ALMOST_EQUAL(mRotationY, 0)) {
+ mMatrixFlags &= ~ROTATION_3D;
+ } else {
+ mMatrixFlags |= ROTATION_3D;
+ }
+ }
+ }
+
+ void setRotationY(float rotationY) {
+ if (rotationY != mRotationY) {
+ mRotationY = rotationY;
+ mMatrixDirty = true;
+ if (ALMOST_EQUAL(mRotationX, 0) && ALMOST_EQUAL(mRotationY, 0)) {
+ mMatrixFlags &= ~ROTATION_3D;
+ } else {
+ mMatrixFlags |= ROTATION_3D;
+ }
+ }
+ }
+
+ void setScaleX(float scaleX) {
+ if (scaleX != mScaleX) {
+ mScaleX = scaleX;
+ mMatrixDirty = true;
+ if (ALMOST_EQUAL(mScaleX, 1) && ALMOST_EQUAL(mScaleY, 1)) {
+ mMatrixFlags &= ~SCALE;
+ } else {
+ mMatrixFlags |= SCALE;
+ }
+ }
+ }
+
+ void setScaleY(float scaleY) {
+ if (scaleY != mScaleY) {
+ mScaleY = scaleY;
+ mMatrixDirty = true;
+ if (ALMOST_EQUAL(mScaleX, 1) && ALMOST_EQUAL(mScaleY, 1)) {
+ mMatrixFlags &= ~SCALE;
+ } else {
+ mMatrixFlags |= SCALE;
+ }
+ }
+ }
+
+ void setPivotX(float pivotX) {
+ mPivotX = pivotX;
+ mMatrixDirty = true;
+ if (ALMOST_EQUAL(mPivotX, 0) && ALMOST_EQUAL(mPivotY, 0)) {
+ mMatrixFlags &= ~PIVOT;
+ } else {
+ mMatrixFlags |= PIVOT;
+ }
+ mPivotExplicitlySet = true;
+ }
+
+ void setPivotY(float pivotY) {
+ mPivotY = pivotY;
+ mMatrixDirty = true;
+ if (ALMOST_EQUAL(mPivotX, 0) && ALMOST_EQUAL(mPivotY, 0)) {
+ mMatrixFlags &= ~PIVOT;
+ } else {
+ mMatrixFlags |= PIVOT;
+ }
+ mPivotExplicitlySet = true;
+ }
+
+ void setCameraDistance(float distance) {
+ if (distance != mCameraDistance) {
+ mCameraDistance = distance;
+ mMatrixDirty = true;
+ if (!mTransformCamera) {
+ mTransformCamera = new Sk3DView();
+ mTransformMatrix3D = new SkMatrix();
+ }
+ mTransformCamera->setCameraLocation(0, 0, distance);
+ }
+ }
+
+ void setLeft(int left) {
+ if (left != mLeft) {
+ mLeft = left;
+ mWidth = mRight - mLeft;
+ if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) {
+ mMatrixDirty = true;
+ }
+ }
+ }
+
+ void setTop(int top) {
+ if (top != mTop) {
+ mTop = top;
+ mHeight = mBottom - mTop;
+ if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) {
+ mMatrixDirty = true;
+ }
+ }
+ }
+
+ void setRight(int right) {
+ if (right != mRight) {
+ mRight = right;
+ mWidth = mRight - mLeft;
+ if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) {
+ mMatrixDirty = true;
+ }
+ }
+ }
+
+ void setBottom(int bottom) {
+ if (bottom != mBottom) {
+ mBottom = bottom;
+ mHeight = mBottom - mTop;
+ if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) {
+ mMatrixDirty = true;
+ }
+ }
+ }
+
+ void setLeftTop(int left, int top) {
+ if (left != mLeft || top != mTop) {
+ mLeft = left;
+ mTop = top;
+ mWidth = mRight - mLeft;
+ mHeight = mBottom - mTop;
+ if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) {
+ mMatrixDirty = true;
+ }
+ }
+ }
+
+ void setLeftTopRightBottom(int left, int top, int right, int bottom) {
+ if (left != mLeft || top != mTop || right != mRight || bottom != mBottom) {
+ mLeft = left;
+ mTop = top;
+ mRight = right;
+ mBottom = bottom;
+ mWidth = mRight - mLeft;
+ mHeight = mBottom - mTop;
+ if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) {
+ mMatrixDirty = true;
+ }
+ }
+ }
+
+ void offsetLeftRight(int offset) {
+ if (offset != 0) {
+ mLeft += offset;
+ mRight += offset;
+ if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) {
+ mMatrixDirty = true;
+ }
+ }
+ }
+
+ void offsetTopBottom(int offset) {
+ if (offset != 0) {
+ mTop += offset;
+ mBottom += offset;
+ if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) {
+ mMatrixDirty = true;
+ }
+ }
+ }
+
+ void setCaching(bool caching) {
+ mCaching = caching;
+ }
+
+ void transformRect(float left, float top, float right, float bottom, Rect& result);
+
private:
void init();
+ void initProperties();
+
void clearResources();
+ void updateMatrix();
+
class TextContainer {
public:
size_t length() const {
@@ -241,6 +483,28 @@ private:
bool mIsRenderable;
String8 mName;
+
+ // View properties
+ float mApplicationScale;
+ bool mClipChildren;
+ float mAlpha;
+ int mMultipliedAlpha;
+ float mTranslationX, mTranslationY;
+ float mRotation, mRotationX, mRotationY;
+ float mScaleX, mScaleY;
+ float mPivotX, mPivotY;
+ float mCameraDistance;
+ int mLeft, mTop, mRight, mBottom;
+ int mWidth, mHeight;
+ int mPrevWidth, mPrevHeight;
+ bool mPivotExplicitlySet;
+ bool mMatrixDirty;
+ bool mMatrixIsIdentity;
+ uint32_t mMatrixFlags;
+ SkMatrix* mTransformMatrix;
+ Sk3DView* mTransformCamera;
+ SkMatrix* mTransformMatrix3D;
+ bool mCaching;
};
///////////////////////////////////////////////////////////////////////////////
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index b4310ea..685fddc 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -1323,14 +1323,26 @@ void OpenGLRenderer::finishDrawTexture() {
bool OpenGLRenderer::drawDisplayList(DisplayList* displayList, uint32_t width, uint32_t height,
Rect& dirty, int32_t flags, uint32_t level) {
- if (quickReject(0.0f, 0.0f, width, height)) {
+ float top = 0;
+ float left = 0;
+ float right = width;
+ float bottom = height;
+ if (USE_DISPLAY_LIST_PROPERTIES) {
+ Rect transformedRect;
+ displayList->transformRect(left, top, right, bottom, transformedRect);
+ left = transformedRect.left;
+ top = transformedRect.top;
+ right = transformedRect.right;
+ bottom = transformedRect.bottom;
+ }
+ if (quickReject(left, top, right, bottom)) {
return false;
}
// All the usual checks and setup operations (quickReject, setupDraw, etc.)
// will be performed by the display list itself
if (displayList && displayList->isRenderable()) {
- return displayList->replay(*this, dirty, flags, level);
+ return displayList->replay(*this, width, height, dirty, flags, level);
}
return false;
@@ -2174,13 +2186,12 @@ void OpenGLRenderer::drawText(const char* text, int bytesCount, int count,
return;
}
+ if (length < 0.0f) length = paint->measureText(text, bytesCount);
switch (paint->getTextAlign()) {
case SkPaint::kCenter_Align:
- if (length < 0.0f) length = paint->measureText(text, bytesCount);
x -= length / 2.0f;
break;
case SkPaint::kRight_Align:
- if (length < 0.0f) length = paint->measureText(text, bytesCount);
x -= length;
break;
default:
@@ -2189,7 +2200,6 @@ void OpenGLRenderer::drawText(const char* text, int bytesCount, int count,
SkPaint::FontMetrics metrics;
paint->getFontMetrics(&metrics, 0.0f);
- // If no length was specified, just perform the hit test on the Y axis
if (quickReject(x, y + metrics.fTop, x + length, y + metrics.fBottom)) {
return;
}