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
ターミナルからフレームバッファを直接操作するプログラムを実行して 画面が上書きされて、表示がおかしくなってもホームキーを押した後、ターミナルに戻れば 画面は元に戻ります。 タスクバーが消えるような最悪の場合でもホームキーを押して設定画面に移動して、 「画面デザイン設定」からテーマを再設定するだけです。
グラフィックライブラリに頼らずに自力でグラフィックを描くのも楽しいものです。 コンピュータの世界では「車輪の再発明」といって、すでに存在するプログラム (今回はグラフィックライブラリ)を自分で作ることをバカにする意見もありますが、 「車輪の発明」の過程をたどって見ることも必要です。数学の試験は「車輪の再発明」 ばかりですよね。