Framebuffer Analysis of Linux Kernel Cultivation

The Linux source code package /document/fb/framebuffer.txt has the following introduction:

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.

The Frame buffer mechanism provides an abstraction layer for graphics cards.

It enables the application program to access the display device through some API interfaces without considering the implementation details of the underlying hardware. But the Framebuffer itself does not have the ability to calculate any data, it is just like a pool for temporarily storing water. The water in the pool is what is shown. The CPU puts the result of the operation into this pool, and the pool then streams the result to the display (usually via DMA). So the application reads and writes to this pool. It can be equivalent to operating the display card. The system can see the framebuffer device in /dev/fb*.

The following picture is a very good description of the framebuffer execution mechanism:

The hierarchy of the framebuffer subsystem:

 

The above image is mainly in the following files:

drivers/vedio/fbmem.c This file is the core of the framebuffer implementation. hardware agnostic

drivers/vedio/xxxfb.c This file is mainly the realization of the framebuffer device driver, such as s3c2410fb.c realizes the framebuffer device driver

fbmem.c is the core of implementing framebuffer. Has nothing to do with hardware.

It uses these data structures :

struct fb_info *fb_info This data structure describes a series of information related to a framebuffer device
struct fb_ops *fb_ops This data structure describes a set of operation functions of a framebuffer device. Similar to file_operations, but only used by the kernel
static const struct file_operations fb_fops This data structure is a collection of file operation functions. When the app opens the device. Users can read, write, ioctl, etc.
struct fb_var_screeninfo var This data structure describes the display characteristics of the framebuffer device and can be changed.
struct fb_fix_screeninfo fix This data structure is used to save the display characteristics of the framebuffer device, which is fixed and cannot be changed

Detailed data structure:

 

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

 

Registration and deregistration of framebuffer devices:

register_framebuffer(struct fb_info *fb_info);

unregister_framebuffer(struct fb_info *fb_info);

Let's see what fb_ioctl has done?

 

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


 

 

According to the static const struct file_operations fb_fops of file operations, the application opens a framebuffer device. Can use read, write, ioctl to directly manipulate the device.

Application routine:

 

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

     

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325323563&siteId=291194637