SDV Media: managing displays

SDV Media exposes available displays to OEM applications with Linux DRM API.

Interaction between DRM components

  • Framebuffer is a source of pixel data, backed by some externally allocated memory buffer.

  • Plane is an image source used by CRTC. It is associated with a framebuffer, and may represent a cropped view of the framebuffer.

  • CRTC represents an overall display pipeline. It may combine multiple planes to create the final video output, and dispatch the output to multiple encoders.

  • Encoder converts video output from CRTC into a form suitable for specific connector.

  • Connector represents an available display connector. For example, an HDMI port.

For more in-depth description, refer to:

API surface

SDV Media provides the Linux DRM interfaces. While they can be used directly using ioctl syscall, for application development it is recommended to use a userspace helper library. For example:

Set up rendering to a single display

  1. Open a DRM device (/dev/dri/card*) and use Linux DRM APIs (e.g. through libdrm) on its file descriptor to select the display and its mode.

    Usually, the host system will only expose a single virtual GPU device, which will show up as /dev/dri/card0.

  2. Allocate front and back buffers with Linux DRM API.

    It's recommended to use minigbm's gbm_bo_create() and get the DMA-BUF file descriptor with gbm_bo_get_fd().

  3. Create GL framebuffers backed by the allocated buffers.

    1. Create an EGLImage out of the DRM buffer with eglCreateImageKHR with EGL_LINUX_DMA_BUF_EXT (from EGL_EXT_image_dma_buf_import extension).

    2. Create a GL texture and use glEGLImageTargetTexture2DOES (from GL_OES_EGL_image extension) to set the texture's storage to the EGLImage from previous step.

    3. Create a GL framebuffer and use glFramebufferTexture2D to set its backing texture to the one created in the previous step.

  4. To render a frame:

    1. Bind one of the created GL framebuffers.

    2. Draw a frame with usual GLES APIs.

    3. Display the frame on a screen: use Linux DRM API (drmModeAtomicCommit()) to send a DRM_MODE_PAGE_FLIP_EVENT with the DMA-BUF file descriptor used by the bound GL framebuffer.

Compose video output from multiple layers

For hardware accelerated multi-layer (multi-plane) composition, we rely on the host system exposing each layer as a separate DRM connector (virtual display), and mapping them to the right hardware location / pipeline.

See Setup rendering to multiple displays for details.

Set up rendering to multiple displays

  1. Open the /dev/dri/card* DRM device as in the single-display flow.

  2. List available display connectors.

    Each display is exposed as a separate DRM connector of the DRM device.

  3. For each display connector:

    1. Select a CRTC compatible with the connector. Each connector has a list of available encoders, and each encoder indicates which CRTCs it can be used with. There will always be at least one compatible CRTC.

      1. Select a plane compatible with the CRTC.

      2. Create DRM framebuffers backed by the a GPU buffers. This process looks the same as for single-display variant.

      3. Connect plane, CRTC and connector, and set the video mode on the CRTC.

        It's possible to set the mode of multiple displays at the same time by using the atomic API for setting following DRM properties for each connector, CRTC, and plane set.

    The full list of necessary properties:

    Target Property Type Description
    connector CRTC_ID CRTC ID ID of the CRTC to assign to the connector
    CRTC MODE_ID blob ID ID of a property blob created using drmModeCreatePropertyBlob, containing the drmModeModeInfo struct of the selected video mode
    CRTC ACTIVE bool true to mark the CRTC as active
    plane FB_ID framebuffer ID ID of the DRM framebuffer to display on screen
    plane SRC_X pixels X coordinate of the framebuffer source image rectangle
    plane SRC_Y pixels Y coordinate of the framebuffer source image rectangle
    plane SRC_W 16.16 fixed point width of the framebuffer source image rectangle (pixels shifted left by 16 bits)
    plane SRC_H 16.16 fixed point height of the framebuffer source image rectangle (pixels shifted left by 16 bits)
    plane CRTC_X pixels X coordinate of the CRTC destination image rectangle
    plane CRTC_Y pixels Y coordinate of the CRTC destination image rectangle
    plane CRTC_W pixels width of the CRTC destination image rectangle
    plane CRTC_H pixels height of the CRTC destination image rectangle
  4. Enter the render loop:

    1. Wait for the page flip event on a CRTC before rendering the next frame.

    2. Render a frame and display it on the screen by scheduling a page flip for given CRTC+framebuffer.