s3c6410 framebuffer分析

本文介绍了s3c6410中的framebuffer,参考代码为Linux2.6.28。网上介绍framebuffer的文章很多,内核代码中也有关于framebuffer的文档,所以本文只介绍一些其它文章较少介绍的部分。

1.     Overview

在嵌入式系统中,会有一块内核空间保存LCD上每一个象素需要被显示的值。系统运行时,CPU的显示控制器会自动从这块内存读取内容,然后发送到LCD显示屏。这块内存就叫作framebuffer。对程序来说,通过修改framebuffer中的内容,就可以控制LCD的显示。

 

LinuxGUI系统都运行在用户空间,不能直接访问内核空间。所以就需要一个framebuffer驱动,将内核空间的framebuffer映射到用户空间,方便GUI的访问。

framebuffer的典型操作如下所示:

l         fd = open(fb, …);

l         ioctl(fb, …);               // 设置framebuffer,比如象素的格式等。

l         pBuffer = mmap(fb, …);    // 映射framebuffer到用户空间

l         。。。                      // 像读写内存一样操作pBuffer

 

 

framebufferLCD接口之间的通路有两种,分别是DMAlocal bus,一般都会将通路设置为DMA以提高性能。设置成DMA时,注意不能用kmalloc分配framebuffer,应使用dma_alloc_writecombine函数分配能被DMA访问的内存空间,对应代码在s3cfb_map_video_memory函数中。

 

s3c6410支持多个层叠窗口(5个),显示的时候,这些窗口会被叠加显示。在这里,framebuffer的概念变成和窗口关联,而不是和LCD显示屏关联。每个窗口对应一个framebuffer,所以,s3c6410中可以有5framebuffer(不考虑硬件双缓冲的情况)。关于窗口的概念在s3c6410的芯片手册中有介绍。

2.     双缓冲

双缓冲是指framebuffer的大小两倍于LCD的大小,可将其称为frame1frame2LCD显示frame1的内容时,GUI在后台绘制frame2LCD显示frame2时,GUI在后台绘制frame1

有多种实现双缓冲的方法,比如硬件切换、virtual screen等。

 

硬件实现

s3c6410的芯片手册中提到它最多支持5个窗口叠加。其中win0win1支持硬件双缓冲。win0对应的寄存器为

l         VIDW00ADD0B0                               // win0buffer0起始地址

l         VIDW00ADD0B1                               // win0buffer1起始地址

l         VIDW00ADD1B0                               // win0buffer0结束地址

l         VIDW00ADD1B1                               // win0buffer1结束地址

要实现win0buffer0/1之间的切换,只需要设置WINCON0寄存器的BUFSEL位即可。显示控制器会根据VIDW00ADD0B0VIDW00ADD0B1的值,自动切换是使用buffer0还是buffer1作为显示内容。

win1对应的寄存器与win0类似。

代码中对应的切换命令为IOCTL S3CFB_CHANGE_REQ

 

Virtual Screen

virtual screen的概念在s3c6410_rev12.pdf的第485页,figure 14-10。通过设定framebufferxoffsetyoffset,可以设置framebufferLCD显示的xy坐标。因此,可以定义frame1的坐标为(0,0)frame2的坐标为(0,<LCD’s yres>)。通过改变x/y的坐标,可以在LCD上切换frame1frame2

在代码中,能改变坐标的IOCTL操作为 FBIOPAN_DISPLAY

 

FBIOPAN_DISPLAY通过改变framebuffer的起始地址实现双缓冲,对应的函数为s3cfb_set_fb_addr。这种机制被Android采用。

3.     alphacolorkey

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控制。

 

目前s3c6410framebuffer实现中,窗口平移和virtual screen平移都由fb_var_screeninfo中的xoffsetyoffset控制,所以使用时要小心。另外FBIOPAN_DISPLAY的实现代码中没有考虑x轴平移,只有y轴平移。

 

你可能感兴趣的:(c,linux,android,video,嵌入式,buffer)