Linux内核修炼之framebuffer分析

Linux源码包中/document/fb/framebuffer.txt有如下介绍:

The frame buffer device provides an abstraction for the graphics hardware. It represents the frame buffer of some video hardware and allows application software to access the graphics hardware through a well-defined interface, so the software doesn't need to know anything about the low-level (hardware register) stuff.

Frame buffer机制为图形显示卡提供了一个抽象层。可以使得应用程序不用考虑底层硬件的实现细节而通过一些API接口即可访问到显示设备。  但Framebuffer本身不具备任何运算数据的能力,就只好比是一个暂时存放水的水池。水池里的水就是显示的东西。CPU将运算后的结果放到这个水池,水池再将结果流到显示器(通常通过DMA传输). 所以应用程序通过读写这个水池,即可相当于操作了显示卡。系统中可以在/dev/fb*看到framebuffer设备。下面这幅图很好的描述了framebuffer运行机制:


framebuffer子系统的层次结构:



上图主要在下面文件中:

drivers/vedio/fbmem.c   该文件是framebuffer实现的核心,与硬件无关

drivers/vedio/xxxfb.c     该文件主要是framebuffer 设备驱动的实现,如s3c2410fb.c实现了framebuffer设备驱动

fbmem.c是实现framebuffer的核心,与硬件无关。它使用了以下这些数据结构

struct fb_info   *fb_info    该数据结构描述了一个framebuffer device相关一系列信息
struct fb_ops   *fb_ops      该数据结构描述了一个framebuffer device的操作函数集合,类似file_operations,但只供内核使用
static const struct file_operations fb_fops   该数据结构为文件操作函数集合,当应用程序打开设备时,用户可以read,write,ioctl等
struct fb_var_screeninfo var      该数据结构描述了framebuffer device显示特性,是可以更改的
struct fb_fix_screeninfo fix        该数据结构用于保存framebuffer device显示特性,是固定不变的,不可以更改

具体数据结构:

[cpp]  view plain  copy
  1. struct fb_var_screeninfo {  
  2.     __u32 xres;         /* visible resolution       */  
  3.     __u32 yres;  
  4.     __u32 xres_virtual;     /* virtual resolution       */  
  5.     __u32 yres_virtual;  
  6.     __u32 xoffset;          /* offset from virtual to visible */  
  7.     __u32 yoffset;          /* resolution           */  
  8.   
  9.     __u32 bits_per_pixel;       /* guess what           */  
  10.     __u32 grayscale;        /* != 0 Graylevels instead of colors */  
  11.   
  12.     struct fb_bitfield red;     /* bitfield in fb mem if true color, */  
  13.     struct fb_bitfield green;   /* else only length is significant */  
  14.     struct fb_bitfield blue;  
  15.     struct fb_bitfield transp;  /* transparency         */    
  16.   
  17.     __u32 nonstd;           /* != 0 Non standard pixel format */  
  18.   
  19.     __u32 activate;         /* see FB_ACTIVATE_*        */  
  20.   
  21.     __u32 height;           /* height of picture in mm    */  
  22.     __u32 width;            /* width of picture in mm     */  
  23.   
  24.     __u32 accel_flags;      /* (OBSOLETE) see fb_info.flags */  
  25.   
  26.     /* Timing: All values in pixclocks, except pixclock (of course) */  
  27.     __u32 pixclock;         /* pixel clock in ps (pico seconds) */  
  28.     __u32 left_margin;      /* time from sync to picture    */  
  29.     __u32 right_margin;     /* time from picture to sync    */  
  30.     __u32 upper_margin;     /* time from sync to picture    */  
  31.     __u32 lower_margin;  
  32.     __u32 hsync_len;        /* length of horizontal sync    */  
  33.     __u32 vsync_len;        /* length of vertical sync  */  
  34.     __u32 sync;         /* see FB_SYNC_*        */  
  35.     __u32 vmode;            /* see FB_VMODE_*       */  
  36.     __u32 rotate;           /* angle we rotate counter clockwise */  
  37.     __u32 reserved[5];      /* Reserved for future compatibility */  
  38. };  

