特集 : 最新組み込みLinux実践講座Part4

対象製品: Armadillo-500Armadillo-300Armadillo-9Armadillo-240Armadillo-230Armadillo-220Armadillo-210Armadillo(HT1070)Armadillo-J
先頭 Part 3 Part 5

(株)アットマークテクノ
中井真大
NAKAI Masahiro

この文書は技術評論社「Software Design」2007年11月号に掲載されたものです。

本章では, DirectFB をAtmark Dist に組み込む方法と, DirectFB-examplesを使用して動作確認を行います.またDirectFB のAPI を解説します.

DirectFB をAtmark Dist へ組み込む

今回作成するアンケートツールでは,手軽にフレームバッファへ画像の描画ができ,マウスやタッチパネルといったインプットデバイスのイベントを取得可能な「DirectFB」を使用します.本稿執筆時点のDirectFB の最新バージョンは1.0.1 です.このバージョンのソースコードを,本特集3章で準備したAtmark Distへ組み込み,ビルドできるようにします(図1).

●図1 Atmark Dist へDirectFB を組み込む

$ cd ~/work.sd
DirectFB のソースコードを取得
$ wget http://www.directfb.org/downloads/Core/DirectFB-1.0.1.tar.gz
$ cd atmark-dist/lib
DirectFB 用のディレクトリを作成
$ mkdir directfb
$ cd directfb
アーカイブを展開
$ tar zxf ../../../DirectFB-1.0.1.tar.gz

Atmark Distにソースコードを展開しただけでは,ビルドすることはできません.Atmark DistのビルドシステムにDirectFBを登録し,ビルドできるように変更する必要があります.

DirectFB を選択できるようにする

まず,Atmark DistのコンフィギュレーションでDirectFBを選択できるように,atmark-dist/config/config.in(リスト1)とatmark-dist/lib/Makefile(リスト2)を修正します.修正内容を見ていきましょう.

●リスト1 atmark-dist/config/config.in の修正個所

(略)
82: comment 'Library Configuration'
83:
84: comment 'Force build (Normally built when required)'
85: bool 'Build directfb'           CONFIG_LIB_DIRECTFB_FORCE                追加
86: if [ "$CONFIG_LIB_DIRECTFB_FORCE" = "y" ]; then                          追加
87:         comment '  directfb tools'                                       追加
88:         bool '  dfbdump'          CONFIG_LIB_DIRECTFB_DFBDUMP            追加
89:         bool '  dfbg'             CONFIG_LIB_DIRECTFB_DFBG               追加
90:         bool '  dfbinfo'          CONFIG_LIB_DIRECTFB_DFBINFO            追加
91:         bool '  dfbinput'         CONFIG_LIB_DIRECTFB_DFBINPUT           追加
92:         bool '  dfblayer'         CONFIG_LIB_DIRECTFB_DFBLAYER           追加
93:         bool '  dfbpenmount'      CONFIG_LIB_DIRECTFB_DFBPENMOUNT        追加
94:         bool '  dfbscreen'        CONFIG_LIB_DIRECTFB_DFBSCREEN          追加
95:         bool '  dfbsummon'        CONFIG_LIB_DIRECTFB_DFBSUMMON          追加
96: fi                                                                       追加
97: bool 'Build flex'               CONFIG_LIB_FLEX_FORCE
(略)
●リスト2 atmark-dist/lib/Makefile の修正個所

(略)
35: #
36: # and build these if someone needs them
37: #
38: dir_$(CONFIG_LIB_DIRECTFB)     += directfb                               追加
39: dir_$(CONFIG_LIB_DIRECTFB_FORCE) += directfb                             追加
40: dir_$(CONFIG_LIB_FLEX)         += flex
41: dir_$(CONFIG_LIB_FLEX_FORCE)   += flex
(略)
81: # And build libraries in the prop directory last
82: dir_y += $(ROOTDIR)/prop
83:
84: dir_d += directfb libsysfs2                                              修正
85:
86: distcleanable = $(foreach e,$(sort $(dir_d)),$(findstring $(e),$(dir_y) $(dir_n) $(dir_)))
(略)
  • リスト1:85行目~96行目

    “Build directfb”が選択された場合に,DirectFBのソースコードに含まれるツール群を選択できるようにします.

  • リスト2:38~39行目

    コンフィギュレーション時にDirectFBが選択された場合,ビルドされるように登録します.

  • リスト2:84行目

    make distclean時にDirectFBがdistcleanされるように登録します.

DirectFB 用のMakefile

次にDirectFB のMakefile を作成します.このMakefile は,DirectFB のソースコードを修正することなくAtmark Distでビルドできるように考慮して作成します.こうすることにより,DirectFB 自体のバージョンが上がった場合でも,少しの変更だけでバージョンアップできるようになります(リスト3).

●リスト3 atmark-dist/lib/directfb/Makefile の作成

 1: #
 2: # Makefile for DirectFB
 3: #
 4:
 5: DIRECTFB_DIR = $(shell pwd)
 6:
 7: SRC_DIR = DirectFB-1.0.1
 8: INSTALL_DIR = preinstall
 9:
10: MAKEHOST = ${shell $(SRC_DIR)/config.guess}
11: MAKETARGET = ${shell $(SRC_DIR)/config.sub $(CROSS)gnu}
12: CONF_OPT = --disable-libtool-lock --enable-shared --disable-x11 \
13:            --with-gfxdrivers=none
14: CONF_OPT_MISC = "CC=$(CROSS_COMPILE)gcc"
15:
16: all: build
17:
18: $(SRC_DIR)/Makefile:
19:         if [ ! -e $(SRC_DIR)/Makefile ]; then \
20:                 (cd $(SRC_DIR); \
21:                  ./configure --host=$(MAKETARGET)\
22:                              $(CONF_OPT) $(CONF_OPT_MISC));\
23:         fi
24:
25: build: $(SRC_DIR)/Makefile
26:         make -C $(SRC_DIR)
27:         mkdir -p $(INSTALL_DIR)
28:         make -C $(SRC_DIR) prefix=$(DIRECTFB_DIR)/$(INSTALL_DIR)/usr/local \
29:                 install
30:
31: romfs: build
32:         @sh romfs-sh $(DIRECTFB_DIR)/$(INSTALL_DIR)/
33:
34: clean:
35:         make -C $(SRC_DIR) clean
36:
37: distclean: clean
38:         make -C $(SRC_DIR) distclean
39:         rm -rf $(INSTALL_DIR)
40:
  • リスト3:18~23行目

    DirectFB が一度もコンフィギュレーションしていない場合に,自動でコンフィギュレーションされるようにします.

  • リスト3:25~29行目

    ビルドを行い,INSTALL_DIRにプレインストールさせます.

インストール用スクリプト

インストール処理が複雑なため,インストール用のスクリプトファイルも作成します(リスト4).

●リスト4 DirectFB のインストールスクリプト(romfs-sh)を作成

 1: #!/bin/sh
 2:
 3: PREINSTALL_DIR=$1
 4: [ "${VERBOSE}" = "" ] && VERBOSE=y
 5:
 6: p_mkdir() {
 7:         [ "${VERBOSE}" = "y" ] && echo MKDIR $2
 8:         mkdir -p $1/$2
 9: }
10:
11: p_romfsinst() {
12:         [ "${VERBOSE}" = "y" ] && echo ROMSINST `basename $2`
13:         ${ROMFSINST} $1 $2
14: }
15:
16: p_symlink() {
17:         [ "${VERBOSE}" = "y" ] && echo SYMLINK `basename $2`
18:         ${ROMFSINST} -s $1 $2
19: }
20:
21: check() {
22:         [ "${ROMFSINST}" = "" ] &&
23:                 echo "ERROR!! Can't find ROMFSINST" && exit 1
24:         [ "${ROMFSDIR}" = "" ] &&
25:                 echo "ERROR!! Can't find ROMFSDIR" && exit 1
26:         [ "${PREINSTALL_DIR}" = "" ] &&
27:                 echo "ERROR!! Can't find PREINSTALL_DIR" && exit 1
28: }
29:
30: prepare() {
31:         mkdir -p ${ROMFSDIR}
32:         p_mkdir ${ROMFSDIR} /lib
33:         p_mkdir ${ROMFSDIR} /usr
34:         p_mkdir ${ROMFSDIR} /usr/local
35:         p_mkdir ${ROMFSDIR} /usr/local/bin
36:         p_mkdir ${ROMFSDIR} /usr/local/lib
37:         p_mkdir ${ROMFSDIR} /usr/local/share
38: }
39:
40: install_core_libs() {
41:         (cd ${PREINSTALL_DIR}/usr/local/lib;
42:                 for lib in `ls lib*.so*`
43:                 do
44:                         LINK=`readlink $lib`
45:                         if [ "${LINK}" = "" ]; then
46:                                 p_romfsinst $lib /lib/$lib
47:                         else
48:                                 p_symlink ${LINK} /lib/$lib
49:                         fi
50:                 done
51:         )
52: }
53:
54: install_bin() {
55:         (cd ${PREINSTALL_DIR}/usr/local/bin;
56:                 for file in `ls`
57:                 do
58:                         p_romfsinst $file /usr/local/bin/$file
59:                 done
60:         )
61: }
62:
63: install_share() {
64:         (cd ${PREINSTALL_DIR};
65:                 for dir in `find usr/local/share/direct* -type d;`
66:                 do
67:                         p_mkdir ${ROMFSDIR} $dir
68:                         (cd $dir;
69:                                 for file in `ls`
70:                                 do
71:                                         p_romfsinst $file /$dir/$file
72:                                 done
73:                         )
74:                 done
75:         )
76: }
77:
78: install_lib() {
79:         (cd ${PREINSTALL_DIR};
80:                 for dir in `find usr/local/lib/direct* -type d;`
81:                 do
82:                         p_mkdir ${ROMFSDIR} $dir
83:                 done
84:                 for file in `find usr/local/lib/direct* -name \*.so;`
85:                 do
86:                         p_romfsinst $file /$file
87:                 done
88:         )
89: }
90:
91: #
92: # main
93: #
94: check
95: prepare
96: install_core_libs
97: install_bin
98: install_share
99: install_lib

