前言

概述

Graphic Framebuffer Group(以下简称GFBG)是数字媒体处理平台提供的管理图像叠加层的模块,它基于Linux Framebuffer实现,在提供Linux Framebuffer基本功能的基础上,还扩展了一些图形层控制功能,如层间Alpha、设置原点等。本文档主要介绍GFBG模块加载和第一次如何开发应用。

说明:

  • 未有特殊说明,SS528V100、SS625V100、SS524V100、SS522V101、与SS626V100完全一致。

  • 未有特殊说明,SS927V100与SS928V100,SS522V100与SS524V100内容完全一致。

产品版本

与本文档相对应的产品版本如下。

产品名称

产品版本

SS928

V100

SS626

V100

SS524

V100

SS522

V100

SS522

V101

SS528

V100

SS625

V100

SS927

V100

读者对象

本文档(本指南)主要适用于以下工程师:

  • 技术支持工程师

  • 软件开发工程师

符号约定

在本文中可能出现下列标志,它们所代表的含义如下。

符号

说明

表示如不避免则将会导致死亡或严重伤害的具有高等级风险的危害。

表示如不避免则可能导致死亡或严重伤害的具有中等级风险的危害。

表示如不避免则可能导致轻微或中度伤害的具有低等级风险的危害。

用于传递设备或环境安全警示信息。如不避免则可能会导致设备损坏、数据丢失、设备性能降低或其它不可预知的结果。

“须知”不涉及人身伤害。

对正文中重点信息的补充说明。

“说明”不是安全警示信息,不涉及人身、设备及环境伤害信息。

修订记录

修订记录累积了每次文档更新的说明。最新版本的文档包含以前所有文档版本的更新内容。

文档版本

发布日期

修改说明

00B01

2025-09-15

第1次临时版本发布。

概述

GFBG简介

Framebuffer(以下简称GFBG)是数字媒体处理平台提供的用于管理叠加图形层的模块,它不仅提供Linux Framebuffer的基本功能,还在Linux Framebuffer的基础上增加层间colorkey、层间colorkey mask、层间Alpha、原点偏移等扩展功能。

体系结构

应用程序基于Linux文件系统使用GFBG。GFBG的体系结构如图1所示。

图 1 GFBG体系结构

应用场景

GFBG可应用于以下场景:

  • MiniGUI窗口系统

    MiniGUI支持Linux Framebuffer。对MiniGUI做少量改动即可移植到芯片上,实现快速移植。

  • 其他的基于Linux Framebuffer的应用程序

    对基于Linux Framebuffer的应用程序不做或做少量改动即可移植到芯片上,实现快速移植。

GFBG与Linux Framebuffer对比

叠加图形层管理

Linux Framebuffer是一个子设备号对应一个显卡,GFBG则是一个子设备号对应一个叠加图形层,GFBG可以管理多个叠加图形层,具体个数和芯片相关。

说明:

  • 对于SS528V100/SS625V100/SS524V100,GFBG最多可以管理4个叠加图形层:图形层0~图形层3(G0~G3),对应的设备文件依次为/dev/fb0 ~ /dev/fb3。 SS528V100/SS625V100/SS524V100支持3个输出设备上可以叠加图形层:高清输出设备0(简称HD0)、高清输出设备1(简称HD1)、标清输出设备0(简称SD0)。4个图形层与这3个输出设备的关系如表1所示。

  • 对于SS522V101,GFBG最多可以管理3个叠加图形层:图形层0、2、3(G0、G2、G3),对应的设备文件依次为/dev/fb0/dev/fb1/dev/fb2。SS522V101支持2个输出设备上可以叠加图形层:高清输出设备0(简称HD0)、标清输出设备0(简称SD0)。3个图形层与输出设备的关系如表2所示。

  • 对于SS928V100,GFBG最多可以管理3个叠加图形层:图形层0、1、3(G0、G1、G3),对应的设备文件依次为/dev/fb0/dev/fb1/dev/fb2。 SS928V100支持2个输出设备上可以叠加图形层:高清输出设备0(简称HD0)、标清输出设备0(简称SD0)。3个图形层与输出设备的关系如表3所示。

  • 对于SS626V100, GFBG最多可以管理5个叠加图形层:图形层0、1、2、3、4(G0、G1、G2、G3、G4),对应的设备文件依次为/dev/fb0 ~ /dev/fb4。5个图形层与3个输出设备的关系如表4所示。

