Produkty Novinky Články Návody Kontakty

Embedded Linux a okýnka - 3. DirectFB

V rámci seriálu o okýnkách v embedded Linuxu jsme si představili grafické prostředí Nano-X (dříve Microwindows) a GUI knihovnu FLTK, která pracovala nad Nano-X. Lákadlem kombinace Nano-X a FLTK byly velmi nízké nároky a dobrá použitelnost FLTK pro vývoj GUI aplikací.
Dnes naši pozornost zaměříme na grafické prostředí DirectFB, další možnou alternativu k desktopovému X-Windows. Stejně jako Nano-X i DirectFB bude pro vykreslování používat TFT displej INT070ATFT připojený k modulu SAM9260 jako framebuferové zařízení.

Něco málo o ...

Aniž byste to tušili, tak se možná s DirectFB setkáváte každý den, například když si pustíte svoji zánovní LCD televizi značky Phillips. Ano DirectFB je rozšířeným grafickým prostředím ve světě linuxových embedded (a nejen embedded) zařízeních. Stejně jako X-Windows a Nano-X poskytuje jednotné grafické prostředí, abstrakci nad výstupním grafickým zřízením, stará se o přijímání událostí od vstupních zařízeních, poskytuje hardwarovou akceleraci vykreslování anebo její softwarovou náhradu na platformách bez HW akcelerace, zvládá průhledná okna, vykreslování do více vrstev atd. Navíc v sobě obsahuje už i základního okenního manažera.
DirectFB oproti Nano-X dokáže obsluhovat nejen klasická vstupní zařízení prostřednictvím jejich dedikovaných ovladačů, ale i událostní vstupní zařízení, tzv. linux input system (zařízení /dev/input/eventX). Vykreslovat okýnka umí nejen na framebuferové zařízení, ale i na řadu dalších grafických karet/čipů. Za tuto univerzálnost vděčí podpoře directfb modulů, které se starají (spolu s patřičnými knihovnami) o vykreslování obrázků, správu fontů a podpoře různých vstupních a výstupních zařízení, včetně grafických akcelerátorů.
Na rozdíl od Nano-X, DirectFB nejde při komunikaci mezi grafickým subsystémem a aplikacemi cestou X-Windows: X-server -- TCP/IP -- X klient, ale používá vlastní řešení nazvané Fusion. Fusion je prostředí pro snadné paralelní a vícevláknové programování. Skládá se z knihovny kompilované v rámci kompilace DirectFB a modulu jádra. Toto prostředí je primárně určené pro řešení způsobu, jak může více aplikací přistupovat k DirectFB, resp. vykreslovat a přijímat události od vstupních zařízení obsluhovaných DirectFB. Nicméně je možné je využívat i pro jiné účely, například pro vytvoření zvukové subsystému - FusionSound. V případě, že nad DirectFB hodláte provozovat pouze jednu aplikaci, nemusíte se Fusion zaobírat. V opačném případě je nutné zkompilovat modul jádra Fusion a instalovat jej do cílového zařízení, plus musíte patřičně nakonfigurovat kompilaci DirectFB.
Za hlavní výhodu DirectFB považuji propracovanost, rozšířenost a hlavně stále aktivní vývoj. Tato platforma je dobře použitelná jak pro středně malé, tak i pro velké a výkonné embedded systémy. To může být paradoxně i nevýhoda - kvůli komplexnosti DirectFB. Přeci jen na binárku o velikosti 400kB se nedostaneme ani omylem. To spíš tak na cca 10MB (nestripované binárky pro SAM9260) plus dalších 1,6 MB pro knihovny pro správu fontů a vykreslování obrázků. Takže docela bumbrlíček, protože strippingem se dostaneme tak na cca 5MB. Nicméně autoři se chlubí, že DirectFB ustanovuje nový standard pro grafická prostředí pod Linuxem. To musíme zkusit!

Než začneme

  • Seznam potřebných nástrojů najdete v prvním díle tohoto seriálu, sekce Než začneme.
  • Zkompilované binárky knihoven, jejich hlavičkové soubory a další soubory budu instalovat do sysrootu (viz stejná sekce první díl), tj. do adresáře /home/emlin/devel/arm/sysroot/sam9260/local v mém virtuálním počítači.
  • Potřebné soubory si ze sysrootu zkopíruji do exportu, tj. adresáře /home/emlin/devel/arm/export/sam9260/roofts-dfb. Tento adresář pak budu přes NFS připojovat k souborovém systému modulu SAM9260, jak kdyby byl jeho lokální součástí.
