blob: cdc237f7cbfd7bcc1d50ed965b2785af09f00cb9 [file] [log] [blame]
page.title=Visualize and Reduce Overdraw
page.tags=render
page.article=true
@jd:body
<style>
.app-icon {
height: 64px;
}
</style>
<p>Every time your app draws a pixel on the screen, it takes time. Every time your app draws a
pixel that has already been drawn, it wastes time. Drawing a pixel more than once per screen
refresh is called <i>o</i><i>verdraw</i>, and it's a common problem affecting
the performance of modern applications. To be efficient, every time your app refreshes the
screen, it should draw every changed pixel only once.</p>
<p>For example, an app might draw a stack of 52 overlapping cards, with only the last card fully
visible. Completely drawing the 51 cards that are underneath and partially covered, is an example
of overdraw.</p>
<div class="figure" style="float:none">
<img src="{@docRoot}images/training/app/stacked_cards.png"
alt=""
height="" />
<p class="img-caption">
<strong>Figure 1. </strong>Example of card stack with potential overdraw.
</p>
</div>
<p>Watch the
<a href="https://www.youtube.com/watch?v=T52v50r-JfE">Understanding Overdraw</a>
video
for a detailed introduction, and see the rest of this page for more on finding and fixing
overdraw.</p>
<iframe width="448" height="252"
src="//www.youtube.com/embed/T52v50r-JfE?autohide=1&amp;showinfo=0"
frameborder="0" allowfullscreen=""
style="float:none; margin: 0 0 20px 20px;"></iframe>
<p class="note"><b>Note:</b> Reducing overdraw can save significant GPU resources and greatly
decrease the time it takes to draw a frame. Reducing overdraw may have a significant impact, if it
is the biggest performance issue your app has; or it may have no noticeable impact, if you are on
a fast device, or if your app has other, much bigger performance issues.</p>
<h2><img class="app-icon" src="{@docRoot}images/training/app/app_icon_gather.png">
Test for overdraw</h2>
<p>You can visualize overdraw using color tinting on your device with the
<a href="{@docRoot}tools/performance/debug-gpu-overdraw/index.html">Debug GPU Overdraw tool</a>.
</p>
<p>To turn on Debug GPU Overdraw on your mobile device:</p>
<ol>
<li>Open <b>Settings.</b></li>
<li>Tap <b>Developer Options</b>.</li>
<li>In the <i>Hardware accelerated rendering</i> section, select <b>Debug GPU
Overdraw</b>.</li>
<li>In the Debug GPU overdraw popup, select <b>Show overdraw areas</b>.</li>
</ol>
<p>See
<a href="{@docRoot}tools/performance/debug-gpu-overdraw/index.html">Debug GPU Overdraw</a>
for a full tutorial, or try the <a href=
"https://io2015codelabs.appspot.com/codelabs/android-performance-debug-gpu-overdraw#1">Debug
GPU Overdraw Codelab</a>.</p>
<h2><img class="app-icon" src="{@docRoot}images/training/app/app_icon_insight.png">
Interpret the Debug GPU Overdraw output</h2>
<p>As a general rule, if at any given point your app is drawing something that the user does not
see, don't draw it. More specifically, Debug GPU Overdraw highlights can guide
you to the following issues:</p>
<ul>
<li><b>Unnecessary backgrounds.</b> See
<a href="#backgrounds">Eliminate unnecessary backgrounds</a>.</li>
<li><b>Areas of the screen that have not changed are drawn.</b> See
<a href="#clip">Clip generously</a>.</li>
<li><b>Complex or poorly organized view hierarchy.</b> See
<a href="{@docRoot}training/app/rendering/hierarchies.html">
Simplifying Complex View Hierarchies</a>.</li>
</ul>
<h2 id="backgrounds"><img class="app-icon" src="{@docRoot}images/training/app/app_icon_action.png">
Eliminate unnecessary backgrounds</h2>
<p>Search your code for <code>android:background</code>, and for each
background, determine whether it's needed and visible on the screen.</p>
<p>Removing unnecessary backgrounds is a quick way of improving rendering performance. An
unnecessary background may never visible, because it's completely covered by
everything else the app is drawing in that view. For example, a parent's default
background that is overdrawn by the children's custom backgrounds.</p>
<p>You can remove backgrounds by removing the <code>android:background</code>? line of code in an view.</p>
<p><b>Before:</b></p>
<pre>
&lt;FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_chatum_latinum_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/white" <===== Background
tools:context=".MainActivity"
tools:ignore="MergeRootFrame" /&gt;
</pre>
<p><b>After:</b></p>
<pre>
&lt;FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_chatum_latinum_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"
tools:ignore="MergeRootFrame" /&gt;
</pre>
<h2 id="clip"><img class="app-icon" src="{@docRoot}images/training/app/app_icon_action.png">
Clip generously</h2>
<p>Find areas that are drawn unnecessarily and clip generously.</p>
<p>When you are using custom views, you may be redrawing areas of the screen that have not
changed.</p>
<p>For each update, even if only a portion of a custom view has changed, the entire view must be
rebuilt. This is most common for views that use Canvas for drawing. For example, if you draw a
small circle in a corner of the view, the whole view gets rebuilt.</p>
<p>The Android system does to a good job at culling views that are 100% invisible or overlapped
by another view, but cannot eliminate more complex views, for example those that include
text transparency or rounded corners.</p>
<p>Before you draw a custom view, test whether it's visible at all. If it is
visible, only draw the portions that the user sees.</p>
<p>See <a href="https://www.youtube.com/watch?v=vkTn3Ule4Ps">
Overdraw, ClipRect, QuickReject</a>.</p>
<iframe width="448" height="252"
src="//www.youtube.com/embed/vkTn3Ule4Ps?autohide=1&amp;showinfo=0"
frameborder="0" allowfullscreen=""
style="float:none; margin: 0 0 20px 20px;"></iframe>