Add RS YUV test

This is a new test to cover both the YUV intrinsic and
the rsGetElementAt_uchar_Y,u,v functions.

bug 10826418

Change-Id: Ia187685abcd26066424f03ae7548ea59504c2e14
diff --git a/tests/src/android/renderscript/cts/yuv.rs b/tests/src/android/renderscript/cts/yuv.rs
new file mode 100644
index 0000000..6d45331
--- /dev/null
+++ b/tests/src/android/renderscript/cts/yuv.rs
@@ -0,0 +1,97 @@
+/*
+ * 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.
+ */
+
+#include "shared.rsh"
+
+#pragma rs_fp_relaxed
+
+rs_allocation mInput;
+
+rs_allocation mInY;
+rs_allocation mInU;
+rs_allocation mInV;
+
+static uchar4 yuvToRGBA4(uchar y, uchar u, uchar v) {
+    short Y = ((short)y) - 16;
+    short U = ((short)u) - 128;
+    short V = ((short)v) - 128;
+
+    short4 p;
+    p.x = (Y * 298 + V * 409 + 128) >> 8;
+    p.y = (Y * 298 - U * 100 - V * 208 + 128) >> 8;
+    p.z = (Y * 298 + U * 516 + 128) >> 8;
+    p.w = 255;
+    if(p.x < 0) {
+        p.x = 0;
+    }
+    if(p.x > 255) {
+        p.x = 255;
+    }
+    if(p.y < 0) {
+        p.y = 0;
+    }
+    if(p.y > 255) {
+        p.y = 255;
+    }
+    if(p.z < 0) {
+        p.z = 0;
+    }
+    if(p.z > 255) {
+        p.z = 255;
+    }
+
+    return (uchar4){p.x, p.y, p.z, p.w};
+}
+
+void makeRef(rs_allocation ay, rs_allocation au, rs_allocation av, rs_allocation aout) {
+    uint32_t w = rsAllocationGetDimX(ay);
+    uint32_t h = rsAllocationGetDimY(ay);
+
+    for (int y = 0; y < h; y++) {
+        //rsDebug("y", y);
+        for (int x = 0; x < w; x++) {
+
+            int py = rsGetElementAt_uchar(ay, x, y);
+            int pu = rsGetElementAt_uchar(au, x >> 1, y >> 1);
+            int pv = rsGetElementAt_uchar(av, x >> 1, y >> 1);
+
+            //rsDebug("py", py);
+            //rsDebug(" u", pu);
+            //rsDebug(" v", pv);
+
+            uchar4 rgb = yuvToRGBA4(py, pu, pv);
+            //rsDebug("  ", rgb);
+
+            rsSetElementAt_uchar4(aout, rgb, x, y);
+        }
+    }
+}
+
+
+uchar4 __attribute__((kernel)) cvt(uint32_t x, uint32_t y) {
+
+    uchar py = rsGetElementAtYuv_uchar_Y(mInput, x, y);
+    uchar pu = rsGetElementAtYuv_uchar_U(mInput, x, y);
+    uchar pv = rsGetElementAtYuv_uchar_V(mInput, x, y);
+
+    //rsDebug("py2", py);
+    //rsDebug(" u2", pu);
+    //rsDebug(" v2", pv);
+
+    return yuvToRGBA4(py, pu, pv);
+}
+
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/YuvTest.java b/tests/tests/renderscript/src/android/renderscript/cts/YuvTest.java
new file mode 100644
index 0000000..c2c7275
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/YuvTest.java
@@ -0,0 +1,211 @@
+/*
+ * 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 java.util.Random;
+
+public class YuvTest extends RSBaseCompute {
+    int width;
+    int height;
+    byte [] by;
+    byte [] bu;
+    byte [] bv;
+    Allocation ay;
+    Allocation au;
+    Allocation av;
+
+    protected ScriptC_verify mVerify;
+
+
+    int getCWidth() {
+        return (width + 1) / 2;
+    }
+    int getCHeight() {
+        return (height + 1) / 2;
+    }
+
+    protected void makeYuvBuffer(int w, int h) {
+        Random r = new Random();
+        width = w;
+        height = h;
+
+        by = new byte[w*h];
+        bu = new byte[getCWidth() * getCHeight()];
+        bv = new byte[getCWidth() * getCHeight()];
+
+        for (int i=0; i < by.length; i++) {
+            by[i] = (byte)r.nextInt(256);
+        }
+        for (int i=0; i < bu.length; i++) {
+            bu[i] = (byte)r.nextInt(256);
+        }
+        for (int i=0; i < bv.length; i++) {
+            bv[i] = (byte)r.nextInt(256);
+        }
+
+        Type.Builder tb = new Type.Builder(mRS, Element.U8(mRS));
+        tb.setX(w);
+        tb.setY(h);
+        ay = Allocation.createTyped(mRS, tb.create());
+
+        tb = new Type.Builder(mRS, Element.U8(mRS));
+        tb.setX(w >> 1);
+        tb.setY(h >> 1);
+        au = Allocation.createTyped(mRS, tb.create());
+        av = Allocation.createTyped(mRS, tb.create());
+
+        ay.copyFrom(by);
+        au.copyFrom(bu);
+        av.copyFrom(bv);
+    }
+
+    public Allocation makeOutput() {
+        Type.Builder tb = new Type.Builder(mRS, Element.RGBA_8888(mRS));
+        tb.setX(width);
+        tb.setY(height);
+        Type t = tb.create();
+        return Allocation.createTyped(mRS, t);
+    }
+
+    // Test for the API 17 conversion path
+    // This used a uchar buffer assuming nv21
+    public void testV17() {
+        mVerify = new ScriptC_verify(mRS);
+
+        makeYuvBuffer(120, 96);
+        Allocation aout = makeOutput();
+        Allocation aref = makeOutput();
+
+        byte tmp[] = new byte[(width * height) + (getCWidth() * getCHeight() * 2)];
+        int i = 0;
+        for (int j = 0; j < (width * height); j++) {
+            tmp[i++] = by[j];
+        }
+        for (int j = 0; j < (getCWidth() * getCHeight()); j++) {
+            tmp[i++] = bv[j];
+            tmp[i++] = bu[j];
+        }
+
+        Allocation ta = Allocation.createSized(mRS, Element.U8(mRS), tmp.length);
+        ta.copyFrom(tmp);
+
+
+        ScriptIntrinsicYuvToRGB syuv = ScriptIntrinsicYuvToRGB.create(mRS, Element.U8(mRS));
+        syuv.setInput(ta);
+        syuv.forEach(aout);
+
+        ScriptC_yuv script = new ScriptC_yuv(mRS);
+        script.invoke_makeRef(ay, au, av, aref);
+
+        mVerify.invoke_verify(aref, aout, ay);
+
+        mRS.finish();
+        mVerify.invoke_checkError();
+        waitForMessage();
+        checkForErrors();
+    }
+
+    // Test for the API 18 conversion path with nv21
+    public void test_NV21() {
+        mVerify = new ScriptC_verify(mRS);
+        ScriptC_yuv script = new ScriptC_yuv(mRS);
+        ScriptIntrinsicYuvToRGB syuv = ScriptIntrinsicYuvToRGB.create(mRS, Element.YUV(mRS));
+
+        makeYuvBuffer(512, 512);
+        Allocation aout = makeOutput();
+        Allocation aref = makeOutput();
+
+
+        Type.Builder tb = new Type.Builder(mRS, Element.YUV(mRS));
+        tb.setX(width);
+        tb.setY(height);
+        tb.setYuvFormat(android.graphics.ImageFormat.NV21);
+        Allocation ta = Allocation.createTyped(mRS, tb.create(), Allocation.USAGE_SCRIPT);
+
+        byte tmp[] = new byte[(width * height) + (getCWidth() * getCHeight() * 2)];
+        int i = 0;
+        for (int j = 0; j < (width * height); j++) {
+            tmp[i++] = by[j];
+        }
+        for (int j = 0; j < (getCWidth() * getCHeight()); j++) {
+            tmp[i++] = bv[j];
+            tmp[i++] = bu[j];
+        }
+        ta.copyFrom(tmp);
+        script.invoke_makeRef(ay, au, av, aref);
+
+        syuv.setInput(ta);
+        syuv.forEach(aout);
+        mVerify.invoke_verify(aref, aout, ay);
+
+        script.set_mInput(ta);
+        script.forEach_cvt(aout);
+        mVerify.invoke_verify(aref, aout, ay);
+
+        mRS.finish();
+        mVerify.invoke_checkError();
+        waitForMessage();
+        checkForErrors();
+    }
+
+    // Test for the API 18 conversion path with yv12
+    public void test_YV12() {
+        mVerify = new ScriptC_verify(mRS);
+        ScriptC_yuv script = new ScriptC_yuv(mRS);
+        ScriptIntrinsicYuvToRGB syuv = ScriptIntrinsicYuvToRGB.create(mRS, Element.YUV(mRS));
+
+        makeYuvBuffer(512, 512);
+        Allocation aout = makeOutput();
+        Allocation aref = makeOutput();
+
+
+        Type.Builder tb = new Type.Builder(mRS, Element.YUV(mRS));
+        tb.setX(width);
+        tb.setY(height);
+        tb.setYuvFormat(android.graphics.ImageFormat.YV12);
+        Allocation ta = Allocation.createTyped(mRS, tb.create(), Allocation.USAGE_SCRIPT);
+
+        byte tmp[] = new byte[(width * height) + (getCWidth() * getCHeight() * 2)];
+        int i = 0;
+        for (int j = 0; j < (width * height); j++) {
+            tmp[i++] = by[j];
+        }
+        for (int j = 0; j < (getCWidth() * getCHeight()); j++) {
+            tmp[i++] = bu[j];
+        }
+        for (int j = 0; j < (getCWidth() * getCHeight()); j++) {
+            tmp[i++] = bv[j];
+        }
+        ta.copyFrom(tmp);
+        script.invoke_makeRef(ay, au, av, aref);
+
+        syuv.setInput(ta);
+        syuv.forEach(aout);
+        mVerify.invoke_verify(aref, aout, ay);
+
+        script.set_mInput(ta);
+        script.forEach_cvt(aout);
+        mVerify.invoke_verify(aref, aout, ay);
+
+        mRS.finish();
+        mVerify.invoke_checkError();
+        waitForMessage();
+        checkForErrors();
+    }
+
+}