FB Q&A

Q1: 使用disp dev0的情况下,FB需要画鼠标和UI,这时如果想做一个表示录像中的红点,要不断闪烁,可以新增fbdev实现吗?

FB在disp dev0上可以通过设置FB_HWLAYER_ID配两个 FB_DEVICE,一个 FB_HWLAYER_ID = 0 ,另一个 FB_HWLAYER_ID = 1,分别对应GOP 0/1,也只有这2个GOP; FB_HWLAYER_ID = 0 这个已经给鼠标使用,FB_HWLAYER_ID = 1已经用来做了一层UI,所以目前情况不能新增fbdev了。这个需求可以通过往buffer写入不同数据来实现,参考drawrect函数接口。

Q2: FB 设定的颜色类型和HDMI设定的颜色类型需一致

  1. fbdev.ini 中的FB_HWLAYER_OUTPUTCOLOR(GOP 输出的颜色空间设定 (0: RGB 1: YUV))

  2. MI_HDMI_Attr_t结构体中的eColorType

    typedef enum
    {
        E_MI_HDMI_COLOR_TYPE_RGB444 = 0,
        E_MI_HDMI_COLOR_TYPE_YCBCR422,
        E_MI_HDMI_COLOR_TYPE_YCBCR444,
        E_MI_HDMI_COLOR_TYPE_YCBCR420,
        E_MI_HDMI_COLOR_TYPE_MAX
    } MI_HDMI_ColorType_e;
    

Q3: 如何调整FB使用的内存空间?

FB的内存使用空间,由config.ini里面的FB_BUFFER_LEN所指定,需要更大的FB内存空间,可通过调节FB_BUFFER_LEN大小(计算单位为:KB)

Q4:设置1366x768@60分辨率时FB报错u32DisplayWidth alignment err,require 8

这是因为FB有硬件限制,FB_WIDTH 要 16/BytesPrePixel 对齐,这里用的ARGB1555格式,所以需要8对齐。

按如下修改即可正常。(注意FB只可以放大不能缩小,所以这里要向下对齐)

MI_FB_DisplayLayerAttr_t stDisplayAttr;
memset(&stDisplayAttr, 0, sizeof(MI_FB_DisplayLayerAttr_t));
stDisplayAttr.u32SetAttrMask = E_MI_FB_DISPLAYLAYER_ATTR_MASK_SCREEN_SIZE |
E_MI_FB_DISPLAYLAYER_ATTR_MASK_BUFFER_SIZE | E_MI_FB_DISPLAYLAYER_ATTR_MASK_DISP_SIZE
| E_MI_FB_DISPLAYLAYER_ATTR_MASK_DISP_POS;
stDisplayAttr.u32Xpos = 0;
stDisplayAttr.u32YPos = 0;
stDisplayAttr.u32dstWidth = width;
stDisplayAttr.u32dstHeight = height;
stDisplayAttr.u32DisplayWidth = width/8*8; //width
stDisplayAttr.u32DisplayHeight = height;
stDisplayAttr.u32ScreenWidth = width;
stDisplayAttr.u32ScreenHeight = height;
stDisplayAttr.eFbColorFmt = E_MI_FB_COLOR_FMT_ARGB1555;
stDisplayAttr.eFbOutputColorSpace = E_MI_FB_OUTPUT_RGB;
if (ioctl(g_fbFd, FBIOSET_DISPLAYLAYER_ATTRIBUTES, &stDisplayAttr))
{
    perror("Error: failed to FBIOSET_DISPLAYLAYER_ATTRIBUTES");
    return;
}

Q5:如何设置FB的分辨率对齐?

宽的对齐方式: 16 / BytesPrePixel ,其中BytesPrePixel 取决于你使用的像素格式 argb1555 BytesPrePixel = 2 , 对齐方式为 (16 / 2 = 8)8字节对齐 argb8888 BytesPrePixel = 4 , 对齐方式为 (16 / 4 = 4)4字节对齐

dst width(stDisplayAttr.u32dstWidth)不需要对齐;displaywidth(stDisplayAttr.u32DisplayWidth)需要对齐,height都不需要对齐。xres需要对齐,yres不需要对齐。

