Edit online

场景选择

4 Dec 2024
Read time: 5 minute(s)
ArtInChip 平台在进行屏幕旋转时,兼容单 buffer 和双 buffer 的应用程序,可以提供多种屏幕旋转场景供用户选择。各种场景的详细对比说明如下表所示:
1. 屏幕旋转场景对比
场景 优势 劣势
双绘制 buffer 和双显示 buffer 对应用友好,仅需修改 dts 配置即可达成竖屏横用,不需要修改上层应用。 占用的内存资源多,需要 4 块 buf,有一块绘制 buf 是可以节省下来的。720x1280 的屏幕显示 32 位 RGB 数据时,需要约 14M 的物理连续内存。
注: 内存资源来源于 CMA 内存,需要确保 CMA 内存 size 满足需求,不然无法生成 /dev/fb0,详细配置可参看参数配置章节。
单绘制 buffer 和双显示 buffer

能避免显示撕裂现象,能节省下一块绘制 buf。

需要修改应用程序。

单绘制 buffer 和单显示 buffer 占用的内存资源最小

需要手动触发更新,必须修改应用。

只有一块显示 buf,撕裂现象不可避免,只能在一些特定的场景中使用。

本节以一块 720x1280 的屏幕竖屏横用为例进行详细说明。

双绘制 buffer 和双显示 buffer

  1. menuconfig 配置
    Board options  --->
        Graphics Support  --->
            Graphics support
                [*] Display Support
                    [*] Support double framebuffer
                    framebuffer rotation degree (90)  --->
  2. disp_conf.h 头文件配置
    /**
     * FB ROTATION options
     */
    
    /* drawing buf for GUI, range [1, 2] */
    #define AIC_FB_DRAW_BUF_NUM 2
    内存使用情况如下所示:
    +-------------------------+
    |      绘制 buf 0         |
    +-------------------------+
    |      绘制 buf 1         |
    +-----+-------------------+
    |     |
    | 显  |
    | 示  |
    | buf |
    | 0   |
    |     |
    +-----+
    |     |
    | 显  |
    | 示  |
    | buf |
    | 1   |
    |     |
    +-----+

    GUI 在绘制 buf0 绘制完界面后,底层驱动会把数据旋转到显示 buf0 进行显示,绘制 buf1 同理。

注:

显示 buffer 的双 buf 由 menuconfig 中的 Support double framebuffer 选项使能。

单绘制 buffer 和双显示 buffer

disp_conf.h 头文件,将绘制 buf 修改为 1 个,并通过 menuconfig 中的 Support double framebuffer 选项使能显示双 buf。
  1. menuconfig 配置
    Board options  --->
        Graphics Support  --->
            Graphics support
                [*] Display Support
                    [*] Support double framebuffer
                    framebuffer rotation degree (90)  --->
  2. disp_conf.h 头文件配置
    /**
     * FB ROTATION options
     */
    
    /* drawing buf for GUI, range [1, 2] */
    #define AIC_FB_DRAW_BUF_NUM 1
内存使用情况如下所示:
+-------------------------+
|      绘制 buf 0         |
+-----+-------------------+
|     |
| 显  |
| 示  |
| buf |
| 0   |
|     |
+-----+
|     |
| 显  |
| 示  |
| buf |
| 1   |
|     |
+-----+
GUI 在绘制 buf0 绘制完界面后,在调用 ioctl pan_display 时,底层驱动会自动切换显示 buf,避免撕裂现象的发生,GUI 应用程序不需要关注显示 buf 的切换。
int buf_id = 0;
int zero = 0;

if (mpp_fb_ioctl(fbfd, FBIOPAN_DISPLAY, buf_id) == 0) {
    if (mpp_fb_ioctl(fbfd, FBIO_WAITFORVSYNC, &zero) < 0) {
        printf("ioctl FBIO_WAITFORVSYNC fail\n");
        return;
    }
} else {
    printf("pan display err\n");
}

单绘制 buffer 和单显示 buffer

disp_conf.h 头文件中,将绘制 buf 修改为 1 个,并取消 menuconfig 中的 Support doubleframe buffer 选项:
  1. menuconfig 配置
    Board options  --->
        Graphics Support  --->
            Graphics support
                [*] Display Support
                    framebuffer rotation degree (90)  --->
  2. disp_conf.h 头文件配置
    /**
     * FB ROTATION options
     */
    
    /* drawing buf for GUI, range [1, 2] */
    #define AIC_FB_DRAW_BUF_NUM 1
其底层的内存使用情况如下所示:
+-------------------------+
|      绘制 buf 0         |
+-----+-------------------+
|     |
| 显  |
| 示  |
| buf |
| 0   |
|     |
+-----+
注:

因为 Display Engine 无法确定 CPU 绘制完成的时机,所以需要应用使用 ioctl pan_display 去手动触发更新。

GUI 在绘制 buf0 绘制完界面后,需要手工调用 ioctl pan_display 才可以触发显示驱动把数据旋转到显示 buf0。
int buf_id = 0;
int zero = 0;

if (mpp_fb_ioctl(fbfd, FBIOPAN_DISPLAY, buf_id) == 0) {
    if (mpp_fb_ioctl(fbfd, FBIO_WAITFORVSYNC, &zero) < 0) {
        printf("ioctl FBIO_WAITFORVSYNC fail\n");
        return;
    }
} else {
    printf("pan display err\n");
}