Qt 5.6 | Qt for Embedded Linux

Qt 5.6.3 Reference Documentation

# Qt for Embedded Linux

Since the Qt 5.0 release, Qt no longer contains its own window system (QWS) implementation. For single-process use cases, the Qt Platform Abstraction is a superior solution. Multiple graphical processes can be supported through Wayland.

There are multiple platform plugins that are potentially usable on Embedded Linux systems: EGLFS, LinuxFB, KMS, DirectFB, Wayland. The availability of these depend on the configuration of Qt. The default platform plugin is also device-specific. For instance, on many boards eglfs is chosen as the default one. If the default is not suitable, the `QT_QPA_PLATFORM` environment variable parameter can be used to request another plugin. Alternatively, for quick tests, the `-platform` command-line can be used with the same syntax.

## Configuring a Specific Device

Building Qt for a given device requires a toolchain and a sysroot. Additionally, some devices require vendor-specific adaptation code for EGL and OpenGL ES 2.0 support. This is not relevant for non-accelerated platforms, for example the ones using the LinuxFB plugin, which is meant for software-based rendering only. This means Qt Quick 2 is not functional in such a setup as it depends on OpenGL for rendering.

The directory qtbase/mkspecs/devices contains configuration and graphics adaptation code for a number of devices. For example, the `linux-rasp-pi2-g++` mkspec contains build settings such as the optimal compiler and linker flags for the Raspberry Pi 2 device. The mkspec also contains information about either an implementation of the eglfs hooks (vendor-specific adaptation code), or a reference to the suitable eglfs device integration plugin. The device is selected through the configure tool's `-device` parameter. The name that follows after this argument must, at least partially, match one of the subdirectories under devices.

The following is an example configuration for the Raspberry Pi 2. For most Embedded Linux boards, the configure command looks similar:

      ./configure -release -opengl es2 -device linux-rasp-pi2-g++ -device-option CROSS_COMPILE=$TOOLCHAIN/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian/bin/arm-linux-gnueabihf- -sysroot $ROOTFS -prefix /usr/local/qt5

The most important parameters are `-device` and `-sysroot`. By specifying `-sysroot`, the include files and libraries used by `configure`'s feature detection tests, as well as Qt itself, is taken from the specified location, instead of the host PC's standard locations. This means that installing development packages on the host machine has no relevance. For example, to get `libinput` support it is not sufficient or necessary to have the `libinput` development headers and libraries installed on the host environment. Instead, the headers and the libraries for the target architecture (e.g. ARM) must be present in the `sysroot`.

`pkg-config` is supported also when performing cross-compilation. `configure` automatically sets `PKG_CONFIG_LIBDIR` to make `pkg-config` report compiler and linker settings based on the `sysroot` instead of the host machine. This usually functions well without any further adjustments. However, environment variables such as `PKG_CONFIG_PATH` must be unset for the host machine before running `configure`. Otherwise, the Qt build may attempt to use inappropriate headers and libraries from the host system.

Specifying `-sysroot` results in automatically setting the `--sysroot` argument when invoking the compiler. In some cases this is not desirable and can be disabled by passing `-no-gcc-sysroot` to `configure`.

`-prefix`, `-extprefix` and `-hostprefix` control the intended destination directory of the Qt build. In the above example the ARM build of Qt is expected to be placed in `/usr/local/qt5` on the target device. Note that running `make install` does not deploy anything to the device. Instead, the `install` step targets the directory specified by `extprefix` which defaults to `sysroot` + `prefix` and is therefore optional. However, in many cases "polluting" the sysroot is not desirable and thus specifying `-extprefix` becomes important. Finally, `-hostprefix` allows separating host tools like qmake, rcc, uic from the binaries for the target. When given, such tools will be installed under the specified directory instead of `extprefix`.

See Qt Configure Options for more information.

## Platform Plugins for Embedded Linux Devices

### EGLFS

EGL is an interface between OpenGL and the native windowing system. Qt can use EGL for context and surface management, however the API contains no platform-specifics: The creation of a native window (which will not necessarily be an actual window on the screen) must still be done by platform-specific means. Hence the need for the board or GPU-specific adaptation code. Such adaptations are provided either as eglfs hooks, which can be a single source file compiled into the platform plugin, or as dynamically loaded EGL device integration plugins.

