Linux内核修炼之framebuffer分析

Stella981
• 阅读 689

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执行机制:

Linux内核修炼之framebuffer分析

framebuffer子系统的层次结构:

Linux内核修炼之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 {  
         __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 */  
     };
    

  

[cpp] view plain copy

  1.  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 */  
     };
    

  

[cpp] view plain copy

  1.  struct fb_info {  
         int node;  
         int flags;  
         struct mutex lock;      /* Lock for open/release/ioctl funcs */  
         struct fb_var_screeninfo var;   /* Current var */  
         struct fb_fix_screeninfo fix;   /* Current fix */  
         struct fb_monspecs monspecs;    /* Current Monitor specs */  
         struct work_struct queue;   /* Framebuffer event queue */  
         struct fb_pixmap pixmap;    /* Image hardware mapper */  
         struct fb_pixmap sprite;    /* Cursor hardware mapper */  
         struct fb_cmap cmap;        /* Current cmap */  
         struct list_head modelist;      /* mode list */  
         struct fb_videomode *mode;  /* current mode */  
             ...  
         struct fb_ops *fbops;  
         struct device *device;      /* This is the parent */  
         struct device *dev;     /* This is this fb device */  
         int class_flag;                    /* private sysfs flags */  
     #ifdef CONFIG_FB_TILEBLITTING  
         struct fb_tile_ops *tileops;    /* Tile Blitting */  
     #endif  
         char __iomem *screen_base;  /* Virtual address */  
         unsigned long screen_size;  /* Amount of ioremapped VRAM or 0 */   
         void *pseudo_palette;       /* Fake palette of 16 colors */   
             ...  
     };
    

 

 

[cpp] view plain copy

  1.  struct fb_ops {  
         /* open/release and usage marking */  
         struct module *owner;  
         int (*fb_open)(struct fb_info *info, int user);  
         int (*fb_release)(struct fb_info *info, int user);  
       
         /* For framebuffers with strange non linear layouts or that do not 
          * work with normal memory mapped access 
          */  
         ssize_t (*fb_read)(struct fb_info *info, char __user *buf,  
                    size_t count, loff_t *ppos);  
         ssize_t (*fb_write)(struct fb_info *info, const char __user *buf,  
                     size_t count, loff_t *ppos);  
       
         /* checks var and eventually tweaks it to something supported, 
          * DO NOT MODIFY PAR */  
         int (*fb_check_var)(struct fb_var_screeninfo *var, struct fb_info *info);  
       
         /* set the video mode according to info->var */  
         int (*fb_set_par)(struct fb_info *info);  
       
         /* set color register */  
         int (*fb_setcolreg)(unsigned regno, unsigned red, unsigned green,  
                     unsigned blue, unsigned transp, struct fb_info *info);  
       
         /* set color registers in batch */  
         int (*fb_setcmap)(struct fb_cmap *cmap, struct fb_info *info);  
       
         /* blank display */  
         int (*fb_blank)(int blank, struct fb_info *info);  
       
         /* pan display */  
         int (*fb_pan_display)(struct fb_var_screeninfo *var, struct fb_info *info);  
       
         /* Draws a rectangle */  
         void (*fb_fillrect) (struct fb_info *info, const struct fb_fillrect *rect);  
         /* Copy data from area to another */  
         void (*fb_copyarea) (struct fb_info *info, const struct fb_copyarea *region);  
         /* Draws a image to the display */  
         void (*fb_imageblit) (struct fb_info *info, const struct fb_image *image);  
       
         /* Draws cursor */  
         int (*fb_cursor) (struct fb_info *info, struct fb_cursor *cursor);  
       
         /* Rotates the display */  
         void (*fb_rotate)(struct fb_info *info, int angle);  
       
         /* wait for blit idle, optional */  
         int (*fb_sync)(struct fb_info *info);  
       
         /* perform fb specific ioctl (optional) */  
         int (*fb_ioctl)(struct fb_info *info, unsigned int cmd,  
                 unsigned long arg);  
       
         /* Handle 32bit compat ioctl (optional) */  
         int (*fb_compat_ioctl)(struct fb_info *info, unsigned cmd,  
                 unsigned long arg);  
       
         /* perform fb specific mmap */  
         int (*fb_mmap)(struct fb_info *info, struct vm_area_struct *vma);  
       
         /* save current hardware state */  
         void (*fb_save_state)(struct fb_info *info);  
       
         /* restore saved state */  
         void (*fb_restore_state)(struct fb_info *info);  
       
         /* get capability given var */  
         void (*fb_get_caps)(struct fb_info *info, struct fb_blit_caps *caps,  
                     struct fb_var_screeninfo *var);  
     };
    

  