Abych zkrátil a zpřehlednil zápisy příkazů, definoval jsem si v BASHi (příkazový interpretr) tři proměnné prostředí, které budu dále v článku používat.
$ SRC="/home/emlin/devel/arm/sysroot/sam9260/src"
$ SYSROOT="/home/emlin/devel/arm/sysroot/sam9260/local"
$ EXPORT="/home/emlin/devel/arm/export/sam9260/rootfs-dfb"

Závislosti

DirectFB závisí podobně jako Nano-X na knihovnách libpng (+ zlib) a jpeg pro vykreslování obrázků a na knihovně freetype pro správu fontů. Tyto knihovny jsme už kompilovali dříve kvůli Nano-X. Pokud je nemáte připravené ve svém sysrootu, mrkněte na první díl, sekce Závislosti.

Kompilace a instalace

Stáhneme si zdrojové kódy DirectFB-1.6.3 a rozbalíme je. Vznikne adresář Direct-1.6.3/. Vstoupíme do něj a pomocí svaté trojkombinace ortodoxního Linuxáka nakonfigurujeme, zkompilujeme a instalujeme do sysrootu knihovny DirectFB, hlavičkové soubory, directfb moduly a nějaké ty directfb utility.
DirectFB jsem nakonfiguroval pro běh pouze jedné aplikace. Byl jsem líný kompilovat a instalovat modul jádra pro prostředí Fusion, který je pro běh více aplikací nad DirectFB vyžadován. Při instalaci DirectFB jsem musel použít fintu s předefinováním proměnné datarootdir. Původní hodnota proměnné je nastavena volbou konfiguračního skriptu na /usr/local/share. To je ale nastavení platné pro kompilaci, resp. pro běh v cílovém zařízení, nikoliv pro instalaci do sysrootu. Proto při instalaci proměnou datarootdir přenastavuji pro účely instalace na $SYSROOT/share.
### konfigurace
$ ./configure --host=arm-none-linux-gnueabi \
  --prefix=$SYSROOT \
  --sysconfdir=/usr/local/etc \
  --datarootdir=/usr/local/share \
  --with-gfxdrivers=none --with-inputdrivers=linuxinput,ps2mouse,keyboard \
  --enable-fbdev --enable-png --enable-jpeg --enable-static \
  --disable-gif --disable-sdl --disable-x11 \
  --disable-pnm --disable-mpeg2 --disable-video4linux \
  CPPFLAGS="-I$SYSROOT/include" \
  CFLAGS='-march=armv5te -mtune=arm926ej-s -mabi=aapcs-linux' \
  LDFLAGS="-Wl,-rpath-link,$SYSROOT/lib -L$SYSROOT/lib" \
  CPPXXFLAGS="-I$SYSROOT/include" \
  CXXFLAGS="-march=armv5te -mtune=arm926ej-s -mabi=aapcs-linux" \
  PKG_CONFIG_PATH="$SYSROOT/lib/pkgconfig"

### kompilace a instalace
$ make
$ make datarootdir="$SYSROOT/share" install 
Další peripetie, se kterou se budeme muset vypořádat, je, že DirectFB hledá své direcfb moduly (např. pro klávesnici) v adresáři odvozeném od hodnoty parametru prefix zadaného při konfiguraci, konkrétně v našem případě v adresáři $SYSROOT/lib. Ovšem na modulu SAM9260, jako cílovém zařízení, budou moduly umístěny v adresáři /usr/local/lib/directfb-neco. Po řadě experimentů s volbami konfigurace jsem toto cross-kompilační omezení obešel vytvořením konfiguračního souboru directfbrc v adresáři $SYSROOT/etc. Tento soubor pak v cílovém zařízení (modulu SAM9260) umístíme do /usr/local/etc (viz níže sekce Instalace do zařízení). Obsah souboru vypadá takto:
# konfiguracni soubor DirectFB

module-dir=/usr/local/lib/directfb-1.6-0
disable-module=linux_input
mouse-protocol=IMPS/2
no-vt-switching 
Parametr module-dir je myslím jasný - určuje, kde budou hledány directfb moduly. Parametr disable-module určuje, které directfb moduly budou vynechány ze zavádění. Já vynechávám modul pro obsluhu událostních vstupních zařízení. To proto, aby se netloukly dedikované moduly pro myš a klávesnici s modulem pro obsluhu událostních vstupních zařízení. Dále definuji protokol pro komunikaci s myší (není povinné, většinou automatické určení funguje dobře) a nakonec volbou no-vt-switching zakazuji experimentální funkci pro přepínání virtuálních terminálů pomocí CTRL+ALT+Fx. Pro detaily se mrkněte do seznamu konfiguračních parametrů.

