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全开放机器人套件服 ... 
随机推荐
- Mysql资料 mysqldump
			目录 一.简介 备份过程 优缺点 命令使用 myisam引擎 二.安装 配置 日志 三.日常使用 备份全库 备份单个库(带建立库的语句) 备份单个库(不自动建立库) 备份表合集 从全备中恢复单个库 其 ... 
- Google Earth Engine 批量点击RUN任务,批量取消正在上传的任务
			本文内容参考自: https://blog.csdn.net/qq_21567935/article/details/89061114 https://blog.csdn.net/qq_2156793 ... 
- 小迪安全 Web安全 基础入门 - 第十天 - 信息打点-APP&小程序篇&抓包封包&XP框架&反编译&资产提取
			一.本节知识点思维导图 二.APP-外在资产收集 1.将APP安装在模拟器中,修改模拟器代理设置,使用Fiddler.Burpsuite.Charles等抓包工具抓取APP访问的http协议数据包,抓 ... 
- CF1166A Silent Classroom 题解
			Content 现在有 \(n\) 名学生,我们需要将这些学生分到两个班上.对于两名在同一班级的学生,如果他们的名字首字母相同,他们就会聊天. 现在给定这些学生的名字,问最少有多少对学生会在一起聊天. ... 
- JavaScript扫盲笔记:
			JavaScript学习: JavaScript代码存在形式: -Head中 <script> </script> -文件 <script src='代码所在路径'> ... 
- redis集群搭建,使用注意
			https://www.cnblogs.com/vieta/p/11192137.html https://blog.csdn.net/qq_42815754/article/details/8291 ... 
- mvn 把本地jar包打包到本地仓库中
			命令如下: mvn install:install-file -Dfile=apache-ant-zip-2.3.jar -DgroupId=com.ckfinder -DartifactId=apa ... 
- vue 判断页面是否滚动到底部
			需求 要求用户阅读完本页所有内容后,下一步按钮才可以点击. 实现思路 通过判断当前页面是否到达底部来设置按钮的点击事件. 要判断当前页面是否到达底部需要用到三个距离--距离顶部的距离scrollTop ... 
- c++ 设计模式概述之享元
			类写的不够规范,目的是为了缩短篇幅,实际中其不要这样做. 参考文章: 1. http://c.biancheng.net/view/1371.html 1.概述 A.享元,我的理解是: 共享的模块单元 ... 
- 【LeetCode】42. Trapping Rain Water 接雨水 (C++)
			作者: 负雪明烛 id: fuxuemingzhu 个人博客:http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 暴力求解 保存左右最大值 单调栈 日期 题目地址:ht ... 