Q6:如何开关UI?

打开UI:echo GUI_SHOW 0 on > /proc/mi_modules/fb/mi_fb0

关闭UI:echo GUI_SHOW 0 off > /proc/mi_modules/fb/mi_fb0

Q7:是否支持两个UI层?

支持。一共支持三个gui层,前两个都是gui + cursor层,后面一个为gui层,具体怎么使用需要进行配置,配置方法请参考api文档说明。

我们默认使用两个:fb0和fb1,其中fb0配置为gui + cursor层,fb1为gui层。

Q8:初始化fb时,报如下错误,画面没有显示。

[MI ERR ]: MI_FB_IMPL_SetCursorAttr[3577]: fb:0 invalid cursor attr(xpos:100, ypos:100, hotSpotX:0, hotSpotY:0, alpha , clrkey , imageinfo<w:256 h:64 pitch:32 clrfmt:6 data:0...

错误原因是因为fb设置鼠标的属性失败,导致后面的fb没有启动起来。日志中的image的w为256,这个数值已经超过了支持标准,修改该参数为64后不再报该错误了。

以下是参数设置不正确的代码示例:

MI_FB_CursorAttr_t stCursorAttr;
stCursorAttr.stCursorImageInfo.u32Width = 256;    //大于128了,需要修改为小于128
stCursorAttr.stCursorImageInfo.u32Height = 64;
......
if (-1 == ioctl(frameBufferFd, FBIOSET_CURSOR_ATTRIBUTE, &stCursorAttr))

{
    printf("set cursor attribute failed\n");
}

注意:fb支持的图标的宽度和高度的最大值为128。

Q9:如何dump FB当前显示的UI?

  1. cp /dev/fb0 /customer/fb0.yuv

  2. dd if=/dev/fb0 of=/customer/fb0.yuv

使用yuv工具查看fb0.yuv就可以看到当前fb画的UI。

Q10:如何修改FB的内存大小?

  1. 进入boot,修改bootargs里面分配给fb的内存大小。如:

    setenv bootargs ubi.mtd=ubia,2048 root=/dev/mtdblock5 
    rootfstype=squashfs ro init=/linuxrc LX_MEM=0x80000000 
    mma_heap=mma_heap_name0,miu=0,sz=0x40000000 mma_heap=mma_heap_fb,miu=0,
    sz=0x1020000 mma_memblock_remove=0 cma=2M mtdparts=nand0:1536k@1280k
    (BOOT),1536k(BOOT_BAK),256k(ENV),5m(KERNEL),5m(RECOVERY),6m(rootfs),1m
    (MISC),109056k(ubia)
    

    只需要修改(sz=0x1020000)数据大小,其它部分的内容不需要修改,修改后保存(saveenv),重启设置生效。

    这样处理的原因是:

    参考kernel\include\uapi\linux\fb.h

    struct fb_fix_screeninfo {
    char id[16]; /* identification string eg "TT Builtin" */
    unsigned long smem_start; /* Start of frame buffer mem */
    /* (physical address) */
    ......
    };
    

    931是使用32位的kernel(950是64位kernel),所以这里smem_start(unsigned long)也是32位地址;而931通过mma分配的是64bit地址,所以要单独layout 一个fb 的mmap heap,目的是让它固定访问在4G (32位)的地址空间内,以保证fb访问正确的地址空间。

  2. 修改/misc/config.ini 中FB_DEVICE_0的 FB_BUFFER_LEN字段的内容,如:

    FB_BUFFER_LEN = 16384
    

    设置成功后,重启生效。

    注意:bootargs中设置的fb的值大小,应该要大于等于/misc/config.ini 配置的所有使用到的fb device的FB_BUFFER_LEN的与所要使用到的cursor的个数 * 128k的和。

    例:

    FB_DEVICE_0的FB_BUFFER_LEN 配置 8M; FB_DEVICE_1的FB_BUFFER_LEN 配置 8M。且在程序中都有使用FB_DEVICE_0和FB_DEVICE_1以及它们对应的FB_CURSOR_0和FB_CURSOR_1

    则bootargs的值则应该设置为:0x1040000 (即:8M + 8M+2*128k)