[cpp]  view plain  copy
  1. struct fb_fix_screeninfo {  
  2.     char id[16];            /* identification string eg "TT Builtin" */  
  3.     unsigned long smem_start;   /* Start of frame buffer mem */  
  4.                     /* (physical address) */  
  5.     __u32 smem_len;         /* Length of frame buffer mem */  
  6.     __u32 type;         /* see FB_TYPE_*        */  
  7.     __u32 type_aux;         /* Interleave for interleaved Planes */  
  8.     __u32 visual;           /* see FB_VISUAL_*      */   
  9.     __u16 xpanstep;         /* zero if no hardware panning  */  
  10.     __u16 ypanstep;         /* zero if no hardware panning  */  
  11.     __u16 ywrapstep;        /* zero if no hardware ywrap    */  
  12.     __u32 line_length;      /* length of a line in bytes    */  
  13.     unsigned long mmio_start;   /* Start of Memory Mapped I/O   */  
  14.                     /* (physical address) */  
  15.     __u32 mmio_len;         /* Length of Memory Mapped I/O  */  
  16.     __u32 accel;            /* Indicate to driver which */  
  17.                     /*  specific chip/card we have  */  
  18.     __u16 reserved[3];      /* Reserved for future compatibility */  
  19. };  

[cpp]  view plain  copy
  1. struct fb_info {  
  2.     int node;  
  3.     int flags;  
  4.     struct mutex lock;      /* Lock for open/release/ioctl funcs */  
  5.     struct fb_var_screeninfo var;   /* Current var */  
  6.     struct fb_fix_screeninfo fix;   /* Current fix */  
  7.     struct fb_monspecs monspecs;    /* Current Monitor specs */  
  8.     struct work_struct queue;   /* Framebuffer event queue */  
  9.     struct fb_pixmap pixmap;    /* Image hardware mapper */  
  10.     struct fb_pixmap sprite;    /* Cursor hardware mapper */  
  11.     struct fb_cmap cmap;        /* Current cmap */  
  12.     struct list_head modelist;      /* mode list */  
  13.     struct fb_videomode *mode;  /* current mode */  
  14.         ...  
  15.     struct fb_ops *fbops;  
  16.     struct device *device;      /* This is the parent */  
  17.     struct device *dev;     /* This is this fb device */  
  18.     int class_flag;                    /* private sysfs flags */  
  19. #ifdef CONFIG_FB_TILEBLITTING  
  20.     struct fb_tile_ops *tileops;    /* Tile Blitting */  
  21. #endif  
  22.     char __iomem *screen_base;  /* Virtual address */  
  23.     unsigned long screen_size;  /* Amount of ioremapped VRAM or 0 */   
  24.     void *pseudo_palette;       /* Fake palette of 16 colors */   
  25.         ...  
  26. };  
