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);
     }
 }