• 8530阅读
  • 0回复

[ 收集][keisuo]framebuffer相关资料整理 [复制链接]

上一主题 下一主题
离线keisuo
 

只看楼主 倒序阅读 楼主  发表于: 2007-05-29
— 本帖被 XChinux 执行加亮操作(2008-07-18) —
1.基于FrameBuffer的图象显示
当Video4Linux使用mmap方式采集图像时,他总是尽最大努力将图像直接显示在屏幕上,但并不一定能够完成,因此一个完整的设备应该具有图像显示的功能,一般来讲,嵌入式Linux下显示一幅图像总共有以下几种方法:
(1)在利用Video4Linux采集图像时,将采集到的图象数据直接放到FrameBuffer的内存映射区中,而Video4Linux也支持这种功能,利用VIDIOCSFBUF和VIDIOCGFBUF这两个ioct1函数,可设置和获得struct video_buffer。但该方法并不是每个图像采集设备都支持。
(2)进图像数据存成各种格式(例如bmp),在各种GUI软件中,均会直接显示不同格式的图像的函数,如MiniGui中的FillBoxWithBitmap函数。
(3)直接将图像数据写入FrameBuffer中。
在这里主要介绍第3种。FrameBuffer设备是运行在Linux控制台上的一个优秀的图形接口,他几乎支持所有的硬件,提供了统一的API接口,很好地实现了硬件无关性,他可以直接操作显存,而且还留有提供图形加速功能的接口,运行时不需要root权限;FrameBuffer的设备节点是/dev/fb*,用户若要使用他,需要在编译内核时选中FrameBuffer,其简单的使用程序如下:


从vinfo和finfo中取得显存起始地址、分辨率、色深等信息,然后根据这些计算出需映射显存的大小。


由此便可直接操作大小为screensize,起始地址为fbp的内存区域,在LCD上直接显示图像、图形、文字等,例如执行memset(fbp,0,screensize)将进行清屏操作。
需要注意的是,对于色深为8位或8位以下的设备,在进行绘图操作前还需要设置合适的调色板,操作调色板要用到fb_camp结构,执行ioctl(fd,FBIOGETCMAP,&old_cmap)将保存调色板信息,执行ioctl(fd,FBIO-PUTCMAP,&new_cmap)将设置新的调色板。
以下介绍如何显示一个象素,这里假设LCD为24位色的。


由此便可逐一显示每个象素,进而显示整幅图像。
2.
目前 L inux 内核支持新的称为 FrameBuffer 的显示驱动
技术。利用这种技术 ,能够很方便的实现视频显示 ,因此在编
译 ARM - L inux 内核时 ,应当将这项特性包括在内。
从应用程序的角度看 ,FrameBuffer 驱动主要使用了两种
数据结构 ,和几种有限的 ioctl 参数控制显示模式。至于视频
数据的读写是通过 mmap ()的方法直接对显存操作。
ioctl ( screen _ f d , FB IO GET _ FSCREEN IN FO , &fix _screeninfo) ;
ioctl ( screen _ f d , FB IO GET _ VSCREEN IN FO , &va r _screeninfo) ;
screen_p t r = (char 3 ) mmap ( . . . . . . ) ;
/ / 循环 3 3 (见上文)
FB IO GET_ FSCREEN IN FO 获得 FrameBuffer 设备无关
的固定信息 ,如显存大小、每行字符数、颜色模式等。而
FB IO GET_VSCREEN IN FO 获得设备无关的可变信息 ,如显示屏的长、宽、颜色深度等 ,需要根据具体应用设置。
3.LCD 实时显示从 ov511 上采集的图像
参考HHARM9-EDU/applications/usbcam2lcd。从摄像头获取bmp位流直接显示
在framebuffer中。此程序图像的采集采用read的方式,注意由于lcd液晶屏显示的
是16bits的RGB图片,所以,ov511输出的图片格式也应该是16bits的RGB图片数
据,宏VIDEO_PALETTE_RGB565定义的就是16bits的RGB数据图片。而linux自
带的ov511驱动中图像采集是32位的,这样采集到的图片显示在lcd上是雪花点。
因此需要修改驱动。 在kernet/driver/usb/目录下有ov511芯片的驱动ov511.c,驱
动里的ov51x_set_default_params函数是设置芯片默认的输出图片的格式,该函数
中的
for (i = 0; i < OV511_NUMFRAMES; i++)
{
ov511->frame.width = ov511->maxwidth;
ov511->frame.height = ov511->maxheight;
ov511->frame.bytes_read = 0;
if (force_palette)
ov511->frame.format = force_palette;
else
ov511->frame.format = VIDEO_PALETTE_RGB24;
ov511->frame.depth = ov511_get_depth(ov511->frame.format);
}
部分语句是主要设置ov511默认输出图片格式的,其中maxwidth和maxheight
设置了图片的最大的宽度和高度。Ifelse语句设置了图片的格式,作如下的修改:
for (i = 0; i < OV511_NUMFRAMES; i++)
{
ov511->frame.width = ov511->maxwidth;
ov511->frame.height = ov511->maxheight;
ov511->frame.bytes_read = 0;
ov511->frame.format = VIDEO_PALETTE_RGB565;
ov511->frame.depth = ov511_get_depth(ov511->frame.format);
}
如果需要,也可以改变图片的默认输出大小。
4.
.通过framebuffer将图像数据直接显示在ARM板所带的液晶上:
打开framebuffer所对应的设备文件:FILE *fd = open("/dev/fb0", O_RDWR);
a. 获取固定的液晶屏幕信息:
if (ioctl(fbfd, FBIOGET_FSCREE NINFO, &finfo))
   perror(“FBIOGET_FSCREENINFO”);
