RGA的使用

RGA即二维图像辅助计算单元,该单元可以在极短时间内拷贝、旋转、格式转换、缩放、混合图片。

rk官方RGA库链接:https://github.com/rockchip-linux/linux-rga

运行时间对比

memcpy > RGA with vir addr > RGA with phy addr

暂时没空整理,先把整个代码贴出来吧。

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h> #include <sys/time.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h> #include <RgaApi.h>
#include <im2d.h> #include <drm/drm.h>
#include "drm/drm_mode.h" #define RGA_ALIGN(x, a) (((x) + (a)-1) / (a) * (a))
#define BUF_WIDTH 1280
#define BUF_HEIGHT 720 #define BUF_SIZE (BUF_WIDTH * BUF_HEIGHT * 4) uint8_t *srcBuffer;
uint8_t *dstBuffer; rga_info_t src;
rga_info_t dst;
rga_info_t src1; /**
* @brief
*
* @param
*
* @return
*/
int get_elapse_in_ms(struct timeval *tv)
{
struct timeval this_tv; gettimeofday(&this_tv, NULL);
uint64_t diff_sec = this_tv.tv_sec - tv->tv_sec;
int elapse_in_ms; if (diff_sec == 0)
{
elapse_in_ms = (this_tv.tv_usec - tv->tv_usec) / 1000.0;
}
else
{
elapse_in_ms = ((--diff_sec) * 1000) + ((1000000 - tv->tv_usec) + this_tv.tv_usec) / 1000.0;
}
return elapse_in_ms;
} /**
* @brief get time elapse in us
*
* @param timeval tv
*
* @return
*/
int get_elapse_in_us(struct timeval *tv)
{
struct timeval this_tv; gettimeofday(&this_tv, NULL);
uint64_t diff_sec = this_tv.tv_sec - tv->tv_sec;
int elapse_in_us; if (diff_sec == 0)
{
elapse_in_us = (this_tv.tv_usec - tv->tv_usec);
}
else
{
elapse_in_us = ((--diff_sec) * 1000000) + ((1000000 - tv->tv_usec) + this_tv.tv_usec);
}
return elapse_in_us;
} /**
* @brief
*
* @param
*
* @return
*/
void make_random_data()
{
int rand_fd;
rand_fd = open("/dev/urandom", O_RDONLY);
read(rand_fd, srcBuffer, BUF_SIZE);
close(rand_fd);
} void check_data()
{
for (int i = 0; i < BUF_SIZE; i++)
{
if (srcBuffer[i] != dstBuffer[i])
{
printf("[diff at pos: %d] src: [%d] dst: [%d]\n", i, srcBuffer[i], dstBuffer[i]);
}
}
} void rga_copy_vir()
{
src.virAddr = srcBuffer;
dst.virAddr = dstBuffer; rga_set_rect(&src.rect, 0, 0, BUF_WIDTH, BUF_HEIGHT, BUF_WIDTH, BUF_HEIGHT, RK_FORMAT_RGBA_8888);
rga_set_rect(&dst.rect, 0, 0, BUF_WIDTH, BUF_HEIGHT, BUF_WIDTH, BUF_HEIGHT, RK_FORMAT_RGBA_8888); c_RkRgaBlit(&src, &dst, NULL);
} int rga_copy()
{
bo_t bo_src, bo_dst;
int buff_fd_src, buff_fd_dst;
struct timeval tv; static const char *card = "/dev/dri/card0";
int drm_fd;
int flag = O_RDWR | O_CLOEXEC;
drm_fd = open(card, flag);
if (drm_fd < 0)
{
fprintf(stderr, "Fail to open %s: %m\n", card);
return -errno;
} ioctl(drm_fd, DRM_IOCTL_SET_MASTER, 0); // memset(&src, 0x0, sizeof(rga_info_t));
// memset(&dst, 0x0, sizeof(rga_info_t));
// src.fd = -1;
// dst.fd = -1;
// src.mmuFlag = 1;
// dst.mmuFlag = 1; /* create dumb */
struct drm_mode_create_dumb arg;
struct drm_mode_create_dumb arg2;
int ret; memset(&arg, 0, sizeof(arg));
arg.bpp = 32;
arg.width = BUF_WIDTH;
arg.height = BUF_HEIGHT; memset(&arg2, 0, sizeof(arg2));
arg2.bpp = 32;
arg2.width = BUF_WIDTH;
arg2.height = BUF_HEIGHT;
// arg.flags = 0; ret = ioctl(drm_fd, DRM_IOCTL_MODE_CREATE_DUMB, &arg);
if (ret)
{
fprintf(stderr, "can't alloc drm dumb buffer src!\n");
return -errno;
} ret = ioctl(drm_fd, DRM_IOCTL_MODE_CREATE_DUMB, &arg2);
if (ret)
{
fprintf(stderr, "can't alloc drm dumb buffer dst!\n");
return -errno;
} printf("arg %u %u %lu \n", arg.handle, arg.pitch, arg.size);
printf("arg2 %u %u %lu \n", arg2.handle, arg2.pitch, arg2.size); /*
// create a dumb scanout buffer
struct drm_mode_create_dumb {
__u32 height;
__u32 width;
__u32 bpp;
__u32 flags;
// handle, pitch, size will be returned
__u32 handle;
__u32 pitch;
__u64 size;
};
*/ bo_src.fd = drm_fd;
bo_src.handle = arg.handle;
bo_src.size = arg.size;
bo_src.pitch = arg.pitch; bo_dst.fd = drm_fd;
bo_dst.handle = arg2.handle;
bo_dst.size = arg2.size;
bo_dst.pitch = arg2.pitch; /* map dumb */
struct drm_mode_map_dumb arg_map_src;
struct drm_mode_map_dumb arg_map_dst;
void *map_src;
void *map_dst; memset(&arg_map_src, 0, sizeof(arg_map_src));
memset(&arg_map_dst, 0, sizeof(arg_map_dst)); arg_map_src.handle = bo_src.handle;
arg_map_dst.handle = bo_dst.handle; ret = ioctl(bo_src.fd, DRM_IOCTL_MODE_MAP_DUMB, &arg_map_src);
if (ret)
{
fprintf(stderr, "can't map drm dumb buffer src!\n");
return -errno;
} ret = ioctl(bo_dst.fd, DRM_IOCTL_MODE_MAP_DUMB, &arg_map_dst);
if (ret)
{
fprintf(stderr, "can't map drm dumb buffer dst!\n");
return -errno;
} map_src = mmap(0, bo_src.size, PROT_READ | PROT_WRITE, MAP_SHARED, bo_src.fd, arg_map_src.offset);
if (map_src == MAP_FAILED)
return -errno; bo_src.ptr = map_src;
printf("bo_src.ptr %p\n", bo_src.ptr);
printf("bo_src.size %d\n", bo_src.size);
printf("arg_map_src.offset %p\n", arg_map_src.offset); map_dst = mmap(0, bo_dst.size, PROT_READ | PROT_WRITE, MAP_SHARED, bo_dst.fd, arg_map_dst.offset);
if (map_dst == MAP_FAILED)
return -EINVAL; bo_dst.ptr = map_dst;
printf("arg_map_dst.offset %p\n", arg_map_dst.offset); c_RkRgaGetBufferFd(&bo_src, &buff_fd_src);
c_RkRgaGetBufferFd(&bo_dst, &buff_fd_dst); printf(" buff_fd_src %d\n", buff_fd_src);
printf(" buff_fd_dst %d\n", buff_fd_src); src.fd = buff_fd_src;
dst.fd = buff_fd_dst; src.phyAddr = map_src;
dst.phyAddr = map_dst; rga_set_rect(&src.rect, 0, 0, BUF_WIDTH, BUF_HEIGHT, BUF_WIDTH, BUF_HEIGHT, RK_FORMAT_RGBA_8888);
rga_set_rect(&dst.rect, 0, 0, BUF_WIDTH, BUF_HEIGHT, BUF_WIDTH, BUF_HEIGHT, RK_FORMAT_RGBA_8888); memcpy(map_src, srcBuffer, BUF_SIZE);
printf("%p\n", map_src); gettimeofday(&tv, NULL);
c_RkRgaBlit(&src, &dst, NULL);
printf("[c_RkRgaBlit with phyAddr] elapse time: %d us\n", get_elapse_in_us(&tv)); /**
* Destroy the dumb, did last.
*/
struct drm_mode_destroy_dumb destroy_arg; /* unmap */
munmap(map_src, BUF_SIZE);
munmap(map_dst, BUF_SIZE); memset(&destroy_arg, 0x0, sizeof(arg));
destroy_arg.handle = bo_src.handle;
ioctl(drm_fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy_arg); memset(&destroy_arg, 0x0, sizeof(destroy_arg));
destroy_arg.handle = bo_dst.handle;
ioctl(drm_fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy_arg); close(drm_fd);
} int main(int argc, char **argv)
{
struct timeval tv; srcBuffer = (unsigned char *)malloc(BUF_SIZE);
dstBuffer = (unsigned char *)malloc(BUF_SIZE); make_random_data();
printf("%s\n", querystring(RGA_VERSION));
printf("%s\n", querystring(RGA_MAX_INPUT));
printf("%s\n", querystring(RGA_INPUT_FORMAT)); gettimeofday(&tv, NULL);
memcpy(dstBuffer, srcBuffer, BUF_SIZE); printf("[memcpy] elapse time: %d us\n", get_elapse_in_us(&tv));
check_data();
memset(dstBuffer, 0x0, BUF_SIZE); gettimeofday(&tv, NULL);
rga_copy_vir();
printf("[rgacpy with virAddr] elapse time: %d us\n",get_elapse_in_us(&tv));
// check_data();
rga_copy();
printf("data haven't been checked!\n"); free(srcBuffer);
free(dstBuffer); return 0;
}

