Frame Buffer的本意帧缓冲。它是指显示设备里的显存。显存里保存是像素的RGB数据。一个显存的大小,屏幕宽度*屏幕高度*每像素字节数。
软件修改显存的像素值,就形成各种显示效果.再由硬件将显存数据送到显示模块输出。显存一般是由SDRAM一段连续的空间来充当。
Linux一般都把FB设备当成显示设备标准接口。它的设备结点 /dev/fbn表示。比如第一个FB设备是/dev/fb0.应用程序通过一组标准IOCTL来操作FB驱动。
fbset就是查询FB驱动的一命 其中最关健是红色那行,分别表示 实际的输出宽度,高度,虚拟输出宽度,高度.和bpp
在描述LCD的物理长度,是指一种对角线物理长度 比如4.3"屏就是对角线为4.3英寸长,这个尺寸与结构设计有关.而与软件编程相关几个参数主要是屏幕分辩率和色深.
屏幕分辩率是指每行和第列的像素数的描述。比如480*272.表示每行分布着480点,每列分布着272点.分辩率越高越意味显示越清
每一个像素的颜色是用三原色的分量来表示,即R(red) G (Green) B (blue) 另外一个与软件高度相关是bpp, (bits per pixel),表RGB的bits数。嵌入式LINUX常用 16bpp,18bpp,24bpp. bpp值越大,能表示颜色越丰富.但是占用空间越多.单色的bpp就是1.
一个点占的字节数移为(BPP) bytes per pixel,BPP与bpp的对应换算并不是一个简单除8的关系,要根据硬件换算。一般是16bpp占用2byte,18,24,32均是4个字节.
bpp还一个说法是,色深(Color Deepth)
在lcd的datasheet还是另外一个描述方法,即一个点的最大颜色数,相于是2的bpp次方.因此颜色数是可以直接换算bpp的
- 8bpp的颜色数256
- 16bpp的颜色数 65,536
- 18bpp的颜色数262,144
- 24bpp的颜色数是 16.1m
FB的基本操作
每个fb驱动实际是一个字符设备结点,其主设备号固定为
1。打开FB设备
open("/dev/fb0",O_RDWR,0)
2.控制功能用
3.显存控制
显存是LINUX内核一个空间。应用程序对显存操作是用mmap后来操作
4.关闭设备close()
取得屏幕信息
ioctl(fd, FBIOGET_VSCREENINFO,&var);
取得屏幕信息,数据存放在var中,它是定义在linux/fb.h中struct fb_var_screeninfo当中
struct fb_var_screeninfo { __u32 xres; /* visible resolution */ __u32 yres; __u32 xres_virtual; /* virtual resolution */ __u32 yres_virtual; __u32 xoffset; /* offset from virtual to visible */ __u32 yoffset; /* resolution */ __u32 bits_per_pixel; /* guess what */ __u32 grayscale; /* != 0 Graylevels instead of colors */ 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 */ __u32 nonstd; /* != 0 Non standard pixel format */ __u32 activate; /* see FB_ACTIVATE_* */ __u32 height; /* height of picture in mm */ __u32 width; /* width of picture in mm */ __u32 accel_flags; /* (OBSOLETE) see fb_info.flags */ /* Timing: All values in pixclocks, except pixclock (of course) */ __u32 pixclock; /* pixel clock in ps (pico seconds) */ __u32 left_margin; /* time from sync to picture */ __u32 right_margin; /* time from picture to sync */ __u32 upper_margin; /* time from sync to picture */ __u32 lower_margin; __u32 hsync_len; /* length of horizontal sync */ __u32 vsync_len; /* length of vertical sync */ __u32 sync; /* see FB_SYNC_* */ __u32 vmode; /* see FB_VMODE_* */ __u32 rotate; /* angle we rotate counter clockwise */ __u32 reserved[5]; /* Reserved for future compatibility */ };
|
xres /yres 是实际屏幕的分辩率.
xres_virtual/yres_virtual是虚拟屏幕的尺寸
xoffset/yoffset是实际屏幕输出虚拟屏幕.
bits_per_pixel 就是BPP
这一些信息就是
设置屏幕信息
在调整的屏幕信息的作用中,主要切换bpp, 缺省的bpp是由内核配置的.但是在运行中可以切换成不同的bpp.比如一般的s3c6410可以在16bpp/18bpp/24bpp切换.但是每次的切换时只在当前打开的fd有效,关闭后又会变成缺省的bpp.
切换bpp只需要把bits_per_pixel 设为相应的值.
Ioctl(fd, FBIOSET_VSCREENINFO,&var);
var一般是FBIOGET_VSCREENINFO取得缺省值,然后再在其上修改.
在实测时,发现s3c6410的LCD驱动有BUG,即在切换成18bpp时,相应的RGB排列值并未调整,仍然是上一次BPP的排列.这样造成BUG.
解决办法是一是调整LCD驱动,二是在应用程序切换成18bpp时,同时切换成RGB排列.即用如下代码
if(ioctl(fd,FBIOGET_VSCREENINFO,&var)==-1) { printf("get screen information failure\n"); return -2; } if(bpp == 18) { var.red.length = 6; var.red.offset = 12; var.red.msb_right = 0; var.green.length = 6; var.green.offset = 6; var.green.msb_right = 0; var.blue.length = 6; var.blue.offset = 0; var.blue.msb_right = 0; } var.bits_per_pixel = bpp; if(ioctl(fd,FBIOPUT_VSCREENINFO,&var)==-1) { printf("put screen2 information failure\n"); return -2; } |
下面是 <stdarg.h> 里面重要的几个宏定义如下:
typedef char* va_list;
void va_start ( va_list ap, prev_param ); /* ANSI version */
type va_arg ( va_list ap, type );
void va_end ( va_list ap );
va_list 是一个字符指针,可以理解为指向当前参数的一个指针,取参必须通过这个指针进行。
<Step 1> 在调用参数表之前,定义一个 va_list 类型的变量,(假设va_list 类型变量被定义为ap);
<Step 2> 然后应该对ap 进行初始化,让它指向可变参数表里面的第一个参数,这是通过 va_start 来实现的,第一个参数是 ap 本身,第二个参数是在变参表前面紧挨着的一个变量,即“...”之前的那个参数;
<Step 3> 然后是获取参数,调用va_arg,它的第一个参数是ap,第二个参数是要获取的参数的指定类型,然后返回这个指定类型的值,并且把 ap 的位置指向变参表的下一个变量位置;
<Step 4> 获取所有的参数之后,我们有必要将这个 ap 指针关掉,以免发生危险,方法是调用 va_end,他是输入的参数 ap 置为 NULL,应该养成获取完参数表之后关闭指针的习惯。说白了,就是让我们的程序具有健壮性。通常va_start和va_end是成对出现。