9. フレームバッファでグラフィックス - その1
下の図は Linux Zaurus で 今回のサンプルプログラムを実行した結果です。 フレームバッファに関する情報を取得した後、画面左下の部分に32ドットx32ドットの 赤い正方形を描画しています。フレームバッファはプログラムからメモリとして アクセスすることができます。フレームバッファの領域のメモリに対して 読み書きすることで画面に自由に描画することができます。SL Zaurus の画面は Qtライブラリを使って描画されていますが、ここでは Qtライブラリを無視して フレームバッファを直接操作しています。
| B500 | C700 QVGA |
|---|---|
| 240 x 320 | 240 x 320 |
| |
| C700 VGA |
|---|
| 640 x 480 |
|
フレームバッファの構造
スクリーンショット中の赤い正方形は 座標 (32, 0)から 32ドットx32ドットの大きさで描画しています。B500、C700ともに画面左下に表示されていることから X座標は左下から上に向かって増加し、Y座標は左から右に向かって増加します。 フレームバッファのメモリの内容は、メモリアドレスが増加する順に左の図の赤い矢印のように表示されます。 1ピクセルは2バイトになっているため、Xを1増加するためにはメモリアドレスを「+2」、 Yを1増加するためにはX方向の1行分のバイト数を加える必要があります。
SL Zaurusのフレームバッファは左下から左上に X が増加し、左から右へ Y が増加する 構造になっています。PCのフレームバッファを左に90度回転させた形になっていることがわかります。
赤 5 ビット、緑 6 ビット、青 5 ビットを使ってピクセルあたり 2 バイトで 65536 色の表示が可能です。
次の表は今回のサンプルプログラムで表示されるフレームバッファの情報をまとめたものです。 調べていませんが、C750 と C760 も C700 と同じではないかと思います。 数多くの値がありますが、機種やモードで変化する重要なものを赤で示してあります。 結局、X と Y の解像度、X の1行の長さ だけを使えば機種とモードの違いに対応できます。(カーネルのバージョンアップで例えば色数などが可変になれば状況はかわりますが)
| 機種 | B500 | C700QVGA | C700VGA | C700VGA縦 |
|---|---|---|---|---|
| Frame Buffer Physical Screen Information | ||||
| ID string | cotulla_fb | W100FB | W100FB | W100FB |
| frame buffer mem start | 0xA0300000 | 0x08800000 | 0x08800000 | 0x08800000 |
| frame buffer mem length | 153600 | 393216 | 2097152 | 2097152 |
| frame buffer type | 0 | 0 | 0 | 0 |
| interleave | 0 | 0 | 0 | 0 |
| frame buffer visual | 2 | 2 | 2 | 2 |
| x pan step | 0 | 0 | 0 | 0 |
| y pan step | 0 | 0 | 0 | 0 |
| y wrap step | 0 | 0 | 0 | 0 |
| line length (bytes) | 640 | 640 | 960 | 960 |
| Memory Mapped I/O start | 0x00000000 | 0x08010000 | 0x08010000 | 0x08010000 |
| Memory Mapped I/O length | 0 | 8192 | 8192 | 8192 |
| acceleration type | 0 | 0 | 0 | 0 |
| Frame Buffer Virtual Screen Information | ||||
| x resolution | 320 | 320 | 480 | 480 |
| y resolution | 240 | 240 | 640 | 640 |
| x res virtual | 320 | 320 | 480 | 480 |
| y res virtual | 240 | 240 | 640 | 640 |
| x offset | 0 | 0 | 0 | 0 |
| y offset | 0 | 0 | 0 | 0 |
| bits/pixel | 16 | 16 | 16 | 16 |
| grayscale | 0 | 0 | 0 | 0 |
| RED offset | 11 | 11 | 11 | 11 |
| RED length | 5 | 5 | 5 | 5 |
| RED msb_right | 0 | 0 | 0 | 0 |
| GREEN offset | 5 | 5 | 5 | 5 |
| GREEN length | 6 | 6 | 6 | 6 |
| GREEN msb_right | 0 | 0 | 0 | 0 |
| BLUE offset | 0 | 0 | 0 | 0 |
| BLUE length | 5 | 5 | 5 | 5 |
| BLUE msb_right | 0 | 0 | 0 | 0 |
| TRANSP offset | 0 | 0 | 0 | 0 |
| TRANSP length | 0 | 0 | 0 | 0 |
| TRANSP msb_right | 0 | 0 | 0 | 0 |
| nonstd | 0 | 0 | 0 | 0 |
| activate | 0 | 0 | 0 | 0 |
| height | 240 | -1 | -1 | -1 |
| width | 320 | -1 | -1 | -1 |
| accel_flags | 0 | 0 | 0 | 0 |
| pixclock | 0 | 4 | 4 | 4 |
| left margin | 0 | 0 | 0 | 0 |
| right margin | 0 | 0 | 0 | 0 |
| upper margin | 0 | 0 | 0 | 0 |
| lower margin | 0 | 0 | 0 | 0 |
| hsync length | 0 | 0 | 0 | 0 |
| vsync length | 0 | 0 | 0 | 0 |
| sync | 0 | 0 | 0 | 0 |
| vmode | 0 | 0 | 0 | 0 |
フレームバッファは以下のようにして使います。
- デバイス /dev/fb0 を読み書き可でオープン
- スクリーンの物理情報を取得
- フレームバッファデバイスをメモリにマップ
- メモリに書き込むことでグラフィックを描画
- 不要になったらメモリをアンマップ
- デバイスをクローズ
ファイルをランダムアクセスするために「ファイルをメモリにマップしてメモリを操作する」 方法と同じです。
フレームバッファ用ライブラリ
フレームバッファを使う上で必要となる決まった操作をサブルーチンとして用意しておきます。 フレームバッファのオープン, クローズ、設定の変更と復帰などです。
@-------------------------------------------------------------------------
@ file : fblib.s
@ 2003/10/05
@ Copyright (C) 2003 Jun Mizutani <mizutani.jun@nifty.ne.jp>
@-------------------------------------------------------------------------
.ifndef __FBLIB
__FBLIB = 1
.ifndef __SYSCALL
.include "syscalls.s"
.endif
.ifndef O_RDWR
O_RDWR = 2
.endif
PROT_READ = 0x1 @ page can be read
PROT_WRITE = 0x2 @ page can be written
MAP_SHARED = 0x01 @ Share changes
FBIOGET_VSCREENINFO = 0x4600
FBIOPUT_VSCREENINFO = 0x4601
FBIOGET_FSCREENINFO = 0x4602
FBIOGETCMAP = 0x4604
FBIOPUTCMAP = 0x4605
@==============================================================
.text
@-------------------------------------------------------------------------
@ open framebuffer device file
@-------------------------------------------------------------------------
fbdev_open:
stmfd sp!, {r1-r2, lr}
adr r0, fb_device @ open /dev/fb0
mov r1, #O_RDWR @ flag
mov r2, #0 @ mode
swi #sys_open
ldr r1, fb_desc
str r0, [r1] @ save fd
ldr r1, mmap_arg
str r0, [r1, #+16] @ fd
cmp r0, #0
ldmfd sp!, {r1-r2, pc} @ return
fb_device:
.asciz "/dev/fb0"
.align 2
@-------------------------------------------------------------------------
@ close framebuffer
@-------------------------------------------------------------------------
fbdev_close:
stmfd sp!, {r0, r1, lr}
ldr r1, fb_desc @ close /dev/fb0
ldr r0, [r1]
swi #sys_close
tst r0, r0
ldmfd sp!, {r0, r1, pc} @ return
@-------------------------------------------------------------------------
@ フレームバッファの物理状態を取得
@-------------------------------------------------------------------------
fb_get_fscreen:
stmfd sp!, {r0-r2, lr}
ldr r1, fb_desc
ldr r0, [r1]
ldr r1, =FBIOGET_FSCREENINFO
ldr r2, fscinfo @ 保存先指定
swi #sys_ioctl
cmp r0, #0
ldmfd sp!, {r0-r2, pc} @ return
@-------------------------------------------------------------------------
@ 現在のフレームバッファの状態を取得
@-------------------------------------------------------------------------
fb_get_screen:
stmfd sp!, {r0-r2, lr}
ldr r1, fb_desc
ldr r0, [r1]
ldr r1, =FBIOGET_VSCREENINFO
ldr r2, scinfsave @ 保存先指定
swi #sys_ioctl
cmp r0, #0
ldmfd sp!, {r0-r2, pc} @ return
@-------------------------------------------------------------------------
@ フレームバッファ設定を書きこむ
@-------------------------------------------------------------------------
fb_set_screen:
stmfd sp!, {r0-r2, lr}
ldr r1, fb_desc
ldr r0, [r1]
ldr r1, =FBIOPUT_VSCREENINFO
ldr r2, scinfdata @ 設定済みデータ
swi #sys_ioctl
cmp r0, #0
ldmfd sp!, {r0-r2, pc} @ return
@-------------------------------------------------------------------------
@ 保存済みのフレームバッファ設定を新規設定用にコピー
@-------------------------------------------------------------------------
fb_copy_scinfo:
stmfd sp!, {r0-r3, lr}
ldr r0, scinfsave
ldr r1, scinfdata
ldr r2, fb_screeninfo_size
1: ldr r3, [r0],#4 @ post-indexed addressing
str r3, [r1],#4
subs r2, r2, #1
bne 1b
ldmfd sp!, {r0-r3, pc} @ return
@-------------------------------------------------------------------------
@ フレームバッファメモリをマッピング
@-------------------------------------------------------------------------
fb_map_screen:
stmfd sp!, {r1-r2, lr}
ldr r0, scinfsave @ screen_info structure
ldr r1, [r0, #+12] @ yres_virtual
ldr r2, [r0, #+8] @ xres_virtual
mul r1, r2, r1 @ x * y
ldr r2, [r0, #+24] @ bits_per_pixel
mov r2, r2, LSR #3
mul r1, r2, r1 @ r1 = x*y*depth/8
ldr r0, mmap_arg
str r1, [r0, #+4] @ mmap_arg_len
ldr r2, =(PROT_READ|PROT_WRITE)
str r2, [r0, #+8] @ mmap_arg_prot
ldr r2, =MAP_SHARED
str r2, [r0, #+12] @ mmap_arg_flags
mov r1, #0
str r1, [r0] @ mmap_arg_addr
str r1, [r0, #+20] @ mmap_arg_offset
swi #old_mmap @ 90
ldr r1, fb_addr
str r0, [r1]
cmp r0, #0
ldmfd sp!, {r1-r2, pc} @ return
@-------------------------------------------------------------------------
@ フレームバッファメモリをアンマップ
@-------------------------------------------------------------------------
fb_unmap_screen:
stmfd sp!, {r0-r2, lr}
adr r2, mmap_arg
ldr r0, [r2] @ adr
ldr r1, [r2, #+4] @ len
swi #sys_munmap
tst r0, r0
ldmfd sp!, {r0-r2, pc} @ return
@-------------------------------------------------------------------------
@ 保存済みのフレームバッファ設定を復帰
@-------------------------------------------------------------------------
fb_restore_sc:
stmfd sp!, {r0-r2, lr}
adr r1, fb_desc
ldr r0, [r1]
ldr r1, =FBIOPUT_VSCREENINFO
ldr r2, scinfsave
swi #sys_ioctl
tst r0, r0
ldmfd sp!, {r0-r2, pc} @ return
@==============================================================
.align 2
mmap_arg: .long _mmap_arg
scinfsave: .long scinfo_save
scinfdata: .long scinfo_data
fscinfo: .long fsc_info
fb_screeninfo_size: .long (scinfo_data - scinfo_save)/4
fb_desc: .long _fb_desc
fb_addr: .long _fb_addr
.pool
@==============================================================
.bss
_fb_desc: .long 0
_fb_addr: .long 0
_mmap_arg:
mmap_arg_addr: .long 0 @ mmap_arg[0]
mmap_arg_len: .long 0 @ mmap_arg[4]
mmap_arg_prot: .long 0 @ mmap_arg[8]
mmap_arg_flags: .long 0 @ mmap_arg[12]
mmap_arg_fd: .long 0 @ mmap_arg[16]
mmap_arg_offset: .long 0 @ mmap_arg[20]
scinfo_save:
sis_xres: .long 0 @ visible resolution
sis_yres: .long 0
sis_xres_virtual: .long 0 @ virtual resolution
sis_yres_virtual: .long 0
sis_xoffset: .long 0 @ offset from virtual to visible
sis_yoffset: .long 0 @ resolution
sis_bits_per_pixel: .long 0 @ guess what
sis_grayscale: .long 0 @ != 0 Graylevels instead of colors
sis_red_offset: .long 0 @ beginning of bitfield
sis_red_length: .long 0 @ length of bitfield
sis_red_msb_right: .long 0 @ != 0 : Most significant bit is
sis_green_offset: .long 0 @ beginning of bitfield
sis_green_length: .long 0 @ length of bitfield
sis_green_msb_right: .long 0 @ != 0 : Most significant bit is
sis_blue_offset: .long 0 @ beginning of bitfield
sis_blue_length: .long 0 @ length of bitfield
sis_blue_msb_right: .long 0 @ != 0 : Most significant bit is
sis_transp_offset: .long 0 @ beginning of bitfield
sis_transp_length: .long 0 @ length of bitfield
sis_transp_msb_right: .long 0 @ != 0 : Most significant bit is
sis_nonstd: .long 0 @ != 0 Non standard pixel format
sis_activate: .long 0 @ see FB_ACTIVATE_*
sis_height: .long 0 @ height of picture in mm
sis_width: .long 0 @ width of picture in mm
sis_accel_flags: .long 0 @ acceleration flags (hints)
sis_pixclock: .long 0 @ pixel clock in ps (pico seconds)
sis_left_margin: .long 0 @ time from sync to picture
sis_right_margin: .long 0 @ time from picture to sync
sis_upper_margin: .long 0 @ time from sync to picture
sis_lower_margin: .long 0
sis_hsync_len: .long 0 @ length of horizontal sync
sis_vsync_len: .long 0 @ length of vertical sync
sis_sync: .long 0 @ see FB_SYNC_*
sis_vmode: .long 0 @ see FB_VMODE_*
sis_reserved: .space 24 @ Reserved for future compatibility
scinfo_data: .skip (scinfo_data - scinfo_save)
fsc_info:
fsi_id: .space 16 @ 0 identification string
fsi_smem_start: .long 0 @ 16 Start of frame buffer mem
fsi_smem_len: .long 0 @ 20 Length of frame buffer mem
fsi_type: .long 0 @ 24 see FB_TYPE_*
fsi_type_aux: .long 0 @ 28 Interleave for interleaved Planes
fsi_visual: .long 0 @ 32 see FB_VISUAL_*
fsi_xpanstep: .hword 0 @ 36 zero if no hardware panning
fsi_ypanstep: .hword 0 @ 38 zero if no hardware panning
fsi_ywrapstep: .hword 0 @ 40 zero if no hardware ywrap
fsi_padding: .hword 0 @ 42 for alignment, jm 1/26/2001
fsi_line_length: .long 0 @ 44 length of a line in bytes
fsi_mmio_start: .long 0 @ 48 Start of Memory Mapped I/O
fsi_mmio_len: .long 0 @ 52 Length of Memory Mapped I/O
fsi_accel: .long 0 @ 56 Type of acceleration available
fsi_reserved: .space 6 @ Reserved for future compatibility
.endif
各サブルーチンを簡単に解説します。レジスタは変化しません。
- fbdev_open
- フレームバッファのデバイスファイルをオープン。最初に呼びます。
- fbdev_close
- フレームバッファのデバイスファイルをクローズ。最後に呼びます。
- fb_get_fscreen
- フレームバッファの物理状態を fscinfo に取得します。
- fb_get_screen
- 現在のフレームバッファの状態を scinfo_save に取得します。たとえば
sis_xres でX方向の解像度を知ることができます。これで取得した値を
使うことで異なる画面モードに対応した描画が可能になります。
- fb_copy_scinfo
- 保存済みのフレームバッファ設定scinfo_save を新規設定用に scinfo_data にコピー。
設定を変更する場合にコピーに変更を加え、オリジナルは復帰用に残しておきます。
SL Zaurusでは使う必要はないかもしれません。
- fb_set_screen
- フレームバッファ設定 scinfo_data を書き込みます。 グラフィックのチップにネイティブに対応したフレームバッファの場合は 動的に変更することができます。
- fb_map_screen
- フレームバッファをメモリをマッピングします。 マッピングされたメモリの先頭アドレスが
r0 に返ります。fb_addr にも同じ値が設定されます。このアドレスから始まるメモリに値を書き込むと
画面に表示されるようになります。
- fb_unmap_screen
- フレームバッファメモリをアンマップ。フレームバッファが不要になったら呼びます。
サンプル
上で用意したライブラリと前回のプログラムを利用したフレームバッファを使ったサンプルプログラムです。 物理的な画面情報と論理的な画面情報、メモリにマップされたフレームバッファの先頭アドレスとサイズを表示した後、赤い正方形を描画します。 fb_get_fscreen と fb_get_screen で得られた情報にアクセスする場合の参考にして下さい。 フレームバッファの情報の意味を表示するための文字列が多いため長くなってしまいました。赤い正方形を描画する部分は 15行だけ です。
@-------------------------------------------------------------------------
@ file : fbinfo.s
@ 2003/10/05
@ Copyright (C) 2003 Jun Mizutani <mizutani.jun@nifty.ne.jp>
@-------------------------------------------------------------------------
.include "syscalls.s"
.include "fblib.s"
.include "stdio.s"
.text
.align 2
.global _start
@-------------------------------------------------------------------------
@ メイン
@-------------------------------------------------------------------------
_start:
@-------------------------------------------
@ フレームバッファの準備
@-------------------------------------------
bl fbdev_open @ /dev/fb0 をオープン
bmi fb_Error
bl fb_get_fscreen @ 物理スクリーン情報を取得
bl fb_get_screen @ スクリーン情報を取得
bmi fb_Error
bl fb_copy_scinfo @ scinfo_data を設定
bl fb_map_screen @ メモリにマッピング
bmi fb_Error
@-------------------------------------------
@ フレームバッファの情報を表示
@-------------------------------------------
adr r3, fbinfo_msg00
ldr r0, [r3], #4
bl OutAsciiZ @ Physical Screen Information title
bl NewLine
ldr r0, [r3], #4
bl OutAsciiZ @ id string
ldr r2, fsc_info0
mov r0, r2
add r2, r2, #16
bl OutAsciiZ
bl NewLine
bl print_hex_data @ frame buffer mem start
mov r1, #4
bl print_long_data
mov r1, #3
1: ldr r0, [r3], #4
bl OutAsciiZ
ldrh r0, [r2], #2 @ hword
bl PrintLeft
bl NewLine
subs r1, r1, #1
bne 1b
add r2, r2, #2 @ skip padding
mov r1, #1
bl print_long_data
bl print_hex_data @ Memory Mapped I/O start
mov r1, #2
bl print_long_data
ldr r0, [r3],#4
bl OutAsciiZ @ Virtual Screen Information
ldr r2, scinfo_data0
mov r1, #34
bl print_long_data
@-------------------------------------------
@ フレームバッファのアドレス
@-------------------------------------------
ldr r0, maped_addr0
bl OutAsciiZ
ldr r1, fb_addr
ldr r0, [r1] @ 先頭アドレス
bl PrintHex8
bl NewLine
ldr r0, maped_length0
bl OutAsciiZ
ldr r1, mmap_arg
ldr r0, [r1, #4] @ サイズ
bl PrintLeft
bl NewLine
@-------------------------------------------
@ フレームバッファに描画
@-------------------------------------------
ldr r1, fb_addr
ldr r0, [r1] @ 先頭アドレス
add r0, r0, #64 @ 32ドット上
ldr r1, fsc_info0
ldr r1, [r1, #44] @ 1行のバイト数
sub r1, r1, #64 @ 次行までのオフセット
mov r3, #32
2: mov r2, #32
mov ip, #0xF800 @ 赤
3: strh ip, [r0], #2
subs r2, r2, #1
bne 3b
add r0, r0, r1
subs r3, r3, #1
bne 2b
@-------------------------------------------
@ フレームバッファの後始末
@-------------------------------------------
bl fb_restore_sc @ 保存済みの設定を復帰
bl fb_unmap_screen
bl fbdev_close
fb_Error:
b Exit
@-------------------------------------------------------------------------
@ 情報表示用サブルーチン
@-------------------------------------------------------------------------
print_long_data:
stmfd sp!, {lr}
1: ldr r0, [r3], #4
bl OutAsciiZ
ldr r0, [r2], #4
bl PrintLeft
bl NewLine
subs r1, r1, #1
bne 1b
ldmfd sp!, {pc}
print_hex_data:
stmfd sp!, {lr}
ldr r0, [r3], #4
bl OutAsciiZ
ldr r0, [r2], #4
bl PrintHex8
bl NewLine
ldmfd sp!, {pc}
@-------------------------------------------------------------------------
@ .data, .bss セクションのアドレス
@-------------------------------------------------------------------------
fsc_info0: .long fsc_info @ fblib.s
scinfo_data0: .long scinfo_data @ fblib.s
fbinfo_msg00: .long fbinfomsg00 @ 表示用メッセージ格納アドレス
fbinfo_msg01: .long fbinfomsg01
fbinfo_msg02: .long fbinfomsg02
fbinfo_msg03: .long fbinfomsg03
fbinfo_msg04: .long fbinfomsg04
fbinfo_msg05: .long fbinfomsg05
fbinfo_msg06: .long fbinfomsg06
fbinfo_msg07: .long fbinfomsg07
fbinfo_msg08: .long fbinfomsg08
fbinfo_msg09: .long fbinfomsg09
fbinfo_msg10: .long fbinfomsg10
fbinfo_msg11: .long fbinfomsg11
fbinfo_msg12: .long fbinfomsg12
fbinfo_msg13: .long fbinfomsg13
fbinfo_msg20: .long fbinfomsg20
fbinfo_msg21: .long fbinfomsg21
fbinfo_msg22: .long fbinfomsg22
fbinfo_msg23: .long fbinfomsg23
fbinfo_msg24: .long fbinfomsg24
fbinfo_msg25: .long fbinfomsg25
fbinfo_msg26: .long fbinfomsg26
fbinfo_msg27: .long fbinfomsg27
fbinfo_msg28: .long fbinfomsg28
fbinfo_msg29: .long fbinfomsg29
fbinfo_msg30: .long fbinfomsg30
fbinfo_msg31: .long fbinfomsg31
fbinfo_msg32: .long fbinfomsg32
fbinfo_msg33: .long fbinfomsg33
fbinfo_msg34: .long fbinfomsg34
fbinfo_msg35: .long fbinfomsg35
fbinfo_msg36: .long fbinfomsg36
fbinfo_msg37: .long fbinfomsg37
fbinfo_msg38: .long fbinfomsg38
fbinfo_msg39: .long fbinfomsg39
fbinfo_msg40: .long fbinfomsg40
fbinfo_msg41: .long fbinfomsg41
fbinfo_msg42: .long fbinfomsg42
fbinfo_msg43: .long fbinfomsg43
fbinfo_msg44: .long fbinfomsg44
fbinfo_msg45: .long fbinfomsg45
fbinfo_msg46: .long fbinfomsg46
fbinfo_msg47: .long fbinfomsg47
fbinfo_msg48: .long fbinfomsg48
fbinfo_msg49: .long fbinfomsg49
fbinfo_msg50: .long fbinfomsg50
fbinfo_msg51: .long fbinfomsg51
fbinfo_msg52: .long fbinfomsg52
fbinfo_msg53: .long fbinfomsg53
fbinfo_msg54: .long fbinfomsg54
maped_addr0: .long maped_addr
maped_length0: .long maped_length
@-------------------------------------------------------------------------
@ 文字列データ
@-------------------------------------------------------------------------
.data
.align 2
fbinfomsg00: .asciz "Frame Buffer Physical Screen Information\n"
fbinfomsg01: .asciz " ID string : "
fbinfomsg02: .asciz " frame buffer mem start : 0x"
fbinfomsg03: .asciz " frame buffer mem length : "
fbinfomsg04: .asciz " frame buffer type : "
fbinfomsg05: .asciz " interleave : "
fbinfomsg06: .asciz " frame buffer visual : "
fbinfomsg07: .asciz " x pan step : "
fbinfomsg08: .asciz " y pan step : "
fbinfomsg09: .asciz " y wrap step : "
fbinfomsg10: .asciz " line length (bytes) : "
fbinfomsg11: .asciz " Memory Mapped I/O start : 0x"
fbinfomsg12: .asciz " Memory Mapped I/O length: "
fbinfomsg13: .asciz " acceleration type : "
fbinfomsg20: .asciz "\nFrame Buffer Virtual Screen Information\n"
fbinfomsg21: .asciz " x resolution : "
fbinfomsg22: .asciz " y resolution : "
fbinfomsg23: .asciz " x res virtual : "
fbinfomsg24: .asciz " y res virtual : "
fbinfomsg25: .asciz " x offset : "
fbinfomsg26: .asciz " y offset : "
fbinfomsg27: .asciz " bits/pixel : "
fbinfomsg28: .asciz " grayscale : "
fbinfomsg29: .asciz " RED offset : "
fbinfomsg30: .asciz " length : "
fbinfomsg31: .asciz " msb_right : "
fbinfomsg32: .asciz " GREEN offset : "
fbinfomsg33: .asciz " length : "
fbinfomsg34: .asciz " msb_right : "
fbinfomsg35: .asciz " BLUE offset : "
fbinfomsg36: .asciz " length : "
fbinfomsg37: .asciz " msb_right : "
fbinfomsg38: .asciz " TRANSP offset : "
fbinfomsg39: .asciz " length : "
fbinfomsg40: .asciz " msb_right : "
fbinfomsg41: .asciz " nonstd : "
fbinfomsg42: .asciz " activate : "
fbinfomsg43: .asciz " height : "
fbinfomsg44: .asciz " width : "
fbinfomsg45: .asciz " accel_flags : "
fbinfomsg46: .asciz " pixclock : "
fbinfomsg47: .asciz " left margin : "
fbinfomsg48: .asciz " right margin : "
fbinfomsg49: .asciz " upper margin : "
fbinfomsg50: .asciz " lower margin : "
fbinfomsg51: .asciz " hsync length : "
fbinfomsg52: .asciz " vsync length : "
fbinfomsg53: .asciz " sync : "
fbinfomsg54: .asciz " vmode : "
maped_addr: .asciz " Frame buffer is mapped from 0x"
maped_length: .asciz " Length of Frame buffer : "
.align 2
文字列のデータを .data セクションに置いて、各文字列の先頭アドレスを .text セクションに ポインタ配列のような形式に用意しています。文字列の先頭アドレスを r3 レジスタを使って 順次アクセスしています。
サンプルプログラムを実際にアセンブルして実行してみます。 アセンブルとリンクにはasld スクリプトを使っています。以下の例は SL-B500 で実行した結果です。
~/Documents/testarm$ asld fbinfo
~/Documents/testarm$ ./fbinfo
Frame Buffer Physical Screen Information
ID string : cotulla_fb
frame buffer mem start : 0xA0300000
frame buffer mem length : 153600
frame buffer type : 0
interleave : 0
frame buffer visual : 2
x pan step : 0
y pan step : 0
y wrap step : 0
line length (bytes) : 640
Memory Mapped I/O start : 0x00000000
Memory Mapped I/O length: 0
acceleration type : 0
Frame Buffer Virtual Screen Information
x resolution : 320
y resolution : 240
x res virtual : 320
y res virtual : 240
x offset : 0
y offset : 0
bits/pixel : 16
grayscale : 0
RED offset : 11
length : 5
msb_right : 0
GREEN offset : 5
length : 6
msb_right : 0
BLUE offset : 0
length : 5
msb_right : 0
TRANSP offset : 0
length : 0
msb_right : 0
nonstd : 0
activate : 0
height : 240
width : 320
accel_flags : 0
pixclock : 0
left margin : 0
right margin : 0
upper margin : 0
lower margin : 0
hsync length : 0
vsync length : 0
sync : 0
vmode : 0
Frame buffer is mapped from 0x40000000
Length of Frame buffer : 153600
ターミナルからフレームバッファを直接操作するプログラムを実行して 画面が上書きされて、表示がおかしくなってもホームキーを押した後、ターミナルに戻れば 画面は元に戻ります。 タスクバーが消えるような最悪の場合でもホームキーを押して設定画面に移動して、 「画面デザイン設定」からテーマを再設定するだけです。
グラフィックライブラリに頼らずに自力でグラフィックを描くのも楽しいものです。 コンピュータの世界では「車輪の再発明」といって、すでに存在するプログラム (今回はグラフィックライブラリ)を自分で作ることをバカにする意見もありますが、 「車輪の発明」の過程をたどって見ることも必要です。数学の試験は「車輪の再発明」 ばかりですよね。