[转]基于FrameBuffer的直接写屏
1.将FrameBuffer配置成800x600x16色的显示模式
在/boot/grub/menu.lst中的kernel加入vga=0x314
//test.c
#include
<
stdio.h
>
#include < unistd.h >
#include < sys / types.h >
#include < sys / stat.h >
#include < fcntl.h >
int main( int argc, char ** argv){
int fb_fd = 0 ;
char * fbdev = " /dev/fb0 " ;
if ((fd_fd = open(fbdev,O_RDWR)) < 0 ){
printf( " open FrameBuffer device failed. " n " );
return - 1 ;
}
printf( " open FrameBuffer device successfully! " n " );
close(fb_fd);
}
#include < unistd.h >
#include < sys / types.h >
#include < sys / stat.h >
#include < fcntl.h >
int main( int argc, char ** argv){
int fb_fd = 0 ;
char * fbdev = " /dev/fb0 " ;
if ((fd_fd = open(fbdev,O_RDWR)) < 0 ){
printf( " open FrameBuffer device failed. " n " );
return - 1 ;
}
printf( " open FrameBuffer device successfully! " n " );
close(fb_fd);
}
编译后执行一下,看看当前内核是否支持FrameBuffer机制.
设备打开成功后要获取相当的参数,使用ioctl,会填充以下结构体,
在linux/fb.h中定义的
struct fb_fix_screeninfo
struct fb_var_screeninfo
struct fb_cmap
从fs.h中可看出
#define FBIOGET_VSCREENINFO 0x4600
#define FBIOGET_FSCREENINFO 0x4602
我们就用这两条命令获取相当的参数信息
//test.c
#include
<
stdio.h
>
#include < unistd.h >
#include < sys / types.h >
#include < sys / stat.h >
#include < fcntl.h >
#include < linux / fb.h >
int main( int argc, char ** argv){
int fb_fd = 0 ;
char * env = " /dev/fb0 " ;
struct fb_fix_screeninfo fb_fixinfo;
struct fb_var_screeninfo fb_varinfo;
if ((fb_fd = open(env,O_RDWR)) < 0 ){
printf( " Error:open FrameBuffer device:%s " n " ,env);
return - 1 ;
} else {
printf( " OK:open FrameBuffer device:%s " n " ,env);
}
if (ioctl(fb_fd,FBIOGET_FSCREENINFO, & fb_fixinfo) ==- 1 ){
printf( " Error:FBIOGET_FSCREENINFO " n " );
goto fail;
}
printf( " ioctl FBIOGET_FSCREENINFO ok " n " );
printf( " id=%s " n " ,fb_fixinfo.id);
printf( " smem_start=%#x " n " ,fb_fixinfo.smem_start);
printf( " mem_len=%d " n " ,fb_fixinfo.smem_len);
printf( " type=%d " n " ,fb_fixinfo.type);
printf( " type_aux=%d " n " ,fb_fixinfo.type_aux);
printf( " visual=%d " n " ,fb_fixinfo.visual);
printf( " xpanstep=%d " n " ,fb_fixinfo.xpanstep);
printf( " ypanstep=%d " n " ,fb_fixinfo.ypanstep);
printf( " ywrapstep=%d " n " ,fb_fixinfo.ywrapstep);
printf( " line_length=%d " n " ,fb_fixinfo.line_length);
printf( " mmio_start=%#x " n " ,fb_fixinfo.mmio_start);
printf( " mmio_len=%#x " n " ,fb_fixinfo.mmio_len);
printf( " accel=%d " n " ,fb_fixinfo.accel);
printf( " reserved[0]=%d " n " ,fb_fixinfo.reserved[0]);
printf( " reserved[1]=%d " n " ,fb_fixinfo.reserved[1]);
printf( " reserved[2]=%d " n " ,fb_fixinfo.reserved[2]);
if (ioctl(fb_fd,FBIOGET_VSCREENINFO, & fb_varinfo) ==- 1 ){
printf( " Error:ioctl:FBIOGET_VSCREENINFO " n " );
goto fail;
}
printf( " ioctl FBIOGET_VSCREENINFO ok " n " );
printf( " xres=%d " n " ,fb_varinfo.xres);
printf( " yres=%d " n " ,fb_varinfo.yres);
printf( " xres_virtual=%d " n " ,fb_varinfo.xres_virtual);
printf( " yres_virtual=%d " n " ,fb_varinfo.yres_virtual);
printf( " xoffset=%d " n " ,fb_varinfo.xoffset);
printf( " yoffset=%d " n " ,fb_varinfo.yoffset);
printf( " bits_per_pixel=%d " n " ,fb_varinfo.bits_per_pixel);
printf( " grayscale=%d " n " ,fb_varinfo.grayscale);
printf( " red=%#x " n " ,fb_varinfo.red);
printf( " green=%#x " n " ,fb_varinfo.green);
printf( " blue=%#x " n " ,fb_varinfo.blue);
printf( " transp=%d " n " ,fb_varinfo.transp);
printf( " nonstd=%d " n " ,fb_varinfo.nonstd);
printf( " activate=%d " n " ,fb_varinfo.activate);
printf( " height=%d " n " ,fb_varinfo.height);
printf( " width=%d " n " ,fb_varinfo.width);
printf( " accel_flags=%d " n " ,fb_varinfo.accel_flags);
printf( " pixclock=%d " n " ,fb_varinfo.pixclock);
printf( " left_margin=%d " n " ,fb_varinfo.left_margin);
printf( " right_margin=%d " n " ,fb_varinfo.right_margin);
printf( " upper_margin=%d " n " ,fb_varinfo.upper_margin);
printf( " lower_margin=%d " n " ,fb_varinfo.lower_margin);
printf( " hsync_len=%d " n " ,fb_varinfo.hsync_len);
printf( " vsync_len=%d " n " ,fb_varinfo.vsync_len);
printf( " sync=%d " n " ,fb_varinfo.sync);
printf( " vmode=%d " n " ,fb_varinfo.vmode);
printf( " rotate=%d " n " ,fb_varinfo.rotate);
printf( " reserved[0]=%d " n " ,fb_varinfo.reserved[0]);
printf( " reserved[1]=%d " n " ,fb_varinfo.reserved[1]);
printf( " reserved[2]=%d " n " ,fb_varinfo.reserved[2]);
printf( " reserved[3]=%d " n " ,fb_varinfo.reserved[3]);
printf( " reserved[4]=%d " n " ,fb_varinfo.reserved[4]);
close(fb_fd);
return 0 ;
fail:
close(fb_fd);
return - 1 ;
}
#include < unistd.h >
#include < sys / types.h >
#include < sys / stat.h >
#include < fcntl.h >
#include < linux / fb.h >
int main( int argc, char ** argv){
int fb_fd = 0 ;
char * env = " /dev/fb0 " ;
struct fb_fix_screeninfo fb_fixinfo;
struct fb_var_screeninfo fb_varinfo;
if ((fb_fd = open(env,O_RDWR)) < 0 ){
printf( " Error:open FrameBuffer device:%s " n " ,env);
return - 1 ;
} else {
printf( " OK:open FrameBuffer device:%s " n " ,env);
}
if (ioctl(fb_fd,FBIOGET_FSCREENINFO, & fb_fixinfo) ==- 1 ){
printf( " Error:FBIOGET_FSCREENINFO " n " );
goto fail;
}
printf( " ioctl FBIOGET_FSCREENINFO ok " n " );
printf( " id=%s " n " ,fb_fixinfo.id);
printf( " smem_start=%#x " n " ,fb_fixinfo.smem_start);
printf( " mem_len=%d " n " ,fb_fixinfo.smem_len);
printf( " type=%d " n " ,fb_fixinfo.type);
printf( " type_aux=%d " n " ,fb_fixinfo.type_aux);
printf( " visual=%d " n " ,fb_fixinfo.visual);
printf( " xpanstep=%d " n " ,fb_fixinfo.xpanstep);
printf( " ypanstep=%d " n " ,fb_fixinfo.ypanstep);
printf( " ywrapstep=%d " n " ,fb_fixinfo.ywrapstep);
printf( " line_length=%d " n " ,fb_fixinfo.line_length);
printf( " mmio_start=%#x " n " ,fb_fixinfo.mmio_start);
printf( " mmio_len=%#x " n " ,fb_fixinfo.mmio_len);
printf( " accel=%d " n " ,fb_fixinfo.accel);
printf( " reserved[0]=%d " n " ,fb_fixinfo.reserved[0]);
printf( " reserved[1]=%d " n " ,fb_fixinfo.reserved[1]);
printf( " reserved[2]=%d " n " ,fb_fixinfo.reserved[2]);
if (ioctl(fb_fd,FBIOGET_VSCREENINFO, & fb_varinfo) ==- 1 ){
printf( " Error:ioctl:FBIOGET_VSCREENINFO " n " );
goto fail;
}
printf( " ioctl FBIOGET_VSCREENINFO ok " n " );
printf( " xres=%d " n " ,fb_varinfo.xres);
printf( " yres=%d " n " ,fb_varinfo.yres);
printf( " xres_virtual=%d " n " ,fb_varinfo.xres_virtual);
printf( " yres_virtual=%d " n " ,fb_varinfo.yres_virtual);
printf( " xoffset=%d " n " ,fb_varinfo.xoffset);
printf( " yoffset=%d " n " ,fb_varinfo.yoffset);
printf( " bits_per_pixel=%d " n " ,fb_varinfo.bits_per_pixel);
printf( " grayscale=%d " n " ,fb_varinfo.grayscale);
printf( " red=%#x " n " ,fb_varinfo.red);
printf( " green=%#x " n " ,fb_varinfo.green);
printf( " blue=%#x " n " ,fb_varinfo.blue);
printf( " transp=%d " n " ,fb_varinfo.transp);
printf( " nonstd=%d " n " ,fb_varinfo.nonstd);
printf( " activate=%d " n " ,fb_varinfo.activate);
printf( " height=%d " n " ,fb_varinfo.height);
printf( " width=%d " n " ,fb_varinfo.width);
printf( " accel_flags=%d " n " ,fb_varinfo.accel_flags);
printf( " pixclock=%d " n " ,fb_varinfo.pixclock);
printf( " left_margin=%d " n " ,fb_varinfo.left_margin);
printf( " right_margin=%d " n " ,fb_varinfo.right_margin);
printf( " upper_margin=%d " n " ,fb_varinfo.upper_margin);
printf( " lower_margin=%d " n " ,fb_varinfo.lower_margin);
printf( " hsync_len=%d " n " ,fb_varinfo.hsync_len);
printf( " vsync_len=%d " n " ,fb_varinfo.vsync_len);
printf( " sync=%d " n " ,fb_varinfo.sync);
printf( " vmode=%d " n " ,fb_varinfo.vmode);
printf( " rotate=%d " n " ,fb_varinfo.rotate);
printf( " reserved[0]=%d " n " ,fb_varinfo.reserved[0]);
printf( " reserved[1]=%d " n " ,fb_varinfo.reserved[1]);
printf( " reserved[2]=%d " n " ,fb_varinfo.reserved[2]);
printf( " reserved[3]=%d " n " ,fb_varinfo.reserved[3]);
printf( " reserved[4]=%d " n " ,fb_varinfo.reserved[4]);
close(fb_fd);
return 0 ;
fail:
close(fb_fd);
return - 1 ;
}
从输出结果来看xres=800,yres=600,从这里可以看出这个FrameBuffer的最大值为800x600
得到framebuffer的信息后,我们开辟一段内存,然后映射framebuffer的内存,
这样当向这段内存写入信息时,framebuffer中就会写入相同的数据,也就会有数据表示的图像显示在屏幕上。
例:在屏幕上显示一个渐变窗体
#include
<
stdio.h
>
#include < unistd.h >
#include < sys / types.h >
#include < sys / stat.h >
#include < fcntl.h >
#include < linux / fb.h >
#include < errno.h >
#include < sys / mman.h >
#include < stdlib.h >
#include < string .h >
#include < sys / ioctl.h >
int flush_screen( char * buf, char * framebuf, int width, int height);
int main( int argc, char * argv[])
{
int fb_fd = 0 ;
struct fb_fix_screeninfo fb_fixinfo;
struct fb_var_screeninfo fb_varinfo;
char * fb_addr;
unsigned long fb_size;
char * buffer;
int i = 0 ;
if ((fb_fd = open( " /dev/fb0 " , O_RDWR)) < 0 ){
printf( " open framebuffer device failed. " n " );
return - 1 ;
}
printf( " open framebuffer device ok " n " );
if (ioctl(fb_fd, FBIOGET_FSCREENINFO, & fb_fixinfo) == - 1 )
{
printf( " ioctl FBIOGET_FSCREENINFO failed. " n " );
return - 1 ;
}
printf( " ioctl FBIOGET_FSCREENINFO ok " n " );
if (ioctl(fb_fd, FBIOGET_VSCREENINFO, & fb_varinfo) == - 1 )
{
printf( " ioctl FBIOGET_VSCREENINFO failed. " n " );
return - 1 ;
}
printf( " ioctl FBIOGET_VSCREENINFO ok " n " );
fb_size = fb_varinfo.yres * fb_fixinfo.line_length; // 整个framebuffer的大小
fb_addr = ( char * )mmap(NULL, fb_size, PROT_READ | PROT_WRITE,MAP_SHARED, fb_fd, 0 ); // 将framebuffer的物理地址映射到进程地址空间
buffer = ( char * )malloc(fb_varinfo.yres * fb_fixinfo.line_length); // 申请一个缓冲区,采用双缓冲方式
for (i = 0 ;i <= 0xff ;i += 0x0f ){
memset(buffer,i,fb_varinfo.yres * fb_fixinfo.line_length);
flush_screen(buffer,fb_addr,fb_varinfo.xres,fb_varinfo.yres);
sleep( 1 );
}
if ( ! fb_addr)
exit( 1 );
free(buffer);
return 0 ;
}
int flush_screen( char * buf, char * framebuf, int width, int height)
{
char * t_data = buf;
char * t_fb_addr = framebuf;
int bytew = width << 1 ;
while ( -- height >= 0 )
{
memcpy(t_fb_addr,t_data,bytew);
t_fb_addr += width;
t_data += width;
}
}
#include < unistd.h >
#include < sys / types.h >
#include < sys / stat.h >
#include < fcntl.h >
#include < linux / fb.h >
#include < errno.h >
#include < sys / mman.h >
#include < stdlib.h >
#include < string .h >
#include < sys / ioctl.h >
int flush_screen( char * buf, char * framebuf, int width, int height);
int main( int argc, char * argv[])
{
int fb_fd = 0 ;
struct fb_fix_screeninfo fb_fixinfo;
struct fb_var_screeninfo fb_varinfo;
char * fb_addr;
unsigned long fb_size;
char * buffer;
int i = 0 ;
if ((fb_fd = open( " /dev/fb0 " , O_RDWR)) < 0 ){
printf( " open framebuffer device failed. " n " );
return - 1 ;
}
printf( " open framebuffer device ok " n " );
if (ioctl(fb_fd, FBIOGET_FSCREENINFO, & fb_fixinfo) == - 1 )
{
printf( " ioctl FBIOGET_FSCREENINFO failed. " n " );
return - 1 ;
}
printf( " ioctl FBIOGET_FSCREENINFO ok " n " );
if (ioctl(fb_fd, FBIOGET_VSCREENINFO, & fb_varinfo) == - 1 )
{
printf( " ioctl FBIOGET_VSCREENINFO failed. " n " );
return - 1 ;
}
printf( " ioctl FBIOGET_VSCREENINFO ok " n " );
fb_size = fb_varinfo.yres * fb_fixinfo.line_length; // 整个framebuffer的大小
fb_addr = ( char * )mmap(NULL, fb_size, PROT_READ | PROT_WRITE,MAP_SHARED, fb_fd, 0 ); // 将framebuffer的物理地址映射到进程地址空间
buffer = ( char * )malloc(fb_varinfo.yres * fb_fixinfo.line_length); // 申请一个缓冲区,采用双缓冲方式
for (i = 0 ;i <= 0xff ;i += 0x0f ){
memset(buffer,i,fb_varinfo.yres * fb_fixinfo.line_length);
flush_screen(buffer,fb_addr,fb_varinfo.xres,fb_varinfo.yres);
sleep( 1 );
}
if ( ! fb_addr)
exit( 1 );
free(buffer);
return 0 ;
}
int flush_screen( char * buf, char * framebuf, int width, int height)
{
char * t_data = buf;
char * t_fb_addr = framebuf;
int bytew = width << 1 ;
while ( -- height >= 0 )
{
memcpy(t_fb_addr,t_data,bytew);
t_fb_addr += width;
t_data += width;
}
}
编译后,运行看一下结果,尽量在字符模式下运行
vi /etc/inittab将运行级别改为3
重启后,运行一下看看结果。
参考链接:
http://www.blogjava.net/lihao336/admin/EditPosts.aspx?postid=345547