Android RenderScript入门(1)_移动开发_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > 移动开发 > Android RenderScript入门(1)

Android RenderScript入门(1)

 2013/11/28 23:31:52  xiao蜗牛  博客园  我要评论(0)
  • 摘要:最近研究android动态壁纸,对RenderScript起了兴趣,因为对这块知识没有涉猎,所以感觉仅仅看两下根本理解不了它,更不要说运用了,所以决定分阶段仔细进行研究,争取最后能写出自己的作品^_^第一阶段当然是入门了,翻译一篇android文档上的权威文章,地址http://developer.android.com/guide/topics/renderscript/compute.html。------------------------------------------------
  • 标签:android

 最近研究android动态壁纸,对RenderScript起了兴趣,因为对这块知识没有涉猎,所以感觉仅仅看两下根本理解不了它,更不要说运用了,所以决定分阶段仔细进行研究,争取最后能写出自己的作品^_^

第一阶段当然是入门了,翻译一篇android文档上的权威文章,地址http://developer.android.com/guide/topics/renderscript/compute.html。

--------------------------------------------------------------------------------------------------

什么是Renderscript

  Renderscript是android平台上进行高性能计算的框架。Renderscript主要面向并行计算,虽然它对计算密集型工作也是有益的。Renderscript在运行时将在设备上可用的处理器间平衡负载,比如多核CPU,GPU或者DSP,它让你专注于算法而不是平衡负载。RenderScript对图像处理,计算摄影学,计算机视觉方面的应用非常有用。

  在开始学习Renderscript前,你应该理解两个主要概念:

1  高性能的计算核心由支持C99协议的语言书写。(也就是C语言。译者注)

2 一套java API 用来管理Renderscript资源,并控制核心计算的执行。

写Renderscript核心

  一个Renderscript核心一般写在.rs文件中,在[工程目录]/src/ 目录下;每一个.rs文件成为一个脚本。每一个脚本包含一系列的内核,函数,变量。通常包含