EGLFS is a platform plugin for running Qt5 applications on top of EGL and OpenGL ES 2.0 without an actual windowing system (like X11 or Wayland). In addition to Qt Quick 2 and native OpenGL applications, it supports software-rendered windows (for example QWidget) too. In the latter case the widgets' contents are rendered using the CPU into images, which are then uploaded into textures and composited by the plugin.

This is the recommended plugin for modern Embedded Linux devices that include a GPU.

EGLFS forces the first top-level window (be it either a QWidget or a QQuickView) to become fullscreen. This window is also chosen to be the root widget window into which all other top-level widgets (for example dialogs, popup menus or combobox dropdowns) are composited. This is necessary because with EGLFS there is always exactly one native window and EGL window surface, and these belong to the widget or window that is created first. This approach works well when there is a main window that exists for the entire lifetime of the application and all other widgets are either non top-levels or are created afterwards, once the main window is shown.

There are further restrictions for OpenGL-based windows. As of Qt 5.3, `eglfs` supports a single fullscreen GL window (for example, an OpenGL-based QWindow, a QQuickView or a QGLWidget). Opening additional OpenGL windows or mixing such windows with QWidget-based content is not supported and terminates the application with an error message.

If necessary, `eglfs` can be configured using the following environment variables:

- `QT_QPA_EGLFS_FB` - Overrides the framebuffer device. The default is `/dev/fb0`. On most embedded platforms this is not very relevant because the framebuffer is used only for querying settings like the display dimensions. On certain devices however, this parameter provides the ability to specify the display to be used in multiple display setups, similarly to the `fb` parameter in LinuxFB.
- `QT_QPA_EGLFS_WIDTH` and `QT_QPA_EGLFS_HEIGHT` - Contain the screen width and height in pixels. While `eglfs` tries to determine the dimensions from the framebuffer device /dev/fb0, but this does not work always and manually specifying the sizes may become necessary.
- `QT_QPA_EGLFS_PHYSICAL_WIDTH` and `QT_QPA_EGLFS_PHYSICAL_HEIGHT` - Physical screen width and height in millimeters. On platforms where the framebuffer device /dev/fb0 is not available or the query is not successful, the values are calculated based on a default DPI of 100. This variable can be used to override any such defaults.
- `QT_QPA_EGLFS_DEPTH` - Overrides the color depth for the screen. On platforms where the framebuffer device /dev/fb0 is not available or the query is not successful, the default of `32` is used. This variable can be used to override any such defaults. Note that this affects only the color depth value reported by QScreen. It has no connection to EGL configurations and the color depth used for OpenGL rendering.
- `QT_QPA_EGLFS_SWAPINTERVAL` - By default a swap interval of `1` will be requested. This enables synchronizing to the displays vertical refresh. The value can be overridden with this environment variable. For instance, passing 0 will disable blocking on swap, resulting in running as fast as possible without any synchronization.
- `QT_QPA_EGLFS_FORCEVSYNC` - When set, `eglfs` requests `FBIO_WAITFORVSYNC` on the framebuffer device.
- `QT_QPA_EGLFS_FORCE888` - When set, the red, green, and blue color channel sizes are ignored whenever creating a new context, window or offscreen surface. Instead, the plugin requests a configuration with 8 bits per channel. This can be helpful on devices where configurations with less than 32 or 24 bits per pixel are chosen by default but are known to be not suitable, for example, due to banding effects. Instead of changing all the applications, this variable provides an easier shortcut to force 24/32 bpp configurations for a given device.
- `QT_QPA_EGLFS_DEBUG` - When set, some debugging information is printed on the debug output. For example, the input QSurfaceFormat and the properties of the chosen EGL configuration are printed while creating a new context. Together with Qt Quick's `QSG_INFO` variable, this can provide useful information for troubleshooting issues related to the EGL configuration.
- `QT_QPA_EGLFS_INTEGRATION` - In addition to the compiled-in hooks, it is also possible to provide device or vendor-specific adaptation in the form of dynamically loaded plugins. This environment variable enforces a specific plugin. For example, setting it to eglfs_kms uses the KMS/DRM backend. This is only an option when no static or compiled-in hooks were specified in the device makespecs. In practice, the traditional compiled-in hooks are rarely used, almost all backends are now migrated to plugins. The device makespecs still contain a relevant `EGLFS_DEVICE_INTEGRATION` entry: the name of the preferred backend for that particular device. This is optional, but very useful to avoid the need to set this environment variable in case there are more than one plugins present in the target system. In a desktop environment the KMS or X11 backends are prioritized, depending on the presence of the `DISPLAY` environment variable. Note that on some boards the special value of `none` is used instead of an actual plugin. This indicates that no special integration is necessary to use EGL with the framebuffer and so no plugins must be loaded.

