framebuffer的两个重要结构体:
struct
fb_fix_screeninfo {
char id[16]; /* identification string eg "TT Builtin" */
unsigned long smem_start; /* Start of frame buffer mem */
/* (physical address) */
__u32 smem_len; /* Length of frame buffer mem */
__u32 type; /* see FB_TYPE_* */
__u32 type_aux; /* Interleave for interleaved Planes */
__u32 visual; /* see FB_VISUAL_* */
__u16 xpanstep; /* zero if no hardware panning */
__u16 ypanstep; /* zero if no hardware panning */
__u16 ywrapstep; /* zero if no hardware ywrap */
__u32 line_length; /* length of a line in bytes */
unsigned long mmio_start; /* Start of Memory Mapped I/O */
/* (physical address) */
__u32 mmio_len; /* Length of Memory Mapped I/O */
__u32 accel; /* Indicate to driver which */
/* specific chip/card we have */
__u16 reserved[3]; /* Reserved for future compatibility */
};
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是
虚拟分辨率,它们定义的是显存分辨率。比如显示屏垂直 分辨率是400,而虚拟分辨率是800。这就意味着在显存中存储着800行显示行,但是每次只能显示400行。但是显示哪400行呢?这就需要另外一个成 员变量yoffset,当yoffset=0时,从显存0行开始显示400行,如果yoffset=30,就从显存31行开始显示400行。实际上这个技 术就是乒乓 buffer 。
我的LCD参数如下:
id manu FB
smem_start -945815552
smem_len 356352
type 0
type_aux 0
visual 3
xpanstep 1
ypanstep 1
line_length 736
mmio_start 0
mmio_len 0
accel 0
xres 720
yres 480
xres_virturl 720
yres_virtual 480
xoffset 0
yoffset 0
bits_per_pixel 8
其中分辨分辨率为720X480,BPP为8,但是其line_length为736。直接在FB绘图的时候要使用line_length计算像素的偏移量,而不是直接使用xres。
另外smem_len不一定等于line_length×yres_virtual。有时smem_len要考虑对齐到页大小(一般4096),所以经常会偏大。
计算像素的偏移量:
location=(x+vinfo.xoffset)*(vinfo.bits_per_pixel/8)+
(y+vinfo.yoffset)*finfo.line_length;
获取/dev/fb0设备信息的函数:
来自 http://blog.chinaunix.net/uid-22666248-id-284148.html
#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>
#include <linux/fb.h>
#include <sys/mman.h>
int main()
{
int fdfd=0;
struct fb_var_screeninfo vinfo;
struct fb_fix_screeninfo finfo;
long int screensize=0;
char *fbp=0;
int x=0,y=0;
long int location=0;
fdfd=open("/dev/fb0",O_RDWR);
printf("the framebuffer device was opended successfully.\n");
ioctl(fdfd,FBIOGET_FSCREENINFO,&finfo); //获取 固定参数
printf("id %s\n",finfo.id);
printf("smem_start %d\n",finfo.smem_start); //帧缓冲 内存开始地址,物理地址
printf("smem_len %d\n",finfo.smem_len); // 帧缓冲 内存 长度
printf("type %d\n",finfo.type);
printf("type_aux %d\n",finfo.type_aux);//平面交织交替
printf("visual %d\n",finfo.visual); //记录 色彩模式
printf("xpanstep %d\n",finfo.xpanstep);//如果没有硬件panning,赋0
printf("ypanstep %d\n",finfo.ypanstep);
printf("line_length %d\n",finfo.line_length);
printf("mmio_start %d\n",finfo.mmio_start);//内存映射IO开始地址 物理地址
printf("mmio_len %d\n",finfo.mmio_len);//内存映射IO 长度
printf("accel %d\n\n",finfo.accel);
ioctl(fdfd,FBIOGET_VSCREENINFO,&vinfo); //获取可变参数
printf("xres %d\n",vinfo.xres); //可见解析度
printf("yres %d\n",vinfo.yres);
printf("xres_virturl %d\n",vinfo.xres_virtual); //虚拟解析度
printf("yres_virtual %d\n",vinfo.yres_virtual);
printf("xoffset %d\n",vinfo.xoffset); //虚拟到可见的偏移
printf("yoffset %d\n",vinfo.yoffset);
printf("bits_per_pixel %d\n",vinfo.bits_per_pixel); //每像素位数 bpp
printf("grayscale %d\n",vinfo.grayscale);//非零时,指灰度
printf("fb_bitfield red.offset %d\n",vinfo.red.offset);
printf("fb_bitfield .length %d\n",vinfo.red.length);
printf("fb_bitfield .msb_right %d\n",vinfo.red.msb_right);
printf("fb_bitfield green.offset %d\n",vinfo.green.offset);
printf("fb_bitfield .length %d\n",vinfo.green.length);
printf("fb_bitfield .msb_right %d\n",vinfo.green.msb_right);
printf("fb_bitfield blue.offset %d\n",vinfo.blue.offset);
printf("fb_bitfield .length %d\n",vinfo.blue.length);
printf("fb_bitfield .msb_right %d\n",vinfo.blue.msb_right);
printf("fb_bitfield transp.offset %d\n",vinfo.transp.offset);
printf("fb_bitfield .length %d\n",vinfo.transp.length);
printf("fb_bitfield .msb_right %d\n",vinfo.transp.msb_right);
printf("nonstd %d\n",vinfo.nonstd); //!=0 非标准像素格式
printf("activate %d\n",vinfo.activate);
printf("height %d\n",vinfo.height); //高度/
printf("widht %d\n",vinfo.width);
printf("accel_flags %d\n",vinfo.accel_flags); //看 fb_info.flags
//定时,除了 pixclock之外,其他的都以像素时钟为单位
printf("pixclock %d\n",vinfo.pixclock);//像素时钟,皮秒
printf("left_margin %d\n",vinfo.left_margin);//行切换:从同步到绘图之间的延迟
printf("right_margin %d\n",vinfo.right_margin);//行切换:从绘图到同步之间的延迟
printf("upper_margin %d\n",vinfo.upper_margin);//帧切换:从同步到绘图之间的延迟
printf("lower_margin %d\n",vinfo.lower_margin);//帧切换:从绘图到同步之间的延迟
printf("hsync_len %d\n",vinfo.hsync_len); //hor 水平同步的长度
printf("vsync_len %d\n",vinfo.vsync_len); //vir 垂直同步的长度
printf("sync %d\n",vinfo.sync); //
printf("vmode %d\n",vinfo.vmode);
printf("rotate %d\n",vinfo.rotate);
screensize=vinfo.xres*vinfo.yres*vinfo.bits_per_pixel/8; //计算一帧图片占了 多少字节
fbp=(char *)mmap(NULL,screensize,PROT_READ|PROT_WRITE,MAP_SHARED,fdfd,0);
printf("the framebuffer devices was mapped to memory successfully\n");
x=100;y=100;
for(y=100;y<200;y++)
for(x=100;x<300;x++)
{
location=(x+vinfo.xoffset)*(vinfo.bits_per_pixel/8)+
(y+vinfo.yoffset)*finfo.line_length;
/*
location=x*2+y*vinfo.xres*2;;
*/
int b=(x-100)/6;
int g=31-(y-100)/16;
int r=10;
unsigned short int t=r<<11|g<<5|b;
*((unsigned short int *)(fbp+location))=t;
}
printf("bye the framebuffer\n");
munmap(fbp,screensize);
close(fdfd);
return 0;
}