fbdev用于为显示图形硬件提供一层软件抽象.它代理了显示图形硬件的帧内存,并且提供了一些良好定义的接口让应用软件去访问图形硬件,而不用去关心底层图形硬件的具体控制细节。
访问fbdev通常通过一些特定的设备节点,例如位于/dev目录下的 /dev/fb*.
一个简单的framebuffer 使用场景:
3个application 通过fb0这个fb device 节点对framebuffer进行修改,然后由图形硬件将修改之后的内容输出到显示端
fbdev 目前是一个字符设备,首设备号29,尾设备号标志frame buffer的编号
方便起见, 设备节点会如下生成(数字表示问设备号):
0 = /dev/fb0 First frame buffer
1 = /dev/fb1 Second frame buffer
…
31 = /dev/fb31 32nd frame buffer
fbdev同时也是一个普通的内存设备。这就意味着,你可以读写它的内容。比如:
cp /dev/fb0 myfile
echo -en '\xFF\xFF\xFF\x00' > /dev/fb0
int fb = open("/dev/fb0", O_RDWR);
assert(fb > 0);
struct fb_var_screeninfo info;
assert(0 == ioctl(fb, FBIOGET_VSCREENINFO, &info));
size_t len = 4 * info.xres * info.yres;
uint32_t *buf = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, fb, 0);
assert(buf != MAP_FAILED);
通过给buf[y * info.xres + x] 赋值就可以轻松的修改 (x,y)这个点的像素。
简介提到fbdev代理了图形硬件的显示帧内存,并且提供了一些接口控制这部分内存,对比上文的framebuffer简单应用场景。
下图是framebuffer的memory layout:
framebuffer的颜色格式可以通过ioctl(fb, FBIOPUT_VSCREENINFO, &info) 设定,通常我们都是在初始化fbdev的时候就决定好. 对fbdev的用户来说,确定了颜色格式用户就知道如何修改对应pixel的内容。
一个pixel的宽度,与颜色格式协调的变量,颜色格式确定了pixel的宽度也确定了。
可通过ioctl FBIOGET_VSCREENINFO/FBIOPUT_VSCREENINFO获取。通常fbdev 代理的framebuffer总大小为:xres_virtualyres_virtualbitsperpixel。
(xoffset,yoffset) (xoffset+xres,yoffset+yres) 在framebuffer中标记了一个矩形框,即当前显示的buffer区域.也就是说display buffer 用于显示的有效区域可以是从framebuffer开始地址开始。
有时候framebuffer的内存大小在FBDEV初始化的时候已经申请好了. 我们可能需要申请一个能够容纳最大分辨的framebuffer,比如1080p,此时我们使用的display buffer 可能是720p.
使用单buffer无法避免画面撕裂的问题,因为你可能总是修改未显示的内容,造成已经被graphic hardware显示的部分和被修改将要显示的部分时空错位。使用双buffer,显示一张display buffer#0,修改另一张显示一张display buffer#1,修改完成之后交换.显示一张display buffer#1,修改另一张显示一张display buffer#0.