RK3588S comes with an RGA3, which is essentially a 2D graphics transformation accelerator that can support typical 2D image transformation processing, such as scaling, merging, watermark overlay, etc. The maximum supported resolution is 8192x8192 image processing.
Since Hot Wheels Technology has open sourced the SDK, it is recommended to build it uniformly on the SDK on the PC side to ensure a consistent build environment. The cross-compilation environment in the SDK is consistent with the environment on the board.
The RGA library source code can currently only be obtained from the SDK, and the entire SDK provided by Hot Wheels Technology can be pulled. The RGA source code is in the SDK root directory
external/linux-rga
. It is recommended to copy this source code to a separate working directory for use
If you do not want to download the entire SDK, you can download the linux-rga package from the link below
First, configure the cross-compilation environment. In the SDK root directory , execute the following lines
DIR=$(pwd)
export PATH=$PATH:${DIR}/prebuilts/gcc/linux-x86/aarch64/gcc-arm-10.3-2021.07-x86_64-aarch64-none-linux-gnu/bin
export CROSS_COMPILE=aarch64-none-linux-gnu-
export ARCH=aarch64
In the rga working directory, open the toolchains directory
Then modify the compiler directory in the toolchain_linux.cmake file as follows
# Replace XXX with the SDK path
SET(TOOLCHAIN_HOME "XXX/prebuilts/gcc/linux-x86/aarch64/gcc-arm-10.3-2021.07-x86_64-aarch64-none-linux-gnu")
Then execute in rga working directory
./cmake-linux.sh
Then compile and the information of the completed compilation is as follows
After the compilation is completed, you can see the following files in the build/build_linux directory
Among them, librga.a is a static library and librga.so is a dynamic library. There is a rgaImDemo in samples/im2d_api_demo as a test demo
Put the rgaImDemo file generated in the above step on the board. First, verify whether the environment on the board is correct. Directly execute
./rgaImDemo --querystring
If you see the following result, it means that the environment on the board is fine.
Find a test image. This image needs to be 1280x720 and in rgba8888 format. There are two in samples/sample_file
. Here we use in1w1280-h720-rgba8888.bin. You can use YUView on the PC to view RAW images. In YUView, you can see the following content
Put it in the /usr/data/ directory on the board and rename it to in0w1280-h720-rgba8888.bin
root@linaro-alip:~# ls -ll /usr/data
Total usage 3600
-rw-rw-rw- 1 root root 3686400 November 26 2023 in0w1280-h720-rgba8888.bin
Then test the image scaling and rotation transformation, which are also the most commonly used functions in RGA
# Zoom in to 720p
root@linaro-alip:~# ./rgaImDemo --resize up
Start selecting mode 0
im2d resize ..
up resize ...
MODE = 2
open file
rga_api version 1.8.1_[3]
resizing .... cost time 3927 us, Run successfully
open /usr/data/out0w1920-h1080-rgba8888.bin and write ok
root@linaro-alip:~#
root@linaro-alip:~#
# Reduce to 480p
root@linaro-alip:~# ./rgaImDemo --resize down
Start selecting mode 0
im2d resize ..
down resize ...
MODE = 2
open file
rga_api version 1.8.1_[3]
resizing .... cost time 2429 us, Run successfully
open /usr/data/out0w720-h480-rgba8888.bin and write ok
root@linaro-alip:~#
root@linaro-alip:~#
root@linaro-alip:~#
# Rotate 90 degrees
root@linaro-alip:~# ./rgaImDemo --rotate 90
Start selecting mode 0
im2d rotate ..
rotation 90 ...
MODE = 4
open file
rga_api version 1.8.1_[3]
rotating .... cost time 3192 us, Run successfully
open /usr/data/out0w720-h1280-rgba8888.bin and write ok
Then put the generated 3 files on the PC side YUView to view
The following uses the im2d_api_demo source code in the demo as an example to introduce how to use the rga dynamic library.
This source file is located in the samples directory of the linux-rga project
First, let's look at the main function. It first uses readArguments to parse all the parameters, and then performs different actions according to the parameter type
int main(int argc, char* argv[]) {
int ret = 0, while_time = 0;
int parm_data[MODE_MAX] = {0};
int COLOR;
IM_USAGE ROTATE;
IM_USAGE FLIP;
int MODE;
IM_INFORMATION IM_INFO;
IM_STATUS STATUS;
im_rect src_rect;
im_rect dst_rect;
rga_buffer_t src;
rga_buffer_t dst;
rga_buffer_handle_t src_handle;
rga_buffer_handle_t dst_handle;
char* src_buf = NULL;
char* dst_buf = NULL;
memset(&src_rect, 0, sizeof(src_rect));
memset(&dst_rect, 0, sizeof(dst_rect));
memset(&src, 0, sizeof(src));
memset(&dst, 0, sizeof(dst));
MODE = readArguments(argc, argv, parm_data);
...
/********** Get parameters **********/
if(MODE != MODE_QUERYSTRING) {
src_buf = (char*)malloc(SRC_WIDTH*SRC_HEIGHT*get_bpp_from_format(SRC_FORMAT));
dst_buf = (char*)malloc(DST_WIDTH*DST_HEIGHT*get_bpp_from_format(DST_FORMAT));
ret = get_buf_from_file(src_buf, SRC_FORMAT, SRC_WIDTH, SRC_HEIGHT, 0);
...
if(MODE == MODE_BLEND || MODE == MODE_FILL) {
ret = get_buf_from_file(dst_buf, DST_FORMAT, DST_WIDTH, DST_HEIGHT, 1);
...
} else {
memset(dst_buf,0x00,DST_WIDTH*DST_HEIGHT*get_bpp_from_format(DST_FORMAT));
}
src_handle = importbuffer_virtualaddr(src_buf, SRC_WIDTH, SRC_HEIGHT, SRC_FORMAT);
...
dst_handle = importbuffer_virtualaddr(dst_buf, DST_WIDTH, DST_HEIGHT, DST_FORMAT);
...
src = wrapbuffer_handle(src_handle, SRC_WIDTH, SRC_HEIGHT, SRC_FORMAT);
dst = wrapbuffer_handle(dst_handle, DST_WIDTH, DST_HEIGHT, DST_FORMAT);
...
}
do {
...
switch(MODE) {
case MODE_QUERYSTRING :
IM_INFO = (IM_INFORMATION)parm_data[MODE_QUERYSTRING];
printf("\n%s\n", querystring(IM_INFO));
break;
case MODE_COPY : //rgaImDemo --copy
ret = imcheck(src, dst, src_rect, dst_rect);
...
STATUS = imcopy(src, dst);
...
break;
case MODE_RESIZE : //rgaImDemo --resize=up/down
releasebuffer_handle(dst_handle);
dst_handle = -1;
switch(parm_data[MODE_RESIZE]) {
case IM_UP_SCALE :
if (dst_buf != NULL) {
free(dst_buf);
dst_buf = NULL;
}
dst_buf = (char*)malloc(1920*1080*get_bpp_from_format(DST_FORMAT));
...
memset(dst_buf,0x00,1920*1080*get_bpp_from_format(DST_FORMAT));
dst_handle = importbuffer_virtualaddr(dst_buf, 1920, 1080, DST_FORMAT);
...
dst = wrapbuffer_handle(dst_handle, 1920, 1080, DST_FORMAT);
...
break;
case IM_DOWN_SCALE :
if (dst_buf != NULL) {
free(dst_buf);
dst_buf = NULL;
}
dst_buf = (char*)malloc(720*480*get_bpp_from_format(DST_FORMAT));
memset(dst_buf,0x00,720*480*get_bpp_from_format(DST_FORMAT));
dst_handle = importbuffer_virtualaddr(dst_buf, 720, 480, DST_FORMAT);
...
dst = wrapbuffer_handle(dst_handle, 720, 480, DST_FORMAT);
...
break;
}
ret = imcheck(src, dst, src_rect, dst_rect);
...
STATUS = imresize(src, dst);
break;
case MODE_CROP : //rgaImDemo --crop
src_rect.x = 100;
src_rect.y = 100;
src_rect.width = 300;
src_rect.height = 300;
ret = imcheck(src, dst, src_rect, dst_rect, IM_CROP);
...
STATUS = imcrop(src, dst, src_rect);
...
break;
case MODE_ROTATE : //rgaImDemo --rotate=90/180/270
ROTATE = (IM_USAGE)parm_data[MODE_ROTATE];
if (IM_HAL_TRANSFORM_ROT_90 == ROTATE || IM_HAL_TRANSFORM_ROT_270 == ROTATE) {
dst.width = src.height;
dst.height = src.width;
dst.wstride = src.hstride;
dst.hstride = src.wstride;
}
ret = imcheck(src, dst, src_rect, dst_rect, ROTATE);
...
STATUS = imrotate(src, dst, ROTATE);
...
break;
case MODE_FLIP : //rgaImDemo --flip=H/V
FLIP = (IM_USAGE)parm_data[MODE_FLIP];
ret = imcheck(src, dst, src_rect, dst_rect);
...
STATUS = imflip(src, dst, FLIP);
...
break;
case MODE_TRANSLATE : //rgaImDemo --translate
src_rect.x = 300;
src_rect.y = 300;
ret = imcheck(src, dst, src_rect, dst_rect);
...
STATUS = imtranslate(src, dst, src_rect.x, src_rect.y);
...
break;
case MODE_BLEND : //rgaImDemo --blend
ret = imcheck(src, dst, src_rect, dst_rect);
...
STATUS = imblend(src, dst);
...
break;
case MODE_CVTCOLOR : //rgaImDemo --cvtcolor
src.format = RK_FORMAT_RGBA_8888;
dst.format = RK_FORMAT_YCbCr_420_SP;
...
ret = imcheck(src, dst, src_rect, dst_rect);
...
STATUS = imcvtcolor(src, dst, src.format, dst.format);
...
break;
case MODE_FILL : //rgaImDemo --fill=blue/green/red
COLOR = parm_data[MODE_FILL];
dst_rect.x = 100;
dst_rect.y = 100;
dst_rect.width = 300;
dst_rect.height = 300;
ret = imcheck(src, dst, src_rect, dst_rect, IM_COLOR_FILL);
...
STATUS = imfill(dst, dst_rect, COLOR);
...
break;
...
}
...
/********** release rga buffer handle **********/
releasebuffer_handle(src_handle);
releasebuffer_handle(dst_handle);
/********** output buf data to file **********/
if (src_buf != NULL) {
free(src_buf);
src_buf = NULL;
}
if (dst_buf != NULL) {
output_buf_data_to_file(dst_buf, dst.format, dst.wstride, dst.hstride, 0);
free(dst_buf);
dst_buf = NULL;
}
return 0;
}
Then the processing of each case is to first call imcheck to check whether the parameters are legal and whether the current hardware supports the operation
Then call different processing, such as
imcopy is to perform a single fast image copy operation, copying the image from the src channel image buffer to the dst channel image buffer
imresize is image scaling
imcrop is image cropping
imrotate is image rotation
Overall, RK's RGA library API is relatively simple to call, and the demo project is also relatively clear.
For specific RGA APIs, please refer to the RGA description document, which is in docs/cn/Common/RGA/Rockchip_Developer_Guide_RGA_CN.pdf.