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>&lt;application&gt;</code></a> tag to enable hardware acceleration for your entire
96  application:</p>
97
98<pre>
99&lt;application android:hardwareAccelerated="true" ...&gt;
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>&lt;activity&gt;</code></a> element. The following example enables hardware acceleration
108for the  entire application but disables it for one activity:</p>
109
110<pre>
111&lt;application android:hardwareAccelerated="true"&gt;
112    &lt;activity ... /&gt;
113    &lt;activity android:hardwareAccelerated="false" /&gt;
114&lt;/application&gt;
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    &#064;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