rockchip-rk3399 RGA的使用的更多相关文章

  1. crosss compile VLC with OpenMAX on ARM board(RockChip RK3399),in order to use Hard Acceleration when decode video

    reference:http://www.x90x90x90.com/en/raspberry-pi-3-howto-compile-vlc-with-hardware-acceleration/ 1 ...

  2. RK3399配置笔记

    1. adb shell 默认超级管理员 在build/core/main.mk下将ADDITIONAL_DEFAULT_PROPERTIES += ro.secure=1改成ADDITIONAL_D ...

  3. 瑞芯微RK3399宣布系统开源,进入百余种行业市场!

    集微网消息,2月24日瑞芯微官方突然宣布, Rockchip RK3399Linux系统开源!作为Rockchip旗舰级芯片,RK3399具有高性能.高扩展.全能型应用特性. 这一重磅消息立马刷爆朋友 ...

  4. [RK3399] 虚拟按键栏显示不全或者方向不对

    CPU:RK3399 系统:Android 7.1 同样的系统代码,换了一个小分辨率的屏,虚拟按键栏就出现显示不全,而且方向不对 出现这种问题的原因是显示密度和屏不匹配,需要适当的降低显示密度即可 d ...

  5. [RK3399] 调试串口ttyS2改为普通串口

    CPU:RK3399 系统:Android 7.1 串口需求量大时,会选择使用 spi 转串口,但是数据量大或者波特率较高时,传输会丢包. 调试串口 ttyS2 也可以让出来,供上层使用,下面是将 t ...

  6. RK3399 4G模块移远EC20移植调试

    转载请注明出处:https://www.cnblogs.com/lialong1st/p/11266330.html CPU:RK3399 系统:Android 7.1 1.通过串口打印或者adb获取 ...

  7. 瑞芯微RK3399六核-迅为3399开发板介绍

    迅为3399开发板基于瑞芯微的RK3399处理器设计,Rockchip RK3399是瑞芯微推出的一款低功耗.高性能的应用处理器芯片,该芯片基于Big.Little架构,即具有独立的NEON协同处理器 ...

  8. Rock Pi开发笔记(二):入手Rock Pi 4B plus(基于瑞星微RK3399)板子并制作系统运行

    前言   入手rock pi 4b plus板子,查看具体的实物,然后制作系统,刷系统,让摇滚派的ubuntu系统运行起来.   Rock Pi 4B plus 介绍   ROCK Pi 4 是 Ra ...

  9. PCI 设备调试手段

    Author: Younix Platform: RK3399 OS: Android 6.0 Kernel: 4.4 Version: v2017.04 一PCI 设备调试手段 busybox ls ...

  10. http://www.artrobot.com/北京钢铁侠

    http://www.artrobot.com/ 钢铁侠ROS智能机器人 钢铁侠ROS智能机器人 型号 ARTrobot-ROS 产品图片:   产品概述: ARTrobot-ROS全开放机器人套件服 ...

