• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.</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
74devices with hardware acceleration turned on to find any problems. The <a
75href="#drawing-support">Unsupported drawing operations</a> section describes known issues with
76drawing 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
107for 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>
121getWindow().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
128the 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
133following code:</p>
134
135<pre>
136myView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
137</pre>
138
139<p class="note"><strong>Note</strong>: You currently cannot enable hardware acceleration at
140the view level. View layers have other functions besides disabling hardware acceleration. See <a
141href="#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
193your application calls {@link android.view.View#invalidate invalidate()} on a button and that
194button sits on top of another view, the Android system redraws the view even though it hasn't
195changed.</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 view’s 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 hierarchy’s
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  view’s 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,
360you can still take advantage of hardware acceleratin everywhere else. See <a
361href="#controlling">Controlling Hardware Acceleration</a> for more information on how to enable and
362disable 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,
369either 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
412around 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
419is hardware accelerated. Running an animation at 60 frames per second is not always possible when
420animating complex views that issue a lot of drawing operations. This can be alleviated by
421using hardware layers to render the view to a hardware texture. The hardware texture can
422then be used to animate the view, eliminating the need for the view to constantly redraw itself
423when it is being animated. The view is not redrawn unless you change the view's
424properties, which calls {@link android.view.View#invalidate invalidate()}, or if you call {@link
425android.view.View#invalidate invalidate()} manually. If you are running an animation in
426your application and do not obtain the smooth results you want, consider enabling hardware layers on
427your 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>:
439Changes 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>
455view.setLayerType(View.LAYER_TYPE_HARDWARE, null);
456ObjectAnimator.ofFloat(view, "rotationY", 180).start();
457</pre>
458
459  <p>Because hardware layers consume video memory, it is highly recommended that you enable them
460only for the duration of the animation and then disable them after the animation is done. You
461can accomplish this using animation listeners:</p>
462  <pre>
463View.setLayerType(View.LAYER_TYPE_HARDWARE, null);
464ObjectAnimator animator = ObjectAnimator.ofFloat(view, "rotationY", 180);
465animator.addListener(new AnimatorListenerAdapter() {
466    &#064;Override
467    public void onAnimationEnd(Animator animation) {
468        view.setLayerType(View.LAYER_TYPE_NONE, null);
469    }
470});
471animator.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
500android.graphics.Path} every time a rendering method is invoked. This forces the garbage
501collector to run more often and also bypasses caches and optimizations in the hardware
502pipeline.</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