SSD_FrameBuf介绍
1. 概述¶
fbdev用于为显示图形硬件提供一层软件抽象.它代理了显示图形硬件的帧内存,并且提供了一些良好定义的接口让应用软件去访问图形硬件,而不用去关心底层图形硬件的具体控制细节。
访问fbdev通常通过一些特定的设备节点,例如位于/dev
目录下的 /dev/fb*
.
一个简单的framebuffer 使用场景:
3个application 通过fb0这个fb device 节点对framebuffer进行修改,然后由图形硬件将修改之后的内容输出到显示端
2. User’s View of /dev/fb*¶
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
-
mmap /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)这个点的像素。
3. Closer look to /dev/fb*¶
简介提到fbdev代理了图形硬件的显示帧内存,并且提供了一些接口控制这部分内存,对比上文的framebuffer简单应用场景。
下图是framebuffer的memory layout:
-
不同的fbdev的实现,让fbdev代理的图形硬件的显示帧内存(framebuffer)会具备不同的初始属性.有些是可配置的属性(通过ioctl(fb, FBIOGET_VSCREENINFO, &info)获取struct fb_var_screeninfo defined in "linux/fb.h"),有些则是固定属性(通过ioctl(fb, FBIOGET_FSCREENINFO, &info)获取struct fb_fix_screeninfo defined in "linux/fb.h").
-
sstar 平台的初始设定方式参见4.1章节
以上图为例我们需要关注几个主要属性:
-
颜色格式(colorformat)
framebuffer的颜色格式可以通过ioctl(fb, FBIOPUT_VSCREENINFO, &info) 设定,通常我们都是在初始化fbdev的时候就决定好. 对fbdev的用户来说,确定了颜色格式用户就知道如何修改对应pixel的内容。
-
bitsperpixel
一个pixel的宽度,与颜色格式协调的变量,颜色格式确定了pixel的宽度也确定了。
-
xres_virtual/yres_virtual
可通过ioctl FBIOGET_VSCREENINFO/FBIOPUT_VSCREENINFO获取。通常fbdev 代理的framebuffer总大小为:xres_virtual*yres_virtual*bitsperpixel。
-
xres/yres,xoffset/yoffset
(xoffset,yoffset) (xoffset+xres,yoffset+yres) 在framebuffer中标记了一个矩形框,即当前显示的buffer区域.也就是说display buffer 用于显示的有效区域可以是从framebuffer开始地址开始。
为何 display buffer 在 framebuffer内
-
支持不同分辨率的内容.
有时候framebuffer的内存大小在FBDEV初始化的时候已经申请好了. 我们可能需要申请一个能够容纳最大分辨的framebuffer,比如1080p,此时我们使用的display buffer 可能是720p.
-
double buffer.
使用单buffer无法避免画面撕裂的问题,因为你可能总是修改未显示的内容,造成已经被graphic hardware显示的部分和被修改将要显示的部分时空错位。使用双buffer,显示一张display buffer#0,修改另一张显示一张display buffer#1,修改完成之后交换.显示一张display buffer#1,修改另一张显示一张display buffer#0.
4. sstar平台 FBDEV介绍¶
4.1. 初始化¶
使用如下命令加载 fbdev:
insmod fbdev.ko [default_config_path_file=<filename>] [default_reserved_mem_name=<memname>]
参数名 | 默认值 | 功能 | 示例 |
---|---|---|---|
default_config_path_file |
"/config/fbdev.ini" |
用于设置fb配置文件 fbdev.ini 的路径 |
insmod fbdev.ko default_config_path_file=/customer/fbdev.ini |
default_reserved_mem_name |
"fb" |
用于配置 bootlogo 使用的内存区域的名字,以便fb在合适的时机释放 |
insmod fbdev.ko default_reserved_mem_name=fb |
默认情况下,insmod 不带任何参数。相关参数使用上表所示的默认值。
4.2. 配置文件fbdev.ini¶
# FBDEV 将会根据[FB_DEVICE]项目的定义生成fbdev设备节点 # 可以有多个[FB_DEVICE],并生成多个fbdev设备节点 [FB_DEVICE] # 该fbdev使用的gop(graphic hardware) ID FB_HWLAYER_ID = 1 # fbdev的framebuffer使用的gop graphic window ID FB_HWWIN_ID = 0 # deprecated FB_HWLAYER_DST = 3 # 该fbdev的framebuffer使用的颜色格式 # RGB565 = 1 # ARGB4444 = 2 # ARGB8888 = 5 # ARGB1555 = 6 # YUV422 = 9 # I8 = 4 # I4 = 13 # I2 = 14 FB_HWWIN_FORMAT = 5 # 修改Output color,0为RGB,1为YUV FB_HWLAYER_OUTPUTCOLOR = 1 # 该fbdev的framebuffer的初始化xres FB_WIDTH = 1280 # 该fbdev的framebuffer的初始化yres FB_HEIGHT = 720 #在自动获取到当前的显示timing之前,使用的初始化gop输出timing 宽 FB_TIMMING_WIDTH = 1920 #在自动获取到当前的显示timing之前,使用的初始化gop输出timing 高 FB_TIMMING_HEIGHT = 1080 # 如果系统的mmap有layout项目为E_MMAP_ID_FB # 那么FBDEV的framebuffer 将使用此处的内存 FB_MMAP_NAME = E_MMAP_ID_FB # 如果系统的mmap没有为FBDEV layout一块内存 # 那么FBDEV的framebuffer将申请如下长度的内存作为framebuffer # FB_BUFFER_LEN >= xres*yres*bytesperpixel*displayBufCnt FB_BUFFER_LEN = 8192 #unit:Kbyte,4096=4M, fbdev.ko alloc size = FB_BUFFER_LEN*1024 # FBDEV 支持的硬件鼠标配置 [FB_CURSOR] # 鼠标层使用的gop ID FB_HWLAYER_ID = 0 # 鼠标层使用的gop graphic window ID FB_HWWIN_ID = 0 # deprecated FB_HWLAYER_DST = 3 # 鼠标层使用的颜色格式 # RGB565 = 1 # ARGB4444 = 2 # ARGB8888 = 5 # ARGB1555 = 6 # YUV422 = 9 # I8 = 4 # I4 = 13 # I2 = 14 FB_HWWIN_FORMAT = 6 # 修改Output color,0为RGB,1为YUV FB_HWLAYER_OUTPUTCOLOR = 1 # 如果系统的mmap有layout项目为E_MMAP_ID_FB # 那么FBDEV的鼠标层 将使用此处的内存 # 如果系统的mmap没有为FBDEV layout一块内存 # 那么FBDEV的鼠标层将自己申请128K内存 FB_MMAP_NAME = E_MMAP_ID_HW_CURSOR # deprecated,fbdev 设备之间的z order(谁显示在上层或者下层) [LAYER_ZORDER] LAYER_ZORDER0 = 0 LAYER_ZORDER1 = 1 LAYER_ZORDER2 = 2 LAYER_ZORDER3 = 3 LAYER_ZORDER4 = 4
4.3. sstar中的图形硬件(GOP)¶
观察fbdev.ini 的配置文件,看到每一个fbdev都会绑定 一个GOP ID,以及一个GWIN ID.在sstar的某个硬件平台中,可以有多个GOP,同时单个GOP可能可以控制多个graphic window(Gwin),每一个Gwin对应一个framebuffer中的display buffer.具体的GOP/Gwin的数量不同的平台存在差异。
-
GOP/Gwin的叠加顺序
以Takoyaki平台为例,Takoyaki拥有2个GOP,每个gop支持管理1个gwin,如下图所示:
-
GOP之间的差异
GOP之间可能存在设计差异,不同的GOP的用途存在倾向性。以Takoyaki平台为例
-
支持的颜色格式
-
是否支持stretch
-
4.4. Takoyaki DISP_GOP 属性¶
属性 | GOP0 | GOP1 |
---|---|---|
颜色格式 | YUV422 | |
RGB565 | ||
ARGB8888 | ||
ARGB4444 | ARGB4444 | |
ARGB1555 | ARGB1555 | |
I8 | I8 | |
I4 | I4 | |
I2 | I2 | |
缩放 | 不支持缩放.FB_WIDTH==FB_TIMING_WIDTH,FB_HEIGHT==FB_TIMING_HEIGHT | 支持放大,在放大的场景下max(xres)=1280 |
支持GWIN数 | 1 | 1 |
FB_WIDTH对齐 | 16/BytesPerPixel | 16/BytesPerPixel |
alpha0/alpha1 for ARGB1555 | 支持分别设置alpha0/alpha1 | 只支持设置alpha1,alpha0=0x0 |
global alpha | 支持 | 支持 |
colorkey | 支持 | 支持 |
4.5. Ikayaki DISP_GOP 属性¶
属性 | GOP0 |
---|---|
颜色格式 | YUV422 |
缩放 | 支持放大,在放大的场景下max(xres)=1280 |
支持GWIN数 | 1 |
global alpha | 支持 |
FB_WIDTH对齐 | 16/BytesPerPixel |
colorkey | 支持 |
alpha0/alpha1 for ARGB1555 | 只支持设置alpha1,alpha0=0x0 |
RGB565 | |
ARGB8888 | |
ARGB4444 | |
ARGB1555 | |
I8 | |
I4 | |
I2 |
4.6. Tiramisu DISP_GOP 属性¶
注意:Tiramisu有两个video path,GOP0和GOP1对应video path 0,GOP2和GOP3对应video path 1。
属性 | GOP0/GOP2 | GOP1/GOP3 |
---|---|---|
颜色格式 | YUV422 | |
RGB565 | ||
ARGB8888 | ||
ARGB4444 | ARGB4444 | |
ARGB1555 | ARGB1555 | |
I8 | I8 | |
I4 | I4 | |
I2 | I2 | |
缩放 | 不支持缩放. FB_WIDTH == FB_TIMING_WIDTH FB_HEIGHT == FB_TIMING_HEIGHT |
支持放大,在放大的场景下max(xres)=1280 |
支持GWIN数 | 1 | 1 |
FB_WIDTH对齐 | 16/BytesPerPixel | 16/BytesPerPixel |
alpha0/alpha1 for ARGB1555 | 支持分别设置alpha0/alpha1 | 只支持设置alpha1,alpha0=0x0 |
global alpha | 支持 | 支持 |
colorkey | 支持 | 支持 |
5. Interfaces¶
简介提到fbdev定义了一些Interfaces给用户操作framebuffer,这里需要注意的是这些接口的实现程度取决于FBDEV的实现者对linux定义的这部分接口的具体实现程度.通常来讲,针对某些具体的平台不需要实现全部的接口定义。
比如:color map/write&read函数等。因为index color显示效果不如ARGB32,操作framebuff 使用mmap比wirte&read函数更方便。
除此之外,FBDEV的提供者还可以针对特定平台提供专有的控制接口。
接口支持情况表
User Space 操作接口 | 描述 | sstar支持平台 |
---|---|---|
open/fopen/close/fclose | 以文件方式打开/关闭fbdev | all |
write/fwrite/read/fread | 以读写文件的方式读写fbdev | none |
mmap | 将fbdev做内存映射 | all |
iocontrol | fbdev支持iocontrol 的方式放送控制命令 | all |
linux标准iocontrol命令表
iocontrol命令 | 描述 | sstar支持平台 |
---|---|---|
FBIOGET_VSCREENINFO | 获取fbdev的可变信息 | all |
FBIOPUT_VSCREENINFO | 设置fbdev的可变信息 | all |
FBIOGET_FSCREENINFO | 获取fbdev的固定信息 | all |
FBIOPAN_DISPLAY | 平移显示,在修改vinfo的可见区域之后 | all |
FBIOPUTCMAP | 设置fbdev的colormap | none |
FBIOGETCMAP | 获取fbdev的colormap | none |
FBIOGET_CON2FBMAP | 获取console对应的framebuffer | all |
FBIOPUT_CON2FBMAP | 映射console对应的framebuffer | all |
FBIOBLANK | 清空framebuffer | none |
sstar专有 iocontrol 命令表
iocontrol命令 | 描述 | sstar支持平台 |
---|---|---|
FBIOGET_SHOW | 获取fbdev的显示状态 | all |
FBIOSET_SHOW | 设置fbdev的显示状态 | all |
FBIOGET_SCREEN_LOCATION | 获取显示区域在framebuffer中的位置信息 | all |
FBIOSET_SCREEN_LOCATION | 设置显示区域在framebuffer中的位置信息 | all |
FBIOGET_GLOBAL_ALPHA | 获取fbdev的全局alpha和ARGB1555的index alpha信息 | all |
FBIOSET_GLOBAL_ALPHA | 设置fbdev的全局alpha和ARGB1555的index alpha信息 | all |
FBIOGET_COLORKEY | 获取fbdev的colorkey信息 | all |
FBIOSET_COLORKEY | 设置fbdev的colorkey信息 | all |
FBIOGET_DISPLAYLAYER_ATTRIBUTES | 获取fbdev显示相关信息 | all |
FBIOSET_DISPLAYLAYER_ATTRIBUTES | 设置fbdev显示相关信息 | all |
FBIOGET_CURSOR_ATTRIBUTE | 设置fbdev的鼠标信息 | all |
FBIOSET_CURSOR_ATTRIBUTE | 获取fbdev的鼠标信息 | all |