Surface objects enable apps to render images to be presented on screens. SurfaceHolder interfaces enable apps to edit and control surfaces.
Surface
A surface is an interface for a producer to exchange buffers with a consumer.
The BufferQueue for a display surface is typically configured for
triple-buffering. Buffers are allocated on demand, so if the producer
generates buffers slowly enough, such as at 30 fps on a 60 fps
display, there might only be two allocated buffers in the queue.
Allocating buffers on demand helps
minimize memory consumption. You can see a summary of the buffers associated
with every layer in the dumpsys SurfaceFlinger
output.
Most clients render onto surfaces using OpenGL ES or Vulkan. However, some clients render onto surfaces using a canvas.
Canvas rendering
The canvas implementation is provided by the Skia Graphics Library. If you want to draw a rectangle, you call the Canvas API, which sets bytes in a buffer appropriately. To ensure that a buffer isn't updated by two clients at once, or written to while being displayed, lock the buffer to access it. Use the following commands to work with canvas locks:
lockCanvas()
locks the buffer for rendering on the CPU and returns a Canvas to use for drawing.unlockCanvasAndPost()
unlocks the buffer and sends it to the compositor.lockHardwareCanvas()
locks the buffer for rendering on the GPU and returns a canvas to use for drawing.
The first time the producer requests a buffer from a BufferQueue, the
buffer is
allocated and initialized to zero. Initialization is necessary to avoid
inadvertently sharing data between processes. However, if you reuse a buffer,
the previous contents are still present. If you repeatedly call
lockCanvas()
and unlockCanvasAndPost()
without
drawing anything, the producer cycles between previously rendered frames.
The surface lock/unlock code keeps a reference to the previously rendered buffer. If you specify a dirty region when locking the surface, it copies the nondirty pixels from the previous buffer. SurfaceFlinger or HWC typically handle the buffer; but because we only need to read from the buffer, there's no need to wait for exclusive access.
SurfaceHolder
A SurfaceHolder is an interface the system uses to share ownership of surfaces with apps. Some clients that work with surfaces want a SurfaceHolder, because APIs to get and set surface parameters are implemented through a SurfaceHolder. A SurfaceView contains a SurfaceHolder.
Most components that interact with a view involve a SurfaceHolder. Some other APIs, such as MediaCodec, operate on the surface itself.