[cpp]  view plain  copy
  1. struct fb_ops {  
  2.     /* open/release and usage marking */  
  3.     struct module *owner;  
  4.     int (*fb_open)(struct fb_info *info, int user);  
  5.     int (*fb_release)(struct fb_info *info, int user);  
  6.   
  7.     /* For framebuffers with strange non linear layouts or that do not 
  8.      * work with normal memory mapped access 
  9.      */  
  10.     ssize_t (*fb_read)(struct fb_info *info, char __user *buf,  
  11.                size_t count, loff_t *ppos);  
  12.     ssize_t (*fb_write)(struct fb_info *info, const char __user *buf,  
  13.                 size_t count, loff_t *ppos);  
  14.   
  15.     /* checks var and eventually tweaks it to something supported, 
  16.      * DO NOT MODIFY PAR */  
  17.     int (*fb_check_var)(struct fb_var_screeninfo *var, struct fb_info *info);  
  18.   
  19.     /* set the video mode according to info->var */  
  20.     int (*fb_set_par)(struct fb_info *info);  
  21.   
  22.     /* set color register */  
  23.     int (*fb_setcolreg)(unsigned regno, unsigned red, unsigned green,  
  24.                 unsigned blue, unsigned transp, struct fb_info *info);  
  25.   
  26.     /* set color registers in batch */  
  27.     int (*fb_setcmap)(struct fb_cmap *cmap, struct fb_info *info);  
  28.   
  29.     /* blank display */  
  30.     int (*fb_blank)(int blank, struct fb_info *info);  
  31.   
  32.     /* pan display */  
  33.     int (*fb_pan_display)(struct fb_var_screeninfo *var, struct fb_info *info);  
  34.   
  35.     /* Draws a rectangle */  
  36.     void (*fb_fillrect) (struct fb_info *info, const struct fb_fillrect *rect);  
  37.     /* Copy data from area to another */  
  38.     void (*fb_copyarea) (struct fb_info *info, const struct fb_copyarea *region);  
  39.     /* Draws a image to the display */  
  40.     void (*fb_imageblit) (struct fb_info *info, const struct fb_image *image);  
  41.   
  42.     /* Draws cursor */  
  43.     int (*fb_cursor) (struct fb_info *info, struct fb_cursor *cursor);  
  44.   
  45.     /* Rotates the display */  
  46.     void (*fb_rotate)(struct fb_info *info, int angle);  
  47.   
  48.     /* wait for blit idle, optional */  
  49.     int (*fb_sync)(struct fb_info *info);  
  50.   
  51.     /* perform fb specific ioctl (optional) */  
  52.     int (*fb_ioctl)(struct fb_info *info, unsigned int cmd,  
  53.             unsigned long arg);  
  54.   
  55.     /* Handle 32bit compat ioctl (optional) */  
  56.     int (*fb_compat_ioctl)(struct fb_info *info, unsigned cmd,  
  57.             unsigned long arg);  
  58.   
  59.     /* perform fb specific mmap */  
  60.     int (*fb_mmap)(struct fb_info *info, struct vm_area_struct *vma);  
  61.   
  62.     /* save current hardware state */  
  63.     void (*fb_save_state)(struct fb_info *info);  
  64.   
  65.     /* restore saved state */  
  66.     void (*fb_restore_state)(struct fb_info *info);  
  67.   
  68.     /* get capability given var */  
  69.     void (*fb_get_caps)(struct fb_info *info, struct fb_blit_caps *caps,  
  70.                 struct fb_var_screeninfo *var);  
  71. };  

[cpp]  view plain  copy
  1. static const struct file_operations fb_fops = {  
  2.     .owner =    THIS_MODULE,  
  3.     .read =     fb_read,  
  4.     .write =    fb_write,  
  5.     .check_flags = my_check,  
  6.     .unlocked_ioctl = fb_ioctl,  
  7. #ifdef CONFIG_COMPAT  
  8.     .compat_ioctl = fb_compat_ioctl,  
  9. #endif  
  10.     .mmap =     fb_mmap,  
  11.     .open =     fb_open,  
  12.     .release =  fb_release,  
  13. #ifdef HAVE_ARCH_FB_UNMAPPED_AREA  
  14.     .get_unmapped_area = get_fb_unmapped_area,  
  15. #endif  
  16. #ifdef CONFIG_FB_DEFERRED_IO  
  17.     .fsync =    fb_deferred_io_fsync,  
  18. #endif  
  19. };  

framebuffer设备的注册与注销:

register_framebuffer(struct fb_info *fb_info);

unregister_framebuffer(struct fb_info *fb_info);

下面看看fb_ioctl 都做了什么?

