场景选择
4 Dec 2024
Read time: 4 minute(s)
ArtInChip 平台在进行屏幕旋转时,兼容单 buffer 和双 buffer
的应用程序,可以提供多种屏幕旋转场景供用户选择。各种场景的详细对比说明如下表所示:
场景 | 优势 | 劣势 |
---|---|---|
双绘制 buffer 和双显示 buffer | 对应用友好,仅需修改 dts 配置即可达成竖屏横用,不需要修改上层应用。 | 占用的内存资源多,需要 4 块 buf,有一块绘制 buf 是可以节省下来的。720x1280 的屏幕显示
32 位 RGB 数据时,需要约 14M 的物理连续内存。 注: 内存资源来源于 CMA 内存,需要确保 CMA 内存 size
满足需求,不然无法生成
/dev/fb0,详细配置可参看参数配置章节。 |
单绘制 buffer 和双显示 buffer |
能避免显示撕裂现象,能节省下一块绘制 buf。 |
需要修改应用程序。 |
单绘制 buffer 和单显示 buffer | 占用的内存资源最小 |
需要手动触发更新,必须修改应用。 只有一块显示 buf,撕裂现象不可避免,只能在一些特定的场景中使用。 |
本节以一块 720x1280 的屏幕竖屏横用为例进行详细说明。
双绘制 buffer 和双显示 buffer
仅需要设置 rotation-degress (旋转角度)和 height-virtual (内存高度),且 height-virtual 必须为横屏高度的 2 倍。此时
GUI 会使用双 framebuffer 的方式绘制界面,显示 buf 个数自动适配为
2。
&fb0 {
artinchip,uboot-logo-on=<1>;
rotation-degress = <270>;
height-virtual = <1440>; // 720 * 2
port {
fb0_out: endpoint {
remote-endpoint = <&de0_in>;
};
};
};
内存使用情况如下所示:
+-------------------------+
| 绘制 buf 0 |
+-------------------------+
| 绘制 buf 1 |
+-----+-------------------+
| |
| 显 |
| 示 |
| buf |
| 0 |
| |
+-----+
| |
| 显 |
| 示 |
| buf |
| 1 |
| |
+-----+
GUI 在绘制 buf0 绘制完界面后,底层驱动会把数据旋转到显示 buf0 进行显示,绘制 buf1 同理。
单绘制 buffer 和双显示 buffer
由于只有 1 块绘制 buf,不需要设置 height-virtual ,但需要设置
disp-buf-num。
&fb0 {
artinchip,uboot-logo-on=<1>;
rotation-degress = <270>;
disp-buf-num = <2>;
port {
fb0_out: endpoint {
remote-endpoint = <&de0_in>;
};
};
};
内存使用情况如下所示:
+-------------------------+
| 绘制 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 |
| |
+-----+
注:
因为 Display Engine 无法确定 CPU 绘制完成的时机,所以需要应用使用 ioctl pan_display 去手动触发更新。
GUI 在绘制 buf0 绘制完界面后,需要下发 ioctl FBIOPAN_DISPLAY 才可以触发屏幕旋转。
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");
}