1 一个编译声明Renderscript核心语言的版本(#pragma version(1))。

目前可用值只有1.

2 一个编译声明这个脚本对应的java类的包名

(#pragma rs java_package_name(com.example.app)).

3 一些可调用的函数。

一个可调用的函数是一个单线程的Renderscript函数,你可以再java代码中调用它并传递任意多的参数。它通常用在较大的处理管道里初始化设置或者一系列计算。

4 一些全局变量。

一个Renderscript全局变量等价于C语言中的一个全局变量。你可以再java代码中访问Renderscript全局变量,它们通常被用来向Renderscript核心传递参数。

5 一些计算核心。

  一个计算核心是在Allocation里的Element间执行的平行的函数。一个简单的核心如下:

uchar4 __attribute__((kernel)) invert(uchar4 in, uint32_t x, uint32_t y) {
  uchar4 out = in;
  out.r = 255 - in.r;
  out.g = 255 - in.g;
  out.b = 255 - in.b;
  return out;
}

它在很多方面跟标准C函数一致。第一个值得注意的是__attribute__((kernel)), 这表明这个函数式Renderscript核心而不是可调用函数。第二个特性是 in参数和它的类型,在Renderscript核心里第一个参数会根据传入内核平台的Allocation被自动填入。默认的,核心将在每一个Element执行一次时在整个Allocation中运行(???不懂 译者注)。 第三个注意点是核心的返回类型,这个返回值将被自动的写入到输出Allocation的适当的位置。Renderscript会在运行时确保输入和输出的Allocation的Element类型互相匹配;如果不匹配,会抛出异常

一个核心可能有一个输入Allocation或/和一个输出Allocation。也可能有多个输入输出Allocation。如果需要多个输入输出Allocation,这些对象应该同re_allocations脚本全局变量绑定,并且通过rsGetElementAt_type() / rsSetElementAt_type() 在核心或可调用函数中访问。

一个核心可以使用x,y和z参数来访问当前执行的坐标。这些参数是可选的,但是类型必须是uint32_t。

6 可选的 init() 函数。

  Init() 韩式是一个特殊的可调用函数,它在脚本初始化时执行。

7 一些静态全局变量和函数。

  静态的全局变量与普通的全局变量不同的地方是它不能从java代码中设定。静态函数是一个标准的C函数,可以再核心和脚本中的可调用方法中调用,但是不能被java API访问。如果全局变量或者函数不需要在java代码中使用,强烈建议声明成静态的。

设置浮点精度

你可以在脚本里控制浮点数的精度。这样做在不要求使用IEEE 754-2008 标准(默认使用)时是很有用的。下面的编译指示可以设置不同的浮点精度:

1 #pragma rs_fp_full (不指定时默认的设置):使用IEEE 754-2008 标准的精度。

2 #pragma rs_fp_relaxed 不严格的使用IEEE 754-2008 的标准,允许少量的精度误差。

3  #pragma rs_fp_imprecise 不需要严格的精度要求,允许#pragma rs_fp_relaxed下的所有情况,还包括:

-0.0会返回+0.0

INF 和 NAN的操作部明确

….(不懂。。。译者注)

大多数应用可以使用#pragma rs_fp_relaxed。

访问Renderscript API

在android应用里使用Renderscript有两种方式

1 android.renderscript 这个包在运行Android3.0(API level 11)的设备上可用,这是原始的API,目前没有被更新。

2 android.support.v8.renderscript 这个包可以通过共享库在运行Android2.2(API level 8)或以上版本的设备上使用。

强烈建议使用第二种方式,因为它包含了最新的更新,并且支持更多的设备。

使用Renderscript共享库API

 为了使用共享库的Renderscript API,你需要安装你的开发环境。你需要下面的SDK工具:

  • Android SDK Tools revision 22.2 or higher
  • Android SDK Build-tools revision 18.1.0 or higher

在eclipse工程中使用共享库,你需要:

1 安装需要的SDK和编译工具

2打开工程根目录下的project.properties文件

3 添加下面的内容

renderscript.target=18
renderscript.support.mode=true
sdk.buildtools=18.1.0

4 在类中导入共享库的类

import android.support.v8.renderscript.*;

在java代码中使用Renderscript

在java代码中使用Renderscript依赖android.renderscript 或者android.support.v8.renderscript中的API。大部分程序遵循如下的使用方式:

1 初始化Renderscript context。Renderscript context通过create(Context)创建,它能保证Renderscript能被使用,并且提供了一个对象来控制所有后面创建的Renderscript对象的生命周期。创建这个context可能是一个耗时的操作,因为可能要在硬件的不同位置创建资源;通常,一个程序同时只能有一个Renderscript context。

2 创建至少一个Allocation来传递给脚本。一个Allocation是一个Renderscript对象,它存储了固定数量的数据。脚本里的核心将Allocation对象作为输入和输出,核心可以在绑定脚本全局变量时通过rsGetElementAt_type() 和rsSetElementType_type()来访问Allocation对象。Allocation对象可以通过数组从java代码传递给Renderscript代码,反之亦然。Allocation对象通常用createTyped(RenderScript, Type) 或者 createFromBitmap(RenderScript, Bitmap)创建。

3 创建你所需的任何脚本。有两种脚本可被创建:

  ScriptC : 这是上面”写Renderscript脚本”部分介绍的用户自定义脚本。Renderscript编译器会为每一个脚本创建一个java类,可以方便从java代码中访问脚本;这个类会被命名成ScriptC_filename。比如:如果上面的核心位于inver.rs中,并且一个Renderscript context已经被创建,在java代码中初始化脚本的代码如下:

ScriptC_invert invert = new ScriptC_invert(mRenderScript);

ScriptIntrinsic : 这是嵌入在Renderscript核心中的通用操作,比如高斯模糊,卷积,图像混合。更多信息请参看 ScriptInstrinsic.

4 在Allocation中的数据。除了android.renderscript创建的Allocation以外,一个空的Allocation将被创建,填充一个Allocation,请使用Allocation的copy方法。

5 设置必要的脚步全局变量。全局变量可以使用ScriptC_filename里的set_globalname来设置。例如,要想设置一个叫elements的整形变量,使用java方法set_elements(int)。Renderscript对象也可以在核心中设置,例如,叫做lookup的rs_allocation变量可以通过set_lookup(Allocation)函数设置。

 

6加载适当的核心。使用ScriptC_filename中的forEach_kernelname()函数可以加载一个核心。加载过程是异步的,加载的顺序和启动的顺序是一致的。根据传入内核的参数的不同,这个函数会携带一个或两个Allocation。默认的,一个核心会在整个输入输出Allocation中执行;为了在一系列Allocation中执行,给forEach函数的最后一个参数传递恰当的Script.LaunchOptions。可调用函数可以使用ScriptC_filename中的invoke_functionname调用。

7 从Allocation对象中拷贝数据。为了在java代码中访问Allocation中的数据,需要使用Allocation的copy方法拷贝到java缓冲区中。这些方法会必要的时候在异步内核和函数调用间做同步

8 销毁Renderscript context。可以使用destroy()方法销毁Renderscript context,或者允许Renderscript context对象被垃圾回收。这样使用这个context中的任何对象将抛出异常。

----------------------------------------------------------------------------------------------------------------

进一步学习

原理层:

1 什么是Allocation?

2 Compute kernel是如何处理Allocation的?

应用层:

1 RenderScript API学习

2 bc文件是什么?

发表评论
用户名: 匿名