Calvin's Tech Space

成于坚忍,毁于浮躁

   :: 首页 :: 联系 :: 聚合  :: 管理

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);
}

编译后执行一下,看看当前内核是否支持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;
}

从输出结果来看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;
                }
}

编译后,运行看一下结果,尽量在字符模式下运行
vi /etc/inittab将运行级别改为3
重启后,运行一下看看结果。

参考链接:
http://www.blogjava.net/lihao336/admin/EditPosts.aspx?postid=345547
posted on 2011-03-03 00:26 calvin 阅读(4116) 评论(0)  编辑  收藏 所属分类: Linux