b. 获取可变的液晶屏幕信息:
if (ioctl(fbfd, FBIOGET_VSCREENINFO,&vinfo))
   perror(“FBIOGET_VSCREENINFO”);
c. 将内核中的framebuffer映射到应用程序中:
   screensize = vinfo.xres * vinfo.yres *vinfo.bits_per_pixel / 8;
fbp = (char *)mmap(0, screensize,PROT_READ | PROT_WRITE,MAP_SHARED, fbfd, 0);
d. 将RGB24 格式的图像点拼成RGB565格式的图像点,然后依次显示在液晶屏上,
   画点函数如下:
   void put_pixel(int x, int y,unsigned short c)
   {
      location = (x+vinfo.xoffset) * (vinfo.bits_per_pixel/8) + (y+vinfo.yoffset) *
finfo.line_length;
      *((unsigned short int*)(fbp + location)) = c;
   }
e. 释放对USB摄像头的控制,关闭应用程序中所打开的设备文件即可:
   close(fd);
5.FrameBuffer 是出现在 2.2.xx 内核当中的一种驱动程序接口。这种接口将显示设备抽象为帧缓冲区。用户可以将它看成是显示内存的一个映像,将其映射到进程地址空间之后,就可以直接进行读写操作,而写操作可以立即反应在屏幕上。该驱动程序的设备文件一般是 /dev/fb0、/dev/fb1 等等。比如,假设现在的显示模式是 1024x768-8 位色,则可以通过如下的命令清空屏幕:
$ dd if=/dev/zero of=/dev/fb0 bs=1024 count=768
在应用程序中,一般通过将 FrameBuffer 设备映射到进程地址空间的方式使用,比如下面的程序就打开 /dev/fb0 设备,并通过 mmap 系统调用进行地址映射,随后用 memset 将屏幕清空(这里假设显示模式是 1024x768-8 位色模式,线性内存模式):
int fb;
unsigned char* fb_mem;

fb = open (“/dev/fb0”, O_RDWR);
fb_mem = mmap (NULL, 1024*768, PROT_READ|PROT_WRITE,MAP_SHARED,fb,0);

