分类: LINUX
2012-10-22 15:06:58
本文介绍了s3c6410中的framebuffer,参考代码为Linux2.6.28。网上介绍framebuffer的文章很多,内核代码中也有关于framebuffer的文档,所以本文只介绍一些其它文章较少介绍的部分。
1. Overview
在嵌入式系统中,会有一块内核空间保存LCD上每一个象素需要被显示的值。系统运行时,CPU的显示控制器会自动从这块内存读取内容,然后发送到LCD显示屏。这块内存就叫作framebuffer。对程序来说,通过修改framebuffer中的内容,就可以控制LCD的显示。
Linux的GUI系统都运行在用户空间,不能直接访问内核空间。所以就需要一个framebuffer驱动,将内核空间的framebuffer映射到用户空间,方便GUI的访问。
对framebuffer的典型操作如下所示:
l fd = open(fb, …);
l ioctl(fb, …); // 设置framebuffer,比如象素的格式等。
l pBuffer = mmap(fb, …); // 映射framebuffer到用户空间
l 。。。 // 像读写内存一样操作pBuffer
framebuffer与LCD接口之间的通路有两种,分别是DMA和local bus,一般都会将通路设置为DMA以提高性能。设置成DMA时,注意不能用kmalloc分配framebuffer,应使用dma_alloc_writecombine函数分配能被DMA访问的内存空间,对应代码在s3cfb_map_video_memory函数中。
s3c6410支持多个层叠窗口(5个),显示的时候,这些窗口会被叠加显示。在这里,framebuffer的概念变成和窗口关联,而不是和LCD显示屏关联。每个窗口对应一个framebuffer,所以,s3c6410中可以有5个framebuffer(不考虑硬件双缓冲的情况)。关于窗口的概念在s3c6410的芯片手册中有介绍。
2. 双缓冲
双缓冲是指framebuffer的大小两倍于LCD的大小,可将其称为frame1和frame2。LCD显示frame1的内容时,GUI在后台绘制frame2;LCD显示frame2时,GUI在后台绘制frame1。
有多种实现双缓冲的方法,比如硬件切换、virtual screen等。
硬件实现
s3c6410的芯片手册中提到它最多支持5个窗口叠加。其中win0和win1支持硬件双缓冲。win0对应的寄存器为
l VIDW00ADD0B0 // win0的buffer0起始地址
l VIDW00ADD0B1 // win0的buffer1起始地址
l VIDW00ADD1B0 // win0的buffer0结束地址
l VIDW00ADD1B1 // win0的buffer1结束地址
要实现win0的buffer0/1之间的切换,只需要设置WINCON0寄存器的BUFSEL位即可。显示控制器会根据VIDW00ADD0B0和VIDW00ADD0B1的值,自动切换是使用buffer0还是buffer1作为显示内容。
win1对应的寄存器与win0类似。
代码中对应的切换命令为IOCTL S3CFB_CHANGE_REQ。
Virtual Screen
virtual screen的概念在s3c6410_rev12.pdf的第485页,figure 14-10。通过设定framebuffer的xoffset和yoffset,可以设置framebuffer被LCD显示的x、y坐标。因此,可以定义frame1的坐标为(0,0),frame2的坐标为(0,
在代码中,能改变坐标的IOCTL操作为 FBIOPAN_DISPLAY。
FBIOPAN_DISPLAY通过改变framebuffer的起始地址实现双缓冲,对应的函数为s3cfb_set_fb_addr。这种机制被Android采用。
3. alpha与colorkey
s3c6410支持硬件alpha操作和colorkey操作。
alpha操作用于实现图形渐变效果,以及半透明效果等等。
colorkey操作可以在融合两个窗口时过滤掉其中一个窗口的某一种特定颜色。因为GUI在显示图象时都是通过画矩形实现,所以这个功能在显示非矩形图像(比如圆形)时很有用。假设要显示圆形图案,可以把圆形放进一个矩形,然后矩形的剩余部分填充一个背景色,并把这个背景色指定为colorkey。这样,显示的时候自动将colorkey指定的颜色过滤,屏幕上就能显示出那个圆形了。
不管是alpha操作还是colorkey操作,都有对应的软件模拟实现。网上类似的代码有很多,不再赘述。
4. 窗口平移与virtual screen平移
窗口平移与virtual screen平移是两个容易被混淆的概念,下面简单介绍一下:
窗口平移
s3c6410硬件上支持5个窗口,每一个窗口都可以显示在LCD的不同位置。所以窗口平移就是指硬件支持的窗口在LCD上的移动。
窗口平移由以下寄存器控制:
S3C_VIDOSD[0-4]A
S3C_VIDOSD[0-4]B
在framebuffer的驱动中,可以通过以下IOCTL控制窗口平移:
S3CFB_OSD_MOVE_LEFT
S3CFB_OSD_MOVE_RIGHT
S3CFB_OSD_MOVE_UP
S3CFB_OSD_MOVE_DOWN
另外SET_OSD_INFO也可以用于控制平移。内核中与窗口平移对应的函数为s3cfb_set_win_position。
virtual screen平移
virtual screen的概念在上面介绍双缓冲的地方提到过,具体可查阅芯片手册。这里的平移指的是显示内容的平移,可以想象成通过拖动GUI中的滚动条造成的效果。
virtual screen的平移由寄存器VIDWxxADD[0-1]实现,内核中对应函数为s3cfb_set_fb_addr,用户程序可以通过调用FBIOPAN_DISPLAY控制。
目前s3c6410的framebuffer实现中,窗口平移和virtual screen平移都由fb_var_screeninfo中的xoffset和yoffset控制,所以使用时要小心。另外FBIOPAN_DISPLAY的实现代码中没有考虑x轴平移,只有y轴平移。