rockchip-rk3399 RGA的使用
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的使用的更多相关文章
- 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 ...
- RK3399配置笔记
1. adb shell 默认超级管理员 在build/core/main.mk下将ADDITIONAL_DEFAULT_PROPERTIES += ro.secure=1改成ADDITIONAL_D ...
- 瑞芯微RK3399宣布系统开源,进入百余种行业市场!
集微网消息,2月24日瑞芯微官方突然宣布, Rockchip RK3399Linux系统开源!作为Rockchip旗舰级芯片,RK3399具有高性能.高扩展.全能型应用特性. 这一重磅消息立马刷爆朋友 ...
- [RK3399] 虚拟按键栏显示不全或者方向不对
CPU:RK3399 系统:Android 7.1 同样的系统代码,换了一个小分辨率的屏,虚拟按键栏就出现显示不全,而且方向不对 出现这种问题的原因是显示密度和屏不匹配,需要适当的降低显示密度即可 d ...
- [RK3399] 调试串口ttyS2改为普通串口
CPU:RK3399 系统:Android 7.1 串口需求量大时,会选择使用 spi 转串口,但是数据量大或者波特率较高时,传输会丢包. 调试串口 ttyS2 也可以让出来,供上层使用,下面是将 t ...
- RK3399 4G模块移远EC20移植调试
转载请注明出处:https://www.cnblogs.com/lialong1st/p/11266330.html CPU:RK3399 系统:Android 7.1 1.通过串口打印或者adb获取 ...
- 瑞芯微RK3399六核-迅为3399开发板介绍
迅为3399开发板基于瑞芯微的RK3399处理器设计,Rockchip RK3399是瑞芯微推出的一款低功耗.高性能的应用处理器芯片,该芯片基于Big.Little架构,即具有独立的NEON协同处理器 ...
- Rock Pi开发笔记(二):入手Rock Pi 4B plus(基于瑞星微RK3399)板子并制作系统运行
前言 入手rock pi 4b plus板子,查看具体的实物,然后制作系统,刷系统,让摇滚派的ubuntu系统运行起来. Rock Pi 4B plus 介绍 ROCK Pi 4 是 Ra ...
- PCI 设备调试手段
Author: Younix Platform: RK3399 OS: Android 6.0 Kernel: 4.4 Version: v2017.04 一PCI 设备调试手段 busybox ls ...
- http://www.artrobot.com/北京钢铁侠
http://www.artrobot.com/ 钢铁侠ROS智能机器人 钢铁侠ROS智能机器人 型号 ARTrobot-ROS 产品图片: 产品概述: ARTrobot-ROS全开放机器人套件服 ...
随机推荐
- 新一代Java程序员必学的Docker容器化技术基础篇
Docker概述 **本人博客网站 **IT小神 www.itxiaoshen.com Docker文档官网 Docker是一个用于开发.发布和运行应用程序的开放平台.Docker使您能够将应用程序与 ...
- Wireshark(五):TCP窗口与拥塞处理
原文出处: EMC中文支持论坛 TCP通过滑动窗口机制检测丢包,并在丢包发生时调整数据传输速率.滑动窗口机制利用数据接收端的接收窗口来控制数据流. 接收窗口值由数据接收端指定,以字节数形式存储于TCP ...
- HGAME2021 week2 pwn writeup
week2一共有4道pwn题 killerqueen 有格式化字符串漏洞,题不算难,但是故事情节真实让人摸不着头脑,但是仔细分析分析,理清楚逻辑就可以做了. 第一次choose1的时候,可以输入0,泄 ...
- [ZJCTF 2019]EasyHeap
目录 逆向分析 create 函数 edit 函数 delete 函数 利用思路 exp 脚本 get flag 内容来源 逆向分析 -------------------------------- ...
- BUGKU web刷题记录
web1 直接F12查看源码,得到flag. web2 直接输入验证码答案,长度被限制,修改可输入长度,提交后得到flag. web3 $what=$_GET['what']; echo $what; ...
- 在程序出现问题,当找不到错误时,第一时间用try ,catch包括起来
在程序出现问题,当找不到错误时,第一时间用try ,catch包括起来,把错误找到.
- Jenkins安装部署使用图文详解(非常详细)
前言 最近公司需要弄一套自动化运维部署,于是抽空学习了一下,用了两天左右完成Jenkins的安装部署和各种项目的配置化,于是整理一下进行分享. 介绍 Jenkins是一个独立的开源软件项目,是基于Ja ...
- JAVA将文件转换成byte数组(byte[])
/** * 将文件转换成byte数组 * @param filePath 文件File类 通过new File(文件路径) * @return byte数组 */ public static byte ...
- JS将时间戳转换为日期格式
function getDate(time){ var date =(new Date(parseInt(time))).toLocaleDateString() return date; } tim ...
- C/C++ 结构体字节对齐
在用sizeof运算符求算某结构体所占空间时,并不是简单地将结构体中所有元素各自占的空间相加,这里涉及到内存字节对齐的问题.从理论上讲,对于任何 变量的访问都可以从任何地址开始访问,但是事实上不是如此 ...