帧缓冲
帧缓冲的概念
帧缓冲(framebuffer)是Linux系统为显示设备提供的一个接口,它将显示缓冲区抽象,屏蔽图像硬件的底层差异,允许上层应用程序在图形模式下直接对显示缓冲区进行读写操作。用户不必关心物理显示缓冲区的具体位置及存放方式,这些都由帧缓冲设备驱动本身来完成。对于帧缓冲设备而言,只要在显示缓冲区中与显示点对应的区域写入颜色值,对应的颜色会自动在屏幕上显示。
帧缓冲设备为标准字符设备,主设备号为29,对应于/dev/fb%d设备文件。帧缓冲驱动的应用非常广泛,在Linux的桌面系统中,Xwindow服务器就是利用帧缓冲进行窗口的绘制。嵌入式系统中的Qt/Embedded等图形用户界面环境也基于帧缓冲而设计。另外,通过帧缓冲可支持汉字点阵的显示,因此帧缓冲也成为Linux汉化的可行方案。
Linux帧缓冲相关的数据结构与函数
1. 帧缓冲设备最关键的一个数据结构体是fb_info 结构体。定义如下:
- struct fb_info
- {
- int node;
- int flags;
- struct fb_var_screeninfo var;
- struct fb_fix_screeninfo fix;
- struct fb_monspecs monspecs;
- struct work_struct queue;
- struct fb_pixmap pixmap;
- struct fb_pixmap sprite;
- struct fb_cmap cmap;
- struct list_head modelist;
- struct fb_videomode *mode;
- #ifdef CONFIG_FB_BACKLIGHT
- struct mutex bl_mutex;
-
- struct backlight_device *bl_dev;
-
- u8 bl_curve[FB_BACKLIGHT_LEVELS];
- #endif
- struct fb_ops *fbops;
- struct device *device;
- struct class_device *class_device;/
- int class_flag;
- #ifdef CONFIG_FB_TILEBLITTING
- struct fb_tile_ops *tileops;
- #endif
- char __iomem *screen_base;
- unsigned long screen_size;
- void *pseudo_palette;
- #define FBINFO_STATE_RUNNING 0
- #define FBINFO_STATE_SUSPENDED 1
- u32 state;
- void *fbcon_par;
- void *par;
- };
fb_info结构体记录了帧缓冲设备的全部信息,包括设备的设置参数、状态以及操作函数指针。每一个帧缓冲设备都必须对应一个fb_info结构体~
2. fb_ops结构体
fb_info结构体成员变量fbops为指向底层操作的函数的指针,这些函数是需要驱动程序开发人员编写的,定义如下:
- struct fb_ops
- {
- struct module *owner;
-
- int(*fb_open)(struct fb_info *info, int user);
- int(*fb_release)(struct fb_info *info, int user);
-
-
- ssize_t(*fb_read)(struct file *file, char _ _user *buf, size_t count, loff_t*ppos);
- ssize_t(*fb_write)(struct file *file, const char _ _user *buf, size_t count, loff_t *ppos);
-
-
- int(*fb_check_var)(struct fb_var_screeninfo *var, struct fb_info *info);
-
-
- int(*fb_set_par)(struct fb_info *info);
-
-
- int(*fb_setcolreg)(unsigned regno, unsigned red, unsigned green, unsigned blue, unsigned transp, struct fb_info *info);
-
-
- int(*fb_setcmap)(struct fb_cmap *cmap, struct fb_info *info);
-
-
- int(*fb_blank)(int blank, struct fb_info *info);
-
-
- int(*fb_pan_display)(struct fb_var_screeninfo *var, struct fb_info *info);
-
-
- void(*fb_fillrect)(struct fb_info *info, const struct fb_fillrect *rect);
-
- void(*fb_copyarea)(struct fb_info *info, const struct fb_copyarea *region);
-
- void(*fb_imageblit)(struct fb_info *info, const struct fb_image *image);
-
-
- int(*fb_cursor)(struct fb_info *info, struct fb_cursor *cursor);
-
-
- void(*fb_rotate)(struct fb_info *info, int angle);
-
-
- int(*fb_sync)(struct fb_info *info);
-
-
- int(*fb_ioctl)(struct fb_info *info, unsigned int cmd, unsigned long arg);
-
-
- int(*fb_compat_ioctl)(struct fb_info *info, unsigned cmd, unsigned long arg);
-
-
- int(*fb_mmap)(struct fb_info *info, struct vm_area_struct *vma);
-
-
- void(*fb_save_state)(struct fb_info *info);
-
-
- void(*fb_restore_state)(struct fb_info *info);
- };
fb_ops的fb_check_var()成员函数用于检查可以修改的屏幕参数并调整到合适的值,而fb_set_par()则使得用户设置的屏幕参数在硬件上有效。
3. fb_var_screeninfo 和fb_fix_screeninfo 结构体
fb_info的fb_var_screeninfo 和fb_fix_screeninfo 成员也是结构体,fb_var_screeninfo记录用户可修改的显示控制器参数,包括屏幕分辨率和每个像素点的比特数。fb_var_screeninfo中的xres定义屏幕一行有多少个点,yres定义屏幕一列有多少个点,bits_per_pixel定义每个点用多少个字节表示。而fb_fix_screeninfo 中记录用户不能修改的显示控制器的参数,如屏幕缓冲区的物理地址、长度。当对帧缓冲设备进行映射操作的时候,就是从fb_fix_screeninfo 中取得缓冲区物理地址的。上述数据成员都需要在驱动程序中初始化和设置。
fb_var_screeninfo和fb_fix_screeninfo结构体的定义分别如下:
- struct fb_var_screeninfo
- {
-
- __u32 xres;
- __u32 yres;
-
- __u32 xres_virtual;
- __u32 yres_virtual;
-
- __u32 xoffset;
- __u32 yoffset;
-
- __u32 bits_per_pixel;
- __u32 grayscale;/非0时指灰度 */
-
-
- struct fb_bitfield red;
- struct fb_bitfield green;
- struct fb_bitfield blue;
- struct fb_bitfield transp;
-
- __u32 nonstd;
-
- __u32 activate;
-
- __u32 height;
- __u32 width;
-
- __u32 accel_flags;
-
-
- __u32 pixclock;
- __u32 left_margin;
- __u32 right_margin;
- __u32 upper_margin;
- __u32 lower_margin;
- __u32 hsync_len;
- __u32 vsync_len;
- __u32 sync;
- __u32 vmode;
- __u32 rotate;
- __u32 reserved[5];
- };
-
- struct fb_fix_screeninfo
- {
- char id[16];
- unsigned long smem_start;
- __u32 smem_len;
- __u32 type;
- __u32 type_aux;
- __u32 visual;
- __u16 xpanstep;
- __u16 ypanstep;
- __u16 ywrapstep;/
- __u32 line_length;
- unsigned long mmio_start;
- __u32 mmio_len;
- __u32 accel;
- __u16 reserved[3];
- };
fb_fix_screeninfo结构体中的成员变量visual记录屏幕使用的色彩模式,在Linux系统中,支持的色彩模式包括以下几种:
Monochrome(FB_VISUAL_MONO01、FB_VISUAL_MONO10),每个像素是黑或白。
Pseudo color ( FB_VISUAL_PSEUDOCOLOR、FB_VISUAL_STATIC_PSEUDOCOLOR),即伪彩色,采用索引颜色显示。
True color(FB_VISUAL_TRUECOLOR),真彩色,分成红、绿、蓝三基色。
Direct color(FB_VISUAL_DIRECTCOLOR),每个像素颜色也是有红、绿、蓝组成,不过每个颜色值是个索引,需要查表。
Grayscale displays,灰度显示,红、绿、蓝的值都一样。
4. fb_bitfield结构体
fb_var_screen结构体中的fb_bitfield结构的成员变量red、green、blue分别记录R、G、B的位域,fb_bitfield结构体描述每一像素显示缓冲区的组织方式,包含位域偏移、位域长度和MSB指示,如下:
- struct fb_bitfield
- {
- __u32 offset;
- __u32 length;
- __u32 msb_right;
- };
5. fb_cmap结构体
fb_cmap结构体记录设备无关的颜色表信息,用户空间可以通过ioctl()的FBIOGETCMAP 和FBIOPUTCMAP命令读取或设定颜色表。
- struct fb_cmap
- {
- __u32 start;
- __u32 len;
-
- __u16 *red;
- __u16 *green;
- __u16 *blue;
- __u16 *transp;
- };
6. 文件操作结构体
作为一种字符设备,帧缓冲设备的文件操作结构体定义于/linux/drivers/vedio/fbmem.c 文件中,如下所示:
- static struct file_operations fb_fops =
- {
- .owner = THIS_MODULE,
- .read = fb_read,
- .write = fb_write,
- .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
- };
帧缓冲设备驱动的文件操作接口函数已经在fbmem.c 中被统一实现,一般不需要由驱动工程师再编写。
7. 注册与注销帧缓冲设备
Linux内核提供了register_framebuffer()和unregister_framebuffer()函数分别注册和注销帧缓冲设备,这两个函数都接受FBI指针为参数,原型为:
int register_framebuffer(struct fb_info *fb_info);
int unregister_framebuffer(struct fb_info *fb_info);
对于register_framebuffer()函数而言,如果注册的帧缓冲设备数超过了FB_MAX(目前定义为32),则函数返回-ENXIO,注册成功则返回0。