1page.title=Surface and SurfaceHolder 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>The 28<a href="http://developer.android.com/reference/android/view/Surface.html">Surface</a> 29class has been part of the public API since 1.0. Its description simply says, 30"Handle onto a raw buffer that is being managed by the screen compositor." The 31statement was accurate when initially written but falls well short of the mark 32on a modern system.</p> 33 34<p>The Surface represents the producer side of a buffer queue that is often (but 35not always!) consumed by SurfaceFlinger. When you render onto a Surface, the 36result ends up in a buffer that gets shipped to the consumer. A Surface is not 37simply a raw chunk of memory you can scribble on.</p> 38 39<p>The BufferQueue for a display Surface is typically configured for 40triple-buffering; but buffers are allocated on demand. So if the producer 41generates buffers slowly enough -- maybe it's animating at 30fps on a 60fps 42display -- there might only be two allocated buffers in the queue. This helps 43minimize memory consumption. You can see a summary of the buffers associated 44with every layer in the <code>dumpsys SurfaceFlinger</code> output.</p> 45 46<h2 id="canvas">Canvas Rendering</h2> 47 48<p>Once upon a time, all rendering was done in software, and you can still do this 49today. The low-level implementation is provided by the Skia graphics library. 50If you want to draw a rectangle, you make a library call, and it sets bytes in a 51buffer appropriately. To ensure that a buffer isn't updated by two clients at 52once, or written to while being displayed, you have to lock the buffer to access 53it. <code>lockCanvas()</code> locks the buffer and returns a Canvas to use for drawing, 54and <code>unlockCanvasAndPost()</code> unlocks the buffer and sends it to the compositor.</p> 55 56<p>As time went on, and devices with general-purpose 3D engines appeared, Android 57reoriented itself around OpenGL ES. However, it was important to keep the old 58API working, for apps as well as app framework code, so an effort was made to 59hardware-accelerate the Canvas API. As you can see from the charts on the 60<a href="http://developer.android.com/guide/topics/graphics/hardware-accel.html">Hardware 61Acceleration</a> 62page, this was a bit of a bumpy ride. Note in particular that while the Canvas 63provided to a View's <code>onDraw()</code> method may be hardware-accelerated, the Canvas 64obtained when an app locks a Surface directly with <code>lockCanvas()</code> never is. 65As of API 23, a hardware-accelerated Canvas can be obtained from a Surface using 66<code>lockHardwareCanvas()</code> instead.</p> 67 68<p>When you lock a Surface for Canvas access, the "CPU renderer" connects to the 69producer side of the BufferQueue and does not disconnect until the Surface is 70destroyed. Most other producers (like GLES) can be disconnected and reconnected 71to a Surface, but the Canvas-based "CPU renderer" cannot. This means you can't 72draw on a surface with GLES or send it frames from a video decoder if you've 73ever locked it for a Canvas.</p> 74 75<p>The first time the producer requests a buffer from a BufferQueue, it is 76allocated and initialized to zeroes. Initialization is necessary to avoid 77inadvertently sharing data between processes. When you re-use a buffer, 78however, the previous contents will still be present. If you repeatedly call 79<code>lockCanvas()</code> and <code>unlockCanvasAndPost()</code> without 80drawing anything, you'll cycle between previously-rendered frames.</p> 81 82<p>The Surface lock/unlock code keeps a reference to the previously-rendered 83buffer. If you specify a dirty region when locking the Surface, it will copy 84the non-dirty pixels from the previous buffer. There's a fair chance the buffer 85will be handled by SurfaceFlinger or HWC; but since we need to only read from 86it, there's no need to wait for exclusive access.</p> 87 88<p>The main non-Canvas way for an application to draw directly on a Surface is 89through OpenGL ES. That's described in the <a href="#eglsurface">EGLSurface and 90OpenGL ES</a> section.</p> 91 92<h2 id="surfaceholder">SurfaceHolder</h2> 93 94<p>Some things that work with Surfaces want a SurfaceHolder, notably SurfaceView. 95The original idea was that Surface represented the raw compositor-managed 96buffer, while SurfaceHolder was managed by the app and kept track of 97higher-level information like the dimensions and format. The Java-language 98definition mirrors the underlying native implementation. It's arguably no 99longer useful to split it this way, but it has long been part of the public API.</p> 100 101<p>Generally speaking, anything having to do with a View will involve a 102SurfaceHolder. Some other APIs, such as MediaCodec, will operate on the Surface 103itself. You can easily get the Surface from the SurfaceHolder, so hang on to 104the latter when you have it.</p> 105 106<p>APIs to get and set Surface parameters, such as the size and format, are 107implemented through SurfaceHolder.</p> 108