表 1 FB设备文件、图形层以及输出设备的对应关系

FB设备文件

图形层

对应显示设备

/dev/fb0

G0

只能在HD0设备上显示。

/dev/fb1

G1

只能在HD1设备上显示。

/dev/fb2

G2

可动态绑定HD0、HD1、SD0显示,G2为硬件鼠标层,它们总是处在显示设备叠加层的最高层。如HD0上有视频层、G0、G2,则叠加顺序从下到上依次为:视频层、G0、G2。

/dev/fb3

G3

可动态绑定HD0、HD1、SD0显示,G3用作智能画框层。

表 2 FB设备文件、图形层以及输出设备的对应关系

FB设备文件

图形层

对应显示设备

/dev/fb0

G0

只能在HD0设备上显示。

/dev/fb1

G2

可动态绑定HD0、HD1、SD0显示,G2为硬件鼠标层,它们总是处在显示设备叠加层的最高层。如HD0上有视频层、G0、G2,则叠加顺序从下到上依次为:视频层、G0、G2。

/dev/fb2

G3

可动态绑定HD0、HD1、SD0显示, G3用作智能画框层。

表 3 FB设备文件、图形层以及输出设备的对应关系

FB设备文件

图形层

对应显示设备

/dev/fb0

G0

只能在HD0设备上显示。

/dev/fb1

G1

只能在HD1设备上显示。

/dev/fb2

G3

可动态绑定HD0、HD1、SD0显示,G3用作智能画框层。

表 4 FB设备文件、图形层以及输出设备的对应关系

FB设备文件

图形层

对应显示设备

/dev/fb0

G0

只能在HD0设备上显示。

/dev/fb1

G1

只能在HD1设备上显示。

/dev/fb2

G2

可动态绑定HD0、HD1、SD0显示,G2为硬件鼠标层,它们总是处在显示设备叠加层的最高层。如HD0上有视频层、G0、G2,则叠加顺序从下到上依次为:视频层、G0、G2。

/dev/fb3

G3

可动态绑定HD0、HD1显示,G3可用作智能画框层。

/dev/fb4

G4

可动态绑定HD1、SD0、G4可用作智能画框层,可用作标清层。

通过模块加载参数,可以控制GFBG管理其中的一个或多个叠加图形层,并像操作普通文件一样操作叠加图形层。

解决方案差异

解决方案名称

支持的图形层

是否支持压缩

是否支持缩放

绑定关系

软鼠标

SS528V100/SS625V100

G0

支持

支持

G0固定绑定到HD0上

不支持

G1

支持

不支持

G1固定绑定到HD1上

不支持

G2

不支持

不支持

G2可动态绑定HD0、HD1、SD0

不支持

G3

不支持

不支持

G3可动态绑定HD0、HD1、SD0

不支持

SS524V100

G0

支持

支持

G0固定绑定到HD0上

不支持

G1

支持

不支持

G1固定绑定到HD1上

不支持

G2

不支持

不支持

G2可动态绑定HD0、HD1、SD0

不支持

G3

不支持

不支持

G3可动态绑定HD0、HD1、SD0

不支持

SS522V101

G0

支持

支持

G0固定绑定到HD0上

不支持

G2

不支持

不支持

G2可动态绑定HD0、SD0

不支持

G3

不支持

不支持

G3可动态绑定HD0、SD0

不支持

SS928V100

G0

支持

支持

G0固定绑定到HD0上

不支持

G1

不支持

不支持

G1固定绑定到HD1上

不支持

G3

不支持

不支持

G3可动态绑定HD0、SD0

不支持

SS626V100

G0

支持

支持

G0固定绑定到HD0上

不支持

G1

支持

支持

G0固定绑定到HD1上

不支持

G2

不支持

不支持

G2可动态绑定HD0、HD1、SD0

不支持

G3

不支持

不支持

G3可动态绑定HD0、HD1

不支持

G4

不支持

不支持

G4可动态绑定HD1、SD0

不支持

时序控制

Linux Framebuffer提供同步时序、扫描方式、同步信号组织等控制方式(需要硬件支持),将物理显存的内容显示在不同的输出设备(如PC显示器、TV、LCD等)上。目前GFBG不支持同步时序、扫描方式、同步信号组织等控制方式。

标准功能与扩展功能

GFBG支持以下的Linux Framebuffer标准功能:

  • 将物理显存映射(或解除映射)到虚拟内存空间。

  • 像操作普通文件一样操作物理显存。

  • 设置硬件显示分辨率和像素格式,每个叠加图形层的支持的最大分辨率和像素格式可以通过支持能力接口获取。

  • 从物理显存的任何位置进行读、写、显示等操作。

  • 在叠加图形层支持索引格式的情况下,支持设置和获取256色的调色板。

GFBG增加以下的扩展功能:

  • 设置和获取叠加图形层的Alpha值。

  • 设置和获取叠加图形层的colorkey值。

  • 设置当前叠加图形层的起始位置(相对于屏幕原点的偏移)。

  • 设置和获取当前叠加图形层的显示状态(显示/隐藏)。

  • 通过模块加载参数配置GFBG的物理显存大小和管理叠加图形层的数目。

  • 设置和获取抗闪烁功能的状态。

  • 设置和获取预乘模式。

  • 设置和获取压缩模式的状态。

  • 设置/获取图形层刷新类型(0 buffer、1 buffer与2 buffer)。

GFBG不支持以下的Linux Framebuffer标准功能:

  • 设置和获取控制台对应的Linux Framebuffer。

  • 获取硬件扫描的实时信息。

  • 获取硬件相关信息。

  • 设置硬件同步时序。

  • 设置硬件同步信号机制。

图形层刷新类型——FB扩展模式

GFBG为上层用户提供了一套完整的刷新方案,称为FB的扩展模式。在对系统性能、内存、图形显示效果各方面综合衡量的基础上,可根据需要选择合适的刷新方案。目前提供的刷新类型有:

  • 0 buffer(即OT_FB_LAYER_BUF_NONE)

    上层用户的绘制buffer即为显示buffer。该刷新类型可以节省内存消耗,速度也最快,但是用户会看到图形的绘制过程。示意如图1所示。

  • 1 buffer(即OT_FB_LAYER_BUF_ONE)

    显示buffer由GFBG提供,因此需要一定的内存。该刷新类型是对显示效果和内存需求的一种折中考虑。但是会有锯齿。示意如图2所示。

  • 2 buffer

    显示buffer由GFBG提供。和前面的刷新类型相比,其要求内存最多,但图形显示效果最好。示意如图3所示。包含以下:

    • OT_FB_LAYER_BUF_DOUBLE

    • OT_FB_LAYER_BUF_DOUBLE_IMMEDIATE

    两者的区别在于后面的每次刷新操作都要等待到绘制的内容真正显示后才返回。

图 1 0 buffer示意图

图 2 1 buffer示意图

图 3 2 buffer示意图

说明: 上文提到的三个分辨率:画布分辨率(即用户绘制buffer的分辩率)、显存分辨率、屏幕显示分辨率。绘图内容从用户绘制buffer到显示buffer的过程支持缩放,也支持抗闪烁;而从显示buffer到显示设备的过程支持缩放,不支持抗闪,显存分辨率与屏幕显示分辨率默认相同,可以通过FBIOPUT_SCREEN_SIZE接口设置屏幕分辨率。

图形层压缩

图形层压缩功能,即图形层接收由TDE压缩的数据,然后基于压缩数据,进行解压显示。当显示buffer数据不发生变化时,图形层每次都会载入压缩之后的数据进行解压显示。对于开启压缩功能的图形层,能够有效降低总线载入带宽,但是却需要额外分配一帧压缩数据的内存空间。