クロスライブラリの追加

DirectFBは,JPEG,PNG,FreeType2ライブラリをサポートします.これらのライブラリを使用可能にするためには,DirectFB をコンフィギュレーションする前に開発環境へ追加しておかなければなりません.コンフィギュレーションシステムは,自動的に開発環境にインストールされているクロスライブラリを検出して,DirectFB が使用可能なライブラリに追加します.

図2のように開発環境にクロスライブラリをインストールしておきます.

●図2 開発環境にクロスライブラリをインストール

$ cd ~/work.sd
$ wget http://ftp.jp.debian.org/debian/pool/main/libj/libjpeg6b/libjpeg62_6b-13_arm.deb
$ wget http://ftp.jp.debian.org/debian/pool/main/libj/libjpeg6b/libjpeg62-dev_6b-13_arm.deb
$ wget http://ftp.jp.debian.org/debian/pool/main/libp/libpng/libpng12-0_1.2.15~beta5-1_arm.deb
$ wget http://ftp.jp.debian.org/debian/pool/main/libp/libpng/libpng12-dev_1.2.15~beta5-1_arm.deb
$ wget http://ftp.jp.debian.org/debian/pool/main/f/freetype/libfreetype6_2.2.1-5+etch1_arm.deb
$ wget http://ftp.jp.debian.org/debian/pool/main/f/freetype/libfreetype6-dev_2.2.1-5+etch1_arm.deb
$ dpkg-cross -a arm -b  libjpeg62_6b-13_arm.deb libjpeg62-dev_6b-13_arm.deb \
                        libpng12-0_1.2.15~beta5-1_arm.deb libpng12-dev_1.2.15~beta5-1_arm.deb \
                        libfreetype6_2.2.1-5+etch1_arm.deb libfreetype6-dev_2.2.1-5+etch1_arm.deb
# dpkg -i *arm-cross*

DirectFB の動作確認

では,DirectFBの動作確認を行うために,DirectFB の簡易デモが収録されているDirectFB-examplesをビルドしてみましょう.先ほどDirectFBを組み込んだのと同じように,DirectFB-examplesを組み込んでみます.本稿執筆時点のバージョンは1.0.0です.

DirectFB-examples のソースコードを準備

まずはソースコードを準備します(図3 ).DirectFB の場合にはライブラリ群の中(atmark-dist/lib)に追加しましたが,ここではアプリケーション群の中(atmark-dist/user)に追加します.

●図3 DirectFB-examples を組み込む

$ cd ~/work.sd
DirectFB-examples のソースコードを取得
$ wget http://www.directfb.org/downloads/Extras/DirectFB-examples-1.0.0.tar.gz
$ cd atmark-dist/user
$ mkdir directfb-examples
$ cd directfb-examples
DirectFB-examples 用のディレクトリを作成し,アーカイブを展開
$ tar zxf ../../../DirectFB-examples-1.0.0.tar.gz 

DirectFB と同様にビルドシステムの変更を行います(リスト5,6).

●リスト5 config/config.in の修正個所

(略)
716: bool 'dhrystone'                CONFIG_USER_DHRYSTONE_DHRYSTONE
717: bool 'de2ts-cal'                CONFIG_USER_DE2TSCAL_DE2TSCAL
718: bool 'directfb-examples'        CONFIG_USER_DIRECTFB_EXAMPLES         追加
719: bool 'expat-examples'           CONFIG_USER_EXPAT_EXAMPLES
720: if [ "$CONFIG_USER_EXPAT_EXAMPLES" = "y" ]; then
(略)
●リスト6 user/Makefile の修正個所

(略)
74: dir_$(CONFIG_USER_DHCPD_DHCPD)              += dhcpd
75: dir_$(CONFIG_USER_DIALD_DIALD)              += diald
76: dir_$(CONFIG_USER_DIRECTFB_EXAMPLES)        += directfb-examples       追加
77: dir_d                                       += directfb-examples       追加
78: dir_$(CONFIG_USER_DISCARD_DISCARD)          += discard
79: dir_$(CONFIG_USER_DISCARD_ECHO)             += discard
(略)

