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