典型的图形层压缩buffer示意图如图1所示。

图 1 压缩 buffer示意图

压缩功能仅支持在FB扩展刷新模式下,OT_FB_LAYER_BUF_DOUBLE和OT_FB_LAYER_BUF_DOUBLE_IMMEDIATE刷新模式下使用。

相关文档

与本指南相关的文档:《GFBG API参考》

模块加载

原理介绍

某些Linux Framebuffer驱动(如versa)不支持在运行期间更改分辨率、颜色深度、时序等显示属性。对此,Linux系统提供一种机制,允许在内核启动或模块加载时,通过参数将相应选项传递给Linux Framebuffer。可以在内核加载器中配置内核启动参数。GFBG驱动在加载时只能设置物理显存的大小,不允许设置其它选项。

加载GFBG驱动gfbg.ko时必须保证内核中已经加载了标准的Framebuffer驱动fb.ko。如果没有加载,可以先用“modprobe fb”加载fb.ko,然后再加载gfbg.ko。

参数设置

GFBG可配置其管理的叠加图形层物理显存的大小。物理显存大小决定了GFBG可使用的最大物理显存和系统的可设置虚拟分辨率。在加载GFBG驱动时通过参数传递设置物理显存大小,物理显存的大小一经设置就不会改变。

参数video

video=“gfbg:vram0_size:xxx, vram1_size:xxx,…”

说明:

  • 选项之间用逗号“,”隔开。

  • 选项和选项值之间用冒号“:”隔开。

  • 如果某个图层不配置物理显存大小,则系统默认分配为0。

  • vram0_size ~ vram3_size分别对应于叠加图形层0 ~ 叠加图形层3。

其中,vramn_size:xxx表示对叠加图形层n配置xxx K字节的物理显存。

(1) 对于FB标准模式,vramn_size和虚拟分辨率的关系如下:

Vramn_size * 1024 >= xres_virtual * yres_virtual * bpp;

其中:xres_virtual * yres_virtual是虚拟分辨率,bpp是每个像素所占字节数。

(2) 对于FB扩展模式,各个图形层需要的内存大小取决于displaysize的大小、图层像素格式以及刷新模式,具体关系如下:

vramn_size * 1024 >= displaywidth * displayHeight * bpp * BufferMode;

如:图形层0在1280*720 分辨率、ARGB8888格式的2 buffer模式下需要的内存vram0_size = 1280*720*4*2 = 7200 K。

说明: vramn_size必须是PAGE_SIZE(4K byte)的倍数,否则GFBG驱动强制将其设为PAGE_SIZE的倍数,向上取整。

参数softcursor

该参数决定是否启用软鼠标功能。当它的值为“off”时,则软鼠标功能为禁止状态(即硬件鼠标功能可用),否则软鼠标功能启用。模块一旦加载,是否启用软鼠标功能便确定。

说明: SS528V100/SS625V100/SS524V100/SS522V101/SS928V100不支持软鼠标。

参数g_layer_mmz_names

该参数决定各个图形层要用到的内存将从哪个mmz上进行分配。该参数为一个字符串数组,最多允许设置4个值,分别依次对应fb0~fb3。模块一旦加载,各个图形层所要用到的内存在哪个mmz上分配便确定。如果不指定值,则系统默认相应层要用到的内存将在无名的mmz上分配。

  • insmod gfbg.ko g_layer_mmz_names=xxxx,xxxx,xxxx,xxxx video="gfbg:vram0_size:32400,vram1_size:32400,vram2_size:256,vram3_size:4052"

  • 以上4块xxxx字符串分别对应fb0~fb3需要指定的mmz分区名。需要该分区名真实存在才生效,否则内存将在无名的mmz上分配。目前未有客户使用,保留该模块参数功能。

参数默认值