随机推荐

  1. Pytorch入门下 —— 其他

    本节内容参照小土堆的pytorch入门视频教程. 现有模型使用和修改 pytorch框架提供了很多现有模型,其中torchvision.models包中有很多关于视觉(图像)领域的模型,如下图: 下面 ...

  2. Xpath 使用技巧

    使用xpath 简介 常见语法 选取节点 谓语 通配符 选取多个路径 运算符 其他用法 使用contains选取包含属性 使用tostring()将对象转换为字符串 使用starts-with 使用n ...

  3. jarvisoj_fm(格式字符串)

    我又回来了,前几天被timeout问题折磨,还是放弃了 拿到题目还是file一下 看到时32位的程序,于是把程序放入ida*32中 可以看到当x等于4的时候可以拿到shell,上面的printf(bu ...

  4. [BUUCTF]PWN6——ciscn_2019_c_1

    [BUUCTF]PWN6--ciscn_2019_c_1 题目网址:https://buuoj.cn/challenges#ciscn_2019_c_1 步骤: 例行检查,64位,开启了nx保护 nc ...

  5. C++ happens-before 关系是不可传递的

    P0668R4 对此进行了解释 The definition of plain happens-before became unpleasantly complicated with the intr ...

  6. CF1492B Card Deck 题解

    Content 有 \(n\) 张纸牌组成的一个牌堆,每张纸牌都有一个价值 \(p_1,p_2,\dots,p_n\).每次选出最顶上的几个牌放到另外一个一开始为空的牌堆里面.定义一个牌堆的总值为 \ ...

  7. VMware 打开虚拟机出现另一个程序已锁定文件的一部分,进程无法访问

    打开虚拟机出现 另一个程序已锁定文件的一部分,进程无法访问 打不开磁盘"D:\Virtual Machines\CentOS 7 64 位\CentOS 7 64 位.vmdk"或 ...

  8. 【LeetCode】946. Validate Stack Sequences 解题报告(Python & C++)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 模拟过程 日期 题目地址:https://leetc ...

  9. Windows服务注册(需要指定config文件的情况下)

    最近,遇到一个问题:需要将telegraf在Win平台下注册为windows服务(避免误操作关闭CMD窗口): 尝试了网上的几种注册Windows服务的方法,发现无法将telegraf这种需要在CMD ...

  10. 遍历 HashMap 的 5 种最佳方式

    使用 Iterator 遍历 HashMap EntrySet 使用 Iterator 遍历 HashMap KeySet 使用 For-each 循环迭代 HashMap 使用 Lambda 表达式 ...