| 
 | 
 
 本帖最后由 jefferyzhang 于 2022-5-27 09:56 编辑  
 
 
简介 
 
在 入门教学(1) 中,我们提到了RK自带的RGA核心,可以非常快速的处理二维图像的基本操作,例如 
旋转、镜像、缩放、拷贝、剪裁、格式转换等等,那么这篇教学就将详细的说说如何使用。(Android和Linux用法是一致的) 
 
 
设备节点 
 
RGA的设备节点挂在: 
 
 
RGA库安装 
 
如果大家不想了解更底层的细节,可以直接安装这个库来使用,我们已经帮大家封装了常用的操作和细节: 
- sudo apt install rockchip-rga-dev
 
  
 
Rockchip封装的LinuxRGA库源码 (new) 
 
- https://github.com/rockchip-linux/linux-rga
 
 - https://github.com/airockchip/librga
 
 
  
 
如果想进一步了解RGA,可以研究下Android的Hardware/rockchip/librga来查看寄存器的配置等更详细的调用方式,或者使用该代码调用RGA。 
 
 
示例代码下载地址 
 
本教学的下载地址(已过期): 
- https://github.com/Jerzha/samples-toybrick-rga.git
 
 新RGA教学sample在rga自带目录的sample目录下 
 
注意: 
1. sample地址里包含了rockchip_rga目录,该目录的内容就是dnf安装的librockchip_rga内容的源码,如果您不需要修改源码,可以直接dnf安装就好了 
2. 如果没有交叉编译环境的话,请放在板子上编译 
 
RGA注意事项 
 
1. 16对齐。所有进入rga的图像的宽高需要进行16对齐,例如1920*1080的图像需要对齐成1920*1088。如果没有显式对齐的话,输出依然会是16对齐的,所以多出几个像素的奇怪的宽高,请不要认为是bug。 
2. 可多线程调用来提高利用率 
3. 或者设置回调函数的方式提高利用率(库没有提供回调函数注册) 
4. RGA自带mmu,可以将虚拟地址转换成物理地址使用(IP核只认识物理地址)。当然如果预先知道物理地址,可以关闭mmu来提升速度。(库没有提供该功能) 
 
 
基础使用流程(已过期,请参看新RGA Sample) 
 
1. 安装RGA库,详见wiki教学 
 
2. 初始化RGA模块,生成context (多线程需要生成多个context) 
 
- RockchipRga *mRga;
 
 - if (!mRga) {
 
 -     printf("create rga failed !\n");
 
 -     abort();
 
 - }
 
 - mRga->ops->initCtx(mRga);
 
  
3. 设置源(src)和目标(dst)的图片格式、宽高。(需要注意的是,图片格式我们引用Linux V4L2的标准图片格式定义) 
 
- mRga->ops->setSrcFormat(mRga, V4L2_PIX_FMT_ABGR32, BUFFER_WIDTH, BUFFER_HEIGHT);
 
 - mRga->ops->setDstFormat(mRga, V4L2_PIX_FMT_ABGR32, BUFFER_WIDTH, BUFFER_HEIGHT);
 
  
4. 设置源(src)和目标(dst)图片的地址。(需要注意的是设置虚拟地址或者fd的接口是不一样的) 
 
- mRga->ops->setSrcBufferPtr(mRga, srcBuffer);
 
 - mRga->ops->setDstBufferPtr(mRga, dstBuffer);
 
  
如果是fd(fd一般存在于通过drm申请的buffer), 当然这篇教学里用不到。 
 
- mRga->ops->setSrcBufferFd(mRga, srcFd);
 
 - mRga->ops->setDstBufferFd(mRga, dstFd);
 
  
5. 如果只是拷贝和格式转换的话,那做到第四部就可以了。如果还有旋转剪裁等操作,需要再多设置几个: 
 
旋转: 
- mRga->ops->setRotate(mRga, RGA_ROTATE_90);  // RGA_ROTATE_180, RGA_ROTATE_270
 
  
剪裁: 
- mRga->ops->setSrcCrop(mRga, crop_x, crop_y, crop_w, crop_h);
 
  
(库里提供的就这些。其他功能有需要的话需要自己新增接口了) 
 
6. 插入rga任务队列,开始执行,同步等待返回。 
 
 
该函数单个执行其实用不满RGA,因为在设置和返回结果时候RGA是空闲的。这时候可以通过多线程的调用来让RGA不停的排队工作。 
或者还有一种更高级的方法就是设置回调函数,给RGA添加任务的时候立即返回,然后等RGA执行完毕后回调告诉程序已经结束,代价当然是程序复杂度就会变得很高。 
 
 
结果总结 
 
拷贝一张4096*2160的ARGB图像,如果使用malloc的内存(不连续),RGA拷贝速度是比CPU(有cache情况)慢的,测试代码RGA大概需要60ms。实际使用上RGA作为一个流处理器,并且使用CMA连续内容,速度会快非常多,cpu memcpy需要19ms(因为有cache,所以这个代码测试实际上也不能代表问题)如果是DRM分配的物理地址(连续地址)的话,RGA速度是比CPU快很多的,大概在低于15ms(具体数字还需要写代码测试)就可以完成一次搬运。 
本篇教学只关注于如果教会大家用RGA,我们就不在这里写drm地址分配的问题了。 
 
 
RGA优点: 
1. 不占用CPU资源 
2. DRM/CMA物理内存拷贝和转换速度很快 
 
RGA缺点: 
1. 对malloc的不连续的虚拟内存操作速度很慢 
 
 
 |   
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有帐号?立即注册  
 
x
 
 
 
 
 |