Home | History | Annotate | Download | only in view
      1 /*
      2  * Copyright (C) 2010 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package android.view;
     18 
     19 import android.graphics.Matrix;
     20 
     21 /**
     22  * <p>A display list records a series of graphics related operations and can replay
     23  * them later. Display lists are usually built by recording operations on a
     24  * {@link HardwareCanvas}. Replaying the operations from a display list avoids
     25  * executing application code on every frame, and is thus much more efficient.</p>
     26  *
     27  * <p>Display lists are used internally for all views by default, and are not
     28  * typically used directly. One reason to consider using a display is a custom
     29  * {@link View} implementation that needs to issue a large number of drawing commands.
     30  * When the view invalidates, all the drawing commands must be reissued, even if
     31  * large portions of the drawing command stream stay the same frame to frame, which
     32  * can become a performance bottleneck. To solve this issue, a custom View might split
     33  * its content into several display lists. A display list is updated only when its
     34  * content, and only its content, needs to be updated.</p>
     35  *
     36  * <p>A text editor might for instance store each paragraph into its own display list.
     37  * Thus when the user inserts or removes characters, only the display list of the
     38  * affected paragraph needs to be recorded again.</p>
     39  *
     40  * <h3>Hardware acceleration</h3>
     41  * <p>Display lists can only be replayed using a {@link HardwareCanvas}. They are not
     42  * supported in software. Always make sure that the {@link android.graphics.Canvas}
     43  * you are using to render a display list is hardware accelerated using
     44  * {@link android.graphics.Canvas#isHardwareAccelerated()}.</p>
     45  *
     46  * <h3>Creating a display list</h3>
     47  * <pre class="prettyprint">
     48  *     HardwareRenderer renderer = myView.getHardwareRenderer();
     49  *     if (renderer != null) {
     50  *         DisplayList displayList = renderer.createDisplayList();
     51  *         HardwareCanvas canvas = displayList.start(width, height);
     52  *         try {
     53  *             // Draw onto the canvas
     54  *             // For instance: canvas.drawBitmap(...);
     55  *         } finally {
     56  *             displayList.end();
     57  *         }
     58  *     }
     59  * </pre>
     60  *
     61  * <h3>Rendering a display list on a View</h3>
     62  * <pre class="prettyprint">
     63  *     protected void onDraw(Canvas canvas) {
     64  *         if (canvas.isHardwareAccelerated()) {
     65  *             HardwareCanvas hardwareCanvas = (HardwareCanvas) canvas;
     66  *             hardwareCanvas.drawDisplayList(mDisplayList);
     67  *         }
     68  *     }
     69  * </pre>
     70  *
     71  * <h3>Releasing resources</h3>
     72  * <p>This step is not mandatory but recommended if you want to release resources
     73  * held by a display list as soon as possible.</p>
     74  * <pre class="prettyprint">
     75  *     // Mark this display list invalid, it cannot be used for drawing anymore,
     76  *     // and release resources held by this display list
     77  *     displayList.clear();
     78  * </pre>
     79  *
     80  * <h3>Properties</h3>
     81  * <p>In addition, a display list offers several properties, such as
     82  * {@link #setScaleX(float)} or {@link #setLeft(int)}, that can be used to affect all
     83  * the drawing commands recorded within. For instance, these properties can be used
     84  * to move around a large number of images without re-issuing all the individual
     85  * <code>drawBitmap()</code> calls.</p>
     86  *
     87  * <pre class="prettyprint">
     88  *     private void createDisplayList() {
     89  *         HardwareRenderer renderer = getHardwareRenderer();
     90  *         if (renderer != null) {
     91  *             mDisplayList = renderer.createDisplayList();
     92  *             HardwareCanvas canvas = mDisplayList.start(width, height);
     93  *             try {
     94  *                 for (Bitmap b : mBitmaps) {
     95  *                     canvas.drawBitmap(b, 0.0f, 0.0f, null);
     96  *                     canvas.translate(0.0f, b.getHeight());
     97  *                 }
     98  *             } finally {
     99  *                 displayList.end();
    100  *             }
    101  *         }
    102  *     }
    103  *
    104  *     protected void onDraw(Canvas canvas) {
    105  *         if (canvas.isHardwareAccelerated()) {
    106  *             HardwareCanvas hardwareCanvas = (HardwareCanvas) canvas;
    107  *             hardwareCanvas.drawDisplayList(mDisplayList);
    108  *         }
    109  *     }
    110  *
    111  *     private void moveContentBy(int x) {
    112  *          // This will move all the bitmaps recorded inside the display list
    113  *          // by x pixels to the right and redraw this view. All the commands
    114  *          // recorded in createDisplayList() won't be re-issued, only onDraw()
    115  *          // will be invoked and will execute very quickly
    116  *          mDisplayList.offsetLeftAndRight(x);
    117  *          invalidate();
    118  *     }
    119  * </pre>
    120  *
    121  * <h3>Threading</h3>
    122  * <p>Display lists must be created on and manipulated from the UI thread only.</p>
    123  *
    124  * @hide
    125  */
    126 public abstract class DisplayList {
    127     private boolean mDirty;
    128 
    129     /**
    130      * Flag used when calling
    131      * {@link HardwareCanvas#drawDisplayList(DisplayList, android.graphics.Rect, int)}
    132      * When this flag is set, draw operations lying outside of the bounds of the
    133      * display list will be culled early. It is recommeneded to always set this
    134      * flag.
    135      *
    136      * @hide
    137      */
    138     public static final int FLAG_CLIP_CHILDREN = 0x1;
    139 
    140     // NOTE: The STATUS_* values *must* match the enum in DrawGlInfo.h
    141 
    142     /**
    143      * Indicates that the display list is done drawing.
    144      *
    145      * @see HardwareCanvas#drawDisplayList(DisplayList, android.graphics.Rect, int)
    146      *
    147      * @hide
    148      */
    149     public static final int STATUS_DONE = 0x0;
    150 
    151     /**
    152      * Indicates that the display list needs another drawing pass.
    153      *
    154      * @see HardwareCanvas#drawDisplayList(DisplayList, android.graphics.Rect, int)
    155      *
    156      * @hide
    157      */
    158     public static final int STATUS_DRAW = 0x1;
    159 
    160     /**
    161      * Indicates that the display list needs to re-execute its GL functors.
    162      *
    163      * @see HardwareCanvas#drawDisplayList(DisplayList, android.graphics.Rect, int)
    164      * @see HardwareCanvas#callDrawGLFunction(int)
    165      *
    166      * @hide
    167      */
    168     public static final int STATUS_INVOKE = 0x2;
    169 
    170     /**
    171      * Indicates that the display list performed GL drawing operations.
    172      *
    173      * @see HardwareCanvas#drawDisplayList(DisplayList, android.graphics.Rect, int)
    174      *
    175      * @hide
    176      */
    177     public static final int STATUS_DREW = 0x4;
    178 
    179     /**
    180      * Starts recording the display list. All operations performed on the
    181      * returned canvas are recorded and stored in this display list.
    182      *
    183      * Calling this method will mark the display list invalid until
    184      * {@link #end()} is called. Only valid display lists can be replayed.
    185      *
    186      * @param width The width of the display list's viewport
    187      * @param height The height of the display list's viewport
    188      *
    189      * @return A canvas to record drawing operations.
    190      *
    191      * @see #end()
    192      * @see #isValid()
    193      */
    194     public abstract HardwareCanvas start(int width, int height);
    195 
    196     /**
    197      * Ends the recording for this display list. A display list cannot be
    198      * replayed if recording is not finished. Calling this method marks
    199      * the display list valid and {@link #isValid()} will return true.
    200      *
    201      * @see #start(int, int)
    202      * @see #isValid()
    203      */
    204     public abstract void end();
    205 
    206     /**
    207      * Clears resources held onto by this display list. After calling this method
    208      * {@link #isValid()} will return false.
    209      *
    210      * @see #isValid()
    211      * @see #reset()
    212      */
    213     public abstract void clear();
    214 
    215 
    216     /**
    217      * Reset native resources. This is called when cleaning up the state of display lists
    218      * during destruction of hardware resources, to ensure that we do not hold onto
    219      * obsolete resources after related resources are gone.
    220      *
    221      * @see #clear()
    222      *
    223      * @hide
    224      */
    225     public abstract void reset();
    226 
    227     /**
    228      * Sets the dirty flag. When a display list is dirty, {@link #clear()} should
    229      * be invoked whenever possible.
    230      *
    231      * @see #isDirty()
    232      * @see #clear()
    233      *
    234      * @hide
    235      */
    236     public void markDirty() {
    237         mDirty = true;
    238     }
    239 
    240     /**
    241      * Removes the dirty flag. This method can be used to cancel a cleanup
    242      * previously scheduled by setting the dirty flag.
    243      *
    244      * @see #isDirty()
    245      * @see #clear()
    246      *
    247      * @hide
    248      */
    249     protected void clearDirty() {
    250         mDirty = false;
    251     }
    252 
    253     /**
    254      * Indicates whether the display list is dirty.
    255      *
    256      * @see #markDirty()
    257      * @see #clear()
    258      *
    259      * @hide
    260      */
    261     public boolean isDirty() {
    262         return mDirty;
    263     }
    264 
    265     /**
    266      * Returns whether the display list is currently usable. If this returns false,
    267      * the display list should be re-recorded prior to replaying it.
    268      *
    269      * @return boolean true if the display list is able to be replayed, false otherwise.
    270      */
    271     public abstract boolean isValid();
    272 
    273     /**
    274      * Return the amount of memory used by this display list.
    275      *
    276      * @return The size of this display list in bytes
    277      *
    278      * @hide
    279      */
    280     public abstract int getSize();
    281 
    282     ///////////////////////////////////////////////////////////////////////////
    283     // DisplayList Property Setters
    284     ///////////////////////////////////////////////////////////////////////////
    285 
    286     /**
    287      * Set the caching property on the display list, which indicates whether the display list
    288      * holds a layer. Layer display lists should avoid creating an alpha layer, since alpha is
    289      * handled in the drawLayer operation directly (and more efficiently).
    290      *
    291      * @param caching true if the display list represents a hardware layer, false otherwise.
    292      *
    293      * @hide
    294      */
    295     public abstract void setCaching(boolean caching);
    296 
    297     /**
    298      * Set whether the display list should clip itself to its bounds. This property is controlled by
    299      * the view's parent.
    300      *
    301      * @param clipToBounds true if the display list should clip to its bounds
    302      */
    303     public abstract void setClipToBounds(boolean clipToBounds);
    304 
    305     /**
    306      * Set the static matrix on the display list. The specified matrix is combined with other
    307      * transforms (such as {@link #setScaleX(float)}, {@link #setRotation(float)}, etc.)
    308      *
    309      * @param matrix A transform matrix to apply to this display list
    310      *
    311      * @see #getMatrix(android.graphics.Matrix)
    312      * @see #getMatrix()
    313      */
    314     public abstract void setMatrix(Matrix matrix);
    315 
    316     /**
    317      * Returns the static matrix set on this display list.
    318      *
    319      * @return A new {@link Matrix} instance populated with this display list's static
    320      *         matrix
    321      *
    322      * @see #getMatrix(android.graphics.Matrix)
    323      * @see #setMatrix(android.graphics.Matrix)
    324      */
    325     public Matrix getMatrix() {
    326         return getMatrix(new Matrix());
    327     }
    328 
    329     /**
    330      * Copies this display list's static matrix into the specified matrix.
    331      *
    332      * @param matrix The {@link Matrix} instance in which to copy this display
    333      *               list's static matrix. Cannot be null
    334      *
    335      * @return The <code>matrix</code> parameter, for convenience
    336      *
    337      * @see #getMatrix()
    338      * @see #setMatrix(android.graphics.Matrix)
    339      */
    340     public abstract Matrix getMatrix(Matrix matrix);
    341 
    342     /**
    343      * Set the Animation matrix on the display list. This matrix exists if an Animation is
    344      * currently playing on a View, and is set on the display list during at draw() time. When
    345      * the Animation finishes, the matrix should be cleared by sending <code>null</code>
    346      * for the matrix parameter.
    347      *
    348      * @param matrix The matrix, null indicates that the matrix should be cleared.
    349      *
    350      * @hide
    351      */
    352     public abstract void setAnimationMatrix(Matrix matrix);
    353 
    354     /**
    355      * Sets the translucency level for the display list.
    356      *
    357      * @param alpha The translucency of the display list, must be a value between 0.0f and 1.0f
    358      *
    359      * @see View#setAlpha(float)
    360      * @see #getAlpha()
    361      */
    362     public abstract void setAlpha(float alpha);
    363 
    364     /**
    365      * Returns the translucency level of this display list.
    366      *
    367      * @return A value between 0.0f and 1.0f
    368      *
    369      * @see #setAlpha(float)
    370      */
    371     public abstract float getAlpha();
    372 
    373     /**
    374      * Sets whether the display list renders content which overlaps. Non-overlapping rendering
    375      * can use a fast path for alpha that avoids rendering to an offscreen buffer. By default
    376      * display lists consider they do not have overlapping content.
    377      *
    378      * @param hasOverlappingRendering False if the content is guaranteed to be non-overlapping,
    379      *                                true otherwise.
    380      *
    381      * @see android.view.View#hasOverlappingRendering()
    382      * @see #hasOverlappingRendering()
    383      */
    384     public abstract void setHasOverlappingRendering(boolean hasOverlappingRendering);
    385 
    386     /**
    387      * Indicates whether the content of this display list overlaps.
    388      *
    389      * @return True if this display list renders content which overlaps, false otherwise.
    390      *
    391      * @see #setHasOverlappingRendering(boolean)
    392      */
    393     public abstract boolean hasOverlappingRendering();
    394 
    395     /**
    396      * Sets the translation value for the display list on the X axis
    397      *
    398      * @param translationX The X axis translation value of the display list, in pixels
    399      *
    400      * @see View#setTranslationX(float)
    401      * @see #getTranslationX()
    402      */
    403     public abstract void setTranslationX(float translationX);
    404 
    405     /**
    406      * Returns the translation value for this display list on the X axis, in pixels.
    407      *
    408      * @see #setTranslationX(float)
    409      */
    410     public abstract float getTranslationX();
    411 
    412     /**
    413      * Sets the translation value for the display list on the Y axis
    414      *
    415      * @param translationY The Y axis translation value of the display list, in pixels
    416      *
    417      * @see View#setTranslationY(float)
    418      * @see #getTranslationY()
    419      */
    420     public abstract void setTranslationY(float translationY);
    421 
    422     /**
    423      * Returns the translation value for this display list on the Y axis, in pixels.
    424      *
    425      * @see #setTranslationY(float)
    426      */
    427     public abstract float getTranslationY();
    428 
    429     /**
    430      * Sets the rotation value for the display list around the Z axis
    431      *
    432      * @param rotation The rotation value of the display list, in degrees
    433      *
    434      * @see View#setRotation(float)
    435      * @see #getRotation()
    436      */
    437     public abstract void setRotation(float rotation);
    438 
    439     /**
    440      * Returns the rotation value for this display list around the Z axis, in degrees.
    441      *
    442      * @see #setRotation(float)
    443      */
    444     public abstract float getRotation();
    445 
    446     /**
    447      * Sets the rotation value for the display list around the X axis
    448      *
    449      * @param rotationX The rotation value of the display list, in degrees
    450      *
    451      * @see View#setRotationX(float)
    452      * @see #getRotationX()
    453      */
    454     public abstract void setRotationX(float rotationX);
    455 
    456     /**
    457      * Returns the rotation value for this display list around the X axis, in degrees.
    458      *
    459      * @see #setRotationX(float)
    460      */
    461     public abstract float getRotationX();
    462 
    463     /**
    464      * Sets the rotation value for the display list around the Y axis
    465      *
    466      * @param rotationY The rotation value of the display list, in degrees
    467      *
    468      * @see View#setRotationY(float)
    469      * @see #getRotationY()
    470      */
    471     public abstract void setRotationY(float rotationY);
    472 
    473     /**
    474      * Returns the rotation value for this display list around the Y axis, in degrees.
    475      *
    476      * @see #setRotationY(float)
    477      */
    478     public abstract float getRotationY();
    479 
    480     /**
    481      * Sets the scale value for the display list on the X axis
    482      *
    483      * @param scaleX The scale value of the display list
    484      *
    485      * @see View#setScaleX(float)
    486      * @see #getScaleX()
    487      */
    488     public abstract void setScaleX(float scaleX);
    489 
    490     /**
    491      * Returns the scale value for this display list on the X axis.
    492      *
    493      * @see #setScaleX(float)
    494      */
    495     public abstract float getScaleX();
    496 
    497     /**
    498      * Sets the scale value for the display list on the Y axis
    499      *
    500      * @param scaleY The scale value of the display list
    501      *
    502      * @see View#setScaleY(float)
    503      * @see #getScaleY()
    504      */
    505     public abstract void setScaleY(float scaleY);
    506 
    507     /**
    508      * Returns the scale value for this display list on the Y axis.
    509      *
    510      * @see #setScaleY(float)
    511      */
    512     public abstract float getScaleY();
    513 
    514     /**
    515      * Sets all of the transform-related values of the display list
    516      *
    517      * @param alpha The alpha value of the display list
    518      * @param translationX The translationX value of the display list
    519      * @param translationY The translationY value of the display list
    520      * @param rotation The rotation value of the display list
    521      * @param rotationX The rotationX value of the display list
    522      * @param rotationY The rotationY value of the display list
    523      * @param scaleX The scaleX value of the display list
    524      * @param scaleY The scaleY value of the display list
    525      *
    526      * @hide
    527      */
    528     public abstract void setTransformationInfo(float alpha, float translationX, float translationY,
    529             float rotation, float rotationX, float rotationY, float scaleX, float scaleY);
    530 
    531     /**
    532      * Sets the pivot value for the display list on the X axis
    533      *
    534      * @param pivotX The pivot value of the display list on the X axis, in pixels
    535      *
    536      * @see View#setPivotX(float)
    537      * @see #getPivotX()
    538      */
    539     public abstract void setPivotX(float pivotX);
    540 
    541     /**
    542      * Returns the pivot value for this display list on the X axis, in pixels.
    543      *
    544      * @see #setPivotX(float)
    545      */
    546     public abstract float getPivotX();
    547 
    548     /**
    549      * Sets the pivot value for the display list on the Y axis
    550      *
    551      * @param pivotY The pivot value of the display list on the Y axis, in pixels
    552      *
    553      * @see View#setPivotY(float)
    554      * @see #getPivotY()
    555      */
    556     public abstract void setPivotY(float pivotY);
    557 
    558     /**
    559      * Returns the pivot value for this display list on the Y axis, in pixels.
    560      *
    561      * @see #setPivotY(float)
    562      */
    563     public abstract float getPivotY();
    564 
    565     /**
    566      * Sets the camera distance for the display list. Refer to
    567      * {@link View#setCameraDistance(float)} for more information on how to
    568      * use this property.
    569      *
    570      * @param distance The distance in Z of the camera of the display list
    571      *
    572      * @see View#setCameraDistance(float)
    573      * @see #getCameraDistance()
    574      */
    575     public abstract void setCameraDistance(float distance);
    576 
    577     /**
    578      * Returns the distance in Z of the camera of the display list.
    579      *
    580      * @see #setCameraDistance(float)
    581      */
    582     public abstract float getCameraDistance();
    583 
    584     /**
    585      * Sets the left position for the display list.
    586      *
    587      * @param left The left position, in pixels, of the display list
    588      *
    589      * @see View#setLeft(int)
    590      * @see #getLeft()
    591      */
    592     public abstract void setLeft(int left);
    593 
    594     /**
    595      * Returns the left position for the display list in pixels.
    596      *
    597      * @see #setLeft(int)
    598      */
    599     public abstract float getLeft();
    600 
    601     /**
    602      * Sets the top position for the display list.
    603      *
    604      * @param top The top position, in pixels, of the display list
    605      *
    606      * @see View#setTop(int)
    607      * @see #getTop()
    608      */
    609     public abstract void setTop(int top);
    610 
    611     /**
    612      * Returns the top position for the display list in pixels.
    613      *
    614      * @see #setTop(int)
    615      */
    616     public abstract float getTop();
    617 
    618     /**
    619      * Sets the right position for the display list.
    620      *
    621      * @param right The right position, in pixels, of the display list
    622      *
    623      * @see View#setRight(int)
    624      * @see #getRight()
    625      */
    626     public abstract void setRight(int right);
    627 
    628     /**
    629      * Returns the right position for the display list in pixels.
    630      *
    631      * @see #setRight(int)
    632      */
    633     public abstract float getRight();
    634 
    635     /**
    636      * Sets the bottom position for the display list.
    637      *
    638      * @param bottom The bottom position, in pixels, of the display list
    639      *
    640      * @see View#setBottom(int)
    641      * @see #getBottom()
    642      */
    643     public abstract void setBottom(int bottom);
    644 
    645     /**
    646      * Returns the bottom position for the display list in pixels.
    647      *
    648      * @see #setBottom(int)
    649      */
    650     public abstract float getBottom();
    651 
    652     /**
    653      * Sets the left and top positions for the display list
    654      *
    655      * @param left The left position of the display list, in pixels
    656      * @param top The top position of the display list, in pixels
    657      * @param right The right position of the display list, in pixels
    658      * @param bottom The bottom position of the display list, in pixels
    659      *
    660      * @see View#setLeft(int)
    661      * @see View#setTop(int)
    662      * @see View#setRight(int)
    663      * @see View#setBottom(int)
    664      */
    665     public abstract void setLeftTopRightBottom(int left, int top, int right, int bottom);
    666 
    667     /**
    668      * Offsets the left and right positions for the display list
    669      *
    670      * @param offset The amount that the left and right positions of the display
    671      *               list are offset, in pixels
    672      *
    673      * @see View#offsetLeftAndRight(int)
    674      */
    675     public abstract void offsetLeftAndRight(float offset);
    676 
    677     /**
    678      * Offsets the top and bottom values for the display list
    679      *
    680      * @param offset The amount that the top and bottom positions of the display
    681      *               list are offset, in pixels
    682      *
    683      * @see View#offsetTopAndBottom(int)
    684      */
    685     public abstract void offsetTopAndBottom(float offset);
    686 }
    687