Kompilace a instalace příkladů

Nejjednodušší způsob, jak vyzkoušet, že DirectFB funguje jak má, je využít nějaký ten příklad, demo nebo něco takového. Autoři DirectFB nabízí ke stažení sadu příkladů a testů a to zvlášť pro každou hlavní verzi DirectFB. Příklady verze 1.6.0 si stáhněte a rozbalte, čímž se vytvoří adresář DirectFB-examples-1.6.0. Konfiguraci, kompilaci a instalaci do sysrootu vyřídíme tuxí trojkombinací.
### konfigurace
$ ./configure --host=arm-none-linux-gnueabi \
  --prefix=$SYSROOT \
  --sysconfdir=/usr/local/etc \
  --datarootdir=/usr/local/share \
  CPPFLAGS="-I$SYSROOT/include" \
  CFLAGS='-march=armv5te -mtune=arm926ej-s -mabi=aapcs-linux' \
  LDFLAGS="-Wl,-rpath-link,$SYSROOT/lib -L$SYSROOT/lib" \
  PKG_CONFIG_PATH="$SYSROOT/lib/pkgconfig"

### kompilace a instalace
$ make
$ make datarootdir="$SYSROOT/share" install

### rucni presun prikladu z bin do bin/apps
$ cd $SYSROOT/bin
$ mv df_* apps/

Instalace do zařízení

Stejně, jako v předchozích dílech seriálu, použijeme pro instalaci do cílového zařízení, modulu SAM9260, sdílení exportu (speciální adresář, viz Než začneme) přes NFS. Obsah exportu připojíme do souborového systému modulu SAM9260 jako /usr/local. Z pohledu modulu nebude možné poznat, že je adresář /usr/local vlastně adresářem v mém (vašem) linuxovém desktopu. Seznam souborů, které zkopírujeme ze sysrootu do exportu uvádím jako seznam kopírovacích příkazů.
### vytvorime si zakladni adresare
$ cd $EXPORT
$ mkdir bin etc lib share bin/apps

### kopirovani z bin/ 
$ cd $SYSROOT/bin
$ cp dfbinfo dfbg -t $EXPORT/bin
$ cd $SYSROOT/bin/apps
$ cp df_andi df_fonts df_window -t $EXPORT/bin/apps

### kopirovani z etc/
$ cp $SYSROOT/etc/directfbrc $EXPORT/etc

### kopirovani z lib/
$ cd $SYSROOT/lib
$ cp -d libfreetype.s* libjpeg.s* libpng.so libpng12.s* libz.s* \
  libdirect.so libdirect-*.s* libdirectfb.so libdirectfb-*.s* \
  libfusion.so libfusion-*.s* -t $EXPORT/lib
$ cp -r directfb-1.6-0 $EXPORT/lib

### kopirovani share/
$ cd $SYSROOT/share
$ cp -r fonts/ directfb-1.6.3/ directfb-examples/ -t $EXPORT/share/
Níže uvedené příkazy povolí sdílení exportu pro modul s IP 192.168.1.12 přes NFS. Sdílený adresář z mého počítače s IP 192.168.1.123 připojíme na modulu jako /usr/local. Pak aktualizujeme příkazem ldconfig cache s dostupnými dynamickými knihovnami.
### na pocitaci
$ echo "$EXPORT 192.168.1.12(rw,sync,no_subtree_check,no_root_squash)" |\
  sudo tee -a /etc/exports
$ sudo service nfs-kernel-server restart

### na modulu jako root
# mount -t nfs -o nolock \
  192.168.1.123://home/emlin/devel/arm/export/sam9260/rootfs-dfb \
  /usr/local
# ldconfig

Testování

Začneme zlehka. Připojíme USB myš a klávesnici, nasdílíme export našeho linuxového stroje přes NFS do adresáře /usr/local v modulu SAM9260. K modulu SAM9260 se přihlásíme přes lokální (USB klávesnice + TFT displej), sériový nebo telnetový terminál a přejdeme do adresáře /usr/local/bin. Zde pustíme utilitu dfbinfo. Měli bychom vidět následující výpis:
~~~~~~~~~~~~~~~~~~~~~~~~~~| DirectFB 1.6.3 |~~~~~~~~~~~~~~~~~~~~~~~~~~
     (c) 2012-2013  DirectFB integrated media GmbH
     (c) 2001-2013  The world wide DirectFB Open Source Community
     (c) 2000-2004  Convergence (integrated media) GmbH
   ----------------------------------------------------------------