In addition to `QT_QPA_EGLFS_DEBUG`, `eglfs` also supports the more modern categorized logging system of Qt. The following logging categories are available:

- `qt.qpa.egldeviceintegration` – Enables logging for dynamically loaded backends. Very useful to check what backend is in use.
- `qt.qpa.input` – Enables debug output both from the `evdev` and `libinput` input handlers. Very useful to check if a given input device was recognized and opened.
- `qt.qpa.eglfs.kms` – Enables verbose logging in the KMS/DRM backend.

### LinuxFB

This plugin writes directly to the framebuffer. Only software-rendered content is supported. Note that on some setups the display performance is expected to be limited.

The `linuxfb` plugin allows specifying additional settings by passing them in the `QT_QPA_PLATFORM` environment variable or `-platform` command-line option. For example, `QT_QPA_PLATFORM=linuxfb:fb=/dev/fb1` specifies that the framebuffer device `/dev/fb1` must be used instead of the default `fb0`. Multiple settings can be specified by separating them with a colon.

- `fb=/dev/fbN` - Specifies the framebuffer devices. On multiple display setups this typically allows running the application on different displays. For the time being there is no way to use multiple framebuffers from one Qt application.
- `size=`<width>`x`<height> - Specifies the screen size in pixels. The plugin tries to query the display dimensions, both physical and logical, from the framebuffer device. This may not always lead to proper results however, and therefore it may become necessary to explicitly specify the values.
- `mmsize=`<width>`x`<height> - Physical width and height in millimeters.
- `offset=`<width>`x`<height> - Offset in pixels specifying the top-left corner of the screen. The default position is at `(0, 0)`.
- `nographicsmodeswitch` - Do not switch the virtual terminal to graphics mode (`KD_GRAPHICS`). In addition to switching to graphics mode, the blinking cursor and screen blanking are normally disabled too. When this parameter is set, these are also skipped.
- `tty=/dev/ttyN` - Overrides the virtual console. Only used when `nographicsmodeswitch` is not set.

## Input

When no windowing system is present, the mouse, keyboard, and touch input are read directly via `evdev` or using helper libraries such as `libinput` or `tslib`. Note that this requires that device nodes `/dev/input/event*` are readable by the user. `eglfs` and `linuxfb` have all the input handling code compiled-in.

### Using libinput

libinput is a library to handle input devices. It offers an alternative to the Qt's own `evdev` input support. To enable using `libinput`, make sure the development files for `libudev` and `libinput` are available when configuring and building Qt. `xkbcommon` is also necessary if keyboard support is desired. With `eglfs` and `linuxfb` no further actions are necessary as these plugins use `libinput` by default. If `libinput` support is not available or the environment variable `QT_QPA_EGLFS_NO_LIBINPUT` is set, Qt's own evdev handlers come in to play.

### Input on eglfs and linuxfb without libinput

Parameters like the device node name can be set in the environment variables `QT_QPA_EVDEV_MOUSE_PARAMETERS`, `QT_QPA_EVDEV_KEYBOARD_PARAMETERS` and `QT_QPA_EVDEV_TOUCHSCREEN_PARAMETERS`. Additionally, the built-in input handlers can be disabled by setting `QT_QPA_EGLFS_DISABLE_INPUT` or `QT_QPA_FB_DISABLE_INPUT` to `1`. On some touch screens the coordinates must be rotated, which is done by setting `QT_QPA_EVDEV_TOUCHSCREEN_PARAMETERS` to `rotate=180`.

