diff options
| author | 2013-02-14 18:03:37 -0800 | |
|---|---|---|
| committer | 2013-02-19 12:30:02 -0800 | |
| commit | 52036b19a5f82bc4d75cfcbff99c65df8d25a99b (patch) | |
| tree | 138a50b1b6ddc1075af93c4dab85d459aef1d6d3 | |
| parent | 736ef1e9dedbdd0c24e27f170034f2f869fd083f (diff) | |
Expose display list APIs
The exposed APIs are slightly simpler than the full APIs used internally.
Only APIs useful to applications are exposed.
Change-Id: Ie03014628d40ad5ef63dedbc52ce3def84429d54
| -rw-r--r-- | core/java/android/view/DisplayList.java | 516 | ||||
| -rw-r--r-- | core/java/android/view/GLES20Canvas.java | 26 | ||||
| -rw-r--r-- | core/java/android/view/GLES20DisplayList.java | 198 | ||||
| -rw-r--r-- | core/java/android/view/GLES20Layer.java | 4 | ||||
| -rw-r--r-- | core/java/android/view/GLES20RenderLayer.java | 9 | ||||
| -rw-r--r-- | core/java/android/view/HardwareCanvas.java | 50 | ||||
| -rw-r--r-- | core/java/android/view/HardwareLayer.java | 11 | ||||
| -rw-r--r-- | core/java/android/view/HardwareRenderer.java | 28 | ||||
| -rw-r--r-- | core/java/android/view/View.java | 25 | ||||
| -rw-r--r-- | core/java/android/view/ViewGroup.java | 2 | ||||
| -rw-r--r-- | core/java/android/view/ViewRootImpl.java | 7 | ||||
| -rw-r--r-- | core/java/android/widget/Editor.java | 21 | ||||
| -rw-r--r-- | core/jni/android_view_GLES20Canvas.cpp | 26 | ||||
| -rw-r--r-- | core/jni/android_view_GLES20DisplayList.cpp | 157 | ||||
| -rw-r--r-- | libs/hwui/DisplayList.cpp | 10 | ||||
| -rw-r--r-- | libs/hwui/DisplayList.h | 73 | ||||
| -rw-r--r-- | libs/hwui/OpenGLRenderer.cpp | 2 |
17 files changed, 925 insertions, 240 deletions
diff --git a/core/java/android/view/DisplayList.java b/core/java/android/view/DisplayList.java index e996e67dd2bf..fa683c07cc5d 100644 --- a/core/java/android/view/DisplayList.java +++ b/core/java/android/view/DisplayList.java @@ -19,13 +19,111 @@ package android.view; import android.graphics.Matrix; /** - * A display lists records a series of graphics related operation and can replay + * <p>A display list records a series of graphics related operations and can replay * them later. Display lists are usually built by recording operations on a - * {@link android.graphics.Canvas}. Replaying the operations from a display list - * avoids executing views drawing code on every frame, and is thus much more - * efficient. + * {@link HardwareCanvas}. Replaying the operations from a display list avoids + * executing application code on every frame, and is thus much more efficient.</p> * - * @hide + * <p>Display lists are used internally for all views by default, and are not + * typically used directly. One reason to consider using a display is a custom + * {@link View} implementation that needs to issue a large number of drawing commands. + * When the view invalidates, all the drawing commands must be reissued, even if + * large portions of the drawing command stream stay the same frame to frame, which + * can become a performance bottleneck. To solve this issue, a custom View might split + * its content into several display lists. A display list is updated only when its + * content, and only its content, needs to be updated.</p> + * + * <p>A text editor might for instance store each paragraph into its own display list. + * Thus when the user inserts or removes characters, only the display list of the + * affected paragraph needs to be recorded again.</p> + * + * <h3>Hardware acceleration</h3> + * <p>Display lists can only be replayed using a {@link HardwareCanvas}. They are not + * supported in software. Always make sure that the {@link android.graphics.Canvas} + * you are using to render a display list is hardware accelerated using + * {@link android.graphics.Canvas#isHardwareAccelerated()}.</p> + * + * <h3>Creating a display list</h3> + * <pre class="prettyprint"> + * HardwareRenderer renderer = myView.getHardwareRenderer(); + * if (renderer != null) { + * DisplayList displayList = renderer.createDisplayList(); + * HardwareCanvas canvas = displayList.start(width, height); + * try { + * // Draw onto the canvas + * // For instance: canvas.drawBitmap(...); + * } finally { + * displayList.end(); + * } + * } + * </pre> + * + * <h3>Rendering a display list on a View</h3> + * <pre class="prettyprint"> + * @Override + * protected void onDraw(Canvas canvas) { + * if (canvas.isHardwareAccelerated()) { + * HardwareCanvas hardwareCanvas = (HardwareCanvas) canvas; + * hardwareCanvas.drawDisplayList(mDisplayList); + * } + * } + * </pre> + * + * <h3>Releasing resources</h3> + * <p>This step is not mandatory but recommended if you want to release resources + * held by a display list as soon as possible.</p> + * <pre class="prettyprint"> + * // Mark this display list invalid, it cannot be used for drawing anymore, + * // and release resources held by this display list + * displayList.clear(); + * </pre> + * + * <h3>Properties</h3> + * <p>In addition, a display list offers several properties, such as + * {@link #setScaleX(float)} or {@link #setLeft(int)}, that can be used to affect all + * the drawing commands recorded within. For instance, these properties can be used + * to move around a large number of images without re-issuing all the individual + * <code>drawBitmap()</code> calls.</p> + * + * <pre class="prettyprint"> + * private void createDisplayList() { + * HardwareRenderer renderer = getHardwareRenderer(); + * if (renderer != null) { + * mDisplayList = renderer.createDisplayList(); + * HardwareCanvas canvas = mDisplayList.start(width, height); + * try { + * for (Bitmap b : mBitmaps) { + * canvas.drawBitmap(b, 0.0f, 0.0f, null); + * canvas.translate(0.0f, b.getHeight()); + * } + * } finally { + * displayList.end(); + * } + * } + * } + * + * @Override + * protected void onDraw(Canvas canvas) { + * if (canvas.isHardwareAccelerated()) { + * HardwareCanvas hardwareCanvas = (HardwareCanvas) canvas; + * hardwareCanvas.drawDisplayList(mDisplayList); + * } + * } + * + * private void moveContentBy(int x) { + * // This will move all the bitmaps recorded inside the display list + * // by x pixels to the right and redraw this view. All the commands + * // recorded in createDisplayList() won't be re-issued, only onDraw() + * // will be invoked and will execute very quickly + * mDisplayList.offsetLeftAndRight(x); + * invalidate(); + * } + * </pre> + * + * <h3>Threading</h3> + * <p>Display lists must be created on and manipulated from the UI thread only.</p> + * + * @hide */ public abstract class DisplayList { private boolean mDirty; @@ -36,6 +134,8 @@ public abstract class DisplayList { * When this flag is set, draw operations lying outside of the bounds of the * display list will be culled early. It is recommeneded to always set this * flag. + * + * @hide */ public static final int FLAG_CLIP_CHILDREN = 0x1; @@ -44,14 +144,18 @@ public abstract class DisplayList { /** * Indicates that the display list is done drawing. * - * @see HardwareCanvas#drawDisplayList(DisplayList, android.graphics.Rect, int) + * @see HardwareCanvas#drawDisplayList(DisplayList, android.graphics.Rect, int) + * + * @hide */ public static final int STATUS_DONE = 0x0; /** * Indicates that the display list needs another drawing pass. * - * @see HardwareCanvas#drawDisplayList(DisplayList, android.graphics.Rect, int) + * @see HardwareCanvas#drawDisplayList(DisplayList, android.graphics.Rect, int) + * + * @hide */ public static final int STATUS_DRAW = 0x1; @@ -59,7 +163,9 @@ public abstract class DisplayList { * Indicates that the display list needs to re-execute its GL functors. * * @see HardwareCanvas#drawDisplayList(DisplayList, android.graphics.Rect, int) - * @see HardwareCanvas#callDrawGLFunction(int) + * @see HardwareCanvas#callDrawGLFunction(int) + * + * @hide */ public static final int STATUS_INVOKE = 0x2; @@ -67,53 +173,79 @@ public abstract class DisplayList { * Indicates that the display list performed GL drawing operations. * * @see HardwareCanvas#drawDisplayList(DisplayList, android.graphics.Rect, int) + * + * @hide */ public static final int STATUS_DREW = 0x4; /** * Starts recording the display list. All operations performed on the * returned canvas are recorded and stored in this display list. - * + * + * Calling this method will mark the display list invalid until + * {@link #end()} is called. Only valid display lists can be replayed. + * + * @param width The width of the display list's viewport + * @param height The height of the display list's viewport + * * @return A canvas to record drawing operations. + * + * @see #end() + * @see #isValid() */ - public abstract HardwareCanvas start(); + public abstract HardwareCanvas start(int width, int height); /** * Ends the recording for this display list. A display list cannot be - * replayed if recording is not finished. + * replayed if recording is not finished. Calling this method marks + * the display list valid and {@link #isValid()} will return true. + * + * @see #start(int, int) + * @see #isValid() */ public abstract void end(); /** - * Invalidates the display list, indicating that it should be repopulated - * with new drawing commands prior to being used again. Calling this method - * causes calls to {@link #isValid()} to return <code>false</code>. + * Clears resources held onto by this display list. After calling this method + * {@link #isValid()} will return false. + * + * @see #isValid() */ - public abstract void invalidate(); + public abstract void clear(); /** - * Clears additional resources held onto by this display list. You should - * only invoke this method after {@link #invalidate()}. + * Sets the dirty flag. When a display list is dirty, {@link #clear()} should + * be invoked whenever possible. + * + * @see #isDirty() + * @see #clear() + * + * @hide */ - public abstract void clear(); + public void markDirty() { + mDirty = true; + } /** - * Sets the dirty flag. When a display list is dirty, both - * {@link #invalidate()} and {@link #clear()} should be invoked whenever - * possible. - * - * @param dirty True to mark the display list dirty, false otherwise + * Removes the dirty flag. This method can be used to cancel a cleanup + * previously scheduled by setting the dirty flag. * * @see #isDirty() + * @see #clear() + * + * @hide */ - public void setDirty(boolean dirty) { - mDirty = dirty; + protected void clearDirty() { + mDirty = false; } /** * Indicates whether the display list is dirty. * - * @see #setDirty(boolean) + * @see #markDirty() + * @see #clear() + * + * @hide */ public boolean isDirty() { return mDirty; @@ -131,6 +263,8 @@ public abstract class DisplayList { * Return the amount of memory used by this display list. * * @return The size of this display list in bytes + * + * @hide */ public abstract int getSize(); @@ -139,228 +273,412 @@ public abstract class DisplayList { /////////////////////////////////////////////////////////////////////////// /** - * 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 + * Set the caching property on the display list, which indicates whether the display list + * holds a layer. Layer display lists 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. + * @param caching true if the display list represents a hardware layer, false otherwise. + * + * @hide */ public abstract void setCaching(boolean caching); /** - * Set whether the DisplayList should clip itself to its bounds. This property is controlled by + * Set whether the display list 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 + * @param clipChildren true if the display list should clip to its bounds */ public abstract void setClipChildren(boolean clipChildren); /** - * Set the static matrix on the DisplayList. This matrix exists if a custom ViewGroup - * overrides - * {@link ViewGroup#getChildStaticTransformation(View, android.view.animation.Transformation)} - * and also has {@link ViewGroup#setStaticTransformationsEnabled(boolean)} set to true. - * This matrix will be concatenated with any other matrices in the DisplayList to position - * the view appropriately. + * Set the static matrix on the display list. The specified matrix is combined with other + * transforms (such as {@link #setScaleX(float)}, {@link #setRotation(float)}, etc.) + * + * @param matrix A transform matrix to apply to this display list * - * @param matrix The matrix + * @see #getMatrix(android.graphics.Matrix) + * @see #getMatrix() */ - public abstract void setStaticMatrix(Matrix matrix); + public abstract void setMatrix(Matrix matrix); + + /** + * Returns the static matrix set on this display list. + * + * @return A new {@link Matrix} instance populated with this display list's static + * matrix + * + * @see #getMatrix(android.graphics.Matrix) + * @see #setMatrix(android.graphics.Matrix) + */ + public Matrix getMatrix() { + return getMatrix(new Matrix()); + } /** - * Set the Animation matrix on the DisplayList. This matrix exists if an Animation is - * currently playing on a View, and is set on the DisplayList during at draw() time. When + * Copies this display list's static matrix into the specified matrix. + * + * @param matrix The {@link Matrix} instance in which to copy this display + * list's static matrix. Cannot be null + * + * @return The <code>matrix</code> parameter, for convenience + * + * @see #getMatrix() + * @see #setMatrix(android.graphics.Matrix) + */ + public abstract Matrix getMatrix(Matrix matrix); + + /** + * Set the Animation matrix on the display list. This matrix exists if an Animation is + * currently playing on a View, and is set on the display list during at draw() time. When * the Animation finishes, the matrix should be cleared by sending <code>null</code> * for the matrix parameter. * * @param matrix The matrix, null indicates that the matrix should be cleared. + * + * @hide */ public abstract void setAnimationMatrix(Matrix matrix); /** - * Sets the alpha value for the DisplayList + * Sets the translucency level for the display list. + * + * @param alpha The translucency of the display list, must be a value between 0.0f and 1.0f * - * @param alpha The translucency of the DisplayList * @see View#setAlpha(float) + * @see #getAlpha() */ public abstract void setAlpha(float alpha); /** - * Sets whether the DisplayList renders content which overlaps. Non-overlapping rendering - * can use a fast path for alpha that avoids rendering to an offscreen buffer. + * Returns the translucency level of this display list. + * + * @return A value between 0.0f and 1.0f + * + * @see #setAlpha(float) + */ + public abstract float getAlpha(); + + /** + * Sets whether the display list renders content which overlaps. Non-overlapping rendering + * can use a fast path for alpha that avoids rendering to an offscreen buffer. By default + * display lists consider they do not have overlapping content. + * + * @param hasOverlappingRendering False if the content is guaranteed to be non-overlapping, + * true otherwise. * - * @param hasOverlappingRendering * @see android.view.View#hasOverlappingRendering() + * @see #hasOverlappingRendering() */ public abstract void setHasOverlappingRendering(boolean hasOverlappingRendering); /** - * Sets the translationX value for the DisplayList + * Indicates whether the content of this display list overlaps. + * + * @return True if this display list renders content which overlaps, false otherwise. + * + * @see #setHasOverlappingRendering(boolean) + */ + public abstract boolean hasOverlappingRendering(); + + /** + * Sets the translation value for the display list on the X axis + * + * @param translationX The X axis translation value of the display list, in pixels * - * @param translationX The translationX value of the DisplayList * @see View#setTranslationX(float) + * @see #getTranslationX() */ public abstract void setTranslationX(float translationX); /** - * Sets the translationY value for the DisplayList + * Returns the translation value for this display list on the X axis, in pixels. + * + * @see #setTranslationX(float) + */ + public abstract float getTranslationX(); + + /** + * Sets the translation value for the display list on the Y axis + * + * @param translationY The Y axis translation value of the display list, in pixels * - * @param translationY The translationY value of the DisplayList * @see View#setTranslationY(float) + * @see #getTranslationY() */ public abstract void setTranslationY(float translationY); /** - * Sets the rotation value for the DisplayList + * Returns the translation value for this display list on the Y axis, in pixels. + * + * @see #setTranslationY(float) + */ + public abstract float getTranslationY(); + + /** + * Sets the rotation value for the display list around the Z axis + * + * @param rotation The rotation value of the display list, in degrees * - * @param rotation The rotation value of the DisplayList * @see View#setRotation(float) + * @see #getRotation() */ public abstract void setRotation(float rotation); /** - * Sets the rotationX value for the DisplayList + * Returns the rotation value for this display list around the Z axis, in degrees. + * + * @see #setRotation(float) + */ + public abstract float getRotation(); + + /** + * Sets the rotation value for the display list around the X axis + * + * @param rotationX The rotation value of the display list, in degrees * - * @param rotationX The rotationX value of the DisplayList * @see View#setRotationX(float) + * @see #getRotationX() */ public abstract void setRotationX(float rotationX); /** - * Sets the rotationY value for the DisplayList + * Returns the rotation value for this display list around the X axis, in degrees. + * + * @see #setRotationX(float) + */ + public abstract float getRotationX(); + + /** + * Sets the rotation value for the display list around the Y axis + * + * @param rotationY The rotation value of the display list, in degrees * - * @param rotationY The rotationY value of the DisplayList * @see View#setRotationY(float) + * @see #getRotationY() */ public abstract void setRotationY(float rotationY); /** - * Sets the scaleX value for the DisplayList + * Returns the rotation value for this display list around the Y axis, in degrees. + * + * @see #setRotationY(float) + */ + public abstract float getRotationY(); + + /** + * Sets the scale value for the display list on the X axis + * + * @param scaleX The scale value of the display list * - * @param scaleX The scaleX value of the DisplayList * @see View#setScaleX(float) + * @see #getScaleX() */ public abstract void setScaleX(float scaleX); /** - * Sets the scaleY value for the DisplayList + * Returns the scale value for this display list on the X axis. + * + * @see #setScaleX(float) + */ + public abstract float getScaleX(); + + /** + * Sets the scale value for the display list on the Y axis + * + * @param scaleY The scale value of the display list * - * @param scaleY The scaleY value of the DisplayList * @see View#setScaleY(float) + * @see #getScaleY() */ public abstract void setScaleY(float scaleY); /** - * Sets all of the transform-related values of the View onto the DisplayList + * Returns the scale value for this display list on the Y axis. * - * @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 + * @see #setScaleY(float) + */ + public abstract float getScaleY(); + + /** + * Sets all of the transform-related values of the display list + * + * @param alpha The alpha value of the display list + * @param translationX The translationX value of the display list + * @param translationY The translationY value of the display list + * @param rotation The rotation value of the display list + * @param rotationX The rotationX value of the display list + * @param rotationY The rotationY value of the display list + * @param scaleX The scaleX value of the display list + * @param scaleY The scaleY value of the display list + * + * @hide */ 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 + * Sets the pivot value for the display list on the X axis + * + * @param pivotX The pivot value of the display list on the X axis, in pixels * - * @param pivotX The pivotX value of the DisplayList * @see View#setPivotX(float) + * @see #getPivotX() */ public abstract void setPivotX(float pivotX); /** - * Sets the pivotY value for the DisplayList + * Returns the pivot value for this display list on the X axis, in pixels. + * + * @see #setPivotX(float) + */ + public abstract float getPivotX(); + + /** + * Sets the pivot value for the display list on the Y axis + * + * @param pivotY The pivot value of the display list on the Y axis, in pixels * - * @param pivotY The pivotY value of the DisplayList * @see View#setPivotY(float) + * @see #getPivotY() */ public abstract void setPivotY(float pivotY); /** - * Sets the camera distance for the DisplayList + * Returns the pivot value for this display list on the Y axis, in pixels. + * + * @see #setPivotY(float) + */ + public abstract float getPivotY(); + + /** + * Sets the camera distance for the display list. Refer to + * {@link View#setCameraDistance(float)} for more information on how to + * use this property. + * + * @param distance The distance in Z of the camera of the display list * - * @param distance The distance in z of the camera of the DisplayList * @see View#setCameraDistance(float) + * @see #getCameraDistance() */ public abstract void setCameraDistance(float distance); /** - * Sets the left value for the DisplayList + * Returns the distance in Z of the camera of the display list. + * + * @see #setCameraDistance(float) + */ + public abstract float getCameraDistance(); + + /** + * Sets the left position for the display list. + * + * @param left The left position, in pixels, of the display list * - * @param left The left value of the DisplayList * @see View#setLeft(int) + * @see #getLeft() */ public abstract void setLeft(int left); /** - * Sets the top value for the DisplayList + * Returns the left position for the display list in pixels. + * + * @see #setLeft(int) + */ + public abstract float getLeft(); + + /** + * Sets the top position for the display list. + * + * @param top The top position, in pixels, of the display list * - * @param top The top value of the DisplayList * @see View#setTop(int) + * @see #getTop() */ public abstract void setTop(int top); /** - * Sets the right value for the DisplayList + * Returns the top position for the display list in pixels. + * + * @see #setTop(int) + */ + public abstract float getTop(); + + /** + * Sets the right position for the display list. + * + * @param right The right position, in pixels, of the display list * - * @param right The right value of the DisplayList * @see View#setRight(int) + * @see #getRight() */ public abstract void setRight(int right); /** - * Sets the bottom value for the DisplayList + * Returns the right position for the display list in pixels. + * + * @see #setRight(int) + */ + public abstract float getRight(); + + /** + * Sets the bottom position for the display list. + * + * @param bottom The bottom position, in pixels, of the display list * - * @param bottom The bottom value of the DisplayList * @see View#setBottom(int) + * @see #getBottom() */ public abstract void setBottom(int bottom); /** - * Sets the left and top values for the DisplayList + * Returns the bottom position for the display list in pixels. * - * @param left The left value of the DisplayList - * @param top The top value of the DisplayList - * @see View#setLeft(int) - * @see View#setTop(int) + * @see #setBottom(int) */ - public abstract void setLeftTop(int left, int top); + public abstract float getBottom(); /** - * Sets the left and top values for the DisplayList + * Sets the left and top positions for the display list + * + * @param left The left position of the display list, in pixels + * @param top The top position of the display list, in pixels + * @param right The right position of the display list, in pixels + * @param bottom The bottom position of the display list, in pixels * - * @param left The left value of the DisplayList - * @param top The top value of the DisplayList * @see View#setLeft(int) * @see View#setTop(int) + * @see View#setRight(int) + * @see View#setBottom(int) */ public abstract void setLeftTopRightBottom(int left, int top, int right, int bottom); /** - * Offsets the left and right values for the DisplayList + * Offsets the left and right positions for the display list + * + * @param offset The amount that the left and right positions of the display + * list are offset, in pixels * - * @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); + public abstract void offsetLeftAndRight(float offset); /** - * Offsets the top and bottom values for the DisplayList + * Offsets the top and bottom values for the display list + * + * @param offset The amount that the top and bottom positions of the display + * list are offset, in pixels * - * @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); + public abstract void offsetTopAndBottom(float offset); /** - * Reset native resources. This is called when cleaning up the state of DisplayLists + * Reset native resources. This is called when cleaning up the state of display lists * during destruction of hardware resources, to ensure that we do not hold onto * obsolete resources after related resources are gone. + * + * @hide */ public abstract void reset(); } diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java index 40f226177381..9c44737d05b3 100644 --- a/core/java/android/view/GLES20Canvas.java +++ b/core/java/android/view/GLES20Canvas.java @@ -377,24 +377,13 @@ class GLES20Canvas extends HardwareCanvas { } private static native int nGetDisplayList(int renderer, int displayList); - - static void destroyDisplayList(int displayList) { - nDestroyDisplayList(displayList); - } - - private static native void nDestroyDisplayList(int displayList); - - static int getDisplayListSize(int displayList) { - return nGetDisplayListSize(displayList); - } - private static native int nGetDisplayListSize(int displayList); - - static void setDisplayListName(int displayList, String name) { - nSetDisplayListName(displayList, name); + @Override + void outputDisplayList(DisplayList displayList) { + nOutputDisplayList(mRenderer, ((GLES20DisplayList) displayList).getNativeDisplayList()); } - private static native void nSetDisplayListName(int displayList, String name); + private static native void nOutputDisplayList(int renderer, int displayList); @Override public int drawDisplayList(DisplayList displayList, Rect dirty, int flags) { @@ -405,13 +394,6 @@ class GLES20Canvas extends HardwareCanvas { private static native int nDrawDisplayList(int renderer, int displayList, Rect dirty, int flags); - @Override - void outputDisplayList(DisplayList displayList) { - nOutputDisplayList(mRenderer, ((GLES20DisplayList) displayList).getNativeDisplayList()); - } - - private static native void nOutputDisplayList(int renderer, int displayList); - /////////////////////////////////////////////////////////////////////////// // Hardware layer /////////////////////////////////////////////////////////////////////////// diff --git a/core/java/android/view/GLES20DisplayList.java b/core/java/android/view/GLES20DisplayList.java index e9bd0c43976d..9c5cdb2bd2c4 100644 --- a/core/java/android/view/GLES20DisplayList.java +++ b/core/java/android/view/GLES20DisplayList.java @@ -58,7 +58,7 @@ class GLES20DisplayList extends DisplayList { } @Override - public HardwareCanvas start() { + public HardwareCanvas start(int width, int height) { if (mCanvas != null) { throw new IllegalStateException("Recording has already started"); } @@ -66,24 +66,25 @@ class GLES20DisplayList extends DisplayList { mValid = false; mCanvas = GLES20RecordingCanvas.obtain(this); mCanvas.start(); + + mCanvas.setViewport(width, height); + // The dirty rect should always be null for a display list + mCanvas.onPreDraw(null); + return mCanvas; } - @Override - public void invalidate() { + public void clear() { + clearDirty(); + if (mCanvas != null) { mCanvas.recycle(); mCanvas = null; } mValid = false; - } - @Override - public void clear() { - if (!mValid) { - mBitmaps.clear(); - mChildDisplayLists.clear(); - } + mBitmaps.clear(); + mChildDisplayLists.clear(); } @Override @@ -101,11 +102,12 @@ class GLES20DisplayList extends DisplayList { @Override public void end() { if (mCanvas != null) { + mCanvas.onPostDraw(); if (mFinalizer != null) { mCanvas.end(mFinalizer.mNativeDisplayList); } else { mFinalizer = new DisplayListFinalizer(mCanvas.end(0)); - GLES20Canvas.setDisplayListName(mFinalizer.mNativeDisplayList, mName); + nSetDisplayListName(mFinalizer.mNativeDisplayList, mName); } mCanvas.recycle(); mCanvas = null; @@ -116,9 +118,13 @@ class GLES20DisplayList extends DisplayList { @Override public int getSize() { if (mFinalizer == null) return 0; - return GLES20Canvas.getDisplayListSize(mFinalizer.mNativeDisplayList); + return nGetDisplayListSize(mFinalizer.mNativeDisplayList); } + private static native void nDestroyDisplayList(int displayList); + private static native int nGetDisplayListSize(int displayList); + private static native void nSetDisplayListName(int displayList, String name); + /////////////////////////////////////////////////////////////////////////// // Native View Properties /////////////////////////////////////////////////////////////////////////// @@ -138,13 +144,21 @@ class GLES20DisplayList extends DisplayList { } @Override - public void setStaticMatrix(Matrix matrix) { + public void setMatrix(Matrix matrix) { if (hasNativeDisplayList()) { nSetStaticMatrix(mFinalizer.mNativeDisplayList, matrix.native_instance); } } @Override + public Matrix getMatrix(Matrix matrix) { + if (hasNativeDisplayList()) { + nGetMatrix(mFinalizer.mNativeDisplayList, matrix.native_instance); + } + return matrix; + } + + @Override public void setAnimationMatrix(Matrix matrix) { if (hasNativeDisplayList()) { nSetAnimationMatrix(mFinalizer.mNativeDisplayList, @@ -160,6 +174,14 @@ class GLES20DisplayList extends DisplayList { } @Override + public float getAlpha() { + if (hasNativeDisplayList()) { + return nGetAlpha(mFinalizer.mNativeDisplayList); + } + return 1.0f; + } + + @Override public void setHasOverlappingRendering(boolean hasOverlappingRendering) { if (hasNativeDisplayList()) { nSetHasOverlappingRendering(mFinalizer.mNativeDisplayList, hasOverlappingRendering); @@ -167,6 +189,15 @@ class GLES20DisplayList extends DisplayList { } @Override + public boolean hasOverlappingRendering() { + //noinspection SimplifiableIfStatement + if (hasNativeDisplayList()) { + return nHasOverlappingRendering(mFinalizer.mNativeDisplayList); + } + return true; + } + + @Override public void setTranslationX(float translationX) { if (hasNativeDisplayList()) { nSetTranslationX(mFinalizer.mNativeDisplayList, translationX); @@ -174,6 +205,14 @@ class GLES20DisplayList extends DisplayList { } @Override + public float getTranslationX() { + if (hasNativeDisplayList()) { + return nGetTranslationX(mFinalizer.mNativeDisplayList); + } + return 0.0f; + } + + @Override public void setTranslationY(float translationY) { if (hasNativeDisplayList()) { nSetTranslationY(mFinalizer.mNativeDisplayList, translationY); @@ -181,6 +220,14 @@ class GLES20DisplayList extends DisplayList { } @Override + public float getTranslationY() { + if (hasNativeDisplayList()) { + return nGetTranslationY(mFinalizer.mNativeDisplayList); + } + return 0.0f; + } + + @Override public void setRotation(float rotation) { if (hasNativeDisplayList()) { nSetRotation(mFinalizer.mNativeDisplayList, rotation); @@ -188,6 +235,14 @@ class GLES20DisplayList extends DisplayList { } @Override + public float getRotation() { + if (hasNativeDisplayList()) { + return nGetRotation(mFinalizer.mNativeDisplayList); + } + return 0.0f; + } + + @Override public void setRotationX(float rotationX) { if (hasNativeDisplayList()) { nSetRotationX(mFinalizer.mNativeDisplayList, rotationX); @@ -195,6 +250,14 @@ class GLES20DisplayList extends DisplayList { } @Override + public float getRotationX() { + if (hasNativeDisplayList()) { + return nGetRotationX(mFinalizer.mNativeDisplayList); + } + return 0.0f; + } + + @Override public void setRotationY(float rotationY) { if (hasNativeDisplayList()) { nSetRotationY(mFinalizer.mNativeDisplayList, rotationY); @@ -202,6 +265,14 @@ class GLES20DisplayList extends DisplayList { } @Override + public float getRotationY() { + if (hasNativeDisplayList()) { + return nGetRotationY(mFinalizer.mNativeDisplayList); + } + return 0.0f; + } + + @Override public void setScaleX(float scaleX) { if (hasNativeDisplayList()) { nSetScaleX(mFinalizer.mNativeDisplayList, scaleX); @@ -209,6 +280,14 @@ class GLES20DisplayList extends DisplayList { } @Override + public float getScaleX() { + if (hasNativeDisplayList()) { + return nGetScaleX(mFinalizer.mNativeDisplayList); + } + return 1.0f; + } + + @Override public void setScaleY(float scaleY) { if (hasNativeDisplayList()) { nSetScaleY(mFinalizer.mNativeDisplayList, scaleY); @@ -216,6 +295,14 @@ class GLES20DisplayList extends DisplayList { } @Override + public float getScaleY() { + if (hasNativeDisplayList()) { + return nGetScaleY(mFinalizer.mNativeDisplayList); + } + return 1.0f; + } + + @Override public void setTransformationInfo(float alpha, float translationX, float translationY, float rotation, float rotationX, float rotationY, float scaleX, float scaleY) { if (hasNativeDisplayList()) { @@ -232,6 +319,14 @@ class GLES20DisplayList extends DisplayList { } @Override + public float getPivotX() { + if (hasNativeDisplayList()) { + return nGetPivotX(mFinalizer.mNativeDisplayList); + } + return 0.0f; + } + + @Override public void setPivotY(float pivotY) { if (hasNativeDisplayList()) { nSetPivotY(mFinalizer.mNativeDisplayList, pivotY); @@ -239,6 +334,14 @@ class GLES20DisplayList extends DisplayList { } @Override + public float getPivotY() { + if (hasNativeDisplayList()) { + return nGetPivotY(mFinalizer.mNativeDisplayList); + } + return 0.0f; + } + + @Override public void setCameraDistance(float distance) { if (hasNativeDisplayList()) { nSetCameraDistance(mFinalizer.mNativeDisplayList, distance); @@ -246,6 +349,14 @@ class GLES20DisplayList extends DisplayList { } @Override + public float getCameraDistance() { + if (hasNativeDisplayList()) { + return nGetCameraDistance(mFinalizer.mNativeDisplayList); + } + return 0.0f; + } + + @Override public void setLeft(int left) { if (hasNativeDisplayList()) { nSetLeft(mFinalizer.mNativeDisplayList, left); @@ -253,6 +364,14 @@ class GLES20DisplayList extends DisplayList { } @Override + public float getLeft() { + if (hasNativeDisplayList()) { + return nGetLeft(mFinalizer.mNativeDisplayList); + } + return 0.0f; + } + + @Override public void setTop(int top) { if (hasNativeDisplayList()) { nSetTop(mFinalizer.mNativeDisplayList, top); @@ -260,6 +379,14 @@ class GLES20DisplayList extends DisplayList { } @Override + public float getTop() { + if (hasNativeDisplayList()) { + return nGetTop(mFinalizer.mNativeDisplayList); + } + return 0.0f; + } + + @Override public void setRight(int right) { if (hasNativeDisplayList()) { nSetRight(mFinalizer.mNativeDisplayList, right); @@ -267,6 +394,14 @@ class GLES20DisplayList extends DisplayList { } @Override + public float getRight() { + if (hasNativeDisplayList()) { + return nGetRight(mFinalizer.mNativeDisplayList); + } + return 0.0f; + } + + @Override public void setBottom(int bottom) { if (hasNativeDisplayList()) { nSetBottom(mFinalizer.mNativeDisplayList, bottom); @@ -274,10 +409,11 @@ class GLES20DisplayList extends DisplayList { } @Override - public void setLeftTop(int left, int top) { + public float getBottom() { if (hasNativeDisplayList()) { - nSetLeftTop(mFinalizer.mNativeDisplayList, left, top); + return nGetBottom(mFinalizer.mNativeDisplayList); } + return 0.0f; } @Override @@ -288,25 +424,24 @@ class GLES20DisplayList extends DisplayList { } @Override - public void offsetLeftRight(int offset) { + public void offsetLeftAndRight(float offset) { if (hasNativeDisplayList()) { - nOffsetLeftRight(mFinalizer.mNativeDisplayList, offset); + nOffsetLeftAndRight(mFinalizer.mNativeDisplayList, offset); } } @Override - public void offsetTopBottom(int offset) { + public void offsetTopAndBottom(float offset) { if (hasNativeDisplayList()) { - nOffsetTopBottom(mFinalizer.mNativeDisplayList, offset); + nOffsetTopAndBottom(mFinalizer.mNativeDisplayList, offset); } } private static native void nReset(int displayList); - private static native void nOffsetTopBottom(int displayList, int offset); - private static native void nOffsetLeftRight(int displayList, int offset); + private static native void nOffsetTopAndBottom(int displayList, float offset); + private static native void nOffsetLeftAndRight(int displayList, float 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); @@ -332,6 +467,23 @@ class GLES20DisplayList extends DisplayList { private static native void nSetStaticMatrix(int displayList, int nativeMatrix); private static native void nSetAnimationMatrix(int displayList, int animationMatrix); + private static native boolean nHasOverlappingRendering(int displayList); + private static native void nGetMatrix(int displayList, int matrix); + private static native float nGetAlpha(int displayList); + private static native float nGetLeft(int displayList); + private static native float nGetTop(int displayList); + private static native float nGetRight(int displayList); + private static native float nGetBottom(int displayList); + private static native float nGetCameraDistance(int displayList); + private static native float nGetScaleX(int displayList); + private static native float nGetScaleY(int displayList); + private static native float nGetTranslationX(int displayList); + private static native float nGetTranslationY(int displayList); + private static native float nGetRotation(int displayList); + private static native float nGetRotationX(int displayList); + private static native float nGetRotationY(int displayList); + private static native float nGetPivotX(int displayList); + private static native float nGetPivotY(int displayList); /////////////////////////////////////////////////////////////////////////// // Finalization @@ -347,7 +499,7 @@ class GLES20DisplayList extends DisplayList { @Override protected void finalize() throws Throwable { try { - GLES20Canvas.destroyDisplayList(mNativeDisplayList); + nDestroyDisplayList(mNativeDisplayList); } finally { super.finalize(); } diff --git a/core/java/android/view/GLES20Layer.java b/core/java/android/view/GLES20Layer.java index 812fb977421e..7ee628be263d 100644 --- a/core/java/android/view/GLES20Layer.java +++ b/core/java/android/view/GLES20Layer.java @@ -53,12 +53,12 @@ abstract class GLES20Layer extends HardwareLayer { } @Override - boolean copyInto(Bitmap bitmap) { + public boolean copyInto(Bitmap bitmap) { return GLES20Canvas.nCopyLayer(mLayer, bitmap.mNativeBitmap); } @Override - void destroy() { + public void destroy() { if (mFinalizer != null) { mFinalizer.destroy(); mFinalizer = null; diff --git a/core/java/android/view/GLES20RenderLayer.java b/core/java/android/view/GLES20RenderLayer.java index 44d4719bcfba..086e78cb7d23 100644 --- a/core/java/android/view/GLES20RenderLayer.java +++ b/core/java/android/view/GLES20RenderLayer.java @@ -92,6 +92,10 @@ class GLES20RenderLayer extends GLES20Layer { if (currentCanvas instanceof GLES20Canvas) { ((GLES20Canvas) currentCanvas).resume(); } + HardwareCanvas canvas = getCanvas(); + if (canvas != null) { + canvas.onPostDraw(); + } } @Override @@ -99,7 +103,10 @@ class GLES20RenderLayer extends GLES20Layer { if (currentCanvas instanceof GLES20Canvas) { ((GLES20Canvas) currentCanvas).interrupt(); } - return getCanvas(); + HardwareCanvas canvas = getCanvas(); + canvas.setViewport(mWidth, mHeight); + canvas.onPreDraw(null); + return canvas; } /** diff --git a/core/java/android/view/HardwareCanvas.java b/core/java/android/view/HardwareCanvas.java index 3d1926077bd2..0dfed69934a4 100644 --- a/core/java/android/view/HardwareCanvas.java +++ b/core/java/android/view/HardwareCanvas.java @@ -23,8 +23,8 @@ import android.graphics.Rect; /** * Hardware accelerated canvas. - * - * @hide + * + * @hide */ public abstract class HardwareCanvas extends Canvas { private String mName; @@ -46,6 +46,8 @@ public abstract class HardwareCanvas extends Canvas { * @param name The name of the canvas, can be null * * @see #getName() + * + * @hide */ public void setName(String name) { mName = name; @@ -57,6 +59,8 @@ public abstract class HardwareCanvas extends Canvas { * @return The name of the canvas or null * * @see #setName(String) + * + * @hide */ public String getName() { return mName; @@ -67,27 +71,43 @@ public abstract class HardwareCanvas extends Canvas { * * @param dirty The dirty rectangle to update, can be null. * @return {@link DisplayList#STATUS_DREW} if anything was drawn (such as a call to clear - * the canvas). + * the canvas). + * + * @hide */ public abstract int onPreDraw(Rect dirty); /** * Invoked after all drawing operation have been performed. + * + * @hide */ public abstract void onPostDraw(); /** + * Draws the specified display list onto this canvas. The display list can only + * be drawn if {@link android.view.DisplayList#isValid()} returns true. + * + * @param displayList The display list to replay. + */ + public void drawDisplayList(DisplayList displayList) { + drawDisplayList(displayList, null, DisplayList.FLAG_CLIP_CHILDREN); + } + + /** * Draws the specified display list onto this canvas. * * @param displayList The display list to replay. * @param dirty The dirty region to redraw in the next pass, matters only - * if this method returns true, can be null. + * if this method returns {@link DisplayList#STATUS_DRAW}, can be null. * @param flags Optional flags about drawing, see {@link DisplayList} for * the possible flags. * * @return One of {@link DisplayList#STATUS_DONE}, {@link DisplayList#STATUS_DRAW}, or * {@link DisplayList#STATUS_INVOKE}, or'd with {@link DisplayList#STATUS_DREW} * if anything was drawn. + * + * @hide */ public abstract int drawDisplayList(DisplayList displayList, Rect dirty, int flags); @@ -96,6 +116,8 @@ public abstract class HardwareCanvas extends Canvas { * tools to output display lists for selected nodes to the log. * * @param displayList The display list to be logged. + * + * @hide */ abstract void outputDisplayList(DisplayList displayList); @@ -106,6 +128,8 @@ public abstract class HardwareCanvas extends Canvas { * @param x The left coordinate of the layer * @param y The top coordinate of the layer * @param paint The paint used to draw the layer + * + * @hide */ abstract void drawHardwareLayer(HardwareLayer layer, float x, float y, Paint paint); @@ -118,6 +142,8 @@ public abstract class HardwareCanvas extends Canvas { * * @return One of {@link DisplayList#STATUS_DONE}, {@link DisplayList#STATUS_DRAW} or * {@link DisplayList#STATUS_INVOKE} + * + * @hide */ public int callDrawGLFunction(int drawGLFunction) { // Noop - this is done in the display list recorder subclass @@ -131,6 +157,8 @@ public abstract class HardwareCanvas extends Canvas { * * @return One of {@link DisplayList#STATUS_DONE}, {@link DisplayList#STATUS_DRAW} or * {@link DisplayList#STATUS_INVOKE} + * + * @hide */ public int invokeFunctors(Rect dirty) { return DisplayList.STATUS_DONE; @@ -143,7 +171,9 @@ public abstract class HardwareCanvas extends Canvas { * * @see #invokeFunctors(android.graphics.Rect) * @see #callDrawGLFunction(int) - * @see #detachFunctor(int) + * @see #detachFunctor(int) + * + * @hide */ abstract void detachFunctor(int functor); @@ -154,7 +184,9 @@ public abstract class HardwareCanvas extends Canvas { * * @see #invokeFunctors(android.graphics.Rect) * @see #callDrawGLFunction(int) - * @see #detachFunctor(int) + * @see #detachFunctor(int) + * + * @hide */ abstract void attachFunctor(int functor); @@ -164,13 +196,17 @@ public abstract class HardwareCanvas extends Canvas { * @param layer The layer to update * * @see #clearLayerUpdates() + * + * @hide */ abstract void pushLayerUpdate(HardwareLayer layer); /** * Removes all enqueued layer updates. * - * @see #pushLayerUpdate(HardwareLayer) + * @see #pushLayerUpdate(HardwareLayer) + * + * @hide */ abstract void clearLayerUpdates(); } diff --git a/core/java/android/view/HardwareLayer.java b/core/java/android/view/HardwareLayer.java index d3bc35a2af42..18b838b37aa7 100644 --- a/core/java/android/view/HardwareLayer.java +++ b/core/java/android/view/HardwareLayer.java @@ -24,7 +24,7 @@ import android.graphics.Rect; /** * A hardware layer can be used to render graphics operations into a hardware - * friendly buffer. For instance, with an OpenGL backend, a hardware layer + * friendly buffer. For instance, with an OpenGL backend a hardware layer * would use a Frame Buffer Object (FBO.) The hardware layer can be used as * a drawing cache when a complex set of graphics operations needs to be * drawn several times. @@ -68,7 +68,7 @@ abstract class HardwareLayer { * @param paint The paint used when the layer is drawn into the destination canvas. * @see View#setLayerPaint(android.graphics.Paint) */ - void setLayerPaint(Paint paint) {} + void setLayerPaint(Paint paint) { } /** * Returns the minimum width of the layer. @@ -144,6 +144,9 @@ abstract class HardwareLayer { * this layer. * * @return A hardware canvas, or null if a canvas cannot be created + * + * @see #start(android.graphics.Canvas) + * @see #end(android.graphics.Canvas) */ abstract HardwareCanvas getCanvas(); @@ -154,12 +157,14 @@ abstract class HardwareLayer { /** * This must be invoked before drawing onto this layer. + * * @param currentCanvas */ abstract HardwareCanvas start(Canvas currentCanvas); - + /** * This must be invoked after drawing onto this layer. + * * @param currentCanvas */ abstract void end(Canvas currentCanvas); diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java index 7c4bcfde5a53..c6e145f2fbef 100644 --- a/core/java/android/view/HardwareRenderer.java +++ b/core/java/android/view/HardwareRenderer.java @@ -49,7 +49,7 @@ import static javax.microedition.khronos.egl.EGL10.*; /** * Interface for rendering a view hierarchy using hardware acceleration. - * + * * @hide */ public abstract class HardwareRenderer { @@ -63,9 +63,9 @@ public abstract class HardwareRenderer { /** * Turn on to only refresh the parts of the screen that need updating. * When turned on the property defined by {@link #RENDER_DIRTY_REGIONS_PROPERTY} - * must also have the value "true". + * must also have the value "true". */ - public static final boolean RENDER_DIRTY_REGIONS = true; + static final boolean RENDER_DIRTY_REGIONS = true; /** * System property used to enable or disable dirty regions invalidation. @@ -353,6 +353,8 @@ public abstract class HardwareRenderer { * resources. * * @param cacheDir A directory the current process can write to + * + * @hide */ public static void setupDiskCache(File cacheDir) { nSetupShadersDiskCache(new File(cacheDir, CACHE_PATH_SHADERS).getAbsolutePath()); @@ -442,11 +444,22 @@ public abstract class HardwareRenderer { /** * Creates a new display list that can be used to record batches of * drawing operations. + * + * @return A new display list. + */ + public DisplayList createDisplayList() { + return createDisplayList(null); + } + + /** + * Creates a new display list that can be used to record batches of + * drawing operations. * - * @param name The name of the display list, used for debugging purpose. - * May be null + * @param name The name of the display list, used for debugging purpose. May be null. * * @return A new display list. + * + * @hide */ public abstract DisplayList createDisplayList(String name); @@ -474,7 +487,6 @@ public abstract class HardwareRenderer { /** * Creates a new {@link SurfaceTexture} that can be used to render into the * specified hardware layer. - * * * @param layer The layer to render into using a {@link android.graphics.SurfaceTexture} * @@ -1971,12 +1983,12 @@ public abstract class HardwareRenderer { } @Override - HardwareLayer createHardwareLayer(int width, int height, boolean isOpaque) { + public HardwareLayer createHardwareLayer(int width, int height, boolean isOpaque) { return new GLES20RenderLayer(width, height, isOpaque); } @Override - SurfaceTexture createSurfaceTexture(HardwareLayer layer) { + public SurfaceTexture createSurfaceTexture(HardwareLayer layer) { return ((GLES20TextureLayer) layer).getSurfaceTexture(); } diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 25cad87a21e0..dcf51e4fd11f 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -16,7 +16,6 @@ package android.view; -import android.app.ActivityThread; import android.content.ClipData; import android.content.Context; import android.content.res.Configuration; @@ -10050,7 +10049,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, mTop += offset; mBottom += offset; if (mDisplayList != null) { - mDisplayList.offsetTopBottom(offset); + mDisplayList.offsetTopAndBottom(offset); invalidateViewProperty(false, false); } else { if (!matrixIsIdentity) { @@ -10098,7 +10097,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, mLeft += offset; mRight += offset; if (mDisplayList != null) { - mDisplayList.offsetLeftRight(offset); + mDisplayList.offsetLeftAndRight(offset); invalidateViewProperty(false, false); } else { if (!matrixIsIdentity) { @@ -11687,7 +11686,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } if (mDisplayList != null) { - mDisplayList.setDirty(false); + mDisplayList.clearDirty(); } } @@ -11966,7 +11965,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, if (mAttachInfo != null) { if (mDisplayList != null) { - mDisplayList.setDirty(true); + mDisplayList.markDirty(); mAttachInfo.mViewRootImpl.enqueueDisplayList(mDisplayList); } mAttachInfo.mViewRootImpl.cancelInvalidate(this); @@ -12670,8 +12669,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } /** - * @return The HardwareRenderer associated with that view or null if hardware rendering - * is not supported or this this has not been attached to a window. + * @return The {@link HardwareRenderer} associated with that view or null if + * hardware rendering is not supported or this view is not attached + * to a window. * * @hide */ @@ -12726,15 +12726,13 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } boolean caching = false; - final HardwareCanvas canvas = displayList.start(); int width = mRight - mLeft; int height = mBottom - mTop; int layerType = getLayerType(); + final HardwareCanvas canvas = displayList.start(width, height); + try { - canvas.setViewport(width, height); - // The dirty rect should always be null for a display list - canvas.onPreDraw(null); if (!isLayer && layerType != LAYER_TYPE_NONE) { if (layerType == LAYER_TYPE_HARDWARE) { final HardwareLayer layer = getHardwareLayer(); @@ -12772,8 +12770,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } } } finally { - canvas.onPostDraw(); - displayList.end(); displayList.setCaching(caching); if (isLayer) { @@ -12818,7 +12814,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback, private void clearDisplayList() { if (mDisplayList != null) { - mDisplayList.invalidate(); mDisplayList.clear(); } } @@ -13394,7 +13389,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, alpha = transform.getAlpha(); } if ((transformType & Transformation.TYPE_MATRIX) != 0) { - displayList.setStaticMatrix(transform.getMatrix()); + displayList.setMatrix(transform.getMatrix()); } } } diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java index a4898fc2f117..5105fda80225 100644 --- a/core/java/android/view/ViewGroup.java +++ b/core/java/android/view/ViewGroup.java @@ -4413,7 +4413,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager v.mTop += offset; v.mBottom += offset; if (v.mDisplayList != null) { - v.mDisplayList.offsetTopBottom(offset); + v.mDisplayList.offsetTopAndBottom(offset); invalidateViewProperty(false, false); } } diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 1d86361d7f30..9b6dafb473d8 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -1437,8 +1437,6 @@ public final class ViewRootImpl implements ViewParent, } // TODO: should handle create/resize failure layerCanvas = mResizeBuffer.start(hwRendererCanvas); - layerCanvas.setViewport(mWidth, mHeight); - layerCanvas.onPreDraw(null); final int restoreCount = layerCanvas.save(); int yoff; @@ -1475,9 +1473,6 @@ public final class ViewRootImpl implements ViewParent, } catch (OutOfMemoryError e) { Log.w(TAG, "Not enough memory for content change anim buffer", e); } finally { - if (layerCanvas != null) { - layerCanvas.onPostDraw(); - } if (mResizeBuffer != null) { mResizeBuffer.end(hwRendererCanvas); if (!completed) { @@ -2506,9 +2501,7 @@ public final class ViewRootImpl implements ViewParent, for (int i = 0; i < count; i++) { final DisplayList displayList = displayLists.get(i); if (displayList.isDirty()) { - displayList.invalidate(); displayList.clear(); - displayList.setDirty(false); } } diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java index c270e9d1ed74..862e2c8fcc41 100644 --- a/core/java/android/widget/Editor.java +++ b/core/java/android/widget/Editor.java @@ -1314,7 +1314,7 @@ public class Editor { blockDisplayList = mTextDisplayLists[blockIndex] = mTextView.getHardwareRenderer().createDisplayList("Text " + blockIndex); } else { - if (blockIsInvalid) blockDisplayList.invalidate(); + if (blockIsInvalid) blockDisplayList.clear(); } final boolean blockDisplayListIsInvalid = !blockDisplayList.isValid(); @@ -1337,19 +1337,16 @@ public class Editor { // Rebuild display list if it is invalid if (blockDisplayListIsInvalid) { - final HardwareCanvas hardwareCanvas = blockDisplayList.start(); + final HardwareCanvas hardwareCanvas = blockDisplayList.start( + right - left, bottom - top); try { - // Tighten the bounds of the viewport to the actual text size - hardwareCanvas.setViewport(right - left, bottom - top); - // The dirty rect should always be null for a display list - hardwareCanvas.onPreDraw(null); - // drawText is always relative to TextView's origin, this translation brings - // this range of text back to the top left corner of the viewport + // drawText is always relative to TextView's origin, this translation + // brings this range of text back to the top left corner of the viewport hardwareCanvas.translate(-left, -top); layout.drawText(hardwareCanvas, blockBeginLine, blockEndLine); - // No need to untranslate, previous context is popped after drawDisplayList + // No need to untranslate, previous context is popped after + // drawDisplayList } finally { - hardwareCanvas.onPostDraw(); blockDisplayList.end(); // Same as drawDisplayList below, handled by our TextView's parent blockDisplayList.setClipChildren(false); @@ -1430,7 +1427,7 @@ public class Editor { while (i < numberOfBlocks) { final int blockIndex = blockIndices[i]; if (blockIndex != DynamicLayout.INVALID_BLOCK_INDEX) { - mTextDisplayLists[blockIndex].invalidate(); + mTextDisplayLists[blockIndex].clear(); } if (blockEndLines[i] >= lastLine) break; i++; @@ -1441,7 +1438,7 @@ public class Editor { void invalidateTextDisplayList() { if (mTextDisplayLists != null) { for (int i = 0; i < mTextDisplayLists.length; i++) { - if (mTextDisplayLists[i] != null) mTextDisplayLists[i].invalidate(); + if (mTextDisplayLists[i] != null) mTextDisplayLists[i].clear(); } } } diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp index 80573a7495b9..a6bb7c75cca3 100644 --- a/core/jni/android_view_GLES20Canvas.cpp +++ b/core/jni/android_view_GLES20Canvas.cpp @@ -41,6 +41,7 @@ #include <SkTemplates.h> #include <SkXfermode.h> +#include <DisplayList.h> #include <DisplayListRenderer.h> #include <LayerRenderer.h> #include <OpenGLRenderer.h> @@ -716,20 +717,6 @@ static DisplayList* android_view_GLES20Canvas_getDisplayList(JNIEnv* env, return renderer->getDisplayList(displayList); } -static jint android_view_GLES20Canvas_getDisplayListSize(JNIEnv* env, - jobject clazz, DisplayList* displayList) { - return displayList->getSize(); -} - -static void android_view_GLES20Canvas_setDisplayListName(JNIEnv* env, - jobject clazz, DisplayList* displayList, jstring name) { - if (name != NULL) { - const char* textArray = env->GetStringUTFChars(name, NULL); - displayList->setName(textArray); - env->ReleaseStringUTFChars(name, textArray); - } -} - static OpenGLRenderer* android_view_GLES20Canvas_createDisplayListRenderer(JNIEnv* env, jobject clazz) { return new DisplayListRenderer; @@ -740,11 +727,6 @@ static void android_view_GLES20Canvas_resetDisplayListRenderer(JNIEnv* env, renderer->reset(); } -static void android_view_GLES20Canvas_destroyDisplayList(JNIEnv* env, - jobject clazz, DisplayList* displayList) { - DisplayList::destroyDisplayListDeferred(displayList); -} - static jint android_view_GLES20Canvas_drawDisplayList(JNIEnv* env, jobject clazz, OpenGLRenderer* renderer, DisplayList* displayList, jobject dirty, jint flags) { @@ -1044,17 +1026,13 @@ static JNINativeMethod gMethods[] = { (void*) android_view_GLES20Canvas_getClipBounds }, { "nGetDisplayList", "(II)I", (void*) android_view_GLES20Canvas_getDisplayList }, - { "nDestroyDisplayList", "(I)V", (void*) android_view_GLES20Canvas_destroyDisplayList }, - { "nGetDisplayListSize", "(I)I", (void*) android_view_GLES20Canvas_getDisplayListSize }, - { "nSetDisplayListName", "(ILjava/lang/String;)V", - (void*) android_view_GLES20Canvas_setDisplayListName }, + { "nOutputDisplayList", "(II)V", (void*) android_view_GLES20Canvas_outputDisplayList }, { "nDrawDisplayList", "(IILandroid/graphics/Rect;I)I", (void*) android_view_GLES20Canvas_drawDisplayList }, { "nCreateDisplayListRenderer", "()I", (void*) android_view_GLES20Canvas_createDisplayListRenderer }, { "nResetDisplayListRenderer", "(I)V", (void*) android_view_GLES20Canvas_resetDisplayListRenderer }, - { "nOutputDisplayList", "(II)V", (void*) android_view_GLES20Canvas_outputDisplayList }, { "nInterrupt", "(I)V", (void*) android_view_GLES20Canvas_interrupt }, { "nResume", "(I)V", (void*) android_view_GLES20Canvas_resume }, diff --git a/core/jni/android_view_GLES20DisplayList.cpp b/core/jni/android_view_GLES20DisplayList.cpp index c5f52df5ad4e..f7a5302ea2b0 100644 --- a/core/jni/android_view_GLES20DisplayList.cpp +++ b/core/jni/android_view_GLES20DisplayList.cpp @@ -23,6 +23,7 @@ #include <nativehelper/JNIHelp.h> #include <android_runtime/AndroidRuntime.h> +#include <DisplayList.h> #include <DisplayListRenderer.h> namespace android { @@ -36,11 +37,34 @@ using namespace uirenderer; */ #ifdef USE_OPENGL_RENDERER +// ---------------------------------------------------------------------------- +// DisplayList view properties +// ---------------------------------------------------------------------------- + static void android_view_GLES20DisplayList_reset(JNIEnv* env, jobject clazz, DisplayList* displayList) { displayList->reset(); } +static jint android_view_GLES20DisplayList_getDisplayListSize(JNIEnv* env, + jobject clazz, DisplayList* displayList) { + return displayList->getSize(); +} + +static void android_view_GLES20DisplayList_setDisplayListName(JNIEnv* env, + jobject clazz, DisplayList* displayList, jstring name) { + if (name != NULL) { + const char* textArray = env->GetStringUTFChars(name, NULL); + displayList->setName(textArray); + env->ReleaseStringUTFChars(name, textArray); + } +} + +static void android_view_GLES20DisplayList_destroyDisplayList(JNIEnv* env, + jobject clazz, DisplayList* displayList) { + DisplayList::destroyDisplayListDeferred(displayList); +} + // ---------------------------------------------------------------------------- // DisplayList view properties // ---------------------------------------------------------------------------- @@ -159,27 +183,112 @@ static void android_view_GLES20DisplayList_setBottom(JNIEnv* env, 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) { +static void android_view_GLES20DisplayList_offsetLeftAndRight(JNIEnv* env, + jobject clazz, DisplayList* displayList, float offset) { displayList->offsetLeftRight(offset); } -static void android_view_GLES20DisplayList_offsetTopBottom(JNIEnv* env, - jobject clazz, DisplayList* displayList, int offset) { +static void android_view_GLES20DisplayList_offsetTopAndBottom(JNIEnv* env, + jobject clazz, DisplayList* displayList, float offset) { displayList->offsetTopBottom(offset); } +static void android_view_GLES20DisplayList_getMatrix(JNIEnv* env, + jobject clazz, DisplayList* displayList, SkMatrix* matrix) { + SkMatrix* source = displayList->getStaticMatrix(); + if (source) { + matrix->setConcat(SkMatrix::I(), *source); + } else { + matrix->setIdentity(); + } +} + +static jboolean android_view_GLES20DisplayList_hasOverlappingRendering(JNIEnv* env, + jobject clazz, DisplayList* displayList) { + return displayList->hasOverlappingRendering(); +} + +static jfloat android_view_GLES20DisplayList_getAlpha(JNIEnv* env, + jobject clazz, DisplayList* displayList) { + return displayList->getAlpha(); +} + +static jfloat android_view_GLES20DisplayList_getLeft(JNIEnv* env, + jobject clazz, DisplayList* displayList) { + return displayList->getLeft(); +} + +static jfloat android_view_GLES20DisplayList_getTop(JNIEnv* env, + jobject clazz, DisplayList* displayList) { + return displayList->getTop(); +} + +static jfloat android_view_GLES20DisplayList_getRight(JNIEnv* env, + jobject clazz, DisplayList* displayList) { + return displayList->getRight(); +} + +static jfloat android_view_GLES20DisplayList_getBottom(JNIEnv* env, + jobject clazz, DisplayList* displayList) { + return displayList->getBottom(); +} + +static jfloat android_view_GLES20DisplayList_getCameraDistance(JNIEnv* env, + jobject clazz, DisplayList* displayList) { + return displayList->getCameraDistance(); +} + +static jfloat android_view_GLES20DisplayList_getScaleX(JNIEnv* env, + jobject clazz, DisplayList* displayList) { + return displayList->getScaleX(); +} + +static jfloat android_view_GLES20DisplayList_getScaleY(JNIEnv* env, + jobject clazz, DisplayList* displayList) { + return displayList->getScaleY(); +} + +static jfloat android_view_GLES20DisplayList_getTranslationX(JNIEnv* env, + jobject clazz, DisplayList* displayList) { + return displayList->getTranslationX(); +} + +static jfloat android_view_GLES20DisplayList_getTranslationY(JNIEnv* env, + jobject clazz, DisplayList* displayList) { + return displayList->getTranslationY(); +} + +static jfloat android_view_GLES20DisplayList_getRotation(JNIEnv* env, + jobject clazz, DisplayList* displayList) { + return displayList->getRotation(); +} + +static jfloat android_view_GLES20DisplayList_getRotationX(JNIEnv* env, + jobject clazz, DisplayList* displayList) { + return displayList->getRotationX(); +} + +static jfloat android_view_GLES20DisplayList_getRotationY(JNIEnv* env, + jobject clazz, DisplayList* displayList) { + return displayList->getRotationY(); +} + +static jfloat android_view_GLES20DisplayList_getPivotX(JNIEnv* env, + jobject clazz, DisplayList* displayList) { + return displayList->getPivotX(); +} + +static jfloat android_view_GLES20DisplayList_getPivotY(JNIEnv* env, + jobject clazz, DisplayList* displayList) { + return displayList->getPivotY(); +} + #endif // USE_OPENGL_RENDERER // ---------------------------------------------------------------------------- @@ -190,6 +299,11 @@ const char* const kClassPathName = "android/view/GLES20DisplayList"; static JNINativeMethod gMethods[] = { #ifdef USE_OPENGL_RENDERER + { "nDestroyDisplayList", "(I)V", (void*) android_view_GLES20DisplayList_destroyDisplayList }, + { "nGetDisplayListSize", "(I)I", (void*) android_view_GLES20DisplayList_getDisplayListSize }, + { "nSetDisplayListName", "(ILjava/lang/String;)V", + (void*) android_view_GLES20DisplayList_setDisplayListName }, + { "nReset", "(I)V", (void*) android_view_GLES20DisplayList_reset }, { "nSetCaching", "(IZ)V", (void*) android_view_GLES20DisplayList_setCaching }, { "nSetStaticMatrix", "(II)V", (void*) android_view_GLES20DisplayList_setStaticMatrix }, @@ -214,12 +328,29 @@ static JNINativeMethod gMethods[] = { { "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 }, - + { "nOffsetLeftAndRight", "(IF)V", (void*) android_view_GLES20DisplayList_offsetLeftAndRight }, + { "nOffsetTopAndBottom", "(IF)V", (void*) android_view_GLES20DisplayList_offsetTopAndBottom }, + + + { "nGetMatrix", "(II)V", (void*) android_view_GLES20DisplayList_getMatrix }, + { "nHasOverlappingRendering", "(I)Z", (void*) android_view_GLES20DisplayList_hasOverlappingRendering }, + { "nGetAlpha", "(I)F", (void*) android_view_GLES20DisplayList_getAlpha }, + { "nGetLeft", "(I)F", (void*) android_view_GLES20DisplayList_getLeft }, + { "nGetTop", "(I)F", (void*) android_view_GLES20DisplayList_getTop }, + { "nGetRight", "(I)F", (void*) android_view_GLES20DisplayList_getRight }, + { "nGetBottom", "(I)F", (void*) android_view_GLES20DisplayList_getBottom }, + { "nGetCameraDistance", "(I)F", (void*) android_view_GLES20DisplayList_getCameraDistance }, + { "nGetScaleX", "(I)F", (void*) android_view_GLES20DisplayList_getScaleX }, + { "nGetScaleY", "(I)F", (void*) android_view_GLES20DisplayList_getScaleY }, + { "nGetTranslationX", "(I)F", (void*) android_view_GLES20DisplayList_getTranslationX }, + { "nGetTranslationY", "(I)F", (void*) android_view_GLES20DisplayList_getTranslationY }, + { "nGetRotation", "(I)F", (void*) android_view_GLES20DisplayList_getRotation }, + { "nGetRotationX", "(I)F", (void*) android_view_GLES20DisplayList_getRotationX }, + { "nGetRotationY", "(I)F", (void*) android_view_GLES20DisplayList_getRotationY }, + { "nGetPivotX", "(I)F", (void*) android_view_GLES20DisplayList_getPivotX }, + { "nGetPivotY", "(I)F", (void*) android_view_GLES20DisplayList_getPivotY }, #endif }; diff --git a/libs/hwui/DisplayList.cpp b/libs/hwui/DisplayList.cpp index 8aac6288cf7b..6fab8dab11fd 100644 --- a/libs/hwui/DisplayList.cpp +++ b/libs/hwui/DisplayList.cpp @@ -263,6 +263,16 @@ void DisplayList::output(uint32_t level) { ALOGD("%*sDone (%p, %s)", level * 2, "", this, mName.string()); } +float DisplayList::getPivotX() { + updateMatrix(); + return mPivotX; +} + +float DisplayList::getPivotY() { + updateMatrix(); + return mPivotY; +} + void DisplayList::updateMatrix() { if (mMatrixDirty) { if (!mTransformMatrix) { diff --git a/libs/hwui/DisplayList.h b/libs/hwui/DisplayList.h index d06827db07d4..86c9ec079c67 100644 --- a/libs/hwui/DisplayList.h +++ b/libs/hwui/DisplayList.h @@ -105,6 +105,10 @@ public: } } + const char* getName() const { + return mName.string(); + } + void setClipChildren(bool clipChildren) { mClipChildren = clipChildren; } @@ -114,6 +118,11 @@ public: mStaticMatrix = new SkMatrix(*matrix); } + // Can return NULL + SkMatrix* getStaticMatrix() { + return mStaticMatrix; + } + void setAnimationMatrix(SkMatrix* matrix) { delete mAnimationMatrix; if (matrix) { @@ -131,10 +140,18 @@ public: } } + float getAlpha() const { + return mAlpha; + } + void setHasOverlappingRendering(bool hasOverlappingRendering) { mHasOverlappingRendering = hasOverlappingRendering; } + bool hasOverlappingRendering() const { + return mHasOverlappingRendering; + } + void setTranslationX(float translationX) { if (translationX != mTranslationX) { mTranslationX = translationX; @@ -147,6 +164,10 @@ public: } } + float getTranslationX() const { + return mTranslationX; + } + void setTranslationY(float translationY) { if (translationY != mTranslationY) { mTranslationY = translationY; @@ -159,6 +180,10 @@ public: } } + float getTranslationY() const { + return mTranslationY; + } + void setRotation(float rotation) { if (rotation != mRotation) { mRotation = rotation; @@ -171,6 +196,10 @@ public: } } + float getRotation() const { + return mRotation; + } + void setRotationX(float rotationX) { if (rotationX != mRotationX) { mRotationX = rotationX; @@ -183,6 +212,10 @@ public: } } + float getRotationX() const { + return mRotationX; + } + void setRotationY(float rotationY) { if (rotationY != mRotationY) { mRotationY = rotationY; @@ -195,6 +228,10 @@ public: } } + float getRotationY() const { + return mRotationY; + } + void setScaleX(float scaleX) { if (scaleX != mScaleX) { mScaleX = scaleX; @@ -207,6 +244,10 @@ public: } } + float getScaleX() const { + return mScaleX; + } + void setScaleY(float scaleY) { if (scaleY != mScaleY) { mScaleY = scaleY; @@ -219,6 +260,10 @@ public: } } + float getScaleY() const { + return mScaleY; + } + void setPivotX(float pivotX) { mPivotX = pivotX; mMatrixDirty = true; @@ -230,6 +275,8 @@ public: mPivotExplicitlySet = true; } + ANDROID_API float getPivotX(); + void setPivotY(float pivotY) { mPivotY = pivotY; mMatrixDirty = true; @@ -241,6 +288,8 @@ public: mPivotExplicitlySet = true; } + ANDROID_API float getPivotY(); + void setCameraDistance(float distance) { if (distance != mCameraDistance) { mCameraDistance = distance; @@ -253,6 +302,10 @@ public: } } + float getCameraDistance() const { + return mCameraDistance; + } + void setLeft(int left) { if (left != mLeft) { mLeft = left; @@ -263,6 +316,10 @@ public: } } + float getLeft() const { + return mLeft; + } + void setTop(int top) { if (top != mTop) { mTop = top; @@ -273,6 +330,10 @@ public: } } + float getTop() const { + return mTop; + } + void setRight(int right) { if (right != mRight) { mRight = right; @@ -283,6 +344,10 @@ public: } } + float getRight() const { + return mRight; + } + void setBottom(int bottom) { if (bottom != mBottom) { mBottom = bottom; @@ -293,6 +358,10 @@ public: } } + float getBottom() const { + return mBottom; + } + void setLeftTop(int left, int top) { if (left != mLeft || top != mTop) { mLeft = left; @@ -319,7 +388,7 @@ public: } } - void offsetLeftRight(int offset) { + void offsetLeftRight(float offset) { if (offset != 0) { mLeft += offset; mRight += offset; @@ -329,7 +398,7 @@ public: } } - void offsetTopBottom(int offset) { + void offsetTopBottom(float offset) { if (offset != 0) { mTop += offset; mBottom += offset; diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp index d11558f5aedf..e5fd7b9f0368 100644 --- a/libs/hwui/OpenGLRenderer.cpp +++ b/libs/hwui/OpenGLRenderer.cpp @@ -280,7 +280,7 @@ void OpenGLRenderer::startTiling(const sp<Snapshot>& s, bool opaque) { void OpenGLRenderer::startTiling(const Rect& clip, int windowHeight, bool opaque) { if (!mSuppressTiling) { mCaches.startTiling(clip.left, windowHeight - clip.bottom, - clip.right - clip.left, clip.bottom - clip.top, opaque); + clip.right - clip.left, clip.bottom - clip.top, opaque); } } |