Android hwcomposer KMS

hwcomposer is the Android composition HAL that allows for the use of hardware-accelerated overlay layers to be shown on various displays.

KMS is the portion of the DRM driver concerned with 'mode setting' of a particular set of displays. It also allows for 'planes' to be shown over a single

'framebuffer'.

[insert diagram: hwc_kms_simple-boxes.png]

Goals

  1. Allow a hwcomposer implementation to use the DRM KMS API to show a single framebuffer on a display.
  2. Allow hwcomposer to show multiple layers on a display using KMS 'planes'
  3. Support hwcomposer's use of the Android sync framework to signal 'ownership' changes of layers' buffers
  4. Support more than one display

Non Goals

  1. Do not support SurfaceFlinger's 'virtual displays'.

  2. Do not support multiple composition devices. In particular do not support (for now) explicit use of a 2D blitter in addition to a display controllers


Components

  1. hwcomposer API implementation
  2. gralloc buffer metadata extractor
  3. KMS Display backend
  4. Interface to libsync (Android sync driver)

uses.png

  1. hwcomposer API implementation
    • This module provides an implementation of all of the hwcomposer API. It provides an abstraction for the Display backend implementation as well as handling any special behaviour of the API. Specifically:
      • ensure the calls to hwc:set() return immediately regardless of the mechanism used by the Display backend to avoid posting content before all layers' acquire fence has been signalled.
      • ensure that events from the display hardware are correctly handled (e.g. hotplug callbacks are appropriately serialised)
  2. Gralloc buffer metadata extraction
    • SurfaceFlinger supplies gralloc buffers to hwcomposer in each layer. These need to be converted into a dma_buf handle to the underlying buffer's memory pages and the associated metadata of dimensions and pixel format (converted into DRM 4CCs). This component is inherently platform-specific:

    • Implementations using the vanilla KMS backend are unlikely to need anything other than straightforward raster RGB pixel formats.
    • If the Display backend is attempting to use hardware overlays then more variation is expected. Examples might include:
      • YUV buffers from video or camera components
      • Special tiled YUV formats from hardware video components
      • Special tiled RGB buffers from GPUs
      • Handling of YUV luma ranges and colour matrices
  3. KMS Display backend
    • The KMS Display backend is intended to provide a hwcomposer implementation that will map onto a kernel driver that maps onto the current, vanilla DRM/KMS interface. This backend is expected to only support CTRC framebuffer operation (and no hardware overlays) and so all composition activity will be delegated back to the GPU.
  4. Android sync framework
    • Hwcoposer requires that the buffer for any layer is not shown until that layer's "acquire fence" has been signalled. At present no DRM/KMS implementations understand these fences and so we are required, in the interim, to handle this in userland. The libsync library exposes the ioctls required to wait in userland. However this introduces two problems:
      1. Waiting synchronously is at odds with the required 'return immediately' for hwc::set()
      2. These libsync APIs are marked as test-only interfaces


Deliverables

1.

hwcomposer module

GWG-NN

2.

Vanilla KMS backend

Tested against PL111 KMS on VExpress

GWG-NN

3.

Gralloc buffer metadata extraction

Initially limited to raster RGB formats for PL111

GWG-NN

4.

Experimental backends trialling atomic pageflip extensions to KMS API

GWG-NN


Implementation

composer.png

The Composer implements the API and handles all interaction with SurfaceFlinger (or equivalent user of hwcomposer).

The Composer has multiple Displays (one for each supported screen). If we support three screens then Composer will have three Displays.

A Display is the abstraction of the particular backend API to use. For use of a vanilla KMS driver there will be a KMSDisplay. For interacting with any other API (e.g. experimenting with KMS additions or something like an ADF driver) there will be a different Display instance.

Composer

All work from an API call is queued and processed in a separate worker thread. This is for two reasons:

  1. It allows us to always meet the requirement to return from hwc::set() immediately regardless of how the backend Display is implementing waiting for fences.
  2. It allows for slightly less locking of internal data structures with the side effect that calls to hwc::dump() will tend to report a more consistent state.

All calls into the backend Displays occur from this worker thread. Displays are handled in order.

Backends

Vanilla DRM/KMS backend

Supports only the most basic functionality - only a single full-screen layer with all composition falling back to the OpenGL implementation.

The actual 'modesetting' here is relatively basic - particularly for the internal screen as it is always assumed to be present and of fixed resolution.

API

init term prepare set blank dump getDisplayConfigs getDisplayAttributes set_vsync_enabled

init

Initializing the KMS display backend attempts to

  • - open the DRM device - get a connector, endcoder and CRTC for the display - find a preferred mode - set up a thread to handle events from the DRM device

The handling for the primary and another other displays will differ slightly since Android expects its primary display to always be present while any secondary screen may be added and removed as a result of a hotplug event.

term

Destroying the display not only involves returning any DRM CTRC, connector and encoder resources back to the DRM device but also ensuring that any sync fences for buffers added to the CRTC get signalled (otherwise they may leak) and that the vsync handling thread is shut down sensibly.

prepare

Because the basic DRM backend only supports a single, full-screen CRTC framebuffer the implementation for prepare is relatively straighforward - alllayers are marked HWC_FRAMEBUFFER and passed back to SurfaceFlinger for composition via OpenGL.

set

The only layer to update is the HWC_FRAMEBUFFER_TARGET output from OpenGL.

This layer will have a sync_fence that must have been signalled prior to setting the buffer as the current output. Because there is no sync_fence support in the vanilla DRM API this waiting will have to occur in userland as a blocking wait.

The memory underlying the buffer should be a dma_buf whose pages suitable for use by the display hardware. The dma_buf

  • is passed to the DRM driver via the PRIME API.

Finally the timeline for display allows us to return a sync_fence to inform the GL stack when the buffer is no longer on the screen and can be reused for future rendering or freed.

blank

Uses the DPMS API to change the display from a 'lit' to 'unlit' state.

dump

Dumo returns the internal state of the hwc itself. In the case of the KMS backend this is relatively straightforward as we only have a single (full screen) layer to report on.

getDisplayAttributes

Returns display attributes like width, height and screen DPI.

set_vsync_enabled

hwcomposer is required to periodically inform SurfaceFlinger of the display's VSYNC events via a callback. The drmWaitVBlank API call will allow us to wait for the next VBlank event so the backend here creates a worker thread whose sole purpose is to wait for VBlank then call out to the supplied callback.

WorkingGroups/Middleware/Graphics/HwcKms (last modified 2013-10-28 20:17:47)