2009年3月11日星期三

Linux下Framebuffer学习


作者:Sam(甄峰) sam_code@hotmail.com


Sam之前写过vfb(虚拟framebuffer) driver. 但现在什么都不记得了。 现在需要在X5平台上使用framebuufer. 只好再学习一次。



零:Framebuffer 简介:

Frame Buffer设备为图形硬件提供抽象。它表示一些视频硬件的Frame Buffer,允许应用软件通过定义好的接口访问图形硬件,所以这些软件不必知道任何关于低层(硬件寄存器)的知识。


使用frame buffer设备的应用程序(例如 X server)默认使用/dev/fb0(老一点的软件使用 /dev/fb0current)。你可以通过设定环境变量$FRAMEBUFFER等于frame buffer设备的路径名来改变frame buffer设备,例如(针对 sh/bash用户):export FRAMEBUFFER=/dev/fb1或者(针对 csh 用户):setenv FRAMEBUFFER /dev/fb1之后,X server将使用第二个frame buffer。


大家都已经知道,frame buffer设备是一个内存设备,就像/dev/mem, 所以他拥有相同的特征。你可以读他,写他,在他里面定位和mmap他(主要用途)。


/dev/fb*也允许在他之上做一些ioctls操作,通过这种方法硬件的许多信息可以获取和设置。颜色映射处理(the color map handling)也通过ioctls工作。


- 你可以取得硬件的不可更改信息,例如名字,屏幕内存组织方式(位面,象素格式,……)和地址和屏幕内存的长度。

- 你可以获取和修改硬件的可变信息,例如可见,虚拟几何,深度,颜色映射格式,定时,等等。如果你试图修改这些信息,驱动可能规整一些值以适应硬件的能力(或者返回EINVAL 如果这个操作不可能) (译注:the driver maybe will round up some values to meet the hardware's capabilities)

- 你可以取得和设置部分颜色映射。通信使用16位每一颜色(红,绿,蓝,透明)来支持所有存在的硬件。驱动处理所有应用于硬件的计算(截取他们到较少的位,可能会舍弃透明)。



视频模式计时:(非常重要)

显示器使用电子束(彩色模式使用3个电子束,单色模式使用1个电子束)绘制屏幕上的图像。屏幕的前面被颜色荧光(象素)覆盖.如果荧光被电子击中,它就会发出光子从而可见.


电子束从左至右绘制水平行,从上到下绘制整个屏幕.通过改变电子束的亮度,便可以显示各种颜色和亮度的像素


每条扫描线完成后电子束必须重新移回到下一行的左端:这称做水平回扫.等到完成整个屏幕(帧)的绘制,电子束会移回到左上方点:这被称做垂直回扫.在水平和垂直回扫期间,电子束被关闭(空).


电子束绘制像素的速度由图形板的时钟决定(译注:dotclock).

例如:时钟是28.37516MHZ(每秒百万周期)。也就是说每秒可以绘制28.37516M像素。

每像素需35242 ps(微秒):1/(28.37516E6 HZ) = 35.242E-9 s


如果屏幕的分辨率是640x480, 将需要640*35.242E-9 s = 22.555E-6 s来绘制一条扫描线上640(xres)个像素.但是水平回扫也需要时间(例如 272 像素), 所以一条完整的水平扫描线需要:(640+272)*35.242E-9 s = 32.141E-6 s

我们称水平刷新率约是31 kHz:1/(32.141E-6 s) = 31.113E3 Hz


整个屏幕有480(yres)条扫描线,但是我们必须还要考虑垂直回扫(例如 49 条扫描线). 所以完整的一屏需要:(480+49)*32.141E-6 s = 17.002E-3 s垂直刷新率约是 59 Hz:1/(17.002E-3 s) = 48.815 Hz这意味着屏幕上的数据每秒钟刷新约59。


从最上面的图可以看出:
水平回扫时间是左边缘(left_margin),右边缘(right_margin)和 hsync 长度(hsync_len)的总和. 而垂直回扫时间是上边缘(upper_margin),下边缘(lower_margin)和 vsync长度(vsync_len)的总和。这些值与fb_var_screeninfo结构体中的项目对应。
frame buffer设备期待所有的水平计时以时钟(以picoseconds, 1E-12 s)为单位,垂直计时则以扫描线数目为单位.
pixclock(以ps为单位的像素时钟)
- pixclock: 以ps为单位的像素时钟(pico seconds)
- left_margin: 从sync到画面的时间
- right_margin: 从画面到sync的时间
- upper_margin: 从sync到画面的时间
-lower_margin: 从画面到sync的时间
- hsync_len: 水平sync的长度
- vsync_len: 垂直sync的长度








一. 基本使用方法:


(之后再补上)





二. 最重要的结构体:


fb_var_screeninfo
简单的项如下:
__u32 xres; /* visible resolution */
__u32 yres; //可见部分的长宽
__u32 xres_virtual; /* virtual resolution */
__u32 yres_virtual; //虚拟部分的长宽
__u32 xoffset; /* offset from virtual to visible */ //可见和虚拟部分的offset
__u32 yoffset; /* resolution */


__u32 bits_per_pixel; //每个象素占多少位
__u32 grayscale; //不等于0的话,灰度


struct fb_bitfield red; /* bitfield in fb mem if true color, */

struct fb_bitfield green; /* else only length is significant */

struct fb_bitfield blue;

struct fb_bitfield transp; /* transparency */

fb_bitfield:结构很重要:

struct fb_bitfield

{

__u32 offset; /* beginning of bitfield */

__u32 length; /* length of bitfield */

__u32 msb_right; /* != 0 : Most significant bit is */

};

像素详解:

以上的结构其实与像素有关,这个结构是说:这种色值(RGB或者transp=alpha)在一个像素点结构中的offset,length

---------------- 一个像素点

R G B a

这样,上面这个结构就明白了吧。

其它机构的含义,请看上面的视频模式部分。呵呵

没有评论: