1 FrameBuffer
1.1 帧缓冲的概念
帧缓冲(FrameBuffer)是Linux系统为显示设备提供的一个接口,它将显示缓冲区抽象,屏蔽图像硬件的底层差异,允许上层应用程序在图形模式下直接对显示缓冲区进行读写操作。用户不必关心物理显示缓冲区的具体位置及存放方式,这些都由缓冲设备驱动本身来完成。对于帧设备而言,只要在显示缓冲区与显示点对应的区域写入颜色值,对应的颜色会自动在屏幕上显示。
帧缓冲设备为标准字符设备,主设备号为29,对应于/dev/fbn设备文件。帧缓冲驱动的应用很广泛,在Linux的桌面系统中,X Window服务器就是利用帧缓冲进行窗口的绘制。嵌入式系统中的Qt/Embedded等图形用户界面环境也基于帧缓冲而设计。
1.2 显示缓冲区与显示点
在帧缓冲设备中,对屏幕显示点的操作通过读写显示缓冲区来完成,在不同的色彩模式下,显示缓冲区和屏幕上的显示点有不同的对应关系。
1.3 重要的数据结构
1.3.1 fb_info结构体
帧缓冲设备最关键的一个数据结构就是fb_info结构体,它记录了帧缓冲设备的全部信息,包括设备的设置参数,状态以及操作函数指针。每一个帧缓冲设备都对应一个fb_info结构体。
struct fb_info {
atomic_t count;
int node;
int flags;
struct mutex lock; /* Lock for open/release/ioctl funcs */
struct mutex mm_lock; /* Lock for fb_mmap and smem_* fields */
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 */
#ifdef CONFIG_FB_BACKLIGHT
/* assigned backlight device */
/* set before framebuffer registration,
remove after unregister */
struct backlight_device *bl_dev;
/* Backlight level curve */
struct mutex bl_curve_mutex;
u8 bl_curve[FB_BACKLIGHT_LEVELS];
#endif
#ifdef CONFIG_FB_DEFERRED_IO
struct delayed_work deferred_work;
struct fb_deferred_io *fbdefio;
#endif
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 */
#define FBINFO_STATE_RUNNING 0
#define FBINFO_STATE_SUSPENDED 1
u32 state; /* Hardware state i.e suspend */
void *fbcon_par; /* fbcon use-only private area */
/* From here on everything is device dependent */
void *par;
/* we need the PCI or similar aperture base/size not
smem_start/size as smem_start may just be an object
allocated inside the aperture so may not actually overlap */
struct apertures_struct {
unsigned int count;
struct aperture {
resource_size_t base;
resource_size_t size;
} ranges[0];
} *apertures;
};
1.3.1.1 fb_ops结构体
fb_info结构体的成员变量fbops为指向底层操作的函数的指针。fb_ops的fb_check_var()成员函数用于检查可以修改的屏幕参数并调整到合适的值,而fb_set_par()则使得用户设置的屏幕参数在硬件上有效。
1.3.1.2 fb_var_screeinfo和fb_fix_screeinfo结构体
fb_var_screeinfo记录用户可修改的显示控制器参数,包括屏幕分辨率和每个像素点的比特数。fb_var_screeinfo中的xres定义屏幕一行有多少个点,yres定义屏幕一列有多少个点,bits_per_pixel定义每个点用于多少个字节表示。而fb_fix_screeinfo中记录用户不能修改的显示控制器的参数。如屏幕缓冲区的物理地址、长度。当对帧缓冲设备进行映射操作的时候,就是从fb_fix_screeinfo中取得缓冲区物理地址的。上述数据成员都需要在驱动程序中初始化和设置。
1.3.1.3 fb_bitfield结构体
fb_bitfield结构体描述每一像素显示缓冲区的组织方式,包括位域偏移、位域长度和MSB(最高有效位)指示。
1.3.1.4 fb_cmap结构体
fb_cmap结构体记录设备无关的颜色表信息,用户空间可以通过ioctl()的FBIOGETCMAP和FBIOPUTCMAP命令获取或设定颜色表。
1.3.1.5 注册与注销帧缓冲设备
Linux内核提供了register_frambuffer()和unregister_frambuffer()函数分别注册和注销帧缓冲设备,这两个函数都接收fb_info指针为参数。
1.4 帧缓冲设备显示缓冲区的申请与释放
在嵌入式系统中,一种常见的方式是直接在RAM空间中分配一段显示缓冲区。在分配显示缓冲区时一定要考虑cache的一致性问题,因为系统往往会通过DMA方式搬移显示数据。合适的方式是使用dma_alloc_writecombine()函数分配一段writecombine区域,对应的writecombine区域由dma_free_writecombine()函数释放。
Writecombine意味着“写合并”,它允许写入的数据被合并,并临时保存在写合并缓冲区中,知道进行一次burst传输而不再需要多次single传输。通过dma_alloc_writecombine()分配的显示缓冲区不会出现cache一致性问题,这一点类似于dma_alloc_coherent()。
dma_alloc_coherent 在 arm 平台上会禁止页表项中的 C (Cacheable) 域以及 B(Bufferable)域。而 dma_alloc_writecombine 只禁止 C (Cacheable) 域.
参考文档:
LInux 设备驱动开发详解
http://blog.csdn.net/zjujoe/article/details/4189612