Sunday, March 17, 2013

Raspberry Pi Wheezy Image With Qt and Wayland Support

According to what I read around, it should be possible to install some build of Qt 5 using apt on Raspberry by adding the Qt repo: read here.

However, some asked for a version of Qt compiled for Pi, so, if that was not ok for you for some reason, this is an entire image with many packages for which Qt has support and includes wayland and QtMultimedia (what is working oob).
This is the configuration of the build:

Bulding on: linux-g++
Building for: devices/linux-rasp-pi-g++
Architecture: arm, features:
Host architecture: i386, features:
Platform notes:

- Also available for Linux: linux-kcc linux-icc linux-cxx

Build .................. libs examples
Configuration .......... cross_compile qpa largefile neon pcre minimal-config small-config medium-config large-config full-config fontconfig libudev evdev linuxfb c++11 accessibility egl eglfs opengl opengles2 shared qpa reduce_exports reduce_relocations clock-gettime clock-monotonic mremap getaddrinfo ipv6ifname getifaddrs inotify system-jpeg png system-freetype system-zlib nis iconv glib gstreamer dbus openssl rpath alsa icu concurrent audio-backend v8 v8snapshot release
Debug .................. no
C++11 support .......... yes
pkg-config ............. yes
Qt D-Bus module ........ yes (run-time)
Qt Concurrent code ..... yes
Qt GUI module .......... yes
Qt Widgets module ...... yes
JavaScriptCore JIT ..... To be decided by JavaScriptCore
QML debugging .......... yes
PCH support ............ no
iWMMXt support ......... no
NEON support ........... yes
IPv6 ifname support .... yes
getaddrinfo support .... yes
getifaddrs support ..... yes
Accessibility .......... yes
NIS support ............ yes
CUPS support ........... no
Iconv support .......... yes
Glib support ........... yes
GStreamer support ...... yes
PulseAudio support ..... no
Large File support ..... yes
GIF support ............ plugin
JPEG support ........... plugin (system)
PNG support ............ yes (qt)
zlib support ........... system
Session management ..... auto
libudev support ........ yes
Use system proxies ..... no
OpenGL support ......... yes (OpenGL ES 2.x)
OpenVG support ......... no
XShape support ......... auto
XVideo support ......... auto
XSync support .......... auto
Xinerama support ....... runtime
Xcursor support ........ runtime
Xfixes support ......... runtime
Xrandr support ......... runtime
Xi support ............. runtime
Xi2 support ............ auto
MIT-SHM support ........ auto
FontConfig support ..... yes
XKB Support ............ auto
GTK theme support ...... no
SQLite support ......... plugin (qt)
OpenSSL support ........ yes (run-time)
Alsa support ........... yes
libICU support ......... yes
PCRE support ........... qt
Xcb support ............ no
Xrender support ........ no
EGLFS support .......... yes
DirectFB support ....... no
LinuxFB support ........ yes
KMS support ............ no


The modules I compiled are:
  1. qtbase
  2. qtscript
  3. qtjsbackend
  4. qtdeclarative
  5. qtgraphicaleffects
  6. qtimageformats
  7. qtmultimedia
  8. qtquick1
  9. qtsvg
  10. qtwayland
  11. qtwebkit
  12. qtwebkit-examples-and-demos
  13. qtxmlpatterns
  14. qt3d

How to Use to Build

To build code with this you need to dd the image to an SD card (4GB at least), and setup your system to cross-compile using the same libs.
First transfer the image to the SD:

tar xvfp wheezy_qt5_20130310.tar
tar xvfpj wheeze_image_20130310_qt5.tar.bz2
sudo dd if=wheezy_image_20130310.img of=your_sd_dev

Then transfer all the libs you need to cross-compile in your sysroot, which must be located in /opt/rpi/sysroot.

sudo mkdir /opt/rpi
sudo mkdir /opt/rpi/sysroot
cd /opt/rpi/sysroot
sudo scp -r root@rpi_ip:/lib root@rpi_ip:/opt .
sudo mkdir usr
sudo scp -r root@rpi_ip:/usr/lib root@rpi_ip:/usr/include root@rpi_ip:/usr/local usr


Now place the Qt tools into your system:

tar xvfpj Qt-rasp-5.0.2_build_rools.tar.bz2
sudo mv Qt-rasp-5.0.2 /usr/local

Setup Qt Creator to Cross-Compile

You should now be able to setup Qt Creator to cross-compile. Open Qt Creator, got to the Window -> Options -> Build & Run. Open the "Compilers" tab and add the new cross-compiler.
Setup the Qt version by selecting the qmake binary from /usr/local/Qt-rasp-5.0.2/bin/qmake.
Setup a new kit by setting both the compiler and the Qt version you just added.
You should be done.

Download the Package

The package is large since it contains the entire image, including all the needed packages. Try to download from here (sorry, I experienced too much traffic so I had to remove it, you can try with this torrent or this ftp, but both will take long; please let me know if you experience troubles).
The userid is pi and the passwords are rasp for both the user pi and root.

Edit 04.16.2013 

I see that many are still trying to download and the server is permanently at full upload speed, I suppose it is better to start using p2p: use this ed2k link to download. I'm sharing this with priority. If you're already downloading via FTP, then please complete the download as quickly as possible; I'll remove the file in a couple of days. In case you experienced issues, please leave a message.

Sunday, March 3, 2013

Bring up Qt 5 on Raspberry Pi with Wayland

Ok, I've been waiting to do this for quite some time but never had the time to actually do it. I tried this quickly twice but without success because of many issues. Now I invested some hours and made it to the end of the journey :-)
I therefore try to describe here the steps to make Qt 5.0.1 (the current version in the Qt git) on the new wheezy image with Wayland support.

Building the Qt Fundamental Modules

Of course the procedure is almost identical to the one used for Qt 5.0 that I described here. I only did a couple of things to speed up the process, you choose how to do it. I briefly describe here some of the steps.

  1. Download the latest available wheezy image from the Raspberry Pi website: http://www.raspberrypi.org/downloads.
  2. Uncompress the image and flash it to your SD card.
  3. Boot the new image on your board.
  4. Install some libs that we will need (I won't compile the xcb platform plugin here, so in this case I decided not to install those xcb libs):

    $ sudo apt-get install libdbus-1-dev libudev-dev libssl-dev
    $ sudo apt-get install libasound2-dev
    $ sudo apt-get install libgstreamer0.10-dev libgstreamer-plugins-base0.10-dev libgstreamer-plugins-bad0.10-dev
    $ sudo apt-get install libffi-dev libpixman-1-dev
    $ sudo apt-get install libsqlite3-dev libicu-dev libfontconfig1-dev


    libdbus-1-dev is used to get the QtDBus module compiled from qtbase, libudev-dev to get udev support, libssl-dev for OpenSSL and libasound2-dev will provide Qt what it needs for ALSA support.
    GStreamer libs instead are mainly used in the qtmultimedia and qtwebkit modules. If the environment is setup correctly for gstreamer support, then the configure script will report the success.
    libffi-dev libpixman-1-dev are needed to compile the qtwayland module or its dependencies. libsqlite3-dev libicu-dev and libfontconfig1-dev instead are needed only if you intend to use QtWebKit.
  5. Instead of the loopback mount of the image on your system to get a correct sysroot, I quickly scp'ed the needed binaries from my board to a newly created sysroot. In particular I copied:
    • /lib
    • /usr/lib
    • /usr/include
    • /opt
    I'll refer to the directory containing all of this as rasp_sysroot. Quick and dirty. You might also consider using rsync though.
    As a final note on this I have to say that scp has the somehow pleasant collateral effect of following the symlinks in libs.
  6. Clone the qt5 git repo and start building the qtbase module:

    $ git clone git://gitorious.org/qt/qt5.git
    $ cd qt5
    $ ./init-repository
    $ cd qt5/qtbase
    $ ./configure -prefix your_qt_prefix -release -device linux-rasp-pi-g++ \
    -make libs -device-option CROSS_COMPILE=your_toolchain_path/bin/arm-linux-gnueabihf- \
    -device-option DISTRO=wheezy -sysroot your_sysroot_path -opensource \
    -confirm-license -no-pch -make examples -nomake tests
    $ make -jn
    $ sudo make install

    In my case it was done automatically by the configure script, but you might need to set the pkgconfig path before running the configuration script:

    $ export PKG_CONFIG_PATH=your_sysroot_path/usr/lib/arm-linux-gnueabihf/pkgconfig
    $ export PKG_CONFIG_LIBDIR=yout_sysroot_path/usr/lib/pkgconfig:your_sysroot_path/usr/lib/arm-linux-gnueabihf/pkgconfig
    $ export PKG_CONFIG_SYSROOT_DIR=yout_sysroot_path


  7. During compilation I got an error indicating that it was impossible to find the header "vchost_config.h". I solved by editing the file in rasp_sysroot/opt/vc/include/interface/vmcs_host/vcgencmd.h:
    33c33

    < #include "vchost_config.h"
    ---
    > #include "linux/vchost_config.h"


    This is not very elegant maybe... anyway it is sufficient. You might add an include path in the qmake.conf or similar, but it seemed good that way :-)
  8. At this point qtbase should have been successfully compiled. Now at least you should compile the qtscript, qtjsbackend and the qtdeclarative module:

    $ cd ..
    $ cd qtscript
    $ your_qt_prefix/bin/qmake
    $ make -jn
    $ sudo make install


    Repeat the same for the other two modules.