DirectFB-example 用Makefile

次に,DirectFB-examples用のMakefileを作成します.このMakefileもDirectFBと同じように作成します(リスト7).

●リスト7 atmark-dist/user/directfb-examples/Makefile

 1: #
 2: # Makefile for DirectFB-examples
 3: #
 4:
 5: DIRECTFB_EXAMPLES_DIR = ${shell pwd}
 6: DIRECTFB_DIR = $(ROOTDIR)/lib/directfb/preinstall/
 7:
 8: SRC_DIR = DirectFB-examples-1.0.0
 9: INSTALL_DIR = preinstall
10:
11: MAKEHOST = ${shell $(SRC_DIR)/config.guess}
12: MAKETARGET = ${shell $(SRC_DIR)/config.sub $(CROSS)gnu}
13:
14: PKG_CONFIG = true
15:
16: CONF_OPT =
17: CONF_OPT_MISC = "CC=$(CROSS_COMPILE)gcc" "PKG_CONFIG=$(PKG_CONFIG)" \
    "CFLAGS=-I$(DIRECTFB_DIR)/usr/local/include/directfb" \
    "LDFLAGS=-L$(DIRECTFB_DIR)/usr/local/lib -ldirectfb -ldirect -lfusion"
18:
19: all: build
20:
21: $(SRC_DIR)/Makefile:
22:         if [ ! -e $(SRC_DIR)/Makefile ]; then \
23:                 (cd $(SRC_DIR); \
24:                  ./configure --host=$(MAKETARGET) \
25:                              $(CONF_OPT) $(CONF_OPT_MISC));\
26:         fi
27:
28: build: $(SRC_DIR)/Makefile
29:         make -C $(SRC_DIR)
30:         mkdir -p $(INSTALL_DIR)
31:         make -C $(SRC_DIR) prefix=$(DIRECTFB_EXAMPLES_DIR)/$(INSTALL_DIR)/usr/local \
32:                 install
33:
34: romfs: build
35:         @[ "$(ROOTDIR)" != "" ] || echo "ERROR!! Can't find ROOTDIR"; exit
36:         @[ "$(ROMFSDIR)" != "" ] || echo "ERROR!! Can't find ROMFSDIR"; exit
37:         @mkdir -p $(ROMFSDIR)
38:         @mkdir -p $(ROMFSDIR)/lib
39:         @mkdir -p $(ROMFSDIR)/usr
40:         @mkdir -p $(ROMFSDIR)/usr/local
41:         @mkdir -p $(ROMFSDIR)/usr/local/bin
42:         @mkdir -p $(ROMFSDIR)/usr/local/share
43:
44:         cp -a $(INSTALL_DIR)/usr/local/bin \
45:                 $(ROMFSDIR)/usr/local/
46:         cp -a $(INSTALL_DIR)/usr/local/share/directfb-* \
47:                 $(ROMFSDIR)/usr/local/share
48:
49: clean:
50:         make -C $(SRC_DIR) clean
51:
52: distclean: clean
53:         make -C $(SRC_DIR) distclean
54:         rm -rf $(INSTALL_DIR)
55:
  • リスト7:34~47行目

    インストール処理を記述しています.インストール先にディレクトリを作成し,各ファイルをコピーします.

動作確認

これで,DirectFB の動作確認ができる状態になりました.図4のようにAtmark Distをコンフィギュレーションし,動作確認してみます.

●図4 コンフィギュレーション

$ make menuconfig
「Vendor/User Settings」のメニュー
Library Configuration  --->
        [*] Build directfb
        ---   directfb tools
        [*]   dfbdump
        [*]   dfbg
        [*]   dfbinfo
        [*]   dfbinput
        [*]   dfblayer
        [*]   dfbpenmount
        [*]   dfbscreen
        [*]   dfbsummon
Miscellaneous Applications  --->
        [*] directfb-examples

