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. gogs报错解决合集

    目录 一.在组织中添加成员,一直显示普通用户 一.在组织中添加成员,一直显示普通用户 组织是公司,团队是公司中的不同队伍.例如A团队设置为加入就有管理员权限,那加入就有管理员. 但在组织成员那一栏中加 ...

  2. Python语法之基本数据类型

    一.数据类型之字符串str 作用:主要用于记录描述性性质的数据,如姓名.地址.邮箱: 定义: 方式1 # 单引号 name = 'jason' 方式2 # 双引号 name = "jason ...

  3. secret_file

    拿到题目例行检查,进入main函数 这个逆向有些复杂,程序首先让我们像dest输入256个字符,我们可以看到关键的strcmp(v15,v17),若相等则执行poppen poppen这个函数有额外的 ...

  4. ciscn_2019_c_1 1

    步骤: 先checksec,看一下开启了什么保护 可以看到开启了nx保护,然后把程序放入ida里面,观察程序代码 先shift+f12观察是否有system和binsh函数 发现没有system和bi ...

  5. Excel里的格式会自动变成日期或会计专用吗?(Excel技巧集团)

    Excel里的格式会自动变成日期或会计专用? 正常情况下当然不会了,可是最近却有很多很多同学问这样的问题,并把这个问题列成了Excel2007和2010的一个Bug,可是小妖同学却从来没遇到过这样的问 ...

  6. 1、学习算法和刷题的框架思维——Go版

    前情提示:Go语言学习者.本文参考https://labuladong.gitee.io/algo,代码自己参考抒写,若有不妥之处,感谢指正 关于golang算法文章,为了便于下载和整理,都已开源放在 ...

  7. 开发webpart时建立图像文件夹和CSS,js文件夹

    如图所示:是通过添加映射来完成,做好之后,把图像拷到文件夹时,当ascx文件里需要用到图像时,直接把图像拖到ascx文件里的位置.这样就知道该图像的路径 了.

  8. 通过一道简单的例题了解Linux内核PWN

    写在前面 这篇文章目的在于简单介绍内核PWN题,揭开内核的神秘面纱.背后的知识点包含Linux驱动和内核源码,学习路线非常陡峭.也就是说,会一道Linux内核PWN需要非常多的铺垫知识,如果要学习可以 ...

  9. MyBatis学习(四)MyBatis一对一关联查询

    一对一关联查询即.两张表通过外键进行关联.从而达到查询外键直接获得两张表的信息.本文基于业务拓展类的方式实现. 项目骨架 配置文件conf.xml和db.properties前几节讲过.这里就不细说了 ...

  10. summernote富文本的简单使用

    官方地址:https://summernote.org/ html代码 <div class="summernote" id="summernote" & ...