Building the QtWayland Dependencies

The xkbcommon and the wayland libraries must be cross-compiled before trying to build QtWayland. To do that first setup the environment; I used this script to do it:

export RPI_SYSROOT=your_sysroot_path
export TOOLCHAIN=your_toolchain_path
export QTDIR=your_qt_sources_dir/qtbase
export PATH=$QTDIR/bin:$TOOLCHAIN/bin:$PATH
export PREFIX=your_qt_prefix
export PKG_CONFIG_PATH="$RPI_SYSROOT/usr/lib/pkgconfig:$RPI_SYSROOT/$PREFIX/lib/pkgconfig:$RPI_SYSROOT/$PREFIX/share/pkgconfig"
export PKG_CONFIG_SYSROOT_DIR="$RPI_SYSROOT"
export PKG_CONFIG_ALLOW_SYSTEM_LIBS=1
export PKG_CONFIG_ALLOW_SYSTEM_CFLAGS=1
export CPP=$TOOLCHAIN/bin/arm-linux-gnueabihf-cpp
export CC=$TOOLCHAIN/bin/arm-linux-gnueabihf-gcc
export CXX=$TOOLCHAIN/bin/arm-linux-gnueabihf-g++
export CFLAGS="--sysroot=$RPI_SYSROOT"
export CXXFLAGS="--sysroot=$RPI_SYSROOT"
export CPPFLAGS="--sysroot=$RPI_SYSROOT"
export LD=$TOOLCHAIN/bin/arm-linux-gnueabihf-ld
export LDFLAGS="--sysroot=$RPI_SYSROOT"
export AS=$TOOLCHAIN/bin/arm-linux-gnueabihf-as
export STRIP=$TOOLCHAIN/bin/arm-linux-gnueabihf-strip
export AR=$TOOLCHAIN/bin/arm-linux-gnueabihf-ar


Start the script and download from git the xkbcommon lib:

$ source env_setup.sh
$ git clone git://people.freedesktop.org/xorg/lib/libxkbcommon.git
$ cd libxkbcommon/
$ ./autogen.sh --prefix=some_prefix --host=arm-linux-gnueabihf
$ make && make install


Copy libs and headers resulting to your_sysroot_path.
Now before compiling the wayland library the wayland scanner is needed for the generation of C code from Wayland protocols. To compile this, open a new environment for standard compilation and start compiling the wayland-scanner and place it in the PATH:

$ git clone git://anongit.freedesktop.org/wayland/wayland
$ cd wayland
$ ./autogen.sh --disable-documentation
$ make
$ cp src/wayland-scanner $QTDIR/bin


Now get back to the cross-compilation environment and compile the wayland library itself:

$ cd wayland_dir
$ git clean -dxf
$ ./autogen.sh --host=arm-linux-gnueabihf --prefix=$RPI_SYSROOT$PREFIX --disable-scanner --disable-documentation
$ make
$ sudo make install


Then, if necessary, copy the libraries into your sysroot.
Now let's build QtWayland:

$ export QT_WAYLAND_GL_CONFIG=brcm_egl
$ cd your_qt_sources_dir
$ git clone http://qt.gitorious.org/qt/qtwayland
$ cd qtwayland
$ your_qt_prefix/qmake CONFIG+=wayland-compositor
$ make
$ sudo make install


At this point I have to say I had issues during the execution of the qmake binary. Unfortunately I couldn't track down all the reasons, but it seems that libxkbcommon couldn't be found. According to the .pro file, the qtCompileTest function is used to check if config.test/xkbcommon can be built. Appearantly, the inclusion of X11/keysym.h couldn't be satisfied, and also it shouldn't be needed... but although the file can be compiled, the qtwayland.pro file still was failing, so I simlply removed the checks for xkbcommon and the rest of the build procedure succeeded.

load(configure)
qtCompileTest(wayland)
#qtCompileTest(xkbcommon)
qtCompileTest(wayland_scanner)
qtCompileTest(wayland_egl)
qtCompileTest(egl)
qtCompileTest(brcm_egl)
qtCompileTest(glx)
qtCompileTest(xcomposite)

CONFIG += config_xkbcommon

load(qt_parts)

!config_wayland {
error(QtWayland requires Wayland 1.0.0 or higher)
}

#!config_xkbcommon {
error(QtWayland requires xkbcommon 0.2.0 or higher)
}

!config_wayland_scanner {
error(QtWayland requires wayland-scanner)
}

!config_wayland_egl {
message("no wayland-egl support detected, cross-toolkit compatibility disabled");
}

Running Applications Using the QtWayland Platform Plugin

Now copy the result of the build which should now be in your sysroot into your Pi and try to run the Wayland example compositor from QtWayland:

cd your_qt_prefix/examples/qtwayland/qml-compositor
export XDG_RUNTIME_DIR=/tmp
./qml-compositor -platform eglfs


At this point the server should be running. Now open another shell and try to run any Qt application using the wayland-brcm platform plugin:

$ cd your_app_path
$ ./your_app_bin -platform wayland-brcm &


Now you should see the window on the screen.
s It is possible however that some EGL/OpenGL error occurs, like eglCreatePixmapSurface failed: 3003, global image id: 0 0, then consider increasing the memory reserved to the GPU, that is a bad_allocation error. Simply add gpu_mem=n, where n is the number of MBs to assign to the GPU in the /boot/config.txt file. Read here for more information: http://elinux.org/RPiconfig.

Building QtWebKit

For more details refer to this. It seems Qt guys have done a good work on QtWebKit. Making it work simply requires to build and run. Compile as said the qtwebkit module, then copy back the libraries to the device and load a WebView element.
The only thing that still seems to be missing is the 16bit color depth support: if you try tu run you might see a mess on the scren, that is because the QtWebProcess is writing 24bit image on 16bit mode. More details on this here.
Anyway, it seems now it is sufficient to set the framebuffer to 24bits to make it work:

$ fbset -depth 24

No need to modify the eglfs plugin anymore. The EGL configuration seems to correctly reflect the framebuffer color depth.

Building QtMultimedia

QtMultimedia is the module responsible for the multimedia content handling. For Linux, it is based on gstreamer, which is available, ad already said, for Raspberry Pi. Anyway, gstreamer relies on plugins to decode/render multimedia content, but most of those are clearly not hardware accelerated, which makes it nearly useless on an embedded platform for video playback.

Anyway, there is a plugin that is supposed to use the RPi accelerated OpenMAX libraries, gst-omx. I have to say I still have never seen it work well, so I'm not sure whether this is working or not on Pi. It is an interesting subject, but I don't if or when I'll get my hands on that.
I tried the QtMultimedia module a couple of times though, and I could play a couple of videos, but the result was clearly useless. Something like this should play the video (no audio):

import QtQuick 2.0
import QtMultimedia 5.0

Rectangle {

   width:  1920
   height: 1080

   color: "black"
 

   MediaPlayer {
      id: player
      source: "file://..."
      autoPlay: true

   }

   VideoOutput {
      id: videoOutput
      source: player
      anchors.fill: parent
   }
}


Bye!