大家都知道Unix/Linux系统是由命令驱动的。那么最基本的系统是命令行的(就是想DOS一样的界面)。X-Window-System是Unix/Linux上的图形系统,它是通过X-Server来控制硬件的。但有一些Linux的发行版在引导的时候就会在屏幕上出现图形,这时的图形是不可能由X来完成的,那是什么机制呢?答案是FrameBuffer。
FrameBuffer不是一个图形系统,更不是窗口系统。它比X要低级,简单来说FrameBuffer就是一种机制的实现。这种机制是把屏幕上的每个点映射成一段线性内存空间,程序可以简单的改变这段内存的值来改变屏幕上某一点的颜色。X的高度可移植性就是来自于这种机制,不管是在那种图形环境下,只要有这种机制的实现就可以运行X。所以在几乎所有的平台上都有相应的X版本的移植。
好了,闲话少说,下面我们来看看可以利用FrameBuffer来干点什么。首先看看你是否有了相应的驱动:找一下在/dev/下是否有fb*这个设备文件,这是个字符类的特殊文件。
这些就是我对FrameBuffer的初步研究,匆忙之间写些东西不成文章,以后要写些更高级一点的函数的实现。
sno: 注:qt的嵌入式版qte使用的是framebuffer 也就是使用的是/dev/fb0来读写的。
===========================================另一篇:
zz:http://blog.csdn.net/shenbin1430/article/details/4294399
FrameBuffer 是出现在 2.2.xx 内核当中的一种驱动程序接口。Linux 工作在保护模式下,所以用户态进程是无法象 DOS 那样使用显卡 BIOS 里提供的中断调用来实现直接写屏,Linux 抽象出 FrameBuffer 这个设备来供用户态进程实现直接写屏。Framebuffer 机制模仿显卡的功能,将显卡硬件结构抽象掉,可以通过 Framebuffer 的读写直接对显存进行操作。用户可以将 framebuffer 看成是显示内存的一个映像,将其映射到进程地址空间之后,就可以直接进行读写操作,而写操作可以立即反应在屏幕上。这种操作是抽象的,统一的。用户不必关 心物理显存的位置、换页机制等等具体细节。这些都是由 framebuffer 设备驱动来完成的。
framebuffer 本身不具备任何运算数据的能力,就只好比是一个暂时存放水的水池.CPU 将运算后的结果放到这个水池,水池再将结果流到显示器.中间不会对数据做处理. 应用程序也可以直接读写这个水池的内容.在这种机制下,尽管 framebuffer 需要真正的显卡驱动的支持,但所有显示任务都有 CPU 完成,因此 CPU 负担很重.
帧缓冲驱动应用广泛,在 linux 的桌面系统中,X window 服务器就是利用帧缓 冲进行窗口的绘制。尤其是通过帧缓冲可显示汉字点阵,成为Linux 汉化的唯一可 行方案。
在开发者看来,FrameBuffer 本质上是一块显示缓存,往显示缓存中写入特定格 式的数据就意味着向屏幕输出内容。所以说 FrameBuffer 就是一块白板。例如 对于初始化为 16 位色的 FrameBuffer 来说, FrameBuffer 中的两个字节代表屏幕上一个点,从上到下,从左至右,屏幕位置与内存地址是 顺序的线性关系。
帧缓存可以在系统存储器(内存)的任意位置,视频控制器通过访问帧缓存来刷新 屏幕。 帧缓存也叫刷新缓存 Frame buffer 或 refresh buffer, 这里的帧(frame)是指整个屏幕范围。
帧缓存有个地址,是在内存里。我们通过不停的向 frame buffer 中写入数据, 显示控制器就自动的从 frame buffer 中取数据并显示出来。全部的图形都共享内 存中同一个帧缓存。
CPU 指定显示控制器工作,则显示控制器根据CPU的控制到指定的地方去取数据 和指令, 目前的数据一般是从显存里取, 如果显存里存不下,则从内存里取, 内存也放不下,则从硬盘里取,当然也不是内存放不下,而是为了节省内存的话, 可以放在硬盘里,然后通过 指令控制显示控制器去取。帧缓存 Frame Buffer 里面存储的东西是一帧一帧的, 显卡会不停的刷新 Frame Buffer, 这每一帧如 果不捕获的话, 则会被丢弃,也就是说是实时的。这每一帧不管是保存在内存 还是显存里, 都是一个显性的信息, 这每一帧假设是 800x600 的分辨率, 则保 存的是 800x600 个像素点,和颜色值。
首先确认内核是否支持 framebuffer ,查看 /proc/fb 文件是否存在,存在则 说明支持,否则,说明不支持。其次查看 framebuffer 设备是否已激活,若 /dev/fbx 文件存在,则说明已经 激活;否则说明没有激活。
在系统启动时可通过向 kernel 传送 vga=mode-number 的参数来激活 FrameBuffer 设备,如 vga=0x314,将会启动 800*600*16bpp 模式 要 linux 缺省激活 framebuffer 设备,需要将/etc/grub.conf改成如下形式:
# grub.conf generated by anaconda # # Note that you do not have to rerun grub after making changes to this file # NOTICE: You do not have a /boot partition. This means that # all kernel and initrd paths are relative to /, eg. # root (hd0,0) # kernel /boot/vmlinuz-version ro root=/dev/sda1 # initrd /boot/initrd-version.img #boot=/dev/sda default=0 timeout=10 splashimage=(hd0,0)/boot/grub/splash.xpm.gz title Red Hat Linux (2.4.18-14) root (hd0,0) kernel /boot/vmlinuz-2.4.18-14 ro root=LABEL=/ hdc=ide-scsi vga=0x314 initrd /boot/initrd-2.4.18-14.img
0x314 表示 800*600*16bpp,其它取值见下表:
color | 640x400 | 640x480 | 800x600 | 1024x768 | 1280x1024 | 1600x1200 |
---|---|---|---|---|---|---|
4bits | ? | ? | 0x302 | ? | ? | ? |
8bits | 0x300 | 0x301 | 0x303 | 0x305 | 0x307 | 0x31C |
15bits | ? | 0x310 | 0x313 | 0x316 | 0x319 | 0x31D |
16bits | ? | 0x311 | 0x314 | 0x317 | 0x31A | 0x31E |
24bits | ? | 0x312 | 0x315 | 0x318 | 0x31B | 0x31F |
32bits | ? | ? | ? | ? | ? | ? |
framebuffer 设备启用后,在重启系统时屏幕左上方会显示一个小企鹅。
帧缓冲设备对应的设备文件为/dev/fb*,如果系统有多个显示卡,Linux 下还可 支持多个帧缓冲设备,最多可达 32 个,分别为 /dev/fb0 到 /dev/fb31 ,而 /dev/fb 则为当前缺省的帧缓冲设备,通常指向 /dev/fb0 。当然在嵌入式系统 中支持一个显示设备就够了。帧缓冲设备为标准字符设备,主设备号为 29,次 设备号则从 0 到 31 ,分别对应 /dev/fb0 至 /dev/fb31 。通过 /dev/fb ,应用程序的操作主要有这几种:
在应用程序中,一般通过将 framebuffer 设备映射到进程地址空间的方式使用, 比如下面的程序就打开 /dev/fb0 设备,并通过 mmap 系统调用进行地址映射, 随后用 memset 将屏幕清空(这里假设显示模式是 1024x768-8 位色模式,线性 内存模式):
int fb; unsigned char* fb_mem; fb = open ("/dev/fb0", O_RDWR); fb_mem = mmap (NULL, 1024*768, PROT_READ|PROT_WRITE,MAP_SHARED,fb,0); memset (fb_mem, 0, 1024*768);
framebuffer 设备还提供了若干 ioctl 命令,通过这些命令,可以获得显示设 备的一些固定信息(比如显示内存大小)、与显示模式相关的可变信息(比如分 辨率、象素结构、每扫描线的字节宽度),以及伪彩色模式下的调色板信息等等。
通过 framebuffer 设备,还可以获得当前内核所支持的加速显示卡的类型(通 过固定信息得到),这种类型通常是和特定显示芯片相关的。比如目前最新的内 核(2.4.9)中,就包含有对 S3、Matrox、nVidia、3Dfx 等等流行显示芯片的 加速支持。在获得了加速芯片类型之后,应用程序就可以将 PCI 设备的内存I/O (memio)映射到进程的地址空间。这些 memio 一般是用来控制显示卡的寄存器, 通过对这些寄存器的操作,应用程序就可以控制特定显卡的加速功能。
PCI 设备可以将自己的控制寄存器映射到物理内存空间,而后,对这些控制寄存 器的访问,给变成了对物理内存的访问。因此,这些寄存器又被称为"memio"。 一旦被映射到物理内存,Linux 的普通进程就可以通过 mmap 将这些内存 I/O 映射到进程地址空间,这样就可以直接访问这些寄存器了。
当然,因为不同的显示芯片具有不同的加速能力,对memio 的使用和定义也各自 不同,这时,就需要针对加速芯片的不同类型来编写实现不同的加速功能。比如 大多数芯片都提供了对矩形填充的硬件加速支持,但不同的芯片实现方式不同, 这时,就需要针对不同的芯片类型编写不同的用来完成填充矩形的函数。
framebuffer 只是一个提供显示内存和显示芯片寄存器从物理内存映射到进程地址空间中的设备。所以,对于应用程序而言,如果希望在 framebuffer 之上进行图形编程,还需要自己动手完成其他许多工作。
/dev/fb 是一个文件,因此我们可以用对其读写。
cat /dev/fb0 > screensnap.txt /* read current sreen to a file*/ cat screensnap.txt > /dev/fb0 /* 将 screensnap.txt 的内容贴到屏幕上 */
可以用如下命令清空屏幕:
dd if=/dev/zero of=/dev/fb
如果显示模式是 1024x768-8 位色,用如下命令清空屏幕:
dd if=/dev/zero of=/dev/fb0 bs=1024 count=768
用如下命令可以将fb中的内容保存下来和重新写回屏幕:
dd if=/dev/fb of=fbfile dd if=fbfile of=/dev/fb
fbset是一个可以查看和设置framebuffer的工具。具体使用方法可参看手册。
sno: android 端的fb0在/dev/graphics/fb0中,而不是/dev/fb0,这点要注意。