Understanding Android Graphics Internals – SurfaceFlinger (III)

In this post, we discuss BufferQueue, BufferQueue::BufferSlot and BufferQueue::BufferState defined in frameworks/native/include/gui/BufferQueue.h.

  • BufferQueue

We have learned the concepts of ANativeWindow and ANativeWindowBuffer defined in system/core/include/system/window.h with class Surface (in frameworks/native/include/gui/Surface.h) being concrete implementation of the former class and GraphicBuffer (in frameworks/native/include/ui/GraphicBuffer.h) being an implementation of the latter. IGraphicBufferProducer (in frameworks/native/include/gui/IGraphicBufferProducer.h) defines the Binder API interface for buffer interactions between a surface and SurfaceFlinger. Therefore a UI may draw on a GraphicBuffer and by invoking eglSwitchBuffesr() to render the current buffer; Within eglSwitchBuffers() calls queueBuffer(), dequeueBuffer(), and other APIs in ANativeWindow as necessary.

What is yet to learn is how a graphic buffer queued through eglSwitchBuffers() is composed into frame buffer or hardware-over-laid for rendering and then how the buffer is released to the surface. Here we attempt to uncover part of the myth.

IGraphicBufferProducer was named after the relation of GraphiBuffer content producer and consumer. When a surface finishes drawing on a graphic buffer and subsequent calling of the Surface::queueBuffer() in eglSwitchBuffers() will invoke BpGraphicBufferProducer::queueBuffer() to pass the graphic buffer  (through BufferQueue::queueBuffer())to a BufferQueue object in the Layer object corresponding to the Surface object.

BufferQueue implements BnGraphicBufferProducer and provides the graphic Buffer consumer APIs( e.g. acquireBuffer(), releaseBuffer(), etc.), Going forward, we use a more formal term frame to denote the content in the graphic buffer.

The Layer class implements SurfaceFlingerConsumer::FrameAvailableListener::onFrameAvailable() is set to be invoked in BufferQueue::queueBuffer(); Layer::onFrameAvailable () marks arrival of a new frame and signals to SurfaceFlinger by a signalLayerUpdate() call. The signalLayerUpdate() will either request a vsync on behalf of the surface or post a MessageQueue::INVALIDATE message.

  • BufferQueue::BufferSlot and BufferQueue::BufferSlot::BufferState.

Within BufferQueue, a GraphicBuffer object is assigned a descriptor BufferSlot object to contain attribute metadata such as  associated EGLDisplay, timestamp, transform, cropping, framenumber, fence, buffer state, and so on.

BufferQueue::BufferSlot::BufferState  represents the different states in which a buffer slot can be. SurfaceFlinger recognizes four buffer states, namely, FREE, DEQUED, QUEUED, ACQUIRED, respectively. You may refer to the BufferQueue.h for further information.

BufferQueue tracks all BufferSlots in an array and index each slot by a cardinal slot number, which is reference as buffer in IGraphicBufferProducer.

Before ending this post, I want to note that in BufferQueue::acquireBuffer(), an argument type BufferItem is used, which is sort of equivalent to BufferQueue::BufferSlot.

Leave a comment