如果加载GFBG驱动时不带任何参数,则系统默认配置的参数值如下。

  • SS528V100

    video="gfbg:vram0_size: 32400,vram1_size: 16200,vram2_size:256,vram3_size: 4052 "

  • SS524V100

    video="gfbg:vram0_size: 32400,vram1_size: 16200,vram2_size:256,vram3_size: 4052 "

  • SS928V100

    video="gfbg:vram0_size: 32400,vram1_size: 16200,vram3_size: 3240 "

  • SS626V100

    video=" gfbg:vram0_size:32400,vram1_size:16200,vram2_size:256,vram3_size:4052,vram4_size:4052 "

用户需要从全局的角度出发配置GFBG需要管理的叠加图形层以及相应的存储空间应从哪个mmz上分配,并且为每个叠加图形层分配适当的显存。

配置举例

配置GFBG管理叠加图形层的示例如下:

说明: GFBG驱动的模块文件为gfbg.ko。

  • 配置GFBG管理一个叠加图形层。

    如果只需要GFBG管理叠加图形层0,且最大虚拟分辨率为720 x 576,用到的像素格式为ARGB1555,则叠加图形层0需要的最小显存为720 x 576 x 2 = 829440 = 810K,配置参数如下:

    insmod gfbg.ko video="gfbg:vram0_size:810, vram2_size:0"。

    如果采用的是double buffer的方式,则需要乘以2,即:

    insmod gfbg.ko video="gfbg:vram0_size:1620, vram2_size:0"。

  • 配置GFBG管理多个叠加图形层。

    如果需要GFBG管理叠加图形层0和叠加图形层1两个叠加层,且最大虚拟分辨率为720 x 576,用到的像素格式为ARGB1555,则两个叠加层需要的最小显存都为720 x 576 x 2 = 829440 = 810K,配置参数如下:

    insmod gfbg.ko video="gfbg:vram0_size:810, vram1_size: 810"

异常情况

配置GFBG时可能出现以下异常情况:如果配置叠加图形层物理显存数据错误,则GFBG将不管理相应的叠加图形层。

第一次开发应用

开发流程

GFBG主要用于显示2D图形(以直接操作物理显存的方式)。

GFBG的开发流程如图1所示。

图 1 GFBG的开发流程

GFBG的开发步骤如下:

  1. 调用VO初始化接口打开VO设备。

  2. 调用open函数打开指定的GFBG设备。

  3. 调用ioctl函数设置GFBG的像素格式以及屏幕高宽等参数(详细内容请参见《GFBG API参考》)。

  4. 调用ioctl函数获取GFBG所分配的物理显存大小、跨度等固定信息。调用ioctl函数也可以使用GFBG提供的层间colorkey、层间colorkey mask、层间alpha、原点偏移等功能。

  5. 调用mmap函数将物理显存映射到虚拟内存空间。

  6. 操作虚拟内存,完成具体的绘制任务。在此步骤可以使用GFBG提供的双缓冲页翻转等功能实现一些绘制效果。

  7. 调用munmap解除显存映射。

  8. 调用close函数关闭设备。

说明: 由于修改虚拟分辨率将改变GFBG的固定信息fb_fix_screeninfo::line_length(跨度),为保证绘制程序能够正确执行,推荐先设置GFBG的可变信息fb_var_screeninfo,再获取GFBG的固定信息fb_fix_screeninfo::line_length。

GFBG各个开发各阶段完成的任务如表1所示。

表 1 GFBG的开发阶段任务表

阶段

任务

初始化阶段

完成显示属性的设置和物理显存的映射。

绘制阶段

完成具体的绘制工作。

终止阶段

完成资源清理工作(步骤6、7)。

注意:此操作必须在ss_mpi_sys_exit之前,因为fb依赖于sys的资源。

实例介绍

本实例利用PAN_DISPLAY连续显示15幅分辨率为640×352的图片,以达到动态显示的效果。

每个文件存储的都是像素格式为ARGB1555的纯数据(不包含附加信息的图像数据)。

【参考代码】

#include <stdio.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <linux/fb.h>
#include "gfbg.h"
 
