new/external/linux-rga/docs/Rockchip_FAQ_RGA_CN.md
2025-05-10 21:58:58 +08:00

1478 lines
69 KiB
Markdown
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# RGA FAQ
文件标识RK-PC-YF-404
发布版本V1.1.2
日期2023-06-28
文件密级:□绝密 □秘密 □内部资料 ■公开
**免责声明**
本文档按“现状”提供,瑞芯微电子股份有限公司(“本公司”,下同)不对本文档的任何陈述、信息和内容的准确性、可靠性、完整性、适销性、特定目的性和非侵权性提供任何明示或暗示的声明或保证。本文档仅作为使用指导的参考。
由于产品版本升级或其他原因,本文档将可能在未经任何通知的情况下,不定期进行更新或修改。
**商标声明**
“Rockchip”、“瑞芯微”、“瑞芯”均为本公司的注册商标归本公司所有。
本文档可能提及的其他所有注册商标或商标,由其各自拥有者所有。
**版权所有 © 2022 瑞芯微电子股份有限公司**
超越合理使用范畴,非经本公司书面许可,任何单位和个人不得擅自摘抄、复制本文档内容的部分或全部,并不得以任何形式传播。
瑞芯微电子股份有限公司
Rockchip Electronics Co., Ltd.
地址: 福建省福州市铜盘路软件园A区18号
网址: [www.rock-chips.com](http://www.rock-chips.com)
客户服务电话: +86-4007-700-590
客户服务传真: +86-591-83951833
客户服务邮箱: [fae@rock-chips.com](mailto:fae@rock-chips.com)
---
**读者对象**
本文档(本指南)主要适用于以下工程师:
- 技术支持工程师
- 软件开发工程师
**修订记录**
| **日期** | **版本** | **作者** | **修改说明** |
| ---------- | -------- | -------- | ------------------------------- |
| 2021/06/28 | 1.0.0 | 余乔伟 | 初始版本 |
| 2022/12/21 | 1.1.0 | 余乔伟 | 增加针对multi_rga驱动的异常案例 |
| 2023/02/09 | 1.1.1 | 余乔伟 | 更正文档格式 |
| 2023/06/28 | 1.1.2 | 余乔伟 | 补充Q&A |
---
**目录**
[TOC]
---
## 概述
本文针对于RGA驱动以及用户态接口librga总结RK平台上调用RGA硬件实现OSDOn Screen Display和 GUIGraphics User Interface图形绘制加速功能时遇到的一些常见问题。
---
## 版本说明
### 硬件版本
RGA硬件主要分为三个版本版本RGA1、RGA2、RGA3。具体平台搭载信息、支持功能以及限制条件可以查看 [Rockchip_Developer_Guide_RGA_CN](./Rockchip_Developer_Guide_RGA_CN.md) ——概述 章节。
### 软件版本
以下仅提供常用的版本查询方式,详细的可以查阅 [Rockchip_Developer_Guide_RGA_CN](./Rockchip_Developer_Guide_RGA_CN.md) —— 版本说明 章节。
#### librga
API版本号分为主版本号、次版本号、修订版本号、编译版本号四个等级版本号对应不同程度的功能更新。
- 版本号查询
比较通用的查询方法如下:
```
strings librga.so |grep rga_api |grep version
```
- 更新版本方式
当发现版本不满足要求时,可以通过以下方式获取源码或预编译的库文件。
- github预编译仓库
https://github.com/airockchip/librga
- 百度网盘链接:
https://eyun.baidu.com/s/3jJ9Aiz0
#### RGA driver
驱动版本号分为主版本号、次版本号、修订版本号、编译版本号四个等级版本号对应不同程度的功能更新通常发布的SDK中HAL库与驱动是匹配的librga内部会进行校验版本开发者无需关心该版本。当出现单独更新librga时出现以下报错则须要更新驱动至对应版本即可。
- 版本号查询
不同芯片平台debug节点开启路径不同通常有以下两个路径。
```
cat /sys/kernel/debug/rkrga/driver_version
cat /proc/rkrga/driver_version
```
- 更新版本方式
当发现版本不满足要求时可以通过以下方式获取源码更新kernel。
- 百度网盘链接:
https://eyun.baidu.com/s/3dGhufEL
#### 版本对应关系
使用RGA时需要确认保证当前的运行环境是可以正常工作的下表为常用的librga与驱动版本对应关系。
| librga版本 | 对应驱动 | 硬件支持 |
| ------------- | ------------------------------------------------------------ | ---------------- |
| 无版本号 | 对应SDK内驱动 | RGA1、RGA2 |
| 1.0.0 ~ 1.3.2 | RGA Device Driverkernel - 4.4及以上)<br/>RGA2 Device Driver无版本号或v2.1.0 | RGA1、RGA2 |
| > 1.4.0 | RGA multicore Device Driverv1.2.0及以上) | RGA2、RGA3 |
| > 1.9.0 | RGA Device Driverkernel-4.4及以上)<br/>RGA2 Device Driver无版本号和v2.1.0<br/>RGA multicore Device Driverv1.2.0及以上) | RGA1、RGA2、RGA3 |
通常发布的SDK中是版本是匹配的但是出于一些应用对高版本librga.so的依赖可以使用以下百度网盘链接获取RGA模块代码更新包
https://eyun.baidu.com/s/3i6sbsDR
- update-to-MULTI_RGA
原有驱动为RGA Device Driver、RGA2 Device Driver时使用该更新包更新驱动到RGA multicore Device Driver并更新匹配版本的librga。
- MUTIL_RGA
原有驱动为RGA multicore Device Driver时使用该更新包更新驱动版本并更新匹配版本的librga。
- RGA2
原有驱动为RGA2 Device Driver时使用该更新包更新驱动版本并更新匹配版本的librga。
- RGA1
原有驱动为RGA Device Driver时使用该更新包更新驱动版本并更新匹配版本的librga。
---
## 调试说明
### HAL层运行日志
#### 日志开关
- Android平台
Android平台支持使用属性配置librga是否开启HAL层日志打印
- 开启日志打印:
```shell
setprop vendor.rga.log 1
logcat -s librga
```
- 设置日志等级:
日志等级分为全打印0、DEFAULT1、DEBUG3、INFO4、WRANING5、ERROR6
```
setprop vendor.rga.log_level 6
```
- Linux平台
Linux平台支持通过设置环境变量的方式librga 1.9.0版本以上),开启/关闭HAL层日志打印
- 开启日志打印:
```
export ROCKCHIP_RGA_LOG=1
```
- 设置日志等级:
日志等级分为全打印0、DEFAULT1、DEBUG3、INFO4、WRANING5、ERROR6
```
export ROCKCHIP_RGA_LOG_LEVEL=6
```
#### 日志说明
- 初始化日志
当每个进程首次调用librga时会初始化librga的单例并打印当前的API版本号等信息
```C++
E rockchiprga: rga_api version 1.9.0_[0]
```
当出现驱动版本与librga版本不适配时会打印对应的报错。
> 当驱动版本较低时,会启动兼容模式,并在单例初始化时打印如下日志,这时可以考虑更新驱动到日志提示的版本,也可以继续使用兼容模式运行。
```shell
librga fail to get driver version! Compatibility mode will be enabled.
29 im2d_rga_impl rga_version_below_minimun_range_user_driver(310): The driver may be compatible, but it is best to update the driver to version 1.2.4. You can try to update the SDK or update the <SDK>/kernel/drivers/video/rockchip/rga3 directory individually. current version: librga 1.8.5, driver .
```
> 当librga版本较低时通过imStrError()会返回一些Invalid parameters相关的报错这表明当前的librga版本过低需要更新librga版本。
```
Invalid parameters: invaild GraphicBuffer, can not get fd and virtual address,
```
- 运行日志
```C++
D librga : <<<<-------- print rgaLog -------->>>> //以下部分为传入librga的参数打印。
D librga : src->hnd = 0x0 , dst->hnd = 0x0 , src1->hnd = 0x0 //三个通道src、src1、dst传入的内存句柄的值
D librga : src: Fd = 00 , phyAddr = 0x0 , virAddr = 0xb400007431ed6040 //src通道传入的内存类型对应的值对应为DMA_FD、物理地址、虚拟地址。
D librga : dst: Fd = 00 , phyAddr = 0x0 , virAddr = 0xb400007431b4f040 //dst通道传入的内存类型对应的值对应为DMA_FD、物理地址、虚拟地址。
D librga : src: Fd = -01 , buf = 0xb400007431ed6040, mmuFlag = 1, mmuType = 0 //src通道将配置传递的内存类型对应的值以及是否使能MMU这里HAL层选择虚拟地址传入驱动。
D librga : dst: Fd = -01 , buf = 0xb400007431b4f040, mmuFlag = 1, mmuType = 0 //dst通道将配置传递的内存类型对应的值以及是否使能MMU这里HAL层选择虚拟地址传入驱动。
E librga : blend = 0 , perpixelAlpha = 1 //混合模式以及图像格式是否本身存在Alpha值
D librga : scaleMode = 0 , stretch = 0; //缩放模式RGA1
E librga : rgaVersion = 3.200000 , ditherEn =0 //硬件版本号16阶灰度图Y4dither使能。
D librga : srcMmuFlag = 1 , dstMmuFlag = 1 , rotateMode = 0 //MMU使能标志位旋转模式。
D librga : <<<<-------- rgaReg -------->>>> //以下为配置入驱动的参数打印。
E librga : render_mode=0 rotate_mode=0 //RGA运行模式旋转模式。
E librga : src:[0,b400007431ed6040,b400007431fb7040],x-y[0,0],w-h[1280,720],vw-vh[1280,720],f=0 //src通道的内存、图像参数、格式信息。
E librga : dst:[0,b400007431b4f040,b400007431c30040],x-y[0,0],w-h[1280,720],vw-vh[1280,720],f=0 //dst通道的内存、图像参数、格式信息。
E librga : pat:[0,0,0],x-y[0,0],w-h[0,0],vw-vh[0,0],f=0 //pat/src1通道的内存、图像参数、格式信息由于当前模式没有使用到该通道所以参数均为0。
//以下部分开发者通常不用关心为librga配置入驱动的不同模式的相关参数。
E librga : ROP:[0,0,0],LUT[0] //ROP模式配置LUT表配置
E librga : color:[0,0,0,0,0] //colorkey配置max color, min color, 填充颜色配置(前景色配置,背景色配置,颜色填充配置)
E librga : MMU:[1,0,80000521] //MMU配置
E librga : mode[0,0,0,0] //palette、csc、colorkey配置
E librga : Full CSC : en[0] //full csc使能标志
E librga : gr_color_x [0, 0, 0] //填充颜色配置对应R、G、B的颜色值
```
### 驱动调试节点
#### 调试节点路径
不同的SDK kernel的配置不同通常RGA的调试节点存在在以下两个目录其中一个或者均存在
- 使用默认使能CONFIG_ROCKCHIP_RGA_DEBUG_FS编译选项的kernel。
```
/sys/kernel/debug
```
- 使能ROCKCHIP_RGA_PROC_FS编译选项的kernel。
```
/proc
```
除了默认的开启外也可以根据自己的项目需求修改kernel的编译选项实现自定义RGA调试节点路径。
#### 调试节点名称
不同的驱动上调试节点的名称是不相同的后续更新的驱动中会统一为rkrgargax_debug的名称目前已经弃用。
| 驱动名称 | 调试节点路径 |
| ------------------------------ | ------------ |
| RGA Device Driver | rga_debug |
| RGA2 Device Driver无版本号 | rga2_debug |
| RGA2 Device Driverv2.1.0 | rkrga |
| RGA multicore Device Driver | rkrga |
#### 调试节点功能
##### 概述
- rga_debug/rga2_debug
rga_debug/rga2_debug节点仅支持运行日志开关功能。
- rkrga
该版本调试节点支持运行日志开关、负载查询、版本查询、硬件信息查询、内存/任务管理器状态查询等功能。
##### 运行日志
###### 日志开关
- 运行日志开关节点名称
| 驱动名称 | 调试节点路径 |
| ------------------------------ | --------------- |
| RGA Device Driver | rga_debug/rga |
| RGA2 Device Driver无版本号 | rga2_debug/rga2 |
| RGA2 Device Driverv2.1.0 | rkrga/debug |
| RGA multicore Device Driver | rkrga/debug |
- 调试功能说明
不同的驱动版本调试日志的开关方式是相同的都是对rga/rga2/debug节点进行操作。
以RGA multicore Device Driver为例在对应的目录下可以通过cat节点获取对应功能说明
```shell
/# cd /sys/kerne/debug/rkrga/
/# cat debug
REG [DIS]
MSG [DIS]
TIME [DIS]
INT [DIS]
CHECK [DIS]
STOP [DIS]
help:
'echo reg > debug' to enable/disable register log printing.
'echo msg > debug' to enable/disable message log printing.
'echo time > debug' to enable/disable time log printing.
'echo int > debug' to enable/disable interruppt log printing.
'echo check > debug' to enable/disable check mode.
'echo stop > debug' to enable/disable stop using hardware
```
> echo reg > debug该命令开关 RGA 寄存器配置信息的打印。打开该打印时,将会打印每次 rga 工作寄存器的配置值
>
> echo msg> debug该命令开关 RGA 上层配置参数信息的打印。打开该打印时,上层调用 rga 驱动传递的参数将被打印出来。
>
> echo time> debug该命令开关 RGA 工作耗时信息的打印。打开该打印时将会打印每一次的调用rga 工作的耗时
>
> echo check> debug该命令开关 RGA 内部的测试 case。打开该打印时将会在 RGA 每次工作的时候检查相关的参数,主要是内存的检查,和对齐是否满足要求。若输出如下 log 表示通过检查。若内存存在越界的情况,将会导致内核 crash。可以通过 cash 之前的打印 log 确认是 src 数据的问题还是 dst 数据的问题。
>
> echo stop> debug该命令开关 RGA 的工作状态。开启时rga 将不工作直接返回。用于一些特殊情况下的调式。
>
> echo int> debug该命令开关 RGA 寄存器中断信息的打印。打开该打印时,将会在 RGA 进入中断后打印中断寄存器和状态基础器的当前值。
>
> echo slt> debug该命令让 rga 驱动执行内部 SLT case 测试 rga 硬件是否正常。 若输出日志“rga slt success !!”则表示功能正常。
- 开关调试节点
日志打印的开启与关闭命令是相同的,每次输入命令进行切换状态(开启/关闭可以通过cat debug节点或者输入命令后打印的日志信息“open xxx”或者“close xxx”确认日志打印功能是否如预期般开启或者关闭。
```
echo <cmd> > <节点名>
```
以RGA multicore Device Driver为例开启运行日志 msg
```shell
/# cd /sys/kernel/debug/rkrga/
/# cat debug
REG [DIS]
MSG [DIS]
TIME [DIS]
INT [DIS]
CHECK [DIS]
STOP [DIS]
help:
'echo reg > debug' to enable/disable register log printing.
'echo msg > debug' to enable/disable message log printing.
'echo time > debug' to enable/disable time log printing.
'echo int > debug' to enable/disable interruppt log printing.
'echo check > debug' to enable/disable check mode.
'echo stop > debug' to enable/disable stop using hardware
/# echo msg > debug
/# cat debug
REG [DIS]
MSG [EN]
TIME [DIS]
INT [DIS]
CHECK [DIS]
STOP [DIS]
help:
'echo reg > debug' to enable/disable register log printing.
'echo msg > debug' to enable/disable message log printing.
'echo time > debug' to enable/disable time log printing.
'echo int > debug' to enable/disable interruppt log printing.
'echo check > debug' to enable/disable check mode.
'echo stop > debug' to enable/disable stop using hardware
/# echo msg > debug
/# cat debug
REG [DIS]
MSG [DIS]
TIME [DIS]
INT [DIS]
CHECK [DIS]
STOP [DIS]
help:
'echo reg > debug' to enable/disable register log printing.
'echo msg > debug' to enable/disable message log printing.
'echo time > debug' to enable/disable time log printing.
'echo int > debug' to enable/disable interruppt log printing.
'echo check > debug' to enable/disable check mode.
'echo stop > debug' to enable/disable stop using hardware
```
开启/关闭运行日志时,内核日志会有对应的日志。
```shell
/# echo reg > /sys/kerne/debug/rkrga/debug
/# dmesg -c //For logs opened through nodes, the printing level is KERNEL_DEBUG. You need to run the dmesg command to view the corresponding logs on the serial port or adb.
[ 4802.344683] rga2: open rga2 reg!
/# echo reg > /sys/kernel/debug/rga2_debug/rga2
/# dmesg -c
[ 5096.412419] rga2: close rga2 reg!
```
###### 日志说明
对于RGA的问题调试需要借助日志来确认RGA硬件最终执行的工作当HAL层的参数传入驱动后以下日志将描述着对应的参数。通常我们调试常用到msg、reg和time三种模式。
- msg模式
- RGA Device Driver、RGA2 Device Driver
```
rga2: open rga2 test MSG! //msg日志开启打印。
rga2: cmd is RGA2_GET_VERSION //获取版本号功能每个进程第一次调用librga时会查询硬件版本。
rga2: cmd is RGA_BLIT_SYNC //显示当前传入的工作模式。
rga2: render_mode:bitblt,bitblit_mode=0,rotate_mode:0 //render_mode显示调用接口bitblit_mode为当前混合模式0双通道模式——A+B->B 1三通道模式A+B->Crotate_mode为旋转角度。
rga2: src : y=0 uv=b4000072cc8bc040 v=b4000072cc99d040 aw=1280 ah=720 vw=1280 vh=720 xoff=0 yoff=0 format=RGBA8888 //src通道的图像数据参数y: 如有则为fd的值 uv如有则为虚拟地址的值 vvw * vh + uv aw、ah实宽实高即实际操作图像区域vw、vh虚宽虚高即图像本身大小xoff、yoffx、y方向的偏移量format传入的图像数据格式。
rga2: dst : y=0 uv=b4000072cc535040 v=b4000072cc616040 aw=1280 ah=720 vw=1280 vh=720 xoff=0 yoff=0 format=RGBA8888 //dst通道的图像数据参数。
rga2: mmu : src=01 src1=00 dst=01 els=00 //MMU使能标志0为关闭1为开启。
rga2: alpha : flag 0 mode0=0 mode1=0 //blend相关配置
rga2: blend mode is no blend //blend混合模式
rga2: yuv2rgb mode is 0 //csc模式
rga2: *** rga2_blit_sync proc ***
```
- RGA multicore Device Driver
- 内存管理器日志
```
rga: import buffer info:
rga_common: external: memory = 0xb400007458406000, type = virt_addr
//memory内存的数值type内存类型
rga_common: memory param: w = 1280, h = 720, f = RGBA8888(0x0), size = 0
//w/h/f以图像画布的形式描述内存大小size内存大小
rga_dma_buf: iova_align size = 3686400 //iova对齐后的大小
```
- 任务请求日志
```
rga: Blit mode: request id = 192732 //运行模式以及request id
rga_debugger: render_mode = 0, bitblit_mode=0, rotate_mode = 0
//render_mode显示调用接口bitblit_mode为当前混合模式0双通道模式——A+B->B 1三通道模式A+B->Crotate_mode为旋转角度。
rga_debugger: src: y = 19 uv = 0 v = e1000 aw = 1280 ah = 720 vw = 1280 vh = 720
//src通道的图像数据参数y: 如有则为fd的值 uv如有则为虚拟地址的值 vvw * vh + uv aw、ah实宽实高即实际操作图像区域vw、vh虚宽虚高即图像本身大小。
rga_debugger: src: xoff = 0, yoff = 0, format = 0x0, rd_mode = 1
//xoff、yoffx、y方向的偏移量format传入的图像数据格式rd_mode当前通道读/写数据模式1raster2FBC3tile 16*16
rga_debugger: dst: y=1a uv=0 v=e1000 aw=1280 ah=720 vw=1280 vh=720
//dst通道的图像数据参数
rga_debugger: dst: xoff = 0, yoff = 0, format = 0x0, rd_mode = 1
rga_debugger: mmu: mmu_flag=0 en=0 //MMU使能标志0为关闭1为开启。使用rga_buffer_handle_t调用时禁用该配置由驱动抉择最优配置。
rga_debugger: alpha: rop_mode = 0 //alpha/ROP模式使能
rga_debugger: yuv2rgb mode is 0 //CSC模式
rga_debugger: set core = 0, priority = 0, in_fence_fd = -1
//set_core用户态指定的核心priority用户态指定的优先级in_fence_fd用户态传递的acquire_fence fd
```
- 硬件匹配日志
```
rga_policy: start policy on core = 1
rga_policy: start policy on core = 2
rga_policy: start policy on core = 4 //遍历所有的核心支持情况
rga_policy: RGA2 only support under 4G memory! //对应核心不支持的原因日志
rga_policy: optional_cores = 3 //当前请求可匹配的硬件核心合集
rga_policy: assign core: 1 //匹配后绑定的硬件核心标识
```
- 对应硬件参数日志
```
rga3_reg: render_mode:bitblt, bitblit_mode=0, rotate_mode:0
rga3_reg: win0: y = ffc70000 uv = ffd51000 v = ffd89400 src_w = 1280 src_h = 720
rga3_reg: win0: vw = 1280 vh = 720 xoff = 0 yoff = 0 format = RGBA8888
rga3_reg: win0: dst_w = 1280, dst_h = 720, rd_mode = 0
rga3_reg: win0: rot_mode = 1, en = 1, compact = 1, endian = 0
rga3_reg: wr: y = ff8e0000 uv = ff9c1000 v = ff9f9400 vw = 1280 vh = 720
rga3_reg: wr: ovlp_xoff = 0 ovlp_yoff = 0 format = RGBA8888 rdmode = 0
rga3_reg: mmu: win0 = 00 win1 = 00 wr = 00
rga3_reg: alpha: flag 0 mode0=0 mode1=a0a
rga3_reg: blend mode is no blend
rga3_reg: yuv2rgb mode is 0
```
- reg模式
```c++
rga2: open rga2 reg! //reg日志开启打印。
rga2: CMD_REG //功能寄存器配置
rga2: 00000000 00000000 00000040 000e1040
rga2: 00119440 00000000 00000500 02cf04ff
rga2: 00000000 00000000 00000000 00000000
rga2: 00000000 00000000 00000000 00000040
rga2: 000e1040 00119440 00000500 02cf04ff
rga2: 00000000 00000000 0000ff00 ffffffff
rga2: 00000007 00000000 00000000 00000101
rga2: 07a80000 00000000 07a800e4 00000000
rga2: CSC_REG //full csc寄存器配置
rga2: 00000000 00000000 00000000 00000000
rga2: 00000000 00000000 00000000 00000000
rga2: 00000000 00000000 00000000 00000000
rga2: CMD_READ_BACK_REG //功能寄存器回读值
rga2: 00000000 00000000 00000040 000e1040
rga2: 00119440 00000000 00000500 02cf04ff
rga2: 00000000 00000000 00000000 00000000
rga2: 00000000 00000000 00000000 00000040
rga2: 000e1040 00119440 00000500 02cf04ff
rga2: 00000000 00000000 0000ff00 ffffffff
rga2: 00000007 00000000 00000000 00000101
rga2: 07a80000 00000000 07a800e4 00000000
rga2: CSC_READ_BACK_REG //full csc寄存器回读值
rga2: 00000000 00000000 00000000 00000000
rga2: 00000000 00000000 00000000 00000000
rga2: 00000000 00000000 00000000 00000000
```
- time模式
- rga2
```
rga2: sync one cmd end time 2414 //打印本次工作RGA硬件的耗时单位为us
```
- multi
```
rga3_reg: set cmd use time = 196 //开始处理请求到配置寄存器的耗时
rga_job: hw use time = 554 //硬件启动到硬件中断返回耗时
rga_job: (pid:3197) job done use time = 751 //开始处理请求到请求完成的耗时
rga_job: (pid:3197) job clean use time = 933 //开始处理请求到请求资源处理完毕的耗时
```
##### 版本信息查询
通过以下命令查询当前驱动名称以及驱动版本:
```
/# cat driver_version
RGA multicore Device Driver: v1.2.23
```
##### 负载查询
通过以下命令查询RGA负载情况
```
/# cat load
num of scheduler = 3 //当前搭载硬件核心数
================= load ==================
scheduler[0]: rga3_core0
load = 0% //对应核心负载占比
-----------------------------------
scheduler[1]: rga3_core1
load = 0%
-----------------------------------
scheduler[2]: rga2
load = 0%
-----------------------------------
```
##### 内存管理器查询
通过以下命令查询内存管理器内内存状态:
```
/# cat mm_session
rga_mm dump:
buffer count = 3 //内存管理器内保存的buffer数量
===============================================================
handle = 34 refcount = 1 mm_flag = 0x2 tgid = 3210 //内存句柄、引用计数、内存标识、进程号打印
virtual address:
va = 0xb400007286e1c000, pages = 0x00000000ae081f65, size = 3686400
iova = 0xffc70000, offset = 0x0, sgt = 0x00000000cc976f9e, size = 3686400, map_core = 0x1
//内存信息
---------------------------------------------------------------
handle = 35 refcount = 1 mm_flag = 0x2 tgid = 3210
virtual address:
va = 0xb400007286a95000, pages = 0x000000002f083efc, size = 3686400
iova = 0xff8e0000, offset = 0x0, sgt = 0x0000000062bb1297, size = 3686400, map_core = 0x1
---------------------------------------------------------------
handle = 36 refcount = 1 mm_flag = 0x2 tgid = 3210
virtual address:
va = 0xb40000728670e000, pages = 0x00000000785fef63, size = 3686400
iova = 0xff550000, offset = 0x0, sgt = 0x00000000cdd7688d, size = 3686400, map_core = 0x1
---------------------------------------------------------------
```
##### 任务请求查询
通过以下命令任务管理器内任务请求状态:
```
/# cat request_manager
rga internal request dump:
request count = 1 //任务管理器内任务请求数量
===============================================================
------------------ request: 200073 ------------------
set cmd num: 1, finish job: 0, failed job: 0, flags = 0x0, ref = 2
//任务请求完成情况
cmd dump: //任务请求参数
rotate_mode = 0
src: y = 25 uv = 0 v = e1000 aw = 1280 ah = 720 vw = 1280 vh = 720
src: xoff = 0, yoff = 0, format = 0x0, rd_mode = 1
dst: y=26 uv=0 v=e1000 aw=1280 ah=720 vw=1280 vh=720
dst: xoff = 0, yoff = 0, format = 0x0, rd_mode = 1
mmu: mmu_flag=0 en=0
alpha: rop_mode = 0
yuv2rgb mode is 0
set core = 0, priority = 0, in_fence_fd = -1
```
##### 硬件信息查询
通过以下命令查询当前搭载硬件信息:
```
/# cat hardware
===================================
rga3_core0, core 1: version: 3.0.76831 //搭载核心的硬件版本、支持的功能选项等参数
input range: 68x2 ~ 8176x8176
output range: 68x2 ~ 8128x8128
scale limit: 1/8 ~ 8
byte_stride_align: 16
max_byte_stride: 32768
csc: RGB2YUV 0xf YUV2RGB 0xf
feature: 0x4
mmu: RK_IOMMU
-----------------------------------
rga3_core1, core 2: version: 3.0.76831
input range: 68x2 ~ 8176x8176
output range: 68x2 ~ 8128x8128
scale limit: 1/8 ~ 8
byte_stride_align: 16
max_byte_stride: 32768
csc: RGB2YUV 0xf YUV2RGB 0xf
feature: 0x4
mmu: RK_IOMMU
-----------------------------------
rga2, core 4: version: 3.2.63318
input range: 2x2 ~ 8192x8192
output range: 2x2 ~ 4096x4096
scale limit: 1/16 ~ 16
byte_stride_align: 4
max_byte_stride: 32768
csc: RGB2YUV 0x7 YUV2RGB 0x7
feature: 0x5f
mmu: RGA_MMU
-----------------------------------
```
##### dump运行数据
通过以下命令dump运行数据用于调试可以通过调试节点配置实现将RGA接下来几帧数据写到指定目录下。没有该节点说明当前kernel不支持内核写入写出数据。
- 设置dump数据路径使能dump运行数据时将输出到该文件夹下。
```
/# echo /data/rga_image > dump_path
/# dmesg -c
rga_debugger: dump path change to: /data/rga_image
```
- 设置dump数据帧数。
```
/# echo 1 > dump_image
/# dmesg -c
rga_debugger: dump image 1
.... RGA运行 ....
/# dmesg -c
rga_debugger: dump image to: /data/rga_image/1_core1_src_plane0_virt_addr_w1280_h720_RGBA8888.bin
rga_debugger: dump image to: /data/rga_image/1_core1_dst_plane0_virt_addr_w1280_h720_RGBA8888.bin
/# ls /data/rga_image/
1_core1_dst_plane0_virt_addr_w1280_h720_RGBA8888.bin 1_core1_src_plane0_virt_addr_w1280_h720_RGBA8888.bin
//输入src、输出dst运行图像数据
```
---
## Q & A
本节将较为常见的RGA相关问题以Q&A的形式进行分类介绍如不在本节内的问题请整理相关日志和初步分析的信息提交至redmine平台交由维护RGA模块的工程师处理。
### 性能咨询
**Q1.1**RGA效率如何评估
**A1.1** RGA在执行拷贝时可以通过以下公式进行计算理论耗时该功能仅支持数据的拷贝评估
单次拷贝图像耗时 = 图像宽 × 图像高 / RGA每秒能处理的像素数量
= 图像宽 × 图像高 / RGA每个时钟周期能够处理的像素数量 × RGA频率
例如: 一幅1920 × 1080大小的图像用RGA频率设定为300M做拷贝的理论耗时是
RGA1 1920 × 1080 / 1 × 300000000 = 0.006912s
RGA2 1920 × 1080 / 2 × 300000000 = 0.003456s
RGA3 1920 × 1080 / 3 × 300000000 = 0.002304s
而实际的耗时与使用的内存类型是相关的,不同的传入内存类型效率从高到低是:物理地址 > dma_fd > 虚拟地址。
在系统空载时物理地址的实际耗时约为理论耗时的1.1-1.2倍使用dma_fd的实际耗时约为理论耗时的1.3-1.5倍而使用虚拟地址的实际耗时约为理论耗时的1.8-2.1倍并且受CPU影响较大。通常我们比较建议开发者使用dma_fd作为传入的内存类型在易获取和效率上得到了较好的平衡虚拟地址仅用于学习阶段了解RGA时作为简单易上手的内存类型来使用。
下表为在RK3566上系统空载时不同的RGA频率的实际测试数据。
**测试环境**
| 芯片平台 | RK3566 |
| ----------- | ----------- |
| RGA硬件版本 | RGA2-EHANCE |
| 系统平台 | Android 11 |
| RGA频率 | 300 M |
| CPU频率 | 1.8 Ghz |
| GPU频率 | 800 M |
| DDR频率 | 1056 M |
**测试数据**
| 分辨率 | 内存类型 | 理论耗时us | 实际耗时us |
| ----------- | ------------------------- | -------------- | -------------- |
| 1280 × 720 | GraphicBuffercache | 1,536 | 2,620 |
| 1280 × 720 | GraphicBufferno cache | 1,536 | 2,050 |
| 1280 × 720 | Drm buffercache | 1,536 | 2,190 |
| 1280 × 720 | Physical addressDrm | 1,536 | 2,000 |
| 1920 × 1080 | GraphicBuffercache | 3,456 | 5,500 |
| 1920 × 1080 | GraphicBufferno cache | 3,456 | 4,180 |
| 1920 × 1080 | Drm buffercache | 3,456 | 4,420 |
| 1920 × 1080 | Physical addressDrm | 3,456 | 4,100 |
| 3840 × 2160 | GraphicBuffercache | 13,824 | 21,500 |
| 3840 × 2160 | GraphicBufferno cache | 13,824 | 15,850 |
| 3840 × 2160 | Drm buffercache | 13,824 | 16,800 |
| 3840 × 2160 | Physical addressDrm | 13,824 | 15,600 |
**Q1.2**:理论公式仅提供拷贝的评估方法,那么其他模式如何评估?
**A1.2**目前仅有拷贝的公式可供评估使用其他模式比如缩放、裁剪可以使用两张图像较大的分辨率带入拷贝公式进行计算得到的耗时进行评估通常会根据缩放、裁剪的大小有一定的上下浮动混合等分辨率没有变化的模式耗时约为拷贝模式耗时的1.1-1.2倍。具体实际场景中由于受到DDR带宽影响建议实际评估时以在目标场景中的实际测试数据为准。
**Q1.3**为什么RGA在一些场景中性能表现很差与跑demo时耗时最大能到2倍
**A1.3**因为RGA在目前RK平台中的总线优先级为最低档当带宽资源较为紧张时例如ISP运行多路的场景中RGA由于带宽资源紧张没有办法及时的读写DDR内的数据产生了较大的延迟从而表现为RGA的性能下降。
**Q1.4**RGA的效率不能满足我们产品的需求有什么办法可以提升么
**A1.4**部分芯片的出厂固件的RGA频率并不是最高频率例如3399、1126等芯片RGA的频率最高可以到400M可以通过以下两种方式实现RGA提频
- 通过命令设置(临时修改,设备重启则恢复频率)
> 查询RGA频率
```c++
cat /sys/kernel/debug/clk/clk_summary | grep rga //查询rga频率其中的aclk的频率
```
> 修改RGA频率
```c++
echo 400000000 > /sys/kernel/debug/clk/aclk_rga/clk_rate //400000000修改为想要修改的频率
```
- 修改dts实现修改RGA频率重启后依旧为设置的频率
> 以下示例为RK3288上修改dts中RGA频率的修改方法其他平台可以在对应的dts中进行修改
```
diff --git a/arch/arm/boot/dts/rk3288-android.dtsi b/arch/arm/boot/dts/rk3288-android.dtsi
index 02938b0..10a1dc4 100644
--- a/arch/arm/boot/dts/rk3288-android.dtsi
+++ b/arch/arm/boot/dts/rk3288-android.dtsi
@@ -450,6 +450,8 @@
compatible = "rockchip,rga2";
clocks = <&cru ACLK_RGA>, <&cru HCLK_RGA>, <&cru SCLK_RGA>;
clock-names = "aclk_rga", "hclk_rga", "clk_rga";
+ assigned-clocks = <&cru ACLK_RGA>, <&cru SCLK_RGA>;
+ assigned-clock-rates = <300000000>, <300000000>;
dma-coherent;
};
```
**Q1.5**RGA是否支持通过命令或接口查询当前的RGA硬件利用率负载
**A1.5**RGA multicore Device Driver支持查看硬件负载详情可以参考 **调试说明——驱动调试节点——调试节点功能——负载查询**。
**Q1.6**为什么一些场景使用异步模式调用RGA耗时比同步模式还要慢
**A1.6**RGA Device Driver、RGA2 Device Driver 由于目前librga的异步模式的标识符为打开的设备节点而单例模式的librga一个进程只会打开一个fd所以imsync()是等待该进程所有的异步模式均运行结束后才会返回。而RGA multicore Device Driver引入了fence机制所以是针对单次请求的实时处理不会存在这种问题。
**Q1.7**有些场景使用虚拟地址调用RGA做拷贝耗时比memcpy还要高可有办法优化
**A1.7**通常我们不建议使用虚拟地址调用RGA因为在CPU负载较高的场景下使用虚拟地址调用RGA的效率会大大下降这是因为RGA驱动中虚拟地址转换为物理地址页表这一部分是由CPU来计算的并且本身虚拟地址转换为物理地址页表这个过程本身就很耗时加之虚拟地址通常没有用户态的接口同步cache因此驱动内部针对虚拟地址是每一帧都会强制同步cache的。所以通常我们建议使用物理地址或dma_fd来调用librga。
**Q1.8**为什么当搭载8G DDR时RGA效率较于4G时性能下降严重
**A1.8**由于部分RGA1/RGA2的IOMMU仅支持最大32位的物理地址而RGA Device Driver、RGA2 Device Driver中对于不满足硬件内存要求的调用申请默认是通过swiotlb机制进行访问访问受限制的内存原理上相当于通过CPU将高位内存拷贝至复合硬件要求的低位内存中再交由硬件进行处理处理完毕后再通过CPU将低位内存搬运回目标的高位内存上。因此效率十分低下通常在正常耗时的3-4倍之间浮动并且引入受CPU负载影响。
RGA Multicore Device Driver中针对访问受限制的内存会禁用swiotlb机制直接通过调用失败的方式显示的通知调用者申请合理的内存再调用来保证RGA的高效。通常伴随着以下日志
> HAL层日志
```
RgaBlit(1483) RGA_BLIT fail: Invalid argument
Failed to call RockChipRga interface, please use 'dmesg' command to view driver error log.
```
> 驱动日志:
```
rga_policy: invalid function policy //标识存在无效的参数,这里是指没有硬件能够访问当前请求配置的内存。
rga_job: job assign failed //匹配硬件核心失败
rga_job: failed to get scheduler, rga_job_commit(403)
rga_job: (pid:3524) job clean use time = 19
rga_job: request[282567] task[0] job_commit failed.
rga_job: rga request commit failed!
rga: request[282567] submit failed!
```
> 驱动运行日志:
```
rga_policy: start policy on core = 4
[82116.782252] rga_policy: RGA2 only support under 4G memory!
//标识当前搭载的RGA2核心仅支持4G以内的内存。
[82116.782256] rga_policy: optional_cores = 0
[82116.782258] rga_policy: invalid function policy
[82116.782260] rga_policy: assign core: -1
[82116.782262] rga_job: job assign failed
```
因此针对这种场景建议申请4G以内的内存调用librga常见的分配4G内存方式可以查看以下示例代码
**<librga_souce_path>/samples/allocator_demo/src/rga_allocator_dma32_demo.cpp**
**<librga_souce_path>/samples/allocator_demo/src/rga_allocator_graphicbuffer_demo.cpp**
### 功能咨询
**Q2.1**如何知道我当前的芯片平台搭载的RGA版本以及可以实现的功能
**A2.1**可以查看源码目录下docs文件夹内的[《Rockchip_Developer_Guide_RGA_CN》](./Rockchip_Developer_Guide_RGA_CN.md)中 “概述” 章节了解RGA的版本以及支持信息。
不同系统的源码路径会有所差异librga源码目录路径在不同SDK的路径如下
Android 7.0即以上SDK
hardware/rockchip/librga
Android 7.0以下SDK
hardware/rk29/librga
Linux SDK
external/linux-rga
**Q2.2**如何调用RGA实现硬件加速可有demo可供参考
**A2.2**1). API调用接口可以查询docs目录下[《Rockchip_Developer_Guide_RGA_CN》](./Rockchip_Developer_Guide_RGA_CN.md)中 “应用接口说明” 章节。
2). 演示demo位于samples目录下rga_im2d_demo该演示demo内部实现了RGA大部分的接口通过命令配置实现对应的RGA功能亦可作为一些场景下测试RGA是否正常的工具。建议初次了解RGA的开发者初期可以直接运行demo并查看结果从而了解RGA的实际功能再根据自己的需求在demo中修改参数实现对应功能最终再尝试单独在自己的工程中调用RGA API。
3). 常见应用常见的示例代码在samples目录下
├── **allocator_demo**:内存分配器相关示例代码<br/>
├── **alpha_demo**alpha混合、叠加相关示例代码<br/>
├── **async_demo**:异步模式相关示例代码<br/>
├── **config_demo**:线程全局配置相关示例代码<br/>
├── **copy_demo**:图像搬运、拷贝相关示例代码<br/>
├── **crop_demo**:图像裁剪、拼接相关示例代码<br/>
├── **cvtcolor_demo**:图像格式转换、色域转换相关示例代码<br/>
├── **fill_demo**:图像填充、画框相关示例代码<br/>
├── **mosaic_demo**:马赛克遮盖相关示例代码<br/>
├── **padding_demo**padding相关示例代码<br/>
├── **resize_demo**:图像缩放相关示例代码<br/>
├── **rop_demo**ROP运算相关示例代码<br/>
└── **transform_demo**:图像变换相关示例代码<br/>
**Q2.3**RGA的支持信息
**Q2.3.1**RGA支持哪些格式
**A2.3.1**:具体支持情况可以查看[《Rockchip_Developer_Guide_RGA_CN》](./Rockchip_Developer_Guide_RGA_CN.md)中 “概述”——“图像格式支持”小节中查询对应的芯片版本搭载的RGA的格式支持情况也可以在代码中调用**querystring(RGA_INPUT_FORMAT | RGA_OUTPUT_FORMAT);** 接口查询当前硬件的输入输出格式支持情况。
**Q2.3.2**RGA支持的缩放倍率是多少
**A2.3.2**:具体支持情况可以查看[《Rockchip_Developer_Guide_RGA_CN》](./Rockchip_Developer_Guide_RGA_CN.md)中 “概述”——“设计指标”小节中查询对应的芯片版本搭载的RGA支持的缩放倍率也可以在代码中调用**querystring(RGA_SCALE_LIMIT);** 接口查询当前硬件的支持的缩放倍率。
**Q2.3.3**RGA支持的最大分辨率是多少
**A2.3.3**:具体支持情况可以查看[《Rockchip_Developer_Guide_RGA_CN》](./Rockchip_Developer_Guide_RGA_CN.md)中 “概述”——“设计指标”小节中查询对应的芯片版本搭载的RGA支持的最大输入输出分辨率也可以在代码中调用**querystring(RGA_MAX_INPUT | RGA_MAX_OUTPUT);** 接口查询当前硬件的支持的最大输入输出分辨率。
**Q2.3.4**RGA对不同的格式对齐要求是什么
**A2.3.4**:具体支持情况可以查看[《Rockchip_Developer_Guide_RGA_CN》](./Rockchip_Developer_Guide_RGA_CN.md)中 “概述”——“图像格式对齐说明”小节中查询对应的芯片版本搭载的RGA对不同格式的对齐要求。
**A2.3**总体来说对于RGA的支持有疑问可以查看[《Rockchip_Developer_Guide_RGA_CN》](./Rockchip_Developer_Guide_RGA_CN.md)其中对于RGA的支持信息会有较详细的介绍。
**Q2.4**多个版本的librga有何差异又该如何分辨
**A2.4**目前的RK平台所有发布SDK中主要分配无法获取版本号的旧版本librga支持查询版本号的新版本librga。
无法获取版本的旧版本librga目前已经停止支持与维护主要的表征点为2020年11月前发布的SDK中搭载的均为旧版本librga部分芯片平台例如RK3399 Linux SDK 2021年6月前发布的SDKV2.5即以下亦为旧版本librga该版本librga无法完美契合较新的驱动可能会出现颜色偏差、格式异常等问题不建议混合使用如果有需要使用到较新内核时建议更新新版本librga反之使用到新版本librga亦然需要更新内核至匹配。
支持查询版本号新版本librga是目前主要支持与维护的版本主要表征点为源码目录下增加 **im2d_api** 目录该版本集成与旧版本librga并推出简单易用的IM2D API亦可称呼为IM2D版librga。新版本librga不仅支持新的IM2D API旧版本的RockchipRga接口和C_XXX接口也是支持的。具体的API调用说明可以查看[《Rockchip_Developer_Guide_RGA_CN》](./Rockchip_Developer_Guide_RGA_CN.md)了解。
通常对于一些新旧版本librga功能支持情况一般优先建议更新整体SDK避免出现依赖问题强烈不建议新版本librga搭配旧驱动或者旧版本librga搭配新内核使用部分场景会有较明显的错误。
**Q2.5**RGA是否有对齐限制
**A2.5**不同的格式对齐要求不同RGA硬件本身是对图像每行的数据是按照字world对齐的方式进行取数的即4个字节32个bit。例如RGBA格式本身单个像素存储大小为324 × 8bit所以没有对齐要求RGB565格式存储大小为165 + 6 +5bit所以需要2对齐RGB888格式存储大小为248 × 3bit所以该格式需要4对齐才能满足RGA硬件的32bit取数要求YUV格式存储相对较为特殊本身排列要求需要2对齐Y通道单像素存储大小为8bitUV通道根据420/422决定每四个像素的存储大小所以YUV格式Y通道需要4对齐才能满足RGA的硬件取数要求则YUV格式需要4对齐其他的未提及的格式对齐要求原理相通。注意该题中对齐均指width stride的对齐要求YUV格式本身实际宽高、偏移量由于格式本身特性也是要求2对齐的。具体对齐限制可以查看[《Rockchip_Developer_Guide_RGA_CN》](./Rockchip_Developer_Guide_RGA_CN.md)中 “概述” —— “图像格式对齐说明”小节。
**Q2.6**RGA能否支持一次绘制多个矩形区域或执行多次操作RGA的工作原理
**A2.6**RGA 在硬件上只能顺序工作即配置的一个任务工作结束和进行下一个配置的工作。因此不能一次绘制多个矩形区域,可以通过 async 模式把需要 RGA 做的工作往底层驱动配置RGA 会将工作存储在驱动自己管理的一个工作队列中按顺序完成。当上层需要处理这块 buffer 时再调用 **imsync()** 来确定 RGA 硬件是否已经完成工作。
在librga 1.9.0版本后增加尾缀为array的接口支持配置多个矩形区域进行划线、画框、填充矩形等操作例如imfillArray、imrectangleArray详细可以查看[《Rockchip_Developer_Guide_RGA_CN》](./Rockchip_Developer_Guide_RGA_CN.md)中 “应用接口” —— “图像颜色填充、边框绘制”小节。
**Q2.7**RGA的fill功能可否支持YUV格式
**A2.7**旧版本的librga是不支持的只有新版本的librga在包含以下提交以后的librga版本是支持的。如若没有该提交请尝试更新SDK至最新版。
```
commit 8c526a6bb9d0e43b293b885245bb53a3fa8ed7f9
Author: Yu Qiaowei <cerf.yu@rock-chips.com>
Date: Wed Dec 23 10:57:28 2020 +0800
Color fill supports YUV format as input source.
Signed-off-by: Yu Qiaowei <cerf.yu@rock-chips.com>
Change-Id: I0073c31d770da513f81b9b64e4c27fee2650f30b
```
该功能与RGB颜色填充调用一致通过配置需要填充色彩的RGB值填充色彩不同的是输出结果可以设置为YUV格式。
**Q2.8**RGA支持YUYV格式么
**A2.8**旧版本的librga此处指2020年10月份前发布的SDK中的librga是不支持的只有新版本的librga源码目录下有 **im2d_api** 目录的版本在包含以下提交以后的librga版本是支持的。如若没有该提交请尝试更新SDK至最新版。
```
commit db278db815d147c0ff7a80faae0ea795ceffd341
Author: Yu Qiaowei <cerf.yu@rock-chips.com>
Date: Tue Nov 24 19:50:17 2020 +0800
Add support for Y4/YUV400/YUYV in imcheck().
Signed-off-by: Yu Qiaowei <cerf.yu@rock-chips.com>
Change-Id: I3cfea7c8bb331b65b5bc741956da47924eeda6e1
```
**Q2.9**RGA支持灰度图输入输出做缩放么
**A2.9**旧版本的librga此处指2020年10月份前发布的SDK中的librga是不支持的只有新版本的librga源码目录下有 **im2d_api** 目录的版本1.2.2版本才支持灰度图输入。如若librga版本低于该版本请尝试更新SDK至最新版。由于RGA硬件本身不支持灰度图格式这里灰度图使用的格式是 **RK_FORMAT_Y400** 表征为没有UV通道的YUV格式仅有Y通道的YUV便是256阶的灰度图。
由于是YUV格式这里需要注意色域空间的问题librga中CSC 转YUV格式时默认为BT.601 limit range而limit range的Y通道并不是0~255涉及到CSC转换RGB转YUV输出为Y400格式时需要注意色域空间的转换时配置full range的标识。
**Q2.10**为什么RK3399上ROP的代码放到RV1126上执行却没有对应的效果
**A2.10**虽然RK3399和RV1126上搭载的RGA均为RGA2-ENHANCE但是他们的小版本是不同的ROP功能在RV1126上被裁剪掉了具体功能支持情况可以查看[《Rockchip_Developer_Guide_RGA_CN》](./Rockchip_Developer_Guide_RGA_CN.md)或者在代码中调用 **querystring(RGA_FEATURE)** 接口实现查询支持功能。
**Q2.11**使用RGA其他功能正常仅在RGB与YUV格式转换时出现严重色差偏粉偏绿是什么原因
预期:
![image-20210708171527861](RGA_FAQ.assets/image-normal.png)
结果:
![image-20210708171608076](RGA_FAQ.assets/image-color-abnormal.png)
**A2.11**该现象通常是由于librga与内核不匹配导致详细版本说明可以查看 **A2.4** 。该问题通常是在一些2020年11月前发布的SDK中使用了github上获取的librga之后出现该现象。github上更新librga为新版本librga与较旧版本的RGA驱动是不匹配的这里一些关于色域空间的配置有发生改变所以会出现较明显的色偏现象。
该问题的解决方案有两种一为更新SDK或RGA驱动保持librga与驱动是匹配的即可第二种则是如若无需新版本librga才有的功能可以使用SDK自带的librga即可。
rga模块源码更新包可以通过百度网盘获取https://eyun.baidu.com/s/3i6sbsDR
**Q2.12**RGA如何实现OSD叠加字幕
预期:
![image-20210708171450243](RGA_FAQ.assets/image-blend.png)
**A2.12**如果输出结果为RGB格式可以通过 **imblend()** 接口实现通常选择src over模式将src通道的图像叠加在dst通道的图像上如果输出结果为YUV格式可以通过 **imcomposite()** 接口实现通常选择dst over模式将src1通道的图像叠加在src通道的图像上再输出到dst通道。
该功能的叠加原理为 **Porter-Duff混合模型** ,详细可以查看[《Rockchip_Developer_Guide_RGA_CN》](./Rockchip_Developer_Guide_RGA_CN.md)中 “应用接口说明” —— “图像合成” 小节。
RGA针对不同输出格式需要不同的配置的原因是RGA2拥有3个图像通道——src、src1/pat、dst。其中src通道支持YUV2RGB转换src1/pat和dst通道只支持RGB2YUV转换而RGA内部的叠加均需要在RGB格式下进行所以为了保证RGB图像叠加在YUV图像上必须src作为叠加的背景图像YUVsrc1作为叠加的前景图像RGB最终由dst通道将混合后的RGB图像转换为YUV格式输出。
可以查看示例代码:
**<librga_souce_path>/samples/alpha_demo/src/rga_alpha_osd_demo.cpp**
**<librga_souce_path>/samples/alpha_demo/src/rga_alpha_yuv_demo.cpp**
**Q2.13**为什么调用RGA实现YUV格式与RGB格式相互转换输出有亮度或者数值差异
**A2.13**:该现象原因大致可分为两种:
1). YUV与RGB互转配置相同时部分像素数值会有轻微差异通常相差为1这是由于RGA硬件实现CSC功能时公式的精度问题导致RGA1和RGA2的CSC公式的小数位精度均为8bitRGA3的CSC公式的小数位精度为10bit。这里由于精度会导致一些运算结果四舍五入后会有±1的误差。
2). 当RGB2YUV和YUV2RGB转换时配置的CSC模式不同导致新版本librga中默认的RGB2YUV、YUV2RGB的CSC模式为BT.601-limit _range当错误的配置了对应的 **color_space_mode** 成员变量时色域空间的配置不同便会导致相互转换时产生较大的变化。而旧版本librga中RGB2YUV默认为BT.601-full_range,YUV2RGB默认为BT.709-limit_range由于两种转换的色域空间配置不同所以互转会存在较大的变化。
**Q2.14**librga中如何配置格式转换时的色域空间呢
**A2.14**两个版本的librga都是支持配置格式转换时的色域空间的。
1). 新版本librga中可以参考[《Rockchip_Developer_Guide_RGA_CN》](./Rockchip_Developer_Guide_RGA_CN.md)中 “应用接口说明” —— “图像格式转换” 小节中介绍重点配置mode参数即可。
2). 旧版本librga中需要修改librga源码Normal/NormaRga.cpp中yuvToRgbMode的值对应的参数如下
| 转换格式 | 色域空间 | 参数 |
| -------- | ------------------ | ------------------------ |
| YUV2RGB | BT.601-limit_range | yuvToRgbMode = 0x1 << 0; |
| YUV2RGB | BT.601-full_range | yuvToRgbMode = 0x2 << 0; |
| YUV2RGB | BT.709-limit_range | yuvToRgbMode = 0x3 << 0; |
| RGB2YUV | BT.601-limit_range | yuvToRgbMode = 0x2 << 4; |
| RGB2YUV | BT.601-full_range | yuvToRgbMode = 0x1 << 4; |
| RGB2YUV | BT.709-limit_range | yuvToRgbMode = 0x3 << 4; |
**Q2.15**调用RGA执行alpha叠加为什么没有效果
**A2.15**检查输入的两张图像的alpha值是否皆为0xFF当叠加中的前景图像的alpha值为0xFF时其结果便是前景图像直接覆盖在背景图像上看起来的结果看着像是没有效果一般实际上是正常的结果。
**Q2.16**调用RGA执行alpha叠加前景图像的alpha值为0x0为什么结果不是全透
前景图黑白和rockchip alpha为0x00
![image-20210708173625438](RGA_FAQ.assets/image-alpha-0x0.png)
预期:
![image-20210708173737882](RGA_FAQ.assets/image-alpha-normal.png)
结果:
![image-20210708173808977](RGA_FAQ.assets/image-alpha-abnormal.png)
**A2.16**我们正常配置的模式是默认颜色值已经预乘过对应的alpha值的结果而直接读取的原始图片的颜色值并没有预乘过alpha值所以需要在调用imblend时额外的增加标志位来标识本次处理中的图像颜色值没有需要预乘alpha值。具体调用方式可以查看[《Rockchip_Developer_Guide_RGA_CN》](./Rockchip_Developer_Guide_RGA_CN.md)中 “应用接口说明” —— “图像合成“ 小节。
**Q2.17**IM2D API可以一次RGA调用实现多种功能么
**A2.17**:可以的,详细可以查看[《Rockchip_Developer_Guide_RGA_CN》](./Rockchip_Developer_Guide_RGA_CN.md)中 “应用接口说明” —— “图像处理” 小节并参考IM2D API其他接口的实现了解 **improcess()** 的用法。
**Q2.18**调用RGA执行图像旋转时结果图像被拉伸
预期:
![image-20210708174014165](RGA_FAQ.assets/image-rotate-90-normal.png)
结果:
![image-20210708174113366](RGA_FAQ.assets/image-rotate-90-abnormal.png)
**A2.18**在旋转90°、270°时如果不希望RGA执行缩放应将图像的宽、高交换否则RGA驱动默认该行为为旋转 + 缩放的行为去执行工作,结果表现便是拉伸的效果了。
**Q2.19**RGB888输出缩放后结果显示图像是斜的并且有黑线
原图1920 × 1080
![image-20210708171527861](RGA_FAQ.assets/image-normal.png)
结果1282 × 720
![image-20210708174334975](RGA_FAQ.assets/image-resize-abnormal.png)
**A2.19**该问题是对齐限制导致的RGB888格式的虚宽需要4对齐请检查配置的图像参数对齐限制可以参考 **Q2.5** 的回答。
**Q2.20**在一些系统流程中调用RGA输出的结果是花的这是什么原因导致的
**A2.20**通常RGA的异常不会出现图像花掉的现象一般遇到这种问题需要先定位问题是否是RGA出现的问题在一些系统流程中需要先确认输入RGA的源数据是否已经是异常的可以通过在调用RGA前将内存里的数据调用 **fwrite()** 写文件出来,查看源数据是否正常。写文件的方法如果不太熟悉,可以参考源码目录下 **core/RgaUtils.cpp** 中的 **output_buf_data_to_file()** 函数的实现部分。
**A2.21**调用RGA处理图像后出现黑色或绿色的小条纹这是什么原因
![image-cache-abnormal](RGA_FAQ.assets/image-cache-abnormal.png)
**Q2.21**这是使用非虚拟地址调用时buffer使能了cache并且在CPU操作前后没有同步cache导致的。如果不了解如何同步cache可以参考samples/allocator_demo/src/rga_allocator_dma_cache_demo.cpp中的用法。
### HAL层报错
#### IM2D_API报错
**Q3.1.1**imcheck()返回报错,该如何处理?
```
check error! Invalid parameters: dst, Error yuv not align to 2, rect[x,y,w,h] = [0, 0, 1281, 720], wstride = 1281, hstride = 720, format = 0xa00(nv12)
output support format : RGBA_8888 RGB_888 RGB_565 RGBA_4444 RGBA_5551 YUV420/YUV422 YUV420_10bit/YUV422_10bit YUYV420 YUYV422 YUV400/Y4
```
**A3.1.1**imcheck()接口作为调用librga的校验接口它将判断即将传递到librga内部的数据结构的参数是否正确、功能是否支持、是否触发硬件限制等可以将imcheck()的返回报错值作为传参传入 **IMStrError()** 返回的字符串则为详细的报错信息,可以根据错误提示确认哪些条件限制被触发,或是参数错误。
如问题中报错则为YUV格式对齐的限制问题这里图像的宽1281不是2对齐的所以校验失败。
**Q3.1.2**imstrError()错误提示没有具体参数打印说明是什么问题?
```
Fatal error: Failed to call RockChipRga interface, please use 'dmesg' command to view driver error log.
```
**A3.1.2**说明配置在im2d api校验已经通过并配置到后级驱动上可以通过dmesg的方式查看驱动的报错。
#### RockchipRga接口报错
**Q3.2.1**“Try to use uninit rgaCtx=(nil)”报错如何处理?
**A3.2.1**1). 该报错为调用到的接口发现librga模块并没有得到初始化所返回报错。目前版本中该报错通常是由于一些较旧的调用RGA的代码中依旧使用RgaInit/RgaDeInit/c_RkRgaInit/c_RkRgaDeInit接口自行管理RGA模块的初始化而目前的版本接口使用的单例模式当被异常DeInit后便会出现该报错只需要移除调用代码中的Init/DeInit相关的调用即可。
2). 当驱动没有probe成功或者驱动设备节点/dev/rga访问受限制时也会产生这样的报错。
**Q3.2.2**“RgaBlit(1027) RGA_BLIT fail: ”、“RGA_COLORFILL(1027) RGA_BLIT fail: ”标头的报错是什么原因?
**A3.2.2**出现该标头报错说明当前RGA任务在驱动运行失败返回具体原因需要通过dmesg查看驱动日志。
**Q3.2.2.1**“RgaBlit(1027) RGA_BLIT fail: Not a typewriter”
**A3.2.2.1**该报错通常为参数错误导致建议检查一下缩放倍数、虚宽是否小于实宽与对应方向的偏移的和、对齐是否符合要求。建议新开发项目使用IM2D API拥有更全面的检测报错机制方便开发者节省大量的调试时间。
**Q3.2.2.2**“RgaBlit(1349) RGA_BLIT fail: Bad file descriptor”
**A3.2.2.2**该报错为ioctl报错标识当前传入的设备节点的fd无效请尝试更新librga或确认RGA的初始化流程是否有被修改。
**Q3.2.2.3**“RgaBlit(1360) RGA_BLIT fail: Bad address”
**A3.2.2.4**该报错通常为传入内核的src/src1/dst通道的内存地址存在问题导致常见为越界可以参照本文档 “日志获取与说明” —— “驱动调试节点” 小节,开启驱动日志,并定位出错的内存。
**Q3.2.2.4**“RgaBlit(1466) RGA BIIT fail: Invalid argument”
**A3.2.2.4**该报错为传入参数不满足当前芯片搭载核心功能、限制要求时上报的无效参数报错建议检查当前配置的任务参数是否满足当前芯片搭载RGA核心的要求。
**Q3.2.3**日志报错“err ws[100,1280,1280]”、”Error srcRect“ 是什么错误?
**A3.2.3**该报错为明显的参数报错“err ws” 即虚宽width stride参数异常其后“[]”内的参数分别为 [x_offeset, width, width_stride]这里由于X方向的偏移与实际操作区域的宽的和大于了虚宽所以librga认为虚宽存在问题而返回的报错。这里只要将虚宽改为1380或将实宽width改为1180即可。
通常该类型报错后logcat中会打印对应的一些参数
```C++
E librga : err ws[100,1280,1280] //标识单签虚宽存在问题
E librga : [RgaBlit,731]Error srcRect //标识是src通道报错
E rockchiprga: fd-vir-phy-hnd-format[0, 0xb400006eb6ea9040, 0x0, 0x0, 0] //对应src通道的输入地址fd、虚拟地址、物理地址、handle
E rockchiprga: rect[100, 0, 1280, 720, 1280, 720, 1, 0] //对应src通道的图像参数依次为x方向偏移、y方向偏移、实际操作区域的宽、实际操作区域的高、图像宽虚高、图像高虚高、图像格式、size目前没有使用到的参数
E rockchiprga: f-blend-size-rotation-col-log-mmu[0, 0, 0, 0, 0, 0, 1] //标识着本次调用中的模式配置。
E rockchiprga: fd-vir-phy-hnd-format[0, 0xb400006eb2ea6040, 0x0, 0x0, 0] //对应dst通道的参数
E rockchiprga: rect[0, 0, 1920, 1080, 1920, 1080, 1, 0]
E rockchiprga: f-blend-size-rotation-col-log-mmu[0, 0, 0, 0, 0, 0, 1]
E rockchiprga: This output the user parameters when rga call blit fail //报错信息
```
### kernel层报错
**Q4.1**“RGA2 failed to get vma, result = 32769, pageCount = 65537”报错是什么导致的
**A4.1**该报错通常为使用虚拟地址调用RGA时虚拟地址的实际内存小于实际需要的内存大小即根据图像参数计算出当前通道的图像需要多大的内存只需检查buffer的大小即可在一些申请和调用不是在同一处的场景下可以在调用RGA前执行一遍memset对应图像的大小确认是否为内存大小不足导致的问题。
改报错后,通常便随着 “rga2 map src0 memory failed” 可以确认是哪一个通道的内存出现问题如该例中所示src通道由于实际申请的buffer大小仅为图像所需大小的一半所以触发了这个报错。
**Q4.2**”rga2_reg_init, [868] set mmu info error“ MMU报错是什么原因
**A4.2**该报错表征为fd/虚拟地址转换为物理地址页表出错通常是申请的内存大小的问题与Q4.1相同。
**Q4.3**“rgadma_buf_get fail fd[328]” 报这种错误一般是指buffer出现了什么异常
**Q4.3**该报错为fd在内核经过dma的接口时的报错建议检查一下申请fd的流程并在librga外部验证fd可用后再用于调用RGA。
**Q4.4**“RGA2 failed to get pte, result = -14, pageCount = 112”、”rga2_reg_init, [868] set mmu info error“ 按照 **Q4.1** 、**Q4.2** 方式检查后还是一样的报错这里使用的是DRM分配的物理地址通过mmap映射的虚拟地址传入RGA的memset均正常这是什么原因导致的
**A4.4**该问题为分配器DRM本身的问题DRM本身认为当用户态获取到物理地址后正常来讲内核态是不需要虚拟地址的了所以在分配buffer时就会将对应的kmap释放仅释放kmap也不会影响到用户态中映射虚拟地址和使用但是当这块buffer用户态的虚拟地址传入RGA驱动驱动进行物理地址页表的转换查询时由于该buffer的kmap已经被释放或是无法查询到对应的页表项或是直接访问到错误的地址导致内核crash。
针对这种场景DRM提供了一个接口标志位用户判断用户态是否希望DRM释放kmap即是否考虑讲映射的虚拟地址传入内核使用
```
(1) drm buffer申请选项增加ROCKCHIP_BO_ALLOC_KMAP定义。
+ /* keep kmap for cma buffer or alloc kmap for other type memory */
+ ROCKCHIP_BO_ALLOC_KMAP = 1 << 4,
(2) 申请drm内存时增加新增的drm buffer选项ROCKCHIP_BO_ALLOC_KMAP。
struct drm_mode_create_dumb arg;
...
- arg.flags = ROCKCHIP_BO_CONTIG;
+ arg.flags = ROCKCHIP_BO_CONTIG | ROCKCHIP_BO_ALLOC_KMAP; //ROCKCHIP_BO_ALLOC_KMAP仅与ROCKCHIP_BO_CONTIG共同使用时有效。
ret = drmIoctl(drm_fd, DRM_IOCTL_MODE_CREATE_DUMB, &arg);
```
并确认kernel是否包含以下提交如若没有请更新SDK
```
commit 1a81ee3e2d3726b9382ff2c48d08f4d837bc0143
Author: Sandy Huang <hjc@rock-chips.com>
Date: Mon May 10 16:52:04 2021 +0800
drm/rockchip: gem: add flag ROCKCHIP_BO_ALLOC_KMAP to assign kmap
RGA need to access CMA buffer at kernel space, so add this flag to keep kernel
line mapping for RGA.
Change-Id: Ia59acee3c904a495792229a80c42f74ae34200e3
Signed-off-by: Sandy Huang <hjc@rock-chips.com>
```
**Q4.5**“RGA_MMU unsupported Memory larger than 4G!”报错该如何解决?
**A4.5**该报错通常对应HAL层报错
```
RgaBlit(1483) RGA_BLIT fail: Invalid argument
Failed to call RockChipRga interface, please use 'dmesg' command to view driver error log.
```
该报错标识当前配置的图像任务配置的内存无法满足当前匹配到的硬件核心对内存的要求由于不同的硬件版本的RGA的IOMMU对内存位数的要求不同当分配的内存超过对应硬件的限制时则会出现该该报错详细的不同硬件版本RGA的限制可见[《Rockchip_Developer_Guide_RGA_CN》](./Rockchip_Developer_Guide_RGA_CN.md)中的概述——设计指标小节。
当出现该报错时,通常有以下几种场景以及对应的解决方案:
1. 在搭载多种RGA的芯片平台例如RK3588搭载有2颗RGA3核心、1颗RGA2核心没有使用importbuffer_xx接口获取handle而是直接使用wrapbuffer_xx接口调用im2d api时
由于没有使用importbuffer_xx来提前映射外部内存到RGA驱动内存因此在实际任务匹配中无法提前获知内存是否不满足对应核心的限制因此在高负载场景下可能会出现该报错建议使用importbuffer_xx提前将外部内存导入到RGA驱动内部避免该问题。
2. 在搭载多种RGA的芯片平台例如RK3588搭载有2颗RGA3核心、1颗RGA2核心使用了importbuffer_xx接口获取handle但是依旧存在该问题
可以检查一下配置的图像任务的参数确认是否配置了仅有RGA2核心内存访问受限制的核心支持的功能或格式以RK3588为例color fill功能和YUV422/420 planar格式均是RGA2核心特有的功能和格式因此该场景下必须分配4G以内内存空间的内存调用RGA。
常见的分配4G内存方式可以查看以下示例代码
**<librga_souce_path>/samples/allocator_demo/src/rga_allocator_dma32_demo.cpp**
**<librga_souce_path>/samples/allocator_demo/src/rga_allocator_graphicbuffer_demo.cpp**
如果使用的其他分配器例如mpp_buffer、v4l2_buffer、drm_buffer等请查询对应分配器是否支持限制分配4G以内内存空间内存并按照对应方式申请复合RGA硬件要求的内存。
3. 仅搭载一种RGA的芯片平台例如仅搭载RGA2的RK3399、RK3568、Rk3566
当芯片平台上仅搭载内存访问受限制的核心时则调用RGA时必须申请符合搭载核心对内存要求的内存解决方案同上场景2。
**Q4.6**“rga_policy: invalid function policy”、“rga_job: job assign failed”字样报错是什么导致的
**A4.6**:可以开启驱动运行日志查看,具体错误原因
例如:
```
rga_policy: start policy on core = 4
rga_policy: RGA2 only support under 4G memory! //标识当前搭载的RGA2核心仅支持4G以内的内存。
rga_policy: optional_cores = 0
rga_policy: invalid function policy
rga_policy: assign core: -1
rga_job: job assign failed
```
```
rga_policy: start policy on core = 1
rga_policy: core = 1, break on rga_check_dst //对应核心不支持的原因日志这里是dst通道的图像参数不满足当前核心要求可以查阅文档确认该核心支持情况这里core 0x1、0x2为RGA3核心0x4为RGA2核心
rga_policy: start policy on core = 2
rga_policy: core = 2, break on rga_check_dst //对应核心不支持的原因日志,同上。
rga_policy: start policy on core = 4
rga_policy: RGA2 only support under 4G memory! //对应核心不支持的原因日志标识当前不匹配原因为该核心不支持4G内存空间以外的内存。
rga_policy: optional_cores = 0
rga_policy: invalid function policy
rga_policy: assign core: -1 //遍历全部核心后,无可匹配核心,则上报匹配失败错误。
rga_job: job assign failed
```
以上两种情况可以根据对应的日志去确认配置的参数信息,并针对性的进行修改。
**Q4.7**“rgaRga err irq! INT[701],STATS[1]” 调用RGA出现中断报错是什么导致的
**A4.7**该问题通常发生在RGA硬件执行过程中遇到问题异常返回异常原因很多常见的有内存越界、异常配置。建议遇到该问题优先检查传入的内存是否会发生越界。
**Q4.8**“rga: Rga sync pid 1001 wait 1 task done timeout” 硬件超时报错一般是什么导致的?
**A4.8**:硬件超时报错原因有很多种,可以按照以下情形依次排查:
1). 检查整体流程确认没有其他模块或应用对该块buffer持锁或异常占用中当同一块buffer被其他模块异常占用时RGA无法正常读写数据超过了驱动设计的200ms的阈值后便会异常返回并打印报错。
2). 检查当前系统的DDR带宽与利用率由于RGA的总线优先级较低当DDR负载跑满时如果RGA在200ms内没有执行完毕驱动便会异常返回并打印该报错。
3). 确认RGA超时报错前是否已经有其他IP模块的报错例如ISP、vpu等当在同一条总线上的硬件出现问题的情况可能会导致RGA无法正常工作驱动等待超过200ms后便异常返回并打印报错。
4). 确认当前RGA频率可以参考 **Q1.4** 中RGA频率相关操作某些场景可能会出现同一条总线上的模块降频后影响到RGA的频率RGA频率下降从而导致整体的性能下降无法在200ms内完成工作驱动便会异常返回并打印报错。
5). 部分芯片RGA被超频到一个较高的频率此时RGA频率上升但是电压没有提升会导致RGA整体性能显著下降导致无法在规定阈值内完成工作从而驱动异常返回并打印报错。该场景建议开发者将RGA频率修改至正常频率超频对整体芯片的稳定性与使用寿命均有影响强烈不建议该种行为。
6). 以上场景均没有发现问题可以尝试在RGA超时报错返回后将目标内存中的数据写到文件中查看RGA是否有写入部分数据如有写入部分数据请重新确认1-5场景该现象明显为RGA性能表现不足导致如果目标内存没有被RGA写入数据收集对应的日志信息以及相关实验过程联系维护RGA模块的工程师。
**Q4.9**当出现timeout报错时同时伴随着“rga_job: hardware has finished, but the software has timeout!”日志,是什么原因?
**A4.9**当出现该日志则说明当前系统环境负责中断的CPU核心被抢占导致RGA驱动在上半部的硬件中断结束后等不到下半部的软中断超过驱动设置的超时阈值后驱动上报的超时错误。
这种情况常见于应用层存在实时进程抢占了CPU导致驱动设备无法正常工作不建议使用实时进程强制抢占CPU资源出现该问题只能从CPU侧进行优化避免负责中断的CPU核心被抢占无法执行其他设备驱动的软中断。