コンフィギュレーション終了後,makeを行うとビルドが開始されます.images/* にバイナリイメージができあがるので,できあがったromfs.img.gzをArmadillo-500のフラッシュメモリに書き込みます.書き込み後リブートすれば,新しいイメージ(DirectFBとDirectFB-examplesが含まれたイメージ)で動作します(図5).

●図5 ビルド

$ make
(略)
$ ls images
linux.bin linux.bin.gz romfs.img romfs.img.gz

なお,フラッシュメモリの書き換えについては,Armadillo-500のマニュアルを参照してください.

新しいイメージで起動したら,ユーザ名root /パスワードroot でログインします.この状態では/usr/local/binにはパスが通っていないため,フルパスでコマンドを実行する必要があります.図6のようにdf_windowを実行すると,図7のような画面がディスプレイに表示されます.

●図6 df_window の実行

(略)
atmark-dist v1.10.0 (AtmarkTechno/Armadillo-500)
Linux 2.6.18-12-at0 [armv6l arch]

Armadillo-500 login: root
Password:
Armadillo-500 # /usr/local/bin/df_window
●図7 df_window を実行した画面

DirectFB のAPI

ここからは,簡単なDirectFBのサンプルソースコード(章末リスト8,図8)を参照しながら,実際にDirectFB のAPI を使用してどのようにソースコードを書くのか説明していきます.なお,各APIの仕様はDirectFB の公式Web サイト(http://www.directfb.org/docs/DirectFB_Reference_1_0/)などで確認できます.

●図8 サンプルプログラムを実行した画面

DirectFB 初期化(45 ~ 61 行目)

DirectFBの初期化を行い,スーパーインターフェースを作成しています.サンプルではウィンドウイベントを取得するようにしか作られていないので,プライマリレイヤの設定しか行っていません.

インプットデバイスのリストやそれらのイベントを取得する場合などは,ここで行うのが良いでしょう.インプットデバイスのリストを取得するには,IDirectFB::EnumInputDevices( )を使用します.

フォント読み込み(66 ~ 74 行目)

DirectFB はFreeType2 ライブラリをサポートしているので,DrawString メソッドを使用して無償のTrueTypeフォントを簡単に描画できます.サンプルでは,DirectFB-examplesに含まれるTrueTypeフォントを使用しています.

無償の日本語TrueTypeフォントには,sazanamiフォント(ttf-sazanami-gothic,ttf-sazanami-mincho)や,kochi フォント(ttf-kochi-gothic,ttf-kochi-mincho)などがあります.

カーソル表示(79 行目)

インプットデバイスとしてマウスを使う場合,カーソル表示を行わなければなりません.サンプルではデフォルトのカーソルイメージ(cursor.dat)が使用されますが,リスト9のようにすればカーソルの形状を変更できます.

●リスト9 カーソル形状の変更

 1: static IDirectFBSurface *cursor;
 2: IDirectFBImageProvider *provider;
 3: DFBSurfaceDescription desc;
 4:
 5: DFBCHECK(dfb->CreateImageProvider(dfb, cursor_file, &provider));
 6: DFBCHECK(provider->GetSurfaceDescription(provider, &desc));
 7: DFBCHECK(dfb->CreateSurface(dfb, &desc, cursor));
 8: DFBCHECK(provider->RenderTo(provider, *cursor, NULL));
 9: DFBCHECK(provider->Release(provider));
10: DFBCHECK(layer->SetCursorShape(layer, *cursor, 0, 0));
11:
12: DFBCHECK(layer->EnableCursor(layer, 1));

バックグラウンドの作成(84 ~ 96 行目)

サンプルでは,バックグラウンド用のサーフェイスを作成し色を指定して塗りつぶしています.これは,バックグラウンド用の画像を描画する前提でコードが書かれているためです.単色で塗りつぶす場合は,IDirectFBDisplayLayer::SetBackgroundColor( )を使用することもできます.画像を描画する場合は,カーソルのサーフェイスに描画するのと同じように,CreateImageProviderを行いRenderToすることによって実現できます.

文字列描画(101 ~ 108 行目)

フォントを描画するには,サンプルのようにフォントを読み込ませ,読み込ませたフォントをバックグラウンド用サーフェイスに指定してからDrawStringメソッドを使用します.

DirectFB がサポートするエンコーディングは,UTF-8 です.日本語を表示させる場合は,ソースコードのエンコーディングを必ずUTF-8 にしてください.他のエンコーディングだと文字化けしてしまいます.

ウィンドウ作成(122 ~ 145 行目)

ボタンなどのオブジェクトを画面に配置する場合,ウィンドウを作成します.プライマリレイヤにウィンドウを作成して,そのウィンドウのサーフェイスを取得,イメージを描画します.最後のSetOpacityは,ウィンドウの不透明度を指定しています.このメソッドの第2引数を“0”(hide状態)に設定すると,マウスによるウィンドウイベントを取得できなくなってしまいます.

イベントバッファ作成(151行目)

ウィンドウのイベントを取得できるようにするためには,イベントバッファを作成する必要があります.すでに作成したイベントバッファにアタッチする場合は,AttachEventBuffer メソッドを使用します.このサンプルでは,ウィンドウイベントしか扱っていませんが,他にもインプットイベントやユーザ定義イベントなども扱うことができます.

イベント取得(158 ~ 169 行目)

作成したイベントバッファからイベントを取得する場合,イベントが到達するまでスレッドをアイドル状態にできるWaitForEvent メソッド群を使用します.イベントを取得するGetEvent メソッドの第2引数は,DFBEventのポインタを指定します.このDFBEventはunion型となっています(リスト10).イベントが発生した場合は,まずclazzメンバでイベントクラスをチェックするようにします.

●リスト10 DFBEvent 共用体

typedef union {
        DFBEventClass         clazz;         /* clazz of event */
        DFBInputEvent         input;         /* field for input events */
        DFBWindowEvent        window;        /* field for window events */
        DFBUserEvent          user;          /* field for user-defined events */
        DFBUniversalEvent     universal;     /* field for universal events */
} DFBEvent;