### Mouse

The mouse cursor shows up whenever `QT_QPA_EGLFS_HIDECURSOR` (for eglfs) or `QT_QPA_FB_HIDECURSOR` (for linuxfb) is not set and Qt's libudev-based device discovery reports that at least one mouse is available. When `libudev` support is not present, the mouse cursor always show up unless explicitly disabled via the environment variable.

Hot plugging is supported, but only if Qt was configured with `libudev` support (that is, if the libudev development headers are present in the sysroot at configure time). This allows connecting or disconnecting an input device while the application is running.

### Keyboard

The evdev keyboard handler supports the following extra parameters:

- `/dev/input/...` - Specifies the name of the input device. When not given, Qt looks for a suitable device either via libudev or by walking through the available nodes.
- `grab` - Enables grabbing the input device.
- `keymap` - Specifies the name of a custom keyboard map file.
- `enable-compose` - Enables compositing.
- `repeat-delay` - Sets a custom key repeat delay.
- `repeat-rate` - Sets a custom key repeat rate.

On Embedded Linux systems that do not have their terminal sessions disabled, the behavior on a key press can be confusing as input event is processed by the Qt application and the tty. To overcome this, the following options are available:

- EGLFS and LinuxFB attempt to disable the terminal keyboard on application startup by setting the tty's keyboard mode to `K_OFF`. This prevents keystrokes from going to the terminal. If the standard behavior needs to be restored for some reason, set the environment variable `QT_QPA_ENABLE_TERMINAL_KEYBOARD` to `1`. Note that this works only when the application is launched from a remote console (for example, via `ssh`) and the terminal keyboard input remains enabled.
- An alternative approach is to use the evdev keyboard handler's `grab` parameter by passing grab=1 in `QT_QPA_EVDEV_KEYBOARD_PARAMETERS`. This results in trying to get a grab on the input device. If the `grab` is successful, no other components in the system receive events from it as long as the Qt application is running. This approach is more suitable for applications started remotely as it does not need access to the tty device.
- Finally, for many specialized Embedded Linux images it does not make sense to have the standard terminal sessions enabled in the first place. Refer to your build environment's documentation on how to disable them. For example, when generating images using the Yocto Project, unsetting `SYSVINIT_ENABLED_GETTYS` results in having no `getty` process running, and thus no input, on any of the virtual terminals.

If the default built-in keymap is not sufficient, a different one can be specified either via the `keymap` parameter or by using the eglfs-specific loadKeymap() function. The latter allows switching the keymap at runtime. Note however that this requires using eglfs' built-in keyboard handler; it is not supported when the keyboard handler is loaded via the `-plugin` command-line parameter.

Note: Special system key combinations, such as console switching (Ctrl+Alt+Fx) or zap (Ctrl+Alt+Backspace) are not currently supported and are ignored.

To generate a custom keymap, the kmap2qmap utility can be used. This can be found in the qttools module. The source files have to be in standard Linux `kmap` format, which is understood by the kernel's `loadkeys` command. This means one can use the following sources to generate `qmap` files:

- The Linux Console Tools (LCT) project.
- Xorg X11 keymaps can be converted to the `kmap` format with the `ckbcomp` utility.
- As `kmap` files are plain-text files, they can also be hand crafted.

`kmap2qmap` is a command line program, that needs at least 2 files as parameters. The last one is the generated `.qmap` file, while all the others are parsed as input `.kmap` files. For example:

      kmap2qmap i386/qwertz/de-latin1-nodeadkeys.kmap include/compose.latin1.inc de-latin1-nodeadkeys.qmap

Note: `kmap2qmap` does not support all the (pseudo) symbols that the Linux kernel supports. When converting a standard keymap, a number of warnings will be shown regarding `Show_Registers`, `Hex_A`, and so on; these messages can safely be ignored.

### Touch

