瑞芯微Rockchip开发者社区
直播中

mushenmu

3年用户 732经验值
擅长:可编程逻辑
私信 关注
[经验]

RK3399Pro入门教程(5)图形加速引擎RGA的使用

在 入门教学(1) 中,我们提到了RK自带的RGA核心,可以非常快速的处理二维图像的基本操作,例如
旋转、镜像、缩放、拷贝、剪裁、格式转换等等,那么这篇教学就将详细的说说如何使用。(Android和Linux用法是一致的)

设备节点

RGA的设备节点挂在:
  1. dev/rga

RGA库安装

如果大家不想了解更底层的细节,可以直接安装这个库来使用,我们已经帮大家封装了常用的操作和细节:
  1. sudo dnf install librockchip_rga-devel

Rockchip封装的LinuxRGA库源码 (new)
  1. https://github.com/rockchip-linux/linux-rga

如果想进一步了解RGA,可以研究下Android的Hardware/rockchip/librga来查看寄存器的配置等更详细的调用方式,或者使用该代码调用RGA。

示例代码下载地址
本教学的下载地址:
  1. https://github.com/Jerzha/samples-toybrick-rga.git
注意:
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来提升速度。(库没有提供该功能)


基础使用流程

1. 安装RGA库,详见wiki教学

2. 初始化RGA模块,生成context (多线程需要生成多个context)
  1. RockchipRga *mRga;
    if (!mRga) {
        printf("create rga failed !n");
        abort();
    }
    mRga->ops->initCtx(mRga);

[url=]代码[/url]
3. 设置源(src)和目标(dst)的图片格式、宽高。(需要注意的是,图片格式我们引用Linux V4L2的标准图片格式定义)
  1. 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的接口是不一样的)
  1. mRga->ops->setSrcBufferPtr(mRga, srcBuffer);
    mRga->ops->setDstBufferPtr(mRga, dstBuffer);


如果是fd(fd一般存在于通过drm申请的buffer), 当然这篇教学里用不到。
  1. mRga->ops->setSrcBufferFd(mRga, srcFd)
    mRga->ops->setDstBufferFd(mRga, dstFd);


5. 如果只是拷贝和格式转换的话,那做到第4步就可以了。如果还有旋转剪裁等操作,需要再多设置几个:

旋转:
  1. mRga->ops->setRotate(mRga, RGA_ROTATE_90);  // RGA_ROTATE_180, RGA_ROTATE_270


剪裁:
  1. mRga->ops->setSrcCrop(mRga, crop_x, crop_y, crop_w, crop_h);

(库里提供的就这些。其他功能有需要的话需要自己新增接口了)

6. 插入rga任务队列,开始执行,同步等待返回。
  1. mRga->ops->go(mRga);

该函数单个执行其实用不满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的不连续的虚拟内存操作速度很慢

回帖(1)

jf_49490666

2024-1-5 15:02:30
请问楼主,我使用rga的接口imcvtcolor的时候,发现一个1920*1088的图片将yuv420SP的图片转换成RGB888耗时6ms,但是CPU很高,多线程并行的时候,10个线程能达到300%,但是把颜色转换去掉,10个线程只有不到100%,请问为什么rga会占用CPU资源?
举报

更多回帖

发帖
×
20
完善资料,
赚取积分