Linux内核修炼之framebuffer分析

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

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.linux

Frame buffer机制为图形显示卡提供了一个抽象层。数据结构

可以使得应用程序不用考虑底层硬件的实现细节而经过一些API接口就能够訪问到显示设备。  但Framebuffer自己不具有不论什么运算数据的能力,就仅仅比如是一个临时存放水的水池。水池里的水就是显示的东西。CPU将运算后的结果放到这个水池,水池再将结果流到显示器(一般经过DMA传输). 因此应用程序经过读写这个水池。就能够至关于操做了显示卡。系统中可以在/dev/fb*看到framebuffer设备。app

如下这幅图很是好的描写叙述了framebuffer执行机制:ide

framebuffer子系统的层次结构:函数

 

上图主要在如下文件里:ui

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

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

fbmem.c是实现framebuffer的核心。与硬件无关。.net

它使用了如下这些数据结构

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;  
    }  
相关文章
相关标签/搜索