#define IMAGE_WIDTH     640
#define IMAGE_HEIGHT    352
#define IMAGE_SIZE      (640*352*2)
#define IMAGE_NUM       14
#define IMAGE_PATH      "./res/%d.bits"
 
static struct fb_bitfield g_r16 = {10, 5, 0};
static struct fb_bitfield g_g16 = {5, 5, 0};
static struct fb_bitfield g_b16 = {0, 5, 0};
static struct fb_bitfield g_a16 = {15, 1, 0};
 
int main()
{
    int fd;
    int i;
    struct fb_fix_screeninfo fix;
    struct fb_var_screeninfo var;
    unsigned char *show_screen;
    unsigned char *hide_screen;
    ot_fb_point point = {40, 112};
FILE *fp;
ot_vo_pub_attr stPubAttr = {0};
    char image_name[128];
    
         /*0. open VO device 0 */
/* …… initialize the attributes for stPubAttr */
         ss_mpi_vo_set_pub_attr(0, &stPubAttr);
ss_mpi_vo_enable(0);
 
    /*1. open Framebuffer device overlay 0*/
    fd = open("/dev/fb0", O_RDWR);
    if(fd < 0) {
        printf("open fb0 failed!\n");
        return -1;
    }
 
    /*2. set the screen original position*/
    if (ioctl(fd, FBIOPUT_SCREEN_ORIGIN_GFBG, &point) < 0)
    {
        printf("set screen original show position failed!\n");
        return -1;
    }
 
    /*3. get the variable screen info*/
    if (ioctl(fd, FBIOGET_VSCREENINFO, &var) < 0)
    {
          printf("Get variable screen info failed!\n");
        close(fd);
        return -1;
    }
 
    /*4. modify the variable screen info
          the screen size: IMAGE_WIDTH*IMAGE_HEIGHT 
          the virtual screen size: IMAGE_WIDTH*(IMAGE_HEIGHT*2) 
          the pixel format: ARGB1555
    */
    var.xres = var.xres_virtual = IMAGE_WIDTH;
    var.yres = IMAGE_HEIGHT;
    var.yres_virtual = IMAGE_HEIGHT*2;
    
    var.transp= g_a16;
    var.red = g_r16;
    var.green = g_g16;
    var.blue = g_b16;
    var.bits_per_pixel = 16;
 
    /*5. set the variable screeninfo*/
    if (ioctl(fd, FBIOPUT_VSCREENINFO, &var) < 0)
    {
          printf("Put variable screen info failed!\n");
        close(fd);
        return -1;
    }
    
    /*6. get the fix screen info*/
    if (ioctl(fd, FBIOGET_FSCREENINFO, &fix) < 0)
    {
        printf("Get fix screen info failed!\n");
        close(fd);
        return -1;
    }
 
    /*7. map the physical video memory for user use*/
    show_screen = mmap(NULL, fix.smem_len, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
    hide_screen = show_screen + IMAGE_SIZE;
    memset(show_screen, 0, IMAGE_SIZE);
 
    /*8. load the bitmaps from file to hide screen and set pan display the hide screen*/
    for(i = 0; i < IMAGE_NUM; i++)
    {
        sprintf(image_name, IMAGE_PATH, i);
        fp = fopen(image_name, "rb");
        if(NULL == fp)
        {
            printf("Load %s failed!\n", image_name);
            close(fd);
            return -1;
        }
    
        fread(hide_screen, 1, IMAGE_SIZE, fp);
        fclose(fp);
        usleep(10);
        if(i%2)
        {
            var.yoffset = 0;
            hide_screen = show_screen + IMAGE_SIZE;
        }
        else
        {
            var.yoffset = IMAGE_HEIGHT;
            hide_screen = show_screen;
        }
        
        if (ioctl(fd, FBIOPAN_DISPLAY, &var) < 0)
        {
            printf("FBIOPAN_DISPLAY failed!\n");
            close(fd);
            return -1;
        }
    }
 
    printf("Enter to quit!\n");
getchar();
 
    /*9. close the devices*/
    close(fd);
ss_mpi_vo_disable(0);
 
    return 0;