1page.title=SurfaceFlinger and Hardware Composer 2@jd:body 3 4<!-- 5 Copyright 2014 The Android Open Source Project 6 7 Licensed under the Apache License, Version 2.0 (the "License"); 8 you may not use this file except in compliance with the License. 9 You may obtain a copy of the License at 10 11 http://www.apache.org/licenses/LICENSE-2.0 12 13 Unless required by applicable law or agreed to in writing, software 14 distributed under the License is distributed on an "AS IS" BASIS, 15 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 See the License for the specific language governing permissions and 17 limitations under the License. 18--> 19<div id="qv-wrapper"> 20 <div id="qv"> 21 <h2>In this document</h2> 22 <ol id="auto-toc"> 23 </ol> 24 </div> 25</div> 26 27<p>Having buffers of graphical data is wonderful, but life is even better when 28you get to see them on your device's screen. That's where SurfaceFlinger and the 29Hardware Composer HAL come in.</p> 30 31 32<h2 id=surfaceflinger>SurfaceFlinger</h2> 33 34<p>SurfaceFlinger's role is to accept buffers of data from multiple sources, 35composite them, and send them to the display. Once upon a time this was done 36with software blitting to a hardware framebuffer (e.g. 37<code>/dev/graphics/fb0</code>), but those days are long gone.</p> 38 39<p>When an app comes to the foreground, the WindowManager service asks 40SurfaceFlinger for a drawing surface. SurfaceFlinger creates a layer (the 41primary component of which is a BufferQueue) for which SurfaceFlinger acts as 42the consumer. A Binder object for the producer side is passed through the 43WindowManager to the app, which can then start sending frames directly to 44SurfaceFlinger.</p> 45 46<p class="note"><strong>Note:</strong> While this section uses SurfaceFlinger 47terminology, WindowManager uses the term <em>window</em> instead of 48<em>layer</em>…and uses layer to mean something else. (It can be argued 49that SurfaceFlinger should really be called LayerFlinger.)</p> 50 51<p>Most applications have three layers on screen at any time: the status bar at 52the top of the screen, the navigation bar at the bottom or side, and the 53application UI. Some apps have more, some less (e.g. the default home app has a 54separate layer for the wallpaper, while a full-screen game might hide the status 55bar. Each layer can be updated independently. The status and navigation bars 56are rendered by a system process, while the app layers are rendered by the app, 57with no coordination between the two.</p> 58 59<p>Device displays refresh at a certain rate, typically 60 frames per second on 60phones and tablets. If the display contents are updated mid-refresh, tearing 61will be visible; so it's important to update the contents only between cycles. 62The system receives a signal from the display when it's safe to update the 63contents. For historical reasons we'll call this the VSYNC signal.</p> 64 65<p>The refresh rate may vary over time, e.g. some mobile devices will range from 58 66to 62fps depending on current conditions. For an HDMI-attached television, this 67could theoretically dip to 24 or 48Hz to match a video. Because we can update 68the screen only once per refresh cycle, submitting buffers for display at 200fps 69would be a waste of effort as most of the frames would never be seen. Instead of 70taking action whenever an app submits a buffer, SurfaceFlinger wakes up when the 71display is ready for something new.</p> 72 73<p>When the VSYNC signal arrives, SurfaceFlinger walks through its list of 74layers looking for new buffers. If it finds a new one, it acquires it; if not, 75it continues to use the previously-acquired buffer. SurfaceFlinger always wants 76to have something to display, so it will hang on to one buffer. If no buffers 77have ever been submitted on a layer, the layer is ignored.</p> 78 79<p>After SurfaceFlinger has collected all buffers for visible layers, it asks 80the Hardware Composer how composition should be performed.</p> 81 82<h2 id=hwc>Hardware Composer</h2> 83 84<p>The Hardware Composer HAL (HWC) was introduced in Android 3.0 and has evolved 85steadily over the years. Its primary purpose is to determine the most efficient 86way to composite buffers with the available hardware. As a HAL, its 87implementation is device-specific and usually done by the display hardware OEM.</p> 88 89<p>The value of this approach is easy to recognize when you consider <em>overlay 90planes</em>, the purpose of which is to composite multiple buffers together in 91the display hardware rather than the GPU. For example, consider a typical 92Android phone in portrait orientation, with the status bar on top, navigation 93bar at the bottom, and app content everywhere else. The contents for each layer 94are in separate buffers. You could handle composition using either of the 95following methods:</p> 96 97<ul> 98<li>Rendering the app content into a scratch buffer, then rendering the status 99bar over it, the navigation bar on top of that, and finally passing the scratch 100buffer to the display hardware.</li> 101<li>Passing all three buffers to the display hardware and tell it to read data 102from different buffers for different parts of the screen.</li> 103</ul> 104 105<p>The latter approach can be significantly more efficient.</p> 106 107<p>Display processor capabilities vary significantly. The number of overlays, 108whether layers can be rotated or blended, and restrictions on positioning and 109overlap can be difficult to express through an API. The HWC attempts to 110accommodate such diversity through a series of decisions:</p> 111 112<ol> 113<li>SurfaceFlinger provides HWC with a full list of layers and asks, "How do 114you want to handle this?"</li> 115<li>HWC responds by marking each layer as overlay or GLES composition.</li> 116<li>SurfaceFlinger takes care of any GLES composition, passing the output buffer 117to HWC, and lets HWC handle the rest.</li> 118</ol> 119 120<p>Since hardware vendors can custom tailor decision-making code, it's possible 121to get the best performance out of every device.</p> 122 123<p>Overlay planes may be less efficient than GL composition when nothing on the 124screen is changing. This is particularly true when overlay contents have 125transparent pixels and overlapping layers are blended together. In such cases, 126the HWC can choose to request GLES composition for some or all layers and retain 127the composited buffer. If SurfaceFlinger comes back asking to composite the same 128set of buffers, the HWC can continue to show the previously-composited scratch 129buffer. This can improve the battery life of an idle device.</p> 130 131<p>Devices running Android 4.4 and later typically support four overlay planes. 132Attempting to composite more layers than overlays causes the system to use GLES 133composition for some of them, meaning the number of layers used by an app can 134have a measurable impact on power consumption and performance.</p> 135 136<h2 id=virtual-displays>Virtual displays</h2> 137 138<p>SurfaceFlinger supports a primary display (i.e. what's built into your phone 139or tablet), an external display (such as a television connected through HDMI), 140and one or more virtual displays that make composited output available within 141the system. Virtual displays can be used to record the screen or send it over a 142network.</p> 143 144<p>Virtual displays may share the same set of layers as the main display 145(the layer stack) or have its own set. There is no VSYNC for a virtual display, 146so the VSYNC for the primary display is used to trigger composition for all 147displays.</p> 148 149<p>In older versions of Android, virtual displays were always composited with 150GLES and the Hardware Composer managed composition for the primary display only. 151In Android 4.4, the Hardware Composer gained the ability to participate in 152virtual display composition.</p> 153 154<p>As you might expect, frames generated for a virtual display are written to a 155BufferQueue.</p> 156 157<h2 id=screenrecord>Case Study: screenrecord</h2> 158 159<p>The <a href="https://android.googlesource.com/platform/frameworks/av/+/marshmallow-release/cmds/screenrecord/">screenrecord 160command</a> allows you to record everything that appears on the screen as an 161.mp4 file on disk. To implement, we have to receive composited frames from 162SurfaceFlinger, write them to the video encoder, and then write the encoded 163video data to a file. The video codecs are managed by a separate process 164(mediaserver) so we have to move large graphics buffers around the system. To 165make it more challenging, we're trying to record 60fps video at full resolution. 166The key to making this work efficiently is BufferQueue.</p> 167 168<p>The MediaCodec class allows an app to provide data as raw bytes in buffers, 169or through a <a href="{@docRoot}devices/graphics/arch-sh.html">Surface</a>. When 170screenrecord requests access to a video encoder, mediaserver creates a 171BufferQueue, connects itself to the consumer side, then passes the producer 172side back to screenrecord as a Surface.</p> 173 174<p>The screenrecord command then asks SurfaceFlinger to create a virtual display 175that mirrors the main display (i.e. it has all of the same layers), and directs 176it to send output to the Surface that came from mediaserver. In this case, 177SurfaceFlinger is the producer of buffers rather than the consumer.</p> 178 179<p>After the configuration is complete, screenrecord waits for encoded data to 180appear. As apps draw, their buffers travel to SurfaceFlinger, which composites 181them into a single buffer that gets sent directly to the video encoder in 182mediaserver. The full frames are never even seen by the screenrecord process. 183Internally, mediaserver has its own way of moving buffers around that also 184passes data by handle, minimizing overhead.</p> 185 186<h2 id=simulate-secondary>Case Study: Simulate secondary displays</h2> 187 188<p>The WindowManager can ask SurfaceFlinger to create a visible layer for which 189SurfaceFlinger acts as the BufferQueue consumer. It's also possible to ask 190SurfaceFlinger to create a virtual display, for which SurfaceFlinger acts as 191the BufferQueue producer. What happens if you connect them, configuring a 192virtual display that renders to a visible layer?</p> 193 194<p>You create a closed loop, where the composited screen appears in a window. 195That window is now part of the composited output, so on the next refresh 196the composited image inside the window will show the window contents as well 197(and then it's 198<a href="https://en.wikipedia.org/wiki/Turtles_all_the_way_down">turtles all the 199way down)</a>. To see this in action, enable 200<a href="http://developer.android.com/tools/index.html">Developer options</a> in 201settings, select <strong>Simulate secondary displays</strong>, and enable a 202window. For bonus points, use screenrecord to capture the act of enabling the 203display then play it back frame-by-frame.</p> 204