For some resistive, single-touch touch screens it may be necessary to fall back to using `tslib` instead of relying on the Linux multi-touch protocol and the event devices. For modern touch screens this is not necessary. `tslib` support can be enabled by setting the environment variable `QT_QPA_EGLFS_TSLIB` or `QT_QPA_FB_TSLIB` to 1. To change the device, set the environment variable `TSLIB_TSDEVICE` or pass the device name on the command-line. Note that the `tslib` input handler generates mouse events and supports single touch only, as opposed to `evdevtouch` which generates true multi-touch QTouchEvent events too.

### Pen-based tablets

The `evdevtablet` plugin provides basic support for Wacom and similar, pen-based tablets. It generates QTabletEvent events only. To enable it, pass `QT_QPA_GENERIC_PLUGINS=evdevtablet` in the environment or, alternatively, pass `-plugin evdevtablet` argument on the command-line. The plugin can take a device node parameter, for example `QT_QPA_GENERIC_PLUGINS=evdevtablet:/dev/event1`, in case the Qt's automatic device discovery (based either on libudev or a walkthrough of `/dev/input/event*`) is not functional or misbehaving.

### Debugging Input Devices

It is possible to print some information to the debug output by enabling the `qt.qpa.input` logging rule, for example by setting the `QT_LOGGING_RULES` environment variable to `qt.qpa.input=true`. This is useful for detecting which device is being used, or to troubleshoot device discovery issues.

### Using Custom Mouse Cursor Images

`eglfs` comes with its own set of 32x32 sized mouse cursor images. If these are not sufficient, a custom cursor atlas can be provided by setting the `QT_QPA_EGLFS_CURSOR` environment variable to the name of a JSON file. The file can also be embedded into the application via Qt's resource system.

For example, an embedded cursor atlas with 8 cursor images per row can be specified like the following:

      {
        "image": ":/cursor-atlas.png",
        "cursorsPerRow": 8,
        "hotSpots": [
            [7, 2],
            [12, 3],
            [12, 12],
            ...
        ]
      }

Note that the images are expected to be tightly packed in the atlas: the width and height of the cursors are decided based on the total image size and the `cursorsPerRow` setting. Atlases have to provide an image for all the supported cursors.

## Display Output

When having multiple displays connected, the level of support for targeting one or more of these from one single Qt application varies between the platform plugins and often depends on the device and its graphics stack.

### eglfs with eglfs_kms backend

When the KMS/DRM backend is in use, eglfs reports all available screens in QGuiApplication::screens(). Applications can target different screens with different windows via QWindow::setScreen(). Note however that the restriction of one single fullscreen window per screen still applies.

When getting started with developing on a given embedded device, it is often necessary to verify the behavior of the device and drivers, and that the connected displays are working as they should. One easy way is to use the hellowindow example. Launching it with `-platform eglfs --multiscreen --timeout` arguments shows a rotating Qt logo on each connected screen for a few seconds.

The KMS/DRM backend also supports custom configurations via a JSON file. Set the environment variable `QT_QPA_EGLFS_KMS_CONFIG` to the name of the file to enable this. The file can also be embedded into the application via the Qt resource system. An example configuration is below:

      {
        "device": "/dev/dri/card1",
        "hwcursor": false,
        "pbuffers": true,
        "outputs": [
          {
            "name": "VGA1",
            "mode": "off"
          },
          {
            "name": "HDMI1",
            "mode": "1024x768"
          }
        ]
      }

Here we configure the specified device so that

- it will not use the hardware cursor (falls back to rendering the mouse cursor via OpenGL; by default hardware cursors are enabled as they are more efficient),
- it will back QOffscreenSurface with standard EGL pbuffer surfaces (by default this is disabled and a gbm surface is used instead),
- output on the VGA connector is disabled, while HDMI is active with a resolution of 1024x768.

Additionally, such a configuration also disables looking for a device via `libudev` and instead the specified device is used.

For troubleshooting it might be useful to enable debug logs from the KMS/DRM backend. To do this, enable the categorized logging rule, `qt.qpa.eglfs.kms`.

### eglfs with eglfs_kms_egldevice backend

