[[PageOutline]] = Qt For Embedded Linux See also: - wiki:Yocto/qt - With 3D Demo shown - wiki:buildroot/qt - QT for Buildroot OS = Platform Plugins On Embedded Linux systems there are multiple 'platform plugins' that can be used for backend display such as EGLFS, LinuxFB, DirectFB, or Wayland. The availability of these plugins depends on how Qt is configured. Note that as of Qt 5.0 Qt no longer has its own window system (QWS) implementation as for single-process use cases the Qt Platform Abstraction is a superior solution. If you need support for a multi-process compositing window manager use the Wayland platform plugin and run a Wayland server. List platform plugins: {{{#!bash ls /usr/lib/arm-linux-gnueabihf/qt5/plugins/platforms }}} The platform plugin is specified in one of two ways:  * running app with '-platform ' cmdline options  * defining QT_QPA_PLATFORM env variable [=#eglfs] == EGLFS EGL is an interface between OpenGL and the native windowing system. 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. EGLFS is the default plugin on many boards and is recommended for Embedded Linux devices that include a GPU. You can use the QT_QPA_PLATFORM env variable or the {{{-platform}}} command-line argument to request another plugin. EGLFS forces the first top-level window (either a QWidget or a QQuickView) to become full screen and chosen to be the root widget window into which all other top-level widgets are composited. There are a number of env variables that can be used to configure EGLFS: see https://doc.qt.io/qt-5/embedded-linux.html#eglfs To use the EGLFS platform plugin with a KMS/DRM backend you need to define a screen configuration file customized to your board and display with some specific details: * device: the display device node on your board (ie /dev/dri/card0) * outputs: an array of outputs from /sys/class/drm Examples: * Ventana IMX6QDL 1080p HDMI: 1. determine device/name/mode {{{#!bash root@focal-ventana:~# ls /sys/class/drm card0 card1 card1-HDMI-A-1 card1-LVDS-1 renderD128 version root@focal-ventana:~# cat /sys/class/drm/card1-HDMI-A-1/modes 1920x1080 }}} - Note there are two outputs 'card1-HDMI-A-1' and 'card1-LVDS-1' (card0 is unused) corresponding to to the /dev/dri/card1 device and the mode 1. create conf file: {{{#!bash cat << EOF > /etc/eglfs_hdmi.json {   "device": "/dev/dri/card1",   "hwcursor": false,   "pbuffers": true,   "outputs": [     {       "name": "HDMI-A-1",       "mode": "1920x1080"     },     {       "name": "LVDS-1",       "mode": "off"     }   ] } EOF }}} - Note we disable LVDS-1 and configure HDMI-A-1 for our desired mode 1. export env vars: {{{#!bash export QT_QPA_EGLFS_KMS_CONFIG=/etc/eglfs_hdmi.json export QT_QPA_EGLFS_ALWAYS_SET_MODE=1 export QT_QPA_PLATFORM=eglfs }}} * Ventana IMX6QDL 1024x600 LVDS: 1. determine device/name/mode {{{#!bash root@focal-ventana:~# ls /sys/class/drm card0 card1 card1-HDMI-A-1 card1-LVDS-1 renderD128 version root@focal-ventana:~# cat /sys/class/drm/LVDS-1/modes 1024x600 }}} - Note there are two outputs 'card1-HDMI-A-1' and 'card1-LVDS-1' (card0 is unused) corresponding to to the /dev/dri/card1 device and the mode 1. create conf file: {{{#!bash cat << EOF > /etc/eglfs_lvds.json {   "device": "/dev/dri/card1",   "hwcursor": false,   "pbuffers": true,   "outputs": [     {       "name": "HDMI-A-1",       "mode": "off"     },     {       "name": "LVDS-1",       "mode": "1024x600"     }   ] } EOF }}} - Note we disable HDMI-A-1 and configure LVDS-1 for our desired mode 1. export env vars: {{{#!bash export QT_QPA_EGLFS_KMS_CONFIG=/etc/eglfs_lvds.json export QT_QPA_EGLFS_ALWAYS_SET_MODE=1 export QT_QPA_PLATFORM=eglfs }}} In order to use EGLFS you need to be using a kernel with the etnaviv KMS/DRM driver enabled, libdrm (userspace lib to interface with Linux DRM drivers), and libmesa. Note that the etnaviv driver uses cma memory - if you get memory allocation errors when trying to run applications try increasing the cma memory via the kernel command-line. For more info see: - https://doc.qt.io/qt-5.12/embedded-linux.html#platform-plugins-for-embedded-linux-devices [=#linuxfb] == LinuxFB LinuxFB writes directly to the framebuffer via Linux's fbdev subsystem where only software-rendered content is supported (no hw acceleration). Note that the fbdev subsystem is being deprecated in the Linux kernel and the DRM dub buffer support is to take its place and is supported in Qt 5.9. To use it set QT_QPA_FB_DRM=1. This provides a double-buffered and page flipped output providing proper vsync for software-rendered content. For env variables and options see https://doc.qt.io/qt-5/embedded-linux.html#linuxfb {{{#!bash export QT_QPA_PLATFORM=linuxfb }}} = Qt Examples [=#qtwebegine] == !QtWebEngine !QtWebEngine is essentially the Chromium core wrapped in Qt making it possible to render web content even without X11/Wayland and it works just fine with pure framebuffer. A simple example using !QtWebEngine can be found at https://code.qt.io/cgit/qt/qtwebengine.git/tree/examples/webengine/minimal To build the simple example which creates a !QtWebEngine fullscreen widget using content from http://www.qt.io:  * Ubuntu Focal 20.04: {{{#!bash apt update && apt upgrade # always a good idea to keep up to date # install basic development requirements apt install build-essential git # install qt5 development packages apt install qtwebengine5-dev # install qt5 runtime apt install qt5-default qml-module-qtwebengine # install qtwebengine minimal code example apt install qtwebengine5-examples cd /usr/lib/arm-linux-gnueabihf/qt5/examples/webengine/minimal # for 32bit arm systems cd /usr/lib/aarch64-linux-gnu/qt5/examples/webengine/minimal # for 64bit aarch64 systems # edit main.qml if you want to change the width/height or url qmake # generate Makefile from *.pro make # build ./minimal --no-sandbox }}} == Qt5 Cinematic Experience This UX demo application presents some graphical features of Qt5. The name 'Cinematic Experience' reflects how it's possible to build user interfaces with increased dynamics. Examples:  * Ubuntu Focal 20.04: {{{#!bash apt update && apt upgrade # always a good idea to keep up to date # install basic development requirements apt install build-essential git # install qt5 runtime apt install qt5-default qml-module-qtquick-controls qml-module-qtquick-controls2 qml-module-qtquick-particles2 # install qt5 development packages apt install qtbase5-dev qtdeclarative5-dev git clone https://github.com/rzr/qt5-cinematic-experience cd qt5-cinematic-experience qmake make ./Qt5_CinematicExperience }}} == Qt5 GL Video Demo This UX demo application shows how to render video frames on 3D objects which in turn are integrated in a Q graphical features of Qt5. The video frames are produced by the GStreamer !GstPlayer library. They are uploaded into OpenGL textures, which are then used on 3D meshes. These meshes are rendered in QQuickFramebufferObject !QtQuick 2 items, and the items are composed by a !PathView on screen. The 3D objects can be rotated with the mouse or with touch events. UI controls allow for adjusting several parameters such as opacity, scale, mesh type, etc. and for adding/removing objects. The video frames can come from local video files, network streams, or Video4Linux2 based video capture devices. Subtitles can be shown on screen. The subtitles can come either from the playing media itself, or from a FIFO if one is enabled in the configuration file. Examples:  * Ubuntu Focal 20.04: {{{#!bash apt update && apt upgrade # always a good idea to keep up to date # install basic development requirements apt install build-essential git # install qt5 runtime and qml modules required apt install qt5-default qml-module-qtquick-controls qml-module-qtquick-controls2 qml-module-qtquick-dialogs qml-module-qt-labs-folderlistmodel qml-module-qt-labs-settings # install qt5 development packages apt install qtbase5-dev qtdeclarative5-dev qtquickcontrols2-5-dev # install Gstreamer development packages apt install libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libgstreamer-plugins-bad1.0-dev libudev-dev git clone https://github.com/dv1/qtglviddemo cd qtglviddemo qmake make ./qtglviddemo }}} See: https://github.com/dv1/qtglviddemo [=#fingerpaint] == Qt5 Toucn and Multitouch input Examples There are various touch/multitouch examples in the [https://code.qt.io/cgit/qt/qtbase.git qtbase git repository]: - [https://doc-snapshots.qt.io/qt5-5.12/qtwidgets-touch-fingerpaint-example.html fingerpaint example] - drag to paint - [https://doc-snapshots.qt.io/qt5-5.12/qtwidgets-touch-dials-example.html dials example] - dragable dials - [https://doc.qt.io/Qt-5/qtwidgets-touch-knobs-example.html knobs] - select a knob by holding with one finger then use another finger to rotate it - [https://doc-snapshots.qt.io/qt5-5.12/qtwidgets-touch-pinchzoom-example.html pinchzoom example] - demonstrates pinch and zoom behaviors ​ Examples: - [https://doc-snapshots.qt.io/qt5-5.12/qtwidgets-touch-fingerpaint-example.html fingerpaint example] app demonstrating how to use touch input  * Ubuntu Focal 20.04: {{{#!bash apt update && apt upgrade # always a good idea to keep up to date # install basic development requirements apt install build-essential git # install libevdev apt install libevdev2 libevdev-tools # install qt5 runtime and qml modules required apt install qt5-default # clone the repo and build git clone git://code.qt.io/qt/qtbase.git -b 5.12 cp -r qtbase/examples/widgets/touch/fingerpaint . cd fingerpaint/ qmake make # run using linuxfb backend ./fingerpaint -platform linuxfb }}} Qt can use Linux evdev directly for input or it can use helper libraries such as libinput or tslib: * By default Qt5 on Ubuntu is using libinput and there is no tslib support * To troublshoot input you can set 'QT_LOGGING_RULES=qt.qpa.input=true'. * If you wish to disable libinput you can set 'QT_QPA_EGLFS_NO_LIBINPUT=1' for eglfs backend or 'QT_QPA_FB_NO_LIBINPUT=1' for linuxfb backend and input will default to evdev. When using evdev you can parameters via QT_QPA_EVDEV_TOUCHSCREEN_PARAMETERS with colon separated parameters, for example: - Run fingerpaint using evdev and linuxfb backend and specify /dev/input/event1 for input, rotate input 90 degrees, and invert both x and y: {{{#!bash QT_LOGGING_RULES=qt.qpa.input=true QT_QPA_FB_NO_LIBINPUT=1 QT_QPA_EVDEV_TOUCHSCREEN_PARAMETERS=/dev/input/event1:rotate=90:invertx:inverty ./fingerpaint -platform linuxfb }}} For more details Qt Input see: - https://doc.qt.io/qt-5.12/embedded-linux.html = User Interface Design with QT It is often best to consider QML instead of HTML5 for UI design. QML is much easier to use than HTML5 and is typically just fine for most user interface designs. QML has been designed for compsiting UIs and screen elements from the start while HTML5 had these things added to an existing standard meant for text rendering.