各DirectFB インターフェース解放(174 ~ 182 行目)

アプリケーションが終了する前に,各DirectFBインターフェースを解放します.これを行わない場合,アプリケーションの終了時にWarning が表示されます(図9).

●図9 未解放終了時のWarning

(!!!) *** WARNING [Application exited without deinitialization of DirectFB!]
                   *** [core.c:813 in dfb_core_deinit_check()]
(!!!) *** WARNING [still objects in 'Layer Region Pool']
                   *** [object.c:231 in fusion_object_pool_destroy()]
(!!!) *** WARNING [still objects in 'Layer Context Pool']
                   *** [object.c:231 in fusion_object_pool_destroy()]
(!!!) *** WARNING [setting window->stack = NULL]
                   *** [default.c:2805 in wm_close_stack()]
(!!!) *** WARNING [still objects in 'Window Pool']
                   *** [object.c:231 in fusion_object_pool_destroy()]
(!!!) *** WARNING [still objects in 'Surface Pool']    
                   *** [object.c:231 in fusion_object_pool_destroy()]
COLUMN

Armadillo-500 とArmadillo-9 のビデオパフォーマンス比較

Armadillo-500 とArmadillo-9 のビデオのパフォーマンスを比較してみました(表A).比較に使用したベンチマークアプリケーションは,DirectFB-examples に含まれる「df_dok」です.結果を見てみると,CPUパワーに依存しそうな項目に対しては,Armadillo-500が倍近いパフォーマンスを発揮しています(図A,B)

●図A Anti-aliased Text

●図B Blit colorkeyed


●表A df_dok の結果(640 ×480,16bpp)
項目Armadillo-500Armadillo-9
Anti-aliased Text 49.720(KChars/sec) 31.558(KChars/sec)
Anti-aliased Text (blend) 9.665(KChars/sec) 5.153(KChars/sec)
Fill Rectangle 29.886(MPixel/sec) 45.226(MPixel/sec)
Fill Rectangle (blend) 2.056(MPixel/sec) 1.084(MPixel/sec)
Fill Rectangles [10] 30.034(MPixel/sec) 45.925(MPixel/sec)
Fill Rectangles [10] (blend) 2.049(MPixel/sec) 1.087(MPixel/sec)
Fill Triangles 27.960(MPixel/sec) 31.146(MPixel/sec)
Fill Triangles (blend) 2.034(MPixel/sec) 1.081(MPixel/sec)
Draw Rectangle 7.630(KRects/sec) 3.500(KRects/sec)
Draw Rectangle (blend) 0.963(KRects/sec) 0.539(KRects/sec)
Draw Lines [10] 25.751(KLines/sec) 12.553(KLines/sec)
Draw Lines [10] (blend) 4.246(KLines/sec) 2.407(KLines/sec)
Fill Spans 28.797(MPixel/sec) 36.564(MPixel/sec)
Fill Spans (blend) 2.046(MPixel/sec) 1.077(MPixel/sec)
Blit 27.851(MPixel/sec) 19.692(MPixel/sec)
Blit colorkeyed 13.072(MPixel/sec) 12.502(MPixel/sec)
Blit destination colorkeyed 5.667(MPixel/sec) 6.437(MPixel/sec)
Blit with format conversion 5.077(MPixel/sec) 2.685(MPixel/sec)
Blit with colorizing 3.186(MPixel/sec) 1.737(MPixel/sec)
Blit from 32bit (blend) 2.200(MPixel/sec) 0.648(MPixel/sec)
Blit from 32bit (blend) with colorizing 1.108(MPixel/sec) 0.567(MPixel/sec)
Stretch Blit 27.452(MPixel/sec) 13.636(MPixel/sec)
Stretch Blit colorkeyed 8.409(MPixel/sec) 7.144(MPixel/sec)
COLUMN

楽チン作業♪

本章で解説した作業を簡単に行うには,図C のようにします.

●図C 本章の作業手順まとめ