This backend, typically used on Tegra devices, is similar to the KMS/DRM backend mentioned above, except that it relies on the EGLDevice and EGLStream extensions instead of GBM.

For technical details about this approach, check out this presentation.

Multiple screens are not currently supported by this backend. Instead, it will find the first available display and pick the EGL layer that corresponds to it. When necessary, this can be overridden by setting the `QT_QPA_EGLFS_LAYER_INDEX` environment variable to the index of the desired layer. To see which layers are available, and to debug potential startup issues, enable the logging category `qt.qpa.eglfs.kms`. In some cases it may be necessary to perform a video mode set on application startup even when the screen reports that the desired resolution is already set. This is normally optimized away, but if the screen stays powered down, try setting the environment variable `QT_QPA_EGLFS_ALWAYS_SET_MODE` to a non-zero value and relaunch the application.

### eglfs with other backends

Other backends, that are typically based on targeting the framebuffer or a composition API directly via the vendor's EGL implementation, usually provide limited or no support for multiple displays. On i.MX6-based boards with Vivante GPUs the `QT_QPA_EGLFS_FB` environment variable can be used to specify the framebuffer to target, similarly to linuxfb. On the Raspberry Pi the `QT_QPA_EGLFS_DISPMANX_ID` environment variable can be used to specify the screen to output to. The value corresponds to one of the `DISPMANX_ID_` constants, refer to the Dispmanx documentation. Note that these approaches, unlike KMS/DRM, will not typically allow to output to multiple screens from the same application. Alternatively, driver-specific environment variables or kernel parameters may also be available as well to control the used framebuffer. Refer to the embedded board's documentation.

### Video Memory

Systems with a fixed amount of dedicated video memory may need extra care before running Qt application based on Qt Quick or classes like QOpenGLWidget. The default setting may be insufficient for such applications, especially when they are displayed on a high resolution (for example, full HD) screen. In this case, they may start failing in unexpected ways. It is recommended to ensure that there is at least 128 MB of GPU memory available. For systems that do not have a fixed amount of memory reserved for the GPU this is not an issue.

### linuxfb

Use the `fb` plugin parameter to specify the framebuffer device to use.

## Unix Signal Handlers

The console-oriented platform plugins like eglfs and linuxfb install signal handlers by default to capture interrupt (`SIGINT`), suspend and continue (`SIGTSTP`, `SIGCONT`) and termination (`SIGTERM`). This way the keyboard, terminal cursor, and possibly other graphics state can be restored when the application terminates or gets suspended due to `kill`, or `Ctrl+C` or `Ctrl+Z`. (although terminating or suspending via the keyboard is only possible when `QT_QPA_ENABLE_TERMINAL_KEYBOARD` is set, as outlined above in the Input section). However, in some cases capturing `SIGINT` can be undesirable as it may conflict with remote debugging for instance. Therefore, the environment variable `QT_QPA_NO_SIGNAL_HANDLER` is provided to opt out from all built-in signal handling.

## Platform Plugins for Windowing Systems on Embedded Linux Devices

### XCB

This is the X11 plugin used on regular desktop Linux platforms. In some embedded environments, that provide X and the necessary development files for xcb, this plugin functions just like it does on a regular PC desktop.

Note: On some devices there is no EGL and OpenGL support available under X because the EGL implementation is not compatible with Xlib. In this case the XCB plugin is built without EGL support, meaning that Qt Quick 2 or other OpenGL-based applications does not work with this platform plugin. It can still be used however to run software-rendered applications (based on QWidget for example).

As a general rule, the usage of XCB on embedded devices is not advisable. Plugins like eglfs are likely to provide better performance, and hardware acceleration.

### Wayland

Wayland is a light-weight windowing system; or more precisely, it is a protocol for clients to talk to a display server.

The Qt Wayland module provides a `wayland` platform plugin that allows Qt application to connect to a Wayland compositor.

Note: You may experience issues with touch screen input while using the Weston reference compositor. Refer to the Qt Wiki for further information.

## Related Topics

- Qt for Device Creation
- Emulator
- Qt Virtual Keyboard