[cpp] view plain copy

  1.  static const struct file_operations fb_fops = {  
         .owner =    THIS_MODULE,  
         .read =     fb_read,  
         .write =    fb_write,  
         .check_flags = my_check,  
         .unlocked_ioctl = fb_ioctl,  
     #ifdef CONFIG_COMPAT  
         .compat_ioctl = fb_compat_ioctl,  
     #endif  
         .mmap =     fb_mmap,  
         .open =     fb_open,  
         .release =  fb_release,  
     #ifdef HAVE_ARCH_FB_UNMAPPED_AREA  
         .get_unmapped_area = get_fb_unmapped_area,  
     #endif  
     #ifdef CONFIG_FB_DEFERRED_IO  
         .fsync =    fb_deferred_io_fsync,  
     #endif  
     };
    

 

 

framebuffer设备的注冊与注销:

register_framebuffer(struct fb_info *fb_info);

unregister_framebuffer(struct fb_info *fb_info);

以下看看fb_ioctl 都做了什么?

static long do_fb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg) { struct fb_ops *fb; struct fb_var_screeninfo var; struct fb_fix_screeninfo fix; struct fb_con2fbmap con2fb; struct fb_cmap cmap_from; struct fb_cmap_user cmap; struct fb_event event; void __user *argp = (void __user *)arg; long ret = 0;

switch (cmd) {
case FBIOGET\_VSCREENINFO:
    if (!lock\_fb\_info(info))
        return -ENODEV;
    var = info->var;
    unlock\_fb\_info(info);

    ret = copy\_to\_user(argp, &var, sizeof(var)) ? -EFAULT : 0;
    break;
case FBIOPUT\_VSCREENINFO:
    if (copy\_from\_user(&var, argp, sizeof(var)))
        return -EFAULT;
    if (!lock\_fb\_info(info))
        return -ENODEV;
    console\_lock();
    info->flags |= FBINFO\_MISC\_USEREVENT;
    ret = fb\_set\_var(info, &var);
    info->flags &= ~FBINFO\_MISC\_USEREVENT;
    console\_unlock();
    unlock\_fb\_info(info);
    if (!ret && copy\_to\_user(argp, &var, sizeof(var)))
        ret = -EFAULT;
    break;
case FBIOGET\_FSCREENINFO:
    if (!lock\_fb\_info(info))
        return -ENODEV;
    fix = info->fix;
    unlock\_fb\_info(info);

    ret = copy\_to\_user(argp, &fix, sizeof(fix)) ? -EFAULT : 0;
    break;
case FBIOPUTCMAP:
    if (copy\_from\_user(&cmap, argp, sizeof(cmap)))
        return -EFAULT;
    ret = fb\_set\_user\_cmap(&cmap, info);
    break;
case FBIOGETCMAP:
    if (copy\_from\_user(&cmap, argp, sizeof(cmap)))
        return -EFAULT;
    if (!lock\_fb\_info(info))
        return -ENODEV;
    cmap\_from = info->cmap;
    unlock\_fb\_info(info);
    ret = fb\_cmap\_to\_user(&cmap\_from, &cmap);
    break;
case FBIOPAN\_DISPLAY:
    if (copy\_from\_user(&var, argp, sizeof(var)))
        return -EFAULT;
    if (!lock\_fb\_info(info))
        return -ENODEV;
    console\_lock();
    ret = fb\_pan\_display(info, &var);
    console\_unlock();
    unlock\_fb\_info(info);
    if (ret == 0 && copy\_to\_user(argp, &var, sizeof(var)))
        return -EFAULT;
    break;
case FBIO\_CURSOR:
    ret = -EINVAL;
    break;
case FBIOGET\_CON2FBMAP:
    if (copy\_from\_user(&con2fb, argp, sizeof(con2fb)))
        return -EFAULT;
    if (con2fb.console < 1 || con2fb.console > MAX\_NR\_CONSOLES)
        return -EINVAL;
    con2fb.framebuffer = -1;
    event.data = &con2fb;
    if (!lock\_fb\_info(info))
        return -ENODEV;
    event.info = info;
    fb\_notifier\_call\_chain(FB\_EVENT\_GET\_CONSOLE\_MAP, &event);
    unlock\_fb\_info(info);
    ret = copy\_to\_user(argp, &con2fb, sizeof(con2fb)) ? -EFAULT : 0;
    break;
case FBIOPUT\_CON2FBMAP:
    if (copy\_from\_user(&con2fb, argp, sizeof(con2fb)))
        return -EFAULT;
    if (con2fb.console < 1 || con2fb.console > MAX\_NR\_CONSOLES)
        return -EINVAL;
    if (con2fb.framebuffer < 0 || con2fb.framebuffer >= FB\_MAX)
        return -EINVAL;
    if (!registered\_fb\[con2fb.framebuffer\])
        request\_module("fb%d", con2fb.framebuffer);
    if (!registered\_fb\[con2fb.framebuffer\]) {
        ret = -EINVAL;
        break;
    }
    event.data = &con2fb;
    if (!lock\_fb\_info(info))
        return -ENODEV;
    event.info = info;
    ret = fb\_notifier\_call\_chain(FB\_EVENT\_SET\_CONSOLE\_MAP, &event);
    unlock\_fb\_info(info);
    break;
case FBIOBLANK:
    if (!lock\_fb\_info(info))
        return -ENODEV;
    console\_lock();
    info->flags |= FBINFO\_MISC\_USEREVENT;
    ret = fb\_blank(info, arg);
    info->flags &= ~FBINFO\_MISC\_USEREVENT;
    console\_unlock();
    unlock\_fb\_info(info);
    break;
default:
    if (!lock\_fb\_info(info))
        return -ENODEV;
    fb = info->fbops;
    if (fb->fb\_ioctl)
        ret = fb->fb\_ioctl(info, cmd, arg);
    else
        ret = -ENOTTY;
    unlock\_fb\_info(info);
}
return ret;

}

