14. フレームバッファでグラフィックス
Linux カーネルの2.2以降フレームバッファが使えるようになっています. アセンブラでもコンソール上でグラフィックを表示するプログラムが比較的 容易に作成できます.フレームバッファを使うためにはカーネルを再構築する 必要がありますが,こちらのページ を参考にしてカーネルを再構築して下さい.
準備
例によって,カーネルのヘッダファイルをアセンブラで使えるように変換します. まずフレームバッファ用の定数や構造体の定義に関する部分を用意します.
;=========================================================================
; file : fb.inc
; 2001/01/24
; derived from : linux-2.4.0/include/linux/fb.h
;=========================================================================
%ifndef _FB_INC
%define _FB_INC
; Definitions of frame buffers
%assign FB_MAJOR 29
%assign FB_MAX 32 ; sufficient for now
; ioctls
; 0x46 is 'F'
%assign FBIOGET_VSCREENINFO 0x4600
%assign FBIOPUT_VSCREENINFO 0x4601
%assign FBIOGET_FSCREENINFO 0x4602
%assign FBIOGETCMAP 0x4604
%assign FBIOPUTCMAP 0x4605
%assign FBIOPAN_DISPLAY 0x4606
; 0x4607-0x460B are defined below
; %assign FBIOGET_MONITORSPEC 0x460C
; %assign FBIOPUT_MONITORSPEC 0x460D
; %assign FBIOSWITCH_MONIBIT 0x460E
%assign FBIOGET_CON2FBMAP 0x460F
%assign FBIOPUT_CON2FBMAP 0x4610
%assign FBIOBLANK 0x4611 ; arg: 0 or vesa level + 1
;%assign FBIOGET_VBLANK _IOR('F', 0x12, struct fb_vblank)
%assign FBIO_ALLOC 0x4613
%assign FBIO_FREE 0x4614
%assign FBIOGET_GLYPH 0x4615
%assign FBIOGET_HWCINFO 0x4616
%assign FBIOPUT_MODEINFO 0x4617
%assign FBIOGET_DISPINFO 0x4618
%assign FB_TYPE_PACKED_PIXELS 0 ; Packed Pixels
%assign FB_TYPE_PLANES 1 ; Non interleaved planes
%assign FB_TYPE_INTERLEAVED_PLANES 2 ; Interleaved planes
%assign FB_TYPE_TEXT 3 ; Text/attributes
%assign FB_TYPE_VGA_PLANES 4 ; EGA/VGA planes
%assign FB_AUX_TEXT_MDA 0 ; Monochrome text
%assign FB_AUX_TEXT_CGA 1 ; CGA/EGA/VGA Color text
%assign FB_AUX_TEXT_S3_MMIO 2 ; S3 MMIO fasttext
%assign FB_AUX_TEXT_MGA_STEP16 3 ; MGA Millenium I: text,attr,14 rsrvd bytes
%assign FB_AUX_TEXT_MGA_STEP8 4 ; other MGAs: text,attr, 6 rsved bytes
%assign FB_AUX_VGA_PLANES_VGA4 0 ; 16 color planes (EGA/VGA)
%assign FB_AUX_VGA_PLANES_CFB4 1 ; CFB4 in planes (VGA)
%assign FB_AUX_VGA_PLANES_CFB8 2 ; CFB8 in planes (VGA)
%assign FB_VISUAL_MONO01 0 ; Monochr. 1=Black 0=White
%assign FB_VISUAL_MONO10 1 ; Monochr. 1=White 0=Black
%assign FB_VISUAL_TRUECOLOR 2 ; True color
%assign FB_VISUAL_PSEUDOCOLOR 3 ; Pseudo color (like atari)
%assign FB_VISUAL_DIRECTCOLOR 4 ; Direct color
%assign FB_VISUAL_STATIC_PSEUDOCOLOR 5 ; Pseudo color readonly
%assign FB_ACCEL_NONE 0 ; no hardware accelerator
%assign FB_ACCEL_ATARIBLITT 1 ; Atari Blitter
%assign FB_ACCEL_AMIGABLITT 2 ; Amiga Blitter
%assign FB_ACCEL_S3_TRIO64 3 ; Cybervision64 (S3 Trio64)
%assign FB_ACCEL_NCR_77C32BLT 4 ; RetinaZ3 (NCR 77C32BLT)
%assign FB_ACCEL_S3_VIRGE 5 ; Cybervision64/3D (S3 ViRGE)
%assign FB_ACCEL_ATI_MACH64GX 6 ; ATI Mach 64GX family
%assign FB_ACCEL_DEC_TGA 7 ; DEC 21030 TGA
%assign FB_ACCEL_ATI_MACH64CT 8 ; ATI Mach 64CT family
%assign FB_ACCEL_ATI_MACH64VT 9 ; ATI Mach 64CT family VT class
%assign FB_ACCEL_ATI_MACH64GT 10 ; ATI Mach 64CT family GT class
%assign FB_ACCEL_SUN_CREATOR 11 ; Sun Creator/Creator3D
%assign FB_ACCEL_SUN_CGSIX 12 ; Sun cg6
%assign FB_ACCEL_SUN_LEO 13 ; Sun leo/zx
%assign FB_ACCEL_IMS_TWINTURBO 14 ; IMS Twin Turbo
%assign FB_ACCEL_3DLABS_PERMEDIA2 15 ; 3Dlabs Permedia 2
%assign FB_ACCEL_MATROX_MGA2064W 16 ; Matrox MGA2064W (Millenium)
%assign FB_ACCEL_MATROX_MGA1064SG 17 ; Matrox MGA1064SG (Mystique)
%assign FB_ACCEL_MATROX_MGA2164W 18 ; Matrox MGA2164W (Millenium II)
%assign FB_ACCEL_MATROX_MGA2164W_AGP 19 ; Matrox MGA2164W (Millenium II)
%assign FB_ACCEL_MATROX_MGAG100 20 ; Matrox G100 (Productiva G100)
%assign FB_ACCEL_MATROX_MGAG200 21 ; Matrox G200 (Myst, Mill, ...)
%assign FB_ACCEL_SUN_CG14 22 ; Sun cgfourteen
%assign FB_ACCEL_SUN_BWTWO 23 ; Sun bwtwo
%assign FB_ACCEL_SUN_CGTHREE 24 ; Sun cgthree
%assign FB_ACCEL_SUN_TCX 25 ; Sun tcx
%assign FB_ACCEL_MATROX_MGAG400 26 ; Matrox G400
%assign FB_ACCEL_NV3 27 ; nVidia RIVA 128
%assign FB_ACCEL_NV4 28 ; nVidia RIVA TNT
%assign FB_ACCEL_NV5 29 ; nVidia RIVA TNT2
%assign FB_ACCEL_CT_6555x 30 ; C&T 6555x
%assign FB_ACCEL_3DFX_BANSHEE 31 ; 3Dfx Banshee
%assign FB_ACCEL_ATI_RAGE128 32 ; ATI Rage128 family
%assign FB_ACCEL_IGS_CYBER2000 33 ; CyberPro 2000
%assign FB_ACCEL_IGS_CYBER2010 34 ; CyberPro 2010
%assign FB_ACCEL_IGS_CYBER5000 35 ; CyberPro 5000
%assign FB_ACCEL_SIS_GLAMOUR 36 ; SiS 300/630/540
struc fb_fix_screeninfo
.id resb 16 ; identification string eg "TT Builtin"
.smem_start resd 1 ; Start of frame buffer mem
; (physical address)
.smem_len resd 1 ; Length of frame buffer mem
.type resd 1 ; see FB_TYPE_*
.type_aux resd 1 ; Interleave for interleaved Planes
.visual resd 1 ; see FB_VISUAL_*
.xpanstep resw 1 ; zero if no hardware panning
.ypanstep resw 1 ; zero if no hardware panning
.ywrapstep resw 1 ; zero if no hardware ywrap
.padding resw 1 ; for alignment, jm 1/26/2001
.line_length resd 1 ; length of a line in bytes
.mmio_start resd 1 ; Start of Memory Mapped I/O
; (physical address)
.mmio_len resd 1 ; Length of Memory Mapped I/O
.accel resd 1 ; Type of acceleration available
.reserved resw 3 ; Reserved for future compatibility
endstruc
; Interpretation of offset for color fields: All offsets are from the right,
; inside a "pixel" value, which is exactly 'bits_per_pixel' wide (means: you
; can use the offset as right argument to <<). A pixel afterwards is a bit
; stream and is written to video memory as that unmodified. This implies
; big-endian byte order if bits_per_pixel is greater than 8.
struc fb_bitfield
.offset resd 1 ; beginning of bitfield
.length resd 1 ; length of bitfield
.msb_right resd 1 ; != 0 : Most significant bit is
; right
endstruc
%assign FB_NONSTD_HAM 1 ; Hold-And-Modify (HAM)
%assign FB_ACTIVATE_NOW 0 ; set values immediately (or vbl)
%assign FB_ACTIVATE_NXTOPEN 1 ; activate on next open
%assign FB_ACTIVATE_TEST 2 ; don't set, round up impossible
%assign FB_ACTIVATE_MASK 15
; values
%assign FB_ACTIVATE_VBL 16 ; activate values on next vbl
%assign FB_CHANGE_CMAP_VBL 32 ; change colormap on vbl
%assign FB_ACTIVATE_ALL 64 ; change all VCs on this fb
%assign FB_ACCELF_TEXT 1 ; text mode acceleration
%assign FB_SYNC_HOR_HIGH_ACT 1 ; horizontal sync high active
%assign FB_SYNC_VERT_HIGH_ACT 2 ; vertical sync high active
%assign FB_SYNC_EXT 4 ; external sync
%assign FB_SYNC_COMP_HIGH_ACT 8 ; composite sync high active
%assign FB_SYNC_BROADCAST 16 ; broadcast video timings
; vtotal = 144d/288n/576i => PAL
; vtotal = 121d/242n/484i => NTSC
%assign FB_SYNC_ON_GREEN 32 ; sync on green
%assign FB_VMODE_NONINTERLACED 0 ; non interlaced
%assign FB_VMODE_INTERLACED 1 ; interlaced
%assign FB_VMODE_DOUBLE 2 ; double scan
%assign FB_VMODE_MASK 255
%assign FB_VMODE_YWRAP 256 ; ywrap instead of panning
%assign FB_VMODE_SMOOTH_XPAN 512 ; smooth xpan possible (internally used)
%assign FB_VMODE_CONUPDATE 512 ; don't update x/yoffset
struc fb_var_screeninfo
.xres resd 1 ; visible resolution
.yres resd 1
.xres_virtual resd 1 ; virtual resolution
.yres_virtual resd 1
.xoffset resd 1 ; offset from virtual to visible
.yoffset resd 1 ; resolution
.bits_per_pixel resd 1 ; guess what
.grayscale resd 1 ; != 0 Graylevels instead of colors
.red_offset resd 1 ; beginning of bitfield
.red_length resd 1 ; length of bitfield
.red_msb_right resd 1 ; != 0 : Most significant bit is
.green_offset resd 1 ; beginning of bitfield
.green_length resd 1 ; length of bitfield
.green_msb_right resd 1 ; != 0 : Most significant bit is
.blue_offset resd 1 ; beginning of bitfield
.blue_length resd 1 ; length of bitfield
.blue_msb_right resd 1 ; != 0 : Most significant bit is
.transp_offset resd 1 ; beginning of bitfield
.transp_length resd 1 ; length of bitfield
.transp_msb_right resd 1 ; != 0 : Most significant bit is
.nonstd resd 1 ; != 0 Non standard pixel format
.activate resd 1 ; see FB_ACTIVATE_*
.height resd 1 ; height of picture in mm
.width resd 1 ; width of picture in mm
.accel_flags resd 1 ; acceleration flags (hints)
; Timing: All values in pixclocks, except pixclock (of course)
.pixclock resd 1 ; pixel clock in ps (pico seconds)
.left_margin resd 1 ; time from sync to picture
.right_margin resd 1 ; time from picture to sync
.upper_margin resd 1 ; time from sync to picture
.lower_margin resd 1
.hsync_len resd 1 ; length of horizontal sync
.vsync_len resd 1 ; length of vertical sync
.sync resd 1 ; see FB_SYNC_*
.vmode resd 1 ; see FB_VMODE_*
.reserved resd 6 ; Reserved for future compatibility
endstruc
struc fb_cmap
.start resd 1 ; First entry
.len resd 1 ; Number of entries
.red resd 1 ; Red values
.green resd 1
.blue resd 1
.transp resd 1 ; transparency, can be NULL
endstruc
struc fb_con2fbmap
.console resd 1;
.framebuffer resd 1;
endstruc
; VESA Blanking Levels
%assign VESA_NO_BLANKING 0
%assign VESA_VSYNC_SUSPEND 1
%assign VESA_HSYNC_SUSPEND 2
%assign VESA_POWERDOWN 3
struc fb_monspecs
.hfmin resd 1 ; hfreq lower limit (Hz)
.hfmax resd 1 ; hfreq upper limit (Hz)
.vfmin resw 1 ; vfreq lower limit (Hz)
.vfmax resw 1 ; vfreq upper limit (Hz)
.dpms resw 1 ; supports DPMS
endstruc
%assign FB_VBLANK_VBLANKING 0x001 ; currently in a vertical blank
%assign FB_VBLANK_HBLANKING 0x002 ; currently in a horizontal blank
%assign FB_VBLANK_HAVE_VBLANK 0x004 ; vertical blanks can be detected
%assign FB_VBLANK_HAVE_HBLANK 0x008 ; horizontal blanks can be detected
%assign FB_VBLANK_HAVE_COUNT 0x010 ; global retrace counter is available
%assign FB_VBLANK_HAVE_VCOUNT 0x020 ; the vcount field is valid
%assign FB_VBLANK_HAVE_HCOUNT 0x040 ; the hcount field is valid
%assign FB_VBLANK_VSYNCING 0x080 ; currently in a vsync
%assign FB_VBLANK_HAVE_VSYNC 0x100 ; verical syncs can be detected
struc fb_vblank
.flags resd 1 ; FB_VBLANK flags
.count resd 1 ; counter of retraces since boot
.vcount resd 1 ; current scanline position
.hcount resd 1 ; current scandot position
.reserved resd 4 ; reserved for future compatibility
endstruc
%assign FBCMD_GET_CURRENTPAR 0xDEAD0005
%assign FBCMD_SET_CURRENTPAR 0xDEAD8005
; Hardware Cursor
%assign FBIOGET_FCURSORINFO 0x4607
%assign FBIOGET_VCURSORINFO 0x4608
%assign FBIOPUT_VCURSORINFO 0x4609
%assign FBIOGET_CURSORSTATE 0x460A
%assign FBIOPUT_CURSORSTATE 0x460B
struc fb_fix_cursorinfo
.crsr_width resw 1 ; width and height of the cursor in
.crsr_height resw 1 ; pixels (zero if no cursor)
.crsr_xsize resw 1 ; cursor size in display pixels
.crsr_ysize resw 1
.crsr_color1 resw 1 ; colormap entry for cursor color1
.crsr_color2 resw 1 ; colormap entry for cursor color2
endstruc
struc fb_var_cursorinfo
.width resw 1
.height resw 1
.xspot resw 1
.yspot resw 1
.data resb 1 ; field with [height][width]
endstruc
struc fb_cursorstate
.xoffset resw 1
.yoffset resw 1
.mode resw 1
endstruc
%assign FB_CURSOR_OFF 0
%assign FB_CURSOR_ON 1
%assign FB_CURSOR_FLASH 2
%endif
次にフレームバッファをメモリにマッピングする mmap システムコールを使用できるように 次のファイルを準備します
;=========================================================================
; file : mman.inc
; 2001/01/08
; derived from : linux-2.4.0-test12/include/asm-i386/mman.h
;=========================================================================
%ifndef __MMAN_H__
%define __MMAN_H__
%assign PROT_READ 0x1 ; page can be read
%assign PROT_WRITE 0x2 ; page can be written
%assign PROT_EXEC 0x4 ; page can be executed
%assign PROT_NONE 0x0 ; page can not be accessed
%assign MAP_SHARED 0x01 ; Share changes
%assign MAP_PRIVATE 0x02 ; Changes are private
%assign MAP_TYPE 0x0f ; Mask for type of mapping
%assign MAP_FIXED 0x10 ; Interpret addr exactly
%assign MAP_ANONYMOUS 0x20 ; don't use a file
%assign MAP_GROWSDOWN 0x0100 ; stack-like segment
%assign MAP_DENYWRITE 0x0800 ; ETXTBSY
%assign MAP_EXECUTABLE 0x1000 ; mark it as an executable
%assign MAP_LOCKED 0x2000 ; pages are locked
%assign MAP_NORESERVE 0x4000 ; don't check for reservations
%assign MS_ASYNC 1 ; sync memory asynchronously
%assign MS_INVALIDATE 2 ; invalidate the caches
%assign MS_SYNC 4 ; synchronous memory sync
%assign MCL_CURRENT 1 ; lock all current mappings
%assign MCL_FUTURE 2 ; lock all future mappings
%assign MADV_NORMAL 0x0 ; default page-in behavior
%assign MADV_RANDOM 0x1 ; page-in minimum required
%assign MADV_SEQUENTIAL 0x2 ; read-ahead aggressively
%assign MADV_WILLNEED 0x3 ; pre-fault pages
%assign MADV_DONTNEED 0x4 ; discard these pages
; compatibility flags
%assign MAP_ANON MAP_ANONYMOUS
%assign MAP_FILE 0
; from linux/arch/i386/kernel/sys_i386.c
struc mmap_arg_struct
.addr resd 1;
.len resd 1;
.prot resd 1;
.flags resd 1;
.fd resd 1;
.offset resd 1;
endstruc
%endif
フレームバッファ用ライブラリ
フレームバッファを使う上で必要となる決まった操作をサブルーチンとして用意しておきます. フレームバッファのオープン, クローズ,設定の変更と復帰などです.
;-------------------------------------------------------------------------
; file : fblib.inc
; 2001/02/22
; Copyright (C) 2001 Jun Mizutani <mizutani.jun@nifty.ne.jp>
;-------------------------------------------------------------------------
%include "fb.inc"
%include "mman.inc"
%assign O_RDWR 02q
;==============================================================
section .text
;-------------------------------------------------------------------------
; フレームバッファのデバイスファイルをオープン
;-------------------------------------------------------------------------
fbdev_open:
mov eax, SYS_open ; /dev/fb0 のオープン
mov ebx, fb_device
mov ecx, O_RDWR
int 0x80
mov [fb_desc], eax ; /dev/fb0 の fd を保存
mov [mmap_arg.fd], eax
test eax, eax
ret
fb_device db "/dev/fb0", 0
;-------------------------------------------------------------------------
; フレームバッファのデバイスファイルをクローズ
;-------------------------------------------------------------------------
fbdev_close:
mov eax, SYS_close ; /dev/fb0
mov ebx, [fb_desc]
int 0x80
ret
;-------------------------------------------------------------------------
; フレームバッファの物理状態を取得
;-------------------------------------------------------------------------
fb_get_fscreen:
mov eax, SYS_ioctl
mov ebx, [fb_desc]
mov ecx, FBIOGET_FSCREENINFO
mov edx, fscinfo ; 保存先指定
int 0x80
test eax, eax
ret
;-------------------------------------------------------------------------
; 現在のフレームバッファの状態を保存
;-------------------------------------------------------------------------
fb_get_screen:
mov eax, SYS_ioctl
mov ebx, [fb_desc]
mov ecx, FBIOGET_VSCREENINFO
mov edx, scinfo_save ; 保存先指定
int 0x80
test eax, eax
ret
;-------------------------------------------------------------------------
; フレームバッファ設定を書きこむ
;-------------------------------------------------------------------------
fb_set_screen:
mov eax, SYS_ioctl
mov ebx, [fb_desc]
mov ecx, FBIOPUT_VSCREENINFO
mov edx, scinfo_data ; 設定済みデータ
int 0x80
test eax, eax
ret
;-------------------------------------------------------------------------
; 保存済みのフレームバッファ設定を新規設定用にコピー
;-------------------------------------------------------------------------
fb_copy_scinfo:
push esi
push edi
mov esi, scinfo_save ; 保存済みデータ
mov edi, scinfo_data ; 設定用データ
mov ecx, (fb_var_screeninfo_size / 4)
cld
rep movsd
pop edi
pop esi
ret
;-------------------------------------------------------------------------
; フレームバッファメモリをマッピング
;-------------------------------------------------------------------------
fb_map_screen:
mov eax, [scinfo_data.yres_virtual]
mul dword [scinfo_data.xres_virtual]
mov ebx, [scinfo_data.bits_per_pixel]
shr ebx, 3
mul ebx
mov [mmap_arg.len], eax
mov dword[mmap_arg.prot], (PROT_READ | PROT_WRITE)
mov dword[mmap_arg.flags], MAP_SHARED
xor eax, eax
mov [mmap_arg.addr], eax
mov [mmap_arg.offset], eax
mov eax, SYS_mmap
mov ebx, mmap_arg
int 0x80
test eax, eax
ret
;-------------------------------------------------------------------------
; フレームバッファメモリをアンマップ
;-------------------------------------------------------------------------
fb_unmap_screen:
mov eax, SYS_munmap
mov ebx, [mmap_arg.addr]
mov ecx, [mmap_arg.len]
int 0x80
test eax, eax
ret
;-------------------------------------------------------------------------
; カラーマップ(パレット)を取得
;-------------------------------------------------------------------------
fb_get_colormap:
mov eax, SYS_ioctl
mov ebx, [fb_desc]
mov ecx, FBIOGETCMAP
mov edx, colormap_save
int 0x80
test eax, eax
ret
;-------------------------------------------------------------------------
; カラーマップ(パレット)を設定
;-------------------------------------------------------------------------
fb_set_colormap:
mov eax, SYS_ioctl
mov ebx, [fb_desc]
mov ecx, FBIOPUTCMAP
mov edx, colormap_data
int 0x80
ret
;-------------------------------------------------------------------------
; カラーマップ(パレット)を作成
;-------------------------------------------------------------------------
fb_test_colormap:
push edi
xor eax, eax
mov eax, 0xffff
mov edi, red_data
mov ecx, 0x100
.loop:
mov [edi], ax
mov [edi+0x200], ax
mov [edi+0x400], ax
sub eax, 0x01
inc edi
loop .loop
pop edi
ret
;-------------------------------------------------------------------------
; 保存済みのフレームバッファ設定を復帰
;-------------------------------------------------------------------------
fb_restore_sc:
mov eax, SYS_ioctl
mov ebx, [fb_desc]
mov ecx, FBIOPUT_VSCREENINFO
mov edx, scinfo_save
int 0x80
ret
;-------------------------------------------------------------------------
; 保存済みのカラーマップ(パレット)を復帰
;-------------------------------------------------------------------------
fb_restore_cmap:
mov eax, SYS_ioctl
mov ebx, [fb_desc]
mov ecx, FBIOPUTCMAP
mov edx, colormap_save
int 0x80
ret
;==============================================================
section .data
align 4
colormap_save istruc fb_cmap
.start dd 0 ; First entry
.len dd 0x100 ; Number of entries (256)
.red dd red_save
.green dd green_save
.blue dd blue_save
.transp dd 0 ; transparency, can be NULL
iend
colormap_data istruc fb_cmap
.start dd 0 ; First entry
.len dd 0x100 ; Number of entries
.red dd red_data
.green dd green_data
.blue dd blue_data
.transp dd 0 ; transparency, can be NULL
iend
;==============================================================
section .bss
alignb 4
fb_desc: resd 1
fb_address: resd 1
red_save: resw 0x100
green_save: resw 0x100
blue_save: resw 0x100
red_data: resw 0x100
green_data: resw 0x100
blue_data: resw 0x100
mmap_arg istruc mmap_arg_struct
.addr resd 1;
.len resd 1;
.prot resd 1;
.flags resd 1;
.fd resd 1;
.offset resd 1;
iend
alignb 4
scinfo_save: istruc fb_var_screeninfo
.xres resd 1 ; visible resolution
.yres resd 1
.xres_virtual resd 1 ; virtual resolution
.yres_virtual resd 1
.xoffset resd 1 ; offset from virtual to visible
.yoffset resd 1 ; resolution
.bits_per_pixel resd 1 ; guess what
.grayscale resd 1 ; != 0 Graylevels instead of colors
.red_offset resd 1 ; beginning of bitfield
.red_length resd 1 ; length of bitfield
.red_msb_right resd 1 ; != 0 : Most significant bit is
.green_offset resd 1 ; beginning of bitfield
.green_length resd 1 ; length of bitfield
.green_msb_right resd 1 ; != 0 : Most significant bit is
.blue_offset resd 1 ; beginning of bitfield
.blue_length resd 1 ; length of bitfield
.blue_msb_right resd 1 ; != 0 : Most significant bit is
.transp_offset resd 1 ; beginning of bitfield
.transp_length resd 1 ; length of bitfield
.transp_msb_right resd 1 ; != 0 : Most significant bit is
.nonstd resd 1 ; != 0 Non standard pixel format
.activate resd 1 ; see FB_ACTIVATE_*
.height resd 1 ; height of picture in mm
.width resd 1 ; width of picture in mm
.accel_flags resd 1 ; acceleration flags (hints)
.pixclock resd 1 ; pixel clock in ps (pico seconds)
.left_margin resd 1 ; time from sync to picture
.right_margin resd 1 ; time from picture to sync
.upper_margin resd 1 ; time from sync to picture
.lower_margin resd 1
.hsync_len resd 1 ; length of horizontal sync
.vsync_len resd 1 ; length of vertical sync
.sync resd 1 ; see FB_SYNC_*
.vmode resd 1 ; see FB_VMODE_*
.reserved resd 6 ; Reserved for future compatibility
iend
alignb 4
scinfo_data: istruc fb_var_screeninfo
.xres resd 1 ; visible resolution
.yres resd 1
.xres_virtual resd 1 ; virtual resolution
.yres_virtual resd 1
.xoffset resd 1 ; offset from virtual to visible
.yoffset resd 1 ; resolution
.bits_per_pixel resd 1 ; guess what
.grayscale resd 1 ; != 0 Graylevels instead of colors
.red_offset resd 1 ; beginning of bitfield
.red_length resd 1 ; length of bitfield
.red_msb_right resd 1 ; != 0 : Most significant bit is
.green_offset resd 1 ; beginning of bitfield
.green_length resd 1 ; length of bitfield
.green_msb_right resd 1 ; != 0 : Most significant bit is
.blue_offset resd 1 ; beginning of bitfield
.blue_length resd 1 ; length of bitfield
.blue_msb_right resd 1 ; != 0 : Most significant bit is
.transp_offset resd 1 ; beginning of bitfield
.transp_length resd 1 ; length of bitfield
.transp_msb_right resd 1 ; != 0 : Most significant bit is
.nonstd resd 1 ; != 0 Non standard pixel format
.activate resd 1 ; see FB_ACTIVATE_*
.height resd 1 ; height of picture in mm
.width resd 1 ; width of picture in mm
.accel_flags resd 1 ; acceleration flags (hints)
.pixclock resd 1 ; pixel clock in ps (pico seconds)
.left_margin resd 1 ; time from sync to picture
.right_margin resd 1 ; time from picture to sync
.upper_margin resd 1 ; time from sync to picture
.lower_margin resd 1
.hsync_len resd 1 ; length of horizontal sync
.vsync_len resd 1 ; length of vertical sync
.sync resd 1 ; see FB_SYNC_*
.vmode resd 1 ; see FB_VMODE_*
.reserved resd 6 ; Reserved for future compatibility
iend
fscinfo istruc fb_fix_screeninfo
.id resb 16 ; identification string eg "TT Builtin"
.smem_start resd 1 ; Start of frame buffer mem
; (physical address)
.smem_len resd 1 ; Length of frame buffer mem
.type resd 1 ; see FB_TYPE_*
.type_aux resd 1 ; Interleave for interleaved Planes
.visual resd 1 ; see FB_VISUAL_*
.xpanstep resw 1 ; zero if no hardware panning
.ypanstep resw 1 ; zero if no hardware panning
.ywrapstep resw 1 ; zero if no hardware ywrap
.padding resw 1 ; for alignment, jm 1/26/2001
.line_length resd 1 ; length of a line in bytes
.mmio_start resd 1 ; Start of Memory Mapped I/O
; (physical address)
.mmio_len resd 1 ; Length of Memory Mapped I/O
.accel resd 1 ; Type of acceleration available
.reserved resw 3 ; Reserved for future compatibility
iend
各サブルーチンを簡単に解説します.eax, ebx, ecx, edx レジスタは保存されません. 必要ならば呼び出し前に保存してください.edi, esi レジスタは変化しません.
- fbdev_open
- フレームバッファのデバイスファイルをオープン.最初に呼びます.
- fbdev_close
- フレームバッファのデバイスファイルをクローズ.最後に呼びます.
- fb_get_fscreen
- フレームバッファの物理状態を fscinfo に取得します.fscinfo.visual の値で
TrueColor(2),PseudoColor(3)を判断することができます.
mode:317の例
Frame Buffer Physical Screen Information ID string : VESA VGA frame buffer mem start : $D6000000 frame buffer mem length : 4194304 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) : 2048 Memory Mapped I/O start : 0 Memory Mapped I/O length: 0 acceleration type : 0
- fb_get_screen
- 現在のフレームバッファの状態を scinfo_save に取得します.たとえば
scinfo_save.xres でX方向の解像度を知ることができます.これで取得した値を
使うことで異なる画面モードに対応した描画が可能になります.
mode:317の例
Frame Buffer Virtual Screen Information x resolution : 1024 y resolution : 768 x res virtual : 1024 y res virtual : 768 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 : -1 width : -1 accel_flags : 0 pixclock : 12714 left margin : 128 right margin : 32 upper margin : 16 lower margin : 4 hsync length : 128 vsync length : 4 sync : 0 vmode : 0 - fb_copy_scinfo
- 保存済みのフレームバッファ設定scinfo_save を新規設定用に scinfo_data にコピー.
設定を変更する場合にコピーに変更を加え,オリジナルは復帰用に残しておきます.
- fb_set_screen
- フレームバッファ設定 scinfo_data を書き込みます.VESA VGA では解像度などを変更 することはできません.RivaTNTなどのチップにネイティブに対応したフレームバッファの場合は 動的に変更することができます.
- fb_map_screen
- フレームバッファをメモリをマッピングします. マッピングされたメモリの先頭アドレスが
eax に返ります.このアドレスから始まるメモリに値を書き込むと画面に表示されるようになります.
- fb_unmap_screen
- フレームバッファメモリをアンマップ.フレームバッファが不要になったら呼びます.
- fb_get_colormap
- カラーマップ(パレット)を取得.frame buffer visual が 3 (Pseudo color) の時に使用します.
- fb_set_colormap
- カラーマップ(パレット)を設定
Pseudo color (256色モード)の時のみ有効です. - fb_test_colormap
- カラーマップ(パレット)を作成する場合のサンプル.作成したカラーマップはfb_set_colormapで設定します.
- fb_restore_cmap
- fb_get_colormap で保存済みのカラーマップ(パレット)を復帰.カラーマップを変更した
場合には終了時に呼び出して元に戻しておきます.
サンプル
fblib.inc を使って実際に画面に何かを表示してみましょう.画面モードは以下のモードの内で ビデオカードがサポートしているモード (317が無難) で起動して下さい.
| Colours | 640x480 | 800x600 | 1024x768 | 1280x1024 | 1600x1200 |
|---|---|---|---|---|---|
| 15 bits | 310 | 313 | 316 | 319 | 31D |
| 16 bits | 311 | 314 | 317 | 31A | 31E |
;---------------------------------------------------------------------
; Frame buffer
; 2001/02/22 Jun Mizutani
; fbtest.asm
;---------------------------------------------------------------------
%include "stdio.inc"
%include "fblib.inc"
%assign O_RDONLY 00q
;==============================================================
section .text
global _start
_start:
;-------------------------------------------
; フレームバッファの準備
;-------------------------------------------
call fbdev_open ; /dev/fb0 をオープン
js near .fb_Error
call fb_get_screen ; スクリーン情報を取得
js .fb_Error
call fb_copy_scinfo ; scinfo_data を設定
call fb_map_screen ; メモリにマッピング
js .fb_Error
mov [fb_mem], eax ; 先頭アドレス
mov edi, [fb_mem]
mov ebx, [mmap_arg.len] ; サイズ
;-------------------------------------------
; [edi] から [edi+ebx-1] の範囲に書き込み
;-------------------------------------------
call OpenRandom
shr ebx, 1
mov ecx, 10000
.loop: call GetRandom
xor edx, edx
div ebx
mov [edi+edx*2], dx ; ランダムに点を打つ
loop .loop
call CloseRandom
xor esi, esi
mov ecx, ebx
shr ecx, 1
.loop2: mov eax, [edi+esi*4] ; 画面読み出し
xor eax, 0x55555555
mov [edi+esi*4], eax ; 画面書き込み
inc esi
loop .loop2
xor esi, esi
mov ecx, ebx
shr ecx, 1
.loop3: mov eax, [edi+esi*4] ; 画面読み出し
xor eax, 0x55555555
mov [edi+esi*4], eax ; 画面書き込み
inc esi
loop .loop3
;-------------------------------------------
; フレームバッファの後始末
;-------------------------------------------
.exit call fb_unmap_screen
call fbdev_close
call Exit
;-------------------------------------------
.fb_Error:
mov eax, fberr_msg
call OutAsciiZ
jmp short .exit
fberr_msg db 'frabe buffer error!', 10, 0
OpenRandom: pusha
mov ebx, RandomDev
mov ecx, O_RDONLY ; flag
mov eax, SYS_open ; システムコール番号
mov edx, 0644q ; mode
int 0x80
mov [RandomFD], eax
popa
ret
GetRandom: pusha
push eax ; バッファ確保
mov eax, SYS_read ; システムコール番号
mov ebx, [RandomFD]
mov ecx, esp
mov edx, 3 ; 読みこみバイト数
int 0x80
pop eax ; 結果読み出し
mov [esp+28], eax
popa
ret
CloseRandom: push ebx
mov eax, SYS_close
mov ebx, [RandomFD]
int 0x80
pop ebx
ret
RandomDev db '/dev/urandom', 0
;==============================================================
section .bss
fb_mem resd 1
RandomFD resd 1
乱数を /dev/urandom から取得しているため長くなっていますが,フレームバッファ の初期化と終了処理は15行程度のコードです.乱数の読み出しに時間がかかっているため ランダムに点を打つ部分は速くありません.グラフィックスの描画は 先頭アドレス [fb_mem] から大きさ [mmap_arg.len] の範囲のメモリになんらかの値を 書き込みだけです.