$ cd ~/work.sd
$ wget http://ftp.jp.debian.org/debian/pool/main/libj/libjpeg6b/libjpeg62_6b-13_arm.deb
$ wget http://ftp.jp.debian.org/debian/pool/main/libj/libjpeg6b/libjpeg62-dev_6b-13_arm.deb
$ wget http://ftp.jp.debian.org/debian/pool/main/libp/libpng/libpng12-0_1.2.15~beta5-1_arm.deb
$ wget http://ftp.jp.debian.org/debian/pool/main/libp/libpng/libpng12-dev_1.2.15~beta5-1_arm.deb
$ wget http://ftp.jp.debian.org/debian/pool/main/f/freetype/libfreetype6_2.2.1-5+etch1_arm.deb
$ wget http://ftp.jp.debian.org/debian/pool/main/f/freetype/libfreetype6-dev_2.2.1-5+etch1_arm.deb
$ dpkg-cross -a arm -b libjpeg62_6b-13_arm.deb libjpeg62-dev_6b-13_arm.deb \
                       libpng12-0_1.2.15~beta5-1_arm.deb libpng12-dev_1.2.15~beta5-1_arm.deb \
                       libfreetype6_2.2.1-5+etch1_arm.deb libfreetype6-dev_2.2.1-5+etch1_arm.deb
