Home | History | Annotate | Download | only in graphics
      1 page.title=Hardware Acceleration
      2 parent.title=Graphics
      3 parent.link=index.html
      4 @jd:body
      5 
      6 
      7   <div id="qv-wrapper">
      8     <div id="qv">
      9       <h2>In this document</h2>
     10 
     11       <ol>
     12         <li><a href="#controlling">Controlling Hardware Acceleration</a></li>
     13         <li><a href="#determining">Determining if a View is Hardware Accelerated</a></li>
     14         <li><a href="#model">Android Drawing Models</a>
     15 
     16           <ol>
     17             <li><a href="#software-model">Software-based drawing model</a></li>
     18             <li><a href="#hardware-model">Hardware accelerated drawing model</a></li>
     19           </ol>
     20         </li>
     21 
     22         <li>
     23           <a href="#unsupported">Unsupported Drawing Operations</a>
     24         </li>
     25 
     26 
     27 
     28         <li>
     29           <a href="#layers">View Layers</a>
     30 
     31           <ol>
     32             <li><a href="#layers-anims">View Layers and Animations</a></li>
     33           </ol>
     34         </li>
     35 
     36         <li><a href="#tips">Tips and Tricks</a></li>
     37       </ol>
     38 
     39       <h2>See also</h2>
     40 
     41       <ol>
     42         <li><a href="{@docRoot}guide/topics/graphics/opengl.html">OpenGL with the Framework
     43         APIs</a></li>
     44 
     45         <li><a href="{@docRoot}guide/topics/renderscript/index.html">RenderScript</a></li>
     46       </ol>
     47     </div>
     48   </div>
     49 
     50   <p>Beginning in Android 3.0 (API level 11), the Android 2D rendering pipeline is designed to
     51   better support hardware acceleration. Hardware acceleration carries out all drawing operations
     52   that are performed on a {@link android.view.View}'s canvas using the GPU.</p>
     53 
     54   <p>The easiest way to enable hardware acceleration is to turn it on
     55   globally for your entire application. If your application uses only standard views and {@link
     56   android.graphics.drawable.Drawable}s, turning it on globally should not cause any adverse
     57   effects. However, because hardware acceleration is not supported for all of the 2D drawing
     58   operations, turning it on might affect some of your applications that use custom views or drawing
     59   calls. Problems usually manifest themselves as invisible elements, exceptions, or wrongly
     60   rendered pixels. To remedy this, Android gives you the option to enable or disable hardware
     61   acceleration at the following levels:</p>
     62 
     63   <ul>
     64     <li>Application</li>
     65 
     66     <li>Activity</li>
     67 
     68     <li>Window</li>
     69 
     70     <li>View</li>
     71   </ul>
     72 
     73   <p>If your application performs custom drawing, test your application on actual hardware
     74 devices with hardware acceleration turned on to find any problems. The <a
     75 href="#drawing-support">Unsupported drawing operations</a> section describes known issues with
     76 drawing operations that cannot be hardware accelerated and how to work around them.</p>
     77 
     78 
     79  <h2 id="controlling">Controlling Hardware Acceleration</h2>
     80   <p>You can control hardware acceleration at the following levels:</p>
     81   <ul>
     82     <li>Application</li>
     83 
     84     <li>Activity</li>
     85 
     86     <li>Window</li>
     87 
     88     <li>View</li>
     89   </ul>
     90 
     91   <h4>Application level</h4>
     92   <p>In your Android manifest file, add the following attribute to the
     93   <a href="{@docRoot}guide/topics/manifest/application-element.html">
     94     <code>&lt;application&gt;</code></a> tag to enable hardware acceleration for your entire
     95   application:</p>
     96 
     97 <pre>
     98 &lt;application android:hardwareAccelerated="true" ...&gt;
     99 </pre>
    100 
    101   <h4>Activity level</h4>
    102   <p>If your application does not behave properly with hardware acceleration turned on globally,
    103   you can control it for individual activities as well. To enable or disable hardware acceleration
    104   at the  activity level, you can use the <code>android:hardwareAccelerated</code>
    105   attribute for the <a href="{@docRoot}guide/topics/manifest/activity-element.html">
    106     <code>&lt;activity&gt;</code></a> element. The following example enables hardware acceleration
    107 for the  entire application but disables it for one activity:</p>
    108 
    109 <pre>
    110 &lt;application android:hardwareAccelerated="true"&gt;
    111     &lt;activity ... /&gt;
    112     &lt;activity android:hardwareAccelerated="false" /&gt;
    113 &lt;/application&gt;
    114 </pre>
    115 
    116   <h4>Window level</h4>
    117   <p>If you need even more fine-grained control, you can enable hardware acceleration for a given
    118   window with the following code:</p>
    119 
    120 <pre>
    121 getWindow().setFlags(
    122     WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
    123     WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
    124 
    125 </pre>
    126 
    127 <p class="note"><strong>Note</strong>:  You currently cannot disable hardware acceleration at
    128 the window level.</p>
    129 
    130   <h4>View level</h4>
    131 
    132   <p>You can disable hardware acceleration for an individual view at runtime with the
    133 following code:</p>
    134 
    135 <pre>
    136 myView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
    137 </pre>
    138 
    139 <p class="note"><strong>Note</strong>: You currently cannot enable hardware acceleration at
    140 the view level. View layers have other functions besides disabling hardware acceleration. See <a
    141 href="#layers">View layers</a> for more information about their uses.</p>
    142 
    143   <h2 id="determining">Determining if a View is Hardware Accelerated</h2>
    144 
    145   <p>It is sometimes useful for an application to know whether it is currently hardware
    146   accelerated, especially for things such as custom views. This is particularly useful if your
    147   application does a lot of custom drawing and not all operations are properly supported by the new
    148   rendering pipeline.</p>
    149 
    150   <p>There are two different ways to check whether the application is hardware accelerated:</p>
    151 
    152   <ul>
    153     <li>{@link android.view.View#isHardwareAccelerated View.isHardwareAccelerated()} returns
    154     <code>true</code> if the {@link android.view.View} is attached to a hardware accelerated
    155     window.</li>
    156 
    157     <li>{@link android.graphics.Canvas#isHardwareAccelerated Canvas.isHardwareAccelerated()}
    158     returns <code>true</code> if the {@link android.graphics.Canvas} is hardware accelerated</li>
    159   </ul>
    160 
    161   <p>If you must do this check in your drawing code, use {@link
    162   android.graphics.Canvas#isHardwareAccelerated Canvas.isHardwareAccelerated()} instead of {@link
    163   android.view.View#isHardwareAccelerated View.isHardwareAccelerated()} when possible. When a view
    164   is attached to a hardware accelerated window, it can still be drawn using a non-hardware
    165   accelerated Canvas. This happens, for instance, when drawing a view into a bitmap for caching
    166   purposes.</p>
    167 
    168 
    169   <h2 id="model">Android Drawing Models</h2>
    170 
    171   <p>When hardware acceleration is enabled, the Android framework utilizes a new drawing model that
    172   utilizes <em>display lists</em> to render your application to the screen. To fully understand
    173   display lists and how they might affect your application, it is useful to understand how Android
    174   draws views without hardware acceleration as well. The following sections describe the
    175   software-based  and hardware-accelerated drawing models.</p>
    176 
    177 <h3>Software-based drawing model</h3>
    178 <p>In the software drawing model, views are drawn with the following two steps:</p>
    179   <ol>
    180     <li>Invalidate the hierarchy</li>
    181 
    182     <li>Draw the hierarchy</li>
    183   </ol>
    184 
    185   <p>Whenever an application needs to update a part of its UI, it invokes {@link
    186   android.view.View#invalidate invalidate()} (or one of its variants) on any view that has changed
    187   content. The invalidation messages are propagated all the way up the view hierarchy to compute
    188   the regions of the screen that need to be redrawn (the dirty region). The Android system then
    189   draws any view in the hierarchy that intersects with the dirty region. Unfortunately, there are
    190   two drawbacks to this drawing model:</p>
    191   <ul>
    192     <li>First, this model requires execution of a lot of code on every draw pass. For example, if
    193 your application calls {@link android.view.View#invalidate invalidate()} on a button and that
    194 button sits on top of another view, the Android system redraws the view even though it hasn't
    195 changed.</li>
    196     <li>The second issue is that the drawing model can hide bugs in your application. Since the
    197   Android system redraws views when they intersect the dirty region, a view whose content you
    198   changed might be redrawn even though {@link android.view.View#invalidate invalidate()} was not
    199   called on it. When this happens, you are relying on another view being invalidated to obtain the
    200   proper behavior. This behavior can change every time you modify your application. Because of
    201   this, you should always call {@link android.view.View#invalidate invalidate()} on your custom
    202   views whenever you modify data or state that affects the views drawing code.</li>
    203 </ul>
    204 
    205   <p class="note"><strong>Note</strong>: Android views automatically call {@link
    206   android.view.View#invalidate invalidate()} when their properties change, such as the background
    207   color or the text in a {@link android.widget.TextView}.</p>
    208 
    209   <h3>Hardware accelerated drawing model</h3>
    210   <p>The Android system still uses {@link android.view.View#invalidate invalidate()} and {@link
    211   android.view.View#draw draw()} to request screen updates and to render views, but handles the
    212   actual drawing differently. Instead of executing the drawing commands immediately, the Android
    213   system records them inside display lists, which contain the output of the view hierarchys
    214   drawing code. Another optimization is that the Android system only needs to record and update
    215   display lists for views marked dirty by an {@link android.view.View#invalidate invalidate()}
    216   call. Views that have not been invalidated can be redrawn simply by re-issuing the previously
    217   recorded display list. The new drawing model contains three stages:</p>
    218 
    219   <ol>
    220     <li>Invalidate the hierarchy</li>
    221 
    222     <li>Record and update display lists</li>
    223 
    224     <li>Draw the display lists</li>
    225   </ol>
    226 
    227   <p>With this model, you cannot rely on a view intersecting the dirty region to have its {@link
    228   android.view.View#draw draw()} method executed. To ensure that the Android system records a
    229   views display list, you must call {@link android.view.View#invalidate invalidate()}. Forgetting
    230   to do so causes a view to look the same even after changing it, which is an easier bug to find if
    231   it happens.</p>
    232 
    233   <p>Using display lists also benefits animation performance because setting specific properties,
    234   such as alpha or rotation, does not require invalidating the targeted view (it is done
    235   automatically). This optimization also applies to views with display lists (any view when your
    236   application is hardware accelerated.) For example, assume there is a {@link
    237   android.widget.LinearLayout} that contains a {@link android.widget.ListView} above a {@link
    238   android.widget.Button}. The display list for the {@link android.widget.LinearLayout} looks like
    239   this:</p>
    240 
    241   <ul>
    242     <li>DrawDisplayList(ListView)</li>
    243 
    244     <li>DrawDisplayList(Button)</li>
    245   </ul>
    246 
    247   <p>Assume now that you want to change the {@link android.widget.ListView}'s opacity. After
    248   invoking <code>setAlpha(0.5f)</code> on the {@link android.widget.ListView}, the display list now
    249   contains this:</p>
    250 
    251   <ul>
    252     <li>SaveLayerAlpha(0.5)</li>
    253 
    254     <li>DrawDisplayList(ListView)</li>
    255 
    256     <li>Restore</li>
    257 
    258     <li>DrawDisplayList(Button)</li>
    259   </ul>
    260 
    261   <p>The complex drawing code of {@link android.widget.ListView} was not executed. Instead, the
    262   system only updated the display list of the much simpler {@link android.widget.LinearLayout}. In
    263   an application without hardware acceleration enabled, the drawing code of both the list and its
    264   parent are executed again.</p>
    265 
    266   <h2 id="unsupported">Unsupported Drawing Operations</h2>
    267 
    268   <p>When hardware accelerated, the 2D rendering pipeline supports the most commonly used {@link
    269   android.graphics.Canvas} drawing operations as well as many less-used operations. All of the
    270   drawing operations that are used to render applications that ship with Android, default widgets
    271   and layouts, and common advanced visual effects such as reflections and tiled textures are
    272   supported. The following list describes known operations that are <strong>not supported</strong>
    273   with hardware acceleration:</p>
    274 
    275   <ul>
    276     <li>
    277       <strong>Canvas</strong>
    278 
    279       <ul>
    280         <li>{@link android.graphics.Canvas#clipPath clipPath()}</li>
    281 
    282         <li>{@link android.graphics.Canvas#clipRegion clipRegion()}</li>
    283 
    284         <li>{@link android.graphics.Canvas#drawPicture drawPicture()}</li>
    285 
    286         <li>{@link android.graphics.Canvas#drawPosText drawPosText()}</li>
    287 
    288         <li>{@link android.graphics.Canvas#drawTextOnPath drawTextOnPath()}</li>
    289 
    290         <li>{@link android.graphics.Canvas#drawVertices drawVertices()}</li>
    291       </ul>
    292     </li>
    293 
    294     <li>
    295       <strong>Paint</strong>
    296 
    297       <ul>
    298         <li>{@link android.graphics.Paint#setLinearText setLinearText()}</li>
    299 
    300         <li>{@link android.graphics.Paint#setMaskFilter setMaskFilter()}</li>
    301 
    302         <li>{@link android.graphics.Paint#setRasterizer setRasterizer()}</li>
    303       </ul>
    304     </li>
    305   </ul>
    306 
    307   <p>In addition, some operations behave differently with hardware acceleration enabled:</p>
    308 
    309   <ul>
    310     <li>
    311       <strong>Canvas</strong>
    312 
    313       <ul>
    314         <li>{@link android.graphics.Canvas#clipRect clipRect()}: <code>XOR</code>,
    315         <code>Difference</code> and <code>ReverseDifference</code> clip modes are ignored. 3D
    316         transforms do not apply to the clip rectangle</li>
    317 
    318         <li>{@link android.graphics.Canvas#drawBitmapMesh drawBitmapMesh()}: colors array is
    319         ignored</li>
    320 
    321         <li>{@link android.graphics.Canvas#drawLines drawLines()}: anti-aliasing is not
    322         supported</li>
    323 
    324         <li>{@link android.graphics.Canvas#setDrawFilter setDrawFilter()}: can be set, but is
    325         ignored</li>
    326       </ul>
    327     </li>
    328 
    329     <li>
    330       <strong>Paint</strong>
    331 
    332       <ul>
    333         <li>{@link android.graphics.Paint#setDither setDither()}: ignored</li>
    334 
    335         <li>{@link android.graphics.Paint#setFilterBitmap setFilterBitmap()}: filtering is always
    336         on</li>
    337 
    338         <li>{@link android.graphics.Paint#setShadowLayer setShadowLayer()}: works with text
    339         only</li>
    340       </ul>
    341     </li>
    342 
    343     <li>
    344       <strong>ComposeShader</strong>
    345 
    346       <ul>
    347         <li>{@link android.graphics.ComposeShader} can only contain shaders of different types (a
    348         {@link android.graphics.BitmapShader} and a {@link android.graphics.LinearGradient} for
    349         instance, but not two instances of {@link android.graphics.BitmapShader} )</li>
    350 
    351         <li>{@link android.graphics.ComposeShader} cannot contain a {@link
    352         android.graphics.ComposeShader}</li>
    353       </ul>
    354     </li>
    355   </ul>
    356 
    357   <p>If your application is affected by any of these missing features or limitations, you can turn
    358   off hardware acceleration for just the affected portion of your application by calling
    359   {@link android.view.View#setLayerType setLayerType(View.LAYER_TYPE_SOFTWARE, null)}. This way,
    360 you can still take advantage of hardware acceleratin everywhere else. See <a
    361 href="#controlling">Controlling Hardware Acceleration</a> for more information on how to enable and
    362 disable hardware acceleration at different levels in your application.
    363 
    364 
    365 
    366   <h2 id="layers">View Layers</h2>
    367 
    368   <p>In all versions of Android, views have had the ability to render into off-screen buffers,
    369 either by using a view's drawing cache, or by using {@link android.graphics.Canvas#saveLayer
    370   Canvas.saveLayer()}. Off-screen buffers, or layers, have several uses. You can use them to get
    371   better performance when animating complex views or to apply composition effects. For instance,
    372   you can implement fade effects using <code>Canvas.saveLayer()</code> to temporarily render a view
    373   into a layer and then composite it back on screen with an opacity factor.</p>
    374 
    375   <p>Beginning in Android 3.0 (API level 11), you have more control on how and when to use layers
    376   with the {@link android.view.View#setLayerType View.setLayerType()} method. This API takes two
    377   parameters: the type of layer you want to use and an optional {@link android.graphics.Paint}
    378   object that describes how the layer should be composited. You can use the {@link
    379   android.graphics.Paint} parameter to apply color filters, special blending modes, or opacity to a
    380   layer. A view can use one of three layer types:</p>
    381 
    382   <ul>
    383     <li>{@link android.view.View#LAYER_TYPE_NONE}: The view is rendered normally and is not backed
    384     by an off-screen buffer. This is the default behavior.</li>
    385 
    386     <li>{@link android.view.View#LAYER_TYPE_HARDWARE}: The view is rendered in hardware into a
    387     hardware texture if the application is hardware accelerated. If the application is not hardware
    388     accelerated, this layer type behaves the same as {@link
    389     android.view.View#LAYER_TYPE_SOFTWARE}.</li>
    390 
    391     <li>{@link android.view.View#LAYER_TYPE_SOFTWARE}: The view is rendered in software into a
    392     bitmap.</li>
    393   </ul>
    394 
    395   <p>The type of layer you use depends on your goal:</p>
    396 
    397   <ul>
    398     <li><strong>Performance</strong>: Use a hardware layer type to render a view into a hardware
    399     texture. Once a view is rendered into a layer, its drawing code does not have to be executed
    400     until the view calls {@link android.view.View#invalidate invalidate()}. Some animations, such as
    401     alpha animations, can then be applied directly onto the layer, which is very efficient
    402     for the GPU to do.</li>
    403 
    404     <li><strong>Visual effects</strong>: Use a hardware or software layer type and a {@link
    405     android.graphics.Paint} to apply special visual treatments to a view. For instance, you can
    406     draw a view in black and white using a {@link
    407     android.graphics.ColorMatrixColorFilter}.</li>
    408 
    409     <li><strong>Compatibility</strong>: Use a software layer type to force a view to be rendered in
    410     software. If a view that is hardware accelerated (for instance, if your whole
    411     application is hardware acclerated), is having rendering problems, this is an easy way to work
    412 around limitations of the hardware rendering
    413     pipeline.</li>
    414   </ul>
    415 
    416   <h3 id="layers-anims">View layers and animations</h3>
    417 
    418   <p>Hardware layers can deliver faster and smoother animations when your application
    419 is hardware accelerated. Running an animation at 60 frames per second is not always possible when
    420 animating complex views that issue a lot of drawing operations. This can be alleviated by
    421 using hardware layers to render the view to a hardware texture. The hardware texture can
    422 then be used to animate the view, eliminating the need for the view to constantly redraw itself
    423 when it is being animated. The view is not redrawn unless you change the view's
    424 properties, which calls {@link android.view.View#invalidate invalidate()}, or if you call {@link
    425 android.view.View#invalidate invalidate()} manually. If you are running an animation in
    426 your application and do not obtain the smooth results you want, consider enabling hardware layers on
    427 your animated views.</p>
    428 
    429   <p>When a view is backed by a hardware layer, some of its properties are handled by the way the
    430   layer is composited on screen. Setting these properties will be efficient because they do not
    431   require the view to be invalidated and redrawn. The following list of properties affect the way
    432   the layer is composited. Calling the setter for any of these properties results in optimal
    433   invalidation and no redrawing of the targeted view:</p>
    434 
    435   <ul>
    436     <li><code>alpha</code>: Changes the layer's opacity</li>
    437 
    438     <li><code>x</code>, <code>y</code>, <code>translationX</code>, <code>translationY</code>:
    439 Changes the layer's position</li>
    440 
    441     <li><code>scaleX</code>, <code>scaleY</code>: Changes the layer's size</li>
    442 
    443     <li><code>rotation</code>, <code>rotationX</code>, <code>rotationY</code>: Changes the
    444     layer's orientation in 3D space</li>
    445 
    446     <li><code>pivotX</code>, <code>pivotY</code>: Changes the layer's transformations origin</li>
    447   </ul>
    448 
    449   <p>These properties are the names used when animating a view with an {@link
    450   android.animation.ObjectAnimator}. If you want to access these properties, call the appropriate
    451   setter or getter. For instance, to modify the alpha property, call {@link
    452   android.view.View#setAlpha setAlpha()}. The following code snippet shows the most efficient way
    453   to rotate a viewiew in 3D around the Y-axis:</p>
    454   <pre>
    455 view.setLayerType(View.LAYER_TYPE_HARDWARE, null);
    456 ObjectAnimator.ofFloat(view, "rotationY", 180).start();
    457 </pre>
    458 
    459   <p>Because hardware layers consume video memory, it is highly recommended that you enable them
    460 only for the duration of the animation and then disable them after the animation is done. You
    461 can accomplish this using animation listeners:</p>
    462   <pre>
    463 View.setLayerType(View.LAYER_TYPE_HARDWARE, null);
    464 ObjectAnimator animator = ObjectAnimator.ofFloat(view, "rotationY", 180);
    465 animator.addListener(new AnimatorListenerAdapter() {
    466     &#064;Override
    467     public void onAnimationEnd(Animator animation) {
    468         view.setLayerType(View.LAYER_TYPE_NONE, null);
    469     }
    470 });
    471 animator.start();
    472 </pre>
    473 
    474   <p>For more information on property animation, see <a href=
    475   "{@docRoot}guide/topics/graphics/prop-animation.html">Property Animation</a>.</p>
    476 
    477  <h2 id="tips">Tips and Tricks</h2>
    478 
    479   <p>Switching to hardware accelerated 2D graphics can instantly increase performance, but you
    480   should still design your application to use the GPU effectively by following these
    481   recommendations:</p>
    482 
    483   <dl>
    484     <dt><strong>Reduce the number of views in your application</strong></dt>
    485 
    486     <dd>The more views the system has to draw, the slower it will be. This applies to the software
    487     rendering pipeline as well. Reducing views is one of the easiest ways to optimize your UI.</dd>
    488 
    489     <dt><strong>Avoid overdraw</strong></dt>
    490 
    491     <dd>Do not draw too many layers on top of each other. Remove any views that are completely
    492     obscured by other opaque views on top of it. If you need to draw several layers blended on top
    493     of each other, consider merging them into a single layer. A good rule of thumb with current
    494     hardware is to not draw more than 2.5 times the number of pixels on screen per frame
    495     (transparent pixels in a bitmap count!).</dd>
    496 
    497     <dt><strong>Don't create render objects in draw methods</strong></dt>
    498 
    499     <dd>A common mistake is to create a new {@link android.graphics.Paint} or a new {@link
    500 android.graphics.Path} every time a rendering method is invoked. This forces the garbage
    501 collector to run more often and also bypasses caches and optimizations in the hardware
    502 pipeline.</dd>
    503 
    504     <dt><strong>Don't modify shapes too often</strong></dt>
    505 
    506     <dd>Complex shapes, paths, and circles for instance, are rendered using texture masks. Every
    507     time you create or modify a path, the hardware pipeline creates a new mask, which can be
    508     expensive.</dd>
    509 
    510     <dt><strong>Don't modify bitmaps too often</strong></dt>
    511 
    512     <dd>Every time you change the content of a bitmap, it is uploaded again as a GPU texture the
    513     next time you draw it.</dd>
    514 
    515     <dt><strong>Use alpha with care</strong></dt>
    516 
    517     <dd>When you make a view translucent using {@link android.view.View#setAlpha setAlpha()},
    518     {@link android.view.animation.AlphaAnimation}, or {@link android.animation.ObjectAnimator}, it
    519     is rendered in an off-screen buffer which doubles the required fill-rate. When applying alpha
    520     on very large views, consider setting the view's layer type to
    521     <code>LAYER_TYPE_HARDWARE</code>.</dd>
    522   </dl>
    523