Edit online

场景选择

ArtinChip 平台在进行屏幕旋转时,兼容单 buffer 和双 buffer 的应用程序。

双绘制 buffer 和双显示 buffer

&fb0 {
    artinchip,uboot-logo-on=<1>;
    rotation-degress = <270>;
    height-virtual = <1440>;  // 720 * 2

    port {
        fb0_out: endpoint {
            remote-endpoint = <&de0_in>;
        };
    };
};
注:

该场景仅需要设置 rotation-degress (旋转角度)和 height-virtual (内存高度),并且 height-virtual 需要为横屏高度的 2 倍。此时 GUI 会使用双 framebuffer 的方式绘制界面,显示 buf 个数自动适配为 2。

内存使用情况如下所示:

+-------------------------+
|      绘制 buf 0         |
+-------------------------+
|      绘制 buf 1         |
+-----+-------------------+
|     |
| 显  |
| 示  |
| buf |
| 0   |
|     |
+-----+
|     |
| 显  |
| 示  |
| buf |
| 1   |
|     |
+-----+

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

这种使用方式的优缺点如下:

  • 优势

    对应用非常友好,不需要修改上层应用,只修改 dts 配置即可达成竖屏横用。

  • 劣势

    占用的内存资源多,需要 4 块 buf,有一块绘制 buf 是可以节省下来的。720x1280 的屏幕显示 32 位 RGB 数据时,需要约 14M 的物理连续内存。

注:

内存资源来源于 CMA 内存,需要确保 CMA 内存 size 满足需求,不然无法生成 /dev/fb0,详细配置可参看参数配置章节。

单绘制 buffer 和双显示 buffer

&fb0 {
    artinchip,uboot-logo-on=<1>;
    rotation-degress = <270>;
    disp-buf-num = <2>;

    port {
        fb0_out: endpoint {
            remote-endpoint = <&de0_in>;
        };
    };
};
注:

该场景只有 1 块绘制 buf, 不需要设置 height-virtual ,但需要设置 disp-buf-num。

内存使用情况如下所示:
+-------------------------+
|      绘制 buf 0         |
+-----+-------------------+
|     |
| 显  |
| 示  |
| buf |
| 0   |
|     |
+-----+
|     |
| 显  |
| 示  |
| buf |
| 1   |
|     |
+-----+

GUI 绘制完界面,下发 ioctl FBIOPAN_DISPLAY,底层驱动会自动切换显示 buf,避免撕裂现象的发生。GUI 应用程序不需要关注显示 buf 的切换。

这种使用方式能避免 LCD 撕裂,并节省一块绘制 buf,但需要修改应用程序。
struct fb_var_screeninfo var = {0};
int zero = 0;

if (ioctl(fbfd, FBIOGET_VSCREENINFO, &var) < 0) {
    printf("ioctl FBIOGET_VSCREENINFO fail\n");
    return;
}

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

单绘制 buffer 和单显示 buffer

&fb0 {
    artinchip,uboot-logo-on=<1>;
    rotation-degress = <270>;

    port {
        fb0_out: endpoint {
            remote-endpoint = <&de0_in>;
        };
    };
};
注:

该场景只需要指定旋转角度。

其底层的内存使用情况如下所示:
+-------------------------+
|      绘制 buf 0         |
+-----+-------------------+
|     |
| 显  |
| 示  |
| buf |
| 0   |
|     |
+-----+

GUI 在绘制 buf0 绘制完界面后,需要下发 ioctl FBIOPAN_DISPLAY 才可以触发屏幕旋转。

注:

display engine 无法确定 CPU 绘制完成的时机,需要应用手动触发更新。

这种方式优劣如下所示:

  • 优势

    占用的内存资源最小

  • 劣势

    • 需要手动触发旋转,必须修改应用

    • 只有一块显示 buf,撕裂现象不可避免

    struct fb_var_screeninfo var = {0};
    int zero = 0;
    
    if (ioctl(fbfd, FBIOGET_VSCREENINFO, &var) < 0) {
        printf("ioctl FBIOGET_VSCREENINFO fail\n");
        return;
    }
    
    if (ioctl(fbfd, FBIOPAN_DISPLAY, &var) == 0) {
        if (ioctl(fbfd, FBIO_WAITFORVSYNC, &zero) < 0) {
            printf("ioctl FBIO_WAITFORVSYNC fail\n");
            return;
        }
    } else {
        printf("pan display err\n");
    }