memset (fb_mem, 0, 1024*768);
FrameBuffer 设备还提供了若干 ioctl 命令,通过这些命令,可以获得显示设备的一些固定信息(比如显示内存大小)、与显示模式相关的可变信息(比如分辨率、象素结构、每扫描线的字节宽度),以及伪彩色模式下的调色板信息等等。
通过 FrameBuffer 设备,还可以获得当前内核所支持的加速显示卡的类型(通过固定信息得到),这种类型通常是和特定显示芯片相关的。比如目前最新的内核(2.4.9)中,就包含有对 S3、Matrox、nVidia、3Dfx 等等流行显示芯片的加速支持。在获得了加速芯片类型之后,应用程序就可以将 PCI 设备的内存I/O(memio)映射到进程的地址空间。这些 memio 一般是用来控制显示卡的寄存器,通过对这些寄存器的操作,应用程序就可以控制特定显卡的加速功能。
PCI 设备可以将自己的控制寄存器映射到物理内存空间,而后,对这些控制寄存器的访问,给变成了对物理内存的访问。因此,这些寄存器又被称为“memio”。一旦被映射到物理内存,Linux 的普通进程就可以通过 mmap 将这些内存 I/O 映射到进程地址空间,这样就可以直接访问这些寄存器了。
当然,因为不同的显示芯片具有不同的加速能力,对memio 的使用和定义也各自不同,这时,就需要针对加速芯片的不同类型来编写实现不同的加速功能。比如大多数芯片都提供了对矩形填充的硬件加速支持,但不同的芯片实现方式不同,这时,就需要针对不同的芯片类型编写不同的用来完成填充矩形的函数。
说到这里,读者可能已经意识到 FrameBuffer 只是一个提供显示内存和显示芯片寄存器从物理内存映射到进程地址空间中的设备。所以,对于应用程序而言,如果希望在 FrameBuffer 之上进行图形编程,还需要完成其他许多工作。举个例子来讲,FrameBuffer 就像一张画布,使用什么样子的画笔,如何画画,还需要你自己动手完成。
6.Qt / Embedded 的底层图形引擎是基于帧缓冲
( Frame-Buffer) ,帧缓冲是出现在 2 . 2 . x 以上内核的版本当中的一
种驱动程序接口。这种接口采用 mmap 系统调用 ,将显示
设备抽象为帧缓冲区。用户可以将它看成是显示内存的
一个映像 ,将其映射到进程地址空间以后 ,就可以直接进
行读写操作了 ,而写操作可以立即反映在屏幕上。帧缓冲
驱动程序是最重要的驱动程序之一 ,正是这个驱动程序才
能使系统屏幕显示内容 ,其实现分为两个方面 :一是对
LCD 及其相关部件的初始化 ,包括画面缓冲区的创建和
对 DMA 通道的设置 ;二是对画面缓冲区的读写 ,具体到
代码为 read ,write 等系统调用接口。
帧缓冲是 Linux 为图形设备提供的一个抽象接口 ,它
允许上层应用程序在图形模式下直接对显示缓冲区进行
读写操作。这种操作是抽象的、统一的。应用程序不必关
心物理显存的位置、换页机制等等具体细节。这些都是由
帧缓冲设备驱动来完成的。帧缓冲设备对应的设备文件
通常为/ dev/ fb031 ,Linux 的帧缓冲设备的驱动主要基于
两个文件 :
1) linux/ include/ linux/ fb . h ;
2) linux/ drivers/ video/ fbmem. c。
帧缓冲设备属于字符设备 ,采用“文件层 - 驱动层”的
接口方式

帧缓冲设备在驱动层所要做的工作仅仅是对 Linux
为帧缓冲的驱动层接口 fb-info 进行初始化 ,然后调用这
两个函数对其注册或注销。帧缓冲设备驱动层接口直接
对 LCD 设备硬件进行操作 ,而 fbmem. c 可以记录和管理
多个底层设备驱动。
文件 fbmem. c 中定义了帧缓冲设备的文件层接口
file- operations 结构体 ,它对应用程序可见 ,该结构体的定
义如下 :
static st ruct file- operations fb-fops =
 {
   owner : THIS- MODUL E ,
   read :fb-read , / 3 读操作 3 /
   write :fb- write , / 3 写操作 3 /
   ioctl :fb-ioctl , / 3 控制操作 3 /
   mmap :fb- mmap ,/ 3 映射操作 3 /
   open :fb- open ,/ 3 打开操作 3 /
   release :fb-release ,/ 3 关闭操作 3 /
 } ;
在这个结构体中功能函数 open ( ) 和 release ( ) 不需要
底层的支持 ,而 read ( ) ,write ( ) ,mmap ( ) 则需要调用 fb-get-fix ( ) ,fb- get- var ( ) ,fb-set- var ( ) (这些函数位于结
构体 fb-info 中指针 fbops 指向的结构体变量中)等与底层
LCD 硬件相关的函数的支持。另一个功能函数是 ioctl () ,
ioctl ()是设备驱动程序中对设备的 I/ O 通道进行管理的
函数 ,应用程序应用 ioctl ()系统调用来调用 fb- get-fix () ,
fb-get- var () ,fb-set- var ( ) 等方法来获得和设置结构体
Fb-info 中 var ,fix 和 cmap 等变量的信息。在 fbmem. c 中
给出了 ioctl ()命令和 fb-info 中结构体 fb-ops 的成员函数
的对应关系如下 :
FB IOGET- VSCREEN INFO fb- get- var
FB IOPU T- VSCREEN INFO fd-set- var
FB IOGET- FSCREEN INFO fb- get-fix
FB IOPU TCMAP fb-set-cmap
FB IOGETCMAP fb- get- cmap
FB IOPAN- DISPLAY fb- pan- display
用户应用程序只需要调用 FB IOXXXX 来操作 LCD
硬件。
[ 此贴被XChinux在2008-07-18 16:44重新编辑 ]
快速回复
限100 字节
 
上一个 下一个