[cpp]  view plain  copy
  1. static long do_fb_ioctl(struct fb_info *info, unsigned int cmd,  
  2.             unsigned long arg)  
  3. {  
  4.     struct fb_ops *fb;  
  5.     struct fb_var_screeninfo var;  
  6.     struct fb_fix_screeninfo fix;  
  7.     struct fb_con2fbmap con2fb;  
  8.     struct fb_cmap cmap_from;  
  9.     struct fb_cmap_user cmap;  
  10.     struct fb_event event;  
  11.     void __user *argp = (void __user *)arg;  
  12.     long ret = 0;  
  13.   
  14.     switch (cmd) {  
  15.     case FBIOGET_VSCREENINFO:  
  16.         if (!lock_fb_info(info))  
  17.             return -ENODEV;  
  18.         var = info->var;  
  19.         unlock_fb_info(info);  
  20.   
  21.         ret = copy_to_user(argp, &var, sizeof(var)) ? -EFAULT : 0;  
  22.         break;  
  23.     case <span style="color:#ff0000;">FBIOPUT_VSCREENINFO</span>:  
  24.         if (copy_from_user(&var, argp, sizeof(var)))  
  25.             return -EFAULT;  
  26.         if (!lock_fb_info(info))  
  27.             return -ENODEV;  
  28.         console_lock();  
  29.         info->flags |= FBINFO_MISC_USEREVENT;  
  30.         ret = fb_set_var(info, &var);  
  31.         info->flags &= ~FBINFO_MISC_USEREVENT;  
  32.         console_unlock();  
  33.         unlock_fb_info(info);  
  34.         if (!ret && copy_to_user(argp, &var, sizeof(var)))  
  35.             ret = -EFAULT;  
  36.         break;  
  37.     case FBIOGET_FSCREENINFO:  
  38.         if (!lock_fb_info(info))  
  39.             return -ENODEV;  
  40.         fix = info->fix;  
  41.         unlock_fb_info(info);  
  42.   
  43.         ret = copy_to_user(argp, &fix, sizeof(fix)) ? -EFAULT : 0;  
  44.         break;  
  45.     case FBIOPUTCMAP:  
  46.         if (copy_from_user(&cmap, argp, sizeof(cmap)))  
  47.             return -EFAULT;  
  48.         ret = fb_set_user_cmap(&cmap, info);  
  49.         break;  
  50.     case FBIOGETCMAP:  
  51.         if (copy_from_user(&cmap, argp, sizeof(cmap)))  
  52.             return -EFAULT;  
  53.         if (!lock_fb_info(info))  
  54.             return -ENODEV;  
  55.         cmap_from = info->cmap;  
  56.         unlock_fb_info(info);  
  57.         ret = fb_cmap_to_user(&cmap_from, &cmap);  
  58.         break;  
  59.     case FBIOPAN_DISPLAY:  
  60.         if (copy_from_user(&var, argp, sizeof(var)))  
  61.             return -EFAULT;  
  62.         if (!lock_fb_info(info))  
  63.             return -ENODEV;  
  64.         console_lock();  
  65.         ret = fb_pan_display(info, &var);  
  66.         console_unlock();  
  67.         unlock_fb_info(info);  
  68.         if (ret == 0 && copy_to_user(argp, &var, sizeof(var)))  
  69.             return -EFAULT;  
  70.         break;  
  71.     case FBIO_CURSOR:  
  72.         ret = -EINVAL;  
  73.         break;  
  74.     case FBIOGET_CON2FBMAP:  
  75.         if (copy_from_user(&con2fb, argp, sizeof(con2fb)))  
  76.             return -EFAULT;  
  77.         if (con2fb.console < 1 || con2fb.console > MAX_NR_CONSOLES)  
  78.             return -EINVAL;  
  79.         con2fb.framebuffer = -1;  
  80.         event.data = &con2fb;  
  81.         if (!lock_fb_info(info))  
  82.             return -ENODEV;  
  83.         event.info = info;  
  84.         fb_notifier_call_chain(FB_EVENT_GET_CONSOLE_MAP, &event);  
  85.         unlock_fb_info(info);  
  86.         ret = copy_to_user(argp, &con2fb, sizeof(con2fb)) ? -EFAULT : 0;  
  87.         break;  
  88.     case FBIOPUT_CON2FBMAP:  
  89.         if (copy_from_user(&con2fb, argp, sizeof(con2fb)))  
  90.             return -EFAULT;  
  91.         if (con2fb.console < 1 || con2fb.console > MAX_NR_CONSOLES)  
  92.             return -EINVAL;  
  93.         if (con2fb.framebuffer < 0 || con2fb.framebuffer >= FB_MAX)  
  94.             return -EINVAL;  
  95.         if (!registered_fb[con2fb.framebuffer])  
  96.             request_module("fb%d", con2fb.framebuffer);  
  97.         if (!registered_fb[con2fb.framebuffer]) {  
  98.             ret = -EINVAL;  
  99.             break;  
  100.         }  
  101.         event.data = &con2fb;  
  102.         if (!lock_fb_info(info))  
  103.             return -ENODEV;  
  104.         event.info = info;  
  105.         ret = fb_notifier_call_chain(FB_EVENT_SET_CONSOLE_MAP, &event);  
  106.         unlock_fb_info(info);  
  107.         break;  
  108.     case FBIOBLANK:  
  109.         if (!lock_fb_info(info))  
  110.             return -ENODEV;  
  111.         console_lock();  
  112.         info->flags |= FBINFO_MISC_USEREVENT;  
  113.         ret = fb_blank(info, arg);  
  114.         info->flags &= ~FBINFO_MISC_USEREVENT;  
  115.         console_unlock();  
  116.         unlock_fb_info(info);  
  117.         break;  
  118.     default:  
  119.         if (!lock_fb_info(info))  
  120.             return -ENODEV;  
  121.         fb = info->fbops;  
  122.         if (fb->fb_ioctl)  
  123.             ret = fb->fb_ioctl(info, cmd, arg);  
  124.         else  
  125.             ret = -ENOTTY;  
  126.         unlock_fb_info(info);  
  127.     }  
  128.     return ret;  
  129. }  
  130.   
  131. static long fb_ioctl(struct file *file, unsigned int cmd, unsigned long arg)  
  132. {  
  133.     struct fb_info *info = file_fb_info(file);  
  134.   
  135.    printk(\nfb_ioctl mem\n);  
  136.     if (!info)  
  137.         return -ENODEV;  
  138.     return do_fb_ioctl(info, cmd, arg);  
  139. }  


