blob: 8ba6676bf11c6f9250bf727ce1a679f496d25a85 [file] [log] [blame]
Robert Lyce8af062011-09-15 15:18:09 -07001page.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
Robert Ly02c93882012-02-22 11:15:53 -080045 <li><a href="{@docRoot}guide/topics/renderscript/index.html">Renderscript</a></li>
Robert Lyce8af062011-09-15 15:18:09 -070046 </ol>
47 </div>
48 </div>
49
Chris Craik0f7ade72013-04-19 16:07:23 -070050 <p>Beginning in Android 3.0 (API level 11), the Android 2D rendering pipeline supports hardware
51 acceleration, meaning that all drawing operations that are performed on a {@link
52 android.view.View}'s canvas use the GPU. Because of the increased resources required to enable
53 hardware acceleration, your app will consume more RAM.</p>
Robert Lyce8af062011-09-15 15:18:09 -070054
Chris Craik0f7ade72013-04-19 16:07:23 -070055 <p>Hardware acceleration is enabled by default if your Target API level is &gt;=14, but can also
56 be explicitly enabled. If your application uses only standard views and {@link
57 android.graphics.drawable.Drawable}s, turning it on globally should not cause any adverse drawing
58 effects. However, because hardware acceleration is not supported for all of the 2D drawing
59 operations, turning it on might affect some of your custom views or drawing calls. Problems
60 usually manifest themselves as invisible elements, exceptions, or wrongly rendered pixels. To
61 remedy this, Android gives you the option to enable or disable hardware acceleration at multiple
62 levels. See <a href="#controlling">Controlling Hardware Acceleration</a>.</p>
Robert Lyce8af062011-09-15 15:18:09 -070063
Chris Craik0f7ade72013-04-19 16:07:23 -070064 <p>If your application performs custom drawing, test your application on actual hardware devices
65 with hardware acceleration turned on to find any problems. The <a
66 href="#drawing-support">Unsupported drawing operations</a> section describes known issues with
67 hardware acceleration and how to work around them.</p>
Robert Lyce8af062011-09-15 15:18:09 -070068
69 <h2 id="controlling">Controlling Hardware Acceleration</h2>
70 <p>You can control hardware acceleration at the following levels:</p>
71 <ul>
72 <li>Application</li>
73
74 <li>Activity</li>
75
76 <li>Window</li>
77
78 <li>View</li>
79 </ul>
80
81 <h4>Application level</h4>
82 <p>In your Android manifest file, add the following attribute to the
83 <a href="{@docRoot}guide/topics/manifest/application-element.html">
84 <code>&lt;application&gt;</code></a> tag to enable hardware acceleration for your entire
85 application:</p>
86
87<pre>
88&lt;application android:hardwareAccelerated="true" ...&gt;
89</pre>
90
91 <h4>Activity level</h4>
Chris Craik0f7ade72013-04-19 16:07:23 -070092 <p>If your application does not behave properly with hardware acceleration turned on globally, you
93 can control it for individual activities as well. To enable or disable hardware acceleration at
94 the activity level, you can use the <code>android:hardwareAccelerated</code> attribute for
95 the <a href="{@docRoot}guide/topics/manifest/activity-element.html">
96 <code>&lt;activity&gt;</code></a> element. The following example enables hardware acceleration for
97 the entire application but disables it for one activity:</p>
Robert Lyce8af062011-09-15 15:18:09 -070098
99<pre>
100&lt;application android:hardwareAccelerated="true"&gt;
101 &lt;activity ... /&gt;
102 &lt;activity android:hardwareAccelerated="false" /&gt;
103&lt;/application&gt;
104</pre>
105
106 <h4>Window level</h4>
107 <p>If you need even more fine-grained control, you can enable hardware acceleration for a given
108 window with the following code:</p>
109
110<pre>
111getWindow().setFlags(
112 WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
113 WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
114
115</pre>
116
117<p class="note"><strong>Note</strong>: You currently cannot disable hardware acceleration at
118the window level.</p>
119
120 <h4>View level</h4>
121
122 <p>You can disable hardware acceleration for an individual view at runtime with the
123following code:</p>
124
125<pre>
126myView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
127</pre>
128
129<p class="note"><strong>Note</strong>: You currently cannot enable hardware acceleration at
130the view level. View layers have other functions besides disabling hardware acceleration. See <a
131href="#layers">View layers</a> for more information about their uses.</p>
132
133 <h2 id="determining">Determining if a View is Hardware Accelerated</h2>
134
135 <p>It is sometimes useful for an application to know whether it is currently hardware
136 accelerated, especially for things such as custom views. This is particularly useful if your
137 application does a lot of custom drawing and not all operations are properly supported by the new
138 rendering pipeline.</p>
139
140 <p>There are two different ways to check whether the application is hardware accelerated:</p>
141
142 <ul>
143 <li>{@link android.view.View#isHardwareAccelerated View.isHardwareAccelerated()} returns
144 <code>true</code> if the {@link android.view.View} is attached to a hardware accelerated
145 window.</li>
146
147 <li>{@link android.graphics.Canvas#isHardwareAccelerated Canvas.isHardwareAccelerated()}
148 returns <code>true</code> if the {@link android.graphics.Canvas} is hardware accelerated</li>
149 </ul>
150
151 <p>If you must do this check in your drawing code, use {@link
152 android.graphics.Canvas#isHardwareAccelerated Canvas.isHardwareAccelerated()} instead of {@link
153 android.view.View#isHardwareAccelerated View.isHardwareAccelerated()} when possible. When a view
154 is attached to a hardware accelerated window, it can still be drawn using a non-hardware
155 accelerated Canvas. This happens, for instance, when drawing a view into a bitmap for caching
156 purposes.</p>
157
158
159 <h2 id="model">Android Drawing Models</h2>
160
161 <p>When hardware acceleration is enabled, the Android framework utilizes a new drawing model that
162 utilizes <em>display lists</em> to render your application to the screen. To fully understand
163 display lists and how they might affect your application, it is useful to understand how Android
164 draws views without hardware acceleration as well. The following sections describe the
165 software-based and hardware-accelerated drawing models.</p>
166
167<h3>Software-based drawing model</h3>
168<p>In the software drawing model, views are drawn with the following two steps:</p>
169 <ol>
170 <li>Invalidate the hierarchy</li>
171
172 <li>Draw the hierarchy</li>
173 </ol>
174
175 <p>Whenever an application needs to update a part of its UI, it invokes {@link
176 android.view.View#invalidate invalidate()} (or one of its variants) on any view that has changed
177 content. The invalidation messages are propagated all the way up the view hierarchy to compute
178 the regions of the screen that need to be redrawn (the dirty region). The Android system then
179 draws any view in the hierarchy that intersects with the dirty region. Unfortunately, there are
180 two drawbacks to this drawing model:</p>
181 <ul>
182 <li>First, this model requires execution of a lot of code on every draw pass. For example, if
183your application calls {@link android.view.View#invalidate invalidate()} on a button and that
184button sits on top of another view, the Android system redraws the view even though it hasn't
185changed.</li>
186 <li>The second issue is that the drawing model can hide bugs in your application. Since the
187 Android system redraws views when they intersect the dirty region, a view whose content you
188 changed might be redrawn even though {@link android.view.View#invalidate invalidate()} was not
189 called on it. When this happens, you are relying on another view being invalidated to obtain the
190 proper behavior. This behavior can change every time you modify your application. Because of
191 this, you should always call {@link android.view.View#invalidate invalidate()} on your custom
192 views whenever you modify data or state that affects the view’s drawing code.</li>
193</ul>
194
195 <p class="note"><strong>Note</strong>: Android views automatically call {@link
196 android.view.View#invalidate invalidate()} when their properties change, such as the background
197 color or the text in a {@link android.widget.TextView}.</p>
198
199 <h3>Hardware accelerated drawing model</h3>
200 <p>The Android system still uses {@link android.view.View#invalidate invalidate()} and {@link
201 android.view.View#draw draw()} to request screen updates and to render views, but handles the
202 actual drawing differently. Instead of executing the drawing commands immediately, the Android
203 system records them inside display lists, which contain the output of the view hierarchy’s
204 drawing code. Another optimization is that the Android system only needs to record and update
205 display lists for views marked dirty by an {@link android.view.View#invalidate invalidate()}
206 call. Views that have not been invalidated can be redrawn simply by re-issuing the previously
207 recorded display list. The new drawing model contains three stages:</p>
208
209 <ol>
210 <li>Invalidate the hierarchy</li>
211
212 <li>Record and update display lists</li>
213
214 <li>Draw the display lists</li>
215 </ol>
216
217 <p>With this model, you cannot rely on a view intersecting the dirty region to have its {@link
218 android.view.View#draw draw()} method executed. To ensure that the Android system records a
219 view’s display list, you must call {@link android.view.View#invalidate invalidate()}. Forgetting
Chris Craik0f7ade72013-04-19 16:07:23 -0700220 to do so causes a view to look the same even after it has been changed.</p>
Robert Lyce8af062011-09-15 15:18:09 -0700221
222 <p>Using display lists also benefits animation performance because setting specific properties,
223 such as alpha or rotation, does not require invalidating the targeted view (it is done
224 automatically). This optimization also applies to views with display lists (any view when your
225 application is hardware accelerated.) For example, assume there is a {@link
226 android.widget.LinearLayout} that contains a {@link android.widget.ListView} above a {@link
227 android.widget.Button}. The display list for the {@link android.widget.LinearLayout} looks like
228 this:</p>
229
230 <ul>
231 <li>DrawDisplayList(ListView)</li>
232
233 <li>DrawDisplayList(Button)</li>
234 </ul>
235
236 <p>Assume now that you want to change the {@link android.widget.ListView}'s opacity. After
237 invoking <code>setAlpha(0.5f)</code> on the {@link android.widget.ListView}, the display list now
238 contains this:</p>
239
240 <ul>
241 <li>SaveLayerAlpha(0.5)</li>
242
243 <li>DrawDisplayList(ListView)</li>
244
245 <li>Restore</li>
246
247 <li>DrawDisplayList(Button)</li>
248 </ul>
249
250 <p>The complex drawing code of {@link android.widget.ListView} was not executed. Instead, the
251 system only updated the display list of the much simpler {@link android.widget.LinearLayout}. In
252 an application without hardware acceleration enabled, the drawing code of both the list and its
253 parent are executed again.</p>
254
255 <h2 id="unsupported">Unsupported Drawing Operations</h2>
256
257 <p>When hardware accelerated, the 2D rendering pipeline supports the most commonly used {@link
258 android.graphics.Canvas} drawing operations as well as many less-used operations. All of the
259 drawing operations that are used to render applications that ship with Android, default widgets
260 and layouts, and common advanced visual effects such as reflections and tiled textures are
Romain Guy9ff7d162013-02-26 14:49:35 -0800261 supported.</p>
Robert Lyce8af062011-09-15 15:18:09 -0700262
Romain Guy9ff7d162013-02-26 14:49:35 -0800263 <p>The following table describes the support level of various operations across API levels:</p>
Robert Lyce8af062011-09-15 15:18:09 -0700264
Romain Guy9ff7d162013-02-26 14:49:35 -0800265 <style type="text/css">
Chris Craik0f7ade72013-04-19 16:07:23 -0700266 .tblGenFixed, .tblGeneric{font-size:15px}.tblGenFixed td {padding:0 3px;letter-spacing:0;word-spacing:0;background-color:#fff;z-index:1;border-top:0px none;border-left:0px none;border-bottom:1px solid #CCC;border-right:1px solid #CCC;} .dn {display:none} .tblGenFixed td.s0 {background-color:white;border-top:1px solid #CCC;border-left:1px solid #CCC;} .tblGenFixed td.s1 {background-color:#434343;color:#ffffff;text-align:center;border-top:1px solid #CCC;} .tblGenFixed td.s2 {background-color:#d9d9d9;color:#000000;text-align:center;} .tblGenFixed td.s3 {background-color:white;color:#000000;text-align:center;} .tblGenFixed td.s5 {background-color:#434343;color:#ffffff;text-align:left;border-left:1px solid #CCC;} .tblGenFixed td.s10 {background-color:white;font-family:courier new,monospace;color:#000000;text-align:right;border-left:1px solid #CCC;} .tblGenFixed td.g_pos {background-color:#d9d9d9;color:#6aa84f;text-align:center;} .tblGenFixed td.g_neg {background-color:#d9d9d9;color:#980000;text-align:center;} .tblGenFixed td.w_pos {background-color:white;color:#6aa84f;text-align:center;} .tblGenFixed td.w_neg {background-color:white;color:#980000;text-align:center;}
Romain Guy9ff7d162013-02-26 14:49:35 -0800267 </style>
268 <table border="0" cellpadding="0" cellspacing="0" class="tblGenFixed" id="tblMain">
269 <tbody>
270 <tr class="rShim">
271 <td class="rShim" style="width:380px;"></td>
272 <td class="rShim" style="width:120px;"></td>
273 <td class="rShim" style="width:120px;"></td>
274 <td class="rShim" style="width:120px;"></td>
275 <td class="rShim" style="width:120px;"></td>
276 </tr>
277 <tr>
278 <td rowspan="2" class="s0"></td>
279 <td colspan="4" class="s1">API level</td>
280 </tr>
281 <tr>
282 <td style="display:none;"></td>
283 <td class="s2">&lt; 16</td>
284 <td class="s3">16</td>
Chris Craik0f7ade72013-04-19 16:07:23 -0700285 <td class="s2">17</td>
Romain Guy9ff7d162013-02-26 14:49:35 -0800286 <td class="s3">18</td>
287 </tr>
288 <tr>
289 <td colspan="5" class="s5">Canvas</td>
290 </tr>
291 <tr>
Romain Guy9ff7d162013-02-26 14:49:35 -0800292 <td class="s10">drawBitmapMesh() (colors array)</td>
Chris Craik0f7ade72013-04-19 16:07:23 -0700293 <td class="g_neg">&#10007;</td>
294 <td class="w_neg">&#10007;</td>
295 <td class="g_neg">&#10007;</td>
296 <td class="w_pos">&#10003;</td>
Romain Guy9ff7d162013-02-26 14:49:35 -0800297 </tr>
298 <tr>
299 <td class="s10">drawPicture()</td>
Chris Craik0f7ade72013-04-19 16:07:23 -0700300 <td class="g_neg">&#10007;</td>
301 <td class="w_neg">&#10007;</td>
302 <td class="g_neg">&#10007;</td>
303 <td class="w_neg">&#10007;</td>
Romain Guy9ff7d162013-02-26 14:49:35 -0800304 </tr>
305 <tr>
306 <td class="s10">drawPosText()</td>
Chris Craik0f7ade72013-04-19 16:07:23 -0700307 <td class="g_neg">&#10007;</td>
308 <td class="w_pos">&#10003;</td>
309 <td class="g_pos">&#10003;</td>
310 <td class="w_pos">&#10003;</td>
Romain Guy9ff7d162013-02-26 14:49:35 -0800311 </tr>
312 <tr>
313 <td class="s10">drawTextOnPath()</td>
Chris Craik0f7ade72013-04-19 16:07:23 -0700314 <td class="g_neg">&#10007;</td>
315 <td class="w_pos">&#10003;</td>
316 <td class="g_pos">&#10003;</td>
317 <td class="w_pos">&#10003;</td>
Romain Guy9ff7d162013-02-26 14:49:35 -0800318 </tr>
319 <tr>
320 <td class="s10">drawVertices()</td>
Chris Craik0f7ade72013-04-19 16:07:23 -0700321 <td class="g_neg">&#10007;</td>
322 <td class="w_neg">&#10007;</td>
323 <td class="g_neg">&#10007;</td>
324 <td class="w_neg">&#10007;</td>
Romain Guy9ff7d162013-02-26 14:49:35 -0800325 </tr>
326 <tr>
327 <td class="s10">setDrawFilter()</td>
Chris Craik0f7ade72013-04-19 16:07:23 -0700328 <td class="g_neg">&#10007;</td>
329 <td class="w_pos">&#10003;</td>
330 <td class="g_pos">&#10003;</td>
331 <td class="w_pos">&#10003;</td>
332 </tr>
333 <tr>
334 <td class="s10">clipPath()</td>
335 <td class="g_neg">&#10007;</td>
336 <td class="w_neg">&#10007;</td>
337 <td class="g_neg">&#10007;</td>
338 <td class="w_pos">&#10003;</td>
339 </tr>
340 <tr>
341 <td class="s10">clipRegion()</td>
342 <td class="g_neg">&#10007;</td>
343 <td class="w_neg">&#10007;</td>
344 <td class="g_neg">&#10007;</td>
345 <td class="w_pos">&#10003;</td>
346 </tr>
347 <tr>
348 <td class="s10">clipRect(Region.Op.XOR)</td>
349 <td class="g_neg">&#10007;</td>
350 <td class="w_neg">&#10007;</td>
351 <td class="g_neg">&#10007;</td>
352 <td class="w_pos">&#10003;</td>
353 </tr>
354 <tr>
355 <td class="s10">clipRect(Region.Op.Difference)</td>
356 <td class="g_neg">&#10007;</td>
357 <td class="w_neg">&#10007;</td>
358 <td class="g_neg">&#10007;</td>
359 <td class="w_pos">&#10003;</td>
360 </tr>
361 <tr>
362 <td class="s10">clipRect(Region.Op.ReverseDifference)</td>
363 <td class="g_neg">&#10007;</td>
364 <td class="w_neg">&#10007;</td>
365 <td class="g_neg">&#10007;</td>
366 <td class="w_pos">&#10003;</td>
367 </tr>
368 <tr>
369 <td class="s10">clipRect() with rotation/perspective</td>
370 <td class="g_neg">&#10007;</td>
371 <td class="w_neg">&#10007;</td>
372 <td class="g_neg">&#10007;</td>
373 <td class="w_pos">&#10003;</td>
Romain Guy9ff7d162013-02-26 14:49:35 -0800374 </tr>
375 <tr>
376 <td colspan="5" class="s5">Paint</td>
377 </tr>
378 <tr>
Chris Craik0f7ade72013-04-19 16:07:23 -0700379 <td class="s10">setAntiAlias() (for text)</td>
380 <td class="g_neg">&#10007;</td>
381 <td class="w_neg">&#10007;</td>
382 <td class="g_neg">&#10007;</td>
383 <td class="w_pos">&#10003;</td>
Romain Guy9ff7d162013-02-26 14:49:35 -0800384 </tr>
385 <tr>
Chris Craik0f7ade72013-04-19 16:07:23 -0700386 <td class="s10">setAntiAlias() (for lines)</td>
387 <td class="g_neg">&#10007;</td>
388 <td class="w_pos">&#10003;</td>
389 <td class="g_pos">&#10003;</td>
390 <td class="w_pos">&#10003;</td>
Romain Guy9ff7d162013-02-26 14:49:35 -0800391 </tr>
392 <tr>
Chris Craik0f7ade72013-04-19 16:07:23 -0700393 <td class="s10">setFilterBitmap()</td>
394 <td class="g_neg">&#10007;</td>
395 <td class="w_neg">&#10007;</td>
396 <td class="g_pos">&#10003;</td>
397 <td class="w_pos">&#10003;</td>
Romain Guy9ff7d162013-02-26 14:49:35 -0800398 </tr>
399 <tr>
Chris Craik0f7ade72013-04-19 16:07:23 -0700400 <td class="s10">setLinearText()</td>
401 <td class="g_neg">&#10007;</td>
402 <td class="w_neg">&#10007;</td>
403 <td class="g_neg">&#10007;</td>
404 <td class="w_neg">&#10007;</td>
Romain Guy9ff7d162013-02-26 14:49:35 -0800405 </tr>
406 <tr>
407 <td class="s10">setMaskFilter()</td>
Chris Craik0f7ade72013-04-19 16:07:23 -0700408 <td class="g_neg">&#10007;</td>
409 <td class="w_neg">&#10007;</td>
410 <td class="g_neg">&#10007;</td>
411 <td class="w_neg">&#10007;</td>
Romain Guy9ff7d162013-02-26 14:49:35 -0800412 </tr>
413 <tr>
414 <td class="s10">setPathEffect() (for lines)</td>
Chris Craik0f7ade72013-04-19 16:07:23 -0700415 <td class="g_neg">&#10007;</td>
416 <td class="w_neg">&#10007;</td>
417 <td class="g_neg">&#10007;</td>
418 <td class="w_neg">&#10007;</td>
Romain Guy9ff7d162013-02-26 14:49:35 -0800419 </tr>
420 <tr>
421 <td class="s10">setRasterizer()</td>
Chris Craik0f7ade72013-04-19 16:07:23 -0700422 <td class="g_neg">&#10007;</td>
423 <td class="w_neg">&#10007;</td>
424 <td class="g_neg">&#10007;</td>
425 <td class="w_neg">&#10007;</td>
Romain Guy9ff7d162013-02-26 14:49:35 -0800426 </tr>
427 <tr>
428 <td class="s10">setShadowLayer() (other than text)</td>
Chris Craik0f7ade72013-04-19 16:07:23 -0700429 <td class="g_neg">&#10007;</td>
430 <td class="w_neg">&#10007;</td>
431 <td class="g_neg">&#10007;</td>
432 <td class="w_neg">&#10007;</td>
Romain Guy9ff7d162013-02-26 14:49:35 -0800433 </tr>
434 <tr>
435 <td class="s10">setStrokeCap() (for lines)</td>
Chris Craik0f7ade72013-04-19 16:07:23 -0700436 <td class="g_neg">&#10007;</td>
437 <td class="w_neg">&#10007;</td>
438 <td class="g_neg">&#10007;</td>
439 <td class="w_pos">&#10003;</td>
Romain Guy9ff7d162013-02-26 14:49:35 -0800440 </tr>
441 <tr>
442 <td class="s10">setStrokeCap() (for points)</td>
Chris Craik0f7ade72013-04-19 16:07:23 -0700443 <td class="g_neg">&#10007;</td>
444 <td class="w_neg">&#10007;</td>
445 <td class="g_neg">&#10007;</td>
446 <td class="w_neg">&#10007;</td>
Romain Guy9ff7d162013-02-26 14:49:35 -0800447 </tr>
448 <tr>
449 <td class="s10">setSubpixelText()</td>
Chris Craik0f7ade72013-04-19 16:07:23 -0700450 <td class="g_neg">&#10007;</td>
451 <td class="w_neg">&#10007;</td>
452 <td class="g_neg">&#10007;</td>
453 <td class="w_neg">&#10007;</td>
Romain Guy9ff7d162013-02-26 14:49:35 -0800454 </tr>
455 <tr>
456 <td colspan="5" class="s5">Xfermode</td>
457 </tr>
458 <tr>
Chris Craik0f7ade72013-04-19 16:07:23 -0700459 <td class="s10">AvoidXfermode</td>
460 <td class="g_neg">&#10007;</td>
461 <td class="w_neg">&#10007;</td>
462 <td class="g_neg">&#10007;</td>
463 <td class="w_neg">&#10007;</td>
Romain Guy9ff7d162013-02-26 14:49:35 -0800464 </tr>
465 <tr>
466 <td class="s10">PixelXorXfermode</td>
Chris Craik0f7ade72013-04-19 16:07:23 -0700467 <td class="g_neg">&#10007;</td>
468 <td class="w_neg">&#10007;</td>
469 <td class="g_neg">&#10007;</td>
470 <td class="w_neg">&#10007;</td>
Romain Guy9ff7d162013-02-26 14:49:35 -0800471 </tr>
472 <tr>
473 <td class="s10">PorterDuff.Mode.DARKEN (framebuffer)</td>
Chris Craik0f7ade72013-04-19 16:07:23 -0700474 <td class="g_neg">&#10007;</td>
475 <td class="w_neg">&#10007;</td>
476 <td class="g_neg">&#10007;</td>
477 <td class="w_neg">&#10007;</td>
Romain Guy9ff7d162013-02-26 14:49:35 -0800478 </tr>
479 <tr>
480 <td class="s10">PorterDuff.Mode.LIGHTEN (framebuffer)</td>
Chris Craik0f7ade72013-04-19 16:07:23 -0700481 <td class="g_neg">&#10007;</td>
482 <td class="w_neg">&#10007;</td>
483 <td class="g_neg">&#10007;</td>
484 <td class="w_neg">&#10007;</td>
Romain Guy9ff7d162013-02-26 14:49:35 -0800485 </tr>
486 <tr>
487 <td class="s10">PorterDuff.Mode.OVERLAY (framebuffer)</td>
Chris Craik0f7ade72013-04-19 16:07:23 -0700488 <td class="g_neg">&#10007;</td>
489 <td class="w_neg">&#10007;</td>
490 <td class="g_neg">&#10007;</td>
491 <td class="w_neg">&#10007;</td>
Romain Guy9ff7d162013-02-26 14:49:35 -0800492 </tr>
493 <tr>
494 <td colspan="5" class="s5">Shader</td>
495 </tr>
496 <tr>
497 <td class="s10">ComposeShader inside ComposeShader</td>
Chris Craik0f7ade72013-04-19 16:07:23 -0700498 <td class="g_neg">&#10007;</td>
499 <td class="w_neg">&#10007;</td>
500 <td class="g_neg">&#10007;</td>
501 <td class="w_neg">&#10007;</td>
Romain Guy9ff7d162013-02-26 14:49:35 -0800502 </tr>
503 <tr>
504 <td class="s10">Same type shaders inside ComposeShader</td>
Chris Craik0f7ade72013-04-19 16:07:23 -0700505 <td class="g_neg">&#10007;</td>
506 <td class="w_neg">&#10007;</td>
507 <td class="g_neg">&#10007;</td>
508 <td class="w_neg">&#10007;</td>
Romain Guy9ff7d162013-02-26 14:49:35 -0800509 </tr>
Romain Guybbb4e032013-03-19 10:31:38 -0700510 <tr>
511 <td class="s10">Local matrix on ComposeShader</td>
Chris Craik0f7ade72013-04-19 16:07:23 -0700512 <td class="g_neg">&#10007;</td>
513 <td class="w_neg">&#10007;</td>
514 <td class="g_neg">&#10007;</td>
515 <td class="w_pos">&#10003;</td>
Romain Guybbb4e032013-03-19 10:31:38 -0700516 </tr>
Romain Guy9ff7d162013-02-26 14:49:35 -0800517 </tbody>
518 </table>
Robert Lyce8af062011-09-15 15:18:09 -0700519
Chris Craik0f7ade72013-04-19 16:07:23 -0700520 <h3 id="scaling">Canvas Scaling</h3>
521
522 <p>The hardware accelerated 2D rendering pipeline was built first to support unscaled drawing,
523 with some drawing operations degrading quality significantly at higher scale values. These
524 operations are implemented as textures drawn at scale 1.0, transformed by the GPU. In API level
525 &lt;17, using these operations will result in scaling artifacts increasing with scale.</p>
526
527 The following table shows when implementation was changed to correctly handle large scales:
528
529 <table border="0" cellpadding="0" cellspacing="0" class="tblGenFixed" id="tblMain">
530 <tbody>
531 <tr class="rShim">
532 <td class="rShim" style="width:380px;"></td>
533 <td class="rShim" style="width:120px;"></td>
534 <td class="rShim" style="width:120px;"></td>
535 <td class="rShim" style="width:120px;"></td>
536 </tr>
537 <tr>
538 <td rowspan="2" class="s0"></td>
539 <td colspan="4" class="s1">API level</td>
540 </tr>
541 <tr>
542 <td style="display:none;"></td>
543 <td class="s2">&lt; 17</td>
544 <td class="s3">17</td>
545 <td class="s2">18</td>
546 </tr>
547 <tr>
548 <td colspan="5" class="s5">Support for large scale factors</td>
549 </tr>
550 <tr>
551 <td class="s10">drawText()</td>
552 <td class="g_neg">&#10007;</td>
553 <td class="w_neg">&#10007;</td>
554 <td class="g_pos">&#10003;</td>
555 </tr>
556 <tr>
557 <td class="s10">drawPosText()</td>
558 <td class="g_neg">&#10007;</td>
559 <td class="w_neg">&#10007;</td>
560 <td class="g_neg">&#10007;</td>
561 </tr>
562 <tr>
563 <td class="s10">drawTextOnPath()</td>
564 <td class="g_neg">&#10007;</td>
565 <td class="w_neg">&#10007;</td>
566 <td class="g_neg">&#10007;</td>
567 </tr>
568 <tr>
569 <td class="s10">Simple Shapes*</td>
570 <td class="g_neg">&#10007;</td>
571 <td class="w_pos">&#10003;</td>
572 <td class="g_pos">&#10003;</td>
573 </tr>
574 <tr>
575 <td class="s10">Complex Shapes*</td>
576 <td class="g_neg">&#10007;</td>
577 <td class="w_neg">&#10007;</td>
578 <td class="g_neg">&#10007;</td>
579 </tr>
580 <tr>
581 <td class="s10">drawPath()</td>
582 <td class="g_neg">&#10007;</td>
583 <td class="w_neg">&#10007;</td>
584 <td class="g_neg">&#10007;</td>
585 </tr>
586 <tr>
587 <td class="s10">Shadow layer</td>
588 <td class="g_neg">&#10007;</td>
589 <td class="w_neg">&#10007;</td>
590 <td class="g_neg">&#10007;</td>
591 </tr>
592 </tbody>
593 </table>
594
595 <p class="note"><strong>Note</strong>: 'Simple' shapes are <code>drawRect()</code>,
596 <code>drawCircle()</code>, <code>drawOval()</code>, <code>drawRoundRect()</code>, and
597 <code>drawArc()</code> (with useCenter=false) commands issued with a Paint that doesn't have a
598 PathEffect, and doesn't contain non-default joins (via <code>setStrokeJoin()</code> /
599 <code>setStrokeMiter()</code>). Other instances of those draw commands fall under 'Complex,' in
600 the above chart.</p>
601
Robert Lyce8af062011-09-15 15:18:09 -0700602 <p>If your application is affected by any of these missing features or limitations, you can turn
Chris Craik0f7ade72013-04-19 16:07:23 -0700603 off hardware acceleration for just the affected portion of your application by calling {@link
604 android.view.View#setLayerType setLayerType(View.LAYER_TYPE_SOFTWARE, null)}. This way, you can
605 still take advantage of hardware acceleration everywhere else. See <a
606 href="#controlling">Controlling Hardware Acceleration</a> for more information on how to enable
607 and disable hardware acceleration at different levels in your application.
Robert Lyce8af062011-09-15 15:18:09 -0700608
609 <h2 id="layers">View Layers</h2>
610
611 <p>In all versions of Android, views have had the ability to render into off-screen buffers,
612either by using a view's drawing cache, or by using {@link android.graphics.Canvas#saveLayer
613 Canvas.saveLayer()}. Off-screen buffers, or layers, have several uses. You can use them to get
614 better performance when animating complex views or to apply composition effects. For instance,
615 you can implement fade effects using <code>Canvas.saveLayer()</code> to temporarily render a view
616 into a layer and then composite it back on screen with an opacity factor.</p>
617
618 <p>Beginning in Android 3.0 (API level 11), you have more control on how and when to use layers
619 with the {@link android.view.View#setLayerType View.setLayerType()} method. This API takes two
620 parameters: the type of layer you want to use and an optional {@link android.graphics.Paint}
621 object that describes how the layer should be composited. You can use the {@link
622 android.graphics.Paint} parameter to apply color filters, special blending modes, or opacity to a
623 layer. A view can use one of three layer types:</p>
624
625 <ul>
626 <li>{@link android.view.View#LAYER_TYPE_NONE}: The view is rendered normally and is not backed
627 by an off-screen buffer. This is the default behavior.</li>
628
629 <li>{@link android.view.View#LAYER_TYPE_HARDWARE}: The view is rendered in hardware into a
630 hardware texture if the application is hardware accelerated. If the application is not hardware
631 accelerated, this layer type behaves the same as {@link
632 android.view.View#LAYER_TYPE_SOFTWARE}.</li>
633
634 <li>{@link android.view.View#LAYER_TYPE_SOFTWARE}: The view is rendered in software into a
635 bitmap.</li>
636 </ul>
637
638 <p>The type of layer you use depends on your goal:</p>
639
640 <ul>
641 <li><strong>Performance</strong>: Use a hardware layer type to render a view into a hardware
642 texture. Once a view is rendered into a layer, its drawing code does not have to be executed
643 until the view calls {@link android.view.View#invalidate invalidate()}. Some animations, such as
644 alpha animations, can then be applied directly onto the layer, which is very efficient
645 for the GPU to do.</li>
646
647 <li><strong>Visual effects</strong>: Use a hardware or software layer type and a {@link
648 android.graphics.Paint} to apply special visual treatments to a view. For instance, you can
649 draw a view in black and white using a {@link
650 android.graphics.ColorMatrixColorFilter}.</li>
651
652 <li><strong>Compatibility</strong>: Use a software layer type to force a view to be rendered in
653 software. If a view that is hardware accelerated (for instance, if your whole
654 application is hardware acclerated), is having rendering problems, this is an easy way to work
655around limitations of the hardware rendering
656 pipeline.</li>
657 </ul>
658
659 <h3 id="layers-anims">View layers and animations</h3>
660
661 <p>Hardware layers can deliver faster and smoother animations when your application
662is hardware accelerated. Running an animation at 60 frames per second is not always possible when
663animating complex views that issue a lot of drawing operations. This can be alleviated by
664using hardware layers to render the view to a hardware texture. The hardware texture can
665then be used to animate the view, eliminating the need for the view to constantly redraw itself
666when it is being animated. The view is not redrawn unless you change the view's
667properties, which calls {@link android.view.View#invalidate invalidate()}, or if you call {@link
668android.view.View#invalidate invalidate()} manually. If you are running an animation in
669your application and do not obtain the smooth results you want, consider enabling hardware layers on
670your animated views.</p>
671
672 <p>When a view is backed by a hardware layer, some of its properties are handled by the way the
673 layer is composited on screen. Setting these properties will be efficient because they do not
674 require the view to be invalidated and redrawn. The following list of properties affect the way
675 the layer is composited. Calling the setter for any of these properties results in optimal
676 invalidation and no redrawing of the targeted view:</p>
677
678 <ul>
679 <li><code>alpha</code>: Changes the layer's opacity</li>
680
681 <li><code>x</code>, <code>y</code>, <code>translationX</code>, <code>translationY</code>:
682Changes the layer's position</li>
683
684 <li><code>scaleX</code>, <code>scaleY</code>: Changes the layer's size</li>
685
686 <li><code>rotation</code>, <code>rotationX</code>, <code>rotationY</code>: Changes the
687 layer's orientation in 3D space</li>
688
689 <li><code>pivotX</code>, <code>pivotY</code>: Changes the layer's transformations origin</li>
690 </ul>
691
692 <p>These properties are the names used when animating a view with an {@link
693 android.animation.ObjectAnimator}. If you want to access these properties, call the appropriate
694 setter or getter. For instance, to modify the alpha property, call {@link
695 android.view.View#setAlpha setAlpha()}. The following code snippet shows the most efficient way
696 to rotate a viewiew in 3D around the Y-axis:</p>
697 <pre>
698view.setLayerType(View.LAYER_TYPE_HARDWARE, null);
699ObjectAnimator.ofFloat(view, "rotationY", 180).start();
700</pre>
701
702 <p>Because hardware layers consume video memory, it is highly recommended that you enable them
703only for the duration of the animation and then disable them after the animation is done. You
704can accomplish this using animation listeners:</p>
705 <pre>
706View.setLayerType(View.LAYER_TYPE_HARDWARE, null);
707ObjectAnimator animator = ObjectAnimator.ofFloat(view, "rotationY", 180);
708animator.addListener(new AnimatorListenerAdapter() {
709 &#064;Override
710 public void onAnimationEnd(Animator animation) {
711 view.setLayerType(View.LAYER_TYPE_NONE, null);
712 }
713});
714animator.start();
715</pre>
716
717 <p>For more information on property animation, see <a href=
718 "{@docRoot}guide/topics/graphics/prop-animation.html">Property Animation</a>.</p>
719
720 <h2 id="tips">Tips and Tricks</h2>
721
722 <p>Switching to hardware accelerated 2D graphics can instantly increase performance, but you
723 should still design your application to use the GPU effectively by following these
724 recommendations:</p>
725
726 <dl>
727 <dt><strong>Reduce the number of views in your application</strong></dt>
728
729 <dd>The more views the system has to draw, the slower it will be. This applies to the software
730 rendering pipeline as well. Reducing views is one of the easiest ways to optimize your UI.</dd>
731
732 <dt><strong>Avoid overdraw</strong></dt>
733
734 <dd>Do not draw too many layers on top of each other. Remove any views that are completely
735 obscured by other opaque views on top of it. If you need to draw several layers blended on top
736 of each other, consider merging them into a single layer. A good rule of thumb with current
737 hardware is to not draw more than 2.5 times the number of pixels on screen per frame
738 (transparent pixels in a bitmap count!).</dd>
739
740 <dt><strong>Don't create render objects in draw methods</strong></dt>
741
742 <dd>A common mistake is to create a new {@link android.graphics.Paint} or a new {@link
743android.graphics.Path} every time a rendering method is invoked. This forces the garbage
744collector to run more often and also bypasses caches and optimizations in the hardware
745pipeline.</dd>
746
747 <dt><strong>Don't modify shapes too often</strong></dt>
748
749 <dd>Complex shapes, paths, and circles for instance, are rendered using texture masks. Every
750 time you create or modify a path, the hardware pipeline creates a new mask, which can be
751 expensive.</dd>
752
753 <dt><strong>Don't modify bitmaps too often</strong></dt>
754
755 <dd>Every time you change the content of a bitmap, it is uploaded again as a GPU texture the
756 next time you draw it.</dd>
757
758 <dt><strong>Use alpha with care</strong></dt>
759
760 <dd>When you make a view translucent using {@link android.view.View#setAlpha setAlpha()},
761 {@link android.view.animation.AlphaAnimation}, or {@link android.animation.ObjectAnimator}, it
762 is rendered in an off-screen buffer which doubles the required fill-rate. When applying alpha
763 on very large views, consider setting the view's layer type to
764 <code>LAYER_TYPE_HARDWARE</code>.</dd>
765 </dl>