创建Renderscript
Renderscript扩大了设备上可用的处理器内核的范围。这种能力是通过名叫rsForEach()(或者是Android框架级别下的forEach_root()方法)方法来获得的。它会自动的区分访问设备设备上可用的处理器内核的工作。目前,Renderscript只能利用CPU内核的优势,但是在将来,它们会能够运行在其他类型的处理器上,如GPU和DSP等。
实现一个Renderscript要涉及创建一个包含Renderscript代码的.rs文件和在Android框架级别下用forEach_root()方法调用该文件(或者是在Renderscript级别下用rsForEach()函数调用该文件)。下图介绍了如何建立一个典型的Renderscript:
图2.Renderscript概要
以下章节介绍如何创建一个简单的Renderscript,并且要在一个Android应用程序中使用它。这个例子使用了SDK开发指南中提供的HelloCompute Renderscript示例。
创建Renderscript文件
Renderscript代码要保留在<project_root>/src/目录中的*.rs和*.rsh文件中。代码中包含了计算的逻辑和所有必要的变量和指针的声明。通常,每个*.rs文件要包含下列项目:
1. 编译指示声明(#pragma rs java_package_name(package.name)),它声明了该Renderscript反射所对应的*.java类名;
2. 编译指示声明(#pragma version(1)),它声明了你要使用的Renderscript的版本(目前只能是1);
3. 一个名叫root()的主函数,该root()函数被rsForEach函数调用,并允许它调用Renderscript代码和在有效的多内核中执行。root()函数必须返回void并且要接收下列参数:
A.分配给Renderscript的输入和输出使用的内存的指针。在Android3.2(API level 13)平台以前的版本中同时需要这两个指针。Android4.0(API Level 14)以后只分配其中之一就可以了。
B.下列参数是可选的,但是如果使用它们就必须同时提供它们:
除了必要的内存分配之外,一个Renderscript执行计算所可能需要的用户定义数据的指针,它能够指向一个简单的原始类型的数据,也可以指向一个复杂的结构体。
用户定义数据的大小。
4. 一个可选的init()方法。这个方法允许再root()方法运行之前做一些初始化的工作,如初始化变量等。这个函数运行一次,并且在Renderscript启动时,Renderscript中其他工作被执行之前,该方法会被自动的调用。
5. 在Renderscript代码中要使用的任何变量、指针和结构体(如果需要,能够在*.rsh文件中声明)。
下列代码显示了mono.rs文件是如何实现的:
#pragma version(1)
#pragma rs java_package_name(com.example.android.rs.hellocompute)
//multipliers to convert a RGB colors to black and white
const static float3 gMonoMult = {0.299f, 0.587f, 0.114f};
void root(const uchar4 *v_in, uchar4 *v_out) {
//unpack a color to a float4
float4 f4 = rsUnpackColor8888(*v_in);
//take the dot product of the color and the multiplier
float3 mono = dot(f4.rgb, gMonoMult);
//repack the float to a color
*v_out = rsPackColorTo8888(mono);
}