(*) DirectFB/Core: Single Application Core. (2013-04-08 07:35)
(*) Direct/Memcpy: Using libc memcpy() 
(*) Direct/Thread: Started 'Fusion Dispatch' (-1) [MESSAGING OTHER/OTHER 0/0] <8388608>... 
(*) Direct/Thread: Started 'VT Flusher' (-1) [DEFAULT OTHER/OTHER 0/0] <8388608>... 
(*) DirectFB/FBDev: Found 'INT070ATFT' (ID 0) with frame buffer at 0xc2b68000, 750k (MMIO 0xfffff800, 0k) 
(*) Direct/Modules: suppress module 'linux_input' 
(*) Direct/Thread: Started 'PS/2 Input' (-1) [INPUT OTHER/OTHER 0/0] <8388608>...
(*) DirectFB/Input: IMPS/2 Mouse 1.0 (directfb.org)
(*) Direct/Thread: Started 'Keyboard Input' (-1) [INPUT OTHER/OTHER 0/0] <8388608>...
(*) DirectFB/Input: Keyboard 0.9 (directfb.org)
(*) DirectFB/Graphics: Generic Software Rasterizer 0.7 (directfb.org)
(*) DirectFB/Core/WM: Default 0.3 (directfb.org)
(*) FBDev/Mode: Setting 800x480 RGB16
(*) FBDev/Mode: Switched to 800x480 (virtual 800x480) at 16 bit (RGB16), pitch 1600
(*) FBDev/Mode: Setting 800x480 RGB16
(*) FBDev/Mode: Switched to 800x480 (virtual 800x480) at 16 bit (RGB16), pitch 1600

Screen (00) FBDev Primary Screen            (primary screen)
   Caps: VSYNC POWER_MANAGEMENT
     
     Layer (00) FBDev Primary Layer             (primary layer)
        Type:    GRAPHICS
        Caps:    SURFACE BRIGHTNESS CONTRAST SATURATION

Input (01) IMPS/2 Mouse                    (primary mouse)
   Vendor  ID: 0x0000
   Product ID: 0x0000
   Type: MOUSE
   Caps: AXES BUTTONS
   Max. Axis: 2
   Max. Button: 2

Input (00) Keyboard                        (primary keyboard)
   Vendor  ID: 0x0000
   Product ID: 0x0000
   Type: KEYBOARD
   Caps: KEYS
   Min. Keycode: 0
   Max. Keycode: 127 
DirectFB mi oznámil, že je nakonfigurován pro současný provoz pouze jedné aplikace, že našel framebuferové zařízení INT070ATFT s velikostí framebuferu 750k, dále, že nezavedl modul linux_input, že detekoval myš s protokolem IMPS/2 a klávesnici. Níže vidíme seznam všech výstupních a vstupních zařízení, která DirectFB detekoval a také určení, která zařízení jsou primární.
Pokud na vás DirectFB zkusí hlášku typu:
(!) DirectFB/core/system: No system found! 
(#) DirectFBError [DirectFBCreate() failed]: No implementation for this interface or content type has been found
tak hledejte chybu v nastavení cesty k directfb modulům případně chybu v názvu nebo umístění souboru /usr/local/etc/directfbrc.
Přesuneme se do adresáře /usr/local/bin/apps a příkazem ./df_window spustíme první testovací aplikaci. Objeví se kurzor na černém pozadí a chvíli po ošklivé hlášce začínající *** UNIMPLEMENTED ..., by se měl objevit obrazec s logem DirectFB (viz obrázek Test s utilitou df_window). Také by mělo jít pohybovat myší. Hrátky ukončíme stiskem tlačítka ESC (toho na lokálně připojené klávesnici!). Takto jednoduše jsme vlastně otestovali, že v DirectFB fungují vstupní a výstupní zařízení.
Test s utilitou df_window
Milovníci tučňáků si mohou zkusit pustit aplikaci df_andi. Není nad to koukat se na rozpínající se populaci 200 tučňáčků (viz obrázek Test s tučňáky).
Test s tučňáky
A komu by to ještě nestačilo může zkusit pustit aplikaci df_fonts, která zobrazí znakovou mapu určeného fontu. Příkaz: ./df_fonts /usr/local/share/fonts/truetype/arial.ttf to zajistí. Obrázek se mi už nechtělo dělat :-)