一、定义与功能
帧缓存,也称为帧缓冲存储器,是屏幕所显示画面的一个直接映象,又称为位映射图(Bit Map)或光栅。帧缓存的每一存储单元对应屏幕上的一个像素,整个帧缓存对应一帧图像。Linux中的帧缓存为显示设备提供了一个接口,把显存抽象后的一种设备,允许上层应用程序在图形模式下直接对显示缓冲区进行读写操作。
二、特点
- 抽象性:帧缓存将显存抽象为一种设备,用户不必关心物理显存的位置、换页机制等具体细节,这些由Framebuffer设备驱动来完成。
- 直接性:修改帧缓存中的内容,即表示修改屏幕上的内容,直接操作帧缓存可以直接从显示器上观察到效果。
- 多缓存支持:帧缓存可能包含多个缓存,如颜色缓存、深度缓存、模板缓存等,这些缓存共同作用下形成最终在屏幕上显示的图像。
- 位置灵活性:帧缓存可以在系统存储器(内存)的任意位置,只要是在GPU能够访问的空间范围内,都可以作为帧缓存使用。
三、应用与实现
- 图形绘制与交互:Linux帧缓冲为图形绘制和交互提供了接口,使得我们日常使用电脑时能够看到各种图形界面以及操作系统的反馈。
- 窗口系统:在Linux的桌面系统中,如Xwindow服务器,就是利用帧缓存进行窗口的绘制。
- 硬件抽象:Linux FrameBuffer 本质上只是提供了对图形设备的硬件抽象,开发者可以将FrameBuffer视为一块显示缓存,往其中写入特定格式的数据就意味着向屏幕输出内容。
四、操作方式
在Linux中,帧缓存设备为标准的字符型设备,用户可以通过以下步骤操作帧缓存:
- 打开
/dev/fb0
设备文件。 - 使用
ioctl()
操作取得当前显示屏幕的参数,如屏幕分辨率、每个像素点的比特数。 - 使用
mmap()
函数,将屏幕缓冲区映射到用户空间。 - 映射后就可以直接读/写屏幕缓冲区,进行绘图和图片显示了。
- 使用完帧缓冲设备后需要将其释放。
- 关闭文件。
五、优缺点
优点:
- 提高性能:通过缓存数据,减少读写磁盘的次数,提高系统的性能。
- 减少磁盘磨损:由于减少了读写磁盘的次数,可以延长磁盘的使用寿命。
- 实时性:帧缓存中的内容是实时更新的,能够反映最新的屏幕显示状态。
缺点:
- 内存占用:帧缓存需要占用一定的内存空间,如果缓存数据过多,可能会导致系统内存不足,影响系统的稳定性。
- 数据一致性:在某些情况下,帧缓存中的数据可能与实际显示的数据存在不一致性,需要开发者注意数据同步问题。
void *pmem;
struct fb_var_screeninfo vinf;
int init_fb(char *devname)
{
//1. 打开显示设备
int fd = open(devname, O_RDWR);
if (-1 == fd)
{
perror("fail open fb");
return -1;
}
//2、获取显示设备相关参数 分辨率 位深度
int ret = ioctl(fd, FBIOGET_VSCREENINFO, &vinf);
if (-1 ==ret)
{
perror("fail ioctl");
return -1;
}
printf("xres = %d, yres = %d\n", vinf.xres, vinf.yres);
printf("xres_virtual = %d, yres_virtual = %d\n", vinf.xres_virtual, vinf.yres_virtual);
printf("bits_per_pixel : %d\n", vinf.bits_per_pixel);
size_t len = vinf.xres_virtual * vinf.yres_virtual * vinf.bits_per_pixel/8;
//3, 建立显存和用户空间的映射关系
pmem = mmap(NULL, len, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
if ((void *)-1 == pmem)
{
perror("fail mmap");
return -1;
}
return fd;
}
画点:
void draw_point(int x, int y, unsigned int col)
{
if (x >= vinf.xres || y >= vinf.yres)
{
return ;
}
if (vinf.bits_per_pixel == RGB888_FMT)
{
unsigned int *p = pmem;
*(p + y * vinf.xres_virtual + x) = col;
}
else if (vinf.bits_per_pixel == RGB565_FMT)
{
unsigned short *p = pmem;
*(p + y * vinf.xres_virtual + x) = col;
}
return ;
}