Linux framebuffer测试程序
Linux framebuffer的框架非常简单, 对于应用程序就是操作一块内存(俗称帧缓存), 当然也有可能是双缓存, 一般用于高帧率场景, 一块帧在填充数据时, 另一块在显示, 接着对调过来, 那通过设置哪里告知驱动层读取哪块帧数据呢? 答案是用vinfo.xoffset,?vinfo.yoffset 需要注意的是, 无论用write()、还是mmap()后直接操作内存都只是填充内存而已, 并不代表能够立马显示, 这得看驱动, 如果驱动实现了自刷新(不断从帧缓存拿数据刷到LCD上), 那填充数据到帧缓存就会立马显示出来, 如果驱动没有实现,那应用程序需要主动的调用?ioctl(fp,FBIOPAN_DISPLAY,&vinfo);, 告知驱动可以刷数据了, 如果这都没显示出来, 估计驱动没实现FBIOPAN_DISPLAY功能。 示例代码:(驱动实现自刷新, 应用依次显示黄、蓝、红,最后画线) #include <unistd.h> #include <stdio.h> #include <fcntl.h> #include <linux/fb.h> #include <sys/mman.h> #include <stdlib.h> #include <string.h> #define RED 0xF800 #define YELLOW 0xFFE0 #define BLUE 0x001F #define WHITE 0xFFFF #define BLACK 0x0000 void fill_color16(short *fb_addr,short bit_map,int psize) { int i; for(i=0; i<psize; i++) { *fb_addr = bit_map; fb_addr++; } } int main () { int fp=0; struct fb_var_screeninfo vinfo; struct fb_fix_screeninfo finfo; long screensize=0; char *fbp = NULL,*test_fbp=NULL; int x = 0,y = 0; long location = 0; int i; int num = 5; int pix_size=0; fp = open("/dev/graphics/fb0",O_RDWR); if(fp < 0) { printf("Error : Can not open framebuffer device/n"); exit(1); } if(ioctl(fp,FBIOGET_FSCREENINFO,&finfo)){ printf("Error reading fixed information/n"); exit(2); } if(ioctl(fp,FBIOGET_VSCREENINFO,&vinfo)){ printf("Error reading variable information/n"); exit(3); } screensize = vinfo.xres * vinfo.yres * vinfo.bits_per_pixel / 8; printf("The phy mem = 0x%x,total size = %d(byte)n",finfo.smem_start,finfo.smem_len); printf("xres = %d,yres = %d,bits_per_pixel = %dn",vinfo.xres,vinfo.yres,vinfo.bits_per_pixel); printf("So the screensize = %d(byte),using %d framen",screensize,finfo.smem_len/screensize); printf("vinfo.xoffset = %d,vinfo.yoffset = %dn",vinfo.xoffset,vinfo.yoffset); printf("vinfo.vmode is :%dn",vinfo.vmode); printf("finfo.ypanstep is :%dn",finfo.ypanstep); printf("vinfo.red.offset=0x%xn",vinfo.red.offset); printf("vinfo.red.length=0x%xn",vinfo.red.length); printf("vinfo.green.offset=0x%xn",vinfo.green.offset); printf("vinfo.green.length=0x%xn",vinfo.green.length); printf("vinfo.blue.offset=0x%xn",vinfo.blue.offset); printf("vinfo.blue.length=0x%xn",vinfo.blue.length); printf("vinfo.transp.offset=0x%xn",vinfo.transp.offset); printf("vinfo.transp.length=0x%xn",vinfo.transp.length); fbp =(char *)mmap(0,PROT_READ | PROT_WRITE,MAP_SHARED,fp,0); if ((int)fbp == -1) { printf ("Error: failed to map framebuffer device to memory./n"); exit (4); } printf("Get virt mem = %pn",fbp); pix_size = vinfo.xres * vinfo.yres; /* using first frame,for FBIOPAN_DISPLAY * 当刷新需要调用FBIOPAN_DISPLAY, 要告知驱动刷哪块帧, 用到下面两个参数 * 如果使用第二帧buffer -> vinfo.xoffset = 0; vinfo.yoffset = vinfo.yres; */ vinfo.xoffset = 0; vinfo.yoffset = 0; /* show color loop */ while(num--) { printf("ndrawing YELLOW......n"); fill_color16((short *)fbp,YELLOW,pix_size); //ioctl(fp,&vinfo); sleep(3); printf("ndrawing BLUE......n"); fill_color16((short *)fbp,BLUE,&vinfo); sleep(3); printf("ndrawing RED......n"); fill_color16((short *)fbp,RED,&vinfo); sleep(3); } #if 1 /*这是你想画的点的位置坐标,(0,0)点在屏幕左上角*/ x = 10; y = 10; location = x * (vinfo.bits_per_pixel / 8) + y * finfo.line_length; test_fbp = fbp + location; printf("draw line.......n"); for(i = 0; i < (vinfo.xres - x); i++) *test_fbp++ = i+30; //ioctl(fp,&vinfo); #endif munmap(fbp,screensize); /*解除映射*/ close (fp); return 0; } ? 当然用read()/write(), 也可以, 就是效率非常低, 太多系统调用导致系统在用户态和kernel态切换, 而且每次还传输一个字节, 但作为例子可以参考一下: #include <unistd.h> #include <stdio.h> #include <fcntl.h> #include <linux/fb.h> #include <sys/mman.h> #include <stdlib.h> #include <string.h> #define RED 0xF800 #define YELLOW 0xFFE0 #define BLUE 0x001F #define WHITE 0xFFFF #define BLACK 0x0000 int main () { int fp=0; struct fb_var_screeninfo vinfo; int i; int pix_size=0; unsigned char color1,color2; fp = open("/dev/graphics/fb0",&vinfo)){ printf("Error reading variable information/n"); exit(3); } pix_size = vinfo.xres * vinfo.yres; color1 = 0; color2 = 0xf8; for(i=0; i<pix_size; i++) { write(fp,&color1,1); write(fp,&color2,1); } close (fp); return 0; } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |