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><application></code></a> tag to enable hardware acceleration for your entire 95 application:</p> 96 97 <pre> 98 <application android:hardwareAccelerated="true" ...> 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><activity></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 <application android:hardwareAccelerated="true"> 111 <activity ... /> 112 <activity android:hardwareAccelerated="false" /> 113 </application> 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 @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