diff options
| author | Chet Haase <chet@google.com> | 2012-03-12 15:48:32 -0700 |
|---|---|---|
| committer | Android (Google) Code Review <android-gerrit@google.com> | 2012-03-12 15:48:32 -0700 |
| commit | 81a0647c302edb4ed74d6d80d8f85c85a6c3fec4 (patch) | |
| tree | da6a3f7ce1cebe1c613f110d2f0421ca0d780ee3 | |
| parent | 035c20f5b4f31a2a4b592ff5004fe67fef0106d2 (diff) | |
| parent | a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3 (diff) | |
| download | frameworks_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.txt | 4 | ||||
| -rw-r--r-- | core/java/android/view/DisplayList.java | 200 | ||||
| -rw-r--r-- | core/java/android/view/GLES20DisplayList.java | 245 | ||||
| -rw-r--r-- | core/java/android/view/HardwareLayer.java | 19 | ||||
| -rw-r--r-- | core/java/android/view/View.java | 327 | ||||
| -rw-r--r-- | core/java/android/view/ViewGroup.java | 16 | ||||
| -rw-r--r-- | core/java/android/view/ViewPropertyAnimator.java | 2 | ||||
| -rw-r--r-- | core/java/android/widget/TextView.java | 5 | ||||
| -rw-r--r-- | core/jni/Android.mk | 1 | ||||
| -rw-r--r-- | core/jni/AndroidRuntime.cpp | 2 | ||||
| -rw-r--r-- | core/jni/android/graphics/Camera.cpp | 18 | ||||
| -rw-r--r-- | core/jni/android_view_GLES20DisplayList.cpp | 227 | ||||
| -rw-r--r-- | graphics/java/android/graphics/Camera.java | 21 | ||||
| -rw-r--r-- | libs/hwui/DisplayListRenderer.cpp | 345 | ||||
| -rw-r--r-- | libs/hwui/DisplayListRenderer.h | 272 | ||||
| -rw-r--r-- | libs/hwui/OpenGLRenderer.cpp | 20 |
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; } |
