Add test for blur and 3dlut intrinsic.

Change-Id: Ib3a378ec8590adeff6a1a56678705339e0bf14b6
diff --git a/tests/src/android/renderscript/cts/intrinsic_3dlut.rs b/tests/src/android/renderscript/cts/intrinsic_3dlut.rs
new file mode 100644
index 0000000..d577b63
--- /dev/null
+++ b/tests/src/android/renderscript/cts/intrinsic_3dlut.rs
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "shared.rsh"
+
+static rs_allocation gCube;
+static int4 gDims;
+static float4 gCoordMul;
+
+void setCube(rs_allocation c) {
+    gCube = c;
+    gDims.x = rsAllocationGetDimX(gCube);
+    gDims.y = rsAllocationGetDimY(gCube);
+    gDims.z = rsAllocationGetDimZ(gCube);
+    gDims.w = 0;
+    gCoordMul = (float4)(1.f / 255.f) * convert_float4(gDims - 1);
+}
+
+uchar4 __attribute__((kernel)) root(uchar4 in) {
+    float4 baseCoord = convert_float4(in) * gCoordMul;
+    int4 coord1 = convert_int4(floor(baseCoord));
+    int4 coord2 = min(coord1 + 1, gDims - 1);
+    float4 f = baseCoord - convert_float4(coord1);
+
+    float4 v000 = convert_float4(rsGetElementAt_uchar4(gCube, coord1.x, coord1.y, coord1.z));
+    float4 v100 = convert_float4(rsGetElementAt_uchar4(gCube, coord2.x, coord1.y, coord1.z));
+    float4 v010 = convert_float4(rsGetElementAt_uchar4(gCube, coord1.x, coord2.y, coord1.z));
+    float4 v110 = convert_float4(rsGetElementAt_uchar4(gCube, coord2.x, coord2.y, coord1.z));
+    float4 v001 = convert_float4(rsGetElementAt_uchar4(gCube, coord1.x, coord1.y, coord2.z));
+    float4 v101 = convert_float4(rsGetElementAt_uchar4(gCube, coord2.x, coord1.y, coord2.z));
+    float4 v011 = convert_float4(rsGetElementAt_uchar4(gCube, coord1.x, coord2.y, coord2.z));
+    float4 v111 = convert_float4(rsGetElementAt_uchar4(gCube, coord2.x, coord2.y, coord2.z));
+
+    float4 yz00 = mix(v000, v100, f.x);
+    float4 yz10 = mix(v010, v110, f.x);
+    float4 yz01 = mix(v001, v101, f.x);
+    float4 yz11 = mix(v011, v111, f.x);
+
+    float4 z0 = mix(yz00, yz10, f.y);
+    float4 z1 = mix(yz01, yz11, f.y);
+
+    float4 v = mix(z0, z1, f.z);
+
+    v = clamp(v, 0.f, 255.f);
+    uchar4 o = convert_uchar4(v + 0.5f);
+    o.w = in.w;
+    return o;
+}
+
diff --git a/tests/src/android/renderscript/cts/intrinsic_blur.rs b/tests/src/android/renderscript/cts/intrinsic_blur.rs
new file mode 100644
index 0000000..88f9ca5
--- /dev/null
+++ b/tests/src/android/renderscript/cts/intrinsic_blur.rs
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "shared.rsh"
+
+int height;
+int width;
+static int radius;
+rs_allocation ScratchPixel1;
+rs_allocation ScratchPixel2;
+
+const int MAX_RADIUS = 25;
+
+// Store our coefficients here
+static float gaussian[MAX_RADIUS * 2 + 1];
+
+float4 __attribute__((kernel)) convert1_uToF(uchar v) {
+    float4 r = rsUnpackColor8888(v);
+    return r.r;
+}
+
+float4 __attribute__((kernel)) convert4_uToF(uchar4 v) {
+    return rsUnpackColor8888(v);
+}
+
+uchar __attribute__((kernel)) convert1_fToU(float4 v) {
+    uchar4 r = rsPackColorTo8888(v);
+    return r.r;
+}
+
+uchar4 __attribute__((kernel)) convert4_fToU(float4 v) {
+    return rsPackColorTo8888(v);
+}
+
+void setRadius(int rad) {
+    // This function is a duplicate of:
+    // RsdCpuScriptIntrinsicBlur::ComputeGaussianWeights()
+    // Which is the reference C implementation
+    radius = rad;
+    const float e = M_E;
+    const float pi = M_PI;
+    float sigma = 0.4f * (float)radius + 0.6f;
+    float coeff1 = 1.0f / (sqrt( 2.0f * pi ) * sigma);
+    float coeff2 = - 1.0f / (2.0f * sigma * sigma);
+    float normalizeFactor = 0.0f;
+    float floatR = 0.0f;
+    for (int r = -radius; r <= radius; r ++) {
+        floatR = (float)r;
+        gaussian[r + radius] = coeff1 * pow(e, floatR * floatR * coeff2);
+        normalizeFactor += gaussian[r + radius];
+    }
+
+    normalizeFactor = 1.0f / normalizeFactor;
+    for (int r = -radius; r <= radius; r ++) {
+        floatR = (float)r;
+        gaussian[r + radius] *= normalizeFactor;
+    }
+}
+
+float4 __attribute__((kernel)) vert(uint32_t x, uint32_t y) {
+    float4 blurredPixel = 0;
+    int gi = 0;
+    for (int r = -radius; r <= radius; r ++) {
+        int validH = rsClamp((int)y + r, (int)0, (int)(height - 1));
+        float4 i = rsGetElementAt_float4(ScratchPixel2, x, validH);
+        blurredPixel += i * gaussian[gi++];
+    }
+    return blurredPixel;
+}
+
+float4 __attribute__((kernel)) horz(uint32_t x, uint32_t y) {
+    float4 blurredPixel = 0;
+    int gi = 0;
+    for (int r = -radius; r <= radius; r ++) {
+        // Stepping left and right away from the pixel
+        int validX = rsClamp((int)x + r, (int)0, (int)(width - 1));
+        float4 i = rsGetElementAt_float4(ScratchPixel1, validX, y);
+        blurredPixel += i * gaussian[gi++];
+    }
+    return blurredPixel;
+}
+
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/Intrinsic3DLut.java b/tests/tests/renderscript/src/android/renderscript/cts/Intrinsic3DLut.java
new file mode 100644
index 0000000..830982f
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/Intrinsic3DLut.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.renderscript.cts;
+
+import android.renderscript.*;
+import android.util.Log;
+
+public class Intrinsic3DLut extends IntrinsicBase {
+    private Allocation mCube;
+    private ScriptC_intrinsic_3dlut mScript;
+    private ScriptIntrinsic3DLUT mIntrinsic;
+    final int sx = 32;
+    final int sy = 32;
+    final int sz = 16;
+
+    private void genCubeIdent() {
+        int dat[] = new int[sx * sy * sz];
+        for (int z = 0; z < sz; z++) {
+            for (int y = 0; y < sy; y++) {
+                for (int x = 0; x < sx; x++ ) {
+                    int v = 0xff000000;
+                    v |= (0xff * x / (sx - 1));
+                    v |= (0xff * y / (sy - 1)) << 8;
+                    v |= (0xff * z / (sz - 1)) << 16;
+                    dat[z*sy*sx + y*sx + x] = v;
+                }
+            }
+        }
+
+        mCube.copyFromUnchecked(dat);
+    }
+
+    private void genCubeRand() {
+        java.util.Random r = new java.util.Random(100);
+        int dat[] = new int[sx * sy * sz];
+        for (int z = 0; z < sz; z++) {
+            for (int y = 0; y < sy; y++) {
+                for (int x = 0; x < sx; x++ ) {
+                    int v = 0xff000000;
+                    v |= r.nextInt(0x100);
+                    v |= r.nextInt(0x100) << 8;
+                    v |= r.nextInt(0x100) << 16;
+                    dat[z*sy*sx + y*sx + x] = v;
+                }
+            }
+        }
+
+        mCube.copyFromUnchecked(dat);
+    }
+
+    private void initCube() {
+        Type.Builder tb = new Type.Builder(mRS, Element.U8_4(mRS));
+        tb.setX(sx);
+        tb.setY(sy);
+        tb.setZ(sz);
+        Type t = tb.create();
+        mCube = Allocation.createTyped(mRS, t);
+        genCubeIdent();
+
+        mScript = new ScriptC_intrinsic_3dlut(mRS);
+        mScript.invoke_setCube(mCube);
+
+        mIntrinsic = ScriptIntrinsic3DLUT.create(mRS, Element.U8_4(mRS));
+        mIntrinsic.setLUT(mCube);
+    }
+
+    public void test1() {
+        initCube();
+        makeBuffers(97, 97, Element.U8_4(mRS));
+
+        mIntrinsic.forEach(mAllocSrc, mAllocDst);
+        mScript.forEach_root(mAllocSrc, mAllocRef);
+
+        mVerify.set_gAllowedIntError(1);
+        mVerify.invoke_verify(mAllocRef, mAllocDst, mAllocSrc);
+        mRS.finish();
+        checkError();
+    }
+
+    public void test2() {
+        initCube();
+        makeBuffers(97, 97, Element.U8_4(mRS));
+        genCubeRand();
+
+        mIntrinsic.forEach(mAllocSrc, mAllocDst);
+        mScript.forEach_root(mAllocSrc, mAllocRef);
+
+        mVerify.set_gAllowedIntError(2);
+        mVerify.invoke_verify(mAllocRef, mAllocDst, mAllocSrc);
+        mRS.finish();
+        checkError();
+    }
+
+
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/IntrinsicBlur.java b/tests/tests/renderscript/src/android/renderscript/cts/IntrinsicBlur.java
new file mode 100644
index 0000000..aa67012
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/IntrinsicBlur.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.renderscript.cts;
+
+import android.renderscript.*;
+import android.util.Log;
+
+public class IntrinsicBlur extends IntrinsicBase {
+    private ScriptIntrinsicBlur mIntrinsic;
+    private int MAX_RADIUS = 25;
+    private ScriptC_intrinsic_blur mScript;
+    private float mRadius = MAX_RADIUS;
+    private float mSaturation = 1.0f;
+    private Allocation mScratchPixelsAllocation1;
+    private Allocation mScratchPixelsAllocation2;
+
+
+
+    private void initTest(int w, int h, Element e) {
+        makeBuffers(w, h, e);
+
+        Type.Builder tb = new Type.Builder(mRS, Element.F32_4(mRS));
+        tb.setX(w);
+        tb.setY(h);
+        mScratchPixelsAllocation1 = Allocation.createTyped(mRS, tb.create());
+        mScratchPixelsAllocation2 = Allocation.createTyped(mRS, tb.create());
+
+        mIntrinsic = ScriptIntrinsicBlur.create(mRS, e);
+        mIntrinsic.setRadius(MAX_RADIUS);
+        mIntrinsic.setInput(mAllocSrc);
+
+        mScript = new ScriptC_intrinsic_blur(mRS);
+        mScript.set_width(w);
+        mScript.set_height(h);
+        mScript.invoke_setRadius(MAX_RADIUS);
+
+        mScript.set_ScratchPixel1(mScratchPixelsAllocation1);
+        mScript.set_ScratchPixel2(mScratchPixelsAllocation2);
+
+        // Make reference
+        copyInput();
+        mScript.forEach_horz(mScratchPixelsAllocation2);
+        mScript.forEach_vert(mScratchPixelsAllocation1);
+        copyOutput();
+    }
+
+    private void copyInput() {
+        if (mAllocSrc.getType().getElement().isCompatible(Element.U8(mRS))) {
+            mScript.forEach_convert1_uToF(mAllocSrc, mScratchPixelsAllocation1);
+            return;
+        }
+        if (mAllocSrc.getType().getElement().isCompatible(Element.U8_4(mRS))) {
+            mScript.forEach_convert4_uToF(mAllocSrc, mScratchPixelsAllocation1);
+            return;
+        }
+        throw new IllegalArgumentException("bad type");
+    }
+
+    private void copyOutput() {
+        if (mAllocSrc.getType().getElement().isCompatible(Element.U8(mRS))) {
+            mScript.forEach_convert1_fToU(mScratchPixelsAllocation1, mAllocRef);
+            return;
+        }
+        if (mAllocSrc.getType().getElement().isCompatible(Element.U8_4(mRS))) {
+            mScript.forEach_convert4_fToU(mScratchPixelsAllocation1, mAllocRef);
+            return;
+        }
+        throw new IllegalArgumentException("bad type");
+    }
+
+    public void testU8_1() {
+        final int w = 97;
+        final int h = 97;
+        Element e = Element.U8(mRS);
+        initTest(w, h, e);
+
+        mIntrinsic.forEach(mAllocDst);
+
+        mVerify.set_gAllowedIntError(1);
+        mVerify.invoke_verify(mAllocRef, mAllocDst, mAllocSrc);
+        mRS.finish();
+        checkError();
+    }
+
+    public void testU8_4() {
+        final int w = 97;
+        final int h = 97;
+        Element e = Element.U8_4(mRS);
+        initTest(w, h, e);
+
+        mIntrinsic.forEach(mAllocDst);
+
+        mVerify.set_gAllowedIntError(1);
+        mVerify.invoke_verify(mAllocRef, mAllocDst, mAllocSrc);
+        mRS.finish();
+        checkError();
+    }
+
+}