根据文件操作的static const struct file_operations fb_fops,应用程序在打开一个framebuffer设备时,可以使用read,write,ioctl来直接操作设备。

应用例程:

[cpp]  view plain  copy
  1. #include <stdio.h>  
  2. #include <stdlib.h>  
  3. #include <unistd.h>  
  4. #include <sys/ioctl.h>  
  5. #include <fcntl.h>          
  6. #include <linux/fb.h>  
  7. #include <sys/mman.h>  
  8.   
  9. struct fb_var_screeninfo vinfo;  
  10. struct fb_fix_screeninfo finfo;  
  11.   
  12. static void fb_var_printf(struct fb_var_screeninfo tmp)  
  13. {  
  14.   
  15.   
  16.     printf("fb_var_screeninfo:\n");  
  17.     printf("xres =%d, yres =%d, bits_per_pixel = %d\n",tmp.xres,tmp.yres,tmp.bits_per_pixel);  
  18.     printf("height=%d,width = %d\n",tmp.height,tmp.width);  
  19.     printf("xres_virtual =%d, yres_virtual =%d, xoffset=%d,yoffset=%d\n",tmp.xres_virtual,tmp.yres_virtual,tmp.xoffset,tmp.yoffset);  
  20.     return ;  
  21. }  
  22. int main(void)  
  23. {  
  24.     int fbfd;  
  25.     int fbsize;  
  26.     unsigned char *fbbuf;  
  27.     char buf[100];  
  28.     int i,res,adc_data;  
  29.     for (i=0; i<100; i++) buf[i] = 0xaa;  
  30.     if ((fbfd = open("/dev/fb0", O_RDWR)) < 0) {  
  31.             printf("open fb0 failed\n");  
  32.          return 1;  
  33.     }  
  34.     printf("fbfd = %d\n", fbfd);  
  35.     if ((res =ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo))) { //获取设备显示特性信息  
  36.         printf("bad vscreeninfo ioctl.error = %d\n",res);  
  37.     }  
  38.   
  39.     fb_var_printf(vinfo);  
  40.     fbsize = vinfo.xres * vinfo.yres * (vinfo.bits_per_pixel/8); //计算显卡(LCD控制器)显存大小,也就是一整屏共占多少个字节  
  41.     printf("fbisze: %d\n",fbsize);  
  42.     if ((fbbuf = mmap(0, fbsize, PROT_READ | PROT_WRITE, MAP_SHARED, fbfd, 0)) == (void*) -1)  //映射显卡设备的内存到用户控件,使得用户直接访问设备内存(显存)  
  43.     {  
  44.         printf("map video error.\n");  
  45.     }  
  46.       
  47.     for (i = 0; i< fbsize; i++) {  //填充farmebuffer缓冲区  
  48.         *(fbbuf+i) = 0xaa;  //颜色信息  
  49.     }  
  50.     munmap(fbbuf, fbsize);         
  51.     close(fbfd);  
  52.     return 0;  
  53. }  
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值