瑞芯微(EASY EAI)RV1126B display
1. DRM技术介绍
EASY-EAI-Nan-TB评估板使用DRM(Direct Rendering Manager)驱动框架实现多应用同时使用同一个显示器的目的。
1.1 显示技术简介
在传统的Linux内核中一般使用fbdev(Frame Buffer)驱动框架管理图形适配器的帧缓冲器,但最初的fb应用层表现得好像单个程序占用了整个显示屏设备,当两个或多个程序试图同时控制相同的硬件时,大多数时候会灾难性地结束。

使用DRM驱动后,所有应用层通过libdrm或其他库函数来使用显示设备,在内核底层,DRM通过管理Buffer队列渲染图形界面,此时处于用户空间的各个应用层均没有fbdev的概念,也不会争抢显存资源。

1.2 libdrm
通过libdrm库操作DRM驱动,是Linux应用的标准做法。在libdrm中,又把drm抽象成【CRTC】、【Encoder】、【Connector】三个对象,它们的特点如下:

1.3 plane
我们从显示设备看到的画面,其实是经过多个plane【叠在一起】合成之后的最终画面。

*注:并不是所有主控都有三层plane,但都会有primary层。想知道某款主控芯片具体有多少个plane,就要去看其对应的规格书。
Linux默认的显示方案:primary一般用作【UI层】,通常用来显示Qt程序或者桌面系统;overlay一般用作【视频层】,通常用来显示解码器输出的视频画面;cursor一般用作鼠标层,仅用于显示鼠标。
但有部分的使用场景,需要用UI盖在【视频层】上面,则可以用下方的void set_uiLayer_on_top(bool onTop);接口实现此需求。
由于直接调用libdrm去控制drm设备的过程过于麻烦且复杂,因此我司针对这种情况封装了一套易用的显示接口,可帮助用户忽略掉复杂的硬件操作,大幅度降低应用程序的开发难度。
1.4 硬件接线说明
本接口需要配合显示设备共同使用,不同显示设备可以参考【相应】的外设使用说明文档。
MIPI-DSI屏:《硬件外设接口(软件组件)/显示输出/MIPI-DSI》
- 快速上手
-
- 开发环境准备
如果您初次阅读此文档,请阅读《入门指南/开发环境准备/Easy-Eai编译环境准备与更新》,并按照其相关的操作,进行编译环境的部署。
在PC端Ubuntu系统中执行run脚本,进入EASY-EAI编译环境,具体如下所示。
cd ~/develop_environment
./run.sh 2404

* 开发环境版本要与开发板【正在运行】的系统版本【一致】。
* 开发板是其它版本的固件,可以修改对应的./run.sh参数(如2204),进入到对应的编译环境;也可以把开发板烧录成与编译环境匹配的固件,具体操作可参考《固件烧录与更新》。
2.2 源码下载以及例程编译
在EASY-EAI编译环境下创建存放源码仓库的管理目录:
cd /opt
mkdir EASY-EAI-Toolkit
cd EASY-EAI-Toolkit
通过git工具,在管理目录内克隆远程仓库
git clone https://github.com/EASY-EAI/EASY-EAI-Toolkit-1126B.git

注:
* 此处可能会因网络原因造成卡顿,请耐心等待。
* 如果实在要在gitHub网页上下载,也要把整个仓库下载下来,不能单独下载本实例对应的目录。
进入到对应的例程目录执行编译操作,具体命令如下所示:
cd EASY-EAI-Toolkit-1126B/Demos/media-display/
./build.sh cpres
注:
* 由于依赖库部署在板卡上,因此交叉编译过程中必须保持/mnt挂载。

注:
* 若使用的是rockit的固件,需要在板卡中补充一下下列库:
sudo apt-get update && sudo apt-get install libdrm-dev -y
2.3 例程运行
通过串口调试或ssh调试,进入板卡后台,定位到例程部署的位置,如下所示:
cd /userdata/Demo/media-display

例程运行命令如下所示:
./test-display
2.4 运行效果
例程运行效果如下所示:

API的详细说明,以及API的调用(本例程源码),详细信息见下方说明。
3. 显示接口API说明
3.1 引用方式
EASY EAI api库位于本仓库的easyeai-api目录中。为方便客户在本地工程中直接调用我们的EASY EAI api库,此处列出工程中需要链接的库以及头文件等,方便用户直接添加。
| 描述 | CMake写法 | Makefile写法 |
| api.cmake | ${media_root}/display/api.cmake ${media_root}/rga/api.cmake | 无 |
| 头文件目录 | ${DISPLAY_INCLUDE_DIRS} ${RGA_INCLUDE_DIRS} | -I ../../easyeai-api/media/display -I ../../easyeai-api/media/rga |
| 源文件目录 | ${RGA_SOURCE_DIRS} | ../../easyeai-api/media/rga |
| 库文件目录 | ${DISPLAY_LIBS_DIRS} | ../../easyeai-api/media/display |
| 库链接参数 | ${DISPLAY_LIBS} ${RGA_LIBS} | -ldisplay -ldrm -lrga -lpthread |
关于用到的RGA部分API,源代码路径为EASY-EAI-Toolkit-1126B/easyeai-api/media/rga/。用户可通过源代码了解接口实现,甚至可对源码进行修改。
而用于显示的部分接口,已经被封装成易用的API接口,相关的接口可以直接查阅EASY-EAI-Toolkit-1126B/easyeai-api/media/display/display.h。具体用法见下方描述:
3.2 初始化plane
函数原型如下所示。
int disp_init(); //初始化overlay层
int uiLayer_init(); //初始化primary层
具体介绍如下所示。
| 函数名:display()、uiLayer_init(); | |
| 头文件 | easyeai-api/media/display/display.h |
| 输入参数 | 无 |
| 返回值 | 0:初始化成功 -1:屏幕硬件初始化失败 -2:plane初始化失败 |
| 注意事项 |
|
3.3 向对应plane提交图像数据
向overlay层提交数据,函数原型如下所示。
void window_commit(void *ptr/*default BGR888*/, int imgWidth, int imgHeight, int imgRotation);
| 函数名:window_commit() | |
| 头文件 | easyeai-api/media/display/display.h |
| 输入参数 | *ptr:待提交图像的数据指针 imgWidth:待提交图像的宽度 imgHeight:待提交图像的高度 imgRotation:需要把待提交图像旋转成什么角度,仅支持:0; HAL_TRANSFORM_ROT_90; HAL_TRANSFORM_ROT_180; HAL_TRANSFORM_ROT_270。 |
| 返回值 | 无 |
| 注意事项 |
|
向primary层提交数据,函数原型如下所示。
void uiLayer_commit(void *ptr/*default BGR888*/, int imgWidth, int imgHeight);
具体介绍如下所示。
| 函数名:uiLayer_commit() | |
| 头文件 | easyeai-api/media/display/display.h |
| 输入参数 | *ptr:待提交图像的数据指针 imgWidth:待提交图像的宽度 imgHeight:待提交图像的高度 |
| 返回值 | 无 |
| 注意事项 |
|
把图像commit上屏幕后,效果如下所示(会进行拉伸):

3.4 释放单层资源
函数原型如下所示。
void disp_release();
void uiLayer_release();
具体介绍如下所示。
| 函数名:disp_release()/uiLayer_release() | |
| 头文件 | easyeai-api/media/display/display.h |
| 输入参数 | 无 |
| 返回值 | 无 |
| 注意事项 | 无 |
3.5 释放所有资源
函数原型如下所示。
void disp_exit(void);
具体介绍如下所示。
| 函数名:disp_exitt() | |
| 头文件 | easyeai-api/media/display/display.h |
| 输入参数 | 无 |
| 返回值 | 无 |
| 注意事项 | 无 |
3.6 把UI层(primary)置顶
函数原型如下所示。
void set_uiLayer_on_top(bool onTop);
具体介绍如下所示。
| 函数名:set_uiLayer_on_top() | ||
| 头文件 | easyeai-api/media/display/display_pro.h | |
| 输入参数 | onTop | true:把UI层置顶 |
| false:把UI层置底 | ||
| 返回值 | 无 | |
| 注意事项 | 无 | |
3.7 设置层间Alpha混合模式
函数原型如下所示。
void set_alpha_blend_mode(int mode);
具体介绍如下所示。
| 函数名:set_alpha_blend_mode() | ||
| 头文件 | easyeai-api/media/display/display_pro.h | |
| 输入参数 | mode | 0:采用预乘模式混合 |
| 1:采用非预乘模式混合 | ||
| 返回值 | 无 | |
| 注意事项 | 无 | |
4. API测试案例
示例代码路径为EASY-EAI-Toolkit-1126B/Demos/media-display/test-display.cpp。
以下为各个API的实际用例。
int main(int argc, char *argv[])
{
if(disp_init()){
fprintf(stderr, "display区域始化失败\n");
return -2;
}
printf("成功初始化display区域,正在显示BGR测试图像...\n");
// 加载图像数据
size_t image_size = 0;
char *pbuf = load_test_image(&image_size);
if (!pbuf) {
return -1;
}
// 把图像显示在窗口里[采用拉伸缩放]
window_commit(pbuf, 720, 1280, 0);
printf("按Ctrl+C退出\n");
// 保持显示
while (1) {
// 可以考虑在这里更新图像内容
sleep(1);
}
free(pbuf);
// disp_release(); //disp_exit();里已经包含了disp_release();动作
disp_exit();
return 0;
}
更多推荐



所有评论(0)