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
diff --git a/core/java/android/view/DisplayList.java b/core/java/android/view/DisplayList.java
index e996e67..fa683c0 100644
--- a/core/java/android/view/DisplayList.java
+++ b/core/java/android/view/DisplayList.java
@@ -19,13 +19,111 @@
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 @@
* 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 @@
/**
* 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 @@
* 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 @@
* 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>.
- */
- public abstract void invalidate();
-
- /**
- * Clears additional resources held onto by this display list. You should
- * only invoke this method after {@link #invalidate()}.
+ * Clears resources held onto by this display list. After calling this method
+ * {@link #isValid()} will return false.
+ *
+ * @see #isValid()
*/
public abstract void clear();
/**
- * 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
+ * Sets the dirty flag. When a display list is dirty, {@link #clear()} should
+ * be invoked whenever possible.
*
* @see #isDirty()
+ * @see #clear()
+ *
+ * @hide
*/
- public void setDirty(boolean dirty) {
- mDirty = dirty;
+ public void markDirty() {
+ mDirty = true;
+ }
+
+ /**
+ * 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
+ */
+ 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 @@
* 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 @@
///////////////////////////////////////////////////////////////////////////
/**
- * 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 The matrix
+ * @param matrix A transform matrix to apply to this display list
+ *
+ * @see #getMatrix(android.graphics.Matrix)
+ * @see #getMatrix()
*/
- public abstract void setStaticMatrix(Matrix matrix);
+ public abstract void setMatrix(Matrix 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
+ * 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());
+ }
+
+ /**
+ * 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 DisplayList
+ * @param alpha The translucency of the display list, must be a value between 0.0f and 1.0f
+ *
* @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.
*
- * @param hasOverlappingRendering
+ * @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.
+ *
* @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.
*
- * @param translationX The translationX value of the DisplayList
+ * @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
+ *
* @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.
*
- * @param translationY The translationY value of the DisplayList
+ * @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
+ *
* @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.
*
- * @param rotation The rotation value of the DisplayList
+ * @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
+ *
* @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.
*
- * @param rotationX The rotationX value of the DisplayList
+ * @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
+ *
* @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.
*
- * @param rotationY The rotationY value of the DisplayList
+ * @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
+ *
* @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.
*
- * @param scaleX The scaleX value of the DisplayList
+ * @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
+ *
* @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.
*
- * @param scaleY The scaleY value of the DisplayList
+ * @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
+ *
* @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 pivotX value of the DisplayList
+ * @param pivotX The pivot value of the display list on the X axis, in pixels
+ *
* @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.
*
- * @param pivotY The pivotY value of the DisplayList
+ * @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
+ *
* @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.
*
- * @param distance The distance in z of the camera of the DisplayList
+ * @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
+ *
* @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.
*
- * @param left The left value of the DisplayList
+ * @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
+ *
* @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.
*
- * @param top The top value of the DisplayList
+ * @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
+ *
* @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.
*
- * @param right The right value of the DisplayList
+ * @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
+ *
* @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.
*
- * @param bottom The bottom value of the DisplayList
+ * @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
+ *
* @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 value of the DisplayList
- * @param top The top value of the DisplayList
+ * @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
+ *
* @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 values of the DisplayList are offset
+ * @param offset The amount that the left and right positions of the display
+ * list are offset, in pixels
+ *
* @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 values of the DisplayList are offset
+ * @param offset The amount that the top and bottom positions of the display
+ * list are offset, in pixels
+ *
* @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 40f2261..9c44737 100644
--- a/core/java/android/view/GLES20Canvas.java
+++ b/core/java/android/view/GLES20Canvas.java
@@ -377,24 +377,13 @@
}
private static native int nGetDisplayList(int renderer, int displayList);
-
- static void destroyDisplayList(int displayList) {
- nDestroyDisplayList(displayList);
+
+ @Override
+ void outputDisplayList(DisplayList displayList) {
+ nOutputDisplayList(mRenderer, ((GLES20DisplayList) displayList).getNativeDisplayList());
}
- 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);
- }
-
- 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 @@
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 e9bd0c4..9c5cdb2 100644
--- a/core/java/android/view/GLES20DisplayList.java
+++ b/core/java/android/view/GLES20DisplayList.java
@@ -58,7 +58,7 @@
}
@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 @@
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 @@
@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 @@
@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 @@
}
@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 @@
}
@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 @@
}
@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 @@
}
@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 @@
}
@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 @@
}
@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 @@
}
@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 @@
}
@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 @@
}
@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 @@
}
@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 @@
}
@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 @@
}
@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 @@
}
@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 @@
}
@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 @@
}
@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 @@
}
@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 @@
}
@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 @@
}
@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 @@
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 @@
@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 812fb97..7ee628b 100644
--- a/core/java/android/view/GLES20Layer.java
+++ b/core/java/android/view/GLES20Layer.java
@@ -53,12 +53,12 @@
}
@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 44d4719..086e78c 100644
--- a/core/java/android/view/GLES20RenderLayer.java
+++ b/core/java/android/view/GLES20RenderLayer.java
@@ -92,6 +92,10 @@
if (currentCanvas instanceof GLES20Canvas) {
((GLES20Canvas) currentCanvas).resume();
}
+ HardwareCanvas canvas = getCanvas();
+ if (canvas != null) {
+ canvas.onPostDraw();
+ }
}
@Override
@@ -99,7 +103,10 @@
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 3d19260..0dfed69 100644
--- a/core/java/android/view/HardwareCanvas.java
+++ b/core/java/android/view/HardwareCanvas.java
@@ -23,8 +23,8 @@
/**
* Hardware accelerated canvas.
- *
- * @hide
+ *
+ * @hide
*/
public abstract class HardwareCanvas extends Canvas {
private String mName;
@@ -46,6 +46,8 @@
* @param name The name of the canvas, can be null
*
* @see #getName()
+ *
+ * @hide
*/
public void setName(String name) {
mName = name;
@@ -57,6 +59,8 @@
* @return The name of the canvas or null
*
* @see #setName(String)
+ *
+ * @hide
*/
public String getName() {
return mName;
@@ -67,27 +71,43 @@
*
* @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 @@
* 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 @@
* @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 @@
*
* @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 @@
*
* @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 @@
*
* @see #invokeFunctors(android.graphics.Rect)
* @see #callDrawGLFunction(int)
- * @see #detachFunctor(int)
+ * @see #detachFunctor(int)
+ *
+ * @hide
*/
abstract void detachFunctor(int functor);
@@ -154,7 +184,9 @@
*
* @see #invokeFunctors(android.graphics.Rect)
* @see #callDrawGLFunction(int)
- * @see #detachFunctor(int)
+ * @see #detachFunctor(int)
+ *
+ * @hide
*/
abstract void attachFunctor(int functor);
@@ -164,13 +196,17 @@
* @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 d3bc35a..18b838b 100644
--- a/core/java/android/view/HardwareLayer.java
+++ b/core/java/android/view/HardwareLayer.java
@@ -24,7 +24,7 @@
/**
* 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 @@
* @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 @@
* 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 @@
/**
* 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 7c4bcfd..c6e145f 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -49,7 +49,7 @@
/**
* Interface for rendering a view hierarchy using hardware acceleration.
- *
+ *
* @hide
*/
public abstract class HardwareRenderer {
@@ -63,9 +63,9 @@
/**
* 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 @@
* 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 @@
/**
* 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 @@
/**
* 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 @@
}
@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 25cad87..dcf51e4 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 @@
mTop += offset;
mBottom += offset;
if (mDisplayList != null) {
- mDisplayList.offsetTopBottom(offset);
+ mDisplayList.offsetTopAndBottom(offset);
invalidateViewProperty(false, false);
} else {
if (!matrixIsIdentity) {
@@ -10098,7 +10097,7 @@
mLeft += offset;
mRight += offset;
if (mDisplayList != null) {
- mDisplayList.offsetLeftRight(offset);
+ mDisplayList.offsetLeftAndRight(offset);
invalidateViewProperty(false, false);
} else {
if (!matrixIsIdentity) {
@@ -11687,7 +11686,7 @@
}
if (mDisplayList != null) {
- mDisplayList.setDirty(false);
+ mDisplayList.clearDirty();
}
}
@@ -11966,7 +11965,7 @@
if (mAttachInfo != null) {
if (mDisplayList != null) {
- mDisplayList.setDirty(true);
+ mDisplayList.markDirty();
mAttachInfo.mViewRootImpl.enqueueDisplayList(mDisplayList);
}
mAttachInfo.mViewRootImpl.cancelInvalidate(this);
@@ -12670,8 +12669,9 @@
}
/**
- * @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 @@
}
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 @@
}
}
} finally {
- canvas.onPostDraw();
-
displayList.end();
displayList.setCaching(caching);
if (isLayer) {
@@ -12818,7 +12814,6 @@
private void clearDisplayList() {
if (mDisplayList != null) {
- mDisplayList.invalidate();
mDisplayList.clear();
}
}
@@ -13394,7 +13389,7 @@
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 a4898fc..5105fda 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -4413,7 +4413,7 @@
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 1d86361..9b6dafb 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -1437,8 +1437,6 @@
}
// 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 @@
} 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 @@
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 c270e9d..862e2c8 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -1314,7 +1314,7 @@
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 @@
// 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 @@
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 @@
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 80573a7..a6bb7c7 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 @@
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 @@
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 @@
(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 c5f52df..f7a5302 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 @@
*/
#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 @@
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 @@
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 @@
{ "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 8aac628..6fab8da 100644
--- a/libs/hwui/DisplayList.cpp
+++ b/libs/hwui/DisplayList.cpp
@@ -263,6 +263,16 @@
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 d06827d..86c9ec0 100644
--- a/libs/hwui/DisplayList.h
+++ b/libs/hwui/DisplayList.h
@@ -105,6 +105,10 @@
}
}
+ const char* getName() const {
+ return mName.string();
+ }
+
void setClipChildren(bool clipChildren) {
mClipChildren = clipChildren;
}
@@ -114,6 +118,11 @@
mStaticMatrix = new SkMatrix(*matrix);
}
+ // Can return NULL
+ SkMatrix* getStaticMatrix() {
+ return mStaticMatrix;
+ }
+
void setAnimationMatrix(SkMatrix* matrix) {
delete mAnimationMatrix;
if (matrix) {
@@ -131,10 +140,18 @@
}
}
+ 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 @@
}
}
+ float getTranslationX() const {
+ return mTranslationX;
+ }
+
void setTranslationY(float translationY) {
if (translationY != mTranslationY) {
mTranslationY = translationY;
@@ -159,6 +180,10 @@
}
}
+ float getTranslationY() const {
+ return mTranslationY;
+ }
+
void setRotation(float rotation) {
if (rotation != mRotation) {
mRotation = rotation;
@@ -171,6 +196,10 @@
}
}
+ float getRotation() const {
+ return mRotation;
+ }
+
void setRotationX(float rotationX) {
if (rotationX != mRotationX) {
mRotationX = rotationX;
@@ -183,6 +212,10 @@
}
}
+ float getRotationX() const {
+ return mRotationX;
+ }
+
void setRotationY(float rotationY) {
if (rotationY != mRotationY) {
mRotationY = rotationY;
@@ -195,6 +228,10 @@
}
}
+ float getRotationY() const {
+ return mRotationY;
+ }
+
void setScaleX(float scaleX) {
if (scaleX != mScaleX) {
mScaleX = scaleX;
@@ -207,6 +244,10 @@
}
}
+ float getScaleX() const {
+ return mScaleX;
+ }
+
void setScaleY(float scaleY) {
if (scaleY != mScaleY) {
mScaleY = scaleY;
@@ -219,6 +260,10 @@
}
}
+ float getScaleY() const {
+ return mScaleY;
+ }
+
void setPivotX(float pivotX) {
mPivotX = pivotX;
mMatrixDirty = true;
@@ -230,6 +275,8 @@
mPivotExplicitlySet = true;
}
+ ANDROID_API float getPivotX();
+
void setPivotY(float pivotY) {
mPivotY = pivotY;
mMatrixDirty = true;
@@ -241,6 +288,8 @@
mPivotExplicitlySet = true;
}
+ ANDROID_API float getPivotY();
+
void setCameraDistance(float distance) {
if (distance != mCameraDistance) {
mCameraDistance = distance;
@@ -253,6 +302,10 @@
}
}
+ float getCameraDistance() const {
+ return mCameraDistance;
+ }
+
void setLeft(int left) {
if (left != mLeft) {
mLeft = left;
@@ -263,6 +316,10 @@
}
}
+ float getLeft() const {
+ return mLeft;
+ }
+
void setTop(int top) {
if (top != mTop) {
mTop = top;
@@ -273,6 +330,10 @@
}
}
+ float getTop() const {
+ return mTop;
+ }
+
void setRight(int right) {
if (right != mRight) {
mRight = right;
@@ -283,6 +344,10 @@
}
}
+ float getRight() const {
+ return mRight;
+ }
+
void setBottom(int bottom) {
if (bottom != mBottom) {
mBottom = bottom;
@@ -293,6 +358,10 @@
}
}
+ float getBottom() const {
+ return mBottom;
+ }
+
void setLeftTop(int left, int top) {
if (left != mLeft || top != mTop) {
mLeft = left;
@@ -319,7 +388,7 @@
}
}
- void offsetLeftRight(int offset) {
+ void offsetLeftRight(float offset) {
if (offset != 0) {
mLeft += offset;
mRight += offset;
@@ -329,7 +398,7 @@
}
}
- 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 d11558f..e5fd7b9 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -280,7 +280,7 @@
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);
}
}