RaspberryPi2EGLFS: Difference between revisions
No edit summary |
|||
(5 intermediate revisions by 3 users not shown) | |||
Line 12: | Line 12: | ||
* Qt 5.10.1 with Raspbian Stretch on Raspberry 3 model B | * Qt 5.10.1 with Raspbian Stretch on Raspberry 3 model B | ||
* Qt 5.10.1 with Raspbian Stretch on Raspberry Zero W | * Qt 5.10.1 with Raspbian Stretch on Raspberry Zero W | ||
* Qt 5.12.3 with Raspbian Stretch on Raspberry 3 model B | |||
* Qt.5.13.1 with Raspbian Stretch on Raspberry3 model B | |||
If you are interested in trying QtWebEngine with WebGL support on RasberryPi3 with the open source Vc4 driver see [[RaspberryPiWithWebEngine|here]]. | |||
======Step by step====== | |||
# Get old raspbian images from [http://downloads.raspberrypi.org/raspbian/images/ here] or latest raspbian image from [https://www.raspberrypi.org/downloads/raspbian/ here]. | # Get old raspbian images from [http://downloads.raspberrypi.org/raspbian/images/ here] or latest raspbian image from [https://www.raspberrypi.org/downloads/raspbian/ here]. | ||
# Follow an [https://www.raspberrypi.org/documentation/installation/installing-images/README.md official installation guide]to boot it up or: Unzip and write it to a memory card. Replace ... with the SD card device (check with lsblk or dmesg eg. mmcblk0)< | # Follow an [https://www.raspberrypi.org/documentation/installation/installing-images/README.md official installation guide]to boot it up or: Unzip and write it to a memory card. Replace ... with the SD card device (check with lsblk or dmesg eg. mmcblk0)<syntaxhighlight> | ||
sudo dd if=2015-09-24-raspbian-jessie.img of=... bs=4M | sudo dd if=2015-09-24-raspbian-jessie.img of=... bs=4M</syntaxhighlight> | ||
</ | # '''[on RPi]''' ''(optional)'' Run raspi-config, change it to boot to the console instead of X, change the GPU memory to 256 MB.<syntaxhighlight> | ||
# '''[on RPi]''' ''(optional)'' Run raspi-config, change it to boot to the console instead of X, change the GPU memory to 256 MB.< | |||
sudo raspi-config | sudo raspi-config | ||
</ | </syntaxhighlight> | ||
# '''[on RPi]''' For <u>Raspbian Stretch</u> you need also to update your RPi (see [https://bugreports.qt.io/browse/QTBUG-62216 here]):< | # '''[on RPi]''' For <u>Raspbian Stretch</u> you need also to update your RPi (see [https://bugreports.qt.io/browse/QTBUG-62216 here]):<syntaxhighlight> | ||
sudo rpi-update | sudo rpi-update | ||
reboot | reboot | ||
</ | </syntaxhighlight> | ||
# '''[on RPi]''' Install a bunch of development files (for simplicity we use build-dep, not everything is really needed, but it is easier this way). | # '''[on RPi]''' Install a bunch of development files (for simplicity we use build-dep, not everything is really needed, but it is easier this way). | ||
## Edit sources list in ''/etc/apt/sources.list'' with use of your favorite editor (nano / vi) and uncomment the '''deb-src''' line:< | ## Edit sources list in ''/etc/apt/sources.list'' with use of your favorite editor (nano / vi) and uncomment the '''deb-src''' line:<syntaxhighlight> | ||
## Update your system and install required libraries:< | sudo nano /etc/apt/sources.list | ||
</syntaxhighlight> | |||
## Update your system and install required libraries:<syntaxhighlight> | |||
sudo apt-get update | sudo apt-get update | ||
sudo apt-get build-dep qt4-x11 | sudo apt-get build-dep qt4-x11 | ||
sudo apt-get build-dep libqt5gui5 | sudo apt-get build-dep libqt5gui5 | ||
sudo apt-get install libudev-dev libinput-dev libts-dev libxcb-xinerama0-dev libxcb-xinerama0 | sudo apt-get install libudev-dev libinput-dev libts-dev libxcb-xinerama0-dev libxcb-xinerama0 | ||
</ | </syntaxhighlight> | ||
# '''[on RPi]''' Prepare our target directory< | # '''[on RPi]''' Prepare our target directory<syntaxhighlight> | ||
sudo mkdir /usr/local/qt5pi | sudo mkdir /usr/local/qt5pi | ||
sudo chown pi:pi /usr/local/qt5pi | sudo chown pi:pi /usr/local/qt5pi | ||
</ | </syntaxhighlight> | ||
# '''[on host PC]''' Create our working directory and get a toolchain:< | # '''[on host PC]''' Create our working directory and get a toolchain:<syntaxhighlight> | ||
mkdir ~/raspi | mkdir ~/raspi | ||
cd ~/raspi | cd ~/raspi | ||
git clone https://github.com/raspberrypi/tools | git clone https://github.com/raspberrypi/tools | ||
</ | </syntaxhighlight> | ||
# '''[on host PC]''' Create a sysroot. Using rsync we can properly keep things synchronized in the future as well. Replace ''raspberrypi.local'' with the address of the Pi.< | # '''[on host PC]''' Create a sysroot. Using rsync we can properly keep things synchronized in the future as well. Replace ''raspberrypi.local'' with the address of the Pi.<syntaxhighlight> | ||
mkdir sysroot sysroot/usr sysroot/opt | mkdir sysroot sysroot/usr sysroot/opt | ||
rsync -avz pi@raspberrypi.local:/lib sysroot | rsync -avz pi@raspberrypi.local:/lib sysroot | ||
Line 48: | Line 53: | ||
rsync -avz pi@raspberrypi.local:/usr/lib sysroot/usr | rsync -avz pi@raspberrypi.local:/usr/lib sysroot/usr | ||
rsync -avz pi@raspberrypi.local:/opt/vc sysroot/opt | rsync -avz pi@raspberrypi.local:/opt/vc sysroot/opt | ||
</ | </syntaxhighlight> | ||
# '''[on host PC]''' Adjust symlinks to be relative. Use provided script, because the old ''fixQualifiedLibraryPaths'' is not working properly:< | # '''[on host PC]''' Adjust symlinks to be relative. Use provided script, because the old ''fixQualifiedLibraryPaths'' is not working properly:<syntaxhighlight> | ||
wget https://raw.githubusercontent.com/Kukkimonsuta/rpi-buildqt/master/scripts/utils/sysroot-relativelinks.py | wget https://raw.githubusercontent.com/Kukkimonsuta/rpi-buildqt/master/scripts/utils/sysroot-relativelinks.py | ||
chmod +x sysroot-relativelinks.py | chmod +x sysroot-relativelinks.py | ||
./sysroot-relativelinks.py sysroot | ./sysroot-relativelinks.py sysroot | ||
</ | </syntaxhighlight> | ||
# '''[on host PC]''' Get qtbase and configure Qt. The target directory is ''/usr/local/qt5pi'' on the Pi, the host tools like qmake will go to ''~/raspi/qt5'', while make install will target ''~/raspi/qt5pi'' (this is what we will sync to the device). Don't forget to adjust paths if you changed that. For some reason the ''~/'' in the paths may not work, if this the case just use full paths. You need to change '''<qt-version>''' with a proper Qt version (for example 5.6, or 5.9.1; note that version 5.9.1 is a tag not a branch, so you may want to create a local branch with it). You need to change '''<rpi-version>''' with a proper Raspberry Pi version. Use: ''linux-rasp-pi-g++'' for RPi, ''linux-rasp-pi2-g++'' for RPi2 and ''linux-rasp-pi3-g++'' for RPi3. If your system is 64 bit you may also edit device option to: <code>-device-option CROSS_COMPILE=~/raspi/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin/arm-linux-gnueabihf-</code> For higher Qt version (like 5.9.1) you may also need to add <code>-no-use-gold-linker</code> option. You probably also want to add ''-jn'' option to make command, where ''n'' is a number of cores you like to use for the complication.< | # '''[on host PC]''' Get qtbase and configure Qt. The target directory is ''/usr/local/qt5pi'' on the Pi, the host tools like qmake will go to ''~/raspi/qt5'', while make install will target ''~/raspi/qt5pi'' (this is what we will sync to the device). Don't forget to adjust paths if you changed that. For some reason the ''~/'' in the paths may not work, if this the case just use full paths. You need to change '''<qt-version>''' with a proper Qt version (for example 5.6, or 5.9.1; note that version 5.9.1 is a tag not a branch, so you may want to create a local branch with it). You need to change '''<rpi-version>''' with a proper Raspberry Pi version. Use: ''linux-rasp-pi-g++'' for RPi, ''linux-rasp-pi2-g++'' for RPi2 and ''linux-rasp-pi3-g++'' for RPi3. If your system is 64 bit you may also edit device option to: <code>-device-option CROSS_COMPILE=~/raspi/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin/arm-linux-gnueabihf-</code> For higher Qt version (like 5.9.1) you may also need to add <code>-no-use-gold-linker</code> option. You probably also want to add ''-jn'' option to make command, where ''n'' is a number of cores you like to use for the complication.<syntaxhighlight> | ||
git clone git://code.qt.io/qt/qtbase.git -b <qt-version> | git clone git://code.qt.io/qt/qtbase.git -b <qt-version> | ||
cd qtbase | cd qtbase | ||
Line 61: | Line 66: | ||
make | make | ||
make install | make install | ||
</ | </syntaxhighlight>If you failed, you can clear everything with:<syntaxhighlight> | ||
git clean -dfx | git clean -dfx | ||
</ | </syntaxhighlight> | ||
# '''[on host PC]''' Deploy Qt to the device. We simply sync everything from ''~/raspi/qt5pi'' to the prefix we configured above.< | # '''[on host PC]''' Deploy Qt to the device. We simply sync everything from ''~/raspi/qt5pi'' to the prefix we configured above.<syntaxhighlight> | ||
cd .. | |||
rsync -avz qt5pi pi@raspberrypi.local:/usr/local | rsync -avz qt5pi pi@raspberrypi.local:/usr/local | ||
</ | </syntaxhighlight> | ||
# '''[on host PC]''' Build an example up to test if everything went well. After proper build, copy an executable to the device.< | # '''[on host PC]''' Build an example up to test if everything went well. After proper build, copy an executable to the device.<syntaxhighlight> | ||
cd qtbase/examples/opengl/qopenglwidget | cd qtbase/examples/opengl/qopenglwidget | ||
~/raspi/qt5/bin/qmake | ~/raspi/qt5/bin/qmake | ||
Line 73: | Line 79: | ||
scp qopenglwidget pi@raspberrypi.local:/home/pi | scp qopenglwidget pi@raspberrypi.local:/home/pi | ||
</ | </syntaxhighlight> | ||
# '''[on RPi]''' Update the device to let the linker find the Qt libs:< | # '''[on RPi]''' Update the device to let the linker find the Qt libs:<syntaxhighlight> | ||
echo /usr/local/qt5pi/lib | sudo tee /etc/ld.so.conf.d/qt5pi.conf | echo /usr/local/qt5pi/lib | sudo tee /etc/ld.so.conf.d/qt5pi.conf | ||
sudo ldconfig | sudo ldconfig | ||
</ | </syntaxhighlight>If you're facing issues with running the example, try to use ''00-qt5pi.conf'' instead of ''qt5pi.conf'', to introduce proper order. | ||
# '''[on RPi]''' Fix the EGL/GLES libraries. The device may have the Mesa version of libEGL and libGLESv2 in ''/usr/lib/arm-linux-gnueabihf'', resulting Qt apps picking these instead of the real thing from ''/opt/vc/lib''. This may be fine for X11 desktop apps not caring about OpenGL performance but is totally useless for windowing system-less, fullscreen embedded apps. You may want to save the originals somewhere, just in case. Make sure you're in "/home/pi" aka "~" when you run these commands:< | # '''[on RPi]''' Fix the EGL/GLES libraries. The device may have the Mesa version of libEGL and libGLESv2 in ''/usr/lib/arm-linux-gnueabihf'', resulting Qt apps picking these instead of the real thing from ''/opt/vc/lib''. This may be fine for X11 desktop apps not caring about OpenGL performance but is totally useless for windowing system-less, fullscreen embedded apps. You may want to save the originals somewhere, just in case. Make sure you're in "/home/pi" aka "~" when you run these commands:<syntaxhighlight> | ||
sudo mv /usr/lib/arm-linux-gnueabihf/libEGL.so.1.0.0 /usr/lib/arm-linux-gnueabihf/libEGL.so.1.0.0_backup | sudo mv /usr/lib/arm-linux-gnueabihf/libEGL.so.1.0.0 /usr/lib/arm-linux-gnueabihf/libEGL.so.1.0.0_backup | ||
sudo mv /usr/lib/arm-linux-gnueabihf/libGLESv2.so.2.0.0 /usr/lib/arm-linux-gnueabihf/libGLESv2.so.2.0.0_backup | sudo mv /usr/lib/arm-linux-gnueabihf/libGLESv2.so.2.0.0 /usr/lib/arm-linux-gnueabihf/libGLESv2.so.2.0.0_backup | ||
Line 84: | Line 90: | ||
sudo ln -s /opt/vc/lib/libGLESv2.so /usr/lib/arm-linux-gnueabihf/libGLESv2.so.2.0.0 | sudo ln -s /opt/vc/lib/libGLESv2.so /usr/lib/arm-linux-gnueabihf/libGLESv2.so.2.0.0 | ||
sudo ln -s /opt/vc/lib/libbrcmEGL.so /opt/vc/lib/libEGL.so | sudo ln -s /opt/vc/lib/libbrcmEGL.so /opt/vc/lib/libEGL.so | ||
sudo ln -s /opt/vc/lib/libbrcmGLESv2.so | sudo ln -s /opt/vc/lib/libbrcmGLESv2.so /opt/vc/lib/libGLESv2.so | ||
</ | </syntaxhighlight>Please make sure to also add missing symbolic links:<syntaxhighlight> | ||
sudo ln -s /opt/vc/lib/libEGL.so /opt/vc/lib/libEGL.so.1 | sudo ln -s /opt/vc/lib/libEGL.so /opt/vc/lib/libEGL.so.1 | ||
sudo ln -s /opt/vc/lib/libGLESv2.so /opt/vc/lib/libGLESv2.so.2 | sudo ln -s /opt/vc/lib/libGLESv2.so /opt/vc/lib/libGLESv2.so.2 | ||
</ | </syntaxhighlight> | ||
# '''[on RPi]''' Run example, that we've built before. At this point it should just work at fullscreen with 60 FPS and mouse, keyboard, and possibly touch support. | # '''[on RPi]''' Run example, that we've built before. At this point it should just work at fullscreen with 60 FPS and mouse, keyboard, and possibly touch support. | ||
# '''[on host PC]''' Build other Qt modules as desired, the steps are always the same (you need to adjust '''<qt-module>''' and '''<qt-version>'''):< | # '''[on host PC]''' Build other Qt modules as desired, the steps are always the same (you need to adjust '''<qt-module>''' and '''<qt-version>'''):<syntaxhighlight> | ||
git clone git://code.qt.io/qt/<qt-module>.git -b <qt-version> | git clone git://code.qt.io/qt/<qt-module>.git -b <qt-version> | ||
cd <qt-module> | cd <qt-module> | ||
Line 97: | Line 103: | ||
make | make | ||
make install | make install | ||
</ | </syntaxhighlight>Then deploy new files by running:<syntaxhighlight>rsync -avz qt5pi pi@raspberrypi.local:/usr/local</syntaxhighlight> | ||
<h3>Additional notes</h3> | <h3>Additional notes</h3> | ||
Line 105: | Line 110: | ||
As a quick fix, try adding disable_overscan=1 to /boot/config.txt and after a reboot check with /opt/vc/bin/tvservice what modes are available. For example, to switch to 1024x768: | As a quick fix, try adding disable_overscan=1 to /boot/config.txt and after a reboot check with /opt/vc/bin/tvservice what modes are available. For example, to switch to 1024x768: | ||
< | <syntaxhighlight> | ||
$ /opt/vc/bin/tvservice -m DMT | $ /opt/vc/bin/tvservice -m DMT | ||
Group DMT has 4 modes: | Group DMT has 4 modes: | ||
Line 115: | Line 120: | ||
$ /opt/vc/bin/tvservice -e "DMT 16 HDMI" | $ /opt/vc/bin/tvservice -e "DMT 16 HDMI" | ||
$ fbset -xres 1024 -yres 768 | $ fbset -xres 1024 -yres 768 | ||
</ | </syntaxhighlight> | ||
<h4>Troubleshooting</h4> | <h4>Troubleshooting</h4> | ||
Line 121: | Line 126: | ||
Enabling the logging categories under qt.qpa is a good idea in general. This will show some debug prints both from eglfs and the input handlers. | Enabling the logging categories under qt.qpa is a good idea in general. This will show some debug prints both from eglfs and the input handlers. | ||
< | <syntaxhighlight> | ||
export QT_LOGGING_RULES=qt.qpa.*=true | export QT_LOGGING_RULES=qt.qpa.*=true | ||
./qopenglwidget | ./qopenglwidget | ||
</ | </syntaxhighlight> | ||
A typical output would like like this: | A typical output would like like this: | ||
< | <syntaxhighlight> | ||
qt.qpa.egldeviceintegration: EGL device integration plugin keys: ("eglfs_brcm", "eglfs_kms") | qt.qpa.egldeviceintegration: EGL device integration plugin keys: ("eglfs_brcm", "eglfs_kms") | ||
qt.qpa.egldeviceintegration: EGL device integration plugin keys (sorted): ("eglfs_brcm", "eglfs_kms") | qt.qpa.egldeviceintegration: EGL device integration plugin keys (sorted): ("eglfs_brcm", "eglfs_kms") | ||
Line 140: | Line 145: | ||
qt.qpa.input: libinput: input device 'Raspberry Pi Sense HAT Joystick', /dev/input/event3 is a keyboard | qt.qpa.input: libinput: input device 'Raspberry Pi Sense HAT Joystick', /dev/input/event3 is a keyboard | ||
qt.qpa.input: Using xkbcommon for key mapping | qt.qpa.input: Using xkbcommon for key mapping | ||
</ | </syntaxhighlight> | ||
Verify that eglfs_brcm is in use and that input devices are correctly found. | Verify that eglfs_brcm is in use and that input devices are correctly found. | ||
Line 148: | Line 153: | ||
It is also wise to carefully check the output of configure (saved as config.summary) before proceeding to build qtbase. Check that the following are marked as 'yes': | It is also wise to carefully check the output of configure (saved as config.summary) before proceeding to build qtbase. Check that the following are marked as 'yes': | ||
< | <syntaxhighlight> | ||
Support enabled for: | Support enabled for: | ||
... | ... | ||
Line 169: | Line 174: | ||
udev ................... yes | udev ................... yes | ||
xkbcommon-evdev......... yes | xkbcommon-evdev......... yes | ||
</ | </syntaxhighlight> | ||
'''Missing EGLFS Fix''' | '''Missing EGLFS Fix''' | ||
Line 177: | Line 182: | ||
Another fix is the replacement of the broken lines: | Another fix is the replacement of the broken lines: | ||
< | <syntaxhighlight>VC_LIBRARY_PATH = $$[QT_SYSROOT]/opt/vc/lib | ||
VC_INCLUDE_PATH = $$[QT_SYSROOT]/opt/vc/include | VC_INCLUDE_PATH = $$[QT_SYSROOT]/opt/vc/include | ||
VC_LINK_LINE = -L$${VC_LIBRARY_PATH} | VC_LINK_LINE = -L$${VC_LIBRARY_PATH} | ||
QMAKE_LIBDIR_OPENGL_ES2 = $${VC_LIBRARY_PATH}</ | QMAKE_LIBDIR_OPENGL_ES2 = $${VC_LIBRARY_PATH}</syntaxhighlight> | ||
<h4>Regarding keyboard input</h4> | <h4>Regarding keyboard input</h4> | ||
Line 191: | Line 196: | ||
If you get an error such as "''This application failed to start because it could not find or load the Qt platform plugin "eglfs" in "".''", when attempting to run a Qt app on the RPi, you may need to set some environment variables. | If you get an error such as "''This application failed to start because it could not find or load the Qt platform plugin "eglfs" in "".''", when attempting to run a Qt app on the RPi, you may need to set some environment variables. | ||
< | <syntaxhighlight> | ||
export QT_QPA_PLATFORM=eglfs | export QT_QPA_PLATFORM=eglfs | ||
export QT_QPA_PLATFORM_PLUGIN_PATH=/usr/local/qt5pi/plugins/platforms | export QT_QPA_PLATFORM_PLUGIN_PATH=/usr/local/qt5pi/plugins/platforms | ||
export LD_LIBRARY_PATH=/usr/local/qt5pi/lib | export LD_LIBRARY_PATH=/usr/local/qt5pi/lib | ||
</ | </syntaxhighlight> | ||
<h3>Qt Creator</h3> | <h3>Qt Creator</h3> | ||
Line 201: | Line 206: | ||
Once Qt is on the device, Qt Creator can be set up to build, deploy, run and debug Qt apps directly on the device with one click. | Once Qt is on the device, Qt Creator can be set up to build, deploy, run and debug Qt apps directly on the device with one click. | ||
< | <syntaxhighlight> | ||
Go to Options -> Devices | Go to Options -> Devices | ||
Add | Add | ||
Line 207: | Line 212: | ||
Enter IP address, user & password | Enter IP address, user & password | ||
Finish | Finish | ||
</ | </syntaxhighlight> | ||
< | <syntaxhighlight> | ||
Go to Options -> Compilers | Go to Options -> Compilers | ||
Add | Add | ||
GCC | GCC | ||
Compiler path: ~/raspi/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian/bin/arm-linux-gnueabihf-g++ | Compiler path: ~/raspi/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian/bin/arm-linux-gnueabihf-g++ | ||
</ | </syntaxhighlight> | ||
< | <syntaxhighlight> | ||
Go to Options -> Debuggers | Go to Options -> Debuggers | ||
Add | Add | ||
~/raspi/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin/arm-linux-gnueabihf-gdb | ~/raspi/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin/arm-linux-gnueabihf-gdb | ||
</ | </syntaxhighlight> | ||
< | <syntaxhighlight> | ||
Go to Options -> Qt Versions | Go to Options -> Qt Versions | ||
Check if an entry with ~/raspi/qt5/bin/qmake shows up. If not, add it. | Check if an entry with ~/raspi/qt5/bin/qmake shows up. If not, add it. | ||
</ | </syntaxhighlight> | ||
< | <syntaxhighlight> | ||
Go to Options -> Build & Run | Go to Options -> Build & Run | ||
Kits | Kits | ||
Line 238: | Line 243: | ||
Qt version: the one we saw under Qt Versions | Qt version: the one we saw under Qt Versions | ||
Qt mkspec: leave empty | Qt mkspec: leave empty | ||
</ | </syntaxhighlight> | ||
Done. At this point you should be able to start a new project with the new kit, build and deploy it, etc. | Done. At this point you should be able to start a new project with the new kit, build and deploy it, etc. | ||
Line 260: | Line 265: | ||
Before building Qt Multimedia 5.6, make sure the following are installed: | Before building Qt Multimedia 5.6, make sure the following are installed: | ||
< | <syntaxhighlight> | ||
sudo apt-get install gstreamer1.0-omx libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev | sudo apt-get install gstreamer1.0-omx libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev | ||
</ | </syntaxhighlight> | ||
Do not forget to sync the headers and libs back to the sysroot on the host PC and re-run the sysroot-relativelinks.py script. | Do not forget to sync the headers and libs back to the sysroot on the host PC and re-run the sysroot-relativelinks.py script. | ||
Line 268: | Line 273: | ||
Once the GStreamer 1.0 dependencies are in place, make sure Qt Multimedia is built with 1.0 support: | Once the GStreamer 1.0 dependencies are in place, make sure Qt Multimedia is built with 1.0 support: | ||
< | <syntaxhighlight> | ||
~/raspi/qt5/bin/qmake -r GST_VERSION=1.0 | ~/raspi/qt5/bin/qmake -r GST_VERSION=1.0 | ||
</ | </syntaxhighlight> | ||
To verify that the accelerated OpenMAX path is used for H.264 videos, do <em>export GST_DEBUG=omx:4</em> before running a video playback app like the qmlvideofx example. | To verify that the accelerated OpenMAX path is used for H.264 videos, do <em>export GST_DEBUG=omx:4</em> before running a video playback app like the qmlvideofx example. |
Latest revision as of 08:43, 23 March 2021
A modern guide for cross-compiling Qt for HW accelerated OpenGL with eglfs on Raspbian and setting up Qt Creator
Initial notes
- This is not intended for running desktop-style, windowed Qt apps under X11, but rather for the real embedded/device creation use case where the Qt app runs fullscreen on top of dispmanx/EGL using the Broadcom drivers.
- For detailed, generic information about eglfs and Qt on Embedded Linux check the Qt documentation.
Tested Configurations
- Qt 5.6 with Raspbian Wheezy / Jessie
- Qt 5.9.1 with Raspbian Stretch on Raspberry 3 model B
- Qt 5.10 with Raspbian Stretch on Raspberry 1 model B
- Qt 5.10.1 with Raspbian Stretch on Raspberry 3 model B
- Qt 5.10.1 with Raspbian Stretch on Raspberry Zero W
- Qt 5.12.3 with Raspbian Stretch on Raspberry 3 model B
- Qt.5.13.1 with Raspbian Stretch on Raspberry3 model B
If you are interested in trying QtWebEngine with WebGL support on RasberryPi3 with the open source Vc4 driver see here.
Step by step
- Get old raspbian images from here or latest raspbian image from here.
- Follow an official installation guideto boot it up or: Unzip and write it to a memory card. Replace ... with the SD card device (check with lsblk or dmesg eg. mmcblk0)
sudo dd if=2015-09-24-raspbian-jessie.img of=... bs=4M
- [on RPi] (optional) Run raspi-config, change it to boot to the console instead of X, change the GPU memory to 256 MB.
sudo raspi-config
- [on RPi] For Raspbian Stretch you need also to update your RPi (see here):
sudo rpi-update reboot
- [on RPi] Install a bunch of development files (for simplicity we use build-dep, not everything is really needed, but it is easier this way).
- Edit sources list in /etc/apt/sources.list with use of your favorite editor (nano / vi) and uncomment the deb-src line:
sudo nano /etc/apt/sources.list
- Update your system and install required libraries:
sudo apt-get update sudo apt-get build-dep qt4-x11 sudo apt-get build-dep libqt5gui5 sudo apt-get install libudev-dev libinput-dev libts-dev libxcb-xinerama0-dev libxcb-xinerama0
- Edit sources list in /etc/apt/sources.list with use of your favorite editor (nano / vi) and uncomment the deb-src line:
- [on RPi] Prepare our target directory
sudo mkdir /usr/local/qt5pi sudo chown pi:pi /usr/local/qt5pi
- [on host PC] Create our working directory and get a toolchain:
mkdir ~/raspi cd ~/raspi git clone https://github.com/raspberrypi/tools
- [on host PC] Create a sysroot. Using rsync we can properly keep things synchronized in the future as well. Replace raspberrypi.local with the address of the Pi.
mkdir sysroot sysroot/usr sysroot/opt rsync -avz pi@raspberrypi.local:/lib sysroot rsync -avz pi@raspberrypi.local:/usr/include sysroot/usr rsync -avz pi@raspberrypi.local:/usr/lib sysroot/usr rsync -avz pi@raspberrypi.local:/opt/vc sysroot/opt
- [on host PC] Adjust symlinks to be relative. Use provided script, because the old fixQualifiedLibraryPaths is not working properly:
wget https://raw.githubusercontent.com/Kukkimonsuta/rpi-buildqt/master/scripts/utils/sysroot-relativelinks.py chmod +x sysroot-relativelinks.py ./sysroot-relativelinks.py sysroot
- [on host PC] Get qtbase and configure Qt. The target directory is /usr/local/qt5pi on the Pi, the host tools like qmake will go to ~/raspi/qt5, while make install will target ~/raspi/qt5pi (this is what we will sync to the device). Don't forget to adjust paths if you changed that. For some reason the ~/ in the paths may not work, if this the case just use full paths. You need to change <qt-version> with a proper Qt version (for example 5.6, or 5.9.1; note that version 5.9.1 is a tag not a branch, so you may want to create a local branch with it). You need to change <rpi-version> with a proper Raspberry Pi version. Use: linux-rasp-pi-g++ for RPi, linux-rasp-pi2-g++ for RPi2 and linux-rasp-pi3-g++ for RPi3. If your system is 64 bit you may also edit device option to: For higher Qt version (like 5.9.1) you may also need to add
-device-option CROSS_COMPILE=~/raspi/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin/arm-linux-gnueabihf-
option. You probably also want to add -jn option to make command, where n is a number of cores you like to use for the complication.-no-use-gold-linker
If you failed, you can clear everything with:git clone git://code.qt.io/qt/qtbase.git -b <qt-version> cd qtbase ./configure -release -opengl es2 -device <rpi-version> -device-option CROSS_COMPILE=~/raspi/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian/bin/arm-linux-gnueabihf- -sysroot ~/raspi/sysroot -opensource -confirm-license -make libs -prefix /usr/local/qt5pi -extprefix ~/raspi/qt5pi -hostprefix ~/raspi/qt5 -v make make install
git clean -dfx
- [on host PC] Deploy Qt to the device. We simply sync everything from ~/raspi/qt5pi to the prefix we configured above.
cd .. rsync -avz qt5pi pi@raspberrypi.local:/usr/local
- [on host PC] Build an example up to test if everything went well. After proper build, copy an executable to the device.
cd qtbase/examples/opengl/qopenglwidget ~/raspi/qt5/bin/qmake make scp qopenglwidget pi@raspberrypi.local:/home/pi
- [on RPi] Update the device to let the linker find the Qt libs:If you're facing issues with running the example, try to use 00-qt5pi.conf instead of qt5pi.conf, to introduce proper order.
echo /usr/local/qt5pi/lib | sudo tee /etc/ld.so.conf.d/qt5pi.conf sudo ldconfig
- [on RPi] Fix the EGL/GLES libraries. The device may have the Mesa version of libEGL and libGLESv2 in /usr/lib/arm-linux-gnueabihf, resulting Qt apps picking these instead of the real thing from /opt/vc/lib. This may be fine for X11 desktop apps not caring about OpenGL performance but is totally useless for windowing system-less, fullscreen embedded apps. You may want to save the originals somewhere, just in case. Make sure you're in "/home/pi" aka "~" when you run these commands:Please make sure to also add missing symbolic links:
sudo mv /usr/lib/arm-linux-gnueabihf/libEGL.so.1.0.0 /usr/lib/arm-linux-gnueabihf/libEGL.so.1.0.0_backup sudo mv /usr/lib/arm-linux-gnueabihf/libGLESv2.so.2.0.0 /usr/lib/arm-linux-gnueabihf/libGLESv2.so.2.0.0_backup sudo ln -s /opt/vc/lib/libEGL.so /usr/lib/arm-linux-gnueabihf/libEGL.so.1.0.0 sudo ln -s /opt/vc/lib/libGLESv2.so /usr/lib/arm-linux-gnueabihf/libGLESv2.so.2.0.0 sudo ln -s /opt/vc/lib/libbrcmEGL.so /opt/vc/lib/libEGL.so sudo ln -s /opt/vc/lib/libbrcmGLESv2.so /opt/vc/lib/libGLESv2.so
sudo ln -s /opt/vc/lib/libEGL.so /opt/vc/lib/libEGL.so.1 sudo ln -s /opt/vc/lib/libGLESv2.so /opt/vc/lib/libGLESv2.so.2
- [on RPi] Run example, that we've built before. At this point it should just work at fullscreen with 60 FPS and mouse, keyboard, and possibly touch support.
- [on host PC] Build other Qt modules as desired, the steps are always the same (you need to adjust <qt-module> and <qt-version>):Then deploy new files by running:
git clone git://code.qt.io/qt/<qt-module>.git -b <qt-version> cd <qt-module> ~/raspi/qt5/bin/qmake make make install
rsync -avz qt5pi pi@raspberrypi.local:/usr/local
Additional notes
Frequently asked question: I only get a low resolution like 640x480 or even 576x416 with black boxes. How to fix this?
As a quick fix, try adding disable_overscan=1 to /boot/config.txt and after a reboot check with /opt/vc/bin/tvservice what modes are available. For example, to switch to 1024x768:
$ /opt/vc/bin/tvservice -m DMT
Group DMT has 4 modes:
mode 4: 640x480 @ 60Hz 4:3, clock:25MHz progressive
mode 9: 800x600 @ 60Hz 4:3, clock:40MHz progressive
mode 16: 1024x768 @ 60Hz 4:3, clock:65MHz progressive
mode 35: 1280x1024 @ 60Hz 5:4, clock:108MHz progressive
$ /opt/vc/bin/tvservice -e "DMT 16 HDMI"
$ fbset -xres 1024 -yres 768
Troubleshooting
Enabling the logging categories under qt.qpa is a good idea in general. This will show some debug prints both from eglfs and the input handlers.
export QT_LOGGING_RULES=qt.qpa.*=true
./qopenglwidget
A typical output would like like this:
qt.qpa.egldeviceintegration: EGL device integration plugin keys: ("eglfs_brcm", "eglfs_kms")
qt.qpa.egldeviceintegration: EGL device integration plugin keys (sorted): ("eglfs_brcm", "eglfs_kms")
qt.qpa.egldeviceintegration: Trying to load device EGL integration "eglfs_brcm"
qt.qpa.egldeviceintegration: Using EGL device integration "eglfs_brcm"
Unable to query physical screen size, defaulting to 100 dpi.
To override, set QT_QPA_EGLFS_PHYSICAL_WIDTH and QT_QPA_EGLFS_PHYSICAL_HEIGHT (in millimeters).
qt.qpa.input: libinput: input device 'Logitech Optical USB Mouse', /dev/input/event0 is a pointer caps = relative-motion button
qt.qpa.input: libinput: input device 'Apple Inc. Apple Keyboard', /dev/input/event1 is a keyboard
qt.qpa.input: libinput: input device 'Apple Inc. Apple Keyboard', /dev/input/event2 is a keyboard
qt.qpa.input: libinput: input device 'Raspberry Pi Sense HAT Joystick', /dev/input/event3 is a keyboard
qt.qpa.input: Using xkbcommon for key mapping
Verify that eglfs_brcm is in use and that input devices are correctly found.
When using a touchscreen, setting the correct physical screen size may be essential to get properly scaled, finger friendly user interface elements with Qt Quick Controls. When using ordinary monitors via HDMI, the default 100 dpi may be acceptable.
It is also wise to carefully check the output of configure (saved as config.summary) before proceeding to build qtbase. Check that the following are marked as 'yes':
Support enabled for:
...
Evdev .................. yes
FontConfig ............. yes
FreeType ............... yes (system library)
...
libinput................ yes
...
OpenGL / OpenVG:
EGL .................. yes
OpenGL ............... yes (OpenGL ES 2.0+)
QPA backends:
EGLFS ................ yes
...
EGLFS Raspberry Pi . yes
...
LinuxFB .............. yes
...
udev ................... yes
xkbcommon-evdev......... yes
Missing EGLFS Fix
On recent versions of Qt (e.g. 5.10.1), the qmake.conf file for linux-rasp-pi3-g++ doesn't work, however, linux-rasp-pi-g++ does. Create a new qmake.conf based on linux-rasp-pi-g++ with the build flags from the Pi 3 spec copied over.
Another fix is the replacement of the broken lines:
VC_LIBRARY_PATH = $$[QT_SYSROOT]/opt/vc/lib
VC_INCLUDE_PATH = $$[QT_SYSROOT]/opt/vc/include
VC_LINK_LINE = -L$${VC_LIBRARY_PATH}
QMAKE_LIBDIR_OPENGL_ES2 = $${VC_LIBRARY_PATH}
Regarding keyboard input
By default Qt attempts to disable the keyboard and hide the cursor on application startup. This is very handy since this way keystrokes will not go to the console (which is enabled by default in a normal Raspbian image) "underneath". However, at the moment this will all silently fail when starting an application remotely via ssh. This is the explanation for the (harmless) 9;15] and similar prints and the keyboard input unexpectedly going to the console as well. As a workaround, start apps directly on the console. Alternatively, you could experiment with getting rid of the first TTY by doing sudo systemctl disable getty@tty1.service and reboot. (tty2 and others remain usable)
Environment variables
If you get an error such as "This application failed to start because it could not find or load the Qt platform plugin "eglfs" in "".", when attempting to run a Qt app on the RPi, you may need to set some environment variables.
export QT_QPA_PLATFORM=eglfs
export QT_QPA_PLATFORM_PLUGIN_PATH=/usr/local/qt5pi/plugins/platforms
export LD_LIBRARY_PATH=/usr/local/qt5pi/lib
Qt Creator
Once Qt is on the device, Qt Creator can be set up to build, deploy, run and debug Qt apps directly on the device with one click.
Go to Options -> Devices
Add
Generic Linux Device
Enter IP address, user & password
Finish
Go to Options -> Compilers
Add
GCC
Compiler path: ~/raspi/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian/bin/arm-linux-gnueabihf-g++
Go to Options -> Debuggers
Add
~/raspi/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin/arm-linux-gnueabihf-gdb
Go to Options -> Qt Versions
Check if an entry with ~/raspi/qt5/bin/qmake shows up. If not, add it.
Go to Options -> Build & Run
Kits
Add
Generic Linux Device
Device: the one we just created
Sysroot: ~/raspi/sysroot
Compiler: the one we just created
Debugger: the one we just created
Qt version: the one we saw under Qt Versions
Qt mkspec: leave empty
Done. At this point you should be able to start a new project with the new kit, build and deploy it, etc.
Note: While things will usually just work for applications, developing libraries and in particular, Qt modules may be problematic when it comes to deployment. The per-project Run tab under Projects -> Build & Run is your friend. In some cases the target deployment paths will just be wrong. Life is too short for worrying about all the intricate details of Creator and the build system. Therefore, if all else fails, use Add Deploy Step ("Make" and "Custom Process Step" are extremely handy, anything can be made working with a combination of make install, rsync and scp) and change Run configuration to Custom Executable.
Sense HAT
To access the sensors and leds on the Sense HAT, you can use the unofficial Qt Sense HAT module on qt-labs. Check it out via git and build it like any other Qt module.
The joystick shows up as an ordinary evdev device providing key events so it will just work. Regarding the leds and sensors, see the README.
Qt Multimedia
Unfortunately the GStreamer-based multimedia stuff is not quite usable at the time of writing - accelerated video works only sometimes (and with glitches), while the camera is just broken.
As an alternative to Qt Multimedia, try using OpenMAX directly. For an open implementation refer to this project. For the Raspberry Pi Camera Module take a look at the raspistill application sources for an example on how to get the camera preview image into an OpenGL texture.
If you wish to experiment with Qt Multimedia, try the following:
Before building Qt Multimedia 5.6, make sure the following are installed:
sudo apt-get install gstreamer1.0-omx libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev
Do not forget to sync the headers and libs back to the sysroot on the host PC and re-run the sysroot-relativelinks.py script.
Once the GStreamer 1.0 dependencies are in place, make sure Qt Multimedia is built with 1.0 support:
~/raspi/qt5/bin/qmake -r GST_VERSION=1.0
To verify that the accelerated OpenMAX path is used for H.264 videos, do export GST_DEBUG=omx:4 before running a video playback app like the qmlvideofx example.