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