static long fb_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct fb_info *info = file_fb_info(file);

printk(\nfb_ioctl mem\n); if (!info) return -ENODEV; return do_fb_ioctl(info, cmd, arg); }

 

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

应用例程:

[cpp] view plain copy

  1.  #include <stdio.h>  
     #include <stdlib.h>  
     #include <unistd.h>  
     #include <sys/ioctl.h>  
     #include <fcntl.h>          
     #include <linux/fb.h>  
     #include <sys/mman.h>  
       
     struct fb_var_screeninfo vinfo;  
     struct fb_fix_screeninfo finfo;  
       
     static void fb_var_printf(struct fb_var_screeninfo tmp)  
     {  
       
       
         printf("fb_var_screeninfo:\n");  
         printf("xres =%d, yres =%d, bits_per_pixel = %d\n",tmp.xres,tmp.yres,tmp.bits_per_pixel);  
         printf("height=%d,width = %d\n",tmp.height,tmp.width);  
         printf("xres_virtual =%d, yres_virtual =%d, xoffset=%d,yoffset=%d\n",tmp.xres_virtual,tmp.yres_virtual,tmp.xoffset,tmp.yoffset);  
         return ;  
     }  
     int main(void)  
     {  
         int fbfd;  
         int fbsize;  
         unsigned char *fbbuf;  
         char buf[100];  
         int i,res,adc_data;  
         for (i=0; i<100; i++) buf[i] = 0xaa;  
         if ((fbfd = open("/dev/fb0", O_RDWR)) < 0) {  
                 printf("open fb0 failed\n");  
              return 1;  
         }  
         printf("fbfd = %d\n", fbfd);  
         if ((res =ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo))) { //获取设备显示特性信息  
             printf("bad vscreeninfo ioctl.error = %d\n",res);  
         }  
       
         fb_var_printf(vinfo);  
         fbsize = vinfo.xres * vinfo.yres * (vinfo.bits_per_pixel/8); //计算显卡(LCD控制器)显存大小。也就是一整屏共占多少个字节  
         printf("fbisze: %d\n",fbsize);  
         if ((fbbuf = mmap(0, fbsize, PROT_READ | PROT_WRITE, MAP_SHARED, fbfd, 0)) == (void*) -1)  //映射显卡设备的内存到用户控件,使得用户直接訪问设备内存(显存)  
         {  
             printf("map video error.\n");  
         }  
           
         for (i = 0; i< fbsize; i++) {  //填充farmebuffer缓冲区  
             *(fbbuf+i) = 0xaa;  //颜色信息  
         }  
         munmap(fbbuf, fbsize);         
         close(fbfd);  
         return 0;  
     }
    
点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
4个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Easter79 Easter79
3年前
Twitter的分布式自增ID算法snowflake (Java版)
概述分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,另外UUID一般是无序的。有些时候我们希望能使用一种简单一些的ID,并且希望ID能够按照时间有序生成。而twitter的snowflake解决了这种需求,最初Twitter把存储系统从MySQL迁移
Wesley13 Wesley13
3年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
3年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
3年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
10个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这