# dpkg -i *arm-cross*
$ wget http://www.directfb.org/downloads/Core/DirectFB-1.0.1.tar.gz
$ wget http://www.directfb.org/downloads/Extras/DirectFB-examples-1.0.0.tar.gz
$ wget http://download.atmark-techno.com/misc/softwaredesign_2007-11/chapter4/atmark-dist-20070727_add_lib_directfb.patch
$ wget http://download.atmark-techno.com/misc/softwaredesign_2007-11/chapter4/atmark-dist-20070727_add_user_directfb-examples.patch
$ cd atmark-dist-20070727
$ patch -p1 < ../atmark-dist-20070727_add_lib_directfb.patch
$ patch -p1 < ../atmark-dist-20070727_add_user_directfb-examples.patch
$ (cd lib/directfb; tar zxf ../../../DirectFB-1.0.1.tar.gz)
$ (cd user/directfb-examples/; tar zxf ../../../DirectFB-examples-1.0.0.tar.gz)
本文図4 を参照
$ make menuconfig
$ make
●リスト8 簡単なDirectFB のサンプルコード

  1: #include <directfb.h>
  2:
  3: #include <stdio.h>
  4:
  5: static IDirectFB *dfb;
  6: static IDirectFBDisplayLayer *layer;
  7: static IDirectFBSurface *background;
  8:
  9: static IDirectFBFont *font;
 10:
 11: static IDirectFBWindow *win1;
 12: static IDirectFBSurface *win1_surface;
 13:
 14: static IDirectFBEventBuffer *event;
 15:
 16: /**
 17:  * 画像などのリソースデータディレクトリを指定しています
 18:  * このサンプルでは,DirectFB-examplesのものを使用します
 19:  **/
 20: #define DATADIR "/usr/local/share/directfb-examples/"
 21:
 22: /**
 23:  * 簡単なエラーチェックマクロ
 24:  **/
 25: #define DFBCHECK(x...)                                              \
 26: ({                                                                  \
 27:         if (x != DFB_OK) {                                          \
 28:                 fprintf(stderr, "%s <%d>:\n\t", __FILE__, __LINE__);\
 29:                 DirectFBErrorFatal(#x, x);                          \
 30:         }                                                           \
 31: })
 32:
 33: int
 34: main(int argc, char **argv)
 35: {
 36:         static int quit = 0;
 37:
 38:         DFBGraphicsDeviceDescription desc;
 39:         DFBDisplayLayerConfig config;
 40:
 41:         /**
 42:          * DirectFBの初期化を行い,スーパーインタフェースを作成します
 43:          * また,プライマリレイヤを取得し設定を行います
 44:          **/
 45:         DFBCHECK(DirectFBInit(&argc, &argv));
 46:         DFBCHECK(DirectFBCreate(&dfb));
 47:
 48:         DFBCHECK(dfb->GetDeviceDescription(dfb, &desc));
 49:
 50:         DFBCHECK(dfb->GetDisplayLayer(dfb, DLID_PRIMARY, &layer));
 51:
 52:         DFBCHECK(layer->SetCooperativeLevel(layer, DLSCL_ADMINISTRATIVE));
 53:
 54:         if (!((desc.blitting_flags & DSBLIT_BLEND_ALPHACHANNEL) &&
 55:               (desc.blitting_flags & DSBLIT_BLEND_COLORALPHA))) {
 56:                 config.flags = DLCONF_BUFFERMODE;
 57:                 config.buffermode = DLBM_BACKSYSTEM;
 58:
 59:                 DFBCHECK(layer->SetConfiguration(layer, &config));
 60:         }
 61:         DFBCHECK(layer->GetConfiguration(layer, &config));
 62:
 63:         /**
 64:          * フォントを読み込みます
 65:          **/
 66:         {
 67:                 DFBFontDescription desc;
 68:                 desc.flags = DFDESC_HEIGHT;
 69:                 desc.height = config.height / 10;
 70:
 71:                 DFBCHECK(dfb->CreateFont(dfb,
 72:                                          DATADIR"fonts/decker.ttf",
 73:                                          &desc, &font));
 74:         }
 75:
 76:         /**
 77:          * カーソル表示を有効にします
 78:          **/
 79:         DFBCHECK(layer->EnableCursor(layer, 1));
 80:
 81:         /**
 82:          * バックグラウンド用のサーフェイスを作成し,赤色で塗りつぶします
 83:          **/
 84:         {
 85:                 DFBSurfaceDescription desc;
 86:                 desc.flags = DSDESC_WIDTH | DSDESC_HEIGHT;
 87:                 desc.width = config.width;
 88:                 desc.height = config.height;
 89:                 DFBCHECK(dfb->CreateSurface(dfb, &desc, &background));
 90:
 91:                 DFBCHECK(background->SetColor(background,
 92:                                               0xff, 0x00, 0x00, 0xff));
 93:                 DFBCHECK(background->FillRectangle(background,
 94:                                                    0, 0,
 95:                                                    desc.width, desc.height));
 96:         }
 97:
 98:         /**
 99:          * バックグラウンドに文字列を描画します
100:          **/
101:         {
102:                 DFBCHECK(background->SetFont(background, font));
103:                 DFBCHECK(background->SetColor(background,
104:                                               0xff, 0xff, 0xff, 0xff));
105:                 DFBCHECK(background->DrawString(background,
106:                                                 "DFB_TEST", -1, 10, 10,
107:                                                 DSTF_LEFT | DSTF_TOP));
108:         }
109:
110:         /**
111:          * プライマリレイヤにバックラウンドサーフェイスをセットします
112:          **/
113:         {
114:                 DFBCHECK(layer->SetBackgroundImage(layer, background));
115:                 DFBCHECK(layer->SetBackgroundMode(layer, DLBM_IMAGE));
116:         }
117:
118:         /**
119:          * プライマリレイヤにウィンドウを作成し,そのウィンドウに
120:          * 画像を描画します
121:          **/
122:         {
123:                 DFBWindowDescription desc;
124:                 IDirectFBImageProvider *provider;
125:
126:                 desc.flags = (DWDESC_POSX | DWDESC_POSY |
127:                               DWDESC_WIDTH | DWDESC_HEIGHT | DWDESC_CAPS);
128:                 desc.posx = 100;
129:                 desc.posy = 100;
130:                 desc.width = config.width - 200;
131:                 desc.height = config.height - 200;
132:                 desc.caps = DWCAPS_ALPHACHANNEL;
134:
133:                 DFBCHECK(layer->CreateWindow(layer, &desc, &win1));
135:                 DFBCHECK(win1->GetSurface(win1, &win1_surface));
136:
137:                 DFBCHECK(dfb->CreateImageProvider(dfb,
138:                                                   DATADIR"/dfblogo.png",
139:                                                   &provider));
140:                 DFBCHECK(provider->RenderTo(provider, win1_surface, NULL));
141:
142:                 DFBCHECK(provider->Release(provider));
143:
144:                 DFBCHECK(win1->SetOpacity(win1, 0xFF));
145:         }
146:
147:         /**
148:          * 作成したウィンドウのイベントを取得できるように,
149:          * イベントバッファを作成します.
150:          **/
151:         DFBCHECK(win1->CreateEventBuffer(win1, &event));
152:
153:         /**
154:          * イベント待ちループ
155:          * ウィンドウ上でボタン押下イベントを検出した場合に,
156:          * ループから抜けます
157:          **/
158:         while (!quit) {
159:                 DFBEvent evt;
160:                 DFBCHECK(event->WaitForEvent(event));
161:
162:                 while (event->HasEvent(event) == DFB_OK) {
163:                         DFBCHECK(event->GetEvent(event, &evt));
164:
165:                         if (evt.clazz == DFEC_WINDOW)
166:                                 if (evt.window.type == DWET_BUTTONDOWN)
167:                                         quit = 1;
168:                 }
169:         }
170:
171:         /**
172:          * 各DirectFBのインタフェースを開放します
173:          **/
174:         event->Release(event);
175:         win1_surface->Release(win1_surface);
176:         win1->Release(win1);
177:
178:         font->Release(font);
179:         background->Release(background);
180:
181:         layer->Release(layer);
182:         dfb->Release(dfb);
183:
184:         return 0;
185: }

先頭 Part 3 Part 5